Loading...
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 */
107struct 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 */
133struct 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
141static 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
163static 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
185static 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
208static 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
242static 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
279static 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
320static 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
368static void idio_24_irq_ack(struct irq_data *data)
369{
370}
371
372static 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
401static 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
430static 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
440static 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
448static 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
484static 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
494static 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
573static 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};
578MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id);
579
580static 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
586module_pci_driver(idio_24_driver);
587
588MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
589MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
590MODULE_LICENSE("GPL v2");
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 driver supports the following ACCES devices: PCIe-IDIO-24,
7 * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12.
8 */
9#include <linux/bits.h>
10#include <linux/device.h>
11#include <linux/err.h>
12#include <linux/gpio/regmap.h>
13#include <linux/irq.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/pci.h>
17#include <linux/regmap.h>
18#include <linux/spinlock.h>
19#include <linux/types.h>
20
21/*
22 * PLX PEX8311 PCI LCS_INTCSR Interrupt Control/Status
23 *
24 * Bit: Description
25 * 0: Enable Interrupt Sources (Bit 0)
26 * 1: Enable Interrupt Sources (Bit 1)
27 * 2: Generate Internal PCI Bus Internal SERR# Interrupt
28 * 3: Mailbox Interrupt Enable
29 * 4: Power Management Interrupt Enable
30 * 5: Power Management Interrupt
31 * 6: Slave Read Local Data Parity Check Error Enable
32 * 7: Slave Read Local Data Parity Check Error Status
33 * 8: Internal PCI Wire Interrupt Enable
34 * 9: PCI Express Doorbell Interrupt Enable
35 * 10: PCI Abort Interrupt Enable
36 * 11: Local Interrupt Input Enable
37 * 12: Retry Abort Enable
38 * 13: PCI Express Doorbell Interrupt Active
39 * 14: PCI Abort Interrupt Active
40 * 15: Local Interrupt Input Active
41 * 16: Local Interrupt Output Enable
42 * 17: Local Doorbell Interrupt Enable
43 * 18: DMA Channel 0 Interrupt Enable
44 * 19: DMA Channel 1 Interrupt Enable
45 * 20: Local Doorbell Interrupt Active
46 * 21: DMA Channel 0 Interrupt Active
47 * 22: DMA Channel 1 Interrupt Active
48 * 23: Built-In Self-Test (BIST) Interrupt Active
49 * 24: Direct Master was the Bus Master during a Master or Target Abort
50 * 25: DMA Channel 0 was the Bus Master during a Master or Target Abort
51 * 26: DMA Channel 1 was the Bus Master during a Master or Target Abort
52 * 27: Target Abort after internal 256 consecutive Master Retrys
53 * 28: PCI Bus wrote data to LCS_MBOX0
54 * 29: PCI Bus wrote data to LCS_MBOX1
55 * 30: PCI Bus wrote data to LCS_MBOX2
56 * 31: PCI Bus wrote data to LCS_MBOX3
57 */
58#define PLX_PEX8311_PCI_LCS_INTCSR 0x68
59#define INTCSR_INTERNAL_PCI_WIRE BIT(8)
60#define INTCSR_LOCAL_INPUT BIT(11)
61#define IDIO_24_ENABLE_IRQ (INTCSR_INTERNAL_PCI_WIRE | INTCSR_LOCAL_INPUT)
62
63#define IDIO_24_OUT_BASE 0x0
64#define IDIO_24_TTLCMOS_OUT_REG 0x3
65#define IDIO_24_IN_BASE 0x4
66#define IDIO_24_TTLCMOS_IN_REG 0x7
67#define IDIO_24_COS_STATUS_BASE 0x8
68#define IDIO_24_CONTROL_REG 0xC
69#define IDIO_24_COS_ENABLE 0xE
70#define IDIO_24_SOFT_RESET 0xF
71
72#define CONTROL_REG_OUT_MODE BIT(1)
73
74#define COS_ENABLE_RISING BIT(1)
75#define COS_ENABLE_FALLING BIT(4)
76#define COS_ENABLE_BOTH (COS_ENABLE_RISING | COS_ENABLE_FALLING)
77
78static const struct regmap_config pex8311_intcsr_regmap_config = {
79 .name = "pex8311_intcsr",
80 .reg_bits = 32,
81 .reg_stride = 1,
82 .reg_base = PLX_PEX8311_PCI_LCS_INTCSR,
83 .val_bits = 32,
84 .io_port = true,
85};
86
87static const struct regmap_range idio_24_wr_ranges[] = {
88 regmap_reg_range(0x0, 0x3), regmap_reg_range(0x8, 0xC),
89 regmap_reg_range(0xE, 0xF),
90};
91static const struct regmap_range idio_24_rd_ranges[] = {
92 regmap_reg_range(0x0, 0xC), regmap_reg_range(0xE, 0xF),
93};
94static const struct regmap_range idio_24_volatile_ranges[] = {
95 regmap_reg_range(0x4, 0xB), regmap_reg_range(0xF, 0xF),
96};
97static const struct regmap_access_table idio_24_wr_table = {
98 .yes_ranges = idio_24_wr_ranges,
99 .n_yes_ranges = ARRAY_SIZE(idio_24_wr_ranges),
100};
101static const struct regmap_access_table idio_24_rd_table = {
102 .yes_ranges = idio_24_rd_ranges,
103 .n_yes_ranges = ARRAY_SIZE(idio_24_rd_ranges),
104};
105static const struct regmap_access_table idio_24_volatile_table = {
106 .yes_ranges = idio_24_volatile_ranges,
107 .n_yes_ranges = ARRAY_SIZE(idio_24_volatile_ranges),
108};
109
110static const struct regmap_config idio_24_regmap_config = {
111 .reg_bits = 8,
112 .reg_stride = 1,
113 .val_bits = 8,
114 .io_port = true,
115 .wr_table = &idio_24_wr_table,
116 .rd_table = &idio_24_rd_table,
117 .volatile_table = &idio_24_volatile_table,
118 .cache_type = REGCACHE_FLAT,
119 .use_raw_spinlock = true,
120};
121
122#define IDIO_24_NGPIO_PER_REG 8
123#define IDIO_24_REGMAP_IRQ(_id) \
124 [24 + _id] = { \
125 .reg_offset = (_id) / IDIO_24_NGPIO_PER_REG, \
126 .mask = BIT((_id) % IDIO_24_NGPIO_PER_REG), \
127 .type = { .types_supported = IRQ_TYPE_EDGE_BOTH }, \
128 }
129#define IDIO_24_IIN_IRQ(_id) IDIO_24_REGMAP_IRQ(_id)
130#define IDIO_24_TTL_IRQ(_id) IDIO_24_REGMAP_IRQ(24 + _id)
131
132static const struct regmap_irq idio_24_regmap_irqs[] = {
133 IDIO_24_IIN_IRQ(0), IDIO_24_IIN_IRQ(1), IDIO_24_IIN_IRQ(2), /* IIN 0-2 */
134 IDIO_24_IIN_IRQ(3), IDIO_24_IIN_IRQ(4), IDIO_24_IIN_IRQ(5), /* IIN 3-5 */
135 IDIO_24_IIN_IRQ(6), IDIO_24_IIN_IRQ(7), IDIO_24_IIN_IRQ(8), /* IIN 6-8 */
136 IDIO_24_IIN_IRQ(9), IDIO_24_IIN_IRQ(10), IDIO_24_IIN_IRQ(11), /* IIN 9-11 */
137 IDIO_24_IIN_IRQ(12), IDIO_24_IIN_IRQ(13), IDIO_24_IIN_IRQ(14), /* IIN 12-14 */
138 IDIO_24_IIN_IRQ(15), IDIO_24_IIN_IRQ(16), IDIO_24_IIN_IRQ(17), /* IIN 15-17 */
139 IDIO_24_IIN_IRQ(18), IDIO_24_IIN_IRQ(19), IDIO_24_IIN_IRQ(20), /* IIN 18-20 */
140 IDIO_24_IIN_IRQ(21), IDIO_24_IIN_IRQ(22), IDIO_24_IIN_IRQ(23), /* IIN 21-23 */
141 IDIO_24_TTL_IRQ(0), IDIO_24_TTL_IRQ(1), IDIO_24_TTL_IRQ(2), /* TTL 0-2 */
142 IDIO_24_TTL_IRQ(3), IDIO_24_TTL_IRQ(4), IDIO_24_TTL_IRQ(5), /* TTL 3-5 */
143 IDIO_24_TTL_IRQ(6), IDIO_24_TTL_IRQ(7), /* TTL 6-7 */
144};
145
146/**
147 * struct idio_24_gpio - GPIO device private data structure
148 * @map: regmap for the device
149 * @lock: synchronization lock to prevent I/O race conditions
150 * @irq_type: type configuration for IRQs
151 */
152struct idio_24_gpio {
153 struct regmap *map;
154 raw_spinlock_t lock;
155 u8 irq_type;
156};
157
158static int idio_24_handle_mask_sync(const int index, const unsigned int mask_buf_def,
159 const unsigned int mask_buf, void *const irq_drv_data)
160{
161 const unsigned int type_mask = COS_ENABLE_BOTH << index;
162 struct idio_24_gpio *const idio24gpio = irq_drv_data;
163 u8 type;
164 int ret;
165
166 raw_spin_lock(&idio24gpio->lock);
167
168 /* if all are masked, then disable interrupts, else set to type */
169 type = (mask_buf == mask_buf_def) ? ~type_mask : idio24gpio->irq_type;
170
171 ret = regmap_update_bits(idio24gpio->map, IDIO_24_COS_ENABLE, type_mask, type);
172
173 raw_spin_unlock(&idio24gpio->lock);
174
175 return ret;
176}
177
178static int idio_24_set_type_config(unsigned int **const buf, const unsigned int type,
179 const struct regmap_irq *const irq_data, const int idx,
180 void *const irq_drv_data)
181{
182 const unsigned int offset = irq_data->reg_offset;
183 const unsigned int rising = COS_ENABLE_RISING << offset;
184 const unsigned int falling = COS_ENABLE_FALLING << offset;
185 const unsigned int mask = COS_ENABLE_BOTH << offset;
186 struct idio_24_gpio *const idio24gpio = irq_drv_data;
187 unsigned int new;
188 unsigned int cos_enable;
189 int ret;
190
191 switch (type) {
192 case IRQ_TYPE_EDGE_RISING:
193 new = rising;
194 break;
195 case IRQ_TYPE_EDGE_FALLING:
196 new = falling;
197 break;
198 case IRQ_TYPE_EDGE_BOTH:
199 new = mask;
200 break;
201 default:
202 return -EINVAL;
203 }
204
205 raw_spin_lock(&idio24gpio->lock);
206
207 /* replace old bitmap with new bitmap */
208 idio24gpio->irq_type = (idio24gpio->irq_type & ~mask) | (new & mask);
209
210 ret = regmap_read(idio24gpio->map, IDIO_24_COS_ENABLE, &cos_enable);
211 if (ret)
212 goto exit_unlock;
213
214 /* if COS is currently enabled then update the edge type */
215 if (cos_enable & mask) {
216 ret = regmap_update_bits(idio24gpio->map, IDIO_24_COS_ENABLE, mask,
217 idio24gpio->irq_type);
218 if (ret)
219 goto exit_unlock;
220 }
221
222exit_unlock:
223 raw_spin_unlock(&idio24gpio->lock);
224
225 return ret;
226}
227
228static int idio_24_reg_mask_xlate(struct gpio_regmap *const gpio, const unsigned int base,
229 const unsigned int offset, unsigned int *const reg,
230 unsigned int *const mask)
231{
232 const unsigned int out_stride = offset / IDIO_24_NGPIO_PER_REG;
233 const unsigned int in_stride = (offset - 24) / IDIO_24_NGPIO_PER_REG;
234 struct regmap *const map = gpio_regmap_get_drvdata(gpio);
235 int err;
236 unsigned int ctrl_reg;
237
238 switch (base) {
239 case IDIO_24_OUT_BASE:
240 *mask = BIT(offset % IDIO_24_NGPIO_PER_REG);
241
242 /* FET Outputs */
243 if (offset < 24) {
244 *reg = IDIO_24_OUT_BASE + out_stride;
245 return 0;
246 }
247
248 /* Isolated Inputs */
249 if (offset < 48) {
250 *reg = IDIO_24_IN_BASE + in_stride;
251 return 0;
252 }
253
254 err = regmap_read(map, IDIO_24_CONTROL_REG, &ctrl_reg);
255 if (err)
256 return err;
257
258 /* TTL/CMOS Outputs */
259 if (ctrl_reg & CONTROL_REG_OUT_MODE) {
260 *reg = IDIO_24_TTLCMOS_OUT_REG;
261 return 0;
262 }
263
264 /* TTL/CMOS Inputs */
265 *reg = IDIO_24_TTLCMOS_IN_REG;
266 return 0;
267 case IDIO_24_CONTROL_REG:
268 /* We can only set direction for TTL/CMOS lines */
269 if (offset < 48)
270 return -ENOTSUPP;
271
272 *reg = IDIO_24_CONTROL_REG;
273 *mask = CONTROL_REG_OUT_MODE;
274 return 0;
275 default:
276 /* Should never reach this path */
277 return -EINVAL;
278 }
279}
280
281#define IDIO_24_NGPIO 56
282static const char *idio_24_names[IDIO_24_NGPIO] = {
283 "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
284 "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
285 "OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
286 "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
287 "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
288 "IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
289 "TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
290};
291
292static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
293{
294 struct device *const dev = &pdev->dev;
295 struct idio_24_gpio *idio24gpio;
296 int err;
297 const size_t pci_plx_bar_index = 1;
298 const size_t pci_bar_index = 2;
299 const char *const name = pci_name(pdev);
300 struct gpio_regmap_config gpio_config = {};
301 void __iomem *pex8311_regs;
302 void __iomem *idio_24_regs;
303 struct regmap *intcsr_map;
304 struct regmap_irq_chip *chip;
305 struct regmap_irq_chip_data *chip_data;
306
307 err = pcim_enable_device(pdev);
308 if (err)
309 return dev_err_probe(dev, err, "Failed to enable PCI device\n");
310
311 pex8311_regs = pcim_iomap_region(pdev, pci_plx_bar_index, "pex8311");
312 if (IS_ERR(pex8311_regs))
313 return dev_err_probe(dev, PTR_ERR(pex8311_regs), "Unable to map PEX 8311 I/O addresses\n");
314
315 idio_24_regs = pcim_iomap_region(pdev, pci_bar_index, name);
316 if (IS_ERR(idio_24_regs))
317 return dev_err_probe(dev, PTR_ERR(idio_24_regs), "Unable to map PCIe-IDIO-24 I/O addresses\n");
318
319 intcsr_map = devm_regmap_init_mmio(dev, pex8311_regs, &pex8311_intcsr_regmap_config);
320 if (IS_ERR(intcsr_map))
321 return dev_err_probe(dev, PTR_ERR(intcsr_map),
322 "Unable to initialize PEX8311 register map\n");
323
324 idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL);
325 if (!idio24gpio)
326 return -ENOMEM;
327
328 idio24gpio->map = devm_regmap_init_mmio(dev, idio_24_regs, &idio_24_regmap_config);
329 if (IS_ERR(idio24gpio->map))
330 return dev_err_probe(dev, PTR_ERR(idio24gpio->map),
331 "Unable to initialize register map\n");
332
333 raw_spin_lock_init(&idio24gpio->lock);
334
335 /* Initialize all IRQ type configuration to IRQ_TYPE_EDGE_BOTH */
336 idio24gpio->irq_type = GENMASK(7, 0);
337
338 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
339 if (!chip)
340 return -ENOMEM;
341
342 chip->name = name;
343 chip->status_base = IDIO_24_COS_STATUS_BASE;
344 chip->mask_base = IDIO_24_COS_ENABLE;
345 chip->ack_base = IDIO_24_COS_STATUS_BASE;
346 chip->num_regs = 4;
347 chip->irqs = idio_24_regmap_irqs;
348 chip->num_irqs = ARRAY_SIZE(idio_24_regmap_irqs);
349 chip->handle_mask_sync = idio_24_handle_mask_sync;
350 chip->set_type_config = idio_24_set_type_config;
351 chip->irq_drv_data = idio24gpio;
352
353 /* Software board reset */
354 err = regmap_write(idio24gpio->map, IDIO_24_SOFT_RESET, 0);
355 if (err)
356 return err;
357 /*
358 * enable PLX PEX8311 internal PCI wire interrupt and local interrupt
359 * input
360 */
361 err = regmap_update_bits(intcsr_map, 0x0, IDIO_24_ENABLE_IRQ, IDIO_24_ENABLE_IRQ);
362 if (err)
363 return err;
364
365 err = devm_regmap_add_irq_chip(dev, idio24gpio->map, pdev->irq, 0, 0, chip, &chip_data);
366 if (err)
367 return dev_err_probe(dev, err, "IRQ registration failed\n");
368
369 gpio_config.parent = dev;
370 gpio_config.regmap = idio24gpio->map;
371 gpio_config.ngpio = IDIO_24_NGPIO;
372 gpio_config.names = idio_24_names;
373 gpio_config.reg_dat_base = GPIO_REGMAP_ADDR(IDIO_24_OUT_BASE);
374 gpio_config.reg_set_base = GPIO_REGMAP_ADDR(IDIO_24_OUT_BASE);
375 gpio_config.reg_dir_out_base = GPIO_REGMAP_ADDR(IDIO_24_CONTROL_REG);
376 gpio_config.ngpio_per_reg = IDIO_24_NGPIO_PER_REG;
377 gpio_config.irq_domain = regmap_irq_get_domain(chip_data);
378 gpio_config.reg_mask_xlate = idio_24_reg_mask_xlate;
379 gpio_config.drvdata = idio24gpio->map;
380
381 return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config));
382}
383
384static const struct pci_device_id idio_24_pci_dev_id[] = {
385 { PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) },
386 { PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) },
387 { 0 }
388};
389MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id);
390
391static struct pci_driver idio_24_driver = {
392 .name = "pcie-idio-24",
393 .id_table = idio_24_pci_dev_id,
394 .probe = idio_24_probe
395};
396
397module_pci_driver(idio_24_driver);
398
399MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
400MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
401MODULE_LICENSE("GPL v2");