1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66struct idio_24_gpio_reg {
67 u8 out0_7;
68 u8 out8_15;
69 u8 out16_23;
70 u8 ttl_out0_7;
71 u8 in0_7;
72 u8 in8_15;
73 u8 in16_23;
74 u8 ttl_in0_7;
75 u8 cos0_7;
76 u8 cos8_15;
77 u8 cos16_23;
78 u8 cos_ttl0_7;
79 u8 ctl;
80 u8 reserved;
81 u8 cos_enable;
82 u8 soft_reset;
83};
84
85
86
87
88
89
90
91
92struct idio_24_gpio {
93 struct gpio_chip chip;
94 raw_spinlock_t lock;
95 struct idio_24_gpio_reg __iomem *reg;
96 unsigned long irq_mask;
97};
98
99static int idio_24_gpio_get_direction(struct gpio_chip *chip,
100 unsigned int offset)
101{
102 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
103 const unsigned long out_mode_mask = BIT(1);
104
105
106 if (offset < 24)
107 return GPIO_LINE_DIRECTION_OUT;
108
109
110 if (offset < 48)
111 return GPIO_LINE_DIRECTION_IN;
112
113
114
115 if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
116 return GPIO_LINE_DIRECTION_OUT;
117
118 return GPIO_LINE_DIRECTION_IN;
119}
120
121static int idio_24_gpio_direction_input(struct gpio_chip *chip,
122 unsigned int offset)
123{
124 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
125 unsigned long flags;
126 unsigned int ctl_state;
127 const unsigned long out_mode_mask = BIT(1);
128
129
130 if (offset > 47) {
131 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
132
133
134 ctl_state = ioread8(&idio24gpio->reg->ctl) & ~out_mode_mask;
135 iowrite8(ctl_state, &idio24gpio->reg->ctl);
136
137 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
138 }
139
140 return 0;
141}
142
143static int idio_24_gpio_direction_output(struct gpio_chip *chip,
144 unsigned int offset, int value)
145{
146 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
147 unsigned long flags;
148 unsigned int ctl_state;
149 const unsigned long out_mode_mask = BIT(1);
150
151
152 if (offset > 47) {
153 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
154
155
156 ctl_state = ioread8(&idio24gpio->reg->ctl) | out_mode_mask;
157 iowrite8(ctl_state, &idio24gpio->reg->ctl);
158
159 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
160 }
161
162 chip->set(chip, offset, value);
163 return 0;
164}
165
166static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset)
167{
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);
171
172
173 if (offset < 8)
174 return !!(ioread8(&idio24gpio->reg->out0_7) & offset_mask);
175
176 if (offset < 16)
177 return !!(ioread8(&idio24gpio->reg->out8_15) & offset_mask);
178
179 if (offset < 24)
180 return !!(ioread8(&idio24gpio->reg->out16_23) & offset_mask);
181
182
183 if (offset < 32)
184 return !!(ioread8(&idio24gpio->reg->in0_7) & offset_mask);
185
186 if (offset < 40)
187 return !!(ioread8(&idio24gpio->reg->in8_15) & offset_mask);
188
189 if (offset < 48)
190 return !!(ioread8(&idio24gpio->reg->in16_23) & offset_mask);
191
192
193 if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
194 return !!(ioread8(&idio24gpio->reg->ttl_out0_7) & offset_mask);
195
196
197 return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask);
198}
199
200static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
201 unsigned long *mask, unsigned long *bits)
202{
203 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
204 unsigned long offset;
205 unsigned long gpio_mask;
206 void __iomem *ports[] = {
207 &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
208 &idio24gpio->reg->out16_23, &idio24gpio->reg->in0_7,
209 &idio24gpio->reg->in8_15, &idio24gpio->reg->in16_23,
210 };
211 size_t index;
212 unsigned long port_state;
213 const unsigned long out_mode_mask = BIT(1);
214
215
216 bitmap_zero(bits, chip->ngpio);
217
218 for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
219 index = offset / 8;
220
221
222 if (index < 6)
223 port_state = ioread8(ports[index]);
224 else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
225 port_state = ioread8(&idio24gpio->reg->ttl_out0_7);
226 else
227 port_state = ioread8(&idio24gpio->reg->ttl_in0_7);
228
229 port_state &= gpio_mask;
230
231 bitmap_set_value8(bits, port_state, offset);
232 }
233
234 return 0;
235}
236
237static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset,
238 int value)
239{
240 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
241 const unsigned long out_mode_mask = BIT(1);
242 void __iomem *base;
243 const unsigned int mask = BIT(offset % 8);
244 unsigned long flags;
245 unsigned int out_state;
246
247
248 if (offset > 23 && offset < 48)
249 return;
250
251
252 if (offset > 47 && !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask))
253 return;
254
255
256 if (offset > 47)
257 base = &idio24gpio->reg->ttl_out0_7;
258
259 else if (offset > 15)
260 base = &idio24gpio->reg->out16_23;
261 else if (offset > 7)
262 base = &idio24gpio->reg->out8_15;
263 else
264 base = &idio24gpio->reg->out0_7;
265
266 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
267
268 if (value)
269 out_state = ioread8(base) | mask;
270 else
271 out_state = ioread8(base) & ~mask;
272
273 iowrite8(out_state, base);
274
275 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
276}
277
278static void idio_24_gpio_set_multiple(struct gpio_chip *chip,
279 unsigned long *mask, unsigned long *bits)
280{
281 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
282 unsigned long offset;
283 unsigned long gpio_mask;
284 void __iomem *ports[] = {
285 &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
286 &idio24gpio->reg->out16_23
287 };
288 size_t index;
289 unsigned long bitmask;
290 unsigned long flags;
291 unsigned long out_state;
292 const unsigned long out_mode_mask = BIT(1);
293
294 for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
295 index = offset / 8;
296
297 bitmask = bitmap_get_value8(bits, offset) & gpio_mask;
298
299 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
300
301
302 if (index < 6) {
303 out_state = ioread8(ports[index]);
304 } else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) {
305 out_state = ioread8(&idio24gpio->reg->ttl_out0_7);
306 } else {
307
308 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
309 continue;
310 }
311
312
313 out_state &= ~gpio_mask;
314 out_state |= bitmask;
315
316
317 if (index < 6)
318 iowrite8(out_state, ports[index]);
319 else
320 iowrite8(out_state, &idio24gpio->reg->ttl_out0_7);
321
322 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
323 }
324}
325
326static void idio_24_irq_ack(struct irq_data *data)
327{
328}
329
330static void idio_24_irq_mask(struct irq_data *data)
331{
332 struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
333 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
334 unsigned long flags;
335 const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
336 unsigned char new_irq_mask;
337 const unsigned long bank_offset = bit_offset/8 * 8;
338 unsigned char cos_enable_state;
339
340 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
341
342 idio24gpio->irq_mask &= BIT(bit_offset);
343 new_irq_mask = idio24gpio->irq_mask >> bank_offset;
344
345 if (!new_irq_mask) {
346 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
347
348
349 cos_enable_state &= ~BIT(bank_offset);
350
351 cos_enable_state &= ~BIT(bank_offset + 4);
352
353 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
354 }
355
356 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
357}
358
359static void idio_24_irq_unmask(struct irq_data *data)
360{
361 struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
362 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
363 unsigned long flags;
364 unsigned char prev_irq_mask;
365 const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
366 const unsigned long bank_offset = bit_offset/8 * 8;
367 unsigned char cos_enable_state;
368
369 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
370
371 prev_irq_mask = idio24gpio->irq_mask >> bank_offset;
372 idio24gpio->irq_mask |= BIT(bit_offset);
373
374 if (!prev_irq_mask) {
375 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
376
377
378 cos_enable_state |= BIT(bank_offset);
379
380 cos_enable_state |= BIT(bank_offset + 4);
381
382 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
383 }
384
385 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
386}
387
388static int idio_24_irq_set_type(struct irq_data *data, unsigned int flow_type)
389{
390
391 if (flow_type != IRQ_TYPE_NONE &&
392 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
393 return -EINVAL;
394
395 return 0;
396}
397
398static struct irq_chip idio_24_irqchip = {
399 .name = "pcie-idio-24",
400 .irq_ack = idio_24_irq_ack,
401 .irq_mask = idio_24_irq_mask,
402 .irq_unmask = idio_24_irq_unmask,
403 .irq_set_type = idio_24_irq_set_type
404};
405
406static irqreturn_t idio_24_irq_handler(int irq, void *dev_id)
407{
408 struct idio_24_gpio *const idio24gpio = dev_id;
409 unsigned long irq_status;
410 struct gpio_chip *const chip = &idio24gpio->chip;
411 unsigned long irq_mask;
412 int gpio;
413
414 raw_spin_lock(&idio24gpio->lock);
415
416
417 irq_status = ioread32(&idio24gpio->reg->cos0_7);
418
419 raw_spin_unlock(&idio24gpio->lock);
420
421
422 if (!irq_status)
423 return IRQ_NONE;
424
425
426 irq_mask = idio24gpio->irq_mask & irq_status;
427
428 for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24)
429 generic_handle_irq(irq_find_mapping(chip->irq.domain,
430 gpio + 24));
431
432 raw_spin_lock(&idio24gpio->lock);
433
434
435 iowrite32(irq_status, &idio24gpio->reg->cos0_7);
436
437 raw_spin_unlock(&idio24gpio->lock);
438
439 return IRQ_HANDLED;
440}
441
442#define IDIO_24_NGPIO 56
443static const char *idio_24_names[IDIO_24_NGPIO] = {
444 "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
445 "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
446 "OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
447 "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
448 "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
449 "IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
450 "TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
451};
452
453static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
454{
455 struct device *const dev = &pdev->dev;
456 struct idio_24_gpio *idio24gpio;
457 int err;
458 const size_t pci_bar_index = 2;
459 const char *const name = pci_name(pdev);
460
461 idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL);
462 if (!idio24gpio)
463 return -ENOMEM;
464
465 err = pcim_enable_device(pdev);
466 if (err) {
467 dev_err(dev, "Failed to enable PCI device (%d)\n", err);
468 return err;
469 }
470
471 err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
472 if (err) {
473 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
474 return err;
475 }
476
477 idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
478
479 idio24gpio->chip.label = name;
480 idio24gpio->chip.parent = dev;
481 idio24gpio->chip.owner = THIS_MODULE;
482 idio24gpio->chip.base = -1;
483 idio24gpio->chip.ngpio = IDIO_24_NGPIO;
484 idio24gpio->chip.names = idio_24_names;
485 idio24gpio->chip.get_direction = idio_24_gpio_get_direction;
486 idio24gpio->chip.direction_input = idio_24_gpio_direction_input;
487 idio24gpio->chip.direction_output = idio_24_gpio_direction_output;
488 idio24gpio->chip.get = idio_24_gpio_get;
489 idio24gpio->chip.get_multiple = idio_24_gpio_get_multiple;
490 idio24gpio->chip.set = idio_24_gpio_set;
491 idio24gpio->chip.set_multiple = idio_24_gpio_set_multiple;
492
493 raw_spin_lock_init(&idio24gpio->lock);
494
495
496 iowrite8(0, &idio24gpio->reg->soft_reset);
497
498 err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio);
499 if (err) {
500 dev_err(dev, "GPIO registering failed (%d)\n", err);
501 return err;
502 }
503
504 err = gpiochip_irqchip_add(&idio24gpio->chip, &idio_24_irqchip, 0,
505 handle_edge_irq, IRQ_TYPE_NONE);
506 if (err) {
507 dev_err(dev, "Could not add irqchip (%d)\n", err);
508 return err;
509 }
510
511 err = devm_request_irq(dev, pdev->irq, idio_24_irq_handler, IRQF_SHARED,
512 name, idio24gpio);
513 if (err) {
514 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
515 return err;
516 }
517
518 return 0;
519}
520
521static const struct pci_device_id idio_24_pci_dev_id[] = {
522 { PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) },
523 { PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) },
524 { 0 }
525};
526MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id);
527
528static struct pci_driver idio_24_driver = {
529 .name = "pcie-idio-24",
530 .id_table = idio_24_pci_dev_id,
531 .probe = idio_24_probe
532};
533
534module_pci_driver(idio_24_driver);
535
536MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
537MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
538MODULE_LICENSE("GPL v2");
539