xref: /openbmc/linux/drivers/gpio/gpio-gpio-mm.c (revision 1c05004f)
11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
26ea5dcdfSWilliam Breathitt Gray /*
36ea5dcdfSWilliam Breathitt Gray  * GPIO driver for the Diamond Systems GPIO-MM
46ea5dcdfSWilliam Breathitt Gray  * Copyright (C) 2016 William Breathitt Gray
56ea5dcdfSWilliam Breathitt Gray  *
66ea5dcdfSWilliam Breathitt Gray  * This driver supports the following Diamond Systems devices: GPIO-MM and
76ea5dcdfSWilliam Breathitt Gray  * GPIO-MM-12.
86ea5dcdfSWilliam Breathitt Gray  */
96ea5dcdfSWilliam Breathitt Gray #include <linux/device.h>
106ea5dcdfSWilliam Breathitt Gray #include <linux/errno.h>
116ea5dcdfSWilliam Breathitt Gray #include <linux/ioport.h>
126ea5dcdfSWilliam Breathitt Gray #include <linux/isa.h>
136ea5dcdfSWilliam Breathitt Gray #include <linux/kernel.h>
146ea5dcdfSWilliam Breathitt Gray #include <linux/module.h>
156ea5dcdfSWilliam Breathitt Gray #include <linux/moduleparam.h>
16*1c05004fSWilliam Breathitt Gray #include <linux/regmap.h>
17*1c05004fSWilliam Breathitt Gray #include <linux/types.h>
18949506dcSWilliam Breathitt Gray 
19949506dcSWilliam Breathitt Gray #include "gpio-i8255.h"
20949506dcSWilliam Breathitt Gray 
21949506dcSWilliam Breathitt Gray MODULE_IMPORT_NS(I8255);
226ea5dcdfSWilliam Breathitt Gray 
236ea5dcdfSWilliam Breathitt Gray #define GPIOMM_EXTENT 8
246ea5dcdfSWilliam Breathitt Gray #define MAX_NUM_GPIOMM max_num_isa_dev(GPIOMM_EXTENT)
256ea5dcdfSWilliam Breathitt Gray 
266ea5dcdfSWilliam Breathitt Gray static unsigned int base[MAX_NUM_GPIOMM];
276ea5dcdfSWilliam Breathitt Gray static unsigned int num_gpiomm;
28d759f906SDavid Howells module_param_hw_array(base, uint, ioport, &num_gpiomm, 0);
296ea5dcdfSWilliam Breathitt Gray MODULE_PARM_DESC(base, "Diamond Systems GPIO-MM base addresses");
306ea5dcdfSWilliam Breathitt Gray 
31949506dcSWilliam Breathitt Gray #define GPIOMM_NUM_PPI 2
32949506dcSWilliam Breathitt Gray 
33*1c05004fSWilliam Breathitt Gray static const struct regmap_range gpiomm_volatile_ranges[] = {
34*1c05004fSWilliam Breathitt Gray 	i8255_volatile_regmap_range(0x0), i8255_volatile_regmap_range(0x4),
356ea5dcdfSWilliam Breathitt Gray };
36*1c05004fSWilliam Breathitt Gray static const struct regmap_access_table gpiomm_volatile_table = {
37*1c05004fSWilliam Breathitt Gray 	.yes_ranges = gpiomm_volatile_ranges,
38*1c05004fSWilliam Breathitt Gray 	.n_yes_ranges = ARRAY_SIZE(gpiomm_volatile_ranges),
39*1c05004fSWilliam Breathitt Gray };
40*1c05004fSWilliam Breathitt Gray static const struct regmap_config gpiomm_regmap_config = {
41*1c05004fSWilliam Breathitt Gray 	.reg_bits = 8,
42*1c05004fSWilliam Breathitt Gray 	.reg_stride = 1,
43*1c05004fSWilliam Breathitt Gray 	.val_bits = 8,
44*1c05004fSWilliam Breathitt Gray 	.io_port = true,
45*1c05004fSWilliam Breathitt Gray 	.max_register = 0x7,
46*1c05004fSWilliam Breathitt Gray 	.volatile_table = &gpiomm_volatile_table,
47*1c05004fSWilliam Breathitt Gray 	.cache_type = REGCACHE_FLAT,
48*1c05004fSWilliam Breathitt Gray };
4965502a12SWilliam Breathitt Gray 
50210b4bdeSWilliam Breathitt Gray #define GPIOMM_NGPIO 48
51210b4bdeSWilliam Breathitt Gray static const char *gpiomm_names[GPIOMM_NGPIO] = {
52210b4bdeSWilliam Breathitt Gray 	"Port 1A0", "Port 1A1", "Port 1A2", "Port 1A3", "Port 1A4", "Port 1A5",
53210b4bdeSWilliam Breathitt Gray 	"Port 1A6", "Port 1A7", "Port 1B0", "Port 1B1", "Port 1B2", "Port 1B3",
54210b4bdeSWilliam Breathitt Gray 	"Port 1B4", "Port 1B5", "Port 1B6", "Port 1B7", "Port 1C0", "Port 1C1",
55210b4bdeSWilliam Breathitt Gray 	"Port 1C2", "Port 1C3", "Port 1C4", "Port 1C5", "Port 1C6", "Port 1C7",
56210b4bdeSWilliam Breathitt Gray 	"Port 2A0", "Port 2A1", "Port 2A2", "Port 2A3", "Port 2A4", "Port 2A5",
57210b4bdeSWilliam Breathitt Gray 	"Port 2A6", "Port 2A7", "Port 2B0", "Port 2B1", "Port 2B2", "Port 2B3",
58210b4bdeSWilliam Breathitt Gray 	"Port 2B4", "Port 2B5", "Port 2B6", "Port 2B7", "Port 2C0", "Port 2C1",
59210b4bdeSWilliam Breathitt Gray 	"Port 2C2", "Port 2C3", "Port 2C4", "Port 2C5", "Port 2C6", "Port 2C7",
60210b4bdeSWilliam Breathitt Gray };
61210b4bdeSWilliam Breathitt Gray 
gpiomm_probe(struct device * dev,unsigned int id)626ea5dcdfSWilliam Breathitt Gray static int gpiomm_probe(struct device *dev, unsigned int id)
636ea5dcdfSWilliam Breathitt Gray {
646ea5dcdfSWilliam Breathitt Gray 	const char *const name = dev_name(dev);
65*1c05004fSWilliam Breathitt Gray 	struct i8255_regmap_config config = {};
66*1c05004fSWilliam Breathitt Gray 	void __iomem *regs;
676ea5dcdfSWilliam Breathitt Gray 
686ea5dcdfSWilliam Breathitt Gray 	if (!devm_request_region(dev, base[id], GPIOMM_EXTENT, name)) {
696ea5dcdfSWilliam Breathitt Gray 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
706ea5dcdfSWilliam Breathitt Gray 			base[id], base[id] + GPIOMM_EXTENT);
716ea5dcdfSWilliam Breathitt Gray 		return -EBUSY;
726ea5dcdfSWilliam Breathitt Gray 	}
736ea5dcdfSWilliam Breathitt Gray 
74*1c05004fSWilliam Breathitt Gray 	regs = devm_ioport_map(dev, base[id], GPIOMM_EXTENT);
75*1c05004fSWilliam Breathitt Gray 	if (!regs)
7654c8e251SWilliam Breathitt Gray 		return -ENOMEM;
7754c8e251SWilliam Breathitt Gray 
78*1c05004fSWilliam Breathitt Gray 	config.map = devm_regmap_init_mmio(dev, regs, &gpiomm_regmap_config);
79*1c05004fSWilliam Breathitt Gray 	if (IS_ERR(config.map))
80*1c05004fSWilliam Breathitt Gray 		return dev_err_probe(dev, PTR_ERR(config.map),
81*1c05004fSWilliam Breathitt Gray 				     "Unable to initialize register map\n");
826ea5dcdfSWilliam Breathitt Gray 
83*1c05004fSWilliam Breathitt Gray 	config.parent = dev;
84*1c05004fSWilliam Breathitt Gray 	config.num_ppi = GPIOMM_NUM_PPI;
85*1c05004fSWilliam Breathitt Gray 	config.names = gpiomm_names;
866ea5dcdfSWilliam Breathitt Gray 
87*1c05004fSWilliam Breathitt Gray 	return devm_i8255_regmap_register(dev, &config);
886ea5dcdfSWilliam Breathitt Gray }
896ea5dcdfSWilliam Breathitt Gray 
906ea5dcdfSWilliam Breathitt Gray static struct isa_driver gpiomm_driver = {
916ea5dcdfSWilliam Breathitt Gray 	.probe = gpiomm_probe,
926ea5dcdfSWilliam Breathitt Gray 	.driver = {
936ea5dcdfSWilliam Breathitt Gray 		.name = "gpio-mm"
946ea5dcdfSWilliam Breathitt Gray 	},
956ea5dcdfSWilliam Breathitt Gray };
966ea5dcdfSWilliam Breathitt Gray 
976ea5dcdfSWilliam Breathitt Gray module_isa_driver(gpiomm_driver, num_gpiomm);
986ea5dcdfSWilliam Breathitt Gray 
996ea5dcdfSWilliam Breathitt Gray MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
1006ea5dcdfSWilliam Breathitt Gray MODULE_DESCRIPTION("Diamond Systems GPIO-MM GPIO driver");
1016ea5dcdfSWilliam Breathitt Gray MODULE_LICENSE("GPL v2");
102