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 * struct idio_24_gpio_reg - GPIO device registers structure
33 * @out0_7: Read: FET Outputs 0-7
34 * Write: FET Outputs 0-7
35 * @out8_15: Read: FET Outputs 8-15
36 * Write: FET Outputs 8-15
37 * @out16_23: Read: FET Outputs 16-23
38 * Write: FET Outputs 16-23
39 * @ttl_out0_7: Read: TTL/CMOS Outputs 0-7
40 * Write: TTL/CMOS Outputs 0-7
41 * @in0_7: Read: Isolated Inputs 0-7
43 * @in8_15: Read: Isolated Inputs 8-15
45 * @in16_23: Read: Isolated Inputs 16-23
47 * @ttl_in0_7: Read: TTL/CMOS Inputs 0-7
49 * @cos0_7: Read: COS Status Inputs 0-7
50 * Write: COS Clear Inputs 0-7
51 * @cos8_15: Read: COS Status Inputs 8-15
52 * Write: COS Clear Inputs 8-15
53 * @cos16_23: Read: COS Status Inputs 16-23
54 * Write: COS Clear Inputs 16-23
55 * @cos_ttl0_7: Read: COS Status TTL/CMOS 0-7
56 * Write: COS Clear TTL/CMOS 0-7
57 * @ctl: Read: Control Register
58 * Write: Control Register
59 * @reserved: Read: Reserved
61 * @cos_enable: Read: COS Enable
63 * @soft_reset: Read: IRQ Output Pin Status
64 * Write: Software Board Reset
66 struct idio_24_gpio_reg
{
86 * struct idio_24_gpio - GPIO device private data structure
87 * @chip: instance of the gpio_chip
88 * @lock: synchronization lock to prevent I/O race conditions
89 * @reg: I/O address offset for the GPIO device registers
90 * @irq_mask: I/O bits affected by interrupts
93 struct gpio_chip chip
;
95 struct idio_24_gpio_reg __iomem
*reg
;
96 unsigned long irq_mask
;
99 static int idio_24_gpio_get_direction(struct gpio_chip
*chip
,
102 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
103 const unsigned long out_mode_mask
= BIT(1);
109 /* Isolated Inputs */
114 /* OUT MODE = 1 when TTL/CMOS Output Mode is set */
115 return !(ioread8(&idio24gpio
->reg
->ctl
) & out_mode_mask
);
118 static int idio_24_gpio_direction_input(struct gpio_chip
*chip
,
121 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
123 unsigned int ctl_state
;
124 const unsigned long out_mode_mask
= BIT(1);
128 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
130 /* Clear TTL/CMOS Output Mode */
131 ctl_state
= ioread8(&idio24gpio
->reg
->ctl
) & ~out_mode_mask
;
132 iowrite8(ctl_state
, &idio24gpio
->reg
->ctl
);
134 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
140 static int idio_24_gpio_direction_output(struct gpio_chip
*chip
,
141 unsigned int offset
, int value
)
143 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
145 unsigned int ctl_state
;
146 const unsigned long out_mode_mask
= BIT(1);
150 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
152 /* Set TTL/CMOS Output Mode */
153 ctl_state
= ioread8(&idio24gpio
->reg
->ctl
) | out_mode_mask
;
154 iowrite8(ctl_state
, &idio24gpio
->reg
->ctl
);
156 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
159 chip
->set(chip
, offset
, value
);
163 static int idio_24_gpio_get(struct gpio_chip
*chip
, unsigned int offset
)
165 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
166 const unsigned long offset_mask
= BIT(offset
% 8);
167 const unsigned long out_mode_mask
= BIT(1);
171 return !!(ioread8(&idio24gpio
->reg
->out0_7
) & offset_mask
);
174 return !!(ioread8(&idio24gpio
->reg
->out8_15
) & offset_mask
);
177 return !!(ioread8(&idio24gpio
->reg
->out16_23
) & offset_mask
);
179 /* Isolated Inputs */
181 return !!(ioread8(&idio24gpio
->reg
->in0_7
) & offset_mask
);
184 return !!(ioread8(&idio24gpio
->reg
->in8_15
) & offset_mask
);
187 return !!(ioread8(&idio24gpio
->reg
->in16_23
) & offset_mask
);
189 /* TTL/CMOS Outputs */
190 if (ioread8(&idio24gpio
->reg
->ctl
) & out_mode_mask
)
191 return !!(ioread8(&idio24gpio
->reg
->ttl_out0_7
) & offset_mask
);
193 /* TTL/CMOS Inputs */
194 return !!(ioread8(&idio24gpio
->reg
->ttl_in0_7
) & offset_mask
);
197 static int idio_24_gpio_get_multiple(struct gpio_chip
*chip
,
198 unsigned long *mask
, unsigned long *bits
)
200 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
202 const unsigned int gpio_reg_size
= 8;
203 unsigned int bits_offset
;
205 unsigned int word_offset
;
206 unsigned long word_mask
;
207 const unsigned long port_mask
= GENMASK(gpio_reg_size
- 1, 0);
208 unsigned long port_state
;
209 void __iomem
*ports
[] = {
210 &idio24gpio
->reg
->out0_7
, &idio24gpio
->reg
->out8_15
,
211 &idio24gpio
->reg
->out16_23
, &idio24gpio
->reg
->in0_7
,
212 &idio24gpio
->reg
->in8_15
, &idio24gpio
->reg
->in16_23
,
214 const unsigned long out_mode_mask
= BIT(1);
216 /* clear bits array to a clean slate */
217 bitmap_zero(bits
, chip
->ngpio
);
219 /* get bits are evaluated a gpio port register at a time */
220 for (i
= 0; i
< ARRAY_SIZE(ports
) + 1; i
++) {
221 /* gpio offset in bits array */
222 bits_offset
= i
* gpio_reg_size
;
224 /* word index for bits array */
225 word_index
= BIT_WORD(bits_offset
);
227 /* gpio offset within current word of bits array */
228 word_offset
= bits_offset
% BITS_PER_LONG
;
230 /* mask of get bits for current gpio within current word */
231 word_mask
= mask
[word_index
] & (port_mask
<< word_offset
);
233 /* no get bits in this port so skip to next one */
237 /* read bits from current gpio port (port 6 is TTL GPIO) */
239 port_state
= ioread8(ports
[i
]);
240 else if (ioread8(&idio24gpio
->reg
->ctl
) & out_mode_mask
)
241 port_state
= ioread8(&idio24gpio
->reg
->ttl_out0_7
);
243 port_state
= ioread8(&idio24gpio
->reg
->ttl_in0_7
);
245 /* store acquired bits at respective bits array offset */
246 bits
[word_index
] |= port_state
<< word_offset
;
252 static void idio_24_gpio_set(struct gpio_chip
*chip
, unsigned int offset
,
255 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
256 const unsigned long out_mode_mask
= BIT(1);
258 const unsigned int mask
= BIT(offset
% 8);
260 unsigned int out_state
;
262 /* Isolated Inputs */
263 if (offset
> 23 && offset
< 48)
266 /* TTL/CMOS Inputs */
267 if (offset
> 47 && !(ioread8(&idio24gpio
->reg
->ctl
) & out_mode_mask
))
270 /* TTL/CMOS Outputs */
272 base
= &idio24gpio
->reg
->ttl_out0_7
;
274 else if (offset
> 15)
275 base
= &idio24gpio
->reg
->out16_23
;
277 base
= &idio24gpio
->reg
->out8_15
;
279 base
= &idio24gpio
->reg
->out0_7
;
281 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
284 out_state
= ioread8(base
) | mask
;
286 out_state
= ioread8(base
) & ~mask
;
288 iowrite8(out_state
, base
);
290 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
293 static void idio_24_gpio_set_multiple(struct gpio_chip
*chip
,
294 unsigned long *mask
, unsigned long *bits
)
296 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
298 unsigned long bits_offset
;
299 unsigned long gpio_mask
;
300 const unsigned int gpio_reg_size
= 8;
301 const unsigned long port_mask
= GENMASK(gpio_reg_size
, 0);
303 unsigned int out_state
;
304 void __iomem
*ports
[] = {
305 &idio24gpio
->reg
->out0_7
, &idio24gpio
->reg
->out8_15
,
306 &idio24gpio
->reg
->out16_23
308 const unsigned long out_mode_mask
= BIT(1);
309 const unsigned int ttl_offset
= 48;
310 const size_t ttl_i
= BIT_WORD(ttl_offset
);
311 const unsigned int word_offset
= ttl_offset
% BITS_PER_LONG
;
312 const unsigned long ttl_mask
= (mask
[ttl_i
] >> word_offset
) & port_mask
;
313 const unsigned long ttl_bits
= (bits
[ttl_i
] >> word_offset
) & ttl_mask
;
315 /* set bits are processed a gpio port register at a time */
316 for (i
= 0; i
< ARRAY_SIZE(ports
); i
++) {
317 /* gpio offset in bits array */
318 bits_offset
= i
* gpio_reg_size
;
320 /* check if any set bits for current port */
321 gpio_mask
= (*mask
>> bits_offset
) & port_mask
;
323 /* no set bits for this port so move on to next port */
327 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
329 /* process output lines */
330 out_state
= ioread8(ports
[i
]) & ~gpio_mask
;
331 out_state
|= (*bits
>> bits_offset
) & gpio_mask
;
332 iowrite8(out_state
, ports
[i
]);
334 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
337 /* check if setting TTL lines and if they are in output mode */
338 if (!ttl_mask
|| !(ioread8(&idio24gpio
->reg
->ctl
) & out_mode_mask
))
341 /* handle TTL output */
342 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
344 /* process output lines */
345 out_state
= ioread8(&idio24gpio
->reg
->ttl_out0_7
) & ~ttl_mask
;
346 out_state
|= ttl_bits
;
347 iowrite8(out_state
, &idio24gpio
->reg
->ttl_out0_7
);
349 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
352 static void idio_24_irq_ack(struct irq_data
*data
)
356 static void idio_24_irq_mask(struct irq_data
*data
)
358 struct gpio_chip
*const chip
= irq_data_get_irq_chip_data(data
);
359 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
361 const unsigned long bit_offset
= irqd_to_hwirq(data
) - 24;
362 unsigned char new_irq_mask
;
363 const unsigned long bank_offset
= bit_offset
/8 * 8;
364 unsigned char cos_enable_state
;
366 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
368 idio24gpio
->irq_mask
&= BIT(bit_offset
);
369 new_irq_mask
= idio24gpio
->irq_mask
>> bank_offset
;
372 cos_enable_state
= ioread8(&idio24gpio
->reg
->cos_enable
);
374 /* Disable Rising Edge detection */
375 cos_enable_state
&= ~BIT(bank_offset
);
376 /* Disable Falling Edge detection */
377 cos_enable_state
&= ~BIT(bank_offset
+ 4);
379 iowrite8(cos_enable_state
, &idio24gpio
->reg
->cos_enable
);
382 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
385 static void idio_24_irq_unmask(struct irq_data
*data
)
387 struct gpio_chip
*const chip
= irq_data_get_irq_chip_data(data
);
388 struct idio_24_gpio
*const idio24gpio
= gpiochip_get_data(chip
);
390 unsigned char prev_irq_mask
;
391 const unsigned long bit_offset
= irqd_to_hwirq(data
) - 24;
392 const unsigned long bank_offset
= bit_offset
/8 * 8;
393 unsigned char cos_enable_state
;
395 raw_spin_lock_irqsave(&idio24gpio
->lock
, flags
);
397 prev_irq_mask
= idio24gpio
->irq_mask
>> bank_offset
;
398 idio24gpio
->irq_mask
|= BIT(bit_offset
);
400 if (!prev_irq_mask
) {
401 cos_enable_state
= ioread8(&idio24gpio
->reg
->cos_enable
);
403 /* Enable Rising Edge detection */
404 cos_enable_state
|= BIT(bank_offset
);
405 /* Enable Falling Edge detection */
406 cos_enable_state
|= BIT(bank_offset
+ 4);
408 iowrite8(cos_enable_state
, &idio24gpio
->reg
->cos_enable
);
411 raw_spin_unlock_irqrestore(&idio24gpio
->lock
, flags
);
414 static int idio_24_irq_set_type(struct irq_data
*data
, unsigned int flow_type
)
416 /* The only valid irq types are none and both-edges */
417 if (flow_type
!= IRQ_TYPE_NONE
&&
418 (flow_type
& IRQ_TYPE_EDGE_BOTH
) != IRQ_TYPE_EDGE_BOTH
)
424 static struct irq_chip idio_24_irqchip
= {
425 .name
= "pcie-idio-24",
426 .irq_ack
= idio_24_irq_ack
,
427 .irq_mask
= idio_24_irq_mask
,
428 .irq_unmask
= idio_24_irq_unmask
,
429 .irq_set_type
= idio_24_irq_set_type
432 static irqreturn_t
idio_24_irq_handler(int irq
, void *dev_id
)
434 struct idio_24_gpio
*const idio24gpio
= dev_id
;
435 unsigned long irq_status
;
436 struct gpio_chip
*const chip
= &idio24gpio
->chip
;
437 unsigned long irq_mask
;
440 raw_spin_lock(&idio24gpio
->lock
);
442 /* Read Change-Of-State status */
443 irq_status
= ioread32(&idio24gpio
->reg
->cos0_7
);
445 raw_spin_unlock(&idio24gpio
->lock
);
447 /* Make sure our device generated IRQ */
451 /* Handle only unmasked IRQ */
452 irq_mask
= idio24gpio
->irq_mask
& irq_status
;
454 for_each_set_bit(gpio
, &irq_mask
, chip
->ngpio
- 24)
455 generic_handle_irq(irq_find_mapping(chip
->irq
.domain
,
458 raw_spin_lock(&idio24gpio
->lock
);
460 /* Clear Change-Of-State status */
461 iowrite32(irq_status
, &idio24gpio
->reg
->cos0_7
);
463 raw_spin_unlock(&idio24gpio
->lock
);
468 #define IDIO_24_NGPIO 56
469 static const char *idio_24_names
[IDIO_24_NGPIO
] = {
470 "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
471 "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
472 "OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
473 "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
474 "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
475 "IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
476 "TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
479 static int idio_24_probe(struct pci_dev
*pdev
, const struct pci_device_id
*id
)
481 struct device
*const dev
= &pdev
->dev
;
482 struct idio_24_gpio
*idio24gpio
;
484 const size_t pci_bar_index
= 2;
485 const char *const name
= pci_name(pdev
);
487 idio24gpio
= devm_kzalloc(dev
, sizeof(*idio24gpio
), GFP_KERNEL
);
491 err
= pcim_enable_device(pdev
);
493 dev_err(dev
, "Failed to enable PCI device (%d)\n", err
);
497 err
= pcim_iomap_regions(pdev
, BIT(pci_bar_index
), name
);
499 dev_err(dev
, "Unable to map PCI I/O addresses (%d)\n", err
);
503 idio24gpio
->reg
= pcim_iomap_table(pdev
)[pci_bar_index
];
505 idio24gpio
->chip
.label
= name
;
506 idio24gpio
->chip
.parent
= dev
;
507 idio24gpio
->chip
.owner
= THIS_MODULE
;
508 idio24gpio
->chip
.base
= -1;
509 idio24gpio
->chip
.ngpio
= IDIO_24_NGPIO
;
510 idio24gpio
->chip
.names
= idio_24_names
;
511 idio24gpio
->chip
.get_direction
= idio_24_gpio_get_direction
;
512 idio24gpio
->chip
.direction_input
= idio_24_gpio_direction_input
;
513 idio24gpio
->chip
.direction_output
= idio_24_gpio_direction_output
;
514 idio24gpio
->chip
.get
= idio_24_gpio_get
;
515 idio24gpio
->chip
.get_multiple
= idio_24_gpio_get_multiple
;
516 idio24gpio
->chip
.set
= idio_24_gpio_set
;
517 idio24gpio
->chip
.set_multiple
= idio_24_gpio_set_multiple
;
519 raw_spin_lock_init(&idio24gpio
->lock
);
521 /* Software board reset */
522 iowrite8(0, &idio24gpio
->reg
->soft_reset
);
524 err
= devm_gpiochip_add_data(dev
, &idio24gpio
->chip
, idio24gpio
);
526 dev_err(dev
, "GPIO registering failed (%d)\n", err
);
530 err
= gpiochip_irqchip_add(&idio24gpio
->chip
, &idio_24_irqchip
, 0,
531 handle_edge_irq
, IRQ_TYPE_NONE
);
533 dev_err(dev
, "Could not add irqchip (%d)\n", err
);
537 err
= devm_request_irq(dev
, pdev
->irq
, idio_24_irq_handler
, IRQF_SHARED
,
540 dev_err(dev
, "IRQ handler registering failed (%d)\n", err
);
547 static const struct pci_device_id idio_24_pci_dev_id
[] = {
548 { PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) },
549 { PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) },
552 MODULE_DEVICE_TABLE(pci
, idio_24_pci_dev_id
);
554 static struct pci_driver idio_24_driver
= {
555 .name
= "pcie-idio-24",
556 .id_table
= idio_24_pci_dev_id
,
557 .probe
= idio_24_probe
560 module_pci_driver(idio_24_driver
);
562 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
563 MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
564 MODULE_LICENSE("GPL v2");