1 // SPDX-License-Identifier: GPL-2.0-only
3 * GPIO driver for the ACCES PCIe-IDIO-24 family
4 * Copyright (C) 2018 William Breathitt Gray
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.
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.
15 * This driver supports the following ACCES devices: PCIe-IDIO-24,
16 * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12.
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>
32 * PLX PEX8311 PCI LCS_INTCSR Interrupt Control/Status
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
68 #define PLX_PEX8311_PCI_LCS_INTCSR 0x68
69 #define INTCSR_INTERNAL_PCI_WIRE BIT(8)
70 #define INTCSR_LOCAL_INPUT BIT(11)
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
84 * @in8_15: Read: Isolated Inputs 8-15
86 * @in16_23: Read: Isolated Inputs 16-23
88 * @ttl_in0_7: Read: TTL/CMOS Inputs 0-7
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
102 * @cos_enable: Read: COS Enable
104 * @soft_reset: Read: IRQ Output Pin Status
105 * Write: Software Board Reset
107 struct idio_24_gpio_reg
{
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
133 struct idio_24_gpio
{
134 struct gpio_chip chip
;
137 struct idio_24_gpio_reg __iomem
*reg
;
138 unsigned long irq_mask
;
141 static int idio_24_gpio_get_direction(struct gpio_chip
*chip
,
144 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
145 const unsigned long out_mode_mask
= BIT(1);
149 return GPIO_LINE_DIRECTION_OUT
;
151 /* Isolated Inputs */
153 return GPIO_LINE_DIRECTION_IN
;
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
;
160 return GPIO_LINE_DIRECTION_IN
;
163 static int idio_24_gpio_direction_input(struct gpio_chip
*chip
,
166 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
168 unsigned int ctl_state
;
169 const unsigned long out_mode_mask
= BIT(1);
173 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
175 /* Clear TTL/CMOS Output Mode */
176 ctl_state
= ioread8(&idio24gpio
->reg
->ctl
) & ~out_mode_mask
;
177 iowrite8(ctl_state
, &idio24gpio
->reg
->ctl
);
179 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
185 static int idio_24_gpio_direction_output(struct gpio_chip
*chip
,
186 unsigned int offset
, int value
)
188 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
190 unsigned int ctl_state
;
191 const unsigned long out_mode_mask
= BIT(1);
195 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
197 /* Set TTL/CMOS Output Mode */
198 ctl_state
= ioread8(&idio24gpio
->reg
->ctl
) | out_mode_mask
;
199 iowrite8(ctl_state
, &idio24gpio
->reg
->ctl
);
201 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
204 chip
->set(chip
, offset
, value
);
208 static int idio_24_gpio_get(struct gpio_chip
*chip
, unsigned int offset
)
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);
216 return !!(ioread8(&idio24gpio
->reg
->out0_7
) & offset_mask
);
219 return !!(ioread8(&idio24gpio
->reg
->out8_15
) & offset_mask
);
222 return !!(ioread8(&idio24gpio
->reg
->out16_23
) & offset_mask
);
224 /* Isolated Inputs */
226 return !!(ioread8(&idio24gpio
->reg
->in0_7
) & offset_mask
);
229 return !!(ioread8(&idio24gpio
->reg
->in8_15
) & offset_mask
);
232 return !!(ioread8(&idio24gpio
->reg
->in16_23
) & offset_mask
);
234 /* TTL/CMOS Outputs */
235 if (ioread8(&idio24gpio
->reg
->ctl
) & out_mode_mask
)
236 return !!(ioread8(&idio24gpio
->reg
->ttl_out0_7
) & offset_mask
);
238 /* TTL/CMOS Inputs */
239 return !!(ioread8(&idio24gpio
->reg
->ttl_in0_7
) & offset_mask
);
242 static int idio_24_gpio_get_multiple(struct gpio_chip
*chip
,
243 unsigned long *mask
, unsigned long *bits
)
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
,
254 unsigned long port_state
;
255 const unsigned long out_mode_mask
= BIT(1);
257 /* clear bits array to a clean slate */
258 bitmap_zero(bits
, chip
->ngpio
);
260 for_each_set_clump8(offset
, gpio_mask
, mask
, ARRAY_SIZE(ports
) * 8) {
263 /* read bits from current gpio port (port 6 is TTL GPIO) */
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
);
269 port_state
= ioread8(&idio24gpio
->reg
->ttl_in0_7
);
271 port_state
&= gpio_mask
;
273 bitmap_set_value8(bits
, port_state
, offset
);
279 static void idio_24_gpio_set(struct gpio_chip
*chip
, unsigned int offset
,
282 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
283 const unsigned long out_mode_mask
= BIT(1);
285 const unsigned int mask
= BIT(offset
% 8);
287 unsigned int out_state
;
289 /* Isolated Inputs */
290 if (offset
> 23 && offset
< 48)
293 /* TTL/CMOS Inputs */
294 if (offset
> 47 && !(ioread8(&idio24gpio
->reg
->ctl
) & out_mode_mask
))
297 /* TTL/CMOS Outputs */
299 base
= &idio24gpio
->reg
->ttl_out0_7
;
301 else if (offset
> 15)
302 base
= &idio24gpio
->reg
->out16_23
;
304 base
= &idio24gpio
->reg
->out8_15
;
306 base
= &idio24gpio
->reg
->out0_7
;
308 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
311 out_state
= ioread8(base
) | mask
;
313 out_state
= ioread8(base
) & ~mask
;
315 iowrite8(out_state
, base
);
317 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
320 static void idio_24_gpio_set_multiple(struct gpio_chip
*chip
,
321 unsigned long *mask
, unsigned long *bits
)
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
331 unsigned long bitmask
;
333 unsigned long out_state
;
334 const unsigned long out_mode_mask
= BIT(1);
336 for_each_set_clump8(offset
, gpio_mask
, mask
, ARRAY_SIZE(ports
) * 8) {
339 bitmask
= bitmap_get_value8(bits
, offset
) & gpio_mask
;
341 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
343 /* read bits from current gpio port (port 6 is TTL GPIO) */
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
);
349 /* skip TTL GPIO if set for input */
350 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
354 /* set requested bit states */
355 out_state
&= ~gpio_mask
;
356 out_state
|= bitmask
;
358 /* write bits for current gpio port (port 6 is TTL GPIO) */
360 iowrite8(out_state
, ports
[index
]);
362 iowrite8(out_state
, &idio24gpio
->reg
->ttl_out0_7
);
364 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
368 static void idio_24_irq_ack(struct irq_data
*data
)
372 static void idio_24_irq_mask(struct irq_data
*data
)
374 struct gpio_chip
*const chip
= irq_data_get_irq_chip_data(data
);
375 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
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
;
382 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
384 idio24gpio
->irq_mask
&= ~BIT(bit_offset
);
385 new_irq_mask
= idio24gpio
->irq_mask
>> bank_offset
* 8;
388 cos_enable_state
= ioread8(&idio24gpio
->reg
->cos_enable
);
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);
395 iowrite8(cos_enable_state
, &idio24gpio
->reg
->cos_enable
);
398 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
401 static void idio_24_irq_unmask(struct irq_data
*data
)
403 struct gpio_chip
*const chip
= irq_data_get_irq_chip_data(data
);
404 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
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
;
411 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
413 prev_irq_mask
= idio24gpio
->irq_mask
>> bank_offset
* 8;
414 idio24gpio
->irq_mask
|= BIT(bit_offset
);
416 if (!prev_irq_mask
) {
417 cos_enable_state
= ioread8(&idio24gpio
->reg
->cos_enable
);
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);
424 iowrite8(cos_enable_state
, &idio24gpio
->reg
->cos_enable
);
427 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
430 static int idio_24_irq_set_type(struct irq_data
*data
, unsigned int flow_type
)
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
)
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
448 static irqreturn_t
idio_24_irq_handler(int irq
, void *dev_id
)
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
;
456 raw_spin_lock(&idio24gpio
->lock
);
458 /* Read Change-Of-State status */
459 irq_status
= ioread32(&idio24gpio
->reg
->cos0_7
);
461 raw_spin_unlock(&idio24gpio
->lock
);
463 /* Make sure our device generated IRQ */
467 /* Handle only unmasked IRQ */
468 irq_mask
= idio24gpio
->irq_mask
& irq_status
;
470 for_each_set_bit(gpio
, &irq_mask
, chip
->ngpio
- 24)
471 generic_handle_irq(irq_find_mapping(chip
->irq
.domain
,
474 raw_spin_lock(&idio24gpio
->lock
);
476 /* Clear Change-Of-State status */
477 iowrite32(irq_status
, &idio24gpio
->reg
->cos0_7
);
479 raw_spin_unlock(&idio24gpio
->lock
);
484 #define IDIO_24_NGPIO 56
485 static const char *idio_24_names
[IDIO_24_NGPIO
] = {
486 "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
487 "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
488 "OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
489 "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
490 "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
491 "IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
492 "TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
495 static int idio_24_probe(struct pci_dev
*pdev
, const struct pci_device_id
*id
)
497 struct device
*const dev
= &pdev
->dev
;
498 struct idio_24_gpio
*idio24gpio
;
500 const size_t pci_plx_bar_index
= 1;
501 const size_t pci_bar_index
= 2;
502 const char *const name
= pci_name(pdev
);
503 struct gpio_irq_chip
*girq
;
505 idio24gpio
= devm_kzalloc(dev
, sizeof(*idio24gpio
), GFP_KERNEL
);
509 err
= pcim_enable_device(pdev
);
511 dev_err(dev
, "Failed to enable PCI device (%d)\n", err
);
515 err
= pcim_iomap_regions(pdev
, BIT(pci_plx_bar_index
) | BIT(pci_bar_index
), name
);
517 dev_err(dev
, "Unable to map PCI I/O addresses (%d)\n", err
);
521 idio24gpio
->plx
= pcim_iomap_table(pdev
)[pci_plx_bar_index
];
522 idio24gpio
->reg
= pcim_iomap_table(pdev
)[pci_bar_index
];
524 idio24gpio
->chip
.label
= name
;
525 idio24gpio
->chip
.parent
= dev
;
526 idio24gpio
->chip
.owner
= THIS_MODULE
;
527 idio24gpio
->chip
.base
= -1;
528 idio24gpio
->chip
.ngpio
= IDIO_24_NGPIO
;
529 idio24gpio
->chip
.names
= idio_24_names
;
530 idio24gpio
->chip
.get_direction
= idio_24_gpio_get_direction
;
531 idio24gpio
->chip
.direction_input
= idio_24_gpio_direction_input
;
532 idio24gpio
->chip
.direction_output
= idio_24_gpio_direction_output
;
533 idio24gpio
->chip
.get
= idio_24_gpio_get
;
534 idio24gpio
->chip
.get_multiple
= idio_24_gpio_get_multiple
;
535 idio24gpio
->chip
.set
= idio_24_gpio_set
;
536 idio24gpio
->chip
.set_multiple
= idio_24_gpio_set_multiple
;
538 girq
= &idio24gpio
->chip
.irq
;
539 girq
->chip
= &idio_24_irqchip
;
540 /* This will let us handle the parent IRQ in the driver */
541 girq
->parent_handler
= NULL
;
542 girq
->num_parents
= 0;
543 girq
->parents
= NULL
;
544 girq
->default_type
= IRQ_TYPE_NONE
;
545 girq
->handler
= handle_edge_irq
;
547 raw_spin_lock_init(&idio24gpio
->lock
);
549 /* Software board reset */
550 iowrite8(0, &idio24gpio
->reg
->soft_reset
);
552 * enable PLX PEX8311 internal PCI wire interrupt and local interrupt
555 iowrite8((INTCSR_INTERNAL_PCI_WIRE
| INTCSR_LOCAL_INPUT
) >> 8,
556 idio24gpio
->plx
+ PLX_PEX8311_PCI_LCS_INTCSR
+ 1);
558 err
= devm_gpiochip_add_data(dev
, &idio24gpio
->chip
, idio24gpio
);
560 dev_err(dev
, "GPIO registering failed (%d)\n", err
);
564 err
= devm_request_irq(dev
, pdev
->irq
, idio_24_irq_handler
, IRQF_SHARED
,
567 dev_err(dev
, "IRQ handler registering failed (%d)\n", err
);
574 static const struct pci_device_id idio_24_pci_dev_id
[] = {
575 { PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) },
576 { PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) },
579 MODULE_DEVICE_TABLE(pci
, idio_24_pci_dev_id
);
581 static struct pci_driver idio_24_driver
= {
582 .name
= "pcie-idio-24",
583 .id_table
= idio_24_pci_dev_id
,
584 .probe
= idio_24_probe
587 module_pci_driver(idio_24_driver
);
589 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
590 MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
591 MODULE_LICENSE("GPL v2");