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