11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21ceacea2SWilliam Breathitt Gray /*
31ceacea2SWilliam Breathitt Gray  * GPIO driver for the ACCES 104-IDIO-16 family
41ceacea2SWilliam Breathitt Gray  * Copyright (C) 2015 William Breathitt Gray
51ceacea2SWilliam Breathitt Gray  *
686ea8a95SWilliam Breathitt Gray  * This driver supports the following ACCES devices: 104-IDIO-16,
786ea8a95SWilliam Breathitt Gray  * 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8.
81ceacea2SWilliam Breathitt Gray  */
9cc442e4dSWilliam Breathitt Gray #include <linux/bits.h>
101ceacea2SWilliam Breathitt Gray #include <linux/device.h>
111ceacea2SWilliam Breathitt Gray #include <linux/errno.h>
121ceacea2SWilliam Breathitt Gray #include <linux/gpio/driver.h>
131ceacea2SWilliam Breathitt Gray #include <linux/io.h>
141ceacea2SWilliam Breathitt Gray #include <linux/ioport.h>
15a1184147SWilliam Breathitt Gray #include <linux/interrupt.h>
16a1184147SWilliam Breathitt Gray #include <linux/irqdesc.h>
1786ea8a95SWilliam Breathitt Gray #include <linux/isa.h>
181ceacea2SWilliam Breathitt Gray #include <linux/kernel.h>
191ceacea2SWilliam Breathitt Gray #include <linux/module.h>
201ceacea2SWilliam Breathitt Gray #include <linux/moduleparam.h>
211ceacea2SWilliam Breathitt Gray #include <linux/spinlock.h>
22cc442e4dSWilliam Breathitt Gray #include <linux/types.h>
231ceacea2SWilliam Breathitt Gray 
2486ea8a95SWilliam Breathitt Gray #define IDIO_16_EXTENT 8
2586ea8a95SWilliam Breathitt Gray #define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT)
2686ea8a95SWilliam Breathitt Gray 
2786ea8a95SWilliam Breathitt Gray static unsigned int base[MAX_NUM_IDIO_16];
2886ea8a95SWilliam Breathitt Gray static unsigned int num_idio_16;
29d759f906SDavid Howells module_param_hw_array(base, uint, ioport, &num_idio_16, 0);
3086ea8a95SWilliam Breathitt Gray MODULE_PARM_DESC(base, "ACCES 104-IDIO-16 base addresses");
3186ea8a95SWilliam Breathitt Gray 
3286ea8a95SWilliam Breathitt Gray static unsigned int irq[MAX_NUM_IDIO_16];
33*c6074f3fSWilliam Breathitt Gray static unsigned int num_irq;
34*c6074f3fSWilliam Breathitt Gray module_param_hw_array(irq, uint, irq, &num_irq, 0);
3586ea8a95SWilliam Breathitt Gray MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
361ceacea2SWilliam Breathitt Gray 
371ceacea2SWilliam Breathitt Gray /**
38cc442e4dSWilliam Breathitt Gray  * struct idio_16_reg - device registers structure
39cc442e4dSWilliam Breathitt Gray  * @out0_7:	Read: N/A
40cc442e4dSWilliam Breathitt Gray  *		Write: FET Drive Outputs 0-7
41cc442e4dSWilliam Breathitt Gray  * @in0_7:	Read: Isolated Inputs 0-7
42cc442e4dSWilliam Breathitt Gray  *		Write: Clear Interrupt
43cc442e4dSWilliam Breathitt Gray  * @irq_ctl:	Read: Enable IRQ
44cc442e4dSWilliam Breathitt Gray  *		Write: Disable IRQ
45cc442e4dSWilliam Breathitt Gray  * @unused:	N/A
46cc442e4dSWilliam Breathitt Gray  * @out8_15:	Read: N/A
47cc442e4dSWilliam Breathitt Gray  *		Write: FET Drive Outputs 8-15
48cc442e4dSWilliam Breathitt Gray  * @in8_15:	Read: Isolated Inputs 8-15
49cc442e4dSWilliam Breathitt Gray  *		Write: N/A
50cc442e4dSWilliam Breathitt Gray  */
51cc442e4dSWilliam Breathitt Gray struct idio_16_reg {
52cc442e4dSWilliam Breathitt Gray 	u8 out0_7;
53cc442e4dSWilliam Breathitt Gray 	u8 in0_7;
54cc442e4dSWilliam Breathitt Gray 	u8 irq_ctl;
55cc442e4dSWilliam Breathitt Gray 	u8 unused;
56cc442e4dSWilliam Breathitt Gray 	u8 out8_15;
57cc442e4dSWilliam Breathitt Gray 	u8 in8_15;
58cc442e4dSWilliam Breathitt Gray };
59cc442e4dSWilliam Breathitt Gray 
60cc442e4dSWilliam Breathitt Gray /**
611ceacea2SWilliam Breathitt Gray  * struct idio_16_gpio - GPIO device private data structure
621ceacea2SWilliam Breathitt Gray  * @chip:	instance of the gpio_chip
63a1184147SWilliam Breathitt Gray  * @lock:	synchronization lock to prevent I/O race conditions
64a1184147SWilliam Breathitt Gray  * @irq_mask:	I/O bits affected by interrupts
65cc442e4dSWilliam Breathitt Gray  * @reg:	I/O address offset for the device registers
661ceacea2SWilliam Breathitt Gray  * @out_state:	output bits state
671ceacea2SWilliam Breathitt Gray  */
681ceacea2SWilliam Breathitt Gray struct idio_16_gpio {
691ceacea2SWilliam Breathitt Gray 	struct gpio_chip chip;
703906e808SJulia Cartwright 	raw_spinlock_t lock;
71a1184147SWilliam Breathitt Gray 	unsigned long irq_mask;
72cc442e4dSWilliam Breathitt Gray 	struct idio_16_reg __iomem *reg;
73cc0f53d2SNavin Sankar Velliangiri 	unsigned int out_state;
741ceacea2SWilliam Breathitt Gray };
751ceacea2SWilliam Breathitt Gray 
76cc0f53d2SNavin Sankar Velliangiri static int idio_16_gpio_get_direction(struct gpio_chip *chip,
77cc0f53d2SNavin Sankar Velliangiri 				      unsigned int offset)
781ceacea2SWilliam Breathitt Gray {
791ceacea2SWilliam Breathitt Gray 	if (offset > 15)
80e42615ecSMatti Vaittinen 		return GPIO_LINE_DIRECTION_IN;
811ceacea2SWilliam Breathitt Gray 
82e42615ecSMatti Vaittinen 	return GPIO_LINE_DIRECTION_OUT;
831ceacea2SWilliam Breathitt Gray }
841ceacea2SWilliam Breathitt Gray 
85cc0f53d2SNavin Sankar Velliangiri static int idio_16_gpio_direction_input(struct gpio_chip *chip,
86cc0f53d2SNavin Sankar Velliangiri 					unsigned int offset)
871ceacea2SWilliam Breathitt Gray {
881ceacea2SWilliam Breathitt Gray 	return 0;
891ceacea2SWilliam Breathitt Gray }
901ceacea2SWilliam Breathitt Gray 
911ceacea2SWilliam Breathitt Gray static int idio_16_gpio_direction_output(struct gpio_chip *chip,
92cc0f53d2SNavin Sankar Velliangiri 	unsigned int offset, int value)
931ceacea2SWilliam Breathitt Gray {
941ceacea2SWilliam Breathitt Gray 	chip->set(chip, offset, value);
951ceacea2SWilliam Breathitt Gray 	return 0;
961ceacea2SWilliam Breathitt Gray }
971ceacea2SWilliam Breathitt Gray 
98cc0f53d2SNavin Sankar Velliangiri static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
991ceacea2SWilliam Breathitt Gray {
100d602ae90SLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
101cc0f53d2SNavin Sankar Velliangiri 	const unsigned int mask = BIT(offset-16);
1021ceacea2SWilliam Breathitt Gray 
1031ceacea2SWilliam Breathitt Gray 	if (offset < 16)
1041ceacea2SWilliam Breathitt Gray 		return -EINVAL;
1051ceacea2SWilliam Breathitt Gray 
1061ceacea2SWilliam Breathitt Gray 	if (offset < 24)
107cc442e4dSWilliam Breathitt Gray 		return !!(ioread8(&idio16gpio->reg->in0_7) & mask);
1081ceacea2SWilliam Breathitt Gray 
109cc442e4dSWilliam Breathitt Gray 	return !!(ioread8(&idio16gpio->reg->in8_15) & (mask>>8));
1101ceacea2SWilliam Breathitt Gray }
1111ceacea2SWilliam Breathitt Gray 
11215f59cffSWilliam Breathitt Gray static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
11315f59cffSWilliam Breathitt Gray 	unsigned long *mask, unsigned long *bits)
11415f59cffSWilliam Breathitt Gray {
11515f59cffSWilliam Breathitt Gray 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
11615f59cffSWilliam Breathitt Gray 
11715f59cffSWilliam Breathitt Gray 	*bits = 0;
11815f59cffSWilliam Breathitt Gray 	if (*mask & GENMASK(23, 16))
119cc442e4dSWilliam Breathitt Gray 		*bits |= (unsigned long)ioread8(&idio16gpio->reg->in0_7) << 16;
12015f59cffSWilliam Breathitt Gray 	if (*mask & GENMASK(31, 24))
121cc442e4dSWilliam Breathitt Gray 		*bits |= (unsigned long)ioread8(&idio16gpio->reg->in8_15) << 24;
12215f59cffSWilliam Breathitt Gray 
12315f59cffSWilliam Breathitt Gray 	return 0;
12415f59cffSWilliam Breathitt Gray }
12515f59cffSWilliam Breathitt Gray 
126cc0f53d2SNavin Sankar Velliangiri static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
127cc0f53d2SNavin Sankar Velliangiri 			     int value)
1281ceacea2SWilliam Breathitt Gray {
129d602ae90SLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
130cc0f53d2SNavin Sankar Velliangiri 	const unsigned int mask = BIT(offset);
1311ceacea2SWilliam Breathitt Gray 	unsigned long flags;
1321ceacea2SWilliam Breathitt Gray 
1331ceacea2SWilliam Breathitt Gray 	if (offset > 15)
1341ceacea2SWilliam Breathitt Gray 		return;
1351ceacea2SWilliam Breathitt Gray 
1363906e808SJulia Cartwright 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
1371ceacea2SWilliam Breathitt Gray 
1381ceacea2SWilliam Breathitt Gray 	if (value)
1396e0171b4SWilliam Breathitt Gray 		idio16gpio->out_state |= mask;
1401ceacea2SWilliam Breathitt Gray 	else
1416e0171b4SWilliam Breathitt Gray 		idio16gpio->out_state &= ~mask;
1421ceacea2SWilliam Breathitt Gray 
1431ceacea2SWilliam Breathitt Gray 	if (offset > 7)
144cc442e4dSWilliam Breathitt Gray 		iowrite8(idio16gpio->out_state >> 8, &idio16gpio->reg->out8_15);
1451ceacea2SWilliam Breathitt Gray 	else
146cc442e4dSWilliam Breathitt Gray 		iowrite8(idio16gpio->out_state, &idio16gpio->reg->out0_7);
1471ceacea2SWilliam Breathitt Gray 
1483906e808SJulia Cartwright 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
1491ceacea2SWilliam Breathitt Gray }
1501ceacea2SWilliam Breathitt Gray 
1519d7ae812SWilliam Breathitt Gray static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
1529d7ae812SWilliam Breathitt Gray 	unsigned long *mask, unsigned long *bits)
1539d7ae812SWilliam Breathitt Gray {
1549d7ae812SWilliam Breathitt Gray 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
1559d7ae812SWilliam Breathitt Gray 	unsigned long flags;
1569d7ae812SWilliam Breathitt Gray 
1573906e808SJulia Cartwright 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
1589d7ae812SWilliam Breathitt Gray 
1599d7ae812SWilliam Breathitt Gray 	idio16gpio->out_state &= ~*mask;
1609d7ae812SWilliam Breathitt Gray 	idio16gpio->out_state |= *mask & *bits;
1619d7ae812SWilliam Breathitt Gray 
1629d7ae812SWilliam Breathitt Gray 	if (*mask & 0xFF)
163cc442e4dSWilliam Breathitt Gray 		iowrite8(idio16gpio->out_state, &idio16gpio->reg->out0_7);
1649d7ae812SWilliam Breathitt Gray 	if ((*mask >> 8) & 0xFF)
165cc442e4dSWilliam Breathitt Gray 		iowrite8(idio16gpio->out_state >> 8, &idio16gpio->reg->out8_15);
1669d7ae812SWilliam Breathitt Gray 
1673906e808SJulia Cartwright 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
1689d7ae812SWilliam Breathitt Gray }
1699d7ae812SWilliam Breathitt Gray 
170a1184147SWilliam Breathitt Gray static void idio_16_irq_ack(struct irq_data *data)
171a1184147SWilliam Breathitt Gray {
172a1184147SWilliam Breathitt Gray }
173a1184147SWilliam Breathitt Gray 
174a1184147SWilliam Breathitt Gray static void idio_16_irq_mask(struct irq_data *data)
175a1184147SWilliam Breathitt Gray {
176a1184147SWilliam Breathitt Gray 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
177d602ae90SLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
178a1184147SWilliam Breathitt Gray 	const unsigned long mask = BIT(irqd_to_hwirq(data));
179a1184147SWilliam Breathitt Gray 	unsigned long flags;
180a1184147SWilliam Breathitt Gray 
181a1184147SWilliam Breathitt Gray 	idio16gpio->irq_mask &= ~mask;
182a1184147SWilliam Breathitt Gray 
183a1184147SWilliam Breathitt Gray 	if (!idio16gpio->irq_mask) {
1843906e808SJulia Cartwright 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
185a1184147SWilliam Breathitt Gray 
186cc442e4dSWilliam Breathitt Gray 		iowrite8(0, &idio16gpio->reg->irq_ctl);
187a1184147SWilliam Breathitt Gray 
1883906e808SJulia Cartwright 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
189a1184147SWilliam Breathitt Gray 	}
190a1184147SWilliam Breathitt Gray }
191a1184147SWilliam Breathitt Gray 
192a1184147SWilliam Breathitt Gray static void idio_16_irq_unmask(struct irq_data *data)
193a1184147SWilliam Breathitt Gray {
194a1184147SWilliam Breathitt Gray 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
195d602ae90SLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
196a1184147SWilliam Breathitt Gray 	const unsigned long mask = BIT(irqd_to_hwirq(data));
197a1184147SWilliam Breathitt Gray 	const unsigned long prev_irq_mask = idio16gpio->irq_mask;
198a1184147SWilliam Breathitt Gray 	unsigned long flags;
199a1184147SWilliam Breathitt Gray 
200a1184147SWilliam Breathitt Gray 	idio16gpio->irq_mask |= mask;
201a1184147SWilliam Breathitt Gray 
202a1184147SWilliam Breathitt Gray 	if (!prev_irq_mask) {
2033906e808SJulia Cartwright 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
204a1184147SWilliam Breathitt Gray 
205cc442e4dSWilliam Breathitt Gray 		ioread8(&idio16gpio->reg->irq_ctl);
206a1184147SWilliam Breathitt Gray 
2073906e808SJulia Cartwright 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
208a1184147SWilliam Breathitt Gray 	}
209a1184147SWilliam Breathitt Gray }
210a1184147SWilliam Breathitt Gray 
211cc0f53d2SNavin Sankar Velliangiri static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
212a1184147SWilliam Breathitt Gray {
213a1184147SWilliam Breathitt Gray 	/* The only valid irq types are none and both-edges */
214a1184147SWilliam Breathitt Gray 	if (flow_type != IRQ_TYPE_NONE &&
215a1184147SWilliam Breathitt Gray 		(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
216a1184147SWilliam Breathitt Gray 		return -EINVAL;
217a1184147SWilliam Breathitt Gray 
218a1184147SWilliam Breathitt Gray 	return 0;
219a1184147SWilliam Breathitt Gray }
220a1184147SWilliam Breathitt Gray 
221a1184147SWilliam Breathitt Gray static struct irq_chip idio_16_irqchip = {
222a1184147SWilliam Breathitt Gray 	.name = "104-idio-16",
223a1184147SWilliam Breathitt Gray 	.irq_ack = idio_16_irq_ack,
224a1184147SWilliam Breathitt Gray 	.irq_mask = idio_16_irq_mask,
225a1184147SWilliam Breathitt Gray 	.irq_unmask = idio_16_irq_unmask,
226a1184147SWilliam Breathitt Gray 	.irq_set_type = idio_16_irq_set_type
227a1184147SWilliam Breathitt Gray };
228a1184147SWilliam Breathitt Gray 
229a1184147SWilliam Breathitt Gray static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
230a1184147SWilliam Breathitt Gray {
231a1184147SWilliam Breathitt Gray 	struct idio_16_gpio *const idio16gpio = dev_id;
232a1184147SWilliam Breathitt Gray 	struct gpio_chip *const chip = &idio16gpio->chip;
233a1184147SWilliam Breathitt Gray 	int gpio;
234a1184147SWilliam Breathitt Gray 
235a1184147SWilliam Breathitt Gray 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
236dbd1c54fSMarc Zyngier 		generic_handle_domain_irq(chip->irq.domain, gpio);
237a1184147SWilliam Breathitt Gray 
2383906e808SJulia Cartwright 	raw_spin_lock(&idio16gpio->lock);
23912b61c9dSWilliam Breathitt Gray 
240cc442e4dSWilliam Breathitt Gray 	iowrite8(0, &idio16gpio->reg->in0_7);
24112b61c9dSWilliam Breathitt Gray 
2423906e808SJulia Cartwright 	raw_spin_unlock(&idio16gpio->lock);
24312b61c9dSWilliam Breathitt Gray 
244a1184147SWilliam Breathitt Gray 	return IRQ_HANDLED;
245a1184147SWilliam Breathitt Gray }
246a1184147SWilliam Breathitt Gray 
247e0af4b5eSWilliam Breathitt Gray #define IDIO_16_NGPIO 32
248e0af4b5eSWilliam Breathitt Gray static const char *idio_16_names[IDIO_16_NGPIO] = {
249e0af4b5eSWilliam Breathitt Gray 	"OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
250e0af4b5eSWilliam Breathitt Gray 	"OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
251e0af4b5eSWilliam Breathitt Gray 	"IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
252e0af4b5eSWilliam Breathitt Gray 	"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
253e0af4b5eSWilliam Breathitt Gray };
254e0af4b5eSWilliam Breathitt Gray 
25582e4613dSLinus Walleij static int idio_16_irq_init_hw(struct gpio_chip *gc)
25682e4613dSLinus Walleij {
25782e4613dSLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc);
25882e4613dSLinus Walleij 
25982e4613dSLinus Walleij 	/* Disable IRQ by default */
260cc442e4dSWilliam Breathitt Gray 	iowrite8(0, &idio16gpio->reg->irq_ctl);
261cc442e4dSWilliam Breathitt Gray 	iowrite8(0, &idio16gpio->reg->in0_7);
26282e4613dSLinus Walleij 
26382e4613dSLinus Walleij 	return 0;
26482e4613dSLinus Walleij }
26582e4613dSLinus Walleij 
26686ea8a95SWilliam Breathitt Gray static int idio_16_probe(struct device *dev, unsigned int id)
2671ceacea2SWilliam Breathitt Gray {
2681ceacea2SWilliam Breathitt Gray 	struct idio_16_gpio *idio16gpio;
2696e0171b4SWilliam Breathitt Gray 	const char *const name = dev_name(dev);
27082e4613dSLinus Walleij 	struct gpio_irq_chip *girq;
2711ceacea2SWilliam Breathitt Gray 	int err;
2721ceacea2SWilliam Breathitt Gray 
2731ceacea2SWilliam Breathitt Gray 	idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
2741ceacea2SWilliam Breathitt Gray 	if (!idio16gpio)
2751ceacea2SWilliam Breathitt Gray 		return -ENOMEM;
2761ceacea2SWilliam Breathitt Gray 
27786ea8a95SWilliam Breathitt Gray 	if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) {
278cb32389cSWilliam Breathitt Gray 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
27986ea8a95SWilliam Breathitt Gray 			base[id], base[id] + IDIO_16_EXTENT);
280cb32389cSWilliam Breathitt Gray 		return -EBUSY;
2811ceacea2SWilliam Breathitt Gray 	}
2821ceacea2SWilliam Breathitt Gray 
283cc442e4dSWilliam Breathitt Gray 	idio16gpio->reg = devm_ioport_map(dev, base[id], IDIO_16_EXTENT);
284cc442e4dSWilliam Breathitt Gray 	if (!idio16gpio->reg)
285e0a574efSWilliam Breathitt Gray 		return -ENOMEM;
286e0a574efSWilliam Breathitt Gray 
2876e0171b4SWilliam Breathitt Gray 	idio16gpio->chip.label = name;
28858383c78SLinus Walleij 	idio16gpio->chip.parent = dev;
2891ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.owner = THIS_MODULE;
2901ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.base = -1;
291e0af4b5eSWilliam Breathitt Gray 	idio16gpio->chip.ngpio = IDIO_16_NGPIO;
292e0af4b5eSWilliam Breathitt Gray 	idio16gpio->chip.names = idio_16_names;
2931ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
2941ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
2951ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
2961ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.get = idio_16_gpio_get;
29715f59cffSWilliam Breathitt Gray 	idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
2981ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.set = idio_16_gpio_set;
2999d7ae812SWilliam Breathitt Gray 	idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
3001ceacea2SWilliam Breathitt Gray 	idio16gpio->out_state = 0xFFFF;
3011ceacea2SWilliam Breathitt Gray 
30282e4613dSLinus Walleij 	girq = &idio16gpio->chip.irq;
30382e4613dSLinus Walleij 	girq->chip = &idio_16_irqchip;
30482e4613dSLinus Walleij 	/* This will let us handle the parent IRQ in the driver */
30582e4613dSLinus Walleij 	girq->parent_handler = NULL;
30682e4613dSLinus Walleij 	girq->num_parents = 0;
30782e4613dSLinus Walleij 	girq->parents = NULL;
30882e4613dSLinus Walleij 	girq->default_type = IRQ_TYPE_NONE;
30982e4613dSLinus Walleij 	girq->handler = handle_edge_irq;
31082e4613dSLinus Walleij 	girq->init_hw = idio_16_irq_init_hw;
31182e4613dSLinus Walleij 
3123906e808SJulia Cartwright 	raw_spin_lock_init(&idio16gpio->lock);
3131ceacea2SWilliam Breathitt Gray 
314837143d3SWilliam Breathitt Gray 	err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
3151ceacea2SWilliam Breathitt Gray 	if (err) {
3161ceacea2SWilliam Breathitt Gray 		dev_err(dev, "GPIO registering failed (%d)\n", err);
317cb32389cSWilliam Breathitt Gray 		return err;
3181ceacea2SWilliam Breathitt Gray 	}
3191ceacea2SWilliam Breathitt Gray 
320837143d3SWilliam Breathitt Gray 	err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name,
321837143d3SWilliam Breathitt Gray 		idio16gpio);
322837143d3SWilliam Breathitt Gray 	if (err) {
323837143d3SWilliam Breathitt Gray 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
324837143d3SWilliam Breathitt Gray 		return err;
325837143d3SWilliam Breathitt Gray 	}
3261ceacea2SWilliam Breathitt Gray 
3271ceacea2SWilliam Breathitt Gray 	return 0;
3281ceacea2SWilliam Breathitt Gray }
3291ceacea2SWilliam Breathitt Gray 
33086ea8a95SWilliam Breathitt Gray static struct isa_driver idio_16_driver = {
33186ea8a95SWilliam Breathitt Gray 	.probe = idio_16_probe,
3321ceacea2SWilliam Breathitt Gray 	.driver = {
3331ceacea2SWilliam Breathitt Gray 		.name = "104-idio-16"
3341ceacea2SWilliam Breathitt Gray 	},
3351ceacea2SWilliam Breathitt Gray };
3361ceacea2SWilliam Breathitt Gray 
337*c6074f3fSWilliam Breathitt Gray module_isa_driver_with_irq(idio_16_driver, num_idio_16, num_irq);
3381ceacea2SWilliam Breathitt Gray 
3391ceacea2SWilliam Breathitt Gray MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
3401ceacea2SWilliam Breathitt Gray MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
34122aeddb5SWilliam Breathitt Gray MODULE_LICENSE("GPL v2");
342