Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / drivers / gpio / gpio-pcie-idio-24.c
blobf666e2e69074cc382ddf5eb1319b9fc455a7a5be
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
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/bitops.h>
19 #include <linux/device.h>
20 #include <linux/errno.h>
21 #include <linux/gpio/driver.h>
22 #include <linux/interrupt.h>
23 #include <linux/irqdesc.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/pci.h>
27 #include <linux/spinlock.h>
28 #include <linux/types.h>
30 /**
31 * struct idio_24_gpio_reg - GPIO device registers structure
32 * @out0_7: Read: FET Outputs 0-7
33 * Write: FET Outputs 0-7
34 * @out8_15: Read: FET Outputs 8-15
35 * Write: FET Outputs 8-15
36 * @out16_23: Read: FET Outputs 16-23
37 * Write: FET Outputs 16-23
38 * @ttl_out0_7: Read: TTL/CMOS Outputs 0-7
39 * Write: TTL/CMOS Outputs 0-7
40 * @in0_7: Read: Isolated Inputs 0-7
41 * Write: Reserved
42 * @in8_15: Read: Isolated Inputs 8-15
43 * Write: Reserved
44 * @in16_23: Read: Isolated Inputs 16-23
45 * Write: Reserved
46 * @ttl_in0_7: Read: TTL/CMOS Inputs 0-7
47 * Write: Reserved
48 * @cos0_7: Read: COS Status Inputs 0-7
49 * Write: COS Clear Inputs 0-7
50 * @cos8_15: Read: COS Status Inputs 8-15
51 * Write: COS Clear Inputs 8-15
52 * @cos16_23: Read: COS Status Inputs 16-23
53 * Write: COS Clear Inputs 16-23
54 * @cos_ttl0_7: Read: COS Status TTL/CMOS 0-7
55 * Write: COS Clear TTL/CMOS 0-7
56 * @ctl: Read: Control Register
57 * Write: Control Register
58 * @reserved: Read: Reserved
59 * Write: Reserved
60 * @cos_enable: Read: COS Enable
61 * Write: COS Enable
62 * @soft_reset: Read: IRQ Output Pin Status
63 * Write: Software Board Reset
65 struct idio_24_gpio_reg {
66 u8 out0_7;
67 u8 out8_15;
68 u8 out16_23;
69 u8 ttl_out0_7;
70 u8 in0_7;
71 u8 in8_15;
72 u8 in16_23;
73 u8 ttl_in0_7;
74 u8 cos0_7;
75 u8 cos8_15;
76 u8 cos16_23;
77 u8 cos_ttl0_7;
78 u8 ctl;
79 u8 reserved;
80 u8 cos_enable;
81 u8 soft_reset;
84 /**
85 * struct idio_24_gpio - GPIO device private data structure
86 * @chip: instance of the gpio_chip
87 * @lock: synchronization lock to prevent I/O race conditions
88 * @reg: I/O address offset for the GPIO device registers
89 * @irq_mask: I/O bits affected by interrupts
91 struct idio_24_gpio {
92 struct gpio_chip chip;
93 raw_spinlock_t lock;
94 struct idio_24_gpio_reg __iomem *reg;
95 unsigned long irq_mask;
98 static int idio_24_gpio_get_direction(struct gpio_chip *chip,
99 unsigned int offset)
101 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
102 const unsigned long out_mode_mask = BIT(1);
104 /* FET Outputs */
105 if (offset < 24)
106 return 0;
108 /* Isolated Inputs */
109 if (offset < 48)
110 return 1;
112 /* TTL/CMOS I/O */
113 /* OUT MODE = 1 when TTL/CMOS Output Mode is set */
114 return !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask);
117 static int idio_24_gpio_direction_input(struct gpio_chip *chip,
118 unsigned int offset)
120 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
121 unsigned long flags;
122 unsigned int ctl_state;
123 const unsigned long out_mode_mask = BIT(1);
125 /* TTL/CMOS I/O */
126 if (offset > 47) {
127 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
129 /* Clear TTL/CMOS Output Mode */
130 ctl_state = ioread8(&idio24gpio->reg->ctl) & ~out_mode_mask;
131 iowrite8(ctl_state, &idio24gpio->reg->ctl);
133 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
136 return 0;
139 static int idio_24_gpio_direction_output(struct gpio_chip *chip,
140 unsigned int offset, int value)
142 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
143 unsigned long flags;
144 unsigned int ctl_state;
145 const unsigned long out_mode_mask = BIT(1);
147 /* TTL/CMOS I/O */
148 if (offset > 47) {
149 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
151 /* Set TTL/CMOS Output Mode */
152 ctl_state = ioread8(&idio24gpio->reg->ctl) | out_mode_mask;
153 iowrite8(ctl_state, &idio24gpio->reg->ctl);
155 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
158 chip->set(chip, offset, value);
159 return 0;
162 static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset)
164 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
165 const unsigned long offset_mask = BIT(offset % 8);
166 const unsigned long out_mode_mask = BIT(1);
168 /* FET Outputs */
169 if (offset < 8)
170 return !!(ioread8(&idio24gpio->reg->out0_7) & offset_mask);
172 if (offset < 16)
173 return !!(ioread8(&idio24gpio->reg->out8_15) & offset_mask);
175 if (offset < 24)
176 return !!(ioread8(&idio24gpio->reg->out16_23) & offset_mask);
178 /* Isolated Inputs */
179 if (offset < 32)
180 return !!(ioread8(&idio24gpio->reg->in0_7) & offset_mask);
182 if (offset < 40)
183 return !!(ioread8(&idio24gpio->reg->in8_15) & offset_mask);
185 if (offset < 48)
186 return !!(ioread8(&idio24gpio->reg->in16_23) & offset_mask);
188 /* TTL/CMOS Outputs */
189 if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
190 return !!(ioread8(&idio24gpio->reg->ttl_out0_7) & offset_mask);
192 /* TTL/CMOS Inputs */
193 return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask);
196 static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset,
197 int value)
199 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
200 const unsigned long out_mode_mask = BIT(1);
201 void __iomem *base;
202 const unsigned int mask = BIT(offset % 8);
203 unsigned long flags;
204 unsigned int out_state;
206 /* Isolated Inputs */
207 if (offset > 23 && offset < 48)
208 return;
210 /* TTL/CMOS Inputs */
211 if (offset > 47 && !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask))
212 return;
214 /* TTL/CMOS Outputs */
215 if (offset > 47)
216 base = &idio24gpio->reg->ttl_out0_7;
217 /* FET Outputs */
218 else if (offset > 15)
219 base = &idio24gpio->reg->out16_23;
220 else if (offset > 7)
221 base = &idio24gpio->reg->out8_15;
222 else
223 base = &idio24gpio->reg->out0_7;
225 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
227 if (value)
228 out_state = ioread8(base) | mask;
229 else
230 out_state = ioread8(base) & ~mask;
232 iowrite8(out_state, base);
234 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
237 static void idio_24_irq_ack(struct irq_data *data)
241 static void idio_24_irq_mask(struct irq_data *data)
243 struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
244 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
245 unsigned long flags;
246 const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
247 unsigned char new_irq_mask;
248 const unsigned long bank_offset = bit_offset/8 * 8;
249 unsigned char cos_enable_state;
251 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
253 idio24gpio->irq_mask &= BIT(bit_offset);
254 new_irq_mask = idio24gpio->irq_mask >> bank_offset;
256 if (!new_irq_mask) {
257 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
259 /* Disable Rising Edge detection */
260 cos_enable_state &= ~BIT(bank_offset);
261 /* Disable Falling Edge detection */
262 cos_enable_state &= ~BIT(bank_offset + 4);
264 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
267 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
270 static void idio_24_irq_unmask(struct irq_data *data)
272 struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
273 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
274 unsigned long flags;
275 unsigned char prev_irq_mask;
276 const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
277 const unsigned long bank_offset = bit_offset/8 * 8;
278 unsigned char cos_enable_state;
280 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
282 prev_irq_mask = idio24gpio->irq_mask >> bank_offset;
283 idio24gpio->irq_mask |= BIT(bit_offset);
285 if (!prev_irq_mask) {
286 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
288 /* Enable Rising Edge detection */
289 cos_enable_state |= BIT(bank_offset);
290 /* Enable Falling Edge detection */
291 cos_enable_state |= BIT(bank_offset + 4);
293 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
296 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
299 static int idio_24_irq_set_type(struct irq_data *data, unsigned int flow_type)
301 /* The only valid irq types are none and both-edges */
302 if (flow_type != IRQ_TYPE_NONE &&
303 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
304 return -EINVAL;
306 return 0;
309 static struct irq_chip idio_24_irqchip = {
310 .name = "pcie-idio-24",
311 .irq_ack = idio_24_irq_ack,
312 .irq_mask = idio_24_irq_mask,
313 .irq_unmask = idio_24_irq_unmask,
314 .irq_set_type = idio_24_irq_set_type
317 static irqreturn_t idio_24_irq_handler(int irq, void *dev_id)
319 struct idio_24_gpio *const idio24gpio = dev_id;
320 unsigned long irq_status;
321 struct gpio_chip *const chip = &idio24gpio->chip;
322 unsigned long irq_mask;
323 int gpio;
325 raw_spin_lock(&idio24gpio->lock);
327 /* Read Change-Of-State status */
328 irq_status = ioread32(&idio24gpio->reg->cos0_7);
330 raw_spin_unlock(&idio24gpio->lock);
332 /* Make sure our device generated IRQ */
333 if (!irq_status)
334 return IRQ_NONE;
336 /* Handle only unmasked IRQ */
337 irq_mask = idio24gpio->irq_mask & irq_status;
339 for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24)
340 generic_handle_irq(irq_find_mapping(chip->irq.domain,
341 gpio + 24));
343 raw_spin_lock(&idio24gpio->lock);
345 /* Clear Change-Of-State status */
346 iowrite32(irq_status, &idio24gpio->reg->cos0_7);
348 raw_spin_unlock(&idio24gpio->lock);
350 return IRQ_HANDLED;
353 #define IDIO_24_NGPIO 56
354 static const char *idio_24_names[IDIO_24_NGPIO] = {
355 "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
356 "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
357 "OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
358 "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
359 "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
360 "IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
361 "TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
364 static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
366 struct device *const dev = &pdev->dev;
367 struct idio_24_gpio *idio24gpio;
368 int err;
369 const size_t pci_bar_index = 2;
370 const char *const name = pci_name(pdev);
372 idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL);
373 if (!idio24gpio)
374 return -ENOMEM;
376 err = pcim_enable_device(pdev);
377 if (err) {
378 dev_err(dev, "Failed to enable PCI device (%d)\n", err);
379 return err;
382 err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
383 if (err) {
384 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
385 return err;
388 idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
390 idio24gpio->chip.label = name;
391 idio24gpio->chip.parent = dev;
392 idio24gpio->chip.owner = THIS_MODULE;
393 idio24gpio->chip.base = -1;
394 idio24gpio->chip.ngpio = IDIO_24_NGPIO;
395 idio24gpio->chip.names = idio_24_names;
396 idio24gpio->chip.get_direction = idio_24_gpio_get_direction;
397 idio24gpio->chip.direction_input = idio_24_gpio_direction_input;
398 idio24gpio->chip.direction_output = idio_24_gpio_direction_output;
399 idio24gpio->chip.get = idio_24_gpio_get;
400 idio24gpio->chip.set = idio_24_gpio_set;
402 raw_spin_lock_init(&idio24gpio->lock);
404 /* Software board reset */
405 iowrite8(0, &idio24gpio->reg->soft_reset);
407 err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio);
408 if (err) {
409 dev_err(dev, "GPIO registering failed (%d)\n", err);
410 return err;
413 err = gpiochip_irqchip_add(&idio24gpio->chip, &idio_24_irqchip, 0,
414 handle_edge_irq, IRQ_TYPE_NONE);
415 if (err) {
416 dev_err(dev, "Could not add irqchip (%d)\n", err);
417 return err;
420 err = devm_request_irq(dev, pdev->irq, idio_24_irq_handler, IRQF_SHARED,
421 name, idio24gpio);
422 if (err) {
423 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
424 return err;
427 return 0;
430 static const struct pci_device_id idio_24_pci_dev_id[] = {
431 { PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) },
432 { PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) },
433 { 0 }
435 MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id);
437 static struct pci_driver idio_24_driver = {
438 .name = "pcie-idio-24",
439 .id_table = idio_24_pci_dev_id,
440 .probe = idio_24_probe
443 module_pci_driver(idio_24_driver);
445 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
446 MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
447 MODULE_LICENSE("GPL v2");