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);
107 return GPIO_LINE_DIRECTION_OUT;
109 /* Isolated Inputs */
111 return GPIO_LINE_DIRECTION_IN;
114 /* OUT MODE = 1 when TTL/CMOS Output Mode is set */
115 if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
116 return GPIO_LINE_DIRECTION_OUT;
118 return GPIO_LINE_DIRECTION_IN;
121 static int idio_24_gpio_direction_input(struct gpio_chip *chip,
124 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
126 unsigned int ctl_state;
127 const unsigned long out_mode_mask = BIT(1);
131 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
133 /* Clear TTL/CMOS Output Mode */
134 ctl_state = ioread8(&idio24gpio->reg->ctl) & ~out_mode_mask;
135 iowrite8(ctl_state, &idio24gpio->reg->ctl);
137 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
143 static int idio_24_gpio_direction_output(struct gpio_chip *chip,
144 unsigned int offset, int value)
146 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
148 unsigned int ctl_state;
149 const unsigned long out_mode_mask = BIT(1);
153 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
155 /* Set TTL/CMOS Output Mode */
156 ctl_state = ioread8(&idio24gpio->reg->ctl) | out_mode_mask;
157 iowrite8(ctl_state, &idio24gpio->reg->ctl);
159 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
162 chip->set(chip, offset, value);
166 static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset)
168 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
169 const unsigned long offset_mask = BIT(offset % 8);
170 const unsigned long out_mode_mask = BIT(1);
174 return !!(ioread8(&idio24gpio->reg->out0_7) & offset_mask);
177 return !!(ioread8(&idio24gpio->reg->out8_15) & offset_mask);
180 return !!(ioread8(&idio24gpio->reg->out16_23) & offset_mask);
182 /* Isolated Inputs */
184 return !!(ioread8(&idio24gpio->reg->in0_7) & offset_mask);
187 return !!(ioread8(&idio24gpio->reg->in8_15) & offset_mask);
190 return !!(ioread8(&idio24gpio->reg->in16_23) & offset_mask);
192 /* TTL/CMOS Outputs */
193 if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
194 return !!(ioread8(&idio24gpio->reg->ttl_out0_7) & offset_mask);
196 /* TTL/CMOS Inputs */
197 return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask);
200 static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
201 unsigned long *mask, unsigned long *bits)
203 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
205 const unsigned int gpio_reg_size = 8;
206 unsigned int bits_offset;
208 unsigned int word_offset;
209 unsigned long word_mask;
210 const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
211 unsigned long port_state;
212 void __iomem *ports[] = {
213 &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
214 &idio24gpio->reg->out16_23, &idio24gpio->reg->in0_7,
215 &idio24gpio->reg->in8_15, &idio24gpio->reg->in16_23,
217 const unsigned long out_mode_mask = BIT(1);
219 /* clear bits array to a clean slate */
220 bitmap_zero(bits, chip->ngpio);
222 /* get bits are evaluated a gpio port register at a time */
223 for (i = 0; i < ARRAY_SIZE(ports) + 1; i++) {
224 /* gpio offset in bits array */
225 bits_offset = i * gpio_reg_size;
227 /* word index for bits array */
228 word_index = BIT_WORD(bits_offset);
230 /* gpio offset within current word of bits array */
231 word_offset = bits_offset % BITS_PER_LONG;
233 /* mask of get bits for current gpio within current word */
234 word_mask = mask[word_index] & (port_mask << word_offset);
236 /* no get bits in this port so skip to next one */
240 /* read bits from current gpio port (port 6 is TTL GPIO) */
242 port_state = ioread8(ports[i]);
243 else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
244 port_state = ioread8(&idio24gpio->reg->ttl_out0_7);
246 port_state = ioread8(&idio24gpio->reg->ttl_in0_7);
248 /* store acquired bits at respective bits array offset */
249 bits[word_index] |= (port_state << word_offset) & word_mask;
255 static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset,
258 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
259 const unsigned long out_mode_mask = BIT(1);
261 const unsigned int mask = BIT(offset % 8);
263 unsigned int out_state;
265 /* Isolated Inputs */
266 if (offset > 23 && offset < 48)
269 /* TTL/CMOS Inputs */
270 if (offset > 47 && !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask))
273 /* TTL/CMOS Outputs */
275 base = &idio24gpio->reg->ttl_out0_7;
277 else if (offset > 15)
278 base = &idio24gpio->reg->out16_23;
280 base = &idio24gpio->reg->out8_15;
282 base = &idio24gpio->reg->out0_7;
284 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
287 out_state = ioread8(base) | mask;
289 out_state = ioread8(base) & ~mask;
291 iowrite8(out_state, base);
293 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
296 static void idio_24_gpio_set_multiple(struct gpio_chip *chip,
297 unsigned long *mask, unsigned long *bits)
299 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
301 unsigned long bits_offset;
302 unsigned long gpio_mask;
303 const unsigned int gpio_reg_size = 8;
304 const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
306 unsigned int out_state;
307 void __iomem *ports[] = {
308 &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
309 &idio24gpio->reg->out16_23
311 const unsigned long out_mode_mask = BIT(1);
312 const unsigned int ttl_offset = 48;
313 const size_t ttl_i = BIT_WORD(ttl_offset);
314 const unsigned int word_offset = ttl_offset % BITS_PER_LONG;
315 const unsigned long ttl_mask = (mask[ttl_i] >> word_offset) & port_mask;
316 const unsigned long ttl_bits = (bits[ttl_i] >> word_offset) & ttl_mask;
318 /* set bits are processed a gpio port register at a time */
319 for (i = 0; i < ARRAY_SIZE(ports); i++) {
320 /* gpio offset in bits array */
321 bits_offset = i * gpio_reg_size;
323 /* check if any set bits for current port */
324 gpio_mask = (*mask >> bits_offset) & port_mask;
326 /* no set bits for this port so move on to next port */
330 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
332 /* process output lines */
333 out_state = ioread8(ports[i]) & ~gpio_mask;
334 out_state |= (*bits >> bits_offset) & gpio_mask;
335 iowrite8(out_state, ports[i]);
337 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
340 /* check if setting TTL lines and if they are in output mode */
341 if (!ttl_mask || !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask))
344 /* handle TTL output */
345 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
347 /* process output lines */
348 out_state = ioread8(&idio24gpio->reg->ttl_out0_7) & ~ttl_mask;
349 out_state |= ttl_bits;
350 iowrite8(out_state, &idio24gpio->reg->ttl_out0_7);
352 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
355 static void idio_24_irq_ack(struct irq_data *data)
359 static void idio_24_irq_mask(struct irq_data *data)
361 struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
362 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
364 const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
365 unsigned char new_irq_mask;
366 const unsigned long bank_offset = bit_offset/8 * 8;
367 unsigned char cos_enable_state;
369 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
371 idio24gpio->irq_mask &= BIT(bit_offset);
372 new_irq_mask = idio24gpio->irq_mask >> bank_offset;
375 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
377 /* Disable Rising Edge detection */
378 cos_enable_state &= ~BIT(bank_offset);
379 /* Disable Falling Edge detection */
380 cos_enable_state &= ~BIT(bank_offset + 4);
382 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
385 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
388 static void idio_24_irq_unmask(struct irq_data *data)
390 struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
391 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
393 unsigned char prev_irq_mask;
394 const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
395 const unsigned long bank_offset = bit_offset/8 * 8;
396 unsigned char cos_enable_state;
398 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
400 prev_irq_mask = idio24gpio->irq_mask >> bank_offset;
401 idio24gpio->irq_mask |= BIT(bit_offset);
403 if (!prev_irq_mask) {
404 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
406 /* Enable Rising Edge detection */
407 cos_enable_state |= BIT(bank_offset);
408 /* Enable Falling Edge detection */
409 cos_enable_state |= BIT(bank_offset + 4);
411 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
414 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
417 static int idio_24_irq_set_type(struct irq_data *data, unsigned int flow_type)
419 /* The only valid irq types are none and both-edges */
420 if (flow_type != IRQ_TYPE_NONE &&
421 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
427 static struct irq_chip idio_24_irqchip = {
428 .name = "pcie-idio-24",
429 .irq_ack = idio_24_irq_ack,
430 .irq_mask = idio_24_irq_mask,
431 .irq_unmask = idio_24_irq_unmask,
432 .irq_set_type = idio_24_irq_set_type
435 static irqreturn_t idio_24_irq_handler(int irq, void *dev_id)
437 struct idio_24_gpio *const idio24gpio = dev_id;
438 unsigned long irq_status;
439 struct gpio_chip *const chip = &idio24gpio->chip;
440 unsigned long irq_mask;
443 raw_spin_lock(&idio24gpio->lock);
445 /* Read Change-Of-State status */
446 irq_status = ioread32(&idio24gpio->reg->cos0_7);
448 raw_spin_unlock(&idio24gpio->lock);
450 /* Make sure our device generated IRQ */
454 /* Handle only unmasked IRQ */
455 irq_mask = idio24gpio->irq_mask & irq_status;
457 for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24)
458 generic_handle_irq(irq_find_mapping(chip->irq.domain,
461 raw_spin_lock(&idio24gpio->lock);
463 /* Clear Change-Of-State status */
464 iowrite32(irq_status, &idio24gpio->reg->cos0_7);
466 raw_spin_unlock(&idio24gpio->lock);
471 #define IDIO_24_NGPIO 56
472 static const char *idio_24_names[IDIO_24_NGPIO] = {
473 "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
474 "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
475 "OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
476 "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
477 "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
478 "IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
479 "TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
482 static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
484 struct device *const dev = &pdev->dev;
485 struct idio_24_gpio *idio24gpio;
487 const size_t pci_bar_index = 2;
488 const char *const name = pci_name(pdev);
490 idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL);
494 err = pcim_enable_device(pdev);
496 dev_err(dev, "Failed to enable PCI device (%d)\n", err);
500 err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
502 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
506 idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
508 idio24gpio->chip.label = name;
509 idio24gpio->chip.parent = dev;
510 idio24gpio->chip.owner = THIS_MODULE;
511 idio24gpio->chip.base = -1;
512 idio24gpio->chip.ngpio = IDIO_24_NGPIO;
513 idio24gpio->chip.names = idio_24_names;
514 idio24gpio->chip.get_direction = idio_24_gpio_get_direction;
515 idio24gpio->chip.direction_input = idio_24_gpio_direction_input;
516 idio24gpio->chip.direction_output = idio_24_gpio_direction_output;
517 idio24gpio->chip.get = idio_24_gpio_get;
518 idio24gpio->chip.get_multiple = idio_24_gpio_get_multiple;
519 idio24gpio->chip.set = idio_24_gpio_set;
520 idio24gpio->chip.set_multiple = idio_24_gpio_set_multiple;
522 raw_spin_lock_init(&idio24gpio->lock);
524 /* Software board reset */
525 iowrite8(0, &idio24gpio->reg->soft_reset);
527 err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio);
529 dev_err(dev, "GPIO registering failed (%d)\n", err);
533 err = gpiochip_irqchip_add(&idio24gpio->chip, &idio_24_irqchip, 0,
534 handle_edge_irq, IRQ_TYPE_NONE);
536 dev_err(dev, "Could not add irqchip (%d)\n", err);
540 err = devm_request_irq(dev, pdev->irq, idio_24_irq_handler, IRQF_SHARED,
543 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
550 static const struct pci_device_id idio_24_pci_dev_id[] = {
551 { PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) },
552 { PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) },
555 MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id);
557 static struct pci_driver idio_24_driver = {
558 .name = "pcie-idio-24",
559 .id_table = idio_24_pci_dev_id,
560 .probe = idio_24_probe
563 module_pci_driver(idio_24_driver);
565 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
566 MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
567 MODULE_LICENSE("GPL v2");