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];
33d759f906SDavid Howells module_param_hw_array(irq, uint, irq, NULL, 0);
3486ea8a95SWilliam Breathitt Gray MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
351ceacea2SWilliam Breathitt Gray 
361ceacea2SWilliam Breathitt Gray /**
37cc442e4dSWilliam Breathitt Gray  * struct idio_16_reg - device registers structure
38cc442e4dSWilliam Breathitt Gray  * @out0_7:	Read: N/A
39cc442e4dSWilliam Breathitt Gray  *		Write: FET Drive Outputs 0-7
40cc442e4dSWilliam Breathitt Gray  * @in0_7:	Read: Isolated Inputs 0-7
41cc442e4dSWilliam Breathitt Gray  *		Write: Clear Interrupt
42cc442e4dSWilliam Breathitt Gray  * @irq_ctl:	Read: Enable IRQ
43cc442e4dSWilliam Breathitt Gray  *		Write: Disable IRQ
44cc442e4dSWilliam Breathitt Gray  * @unused:	N/A
45cc442e4dSWilliam Breathitt Gray  * @out8_15:	Read: N/A
46cc442e4dSWilliam Breathitt Gray  *		Write: FET Drive Outputs 8-15
47cc442e4dSWilliam Breathitt Gray  * @in8_15:	Read: Isolated Inputs 8-15
48cc442e4dSWilliam Breathitt Gray  *		Write: N/A
49cc442e4dSWilliam Breathitt Gray  */
50cc442e4dSWilliam Breathitt Gray struct idio_16_reg {
51cc442e4dSWilliam Breathitt Gray 	u8 out0_7;
52cc442e4dSWilliam Breathitt Gray 	u8 in0_7;
53cc442e4dSWilliam Breathitt Gray 	u8 irq_ctl;
54cc442e4dSWilliam Breathitt Gray 	u8 unused;
55cc442e4dSWilliam Breathitt Gray 	u8 out8_15;
56cc442e4dSWilliam Breathitt Gray 	u8 in8_15;
57cc442e4dSWilliam Breathitt Gray };
58cc442e4dSWilliam Breathitt Gray 
59cc442e4dSWilliam Breathitt Gray /**
601ceacea2SWilliam Breathitt Gray  * struct idio_16_gpio - GPIO device private data structure
611ceacea2SWilliam Breathitt Gray  * @chip:	instance of the gpio_chip
62a1184147SWilliam Breathitt Gray  * @lock:	synchronization lock to prevent I/O race conditions
63a1184147SWilliam Breathitt Gray  * @irq_mask:	I/O bits affected by interrupts
64cc442e4dSWilliam Breathitt Gray  * @reg:	I/O address offset for the device registers
651ceacea2SWilliam Breathitt Gray  * @out_state:	output bits state
661ceacea2SWilliam Breathitt Gray  */
671ceacea2SWilliam Breathitt Gray struct idio_16_gpio {
681ceacea2SWilliam Breathitt Gray 	struct gpio_chip chip;
693906e808SJulia Cartwright 	raw_spinlock_t lock;
70a1184147SWilliam Breathitt Gray 	unsigned long irq_mask;
71cc442e4dSWilliam Breathitt Gray 	struct idio_16_reg __iomem *reg;
72cc0f53d2SNavin Sankar Velliangiri 	unsigned int out_state;
731ceacea2SWilliam Breathitt Gray };
741ceacea2SWilliam Breathitt Gray 
75cc0f53d2SNavin Sankar Velliangiri static int idio_16_gpio_get_direction(struct gpio_chip *chip,
76cc0f53d2SNavin Sankar Velliangiri 				      unsigned int offset)
771ceacea2SWilliam Breathitt Gray {
781ceacea2SWilliam Breathitt Gray 	if (offset > 15)
79e42615ecSMatti Vaittinen 		return GPIO_LINE_DIRECTION_IN;
801ceacea2SWilliam Breathitt Gray 
81e42615ecSMatti Vaittinen 	return GPIO_LINE_DIRECTION_OUT;
821ceacea2SWilliam Breathitt Gray }
831ceacea2SWilliam Breathitt Gray 
84cc0f53d2SNavin Sankar Velliangiri static int idio_16_gpio_direction_input(struct gpio_chip *chip,
85cc0f53d2SNavin Sankar Velliangiri 					unsigned int offset)
861ceacea2SWilliam Breathitt Gray {
871ceacea2SWilliam Breathitt Gray 	return 0;
881ceacea2SWilliam Breathitt Gray }
891ceacea2SWilliam Breathitt Gray 
901ceacea2SWilliam Breathitt Gray static int idio_16_gpio_direction_output(struct gpio_chip *chip,
91cc0f53d2SNavin Sankar Velliangiri 	unsigned int offset, int value)
921ceacea2SWilliam Breathitt Gray {
931ceacea2SWilliam Breathitt Gray 	chip->set(chip, offset, value);
941ceacea2SWilliam Breathitt Gray 	return 0;
951ceacea2SWilliam Breathitt Gray }
961ceacea2SWilliam Breathitt Gray 
97cc0f53d2SNavin Sankar Velliangiri static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
981ceacea2SWilliam Breathitt Gray {
99d602ae90SLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
100cc0f53d2SNavin Sankar Velliangiri 	const unsigned int mask = BIT(offset-16);
1011ceacea2SWilliam Breathitt Gray 
1021ceacea2SWilliam Breathitt Gray 	if (offset < 16)
1031ceacea2SWilliam Breathitt Gray 		return -EINVAL;
1041ceacea2SWilliam Breathitt Gray 
1051ceacea2SWilliam Breathitt Gray 	if (offset < 24)
106cc442e4dSWilliam Breathitt Gray 		return !!(ioread8(&idio16gpio->reg->in0_7) & mask);
1071ceacea2SWilliam Breathitt Gray 
108cc442e4dSWilliam Breathitt Gray 	return !!(ioread8(&idio16gpio->reg->in8_15) & (mask>>8));
1091ceacea2SWilliam Breathitt Gray }
1101ceacea2SWilliam Breathitt Gray 
11115f59cffSWilliam Breathitt Gray static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
11215f59cffSWilliam Breathitt Gray 	unsigned long *mask, unsigned long *bits)
11315f59cffSWilliam Breathitt Gray {
11415f59cffSWilliam Breathitt Gray 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
11515f59cffSWilliam Breathitt Gray 
11615f59cffSWilliam Breathitt Gray 	*bits = 0;
11715f59cffSWilliam Breathitt Gray 	if (*mask & GENMASK(23, 16))
118cc442e4dSWilliam Breathitt Gray 		*bits |= (unsigned long)ioread8(&idio16gpio->reg->in0_7) << 16;
11915f59cffSWilliam Breathitt Gray 	if (*mask & GENMASK(31, 24))
120cc442e4dSWilliam Breathitt Gray 		*bits |= (unsigned long)ioread8(&idio16gpio->reg->in8_15) << 24;
12115f59cffSWilliam Breathitt Gray 
12215f59cffSWilliam Breathitt Gray 	return 0;
12315f59cffSWilliam Breathitt Gray }
12415f59cffSWilliam Breathitt Gray 
125cc0f53d2SNavin Sankar Velliangiri static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
126cc0f53d2SNavin Sankar Velliangiri 			     int value)
1271ceacea2SWilliam Breathitt Gray {
128d602ae90SLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
129cc0f53d2SNavin Sankar Velliangiri 	const unsigned int mask = BIT(offset);
1301ceacea2SWilliam Breathitt Gray 	unsigned long flags;
1311ceacea2SWilliam Breathitt Gray 
1321ceacea2SWilliam Breathitt Gray 	if (offset > 15)
1331ceacea2SWilliam Breathitt Gray 		return;
1341ceacea2SWilliam Breathitt Gray 
1353906e808SJulia Cartwright 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
1361ceacea2SWilliam Breathitt Gray 
1371ceacea2SWilliam Breathitt Gray 	if (value)
1386e0171b4SWilliam Breathitt Gray 		idio16gpio->out_state |= mask;
1391ceacea2SWilliam Breathitt Gray 	else
1406e0171b4SWilliam Breathitt Gray 		idio16gpio->out_state &= ~mask;
1411ceacea2SWilliam Breathitt Gray 
1421ceacea2SWilliam Breathitt Gray 	if (offset > 7)
143cc442e4dSWilliam Breathitt Gray 		iowrite8(idio16gpio->out_state >> 8, &idio16gpio->reg->out8_15);
1441ceacea2SWilliam Breathitt Gray 	else
145cc442e4dSWilliam Breathitt Gray 		iowrite8(idio16gpio->out_state, &idio16gpio->reg->out0_7);
1461ceacea2SWilliam Breathitt Gray 
1473906e808SJulia Cartwright 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
1481ceacea2SWilliam Breathitt Gray }
1491ceacea2SWilliam Breathitt Gray 
1509d7ae812SWilliam Breathitt Gray static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
1519d7ae812SWilliam Breathitt Gray 	unsigned long *mask, unsigned long *bits)
1529d7ae812SWilliam Breathitt Gray {
1539d7ae812SWilliam Breathitt Gray 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
1549d7ae812SWilliam Breathitt Gray 	unsigned long flags;
1559d7ae812SWilliam Breathitt Gray 
1563906e808SJulia Cartwright 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
1579d7ae812SWilliam Breathitt Gray 
1589d7ae812SWilliam Breathitt Gray 	idio16gpio->out_state &= ~*mask;
1599d7ae812SWilliam Breathitt Gray 	idio16gpio->out_state |= *mask & *bits;
1609d7ae812SWilliam Breathitt Gray 
1619d7ae812SWilliam Breathitt Gray 	if (*mask & 0xFF)
162cc442e4dSWilliam Breathitt Gray 		iowrite8(idio16gpio->out_state, &idio16gpio->reg->out0_7);
1639d7ae812SWilliam Breathitt Gray 	if ((*mask >> 8) & 0xFF)
164cc442e4dSWilliam Breathitt Gray 		iowrite8(idio16gpio->out_state >> 8, &idio16gpio->reg->out8_15);
1659d7ae812SWilliam Breathitt Gray 
1663906e808SJulia Cartwright 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
1679d7ae812SWilliam Breathitt Gray }
1689d7ae812SWilliam Breathitt Gray 
169a1184147SWilliam Breathitt Gray static void idio_16_irq_ack(struct irq_data *data)
170a1184147SWilliam Breathitt Gray {
171a1184147SWilliam Breathitt Gray }
172a1184147SWilliam Breathitt Gray 
173a1184147SWilliam Breathitt Gray static void idio_16_irq_mask(struct irq_data *data)
174a1184147SWilliam Breathitt Gray {
175a1184147SWilliam Breathitt Gray 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
176d602ae90SLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
177*410a5041SWilliam Breathitt Gray 	const unsigned long offset = irqd_to_hwirq(data);
178a1184147SWilliam Breathitt Gray 	unsigned long flags;
179a1184147SWilliam Breathitt Gray 
180*410a5041SWilliam Breathitt Gray 	idio16gpio->irq_mask &= ~BIT(offset);
181*410a5041SWilliam Breathitt Gray 	gpiochip_disable_irq(chip, offset);
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);
196*410a5041SWilliam Breathitt Gray 	const unsigned long offset = 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 
200*410a5041SWilliam Breathitt Gray 	gpiochip_enable_irq(chip, offset);
201*410a5041SWilliam Breathitt Gray 	idio16gpio->irq_mask |= BIT(offset);
202a1184147SWilliam Breathitt Gray 
203a1184147SWilliam Breathitt Gray 	if (!prev_irq_mask) {
2043906e808SJulia Cartwright 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
205a1184147SWilliam Breathitt Gray 
206cc442e4dSWilliam Breathitt Gray 		ioread8(&idio16gpio->reg->irq_ctl);
207a1184147SWilliam Breathitt Gray 
2083906e808SJulia Cartwright 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
209a1184147SWilliam Breathitt Gray 	}
210a1184147SWilliam Breathitt Gray }
211a1184147SWilliam Breathitt Gray 
212cc0f53d2SNavin Sankar Velliangiri static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
213a1184147SWilliam Breathitt Gray {
214a1184147SWilliam Breathitt Gray 	/* The only valid irq types are none and both-edges */
215a1184147SWilliam Breathitt Gray 	if (flow_type != IRQ_TYPE_NONE &&
216a1184147SWilliam Breathitt Gray 		(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
217a1184147SWilliam Breathitt Gray 		return -EINVAL;
218a1184147SWilliam Breathitt Gray 
219a1184147SWilliam Breathitt Gray 	return 0;
220a1184147SWilliam Breathitt Gray }
221a1184147SWilliam Breathitt Gray 
222*410a5041SWilliam Breathitt Gray static const struct irq_chip idio_16_irqchip = {
223a1184147SWilliam Breathitt Gray 	.name = "104-idio-16",
224a1184147SWilliam Breathitt Gray 	.irq_ack = idio_16_irq_ack,
225a1184147SWilliam Breathitt Gray 	.irq_mask = idio_16_irq_mask,
226a1184147SWilliam Breathitt Gray 	.irq_unmask = idio_16_irq_unmask,
227*410a5041SWilliam Breathitt Gray 	.irq_set_type = idio_16_irq_set_type,
228*410a5041SWilliam Breathitt Gray 	.flags = IRQCHIP_IMMUTABLE,
229*410a5041SWilliam Breathitt Gray 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
230a1184147SWilliam Breathitt Gray };
231a1184147SWilliam Breathitt Gray 
232a1184147SWilliam Breathitt Gray static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
233a1184147SWilliam Breathitt Gray {
234a1184147SWilliam Breathitt Gray 	struct idio_16_gpio *const idio16gpio = dev_id;
235a1184147SWilliam Breathitt Gray 	struct gpio_chip *const chip = &idio16gpio->chip;
236a1184147SWilliam Breathitt Gray 	int gpio;
237a1184147SWilliam Breathitt Gray 
238a1184147SWilliam Breathitt Gray 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
239dbd1c54fSMarc Zyngier 		generic_handle_domain_irq(chip->irq.domain, gpio);
240a1184147SWilliam Breathitt Gray 
2413906e808SJulia Cartwright 	raw_spin_lock(&idio16gpio->lock);
24212b61c9dSWilliam Breathitt Gray 
243cc442e4dSWilliam Breathitt Gray 	iowrite8(0, &idio16gpio->reg->in0_7);
24412b61c9dSWilliam Breathitt Gray 
2453906e808SJulia Cartwright 	raw_spin_unlock(&idio16gpio->lock);
24612b61c9dSWilliam Breathitt Gray 
247a1184147SWilliam Breathitt Gray 	return IRQ_HANDLED;
248a1184147SWilliam Breathitt Gray }
249a1184147SWilliam Breathitt Gray 
250e0af4b5eSWilliam Breathitt Gray #define IDIO_16_NGPIO 32
251e0af4b5eSWilliam Breathitt Gray static const char *idio_16_names[IDIO_16_NGPIO] = {
252e0af4b5eSWilliam Breathitt Gray 	"OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
253e0af4b5eSWilliam Breathitt Gray 	"OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
254e0af4b5eSWilliam Breathitt Gray 	"IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
255e0af4b5eSWilliam Breathitt Gray 	"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
256e0af4b5eSWilliam Breathitt Gray };
257e0af4b5eSWilliam Breathitt Gray 
25882e4613dSLinus Walleij static int idio_16_irq_init_hw(struct gpio_chip *gc)
25982e4613dSLinus Walleij {
26082e4613dSLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc);
26182e4613dSLinus Walleij 
26282e4613dSLinus Walleij 	/* Disable IRQ by default */
263cc442e4dSWilliam Breathitt Gray 	iowrite8(0, &idio16gpio->reg->irq_ctl);
264cc442e4dSWilliam Breathitt Gray 	iowrite8(0, &idio16gpio->reg->in0_7);
26582e4613dSLinus Walleij 
26682e4613dSLinus Walleij 	return 0;
26782e4613dSLinus Walleij }
26882e4613dSLinus Walleij 
26986ea8a95SWilliam Breathitt Gray static int idio_16_probe(struct device *dev, unsigned int id)
2701ceacea2SWilliam Breathitt Gray {
2711ceacea2SWilliam Breathitt Gray 	struct idio_16_gpio *idio16gpio;
2726e0171b4SWilliam Breathitt Gray 	const char *const name = dev_name(dev);
27382e4613dSLinus Walleij 	struct gpio_irq_chip *girq;
2741ceacea2SWilliam Breathitt Gray 	int err;
2751ceacea2SWilliam Breathitt Gray 
2761ceacea2SWilliam Breathitt Gray 	idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
2771ceacea2SWilliam Breathitt Gray 	if (!idio16gpio)
2781ceacea2SWilliam Breathitt Gray 		return -ENOMEM;
2791ceacea2SWilliam Breathitt Gray 
28086ea8a95SWilliam Breathitt Gray 	if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) {
281cb32389cSWilliam Breathitt Gray 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
28286ea8a95SWilliam Breathitt Gray 			base[id], base[id] + IDIO_16_EXTENT);
283cb32389cSWilliam Breathitt Gray 		return -EBUSY;
2841ceacea2SWilliam Breathitt Gray 	}
2851ceacea2SWilliam Breathitt Gray 
286cc442e4dSWilliam Breathitt Gray 	idio16gpio->reg = devm_ioport_map(dev, base[id], IDIO_16_EXTENT);
287cc442e4dSWilliam Breathitt Gray 	if (!idio16gpio->reg)
288e0a574efSWilliam Breathitt Gray 		return -ENOMEM;
289e0a574efSWilliam Breathitt Gray 
2906e0171b4SWilliam Breathitt Gray 	idio16gpio->chip.label = name;
29158383c78SLinus Walleij 	idio16gpio->chip.parent = dev;
2921ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.owner = THIS_MODULE;
2931ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.base = -1;
294e0af4b5eSWilliam Breathitt Gray 	idio16gpio->chip.ngpio = IDIO_16_NGPIO;
295e0af4b5eSWilliam Breathitt Gray 	idio16gpio->chip.names = idio_16_names;
2961ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
2971ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
2981ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
2991ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.get = idio_16_gpio_get;
30015f59cffSWilliam Breathitt Gray 	idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
3011ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.set = idio_16_gpio_set;
3029d7ae812SWilliam Breathitt Gray 	idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
3031ceacea2SWilliam Breathitt Gray 	idio16gpio->out_state = 0xFFFF;
3041ceacea2SWilliam Breathitt Gray 
30582e4613dSLinus Walleij 	girq = &idio16gpio->chip.irq;
306*410a5041SWilliam Breathitt Gray 	gpio_irq_chip_set_chip(girq, &idio_16_irqchip);
30782e4613dSLinus Walleij 	/* This will let us handle the parent IRQ in the driver */
30882e4613dSLinus Walleij 	girq->parent_handler = NULL;
30982e4613dSLinus Walleij 	girq->num_parents = 0;
31082e4613dSLinus Walleij 	girq->parents = NULL;
31182e4613dSLinus Walleij 	girq->default_type = IRQ_TYPE_NONE;
31282e4613dSLinus Walleij 	girq->handler = handle_edge_irq;
31382e4613dSLinus Walleij 	girq->init_hw = idio_16_irq_init_hw;
31482e4613dSLinus Walleij 
3153906e808SJulia Cartwright 	raw_spin_lock_init(&idio16gpio->lock);
3161ceacea2SWilliam Breathitt Gray 
317837143d3SWilliam Breathitt Gray 	err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
3181ceacea2SWilliam Breathitt Gray 	if (err) {
3191ceacea2SWilliam Breathitt Gray 		dev_err(dev, "GPIO registering failed (%d)\n", err);
320cb32389cSWilliam Breathitt Gray 		return err;
3211ceacea2SWilliam Breathitt Gray 	}
3221ceacea2SWilliam Breathitt Gray 
323837143d3SWilliam Breathitt Gray 	err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name,
324837143d3SWilliam Breathitt Gray 		idio16gpio);
325837143d3SWilliam Breathitt Gray 	if (err) {
326837143d3SWilliam Breathitt Gray 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
327837143d3SWilliam Breathitt Gray 		return err;
328837143d3SWilliam Breathitt Gray 	}
3291ceacea2SWilliam Breathitt Gray 
3301ceacea2SWilliam Breathitt Gray 	return 0;
3311ceacea2SWilliam Breathitt Gray }
3321ceacea2SWilliam Breathitt Gray 
33386ea8a95SWilliam Breathitt Gray static struct isa_driver idio_16_driver = {
33486ea8a95SWilliam Breathitt Gray 	.probe = idio_16_probe,
3351ceacea2SWilliam Breathitt Gray 	.driver = {
3361ceacea2SWilliam Breathitt Gray 		.name = "104-idio-16"
3371ceacea2SWilliam Breathitt Gray 	},
3381ceacea2SWilliam Breathitt Gray };
3391ceacea2SWilliam Breathitt Gray 
34086ea8a95SWilliam Breathitt Gray module_isa_driver(idio_16_driver, num_idio_16);
3411ceacea2SWilliam Breathitt Gray 
3421ceacea2SWilliam Breathitt Gray MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
3431ceacea2SWilliam Breathitt Gray MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
34422aeddb5SWilliam Breathitt Gray MODULE_LICENSE("GPL v2");
345