xref: /linux/drivers/gpio/gpio-104-idio-16.c (revision 0be3ff0c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * GPIO driver for the ACCES 104-IDIO-16 family
4  * Copyright (C) 2015 William Breathitt Gray
5  *
6  * This driver supports the following ACCES devices: 104-IDIO-16,
7  * 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8.
8  */
9 #include <linux/bitops.h>
10 #include <linux/device.h>
11 #include <linux/errno.h>
12 #include <linux/gpio/driver.h>
13 #include <linux/io.h>
14 #include <linux/ioport.h>
15 #include <linux/interrupt.h>
16 #include <linux/irqdesc.h>
17 #include <linux/isa.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/moduleparam.h>
21 #include <linux/spinlock.h>
22 
23 #define IDIO_16_EXTENT 8
24 #define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT)
25 
26 static unsigned int base[MAX_NUM_IDIO_16];
27 static unsigned int num_idio_16;
28 module_param_hw_array(base, uint, ioport, &num_idio_16, 0);
29 MODULE_PARM_DESC(base, "ACCES 104-IDIO-16 base addresses");
30 
31 static unsigned int irq[MAX_NUM_IDIO_16];
32 module_param_hw_array(irq, uint, irq, NULL, 0);
33 MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
34 
35 /**
36  * struct idio_16_gpio - GPIO device private data structure
37  * @chip:	instance of the gpio_chip
38  * @lock:	synchronization lock to prevent I/O race conditions
39  * @irq_mask:	I/O bits affected by interrupts
40  * @base:	base port address of the GPIO device
41  * @out_state:	output bits state
42  */
43 struct idio_16_gpio {
44 	struct gpio_chip chip;
45 	raw_spinlock_t lock;
46 	unsigned long irq_mask;
47 	unsigned int base;
48 	unsigned int out_state;
49 };
50 
51 static int idio_16_gpio_get_direction(struct gpio_chip *chip,
52 				      unsigned int offset)
53 {
54 	if (offset > 15)
55 		return GPIO_LINE_DIRECTION_IN;
56 
57 	return GPIO_LINE_DIRECTION_OUT;
58 }
59 
60 static int idio_16_gpio_direction_input(struct gpio_chip *chip,
61 					unsigned int offset)
62 {
63 	return 0;
64 }
65 
66 static int idio_16_gpio_direction_output(struct gpio_chip *chip,
67 	unsigned int offset, int value)
68 {
69 	chip->set(chip, offset, value);
70 	return 0;
71 }
72 
73 static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
74 {
75 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
76 	const unsigned int mask = BIT(offset-16);
77 
78 	if (offset < 16)
79 		return -EINVAL;
80 
81 	if (offset < 24)
82 		return !!(inb(idio16gpio->base + 1) & mask);
83 
84 	return !!(inb(idio16gpio->base + 5) & (mask>>8));
85 }
86 
87 static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
88 	unsigned long *mask, unsigned long *bits)
89 {
90 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
91 
92 	*bits = 0;
93 	if (*mask & GENMASK(23, 16))
94 		*bits |= (unsigned long)inb(idio16gpio->base + 1) << 16;
95 	if (*mask & GENMASK(31, 24))
96 		*bits |= (unsigned long)inb(idio16gpio->base + 5) << 24;
97 
98 	return 0;
99 }
100 
101 static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
102 			     int value)
103 {
104 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
105 	const unsigned int mask = BIT(offset);
106 	unsigned long flags;
107 
108 	if (offset > 15)
109 		return;
110 
111 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
112 
113 	if (value)
114 		idio16gpio->out_state |= mask;
115 	else
116 		idio16gpio->out_state &= ~mask;
117 
118 	if (offset > 7)
119 		outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
120 	else
121 		outb(idio16gpio->out_state, idio16gpio->base);
122 
123 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
124 }
125 
126 static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
127 	unsigned long *mask, unsigned long *bits)
128 {
129 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
130 	unsigned long flags;
131 
132 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
133 
134 	idio16gpio->out_state &= ~*mask;
135 	idio16gpio->out_state |= *mask & *bits;
136 
137 	if (*mask & 0xFF)
138 		outb(idio16gpio->out_state, idio16gpio->base);
139 	if ((*mask >> 8) & 0xFF)
140 		outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
141 
142 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
143 }
144 
145 static void idio_16_irq_ack(struct irq_data *data)
146 {
147 }
148 
149 static void idio_16_irq_mask(struct irq_data *data)
150 {
151 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
152 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
153 	const unsigned long mask = BIT(irqd_to_hwirq(data));
154 	unsigned long flags;
155 
156 	idio16gpio->irq_mask &= ~mask;
157 
158 	if (!idio16gpio->irq_mask) {
159 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
160 
161 		outb(0, idio16gpio->base + 2);
162 
163 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
164 	}
165 }
166 
167 static void idio_16_irq_unmask(struct irq_data *data)
168 {
169 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
170 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
171 	const unsigned long mask = BIT(irqd_to_hwirq(data));
172 	const unsigned long prev_irq_mask = idio16gpio->irq_mask;
173 	unsigned long flags;
174 
175 	idio16gpio->irq_mask |= mask;
176 
177 	if (!prev_irq_mask) {
178 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
179 
180 		inb(idio16gpio->base + 2);
181 
182 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
183 	}
184 }
185 
186 static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
187 {
188 	/* The only valid irq types are none and both-edges */
189 	if (flow_type != IRQ_TYPE_NONE &&
190 		(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
191 		return -EINVAL;
192 
193 	return 0;
194 }
195 
196 static struct irq_chip idio_16_irqchip = {
197 	.name = "104-idio-16",
198 	.irq_ack = idio_16_irq_ack,
199 	.irq_mask = idio_16_irq_mask,
200 	.irq_unmask = idio_16_irq_unmask,
201 	.irq_set_type = idio_16_irq_set_type
202 };
203 
204 static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
205 {
206 	struct idio_16_gpio *const idio16gpio = dev_id;
207 	struct gpio_chip *const chip = &idio16gpio->chip;
208 	int gpio;
209 
210 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
211 		generic_handle_domain_irq(chip->irq.domain, gpio);
212 
213 	raw_spin_lock(&idio16gpio->lock);
214 
215 	outb(0, idio16gpio->base + 1);
216 
217 	raw_spin_unlock(&idio16gpio->lock);
218 
219 	return IRQ_HANDLED;
220 }
221 
222 #define IDIO_16_NGPIO 32
223 static const char *idio_16_names[IDIO_16_NGPIO] = {
224 	"OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
225 	"OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
226 	"IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
227 	"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
228 };
229 
230 static int idio_16_irq_init_hw(struct gpio_chip *gc)
231 {
232 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc);
233 
234 	/* Disable IRQ by default */
235 	outb(0, idio16gpio->base + 2);
236 	outb(0, idio16gpio->base + 1);
237 
238 	return 0;
239 }
240 
241 static int idio_16_probe(struct device *dev, unsigned int id)
242 {
243 	struct idio_16_gpio *idio16gpio;
244 	const char *const name = dev_name(dev);
245 	struct gpio_irq_chip *girq;
246 	int err;
247 
248 	idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
249 	if (!idio16gpio)
250 		return -ENOMEM;
251 
252 	if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) {
253 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
254 			base[id], base[id] + IDIO_16_EXTENT);
255 		return -EBUSY;
256 	}
257 
258 	idio16gpio->chip.label = name;
259 	idio16gpio->chip.parent = dev;
260 	idio16gpio->chip.owner = THIS_MODULE;
261 	idio16gpio->chip.base = -1;
262 	idio16gpio->chip.ngpio = IDIO_16_NGPIO;
263 	idio16gpio->chip.names = idio_16_names;
264 	idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
265 	idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
266 	idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
267 	idio16gpio->chip.get = idio_16_gpio_get;
268 	idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
269 	idio16gpio->chip.set = idio_16_gpio_set;
270 	idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
271 	idio16gpio->base = base[id];
272 	idio16gpio->out_state = 0xFFFF;
273 
274 	girq = &idio16gpio->chip.irq;
275 	girq->chip = &idio_16_irqchip;
276 	/* This will let us handle the parent IRQ in the driver */
277 	girq->parent_handler = NULL;
278 	girq->num_parents = 0;
279 	girq->parents = NULL;
280 	girq->default_type = IRQ_TYPE_NONE;
281 	girq->handler = handle_edge_irq;
282 	girq->init_hw = idio_16_irq_init_hw;
283 
284 	raw_spin_lock_init(&idio16gpio->lock);
285 
286 	err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
287 	if (err) {
288 		dev_err(dev, "GPIO registering failed (%d)\n", err);
289 		return err;
290 	}
291 
292 	err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name,
293 		idio16gpio);
294 	if (err) {
295 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
296 		return err;
297 	}
298 
299 	return 0;
300 }
301 
302 static struct isa_driver idio_16_driver = {
303 	.probe = idio_16_probe,
304 	.driver = {
305 		.name = "104-idio-16"
306 	},
307 };
308 
309 module_isa_driver(idio_16_driver, num_idio_16);
310 
311 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
312 MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
313 MODULE_LICENSE("GPL v2");
314