2 * GPIO driver for the ACCES PCI-IDIO-16
3 * Copyright (C) 2017 William Breathitt Gray
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 #include <linux/bitops.h>
15 #include <linux/device.h>
16 #include <linux/errno.h>
17 #include <linux/gpio/driver.h>
18 #include <linux/interrupt.h>
19 #include <linux/irqdesc.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/pci.h>
23 #include <linux/spinlock.h>
24 #include <linux/types.h>
27 * struct idio_16_gpio_reg - GPIO device registers structure
28 * @out0_7: Read: FET Drive Outputs 0-7
29 * Write: FET Drive Outputs 0-7
30 * @in0_7: Read: Isolated Inputs 0-7
31 * Write: Clear Interrupt
32 * @irq_ctl: Read: Enable IRQ
34 * @filter_ctl: Read: Activate Input Filters 0-15
35 * Write: Deactivate Input Filters 0-15
36 * @out8_15: Read: FET Drive Outputs 8-15
37 * Write: FET Drive Outputs 8-15
38 * @in8_15: Read: Isolated Inputs 8-15
40 * @irq_status: Read: Interrupt status
43 struct idio_16_gpio_reg
{
54 * struct idio_16_gpio - GPIO device private data structure
55 * @chip: instance of the gpio_chip
56 * @lock: synchronization lock to prevent I/O race conditions
57 * @reg: I/O address offset for the GPIO device registers
58 * @irq_mask: I/O bits affected by interrupts
61 struct gpio_chip chip
;
63 struct idio_16_gpio_reg __iomem
*reg
;
64 unsigned long irq_mask
;
67 static int idio_16_gpio_get_direction(struct gpio_chip
*chip
,
76 static int idio_16_gpio_direction_input(struct gpio_chip
*chip
,
82 static int idio_16_gpio_direction_output(struct gpio_chip
*chip
,
83 unsigned int offset
, int value
)
85 chip
->set(chip
, offset
, value
);
89 static int idio_16_gpio_get(struct gpio_chip
*chip
, unsigned int offset
)
91 struct idio_16_gpio
*const idio16gpio
= gpiochip_get_data(chip
);
92 unsigned long mask
= BIT(offset
);
95 return !!(ioread8(&idio16gpio
->reg
->out0_7
) & mask
);
98 return !!(ioread8(&idio16gpio
->reg
->out8_15
) & (mask
>> 8));
101 return !!(ioread8(&idio16gpio
->reg
->in0_7
) & (mask
>> 16));
103 return !!(ioread8(&idio16gpio
->reg
->in8_15
) & (mask
>> 24));
106 static void idio_16_gpio_set(struct gpio_chip
*chip
, unsigned int offset
,
109 struct idio_16_gpio
*const idio16gpio
= gpiochip_get_data(chip
);
110 unsigned int mask
= BIT(offset
);
113 unsigned int out_state
;
120 base
= &idio16gpio
->reg
->out8_15
;
122 base
= &idio16gpio
->reg
->out0_7
;
124 raw_spin_lock_irqsave(&idio16gpio
->lock
, flags
);
127 out_state
= ioread8(base
) | mask
;
129 out_state
= ioread8(base
) & ~mask
;
131 iowrite8(out_state
, base
);
133 raw_spin_unlock_irqrestore(&idio16gpio
->lock
, flags
);
136 static void idio_16_gpio_set_multiple(struct gpio_chip
*chip
,
137 unsigned long *mask
, unsigned long *bits
)
139 struct idio_16_gpio
*const idio16gpio
= gpiochip_get_data(chip
);
141 unsigned int out_state
;
143 raw_spin_lock_irqsave(&idio16gpio
->lock
, flags
);
145 /* process output lines 0-7 */
147 out_state
= ioread8(&idio16gpio
->reg
->out0_7
) & ~*mask
;
148 out_state
|= *mask
& *bits
;
149 iowrite8(out_state
, &idio16gpio
->reg
->out0_7
);
152 /* shift to next output line word */
155 /* process output lines 8-15 */
158 out_state
= ioread8(&idio16gpio
->reg
->out8_15
) & ~*mask
;
159 out_state
|= *mask
& *bits
;
160 iowrite8(out_state
, &idio16gpio
->reg
->out8_15
);
163 raw_spin_unlock_irqrestore(&idio16gpio
->lock
, flags
);
166 static void idio_16_irq_ack(struct irq_data
*data
)
170 static void idio_16_irq_mask(struct irq_data
*data
)
172 struct gpio_chip
*chip
= irq_data_get_irq_chip_data(data
);
173 struct idio_16_gpio
*const idio16gpio
= gpiochip_get_data(chip
);
174 const unsigned long mask
= BIT(irqd_to_hwirq(data
));
177 idio16gpio
->irq_mask
&= ~mask
;
179 if (!idio16gpio
->irq_mask
) {
180 raw_spin_lock_irqsave(&idio16gpio
->lock
, flags
);
182 iowrite8(0, &idio16gpio
->reg
->irq_ctl
);
184 raw_spin_unlock_irqrestore(&idio16gpio
->lock
, flags
);
188 static void idio_16_irq_unmask(struct irq_data
*data
)
190 struct gpio_chip
*chip
= irq_data_get_irq_chip_data(data
);
191 struct idio_16_gpio
*const idio16gpio
= gpiochip_get_data(chip
);
192 const unsigned long mask
= BIT(irqd_to_hwirq(data
));
193 const unsigned long prev_irq_mask
= idio16gpio
->irq_mask
;
196 idio16gpio
->irq_mask
|= mask
;
198 if (!prev_irq_mask
) {
199 raw_spin_lock_irqsave(&idio16gpio
->lock
, flags
);
201 ioread8(&idio16gpio
->reg
->irq_ctl
);
203 raw_spin_unlock_irqrestore(&idio16gpio
->lock
, flags
);
207 static int idio_16_irq_set_type(struct irq_data
*data
, unsigned int flow_type
)
209 /* The only valid irq types are none and both-edges */
210 if (flow_type
!= IRQ_TYPE_NONE
&&
211 (flow_type
& IRQ_TYPE_EDGE_BOTH
) != IRQ_TYPE_EDGE_BOTH
)
217 static struct irq_chip idio_16_irqchip
= {
218 .name
= "pci-idio-16",
219 .irq_ack
= idio_16_irq_ack
,
220 .irq_mask
= idio_16_irq_mask
,
221 .irq_unmask
= idio_16_irq_unmask
,
222 .irq_set_type
= idio_16_irq_set_type
225 static irqreturn_t
idio_16_irq_handler(int irq
, void *dev_id
)
227 struct idio_16_gpio
*const idio16gpio
= dev_id
;
228 unsigned int irq_status
;
229 struct gpio_chip
*const chip
= &idio16gpio
->chip
;
232 raw_spin_lock(&idio16gpio
->lock
);
234 irq_status
= ioread8(&idio16gpio
->reg
->irq_status
);
236 raw_spin_unlock(&idio16gpio
->lock
);
238 /* Make sure our device generated IRQ */
239 if (!(irq_status
& 0x3) || !(irq_status
& 0x4))
242 for_each_set_bit(gpio
, &idio16gpio
->irq_mask
, chip
->ngpio
)
243 generic_handle_irq(irq_find_mapping(chip
->irqdomain
, gpio
));
245 raw_spin_lock(&idio16gpio
->lock
);
247 /* Clear interrupt */
248 iowrite8(0, &idio16gpio
->reg
->in0_7
);
250 raw_spin_unlock(&idio16gpio
->lock
);
255 #define IDIO_16_NGPIO 32
256 static const char *idio_16_names
[IDIO_16_NGPIO
] = {
257 "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
258 "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
259 "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
260 "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
263 static int idio_16_probe(struct pci_dev
*pdev
, const struct pci_device_id
*id
)
265 struct device
*const dev
= &pdev
->dev
;
266 struct idio_16_gpio
*idio16gpio
;
268 const size_t pci_bar_index
= 2;
269 const char *const name
= pci_name(pdev
);
271 idio16gpio
= devm_kzalloc(dev
, sizeof(*idio16gpio
), GFP_KERNEL
);
275 err
= pcim_enable_device(pdev
);
277 dev_err(dev
, "Failed to enable PCI device (%d)\n", err
);
281 err
= pcim_iomap_regions(pdev
, BIT(pci_bar_index
), name
);
283 dev_err(dev
, "Unable to map PCI I/O addresses (%d)\n", err
);
287 idio16gpio
->reg
= pcim_iomap_table(pdev
)[pci_bar_index
];
289 /* Deactivate input filters */
290 iowrite8(0, &idio16gpio
->reg
->filter_ctl
);
292 idio16gpio
->chip
.label
= name
;
293 idio16gpio
->chip
.parent
= dev
;
294 idio16gpio
->chip
.owner
= THIS_MODULE
;
295 idio16gpio
->chip
.base
= -1;
296 idio16gpio
->chip
.ngpio
= IDIO_16_NGPIO
;
297 idio16gpio
->chip
.names
= idio_16_names
;
298 idio16gpio
->chip
.get_direction
= idio_16_gpio_get_direction
;
299 idio16gpio
->chip
.direction_input
= idio_16_gpio_direction_input
;
300 idio16gpio
->chip
.direction_output
= idio_16_gpio_direction_output
;
301 idio16gpio
->chip
.get
= idio_16_gpio_get
;
302 idio16gpio
->chip
.set
= idio_16_gpio_set
;
303 idio16gpio
->chip
.set_multiple
= idio_16_gpio_set_multiple
;
305 raw_spin_lock_init(&idio16gpio
->lock
);
307 err
= devm_gpiochip_add_data(dev
, &idio16gpio
->chip
, idio16gpio
);
309 dev_err(dev
, "GPIO registering failed (%d)\n", err
);
313 /* Disable IRQ by default and clear any pending interrupt */
314 iowrite8(0, &idio16gpio
->reg
->irq_ctl
);
315 iowrite8(0, &idio16gpio
->reg
->in0_7
);
317 err
= gpiochip_irqchip_add(&idio16gpio
->chip
, &idio_16_irqchip
, 0,
318 handle_edge_irq
, IRQ_TYPE_NONE
);
320 dev_err(dev
, "Could not add irqchip (%d)\n", err
);
324 err
= devm_request_irq(dev
, pdev
->irq
, idio_16_irq_handler
, IRQF_SHARED
,
327 dev_err(dev
, "IRQ handler registering failed (%d)\n", err
);
334 static const struct pci_device_id idio_16_pci_dev_id
[] = {
335 { PCI_DEVICE(0x494F, 0x0DC8) }, { 0 }
337 MODULE_DEVICE_TABLE(pci
, idio_16_pci_dev_id
);
339 static struct pci_driver idio_16_driver
= {
340 .name
= "pci-idio-16",
341 .id_table
= idio_16_pci_dev_id
,
342 .probe
= idio_16_probe
345 module_pci_driver(idio_16_driver
);
347 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
348 MODULE_DESCRIPTION("ACCES PCI-IDIO-16 GPIO driver");
349 MODULE_LICENSE("GPL v2");