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