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,
136 						           flags);
137 			}
138 
139 			return;
140 		}
141 }
142 
143 static void idi_48_irq_unmask(struct irq_data *data)
144 {
145 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
146 	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
147 	const unsigned offset = irqd_to_hwirq(data);
148 	unsigned i;
149 	unsigned mask;
150 	unsigned boundary;
151 	unsigned prev_irq_mask;
152 	unsigned long flags;
153 
154 	for (i = 0; i < 48; i += 8)
155 		if (offset < i + 8) {
156 			mask = BIT(offset - i);
157 			boundary = i / 8;
158 			prev_irq_mask = idi48gpio->irq_mask[boundary];
159 
160 			idi48gpio->irq_mask[boundary] |= mask;
161 
162 			if (!prev_irq_mask) {
163 				idi48gpio->cos_enb |= BIT(boundary);
164 
165 				raw_spin_lock_irqsave(&idi48gpio->lock, flags);
166 
167 				outb(idi48gpio->cos_enb, idi48gpio->base + 7);
168 
169 				raw_spin_unlock_irqrestore(&idi48gpio->lock,
170 						           flags);
171 			}
172 
173 			return;
174 		}
175 }
176 
177 static int idi_48_irq_set_type(struct irq_data *data, unsigned flow_type)
178 {
179 	/* The only valid irq types are none and both-edges */
180 	if (flow_type != IRQ_TYPE_NONE &&
181 		(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
182 		return -EINVAL;
183 
184 	return 0;
185 }
186 
187 static struct irq_chip idi_48_irqchip = {
188 	.name = "104-idi-48",
189 	.irq_ack = idi_48_irq_ack,
190 	.irq_mask = idi_48_irq_mask,
191 	.irq_unmask = idi_48_irq_unmask,
192 	.irq_set_type = idi_48_irq_set_type
193 };
194 
195 static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
196 {
197 	struct idi_48_gpio *const idi48gpio = dev_id;
198 	unsigned long cos_status;
199 	unsigned long boundary;
200 	unsigned long irq_mask;
201 	unsigned long bit_num;
202 	unsigned long gpio;
203 	struct gpio_chip *const chip = &idi48gpio->chip;
204 
205 	spin_lock(&idi48gpio->ack_lock);
206 
207 	raw_spin_lock(&idi48gpio->lock);
208 
209 	cos_status = inb(idi48gpio->base + 7);
210 
211 	raw_spin_unlock(&idi48gpio->lock);
212 
213 	/* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */
214 	if (cos_status & BIT(6)) {
215 		spin_unlock(&idi48gpio->ack_lock);
216 		return IRQ_NONE;
217 	}
218 
219 	/* Bit 0-5 indicate which Change-Of-State boundary triggered the IRQ */
220 	cos_status &= 0x3F;
221 
222 	for_each_set_bit(boundary, &cos_status, 6) {
223 		irq_mask = idi48gpio->irq_mask[boundary];
224 
225 		for_each_set_bit(bit_num, &irq_mask, 8) {
226 			gpio = bit_num + boundary * 8;
227 
228 			generic_handle_irq(irq_find_mapping(chip->irq.domain,
229 				gpio));
230 		}
231 	}
232 
233 	spin_unlock(&idi48gpio->ack_lock);
234 
235 	return IRQ_HANDLED;
236 }
237 
238 #define IDI48_NGPIO 48
239 static const char *idi48_names[IDI48_NGPIO] = {
240 	"Bit 0 A", "Bit 1 A", "Bit 2 A", "Bit 3 A", "Bit 4 A", "Bit 5 A",
241 	"Bit 6 A", "Bit 7 A", "Bit 8 A", "Bit 9 A", "Bit 10 A", "Bit 11 A",
242 	"Bit 12 A", "Bit 13 A", "Bit 14 A", "Bit 15 A",	"Bit 16 A", "Bit 17 A",
243 	"Bit 18 A", "Bit 19 A", "Bit 20 A", "Bit 21 A", "Bit 22 A", "Bit 23 A",
244 	"Bit 0 B", "Bit 1 B", "Bit 2 B", "Bit 3 B", "Bit 4 B", "Bit 5 B",
245 	"Bit 6 B", "Bit 7 B", "Bit 8 B", "Bit 9 B", "Bit 10 B", "Bit 11 B",
246 	"Bit 12 B", "Bit 13 B", "Bit 14 B", "Bit 15 B",	"Bit 16 B", "Bit 17 B",
247 	"Bit 18 B", "Bit 19 B", "Bit 20 B", "Bit 21 B", "Bit 22 B", "Bit 23 B"
248 };
249 
250 static int idi_48_probe(struct device *dev, unsigned int id)
251 {
252 	struct idi_48_gpio *idi48gpio;
253 	const char *const name = dev_name(dev);
254 	int err;
255 
256 	idi48gpio = devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL);
257 	if (!idi48gpio)
258 		return -ENOMEM;
259 
260 	if (!devm_request_region(dev, base[id], IDI_48_EXTENT, name)) {
261 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
262 			base[id], base[id] + IDI_48_EXTENT);
263 		return -EBUSY;
264 	}
265 
266 	idi48gpio->chip.label = name;
267 	idi48gpio->chip.parent = dev;
268 	idi48gpio->chip.owner = THIS_MODULE;
269 	idi48gpio->chip.base = -1;
270 	idi48gpio->chip.ngpio = IDI48_NGPIO;
271 	idi48gpio->chip.names = idi48_names;
272 	idi48gpio->chip.get_direction = idi_48_gpio_get_direction;
273 	idi48gpio->chip.direction_input = idi_48_gpio_direction_input;
274 	idi48gpio->chip.get = idi_48_gpio_get;
275 	idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple;
276 	idi48gpio->base = base[id];
277 
278 	raw_spin_lock_init(&idi48gpio->lock);
279 	spin_lock_init(&idi48gpio->ack_lock);
280 
281 	err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio);
282 	if (err) {
283 		dev_err(dev, "GPIO registering failed (%d)\n", err);
284 		return err;
285 	}
286 
287 	/* Disable IRQ by default */
288 	outb(0, base[id] + 7);
289 	inb(base[id] + 7);
290 
291 	err = gpiochip_irqchip_add(&idi48gpio->chip, &idi_48_irqchip, 0,
292 		handle_edge_irq, IRQ_TYPE_NONE);
293 	if (err) {
294 		dev_err(dev, "Could not add irqchip (%d)\n", err);
295 		return err;
296 	}
297 
298 	err = devm_request_irq(dev, irq[id], idi_48_irq_handler, IRQF_SHARED,
299 		name, idi48gpio);
300 	if (err) {
301 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
302 		return err;
303 	}
304 
305 	return 0;
306 }
307 
308 static struct isa_driver idi_48_driver = {
309 	.probe = idi_48_probe,
310 	.driver = {
311 		.name = "104-idi-48"
312 	},
313 };
314 module_isa_driver(idi_48_driver, num_idi_48);
315 
316 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
317 MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver");
318 MODULE_LICENSE("GPL v2");
319