Merge tag 'io_uring-6.5-2023-07-28' of git://git.kernel.dk/linux
[linux-2.6-microblaze.git] / drivers / gpio / gpio-pci-idio-16.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * GPIO driver for the ACCES PCI-IDIO-16
4  * Copyright (C) 2017 William Breathitt Gray
5  */
6 #include <linux/bits.h>
7 #include <linux/device.h>
8 #include <linux/errno.h>
9 #include <linux/gpio/driver.h>
10 #include <linux/interrupt.h>
11 #include <linux/irqdesc.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/pci.h>
15 #include <linux/spinlock.h>
16 #include <linux/types.h>
17
18 #include "gpio-idio-16.h"
19
20 /**
21  * struct idio_16_gpio - GPIO device private data structure
22  * @chip:       instance of the gpio_chip
23  * @lock:       synchronization lock to prevent I/O race conditions
24  * @reg:        I/O address offset for the GPIO device registers
25  * @state:      ACCES IDIO-16 device state
26  * @irq_mask:   I/O bits affected by interrupts
27  */
28 struct idio_16_gpio {
29         struct gpio_chip chip;
30         raw_spinlock_t lock;
31         struct idio_16 __iomem *reg;
32         struct idio_16_state state;
33         unsigned long irq_mask;
34 };
35
36 static int idio_16_gpio_get_direction(struct gpio_chip *chip,
37         unsigned int offset)
38 {
39         if (idio_16_get_direction(offset))
40                 return GPIO_LINE_DIRECTION_IN;
41
42         return GPIO_LINE_DIRECTION_OUT;
43 }
44
45 static int idio_16_gpio_direction_input(struct gpio_chip *chip,
46         unsigned int offset)
47 {
48         return 0;
49 }
50
51 static int idio_16_gpio_direction_output(struct gpio_chip *chip,
52         unsigned int offset, int value)
53 {
54         chip->set(chip, offset, value);
55         return 0;
56 }
57
58 static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
59 {
60         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
61
62         return idio_16_get(idio16gpio->reg, &idio16gpio->state, offset);
63 }
64
65 static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
66         unsigned long *mask, unsigned long *bits)
67 {
68         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
69
70         idio_16_get_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
71         return 0;
72 }
73
74 static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
75         int value)
76 {
77         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
78
79         idio_16_set(idio16gpio->reg, &idio16gpio->state, offset, value);
80 }
81
82 static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
83         unsigned long *mask, unsigned long *bits)
84 {
85         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
86
87         idio_16_set_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
88 }
89
90 static void idio_16_irq_ack(struct irq_data *data)
91 {
92 }
93
94 static void idio_16_irq_mask(struct irq_data *data)
95 {
96         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
97         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
98         const unsigned long mask = BIT(irqd_to_hwirq(data));
99         unsigned long flags;
100
101         idio16gpio->irq_mask &= ~mask;
102
103         if (!idio16gpio->irq_mask) {
104                 raw_spin_lock_irqsave(&idio16gpio->lock, flags);
105
106                 iowrite8(0, &idio16gpio->reg->irq_ctl);
107
108                 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
109         }
110
111         gpiochip_disable_irq(chip, irqd_to_hwirq(data));
112 }
113
114 static void idio_16_irq_unmask(struct irq_data *data)
115 {
116         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
117         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
118         const unsigned long mask = BIT(irqd_to_hwirq(data));
119         const unsigned long prev_irq_mask = idio16gpio->irq_mask;
120         unsigned long flags;
121
122         gpiochip_enable_irq(chip, irqd_to_hwirq(data));
123
124         idio16gpio->irq_mask |= mask;
125
126         if (!prev_irq_mask) {
127                 raw_spin_lock_irqsave(&idio16gpio->lock, flags);
128
129                 ioread8(&idio16gpio->reg->irq_ctl);
130
131                 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
132         }
133 }
134
135 static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
136 {
137         /* The only valid irq types are none and both-edges */
138         if (flow_type != IRQ_TYPE_NONE &&
139                 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
140                 return -EINVAL;
141
142         return 0;
143 }
144
145 static const struct irq_chip idio_16_irqchip = {
146         .name = "pci-idio-16",
147         .irq_ack = idio_16_irq_ack,
148         .irq_mask = idio_16_irq_mask,
149         .irq_unmask = idio_16_irq_unmask,
150         .irq_set_type = idio_16_irq_set_type,
151         .flags = IRQCHIP_IMMUTABLE,
152         GPIOCHIP_IRQ_RESOURCE_HELPERS,
153 };
154
155 static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
156 {
157         struct idio_16_gpio *const idio16gpio = dev_id;
158         unsigned int irq_status;
159         struct gpio_chip *const chip = &idio16gpio->chip;
160         int gpio;
161
162         raw_spin_lock(&idio16gpio->lock);
163
164         irq_status = ioread8(&idio16gpio->reg->irq_status);
165
166         raw_spin_unlock(&idio16gpio->lock);
167
168         /* Make sure our device generated IRQ */
169         if (!(irq_status & 0x3) || !(irq_status & 0x4))
170                 return IRQ_NONE;
171
172         for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
173                 generic_handle_domain_irq(chip->irq.domain, gpio);
174
175         raw_spin_lock(&idio16gpio->lock);
176
177         /* Clear interrupt */
178         iowrite8(0, &idio16gpio->reg->in0_7);
179
180         raw_spin_unlock(&idio16gpio->lock);
181
182         return IRQ_HANDLED;
183 }
184
185 #define IDIO_16_NGPIO 32
186 static const char *idio_16_names[IDIO_16_NGPIO] = {
187         "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
188         "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
189         "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
190         "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
191 };
192
193 static int idio_16_irq_init_hw(struct gpio_chip *gc)
194 {
195         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc);
196
197         /* Disable IRQ by default and clear any pending interrupt */
198         iowrite8(0, &idio16gpio->reg->irq_ctl);
199         iowrite8(0, &idio16gpio->reg->in0_7);
200
201         return 0;
202 }
203
204 static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
205 {
206         struct device *const dev = &pdev->dev;
207         struct idio_16_gpio *idio16gpio;
208         int err;
209         const size_t pci_bar_index = 2;
210         const char *const name = pci_name(pdev);
211         struct gpio_irq_chip *girq;
212
213         idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
214         if (!idio16gpio)
215                 return -ENOMEM;
216
217         err = pcim_enable_device(pdev);
218         if (err) {
219                 dev_err(dev, "Failed to enable PCI device (%d)\n", err);
220                 return err;
221         }
222
223         err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
224         if (err) {
225                 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
226                 return err;
227         }
228
229         idio16gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
230
231         /* Deactivate input filters */
232         iowrite8(0, &idio16gpio->reg->filter_ctl);
233
234         idio16gpio->chip.label = name;
235         idio16gpio->chip.parent = dev;
236         idio16gpio->chip.owner = THIS_MODULE;
237         idio16gpio->chip.base = -1;
238         idio16gpio->chip.ngpio = IDIO_16_NGPIO;
239         idio16gpio->chip.names = idio_16_names;
240         idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
241         idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
242         idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
243         idio16gpio->chip.get = idio_16_gpio_get;
244         idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
245         idio16gpio->chip.set = idio_16_gpio_set;
246         idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
247
248         idio_16_state_init(&idio16gpio->state);
249
250         girq = &idio16gpio->chip.irq;
251         gpio_irq_chip_set_chip(girq, &idio_16_irqchip);
252         /* This will let us handle the parent IRQ in the driver */
253         girq->parent_handler = NULL;
254         girq->num_parents = 0;
255         girq->parents = NULL;
256         girq->default_type = IRQ_TYPE_NONE;
257         girq->handler = handle_edge_irq;
258         girq->init_hw = idio_16_irq_init_hw;
259
260         raw_spin_lock_init(&idio16gpio->lock);
261
262         err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
263         if (err) {
264                 dev_err(dev, "GPIO registering failed (%d)\n", err);
265                 return err;
266         }
267
268         err = devm_request_irq(dev, pdev->irq, idio_16_irq_handler, IRQF_SHARED,
269                 name, idio16gpio);
270         if (err) {
271                 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
272                 return err;
273         }
274
275         return 0;
276 }
277
278 static const struct pci_device_id idio_16_pci_dev_id[] = {
279         { PCI_DEVICE(0x494F, 0x0DC8) }, { 0 }
280 };
281 MODULE_DEVICE_TABLE(pci, idio_16_pci_dev_id);
282
283 static struct pci_driver idio_16_driver = {
284         .name = "pci-idio-16",
285         .id_table = idio_16_pci_dev_id,
286         .probe = idio_16_probe
287 };
288
289 module_pci_driver(idio_16_driver);
290
291 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
292 MODULE_DESCRIPTION("ACCES PCI-IDIO-16 GPIO driver");
293 MODULE_LICENSE("GPL v2");
294 MODULE_IMPORT_NS(GPIO_IDIO_16);