xref: /linux/drivers/gpio/gpio-pci-idio-16.c (revision e9f0878c4b2004ac19581274c1ae4c61ae3ca70e)
1 /*
2  * GPIO driver for the ACCES PCI-IDIO-16
3  * Copyright (C) 2017 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 #include <linux/bitmap.h>
15 #include <linux/bitops.h>
16 #include <linux/device.h>
17 #include <linux/errno.h>
18 #include <linux/gpio/driver.h>
19 #include <linux/interrupt.h>
20 #include <linux/irqdesc.h>
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/pci.h>
24 #include <linux/spinlock.h>
25 #include <linux/types.h>
26 
27 /**
28  * struct idio_16_gpio_reg - GPIO device registers structure
29  * @out0_7:	Read: FET Drive Outputs 0-7
30  *		Write: FET Drive Outputs 0-7
31  * @in0_7:	Read: Isolated Inputs 0-7
32  *		Write: Clear Interrupt
33  * @irq_ctl:	Read: Enable IRQ
34  *		Write: Disable IRQ
35  * @filter_ctl:	Read: Activate Input Filters 0-15
36  *		Write: Deactivate Input Filters 0-15
37  * @out8_15:	Read: FET Drive Outputs 8-15
38  *		Write: FET Drive Outputs 8-15
39  * @in8_15:	Read: Isolated Inputs 8-15
40  *		Write: Unused
41  * @irq_status:	Read: Interrupt status
42  *		Write: Unused
43  */
44 struct idio_16_gpio_reg {
45 	u8 out0_7;
46 	u8 in0_7;
47 	u8 irq_ctl;
48 	u8 filter_ctl;
49 	u8 out8_15;
50 	u8 in8_15;
51 	u8 irq_status;
52 };
53 
54 /**
55  * struct idio_16_gpio - GPIO device private data structure
56  * @chip:	instance of the gpio_chip
57  * @lock:	synchronization lock to prevent I/O race conditions
58  * @reg:	I/O address offset for the GPIO device registers
59  * @irq_mask:	I/O bits affected by interrupts
60  */
61 struct idio_16_gpio {
62 	struct gpio_chip chip;
63 	raw_spinlock_t lock;
64 	struct idio_16_gpio_reg __iomem *reg;
65 	unsigned long irq_mask;
66 };
67 
68 static int idio_16_gpio_get_direction(struct gpio_chip *chip,
69 	unsigned int offset)
70 {
71 	if (offset > 15)
72 		return 1;
73 
74 	return 0;
75 }
76 
77 static int idio_16_gpio_direction_input(struct gpio_chip *chip,
78 	unsigned int offset)
79 {
80 	return 0;
81 }
82 
83 static int idio_16_gpio_direction_output(struct gpio_chip *chip,
84 	unsigned int offset, int value)
85 {
86 	chip->set(chip, offset, value);
87 	return 0;
88 }
89 
90 static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
91 {
92 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
93 	unsigned long mask = BIT(offset);
94 
95 	if (offset < 8)
96 		return !!(ioread8(&idio16gpio->reg->out0_7) & mask);
97 
98 	if (offset < 16)
99 		return !!(ioread8(&idio16gpio->reg->out8_15) & (mask >> 8));
100 
101 	if (offset < 24)
102 		return !!(ioread8(&idio16gpio->reg->in0_7) & (mask >> 16));
103 
104 	return !!(ioread8(&idio16gpio->reg->in8_15) & (mask >> 24));
105 }
106 
107 static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
108 	unsigned long *mask, unsigned long *bits)
109 {
110 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
111 	size_t i;
112 	const unsigned int gpio_reg_size = 8;
113 	unsigned int bits_offset;
114 	size_t word_index;
115 	unsigned int word_offset;
116 	unsigned long word_mask;
117 	const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
118 	unsigned long port_state;
119 	void __iomem *ports[] = {
120 		&idio16gpio->reg->out0_7, &idio16gpio->reg->out8_15,
121 		&idio16gpio->reg->in0_7, &idio16gpio->reg->in8_15,
122 	};
123 
124 	/* clear bits array to a clean slate */
125 	bitmap_zero(bits, chip->ngpio);
126 
127 	/* get bits are evaluated a gpio port register at a time */
128 	for (i = 0; i < ARRAY_SIZE(ports); i++) {
129 		/* gpio offset in bits array */
130 		bits_offset = i * gpio_reg_size;
131 
132 		/* word index for bits array */
133 		word_index = BIT_WORD(bits_offset);
134 
135 		/* gpio offset within current word of bits array */
136 		word_offset = bits_offset % BITS_PER_LONG;
137 
138 		/* mask of get bits for current gpio within current word */
139 		word_mask = mask[word_index] & (port_mask << word_offset);
140 		if (!word_mask) {
141 			/* no get bits in this port so skip to next one */
142 			continue;
143 		}
144 
145 		/* read bits from current gpio port */
146 		port_state = ioread8(ports[i]);
147 
148 		/* store acquired bits at respective bits array offset */
149 		bits[word_index] |= port_state << word_offset;
150 	}
151 
152 	return 0;
153 }
154 
155 static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
156 	int value)
157 {
158 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
159 	unsigned int mask = BIT(offset);
160 	void __iomem *base;
161 	unsigned long flags;
162 	unsigned int out_state;
163 
164 	if (offset > 15)
165 		return;
166 
167 	if (offset > 7) {
168 		mask >>= 8;
169 		base = &idio16gpio->reg->out8_15;
170 	} else
171 		base = &idio16gpio->reg->out0_7;
172 
173 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
174 
175 	if (value)
176 		out_state = ioread8(base) | mask;
177 	else
178 		out_state = ioread8(base) & ~mask;
179 
180 	iowrite8(out_state, base);
181 
182 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
183 }
184 
185 static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
186 	unsigned long *mask, unsigned long *bits)
187 {
188 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
189 	unsigned long flags;
190 	unsigned int out_state;
191 
192 	raw_spin_lock_irqsave(&idio16gpio->lock, flags);
193 
194 	/* process output lines 0-7 */
195 	if (*mask & 0xFF) {
196 		out_state = ioread8(&idio16gpio->reg->out0_7) & ~*mask;
197 		out_state |= *mask & *bits;
198 		iowrite8(out_state, &idio16gpio->reg->out0_7);
199 	}
200 
201 	/* shift to next output line word */
202 	*mask >>= 8;
203 
204 	/* process output lines 8-15 */
205 	if (*mask & 0xFF) {
206 		*bits >>= 8;
207 		out_state = ioread8(&idio16gpio->reg->out8_15) & ~*mask;
208 		out_state |= *mask & *bits;
209 		iowrite8(out_state, &idio16gpio->reg->out8_15);
210 	}
211 
212 	raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
213 }
214 
215 static void idio_16_irq_ack(struct irq_data *data)
216 {
217 }
218 
219 static void idio_16_irq_mask(struct irq_data *data)
220 {
221 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
222 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
223 	const unsigned long mask = BIT(irqd_to_hwirq(data));
224 	unsigned long flags;
225 
226 	idio16gpio->irq_mask &= ~mask;
227 
228 	if (!idio16gpio->irq_mask) {
229 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
230 
231 		iowrite8(0, &idio16gpio->reg->irq_ctl);
232 
233 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
234 	}
235 }
236 
237 static void idio_16_irq_unmask(struct irq_data *data)
238 {
239 	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
240 	struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
241 	const unsigned long mask = BIT(irqd_to_hwirq(data));
242 	const unsigned long prev_irq_mask = idio16gpio->irq_mask;
243 	unsigned long flags;
244 
245 	idio16gpio->irq_mask |= mask;
246 
247 	if (!prev_irq_mask) {
248 		raw_spin_lock_irqsave(&idio16gpio->lock, flags);
249 
250 		ioread8(&idio16gpio->reg->irq_ctl);
251 
252 		raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
253 	}
254 }
255 
256 static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
257 {
258 	/* The only valid irq types are none and both-edges */
259 	if (flow_type != IRQ_TYPE_NONE &&
260 		(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
261 		return -EINVAL;
262 
263 	return 0;
264 }
265 
266 static struct irq_chip idio_16_irqchip = {
267 	.name = "pci-idio-16",
268 	.irq_ack = idio_16_irq_ack,
269 	.irq_mask = idio_16_irq_mask,
270 	.irq_unmask = idio_16_irq_unmask,
271 	.irq_set_type = idio_16_irq_set_type
272 };
273 
274 static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
275 {
276 	struct idio_16_gpio *const idio16gpio = dev_id;
277 	unsigned int irq_status;
278 	struct gpio_chip *const chip = &idio16gpio->chip;
279 	int gpio;
280 
281 	raw_spin_lock(&idio16gpio->lock);
282 
283 	irq_status = ioread8(&idio16gpio->reg->irq_status);
284 
285 	raw_spin_unlock(&idio16gpio->lock);
286 
287 	/* Make sure our device generated IRQ */
288 	if (!(irq_status & 0x3) || !(irq_status & 0x4))
289 		return IRQ_NONE;
290 
291 	for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
292 		generic_handle_irq(irq_find_mapping(chip->irq.domain, gpio));
293 
294 	raw_spin_lock(&idio16gpio->lock);
295 
296 	/* Clear interrupt */
297 	iowrite8(0, &idio16gpio->reg->in0_7);
298 
299 	raw_spin_unlock(&idio16gpio->lock);
300 
301 	return IRQ_HANDLED;
302 }
303 
304 #define IDIO_16_NGPIO 32
305 static const char *idio_16_names[IDIO_16_NGPIO] = {
306 	"OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
307 	"OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
308 	"IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
309 	"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
310 };
311 
312 static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
313 {
314 	struct device *const dev = &pdev->dev;
315 	struct idio_16_gpio *idio16gpio;
316 	int err;
317 	const size_t pci_bar_index = 2;
318 	const char *const name = pci_name(pdev);
319 
320 	idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
321 	if (!idio16gpio)
322 		return -ENOMEM;
323 
324 	err = pcim_enable_device(pdev);
325 	if (err) {
326 		dev_err(dev, "Failed to enable PCI device (%d)\n", err);
327 		return err;
328 	}
329 
330 	err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
331 	if (err) {
332 		dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
333 		return err;
334 	}
335 
336 	idio16gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
337 
338 	/* Deactivate input filters */
339 	iowrite8(0, &idio16gpio->reg->filter_ctl);
340 
341 	idio16gpio->chip.label = name;
342 	idio16gpio->chip.parent = dev;
343 	idio16gpio->chip.owner = THIS_MODULE;
344 	idio16gpio->chip.base = -1;
345 	idio16gpio->chip.ngpio = IDIO_16_NGPIO;
346 	idio16gpio->chip.names = idio_16_names;
347 	idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
348 	idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
349 	idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
350 	idio16gpio->chip.get = idio_16_gpio_get;
351 	idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
352 	idio16gpio->chip.set = idio_16_gpio_set;
353 	idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
354 
355 	raw_spin_lock_init(&idio16gpio->lock);
356 
357 	err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
358 	if (err) {
359 		dev_err(dev, "GPIO registering failed (%d)\n", err);
360 		return err;
361 	}
362 
363 	/* Disable IRQ by default and clear any pending interrupt */
364 	iowrite8(0, &idio16gpio->reg->irq_ctl);
365 	iowrite8(0, &idio16gpio->reg->in0_7);
366 
367 	err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0,
368 		handle_edge_irq, IRQ_TYPE_NONE);
369 	if (err) {
370 		dev_err(dev, "Could not add irqchip (%d)\n", err);
371 		return err;
372 	}
373 
374 	err = devm_request_irq(dev, pdev->irq, idio_16_irq_handler, IRQF_SHARED,
375 		name, idio16gpio);
376 	if (err) {
377 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
378 		return err;
379 	}
380 
381 	return 0;
382 }
383 
384 static const struct pci_device_id idio_16_pci_dev_id[] = {
385 	{ PCI_DEVICE(0x494F, 0x0DC8) }, { 0 }
386 };
387 MODULE_DEVICE_TABLE(pci, idio_16_pci_dev_id);
388 
389 static struct pci_driver idio_16_driver = {
390 	.name = "pci-idio-16",
391 	.id_table = idio_16_pci_dev_id,
392 	.probe = idio_16_probe
393 };
394 
395 module_pci_driver(idio_16_driver);
396 
397 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
398 MODULE_DESCRIPTION("ACCES PCI-IDIO-16 GPIO driver");
399 MODULE_LICENSE("GPL v2");
400