xref: /linux/drivers/gpio/gpio-104-idio-16.c (revision c411ed854584a71b0e86ac3019b60e4789d88086)
1 /*
2  * GPIO driver for the ACCES 104-IDIO-16 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-IDIO-16,
15  * 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8.
16  */
17 #include <linux/bitops.h>
18 #include <linux/device.h>
19 #include <linux/errno.h>
20 #include <linux/gpio/driver.h>
21 #include <linux/io.h>
22 #include <linux/ioport.h>
23 #include <linux/interrupt.h>
24 #include <linux/irqdesc.h>
25 #include <linux/isa.h>
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/moduleparam.h>
29 #include <linux/spinlock.h>
30 
31 #define IDIO_16_EXTENT 8
32 #define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT)
33 
34 static unsigned int base[MAX_NUM_IDIO_16];
35 static unsigned int num_idio_16;
36 module_param_hw_array(base, uint, ioport, &num_idio_16, 0);
37 MODULE_PARM_DESC(base, "ACCES 104-IDIO-16 base addresses");
38 
39 static unsigned int irq[MAX_NUM_IDIO_16];
40 module_param_hw_array(irq, uint, irq, NULL, 0);
41 MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
42 
43 /**
44  * struct idio_16_gpio - GPIO device private data structure
45  * @chip:	instance of the gpio_chip
46  * @lock:	synchronization lock to prevent I/O race conditions
47  * @irq_mask:	I/O bits affected by interrupts
48  * @base:	base port address of the GPIO device
49  * @out_state:	output bits state
50  */
51 struct idio_16_gpio {
52 	struct gpio_chip chip;
53 	raw_spinlock_t lock;
54 	unsigned long irq_mask;
55 	unsigned base;
56 	unsigned out_state;
57 };
58 
59 static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
60 {
61 	if (offset > 15)
62 		return 1;
63 
64 	return 0;
65 }
66 
67 static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
68 {
69 	return 0;
70 }
71 
72 static int idio_16_gpio_direction_output(struct gpio_chip *chip,
73 	unsigned offset, int value)
74 {
75 	chip->set(chip, offset, value);
76 	return 0;
77 }
78 
79 static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset)
80 {
81 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
82 	const unsigned mask = BIT(offset-16);
83 
84 	if (offset < 16)
85 		return -EINVAL;
86 
87 	if (offset < 24)
88 		return !!(inb(idio16gpio->base + 1) & mask);
89 
90 	return !!(inb(idio16gpio->base + 5) & (mask>>8));
91 }
92 
93 static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
94 {
95 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
96 	const unsigned mask = BIT(offset);
97 	unsigned long flags;
98 
99 	if (offset > 15)
100 		return;
101 
102 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
103 
104 	if (value)
105 		idio16gpio->out_state |= mask;
106 	else
107 		idio16gpio->out_state &= ~mask;
108 
109 	if (offset > 7)
110 		outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
111 	else
112 		outb(idio16gpio->out_state, idio16gpio->base);
113 
114 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
115 }
116 
117 static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
118 	unsigned long *mask, unsigned long *bits)
119 {
120 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
121 	unsigned long flags;
122 
123 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
124 
125 	idio16gpio->out_state &= ~*mask;
126 	idio16gpio->out_state |= *mask & *bits;
127 
128 	if (*mask & 0xFF)
129 		outb(idio16gpio->out_state, idio16gpio->base);
130 	if ((*mask >> 8) & 0xFF)
131 		outb(idio16gpio->out_state >> 8, idio16gpio->base + 4);
132 
133 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
134 }
135 
136 static void idio_16_irq_ack(struct irq_data *data)
137 {
138 }
139 
140 static void idio_16_irq_mask(struct irq_data *data)
141 {
142 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
143 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
144 	const unsigned long mask = BIT(irqd_to_hwirq(data));
145 	unsigned long flags;
146 
147 	idio16gpio->irq_mask &= ~mask;
148 
149 	if (!idio16gpio->irq_mask) {
150 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
151 
152 		outb(0, idio16gpio->base + 2);
153 
154 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
155 	}
156 }
157 
158 static void idio_16_irq_unmask(struct irq_data *data)
159 {
160 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
161 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
162 	const unsigned long mask = BIT(irqd_to_hwirq(data));
163 	const unsigned long prev_irq_mask = idio16gpio->irq_mask;
164 	unsigned long flags;
165 
166 	idio16gpio->irq_mask |= mask;
167 
168 	if (!prev_irq_mask) {
169 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
170 
171 		inb(idio16gpio->base + 2);
172 
173 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
174 	}
175 }
176 
177 static int idio_16_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 idio_16_irqchip = {
188 	.name = "104-idio-16",
189 	.irq_ack = idio_16_irq_ack,
190 	.irq_mask = idio_16_irq_mask,
191 	.irq_unmask = idio_16_irq_unmask,
192 	.irq_set_type = idio_16_irq_set_type
193 };
194 
195 static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
196 {
197 	struct idio_16_gpio *const idio16gpio = dev_id;
198 	struct gpio_chip *const chip = &idio16gpio->chip;
199 	int gpio;
200 
201 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
202 		generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio));
203 
204 	raw_spin_lock(&idio16gpio->lock);
205 
206 	outb(0, idio16gpio->base + 1);
207 
208 	raw_spin_unlock(&idio16gpio->lock);
209 
210 	return IRQ_HANDLED;
211 }
212 
213 #define IDIO_16_NGPIO 32
214 static const char *idio_16_names[IDIO_16_NGPIO] = {
215 	"OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
216 	"OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
217 	"IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
218 	"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
219 };
220 
221 static int idio_16_probe(struct device *dev, unsigned int id)
222 {
223 	struct idio_16_gpio *idio16gpio;
224 	const char *const name = dev_name(dev);
225 	int err;
226 
227 	idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
228 	if (!idio16gpio)
229 		return -ENOMEM;
230 
231 	if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) {
232 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
233 			base[id], base[id] + IDIO_16_EXTENT);
234 		return -EBUSY;
235 	}
236 
237 	idio16gpio->chip.label = name;
238 	idio16gpio->chip.parent = dev;
239 	idio16gpio->chip.owner = THIS_MODULE;
240 	idio16gpio->chip.base = -1;
241 	idio16gpio->chip.ngpio = IDIO_16_NGPIO;
242 	idio16gpio->chip.names = idio_16_names;
243 	idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
244 	idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
245 	idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
246 	idio16gpio->chip.get = idio_16_gpio_get;
247 	idio16gpio->chip.set = idio_16_gpio_set;
248 	idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
249 	idio16gpio->base = base[id];
250 	idio16gpio->out_state = 0xFFFF;
251 
252 	raw_spin_lock_init(&idio16gpio->lock);
253 
254 	err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
255 	if (err) {
256 		dev_err(dev, "GPIO registering failed (%d)\n", err);
257 		return err;
258 	}
259 
260 	/* Disable IRQ by default */
261 	outb(0, base[id] + 2);
262 	outb(0, base[id] + 1);
263 
264 	err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0,
265 		handle_edge_irq, IRQ_TYPE_NONE);
266 	if (err) {
267 		dev_err(dev, "Could not add irqchip (%d)\n", err);
268 		return err;
269 	}
270 
271 	err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name,
272 		idio16gpio);
273 	if (err) {
274 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
275 		return err;
276 	}
277 
278 	return 0;
279 }
280 
281 static struct isa_driver idio_16_driver = {
282 	.probe = idio_16_probe,
283 	.driver = {
284 		.name = "104-idio-16"
285 	},
286 };
287 
288 module_isa_driver(idio_16_driver, num_idio_16);
289 
290 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
291 MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
292 MODULE_LICENSE("GPL v2");
293