Merge drm/drm-next into drm-intel-next-queued
[linux-2.6-microblaze.git] / drivers / gpio / gpio-104-idio-16.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * GPIO driver for the ACCES 104-IDIO-16 family
4  * Copyright (C) 2015 William Breathitt Gray
5  *
6  * This driver supports the following ACCES devices: 104-IDIO-16,
7  * 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8.
8  */
9 #include <linux/bitops.h>
10 #include <linux/device.h>
11 #include <linux/errno.h>
12 #include <linux/gpio/driver.h>
13 #include <linux/io.h>
14 #include <linux/ioport.h>
15 #include <linux/interrupt.h>
16 #include <linux/irqdesc.h>
17 #include <linux/isa.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/moduleparam.h>
21 #include <linux/spinlock.h>
22
23 #define IDIO_16_EXTENT 8
24 #define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT)
25
26 static unsigned int base[MAX_NUM_IDIO_16];
27 static unsigned int num_idio_16;
28 module_param_hw_array(base, uint, ioport, &num_idio_16, 0);
29 MODULE_PARM_DESC(base, "ACCES 104-IDIO-16 base addresses");
30
31 static unsigned int irq[MAX_NUM_IDIO_16];
32 module_param_hw_array(irq, uint, irq, NULL, 0);
33 MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
34
35 /**
36  * struct idio_16_gpio - GPIO device private data structure
37  * @chip:       instance of the gpio_chip
38  * @lock:       synchronization lock to prevent I/O race conditions
39  * @irq_mask:   I/O bits affected by interrupts
40  * @base:       base port address of the GPIO device
41  * @out_state:  output bits state
42  */
43 struct idio_16_gpio {
44         struct gpio_chip chip;
45         raw_spinlock_t lock;
46         unsigned long irq_mask;
47         unsigned base;
48         unsigned out_state;
49 };
50
51 static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
52 {
53         if (offset > 15)
54                 return GPIO_LINE_DIRECTION_IN;
55
56         return GPIO_LINE_DIRECTION_OUT;
57 }
58
59 static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
60 {
61         return 0;
62 }
63
64 static int idio_16_gpio_direction_output(struct gpio_chip *chip,
65         unsigned offset, int value)
66 {
67         chip->set(chip, offset, value);
68         return 0;
69 }
70
71 static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset)
72 {
73         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
74         const unsigned mask = BIT(offset-16);
75
76         if (offset < 16)
77                 return -EINVAL;
78
79         if (offset < 24)
80                 return !!(inb(idio16gpio->base + 1) & mask);
81
82         return !!(inb(idio16gpio->base + 5) & (mask>>8));
83 }
84
85 static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
86         unsigned long *mask, unsigned long *bits)
87 {
88         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
89
90         *bits = 0;
91         if (*mask & GENMASK(23, 16))
92                 *bits |= (unsigned long)inb(idio16gpio->base + 1) << 16;
93         if (*mask & GENMASK(31, 24))
94                 *bits |= (unsigned long)inb(idio16gpio->base + 5) << 24;
95
96         return 0;
97 }
98
99 static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
100 {
101         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
102         const unsigned mask = BIT(offset);
103         unsigned long flags;
104
105         if (offset > 15)
106                 return;
107
108         raw_spin_lock_irqsave(&idio16gpio->lock, flags);
109
110         if (value)
111                 idio16gpio->out_state |= mask;
112         else
113                 idio16gpio->out_state &= ~mask;
114
115         if (offset > 7)
116                 outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
117         else
118                 outb(idio16gpio->out_state, idio16gpio->base);
119
120         raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
121 }
122
123 static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
124         unsigned long *mask, unsigned long *bits)
125 {
126         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
127         unsigned long flags;
128
129         raw_spin_lock_irqsave(&idio16gpio->lock, flags);
130
131         idio16gpio->out_state &= ~*mask;
132         idio16gpio->out_state |= *mask & *bits;
133
134         if (*mask & 0xFF)
135                 outb(idio16gpio->out_state, idio16gpio->base);
136         if ((*mask >> 8) & 0xFF)
137                 outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
138
139         raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
140 }
141
142 static void idio_16_irq_ack(struct irq_data *data)
143 {
144 }
145
146 static void idio_16_irq_mask(struct irq_data *data)
147 {
148         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
149         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
150         const unsigned long mask = BIT(irqd_to_hwirq(data));
151         unsigned long flags;
152
153         idio16gpio->irq_mask &= ~mask;
154
155         if (!idio16gpio->irq_mask) {
156                 raw_spin_lock_irqsave(&idio16gpio->lock, flags);
157
158                 outb(0, idio16gpio->base + 2);
159
160                 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
161         }
162 }
163
164 static void idio_16_irq_unmask(struct irq_data *data)
165 {
166         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
167         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
168         const unsigned long mask = BIT(irqd_to_hwirq(data));
169         const unsigned long prev_irq_mask = idio16gpio->irq_mask;
170         unsigned long flags;
171
172         idio16gpio->irq_mask |= mask;
173
174         if (!prev_irq_mask) {
175                 raw_spin_lock_irqsave(&idio16gpio->lock, flags);
176
177                 inb(idio16gpio->base + 2);
178
179                 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
180         }
181 }
182
183 static int idio_16_irq_set_type(struct irq_data *data, unsigned flow_type)
184 {
185         /* The only valid irq types are none and both-edges */
186         if (flow_type != IRQ_TYPE_NONE &&
187                 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
188                 return -EINVAL;
189
190         return 0;
191 }
192
193 static struct irq_chip idio_16_irqchip = {
194         .name = "104-idio-16",
195         .irq_ack = idio_16_irq_ack,
196         .irq_mask = idio_16_irq_mask,
197         .irq_unmask = idio_16_irq_unmask,
198         .irq_set_type = idio_16_irq_set_type
199 };
200
201 static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
202 {
203         struct idio_16_gpio *const idio16gpio = dev_id;
204         struct gpio_chip *const chip = &idio16gpio->chip;
205         int gpio;
206
207         for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
208                 generic_handle_irq(irq_find_mapping(chip->irq.domain, gpio));
209
210         raw_spin_lock(&idio16gpio->lock);
211
212         outb(0, idio16gpio->base + 1);
213
214         raw_spin_unlock(&idio16gpio->lock);
215
216         return IRQ_HANDLED;
217 }
218
219 #define IDIO_16_NGPIO 32
220 static const char *idio_16_names[IDIO_16_NGPIO] = {
221         "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
222         "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
223         "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
224         "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
225 };
226
227 static int idio_16_probe(struct device *dev, unsigned int id)
228 {
229         struct idio_16_gpio *idio16gpio;
230         const char *const name = dev_name(dev);
231         int err;
232
233         idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
234         if (!idio16gpio)
235                 return -ENOMEM;
236
237         if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) {
238                 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
239                         base[id], base[id] + IDIO_16_EXTENT);
240                 return -EBUSY;
241         }
242
243         idio16gpio->chip.label = name;
244         idio16gpio->chip.parent = dev;
245         idio16gpio->chip.owner = THIS_MODULE;
246         idio16gpio->chip.base = -1;
247         idio16gpio->chip.ngpio = IDIO_16_NGPIO;
248         idio16gpio->chip.names = idio_16_names;
249         idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
250         idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
251         idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
252         idio16gpio->chip.get = idio_16_gpio_get;
253         idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
254         idio16gpio->chip.set = idio_16_gpio_set;
255         idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
256         idio16gpio->base = base[id];
257         idio16gpio->out_state = 0xFFFF;
258
259         raw_spin_lock_init(&idio16gpio->lock);
260
261         err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
262         if (err) {
263                 dev_err(dev, "GPIO registering failed (%d)\n", err);
264                 return err;
265         }
266
267         /* Disable IRQ by default */
268         outb(0, base[id] + 2);
269         outb(0, base[id] + 1);
270
271         err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0,
272                 handle_edge_irq, IRQ_TYPE_NONE);
273         if (err) {
274                 dev_err(dev, "Could not add irqchip (%d)\n", err);
275                 return err;
276         }
277
278         err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name,
279                 idio16gpio);
280         if (err) {
281                 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
282                 return err;
283         }
284
285         return 0;
286 }
287
288 static struct isa_driver idio_16_driver = {
289         .probe = idio_16_probe,
290         .driver = {
291                 .name = "104-idio-16"
292         },
293 };
294
295 module_isa_driver(idio_16_driver, num_idio_16);
296
297 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
298 MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
299 MODULE_LICENSE("GPL v2");