xref: /linux/drivers/gpio/gpio-104-idio-16.c (revision d2912cb15bdda8ba4a5dd73396ad62641af2f520)
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 base;
48 	unsigned out_state;
49 };
50 
51 static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
52 {
53 	if (offset > 15)
54 		return 1;
55 
56 	return 0;
57 }
58 
59 static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
60 {
61 	return 0;
62 }
63 
64 static int idio_16_gpio_direction_output(struct gpio_chip *chip,
65 	unsigned offset, int value)
66 {
67 	chip->set(chip, offset, value);
68 	return 0;
69 }
70 
71 static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset)
72 {
73 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
74 	const unsigned mask = BIT(offset-16);
75 
76 	if (offset < 16)
77 		return -EINVAL;
78 
79 	if (offset < 24)
80 		return !!(inb(idio16gpio->base + 1) & mask);
81 
82 	return !!(inb(idio16gpio->base + 5) & (mask>>8));
83 }
84 
85 static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
86 	unsigned long *mask, unsigned long *bits)
87 {
88 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
89 
90 	*bits = 0;
91 	if (*mask & GENMASK(23, 16))
92 		*bits |= (unsigned long)inb(idio16gpio->base + 1) << 16;
93 	if (*mask & GENMASK(31, 24))
94 		*bits |= (unsigned long)inb(idio16gpio->base + 5) << 24;
95 
96 	return 0;
97 }
98 
99 static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
100 {
101 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
102 	const unsigned mask = BIT(offset);
103 	unsigned long flags;
104 
105 	if (offset > 15)
106 		return;
107 
108 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
109 
110 	if (value)
111 		idio16gpio->out_state |= mask;
112 	else
113 		idio16gpio->out_state &= ~mask;
114 
115 	if (offset > 7)
116 		outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
117 	else
118 		outb(idio16gpio->out_state, idio16gpio->base);
119 
120 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
121 }
122 
123 static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
124 	unsigned long *mask, unsigned long *bits)
125 {
126 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
127 	unsigned long flags;
128 
129 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
130 
131 	idio16gpio->out_state &= ~*mask;
132 	idio16gpio->out_state |= *mask & *bits;
133 
134 	if (*mask & 0xFF)
135 		outb(idio16gpio->out_state, idio16gpio->base);
136 	if ((*mask >> 8) & 0xFF)
137 		outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
138 
139 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
140 }
141 
142 static void idio_16_irq_ack(struct irq_data *data)
143 {
144 }
145 
146 static void idio_16_irq_mask(struct irq_data *data)
147 {
148 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
149 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
150 	const unsigned long mask = BIT(irqd_to_hwirq(data));
151 	unsigned long flags;
152 
153 	idio16gpio->irq_mask &= ~mask;
154 
155 	if (!idio16gpio->irq_mask) {
156 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
157 
158 		outb(0, idio16gpio->base + 2);
159 
160 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
161 	}
162 }
163 
164 static void idio_16_irq_unmask(struct irq_data *data)
165 {
166 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
167 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
168 	const unsigned long mask = BIT(irqd_to_hwirq(data));
169 	const unsigned long prev_irq_mask = idio16gpio->irq_mask;
170 	unsigned long flags;
171 
172 	idio16gpio->irq_mask |= mask;
173 
174 	if (!prev_irq_mask) {
175 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
176 
177 		inb(idio16gpio->base + 2);
178 
179 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
180 	}
181 }
182 
183 static int idio_16_irq_set_type(struct irq_data *data, unsigned flow_type)
184 {
185 	/* The only valid irq types are none and both-edges */
186 	if (flow_type != IRQ_TYPE_NONE &&
187 		(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
188 		return -EINVAL;
189 
190 	return 0;
191 }
192 
193 static struct irq_chip idio_16_irqchip = {
194 	.name = "104-idio-16",
195 	.irq_ack = idio_16_irq_ack,
196 	.irq_mask = idio_16_irq_mask,
197 	.irq_unmask = idio_16_irq_unmask,
198 	.irq_set_type = idio_16_irq_set_type
199 };
200 
201 static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
202 {
203 	struct idio_16_gpio *const idio16gpio = dev_id;
204 	struct gpio_chip *const chip = &idio16gpio->chip;
205 	int gpio;
206 
207 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
208 		generic_handle_irq(irq_find_mapping(chip->irq.domain, gpio));
209 
210 	raw_spin_lock(&idio16gpio->lock);
211 
212 	outb(0, idio16gpio->base + 1);
213 
214 	raw_spin_unlock(&idio16gpio->lock);
215 
216 	return IRQ_HANDLED;
217 }
218 
219 #define IDIO_16_NGPIO 32
220 static const char *idio_16_names[IDIO_16_NGPIO] = {
221 	"OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
222 	"OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
223 	"IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
224 	"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
225 };
226 
227 static int idio_16_probe(struct device *dev, unsigned int id)
228 {
229 	struct idio_16_gpio *idio16gpio;
230 	const char *const name = dev_name(dev);
231 	int err;
232 
233 	idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
234 	if (!idio16gpio)
235 		return -ENOMEM;
236 
237 	if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) {
238 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
239 			base[id], base[id] + IDIO_16_EXTENT);
240 		return -EBUSY;
241 	}
242 
243 	idio16gpio->chip.label = name;
244 	idio16gpio->chip.parent = dev;
245 	idio16gpio->chip.owner = THIS_MODULE;
246 	idio16gpio->chip.base = -1;
247 	idio16gpio->chip.ngpio = IDIO_16_NGPIO;
248 	idio16gpio->chip.names = idio_16_names;
249 	idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
250 	idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
251 	idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
252 	idio16gpio->chip.get = idio_16_gpio_get;
253 	idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
254 	idio16gpio->chip.set = idio_16_gpio_set;
255 	idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
256 	idio16gpio->base = base[id];
257 	idio16gpio->out_state = 0xFFFF;
258 
259 	raw_spin_lock_init(&idio16gpio->lock);
260 
261 	err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
262 	if (err) {
263 		dev_err(dev, "GPIO registering failed (%d)\n", err);
264 		return err;
265 	}
266 
267 	/* Disable IRQ by default */
268 	outb(0, base[id] + 2);
269 	outb(0, base[id] + 1);
270 
271 	err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0,
272 		handle_edge_irq, IRQ_TYPE_NONE);
273 	if (err) {
274 		dev_err(dev, "Could not add irqchip (%d)\n", err);
275 		return err;
276 	}
277 
278 	err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name,
279 		idio16gpio);
280 	if (err) {
281 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
282 		return err;
283 	}
284 
285 	return 0;
286 }
287 
288 static struct isa_driver idio_16_driver = {
289 	.probe = idio_16_probe,
290 	.driver = {
291 		.name = "104-idio-16"
292 	},
293 };
294 
295 module_isa_driver(idio_16_driver, num_idio_16);
296 
297 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
298 MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
299 MODULE_LICENSE("GPL v2");
300