GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / gpio / gpio-pcie-idio-24.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * GPIO driver for the ACCES PCIe-IDIO-24 family
4  * Copyright (C) 2018 William Breathitt Gray
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License, version 2, as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * This driver supports the following ACCES devices: PCIe-IDIO-24,
16  * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12.
17  */
18 #include <linux/bitmap.h>
19 #include <linux/bitops.h>
20 #include <linux/device.h>
21 #include <linux/errno.h>
22 #include <linux/gpio/driver.h>
23 #include <linux/interrupt.h>
24 #include <linux/irqdesc.h>
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/pci.h>
28 #include <linux/spinlock.h>
29 #include <linux/types.h>
30
31 /*
32  * PLX PEX8311 PCI LCS_INTCSR Interrupt Control/Status
33  *
34  * Bit: Description
35  *   0: Enable Interrupt Sources (Bit 0)
36  *   1: Enable Interrupt Sources (Bit 1)
37  *   2: Generate Internal PCI Bus Internal SERR# Interrupt
38  *   3: Mailbox Interrupt Enable
39  *   4: Power Management Interrupt Enable
40  *   5: Power Management Interrupt
41  *   6: Slave Read Local Data Parity Check Error Enable
42  *   7: Slave Read Local Data Parity Check Error Status
43  *   8: Internal PCI Wire Interrupt Enable
44  *   9: PCI Express Doorbell Interrupt Enable
45  *  10: PCI Abort Interrupt Enable
46  *  11: Local Interrupt Input Enable
47  *  12: Retry Abort Enable
48  *  13: PCI Express Doorbell Interrupt Active
49  *  14: PCI Abort Interrupt Active
50  *  15: Local Interrupt Input Active
51  *  16: Local Interrupt Output Enable
52  *  17: Local Doorbell Interrupt Enable
53  *  18: DMA Channel 0 Interrupt Enable
54  *  19: DMA Channel 1 Interrupt Enable
55  *  20: Local Doorbell Interrupt Active
56  *  21: DMA Channel 0 Interrupt Active
57  *  22: DMA Channel 1 Interrupt Active
58  *  23: Built-In Self-Test (BIST) Interrupt Active
59  *  24: Direct Master was the Bus Master during a Master or Target Abort
60  *  25: DMA Channel 0 was the Bus Master during a Master or Target Abort
61  *  26: DMA Channel 1 was the Bus Master during a Master or Target Abort
62  *  27: Target Abort after internal 256 consecutive Master Retrys
63  *  28: PCI Bus wrote data to LCS_MBOX0
64  *  29: PCI Bus wrote data to LCS_MBOX1
65  *  30: PCI Bus wrote data to LCS_MBOX2
66  *  31: PCI Bus wrote data to LCS_MBOX3
67  */
68 #define PLX_PEX8311_PCI_LCS_INTCSR  0x68
69 #define INTCSR_INTERNAL_PCI_WIRE    BIT(8)
70 #define INTCSR_LOCAL_INPUT          BIT(11)
71
72 /**
73  * struct idio_24_gpio_reg - GPIO device registers structure
74  * @out0_7:     Read: FET Outputs 0-7
75  *              Write: FET Outputs 0-7
76  * @out8_15:    Read: FET Outputs 8-15
77  *              Write: FET Outputs 8-15
78  * @out16_23:   Read: FET Outputs 16-23
79  *              Write: FET Outputs 16-23
80  * @ttl_out0_7: Read: TTL/CMOS Outputs 0-7
81  *              Write: TTL/CMOS Outputs 0-7
82  * @in0_7:      Read: Isolated Inputs 0-7
83  *              Write: Reserved
84  * @in8_15:     Read: Isolated Inputs 8-15
85  *              Write: Reserved
86  * @in16_23:    Read: Isolated Inputs 16-23
87  *              Write: Reserved
88  * @ttl_in0_7:  Read: TTL/CMOS Inputs 0-7
89  *              Write: Reserved
90  * @cos0_7:     Read: COS Status Inputs 0-7
91  *              Write: COS Clear Inputs 0-7
92  * @cos8_15:    Read: COS Status Inputs 8-15
93  *              Write: COS Clear Inputs 8-15
94  * @cos16_23:   Read: COS Status Inputs 16-23
95  *              Write: COS Clear Inputs 16-23
96  * @cos_ttl0_7: Read: COS Status TTL/CMOS 0-7
97  *              Write: COS Clear TTL/CMOS 0-7
98  * @ctl:        Read: Control Register
99  *              Write: Control Register
100  * @reserved:   Read: Reserved
101  *              Write: Reserved
102  * @cos_enable: Read: COS Enable
103  *              Write: COS Enable
104  * @soft_reset: Read: IRQ Output Pin Status
105  *              Write: Software Board Reset
106  */
107 struct idio_24_gpio_reg {
108         u8 out0_7;
109         u8 out8_15;
110         u8 out16_23;
111         u8 ttl_out0_7;
112         u8 in0_7;
113         u8 in8_15;
114         u8 in16_23;
115         u8 ttl_in0_7;
116         u8 cos0_7;
117         u8 cos8_15;
118         u8 cos16_23;
119         u8 cos_ttl0_7;
120         u8 ctl;
121         u8 reserved;
122         u8 cos_enable;
123         u8 soft_reset;
124 };
125
126 /**
127  * struct idio_24_gpio - GPIO device private data structure
128  * @chip:       instance of the gpio_chip
129  * @lock:       synchronization lock to prevent I/O race conditions
130  * @reg:        I/O address offset for the GPIO device registers
131  * @irq_mask:   I/O bits affected by interrupts
132  */
133 struct idio_24_gpio {
134         struct gpio_chip chip;
135         raw_spinlock_t lock;
136         __u8 __iomem *plx;
137         struct idio_24_gpio_reg __iomem *reg;
138         unsigned long irq_mask;
139 };
140
141 static int idio_24_gpio_get_direction(struct gpio_chip *chip,
142         unsigned int offset)
143 {
144         struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
145         const unsigned long out_mode_mask = BIT(1);
146
147         /* FET Outputs */
148         if (offset < 24)
149                 return GPIO_LINE_DIRECTION_OUT;
150
151         /* Isolated Inputs */
152         if (offset < 48)
153                 return GPIO_LINE_DIRECTION_IN;
154
155         /* TTL/CMOS I/O */
156         /* OUT MODE = 1 when TTL/CMOS Output Mode is set */
157         if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
158                 return GPIO_LINE_DIRECTION_OUT;
159
160         return GPIO_LINE_DIRECTION_IN;
161 }
162
163 static int idio_24_gpio_direction_input(struct gpio_chip *chip,
164         unsigned int offset)
165 {
166         struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
167         unsigned long flags;
168         unsigned int ctl_state;
169         const unsigned long out_mode_mask = BIT(1);
170
171         /* TTL/CMOS I/O */
172         if (offset > 47) {
173                 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
174
175                 /* Clear TTL/CMOS Output Mode */
176                 ctl_state = ioread8(&idio24gpio->reg->ctl) & ~out_mode_mask;
177                 iowrite8(ctl_state, &idio24gpio->reg->ctl);
178
179                 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
180         }
181
182         return 0;
183 }
184
185 static int idio_24_gpio_direction_output(struct gpio_chip *chip,
186         unsigned int offset, int value)
187 {
188         struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
189         unsigned long flags;
190         unsigned int ctl_state;
191         const unsigned long out_mode_mask = BIT(1);
192
193         /* TTL/CMOS I/O */
194         if (offset > 47) {
195                 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
196
197                 /* Set TTL/CMOS Output Mode */
198                 ctl_state = ioread8(&idio24gpio->reg->ctl) | out_mode_mask;
199                 iowrite8(ctl_state, &idio24gpio->reg->ctl);
200
201                 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
202         }
203
204         chip->set(chip, offset, value);
205         return 0;
206 }
207
208 static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset)
209 {
210         struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
211         const unsigned long offset_mask = BIT(offset % 8);
212         const unsigned long out_mode_mask = BIT(1);
213
214         /* FET Outputs */
215         if (offset < 8)
216                 return !!(ioread8(&idio24gpio->reg->out0_7) & offset_mask);
217
218         if (offset < 16)
219                 return !!(ioread8(&idio24gpio->reg->out8_15) & offset_mask);
220
221         if (offset < 24)
222                 return !!(ioread8(&idio24gpio->reg->out16_23) & offset_mask);
223
224         /* Isolated Inputs */
225         if (offset < 32)
226                 return !!(ioread8(&idio24gpio->reg->in0_7) & offset_mask);
227
228         if (offset < 40)
229                 return !!(ioread8(&idio24gpio->reg->in8_15) & offset_mask);
230
231         if (offset < 48)
232                 return !!(ioread8(&idio24gpio->reg->in16_23) & offset_mask);
233
234         /* TTL/CMOS Outputs */
235         if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
236                 return !!(ioread8(&idio24gpio->reg->ttl_out0_7) & offset_mask);
237
238         /* TTL/CMOS Inputs */
239         return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask);
240 }
241
242 static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
243         unsigned long *mask, unsigned long *bits)
244 {
245         struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
246         unsigned long offset;
247         unsigned long gpio_mask;
248         void __iomem *ports[] = {
249                 &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
250                 &idio24gpio->reg->out16_23, &idio24gpio->reg->in0_7,
251                 &idio24gpio->reg->in8_15, &idio24gpio->reg->in16_23,
252         };
253         size_t index;
254         unsigned long port_state;
255         const unsigned long out_mode_mask = BIT(1);
256
257         /* clear bits array to a clean slate */
258         bitmap_zero(bits, chip->ngpio);
259
260         for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
261                 index = offset / 8;
262
263                 /* read bits from current gpio port (port 6 is TTL GPIO) */
264                 if (index < 6)
265                         port_state = ioread8(ports[index]);
266                 else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
267                         port_state = ioread8(&idio24gpio->reg->ttl_out0_7);
268                 else
269                         port_state = ioread8(&idio24gpio->reg->ttl_in0_7);
270
271                 port_state &= gpio_mask;
272
273                 bitmap_set_value8(bits, port_state, offset);
274         }
275
276         return 0;
277 }
278
279 static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset,
280         int value)
281 {
282         struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
283         const unsigned long out_mode_mask = BIT(1);
284         void __iomem *base;
285         const unsigned int mask = BIT(offset % 8);
286         unsigned long flags;
287         unsigned int out_state;
288
289         /* Isolated Inputs */
290         if (offset > 23 && offset < 48)
291                 return;
292
293         /* TTL/CMOS Inputs */
294         if (offset > 47 && !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask))
295                 return;
296
297         /* TTL/CMOS Outputs */
298         if (offset > 47)
299                 base = &idio24gpio->reg->ttl_out0_7;
300         /* FET Outputs */
301         else if (offset > 15)
302                 base = &idio24gpio->reg->out16_23;
303         else if (offset > 7)
304                 base = &idio24gpio->reg->out8_15;
305         else
306                 base = &idio24gpio->reg->out0_7;
307
308         raw_spin_lock_irqsave(&idio24gpio->lock, flags);
309
310         if (value)
311                 out_state = ioread8(base) | mask;
312         else
313                 out_state = ioread8(base) & ~mask;
314
315         iowrite8(out_state, base);
316
317         raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
318 }
319
320 static void idio_24_gpio_set_multiple(struct gpio_chip *chip,
321         unsigned long *mask, unsigned long *bits)
322 {
323         struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
324         unsigned long offset;
325         unsigned long gpio_mask;
326         void __iomem *ports[] = {
327                 &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
328                 &idio24gpio->reg->out16_23
329         };
330         size_t index;
331         unsigned long bitmask;
332         unsigned long flags;
333         unsigned long out_state;
334         const unsigned long out_mode_mask = BIT(1);
335
336         for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
337                 index = offset / 8;
338
339                 bitmask = bitmap_get_value8(bits, offset) & gpio_mask;
340
341                 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
342
343                 /* read bits from current gpio port (port 6 is TTL GPIO) */
344                 if (index < 6) {
345                         out_state = ioread8(ports[index]);
346                 } else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) {
347                         out_state = ioread8(&idio24gpio->reg->ttl_out0_7);
348                 } else {
349                         /* skip TTL GPIO if set for input */
350                         raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
351                         continue;
352                 }
353
354                 /* set requested bit states */
355                 out_state &= ~gpio_mask;
356                 out_state |= bitmask;
357
358                 /* write bits for current gpio port (port 6 is TTL GPIO) */
359                 if (index < 6)
360                         iowrite8(out_state, ports[index]);
361                 else
362                         iowrite8(out_state, &idio24gpio->reg->ttl_out0_7);
363
364                 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
365         }
366 }
367
368 static void idio_24_irq_ack(struct irq_data *data)
369 {
370 }
371
372 static void idio_24_irq_mask(struct irq_data *data)
373 {
374         struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
375         struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
376         unsigned long flags;
377         const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
378         unsigned char new_irq_mask;
379         const unsigned long bank_offset = bit_offset / 8;
380         unsigned char cos_enable_state;
381
382         raw_spin_lock_irqsave(&idio24gpio->lock, flags);
383
384         idio24gpio->irq_mask &= ~BIT(bit_offset);
385         new_irq_mask = idio24gpio->irq_mask >> bank_offset * 8;
386
387         if (!new_irq_mask) {
388                 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
389
390                 /* Disable Rising Edge detection */
391                 cos_enable_state &= ~BIT(bank_offset);
392                 /* Disable Falling Edge detection */
393                 cos_enable_state &= ~BIT(bank_offset + 4);
394
395                 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
396         }
397
398         raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
399 }
400
401 static void idio_24_irq_unmask(struct irq_data *data)
402 {
403         struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
404         struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
405         unsigned long flags;
406         unsigned char prev_irq_mask;
407         const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
408         const unsigned long bank_offset = bit_offset / 8;
409         unsigned char cos_enable_state;
410
411         raw_spin_lock_irqsave(&idio24gpio->lock, flags);
412
413         prev_irq_mask = idio24gpio->irq_mask >> bank_offset * 8;
414         idio24gpio->irq_mask |= BIT(bit_offset);
415
416         if (!prev_irq_mask) {
417                 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
418
419                 /* Enable Rising Edge detection */
420                 cos_enable_state |= BIT(bank_offset);
421                 /* Enable Falling Edge detection */
422                 cos_enable_state |= BIT(bank_offset + 4);
423
424                 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
425         }
426
427         raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
428 }
429
430 static int idio_24_irq_set_type(struct irq_data *data, unsigned int flow_type)
431 {
432         /* The only valid irq types are none and both-edges */
433         if (flow_type != IRQ_TYPE_NONE &&
434                 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
435                 return -EINVAL;
436
437         return 0;
438 }
439
440 static struct irq_chip idio_24_irqchip = {
441         .name = "pcie-idio-24",
442         .irq_ack = idio_24_irq_ack,
443         .irq_mask = idio_24_irq_mask,
444         .irq_unmask = idio_24_irq_unmask,
445         .irq_set_type = idio_24_irq_set_type
446 };
447
448 static irqreturn_t idio_24_irq_handler(int irq, void *dev_id)
449 {
450         struct idio_24_gpio *const idio24gpio = dev_id;
451         unsigned long irq_status;
452         struct gpio_chip *const chip = &idio24gpio->chip;
453         unsigned long irq_mask;
454         int gpio;
455
456         raw_spin_lock(&idio24gpio->lock);
457
458         /* Read Change-Of-State status */
459         irq_status = ioread32(&idio24gpio->reg->cos0_7);
460
461         raw_spin_unlock(&idio24gpio->lock);
462
463         /* Make sure our device generated IRQ */
464         if (!irq_status)
465                 return IRQ_NONE;
466
467         /* Handle only unmasked IRQ */
468         irq_mask = idio24gpio->irq_mask & irq_status;
469
470         for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24)
471                 generic_handle_domain_irq(chip->irq.domain, gpio + 24);
472
473         raw_spin_lock(&idio24gpio->lock);
474
475         /* Clear Change-Of-State status */
476         iowrite32(irq_status, &idio24gpio->reg->cos0_7);
477
478         raw_spin_unlock(&idio24gpio->lock);
479
480         return IRQ_HANDLED;
481 }
482
483 #define IDIO_24_NGPIO 56
484 static const char *idio_24_names[IDIO_24_NGPIO] = {
485         "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
486         "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
487         "OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
488         "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
489         "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
490         "IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
491         "TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
492 };
493
494 static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
495 {
496         struct device *const dev = &pdev->dev;
497         struct idio_24_gpio *idio24gpio;
498         int err;
499         const size_t pci_plx_bar_index = 1;
500         const size_t pci_bar_index = 2;
501         const char *const name = pci_name(pdev);
502         struct gpio_irq_chip *girq;
503
504         idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL);
505         if (!idio24gpio)
506                 return -ENOMEM;
507
508         err = pcim_enable_device(pdev);
509         if (err) {
510                 dev_err(dev, "Failed to enable PCI device (%d)\n", err);
511                 return err;
512         }
513
514         err = pcim_iomap_regions(pdev, BIT(pci_plx_bar_index) | BIT(pci_bar_index), name);
515         if (err) {
516                 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
517                 return err;
518         }
519
520         idio24gpio->plx = pcim_iomap_table(pdev)[pci_plx_bar_index];
521         idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
522
523         idio24gpio->chip.label = name;
524         idio24gpio->chip.parent = dev;
525         idio24gpio->chip.owner = THIS_MODULE;
526         idio24gpio->chip.base = -1;
527         idio24gpio->chip.ngpio = IDIO_24_NGPIO;
528         idio24gpio->chip.names = idio_24_names;
529         idio24gpio->chip.get_direction = idio_24_gpio_get_direction;
530         idio24gpio->chip.direction_input = idio_24_gpio_direction_input;
531         idio24gpio->chip.direction_output = idio_24_gpio_direction_output;
532         idio24gpio->chip.get = idio_24_gpio_get;
533         idio24gpio->chip.get_multiple = idio_24_gpio_get_multiple;
534         idio24gpio->chip.set = idio_24_gpio_set;
535         idio24gpio->chip.set_multiple = idio_24_gpio_set_multiple;
536
537         girq = &idio24gpio->chip.irq;
538         girq->chip = &idio_24_irqchip;
539         /* This will let us handle the parent IRQ in the driver */
540         girq->parent_handler = NULL;
541         girq->num_parents = 0;
542         girq->parents = NULL;
543         girq->default_type = IRQ_TYPE_NONE;
544         girq->handler = handle_edge_irq;
545
546         raw_spin_lock_init(&idio24gpio->lock);
547
548         /* Software board reset */
549         iowrite8(0, &idio24gpio->reg->soft_reset);
550         /*
551          * enable PLX PEX8311 internal PCI wire interrupt and local interrupt
552          * input
553          */
554         iowrite8((INTCSR_INTERNAL_PCI_WIRE | INTCSR_LOCAL_INPUT) >> 8,
555                  idio24gpio->plx + PLX_PEX8311_PCI_LCS_INTCSR + 1);
556
557         err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio);
558         if (err) {
559                 dev_err(dev, "GPIO registering failed (%d)\n", err);
560                 return err;
561         }
562
563         err = devm_request_irq(dev, pdev->irq, idio_24_irq_handler, IRQF_SHARED,
564                 name, idio24gpio);
565         if (err) {
566                 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
567                 return err;
568         }
569
570         return 0;
571 }
572
573 static const struct pci_device_id idio_24_pci_dev_id[] = {
574         { PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) },
575         { PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) },
576         { 0 }
577 };
578 MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id);
579
580 static struct pci_driver idio_24_driver = {
581         .name = "pcie-idio-24",
582         .id_table = idio_24_pci_dev_id,
583         .probe = idio_24_probe
584 };
585
586 module_pci_driver(idio_24_driver);
587
588 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
589 MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
590 MODULE_LICENSE("GPL v2");