xref: /linux/drivers/gpio/gpio-104-idi-48.c (revision 058443934524590d5537a80f490267cc95a61c05)
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/bits.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 #include <linux/types.h>
23 
24 #include "gpio-i8255.h"
25 
26 MODULE_IMPORT_NS(I8255);
27 
28 #define IDI_48_EXTENT 8
29 #define MAX_NUM_IDI_48 max_num_isa_dev(IDI_48_EXTENT)
30 
31 static unsigned int base[MAX_NUM_IDI_48];
32 static unsigned int num_idi_48;
33 module_param_hw_array(base, uint, ioport, &num_idi_48, 0);
34 MODULE_PARM_DESC(base, "ACCES 104-IDI-48 base addresses");
35 
36 static unsigned int irq[MAX_NUM_IDI_48];
37 module_param_hw_array(irq, uint, irq, NULL, 0);
38 MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
39 
40 /**
41  * struct idi_48_reg - device register structure
42  * @port0:	Port 0 Inputs
43  * @unused:	Unused
44  * @port1:	Port 1 Inputs
45  * @irq:	Read: IRQ Status Register/IRQ Clear
46  *		Write: IRQ Enable/Disable
47  */
48 struct idi_48_reg {
49 	u8 port0[3];
50 	u8 unused;
51 	u8 port1[3];
52 	u8 irq;
53 };
54 
55 /**
56  * struct idi_48_gpio - GPIO device private data structure
57  * @chip:	instance of the gpio_chip
58  * @lock:	synchronization lock to prevent I/O race conditions
59  * @irq_mask:	input bits affected by interrupts
60  * @reg:	I/O address offset for the device registers
61  * @cos_enb:	Change-Of-State IRQ enable boundaries mask
62  */
63 struct idi_48_gpio {
64 	struct gpio_chip chip;
65 	spinlock_t lock;
66 	unsigned char irq_mask[6];
67 	struct idi_48_reg __iomem *reg;
68 	unsigned char cos_enb;
69 };
70 
71 static int idi_48_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
72 {
73 	return GPIO_LINE_DIRECTION_IN;
74 }
75 
76 static int idi_48_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
77 {
78 	return 0;
79 }
80 
81 static int idi_48_gpio_get(struct gpio_chip *chip, unsigned int offset)
82 {
83 	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
84 	void __iomem *const ppi = idi48gpio->reg;
85 
86 	return i8255_get(ppi, offset);
87 }
88 
89 static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
90 	unsigned long *bits)
91 {
92 	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
93 	void __iomem *const ppi = idi48gpio->reg;
94 
95 	i8255_get_multiple(ppi, mask, bits, chip->ngpio);
96 
97 	return 0;
98 }
99 
100 static void idi_48_irq_ack(struct irq_data *data)
101 {
102 }
103 
104 static void idi_48_irq_mask(struct irq_data *data)
105 {
106 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
107 	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
108 	const unsigned int offset = irqd_to_hwirq(data);
109 	const unsigned long boundary = offset / 8;
110 	const unsigned long mask = BIT(offset % 8);
111 	unsigned long flags;
112 
113 	spin_lock_irqsave(&idi48gpio->lock, flags);
114 
115 	idi48gpio->irq_mask[boundary] &= ~mask;
116 	gpiochip_disable_irq(chip, offset);
117 
118 	/* Exit early if there are still input lines with IRQ unmasked */
119 	if (idi48gpio->irq_mask[boundary])
120 		goto exit;
121 
122 	idi48gpio->cos_enb &= ~BIT(boundary);
123 
124 	iowrite8(idi48gpio->cos_enb, &idi48gpio->reg->irq);
125 
126 exit:
127 	spin_unlock_irqrestore(&idi48gpio->lock, flags);
128 }
129 
130 static void idi_48_irq_unmask(struct irq_data *data)
131 {
132 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
133 	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
134 	const unsigned int offset = irqd_to_hwirq(data);
135 	const unsigned long boundary = offset / 8;
136 	const unsigned long mask = BIT(offset % 8);
137 	unsigned int prev_irq_mask;
138 	unsigned long flags;
139 
140 	spin_lock_irqsave(&idi48gpio->lock, flags);
141 
142 	prev_irq_mask = idi48gpio->irq_mask[boundary];
143 
144 	gpiochip_enable_irq(chip, offset);
145 	idi48gpio->irq_mask[boundary] |= mask;
146 
147 	/* Exit early if IRQ was already unmasked for this boundary */
148 	if (prev_irq_mask)
149 		goto exit;
150 
151 	idi48gpio->cos_enb |= BIT(boundary);
152 
153 	iowrite8(idi48gpio->cos_enb, &idi48gpio->reg->irq);
154 
155 exit:
156 	spin_unlock_irqrestore(&idi48gpio->lock, flags);
157 }
158 
159 static int idi_48_irq_set_type(struct irq_data *data, unsigned int flow_type)
160 {
161 	/* The only valid irq types are none and both-edges */
162 	if (flow_type != IRQ_TYPE_NONE &&
163 		(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
164 		return -EINVAL;
165 
166 	return 0;
167 }
168 
169 static const struct irq_chip idi_48_irqchip = {
170 	.name = "104-idi-48",
171 	.irq_ack = idi_48_irq_ack,
172 	.irq_mask = idi_48_irq_mask,
173 	.irq_unmask = idi_48_irq_unmask,
174 	.irq_set_type = idi_48_irq_set_type,
175 	.flags = IRQCHIP_IMMUTABLE,
176 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
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->lock);
190 
191 	cos_status = ioread8(&idi48gpio->reg->irq);
192 
193 	/* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */
194 	if (cos_status & BIT(6)) {
195 		spin_unlock(&idi48gpio->lock);
196 		return IRQ_NONE;
197 	}
198 
199 	/* Bit 0-5 indicate which Change-Of-State boundary triggered the IRQ */
200 	cos_status &= 0x3F;
201 
202 	for_each_set_bit(boundary, &cos_status, 6) {
203 		irq_mask = idi48gpio->irq_mask[boundary];
204 
205 		for_each_set_bit(bit_num, &irq_mask, 8) {
206 			gpio = bit_num + boundary * 8;
207 
208 			generic_handle_domain_irq(chip->irq.domain,
209 						  gpio);
210 		}
211 	}
212 
213 	spin_unlock(&idi48gpio->lock);
214 
215 	return IRQ_HANDLED;
216 }
217 
218 #define IDI48_NGPIO 48
219 static const char *idi48_names[IDI48_NGPIO] = {
220 	"Bit 0 A", "Bit 1 A", "Bit 2 A", "Bit 3 A", "Bit 4 A", "Bit 5 A",
221 	"Bit 6 A", "Bit 7 A", "Bit 8 A", "Bit 9 A", "Bit 10 A", "Bit 11 A",
222 	"Bit 12 A", "Bit 13 A", "Bit 14 A", "Bit 15 A",	"Bit 16 A", "Bit 17 A",
223 	"Bit 18 A", "Bit 19 A", "Bit 20 A", "Bit 21 A", "Bit 22 A", "Bit 23 A",
224 	"Bit 0 B", "Bit 1 B", "Bit 2 B", "Bit 3 B", "Bit 4 B", "Bit 5 B",
225 	"Bit 6 B", "Bit 7 B", "Bit 8 B", "Bit 9 B", "Bit 10 B", "Bit 11 B",
226 	"Bit 12 B", "Bit 13 B", "Bit 14 B", "Bit 15 B",	"Bit 16 B", "Bit 17 B",
227 	"Bit 18 B", "Bit 19 B", "Bit 20 B", "Bit 21 B", "Bit 22 B", "Bit 23 B"
228 };
229 
230 static int idi_48_irq_init_hw(struct gpio_chip *gc)
231 {
232 	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(gc);
233 
234 	/* Disable IRQ by default */
235 	iowrite8(0, &idi48gpio->reg->irq);
236 	ioread8(&idi48gpio->reg->irq);
237 
238 	return 0;
239 }
240 
241 static int idi_48_probe(struct device *dev, unsigned int id)
242 {
243 	struct idi_48_gpio *idi48gpio;
244 	const char *const name = dev_name(dev);
245 	struct gpio_irq_chip *girq;
246 	int err;
247 
248 	idi48gpio = devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL);
249 	if (!idi48gpio)
250 		return -ENOMEM;
251 
252 	if (!devm_request_region(dev, base[id], IDI_48_EXTENT, name)) {
253 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
254 			base[id], base[id] + IDI_48_EXTENT);
255 		return -EBUSY;
256 	}
257 
258 	idi48gpio->reg = devm_ioport_map(dev, base[id], IDI_48_EXTENT);
259 	if (!idi48gpio->reg)
260 		return -ENOMEM;
261 
262 	idi48gpio->chip.label = name;
263 	idi48gpio->chip.parent = dev;
264 	idi48gpio->chip.owner = THIS_MODULE;
265 	idi48gpio->chip.base = -1;
266 	idi48gpio->chip.ngpio = IDI48_NGPIO;
267 	idi48gpio->chip.names = idi48_names;
268 	idi48gpio->chip.get_direction = idi_48_gpio_get_direction;
269 	idi48gpio->chip.direction_input = idi_48_gpio_direction_input;
270 	idi48gpio->chip.get = idi_48_gpio_get;
271 	idi48gpio->chip.get_multiple = idi_48_gpio_get_multiple;
272 
273 	girq = &idi48gpio->chip.irq;
274 	gpio_irq_chip_set_chip(girq, &idi_48_irqchip);
275 	/* This will let us handle the parent IRQ in the driver */
276 	girq->parent_handler = NULL;
277 	girq->num_parents = 0;
278 	girq->parents = NULL;
279 	girq->default_type = IRQ_TYPE_NONE;
280 	girq->handler = handle_edge_irq;
281 	girq->init_hw = idi_48_irq_init_hw;
282 
283 	spin_lock_init(&idi48gpio->lock);
284 
285 	err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio);
286 	if (err) {
287 		dev_err(dev, "GPIO registering failed (%d)\n", err);
288 		return err;
289 	}
290 
291 	err = devm_request_irq(dev, irq[id], idi_48_irq_handler, IRQF_SHARED,
292 		name, idi48gpio);
293 	if (err) {
294 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
295 		return err;
296 	}
297 
298 	return 0;
299 }
300 
301 static struct isa_driver idi_48_driver = {
302 	.probe = idi_48_probe,
303 	.driver = {
304 		.name = "104-idi-48"
305 	},
306 };
307 module_isa_driver(idi_48_driver, num_idi_48);
308 
309 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
310 MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver");
311 MODULE_LICENSE("GPL v2");
312