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