xref: /linux/drivers/gpio/gpio-104-idi-48.c (revision 0d3b051adbb72ed81956447d0d1e54d5943ee6f5)
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 	unsigned 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 	unsigned base_offset;
70 	unsigned mask;
71 
72 	for (i = 0; i < 48; i += 8)
73 		if (offset < i + 8) {
74 			base_offset = register_offset[i / 8];
75 			mask = BIT(offset - i);
76 
77 			return !!(inb(idi48gpio->base + base_offset) & 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 	unsigned int 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 = inb(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 				outb(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 				outb(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 = inb(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_irq(irq_find_mapping(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 	outb(0, idi48gpio->base + 7);
254 	inb(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->chip.label = name;
277 	idi48gpio->chip.parent = dev;
278 	idi48gpio->chip.owner = THIS_MODULE;
279 	idi48gpio->chip.base = -1;
280 	idi48gpio->chip.ngpio = IDI48_NGPIO;
281 	idi48gpio->chip.names = idi48_names;
282 	idi48gpio->chip.get_direction = idi_48_gpio_get_direction;
283 	idi48gpio->chip.direction_input = idi_48_gpio_direction_input;
284 	idi48gpio->chip.get = idi_48_gpio_get;
285 	idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple;
286 	idi48gpio->base = base[id];
287 
288 	girq = &idi48gpio->chip.irq;
289 	girq->chip = &idi_48_irqchip;
290 	/* This will let us handle the parent IRQ in the driver */
291 	girq->parent_handler = NULL;
292 	girq->num_parents = 0;
293 	girq->parents = NULL;
294 	girq->default_type = IRQ_TYPE_NONE;
295 	girq->handler = handle_edge_irq;
296 	girq->init_hw = idi_48_irq_init_hw;
297 
298 	raw_spin_lock_init(&idi48gpio->lock);
299 	spin_lock_init(&idi48gpio->ack_lock);
300 
301 	err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio);
302 	if (err) {
303 		dev_err(dev, "GPIO registering failed (%d)\n", err);
304 		return err;
305 	}
306 
307 	err = devm_request_irq(dev, irq[id], idi_48_irq_handler, IRQF_SHARED,
308 		name, idi48gpio);
309 	if (err) {
310 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
311 		return err;
312 	}
313 
314 	return 0;
315 }
316 
317 static struct isa_driver idi_48_driver = {
318 	.probe = idi_48_probe,
319 	.driver = {
320 		.name = "104-idi-48"
321 	},
322 };
323 module_isa_driver(idi_48_driver, num_idi_48);
324 
325 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
326 MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver");
327 MODULE_LICENSE("GPL v2");
328