Merge tag 'tag-chrome-platform-for-v4.21' of git://git.kernel.org/pub/scm/linux/kerne...
[sfrench/cifs-2.6.git] / drivers / gpio / gpio-pci-idio-16.c
1 /*
2  * GPIO driver for the ACCES PCI-IDIO-16
3  * Copyright (C) 2017 William Breathitt Gray
4  *
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.
8  *
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.
13  */
14 #include <linux/bitmap.h>
15 #include <linux/bitops.h>
16 #include <linux/device.h>
17 #include <linux/errno.h>
18 #include <linux/gpio/driver.h>
19 #include <linux/interrupt.h>
20 #include <linux/irqdesc.h>
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/pci.h>
24 #include <linux/spinlock.h>
25 #include <linux/types.h>
26
27 /**
28  * struct idio_16_gpio_reg - GPIO device registers structure
29  * @out0_7:     Read: FET Drive Outputs 0-7
30  *              Write: FET Drive Outputs 0-7
31  * @in0_7:      Read: Isolated Inputs 0-7
32  *              Write: Clear Interrupt
33  * @irq_ctl:    Read: Enable IRQ
34  *              Write: Disable IRQ
35  * @filter_ctl: Read: Activate Input Filters 0-15
36  *              Write: Deactivate Input Filters 0-15
37  * @out8_15:    Read: FET Drive Outputs 8-15
38  *              Write: FET Drive Outputs 8-15
39  * @in8_15:     Read: Isolated Inputs 8-15
40  *              Write: Unused
41  * @irq_status: Read: Interrupt status
42  *              Write: Unused
43  */
44 struct idio_16_gpio_reg {
45         u8 out0_7;
46         u8 in0_7;
47         u8 irq_ctl;
48         u8 filter_ctl;
49         u8 out8_15;
50         u8 in8_15;
51         u8 irq_status;
52 };
53
54 /**
55  * struct idio_16_gpio - GPIO device private data structure
56  * @chip:       instance of the gpio_chip
57  * @lock:       synchronization lock to prevent I/O race conditions
58  * @reg:        I/O address offset for the GPIO device registers
59  * @irq_mask:   I/O bits affected by interrupts
60  */
61 struct idio_16_gpio {
62         struct gpio_chip chip;
63         raw_spinlock_t lock;
64         struct idio_16_gpio_reg __iomem *reg;
65         unsigned long irq_mask;
66 };
67
68 static int idio_16_gpio_get_direction(struct gpio_chip *chip,
69         unsigned int offset)
70 {
71         if (offset > 15)
72                 return 1;
73
74         return 0;
75 }
76
77 static int idio_16_gpio_direction_input(struct gpio_chip *chip,
78         unsigned int offset)
79 {
80         return 0;
81 }
82
83 static int idio_16_gpio_direction_output(struct gpio_chip *chip,
84         unsigned int offset, int value)
85 {
86         chip->set(chip, offset, value);
87         return 0;
88 }
89
90 static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
91 {
92         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
93         unsigned long mask = BIT(offset);
94
95         if (offset < 8)
96                 return !!(ioread8(&idio16gpio->reg->out0_7) & mask);
97
98         if (offset < 16)
99                 return !!(ioread8(&idio16gpio->reg->out8_15) & (mask >> 8));
100
101         if (offset < 24)
102                 return !!(ioread8(&idio16gpio->reg->in0_7) & (mask >> 16));
103
104         return !!(ioread8(&idio16gpio->reg->in8_15) & (mask >> 24));
105 }
106
107 static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
108         unsigned long *mask, unsigned long *bits)
109 {
110         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
111         size_t i;
112         const unsigned int gpio_reg_size = 8;
113         unsigned int bits_offset;
114         size_t word_index;
115         unsigned int word_offset;
116         unsigned long word_mask;
117         const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
118         unsigned long port_state;
119         void __iomem *ports[] = {
120                 &idio16gpio->reg->out0_7, &idio16gpio->reg->out8_15,
121                 &idio16gpio->reg->in0_7, &idio16gpio->reg->in8_15,
122         };
123
124         /* clear bits array to a clean slate */
125         bitmap_zero(bits, chip->ngpio);
126
127         /* get bits are evaluated a gpio port register at a time */
128         for (i = 0; i < ARRAY_SIZE(ports); i++) {
129                 /* gpio offset in bits array */
130                 bits_offset = i * gpio_reg_size;
131
132                 /* word index for bits array */
133                 word_index = BIT_WORD(bits_offset);
134
135                 /* gpio offset within current word of bits array */
136                 word_offset = bits_offset % BITS_PER_LONG;
137
138                 /* mask of get bits for current gpio within current word */
139                 word_mask = mask[word_index] & (port_mask << word_offset);
140                 if (!word_mask) {
141                         /* no get bits in this port so skip to next one */
142                         continue;
143                 }
144
145                 /* read bits from current gpio port */
146                 port_state = ioread8(ports[i]);
147
148                 /* store acquired bits at respective bits array offset */
149                 bits[word_index] |= (port_state << word_offset) & word_mask;
150         }
151
152         return 0;
153 }
154
155 static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
156         int value)
157 {
158         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
159         unsigned int mask = BIT(offset);
160         void __iomem *base;
161         unsigned long flags;
162         unsigned int out_state;
163
164         if (offset > 15)
165                 return;
166
167         if (offset > 7) {
168                 mask >>= 8;
169                 base = &idio16gpio->reg->out8_15;
170         } else
171                 base = &idio16gpio->reg->out0_7;
172
173         raw_spin_lock_irqsave(&idio16gpio->lock, flags);
174
175         if (value)
176                 out_state = ioread8(base) | mask;
177         else
178                 out_state = ioread8(base) & ~mask;
179
180         iowrite8(out_state, base);
181
182         raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
183 }
184
185 static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
186         unsigned long *mask, unsigned long *bits)
187 {
188         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
189         unsigned long flags;
190         unsigned int out_state;
191
192         raw_spin_lock_irqsave(&idio16gpio->lock, flags);
193
194         /* process output lines 0-7 */
195         if (*mask & 0xFF) {
196                 out_state = ioread8(&idio16gpio->reg->out0_7) & ~*mask;
197                 out_state |= *mask & *bits;
198                 iowrite8(out_state, &idio16gpio->reg->out0_7);
199         }
200
201         /* shift to next output line word */
202         *mask >>= 8;
203
204         /* process output lines 8-15 */
205         if (*mask & 0xFF) {
206                 *bits >>= 8;
207                 out_state = ioread8(&idio16gpio->reg->out8_15) & ~*mask;
208                 out_state |= *mask & *bits;
209                 iowrite8(out_state, &idio16gpio->reg->out8_15);
210         }
211
212         raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
213 }
214
215 static void idio_16_irq_ack(struct irq_data *data)
216 {
217 }
218
219 static void idio_16_irq_mask(struct irq_data *data)
220 {
221         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
222         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
223         const unsigned long mask = BIT(irqd_to_hwirq(data));
224         unsigned long flags;
225
226         idio16gpio->irq_mask &= ~mask;
227
228         if (!idio16gpio->irq_mask) {
229                 raw_spin_lock_irqsave(&idio16gpio->lock, flags);
230
231                 iowrite8(0, &idio16gpio->reg->irq_ctl);
232
233                 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
234         }
235 }
236
237 static void idio_16_irq_unmask(struct irq_data *data)
238 {
239         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
240         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
241         const unsigned long mask = BIT(irqd_to_hwirq(data));
242         const unsigned long prev_irq_mask = idio16gpio->irq_mask;
243         unsigned long flags;
244
245         idio16gpio->irq_mask |= mask;
246
247         if (!prev_irq_mask) {
248                 raw_spin_lock_irqsave(&idio16gpio->lock, flags);
249
250                 ioread8(&idio16gpio->reg->irq_ctl);
251
252                 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
253         }
254 }
255
256 static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
257 {
258         /* The only valid irq types are none and both-edges */
259         if (flow_type != IRQ_TYPE_NONE &&
260                 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
261                 return -EINVAL;
262
263         return 0;
264 }
265
266 static struct irq_chip idio_16_irqchip = {
267         .name = "pci-idio-16",
268         .irq_ack = idio_16_irq_ack,
269         .irq_mask = idio_16_irq_mask,
270         .irq_unmask = idio_16_irq_unmask,
271         .irq_set_type = idio_16_irq_set_type
272 };
273
274 static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
275 {
276         struct idio_16_gpio *const idio16gpio = dev_id;
277         unsigned int irq_status;
278         struct gpio_chip *const chip = &idio16gpio->chip;
279         int gpio;
280
281         raw_spin_lock(&idio16gpio->lock);
282
283         irq_status = ioread8(&idio16gpio->reg->irq_status);
284
285         raw_spin_unlock(&idio16gpio->lock);
286
287         /* Make sure our device generated IRQ */
288         if (!(irq_status & 0x3) || !(irq_status & 0x4))
289                 return IRQ_NONE;
290
291         for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
292                 generic_handle_irq(irq_find_mapping(chip->irq.domain, gpio));
293
294         raw_spin_lock(&idio16gpio->lock);
295
296         /* Clear interrupt */
297         iowrite8(0, &idio16gpio->reg->in0_7);
298
299         raw_spin_unlock(&idio16gpio->lock);
300
301         return IRQ_HANDLED;
302 }
303
304 #define IDIO_16_NGPIO 32
305 static const char *idio_16_names[IDIO_16_NGPIO] = {
306         "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
307         "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
308         "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
309         "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
310 };
311
312 static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
313 {
314         struct device *const dev = &pdev->dev;
315         struct idio_16_gpio *idio16gpio;
316         int err;
317         const size_t pci_bar_index = 2;
318         const char *const name = pci_name(pdev);
319
320         idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
321         if (!idio16gpio)
322                 return -ENOMEM;
323
324         err = pcim_enable_device(pdev);
325         if (err) {
326                 dev_err(dev, "Failed to enable PCI device (%d)\n", err);
327                 return err;
328         }
329
330         err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
331         if (err) {
332                 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
333                 return err;
334         }
335
336         idio16gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
337
338         /* Deactivate input filters */
339         iowrite8(0, &idio16gpio->reg->filter_ctl);
340
341         idio16gpio->chip.label = name;
342         idio16gpio->chip.parent = dev;
343         idio16gpio->chip.owner = THIS_MODULE;
344         idio16gpio->chip.base = -1;
345         idio16gpio->chip.ngpio = IDIO_16_NGPIO;
346         idio16gpio->chip.names = idio_16_names;
347         idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
348         idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
349         idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
350         idio16gpio->chip.get = idio_16_gpio_get;
351         idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
352         idio16gpio->chip.set = idio_16_gpio_set;
353         idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
354
355         raw_spin_lock_init(&idio16gpio->lock);
356
357         err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
358         if (err) {
359                 dev_err(dev, "GPIO registering failed (%d)\n", err);
360                 return err;
361         }
362
363         /* Disable IRQ by default and clear any pending interrupt */
364         iowrite8(0, &idio16gpio->reg->irq_ctl);
365         iowrite8(0, &idio16gpio->reg->in0_7);
366
367         err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0,
368                 handle_edge_irq, IRQ_TYPE_NONE);
369         if (err) {
370                 dev_err(dev, "Could not add irqchip (%d)\n", err);
371                 return err;
372         }
373
374         err = devm_request_irq(dev, pdev->irq, idio_16_irq_handler, IRQF_SHARED,
375                 name, idio16gpio);
376         if (err) {
377                 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
378                 return err;
379         }
380
381         return 0;
382 }
383
384 static const struct pci_device_id idio_16_pci_dev_id[] = {
385         { PCI_DEVICE(0x494F, 0x0DC8) }, { 0 }
386 };
387 MODULE_DEVICE_TABLE(pci, idio_16_pci_dev_id);
388
389 static struct pci_driver idio_16_driver = {
390         .name = "pci-idio-16",
391         .id_table = idio_16_pci_dev_id,
392         .probe = idio_16_probe
393 };
394
395 module_pci_driver(idio_16_driver);
396
397 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
398 MODULE_DESCRIPTION("ACCES PCI-IDIO-16 GPIO driver");
399 MODULE_LICENSE("GPL v2");