GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / gpio / gpio-104-idi-48.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * GPIO driver for the ACCES 104-IDI-48 family
4  * Copyright (C) 2015 William Breathitt Gray
5  *
6  * This driver supports the following ACCES devices: 104-IDI-48A,
7  * 104-IDI-48AC, 104-IDI-48B, and 104-IDI-48BC.
8  */
9 #include <linux/bitmap.h>
10 #include <linux/bitops.h>
11 #include <linux/device.h>
12 #include <linux/errno.h>
13 #include <linux/gpio/driver.h>
14 #include <linux/io.h>
15 #include <linux/ioport.h>
16 #include <linux/interrupt.h>
17 #include <linux/irqdesc.h>
18 #include <linux/isa.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/moduleparam.h>
22 #include <linux/spinlock.h>
23
24 #define IDI_48_EXTENT 8
25 #define MAX_NUM_IDI_48 max_num_isa_dev(IDI_48_EXTENT)
26
27 static unsigned int base[MAX_NUM_IDI_48];
28 static unsigned int num_idi_48;
29 module_param_hw_array(base, uint, ioport, &num_idi_48, 0);
30 MODULE_PARM_DESC(base, "ACCES 104-IDI-48 base addresses");
31
32 static unsigned int irq[MAX_NUM_IDI_48];
33 module_param_hw_array(irq, uint, irq, NULL, 0);
34 MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
35
36 /**
37  * struct idi_48_gpio - GPIO device private data structure
38  * @chip:       instance of the gpio_chip
39  * @lock:       synchronization lock to prevent I/O race conditions
40  * @ack_lock:   synchronization lock to prevent IRQ handler race conditions
41  * @irq_mask:   input bits affected by interrupts
42  * @base:       base port address of the GPIO device
43  * @cos_enb:    Change-Of-State IRQ enable boundaries mask
44  */
45 struct idi_48_gpio {
46         struct gpio_chip chip;
47         raw_spinlock_t lock;
48         spinlock_t ack_lock;
49         unsigned char irq_mask[6];
50         void __iomem *base;
51         unsigned char cos_enb;
52 };
53
54 static int idi_48_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
55 {
56         return GPIO_LINE_DIRECTION_IN;
57 }
58
59 static int idi_48_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
60 {
61         return 0;
62 }
63
64 static int idi_48_gpio_get(struct gpio_chip *chip, unsigned offset)
65 {
66         struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
67         unsigned i;
68         static const unsigned int register_offset[6] = { 0, 1, 2, 4, 5, 6 };
69         void __iomem *port_addr;
70         unsigned mask;
71
72         for (i = 0; i < 48; i += 8)
73                 if (offset < i + 8) {
74                         port_addr = idi48gpio->base + register_offset[i / 8];
75                         mask = BIT(offset - i);
76
77                         return !!(ioread8(port_addr) & mask);
78                 }
79
80         /* The following line should never execute since offset < 48 */
81         return 0;
82 }
83
84 static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
85         unsigned long *bits)
86 {
87         struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
88         unsigned long offset;
89         unsigned long gpio_mask;
90         static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
91         void __iomem *port_addr;
92         unsigned long port_state;
93
94         /* clear bits array to a clean slate */
95         bitmap_zero(bits, chip->ngpio);
96
97         for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
98                 port_addr = idi48gpio->base + ports[offset / 8];
99                 port_state = ioread8(port_addr) & gpio_mask;
100
101                 bitmap_set_value8(bits, port_state, offset);
102         }
103
104         return 0;
105 }
106
107 static void idi_48_irq_ack(struct irq_data *data)
108 {
109 }
110
111 static void idi_48_irq_mask(struct irq_data *data)
112 {
113         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
114         struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
115         const unsigned offset = irqd_to_hwirq(data);
116         unsigned i;
117         unsigned mask;
118         unsigned boundary;
119         unsigned long flags;
120
121         for (i = 0; i < 48; i += 8)
122                 if (offset < i + 8) {
123                         mask = BIT(offset - i);
124                         boundary = i / 8;
125
126                         idi48gpio->irq_mask[boundary] &= ~mask;
127
128                         if (!idi48gpio->irq_mask[boundary]) {
129                                 idi48gpio->cos_enb &= ~BIT(boundary);
130
131                                 raw_spin_lock_irqsave(&idi48gpio->lock, flags);
132
133                                 iowrite8(idi48gpio->cos_enb, idi48gpio->base + 7);
134
135                                 raw_spin_unlock_irqrestore(&idi48gpio->lock, flags);
136                         }
137
138                         return;
139                 }
140 }
141
142 static void idi_48_irq_unmask(struct irq_data *data)
143 {
144         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
145         struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
146         const unsigned offset = irqd_to_hwirq(data);
147         unsigned i;
148         unsigned mask;
149         unsigned boundary;
150         unsigned prev_irq_mask;
151         unsigned long flags;
152
153         for (i = 0; i < 48; i += 8)
154                 if (offset < i + 8) {
155                         mask = BIT(offset - i);
156                         boundary = i / 8;
157                         prev_irq_mask = idi48gpio->irq_mask[boundary];
158
159                         idi48gpio->irq_mask[boundary] |= mask;
160
161                         if (!prev_irq_mask) {
162                                 idi48gpio->cos_enb |= BIT(boundary);
163
164                                 raw_spin_lock_irqsave(&idi48gpio->lock, flags);
165
166                                 iowrite8(idi48gpio->cos_enb, idi48gpio->base + 7);
167
168                                 raw_spin_unlock_irqrestore(&idi48gpio->lock, flags);
169                         }
170
171                         return;
172                 }
173 }
174
175 static int idi_48_irq_set_type(struct irq_data *data, unsigned flow_type)
176 {
177         /* The only valid irq types are none and both-edges */
178         if (flow_type != IRQ_TYPE_NONE &&
179                 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
180                 return -EINVAL;
181
182         return 0;
183 }
184
185 static struct irq_chip idi_48_irqchip = {
186         .name = "104-idi-48",
187         .irq_ack = idi_48_irq_ack,
188         .irq_mask = idi_48_irq_mask,
189         .irq_unmask = idi_48_irq_unmask,
190         .irq_set_type = idi_48_irq_set_type
191 };
192
193 static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
194 {
195         struct idi_48_gpio *const idi48gpio = dev_id;
196         unsigned long cos_status;
197         unsigned long boundary;
198         unsigned long irq_mask;
199         unsigned long bit_num;
200         unsigned long gpio;
201         struct gpio_chip *const chip = &idi48gpio->chip;
202
203         spin_lock(&idi48gpio->ack_lock);
204
205         raw_spin_lock(&idi48gpio->lock);
206
207         cos_status = ioread8(idi48gpio->base + 7);
208
209         raw_spin_unlock(&idi48gpio->lock);
210
211         /* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */
212         if (cos_status & BIT(6)) {
213                 spin_unlock(&idi48gpio->ack_lock);
214                 return IRQ_NONE;
215         }
216
217         /* Bit 0-5 indicate which Change-Of-State boundary triggered the IRQ */
218         cos_status &= 0x3F;
219
220         for_each_set_bit(boundary, &cos_status, 6) {
221                 irq_mask = idi48gpio->irq_mask[boundary];
222
223                 for_each_set_bit(bit_num, &irq_mask, 8) {
224                         gpio = bit_num + boundary * 8;
225
226                         generic_handle_domain_irq(chip->irq.domain,
227                                                   gpio);
228                 }
229         }
230
231         spin_unlock(&idi48gpio->ack_lock);
232
233         return IRQ_HANDLED;
234 }
235
236 #define IDI48_NGPIO 48
237 static const char *idi48_names[IDI48_NGPIO] = {
238         "Bit 0 A", "Bit 1 A", "Bit 2 A", "Bit 3 A", "Bit 4 A", "Bit 5 A",
239         "Bit 6 A", "Bit 7 A", "Bit 8 A", "Bit 9 A", "Bit 10 A", "Bit 11 A",
240         "Bit 12 A", "Bit 13 A", "Bit 14 A", "Bit 15 A", "Bit 16 A", "Bit 17 A",
241         "Bit 18 A", "Bit 19 A", "Bit 20 A", "Bit 21 A", "Bit 22 A", "Bit 23 A",
242         "Bit 0 B", "Bit 1 B", "Bit 2 B", "Bit 3 B", "Bit 4 B", "Bit 5 B",
243         "Bit 6 B", "Bit 7 B", "Bit 8 B", "Bit 9 B", "Bit 10 B", "Bit 11 B",
244         "Bit 12 B", "Bit 13 B", "Bit 14 B", "Bit 15 B", "Bit 16 B", "Bit 17 B",
245         "Bit 18 B", "Bit 19 B", "Bit 20 B", "Bit 21 B", "Bit 22 B", "Bit 23 B"
246 };
247
248 static int idi_48_irq_init_hw(struct gpio_chip *gc)
249 {
250         struct idi_48_gpio *const idi48gpio = gpiochip_get_data(gc);
251
252         /* Disable IRQ by default */
253         iowrite8(0, idi48gpio->base + 7);
254         ioread8(idi48gpio->base + 7);
255
256         return 0;
257 }
258
259 static int idi_48_probe(struct device *dev, unsigned int id)
260 {
261         struct idi_48_gpio *idi48gpio;
262         const char *const name = dev_name(dev);
263         struct gpio_irq_chip *girq;
264         int err;
265
266         idi48gpio = devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL);
267         if (!idi48gpio)
268                 return -ENOMEM;
269
270         if (!devm_request_region(dev, base[id], IDI_48_EXTENT, name)) {
271                 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
272                         base[id], base[id] + IDI_48_EXTENT);
273                 return -EBUSY;
274         }
275
276         idi48gpio->base = devm_ioport_map(dev, base[id], IDI_48_EXTENT);
277         if (!idi48gpio->base)
278                 return -ENOMEM;
279
280         idi48gpio->chip.label = name;
281         idi48gpio->chip.parent = dev;
282         idi48gpio->chip.owner = THIS_MODULE;
283         idi48gpio->chip.base = -1;
284         idi48gpio->chip.ngpio = IDI48_NGPIO;
285         idi48gpio->chip.names = idi48_names;
286         idi48gpio->chip.get_direction = idi_48_gpio_get_direction;
287         idi48gpio->chip.direction_input = idi_48_gpio_direction_input;
288         idi48gpio->chip.get = idi_48_gpio_get;
289         idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple;
290
291         girq = &idi48gpio->chip.irq;
292         girq->chip = &idi_48_irqchip;
293         /* This will let us handle the parent IRQ in the driver */
294         girq->parent_handler = NULL;
295         girq->num_parents = 0;
296         girq->parents = NULL;
297         girq->default_type = IRQ_TYPE_NONE;
298         girq->handler = handle_edge_irq;
299         girq->init_hw = idi_48_irq_init_hw;
300
301         raw_spin_lock_init(&idi48gpio->lock);
302         spin_lock_init(&idi48gpio->ack_lock);
303
304         err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio);
305         if (err) {
306                 dev_err(dev, "GPIO registering failed (%d)\n", err);
307                 return err;
308         }
309
310         err = devm_request_irq(dev, irq[id], idi_48_irq_handler, IRQF_SHARED,
311                 name, idi48gpio);
312         if (err) {
313                 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
314                 return err;
315         }
316
317         return 0;
318 }
319
320 static struct isa_driver idi_48_driver = {
321         .probe = idi_48_probe,
322         .driver = {
323                 .name = "104-idi-48"
324         },
325 };
326 module_isa_driver(idi_48_driver, num_idi_48);
327
328 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
329 MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver");
330 MODULE_LICENSE("GPL v2");