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  */
9a1184147SWilliam Breathitt Gray #include <linux/bitops.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>
221ceacea2SWilliam Breathitt Gray 
2386ea8a95SWilliam Breathitt Gray #define IDIO_16_EXTENT 8
2486ea8a95SWilliam Breathitt Gray #define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT)
2586ea8a95SWilliam Breathitt Gray 
2686ea8a95SWilliam Breathitt Gray static unsigned int base[MAX_NUM_IDIO_16];
2786ea8a95SWilliam Breathitt Gray static unsigned int num_idio_16;
28d759f906SDavid Howells module_param_hw_array(base, uint, ioport, &num_idio_16, 0);
2986ea8a95SWilliam Breathitt Gray MODULE_PARM_DESC(base, "ACCES 104-IDIO-16 base addresses");
3086ea8a95SWilliam Breathitt Gray 
3186ea8a95SWilliam Breathitt Gray static unsigned int irq[MAX_NUM_IDIO_16];
32d759f906SDavid Howells module_param_hw_array(irq, uint, irq, NULL, 0);
3386ea8a95SWilliam Breathitt Gray MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
341ceacea2SWilliam Breathitt Gray 
351ceacea2SWilliam Breathitt Gray /**
361ceacea2SWilliam Breathitt Gray  * struct idio_16_gpio - GPIO device private data structure
371ceacea2SWilliam Breathitt Gray  * @chip:	instance of the gpio_chip
38a1184147SWilliam Breathitt Gray  * @lock:	synchronization lock to prevent I/O race conditions
39a1184147SWilliam Breathitt Gray  * @irq_mask:	I/O bits affected by interrupts
401ceacea2SWilliam Breathitt Gray  * @base:	base port address of the GPIO device
411ceacea2SWilliam Breathitt Gray  * @out_state:	output bits state
421ceacea2SWilliam Breathitt Gray  */
431ceacea2SWilliam Breathitt Gray struct idio_16_gpio {
441ceacea2SWilliam Breathitt Gray 	struct gpio_chip chip;
453906e808SJulia Cartwright 	raw_spinlock_t lock;
46a1184147SWilliam Breathitt Gray 	unsigned long irq_mask;
47cc0f53d2SNavin Sankar Velliangiri 	unsigned int base;
48cc0f53d2SNavin Sankar Velliangiri 	unsigned int out_state;
491ceacea2SWilliam Breathitt Gray };
501ceacea2SWilliam Breathitt Gray 
51cc0f53d2SNavin Sankar Velliangiri static int idio_16_gpio_get_direction(struct gpio_chip *chip,
52cc0f53d2SNavin Sankar Velliangiri 				      unsigned int offset)
531ceacea2SWilliam Breathitt Gray {
541ceacea2SWilliam Breathitt Gray 	if (offset > 15)
55e42615ecSMatti Vaittinen 		return GPIO_LINE_DIRECTION_IN;
561ceacea2SWilliam Breathitt Gray 
57e42615ecSMatti Vaittinen 	return GPIO_LINE_DIRECTION_OUT;
581ceacea2SWilliam Breathitt Gray }
591ceacea2SWilliam Breathitt Gray 
60cc0f53d2SNavin Sankar Velliangiri static int idio_16_gpio_direction_input(struct gpio_chip *chip,
61cc0f53d2SNavin Sankar Velliangiri 					unsigned int offset)
621ceacea2SWilliam Breathitt Gray {
631ceacea2SWilliam Breathitt Gray 	return 0;
641ceacea2SWilliam Breathitt Gray }
651ceacea2SWilliam Breathitt Gray 
661ceacea2SWilliam Breathitt Gray static int idio_16_gpio_direction_output(struct gpio_chip *chip,
67cc0f53d2SNavin Sankar Velliangiri 	unsigned int offset, int value)
681ceacea2SWilliam Breathitt Gray {
691ceacea2SWilliam Breathitt Gray 	chip->set(chip, offset, value);
701ceacea2SWilliam Breathitt Gray 	return 0;
711ceacea2SWilliam Breathitt Gray }
721ceacea2SWilliam Breathitt Gray 
73cc0f53d2SNavin Sankar Velliangiri static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
741ceacea2SWilliam Breathitt Gray {
75d602ae90SLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
76cc0f53d2SNavin Sankar Velliangiri 	const unsigned int mask = BIT(offset-16);
771ceacea2SWilliam Breathitt Gray 
781ceacea2SWilliam Breathitt Gray 	if (offset < 16)
791ceacea2SWilliam Breathitt Gray 		return -EINVAL;
801ceacea2SWilliam Breathitt Gray 
811ceacea2SWilliam Breathitt Gray 	if (offset < 24)
826e0171b4SWilliam Breathitt Gray 		return !!(inb(idio16gpio->base + 1) & mask);
831ceacea2SWilliam Breathitt Gray 
846e0171b4SWilliam Breathitt Gray 	return !!(inb(idio16gpio->base + 5) & (mask>>8));
851ceacea2SWilliam Breathitt Gray }
861ceacea2SWilliam Breathitt Gray 
8715f59cffSWilliam Breathitt Gray static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
8815f59cffSWilliam Breathitt Gray 	unsigned long *mask, unsigned long *bits)
8915f59cffSWilliam Breathitt Gray {
9015f59cffSWilliam Breathitt Gray 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
9115f59cffSWilliam Breathitt Gray 
9215f59cffSWilliam Breathitt Gray 	*bits = 0;
9315f59cffSWilliam Breathitt Gray 	if (*mask & GENMASK(23, 16))
9415f59cffSWilliam Breathitt Gray 		*bits |= (unsigned long)inb(idio16gpio->base + 1) << 16;
9515f59cffSWilliam Breathitt Gray 	if (*mask & GENMASK(31, 24))
9615f59cffSWilliam Breathitt Gray 		*bits |= (unsigned long)inb(idio16gpio->base + 5) << 24;
9715f59cffSWilliam Breathitt Gray 
9815f59cffSWilliam Breathitt Gray 	return 0;
9915f59cffSWilliam Breathitt Gray }
10015f59cffSWilliam Breathitt Gray 
101cc0f53d2SNavin Sankar Velliangiri static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
102cc0f53d2SNavin Sankar Velliangiri 			     int value)
1031ceacea2SWilliam Breathitt Gray {
104d602ae90SLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
105cc0f53d2SNavin Sankar Velliangiri 	const unsigned int mask = BIT(offset);
1061ceacea2SWilliam Breathitt Gray 	unsigned long flags;
1071ceacea2SWilliam Breathitt Gray 
1081ceacea2SWilliam Breathitt Gray 	if (offset > 15)
1091ceacea2SWilliam Breathitt Gray 		return;
1101ceacea2SWilliam Breathitt Gray 
1113906e808SJulia Cartwright 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
1121ceacea2SWilliam Breathitt Gray 
1131ceacea2SWilliam Breathitt Gray 	if (value)
1146e0171b4SWilliam Breathitt Gray 		idio16gpio->out_state |= mask;
1151ceacea2SWilliam Breathitt Gray 	else
1166e0171b4SWilliam Breathitt Gray 		idio16gpio->out_state &= ~mask;
1171ceacea2SWilliam Breathitt Gray 
1181ceacea2SWilliam Breathitt Gray 	if (offset > 7)
1191ceacea2SWilliam Breathitt Gray 		outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
1201ceacea2SWilliam Breathitt Gray 	else
1211ceacea2SWilliam Breathitt Gray 		outb(idio16gpio->out_state, idio16gpio->base);
1221ceacea2SWilliam Breathitt Gray 
1233906e808SJulia Cartwright 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
1241ceacea2SWilliam Breathitt Gray }
1251ceacea2SWilliam Breathitt Gray 
1269d7ae812SWilliam Breathitt Gray static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
1279d7ae812SWilliam Breathitt Gray 	unsigned long *mask, unsigned long *bits)
1289d7ae812SWilliam Breathitt Gray {
1299d7ae812SWilliam Breathitt Gray 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
1309d7ae812SWilliam Breathitt Gray 	unsigned long flags;
1319d7ae812SWilliam Breathitt Gray 
1323906e808SJulia Cartwright 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
1339d7ae812SWilliam Breathitt Gray 
1349d7ae812SWilliam Breathitt Gray 	idio16gpio->out_state &= ~*mask;
1359d7ae812SWilliam Breathitt Gray 	idio16gpio->out_state |= *mask & *bits;
1369d7ae812SWilliam Breathitt Gray 
1379d7ae812SWilliam Breathitt Gray 	if (*mask & 0xFF)
1389d7ae812SWilliam Breathitt Gray 		outb(idio16gpio->out_state, idio16gpio->base);
1399d7ae812SWilliam Breathitt Gray 	if ((*mask >> 8) & 0xFF)
1409d7ae812SWilliam Breathitt Gray 		outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
1419d7ae812SWilliam Breathitt Gray 
1423906e808SJulia Cartwright 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
1439d7ae812SWilliam Breathitt Gray }
1449d7ae812SWilliam Breathitt Gray 
145a1184147SWilliam Breathitt Gray static void idio_16_irq_ack(struct irq_data *data)
146a1184147SWilliam Breathitt Gray {
147a1184147SWilliam Breathitt Gray }
148a1184147SWilliam Breathitt Gray 
149a1184147SWilliam Breathitt Gray static void idio_16_irq_mask(struct irq_data *data)
150a1184147SWilliam Breathitt Gray {
151a1184147SWilliam Breathitt Gray 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
152d602ae90SLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
153a1184147SWilliam Breathitt Gray 	const unsigned long mask = BIT(irqd_to_hwirq(data));
154a1184147SWilliam Breathitt Gray 	unsigned long flags;
155a1184147SWilliam Breathitt Gray 
156a1184147SWilliam Breathitt Gray 	idio16gpio->irq_mask &= ~mask;
157a1184147SWilliam Breathitt Gray 
158a1184147SWilliam Breathitt Gray 	if (!idio16gpio->irq_mask) {
1593906e808SJulia Cartwright 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
160a1184147SWilliam Breathitt Gray 
161a1184147SWilliam Breathitt Gray 		outb(0, idio16gpio->base + 2);
162a1184147SWilliam Breathitt Gray 
1633906e808SJulia Cartwright 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
164a1184147SWilliam Breathitt Gray 	}
165a1184147SWilliam Breathitt Gray }
166a1184147SWilliam Breathitt Gray 
167a1184147SWilliam Breathitt Gray static void idio_16_irq_unmask(struct irq_data *data)
168a1184147SWilliam Breathitt Gray {
169a1184147SWilliam Breathitt Gray 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
170d602ae90SLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
171a1184147SWilliam Breathitt Gray 	const unsigned long mask = BIT(irqd_to_hwirq(data));
172a1184147SWilliam Breathitt Gray 	const unsigned long prev_irq_mask = idio16gpio->irq_mask;
173a1184147SWilliam Breathitt Gray 	unsigned long flags;
174a1184147SWilliam Breathitt Gray 
175a1184147SWilliam Breathitt Gray 	idio16gpio->irq_mask |= mask;
176a1184147SWilliam Breathitt Gray 
177a1184147SWilliam Breathitt Gray 	if (!prev_irq_mask) {
1783906e808SJulia Cartwright 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
179a1184147SWilliam Breathitt Gray 
180a1184147SWilliam Breathitt Gray 		inb(idio16gpio->base + 2);
181a1184147SWilliam Breathitt Gray 
1823906e808SJulia Cartwright 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
183a1184147SWilliam Breathitt Gray 	}
184a1184147SWilliam Breathitt Gray }
185a1184147SWilliam Breathitt Gray 
186cc0f53d2SNavin Sankar Velliangiri static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
187a1184147SWilliam Breathitt Gray {
188a1184147SWilliam Breathitt Gray 	/* The only valid irq types are none and both-edges */
189a1184147SWilliam Breathitt Gray 	if (flow_type != IRQ_TYPE_NONE &&
190a1184147SWilliam Breathitt Gray 		(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
191a1184147SWilliam Breathitt Gray 		return -EINVAL;
192a1184147SWilliam Breathitt Gray 
193a1184147SWilliam Breathitt Gray 	return 0;
194a1184147SWilliam Breathitt Gray }
195a1184147SWilliam Breathitt Gray 
196a1184147SWilliam Breathitt Gray static struct irq_chip idio_16_irqchip = {
197a1184147SWilliam Breathitt Gray 	.name = "104-idio-16",
198a1184147SWilliam Breathitt Gray 	.irq_ack = idio_16_irq_ack,
199a1184147SWilliam Breathitt Gray 	.irq_mask = idio_16_irq_mask,
200a1184147SWilliam Breathitt Gray 	.irq_unmask = idio_16_irq_unmask,
201a1184147SWilliam Breathitt Gray 	.irq_set_type = idio_16_irq_set_type
202a1184147SWilliam Breathitt Gray };
203a1184147SWilliam Breathitt Gray 
204a1184147SWilliam Breathitt Gray static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
205a1184147SWilliam Breathitt Gray {
206a1184147SWilliam Breathitt Gray 	struct idio_16_gpio *const idio16gpio = dev_id;
207a1184147SWilliam Breathitt Gray 	struct gpio_chip *const chip = &idio16gpio->chip;
208a1184147SWilliam Breathitt Gray 	int gpio;
209a1184147SWilliam Breathitt Gray 
210a1184147SWilliam Breathitt Gray 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
211*dbd1c54fSMarc Zyngier 		generic_handle_domain_irq(chip->irq.domain, gpio);
212a1184147SWilliam Breathitt Gray 
2133906e808SJulia Cartwright 	raw_spin_lock(&idio16gpio->lock);
21412b61c9dSWilliam Breathitt Gray 
21512b61c9dSWilliam Breathitt Gray 	outb(0, idio16gpio->base + 1);
21612b61c9dSWilliam Breathitt Gray 
2173906e808SJulia Cartwright 	raw_spin_unlock(&idio16gpio->lock);
21812b61c9dSWilliam Breathitt Gray 
219a1184147SWilliam Breathitt Gray 	return IRQ_HANDLED;
220a1184147SWilliam Breathitt Gray }
221a1184147SWilliam Breathitt Gray 
222e0af4b5eSWilliam Breathitt Gray #define IDIO_16_NGPIO 32
223e0af4b5eSWilliam Breathitt Gray static const char *idio_16_names[IDIO_16_NGPIO] = {
224e0af4b5eSWilliam Breathitt Gray 	"OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
225e0af4b5eSWilliam Breathitt Gray 	"OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
226e0af4b5eSWilliam Breathitt Gray 	"IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
227e0af4b5eSWilliam Breathitt Gray 	"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
228e0af4b5eSWilliam Breathitt Gray };
229e0af4b5eSWilliam Breathitt Gray 
23082e4613dSLinus Walleij static int idio_16_irq_init_hw(struct gpio_chip *gc)
23182e4613dSLinus Walleij {
23282e4613dSLinus Walleij 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc);
23382e4613dSLinus Walleij 
23482e4613dSLinus Walleij 	/* Disable IRQ by default */
23582e4613dSLinus Walleij 	outb(0, idio16gpio->base + 2);
23682e4613dSLinus Walleij 	outb(0, idio16gpio->base + 1);
23782e4613dSLinus Walleij 
23882e4613dSLinus Walleij 	return 0;
23982e4613dSLinus Walleij }
24082e4613dSLinus Walleij 
24186ea8a95SWilliam Breathitt Gray static int idio_16_probe(struct device *dev, unsigned int id)
2421ceacea2SWilliam Breathitt Gray {
2431ceacea2SWilliam Breathitt Gray 	struct idio_16_gpio *idio16gpio;
2446e0171b4SWilliam Breathitt Gray 	const char *const name = dev_name(dev);
24582e4613dSLinus Walleij 	struct gpio_irq_chip *girq;
2461ceacea2SWilliam Breathitt Gray 	int err;
2471ceacea2SWilliam Breathitt Gray 
2481ceacea2SWilliam Breathitt Gray 	idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
2491ceacea2SWilliam Breathitt Gray 	if (!idio16gpio)
2501ceacea2SWilliam Breathitt Gray 		return -ENOMEM;
2511ceacea2SWilliam Breathitt Gray 
25286ea8a95SWilliam Breathitt Gray 	if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) {
253cb32389cSWilliam Breathitt Gray 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
25486ea8a95SWilliam Breathitt Gray 			base[id], base[id] + IDIO_16_EXTENT);
255cb32389cSWilliam Breathitt Gray 		return -EBUSY;
2561ceacea2SWilliam Breathitt Gray 	}
2571ceacea2SWilliam Breathitt Gray 
2586e0171b4SWilliam Breathitt Gray 	idio16gpio->chip.label = name;
25958383c78SLinus Walleij 	idio16gpio->chip.parent = dev;
2601ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.owner = THIS_MODULE;
2611ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.base = -1;
262e0af4b5eSWilliam Breathitt Gray 	idio16gpio->chip.ngpio = IDIO_16_NGPIO;
263e0af4b5eSWilliam Breathitt Gray 	idio16gpio->chip.names = idio_16_names;
2641ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
2651ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
2661ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
2671ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.get = idio_16_gpio_get;
26815f59cffSWilliam Breathitt Gray 	idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
2691ceacea2SWilliam Breathitt Gray 	idio16gpio->chip.set = idio_16_gpio_set;
2709d7ae812SWilliam Breathitt Gray 	idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
27186ea8a95SWilliam Breathitt Gray 	idio16gpio->base = base[id];
2721ceacea2SWilliam Breathitt Gray 	idio16gpio->out_state = 0xFFFF;
2731ceacea2SWilliam Breathitt Gray 
27482e4613dSLinus Walleij 	girq = &idio16gpio->chip.irq;
27582e4613dSLinus Walleij 	girq->chip = &idio_16_irqchip;
27682e4613dSLinus Walleij 	/* This will let us handle the parent IRQ in the driver */
27782e4613dSLinus Walleij 	girq->parent_handler = NULL;
27882e4613dSLinus Walleij 	girq->num_parents = 0;
27982e4613dSLinus Walleij 	girq->parents = NULL;
28082e4613dSLinus Walleij 	girq->default_type = IRQ_TYPE_NONE;
28182e4613dSLinus Walleij 	girq->handler = handle_edge_irq;
28282e4613dSLinus Walleij 	girq->init_hw = idio_16_irq_init_hw;
28382e4613dSLinus Walleij 
2843906e808SJulia Cartwright 	raw_spin_lock_init(&idio16gpio->lock);
2851ceacea2SWilliam Breathitt Gray 
286837143d3SWilliam Breathitt Gray 	err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
2871ceacea2SWilliam Breathitt Gray 	if (err) {
2881ceacea2SWilliam Breathitt Gray 		dev_err(dev, "GPIO registering failed (%d)\n", err);
289cb32389cSWilliam Breathitt Gray 		return err;
2901ceacea2SWilliam Breathitt Gray 	}
2911ceacea2SWilliam Breathitt Gray 
292837143d3SWilliam Breathitt Gray 	err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name,
293837143d3SWilliam Breathitt Gray 		idio16gpio);
294837143d3SWilliam Breathitt Gray 	if (err) {
295837143d3SWilliam Breathitt Gray 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
296837143d3SWilliam Breathitt Gray 		return err;
297837143d3SWilliam Breathitt Gray 	}
2981ceacea2SWilliam Breathitt Gray 
2991ceacea2SWilliam Breathitt Gray 	return 0;
3001ceacea2SWilliam Breathitt Gray }
3011ceacea2SWilliam Breathitt Gray 
30286ea8a95SWilliam Breathitt Gray static struct isa_driver idio_16_driver = {
30386ea8a95SWilliam Breathitt Gray 	.probe = idio_16_probe,
3041ceacea2SWilliam Breathitt Gray 	.driver = {
3051ceacea2SWilliam Breathitt Gray 		.name = "104-idio-16"
3061ceacea2SWilliam Breathitt Gray 	},
3071ceacea2SWilliam Breathitt Gray };
3081ceacea2SWilliam Breathitt Gray 
30986ea8a95SWilliam Breathitt Gray module_isa_driver(idio_16_driver, num_idio_16);
3101ceacea2SWilliam Breathitt Gray 
3111ceacea2SWilliam Breathitt Gray MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
3121ceacea2SWilliam Breathitt Gray MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
31322aeddb5SWilliam Breathitt Gray MODULE_LICENSE("GPL v2");
314