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