1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * GPIO driver for the ACCES PCIe-IDIO-24 family
4  * Copyright (C) 2018 William Breathitt Gray
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License, version 2, as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * This driver supports the following ACCES devices: PCIe-IDIO-24,
16  * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12.
17  */
18 #include <linux/bitops.h>
19 #include <linux/device.h>
20 #include <linux/errno.h>
21 #include <linux/gpio/driver.h>
22 #include <linux/interrupt.h>
23 #include <linux/irqdesc.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/pci.h>
27 #include <linux/spinlock.h>
28 #include <linux/types.h>
29 
30 /**
31  * struct idio_24_gpio_reg - GPIO device registers structure
32  * @out0_7:	Read: FET Outputs 0-7
33  *		Write: FET Outputs 0-7
34  * @out8_15:	Read: FET Outputs 8-15
35  *		Write: FET Outputs 8-15
36  * @out16_23:	Read: FET Outputs 16-23
37  *		Write: FET Outputs 16-23
38  * @ttl_out0_7:	Read: TTL/CMOS Outputs 0-7
39  *		Write: TTL/CMOS Outputs 0-7
40  * @in0_7:	Read: Isolated Inputs 0-7
41  *		Write: Reserved
42  * @in8_15:	Read: Isolated Inputs 8-15
43  *		Write: Reserved
44  * @in16_23:	Read: Isolated Inputs 16-23
45  *		Write: Reserved
46  * @ttl_in0_7:	Read: TTL/CMOS Inputs 0-7
47  *		Write: Reserved
48  * @cos0_7:	Read: COS Status Inputs 0-7
49  *		Write: COS Clear Inputs 0-7
50  * @cos8_15:	Read: COS Status Inputs 8-15
51  *		Write: COS Clear Inputs 8-15
52  * @cos16_23:	Read: COS Status Inputs 16-23
53  *		Write: COS Clear Inputs 16-23
54  * @cos_ttl0_7:	Read: COS Status TTL/CMOS 0-7
55  *		Write: COS Clear TTL/CMOS 0-7
56  * @ctl:	Read: Control Register
57  *		Write: Control Register
58  * @reserved:	Read: Reserved
59  *		Write: Reserved
60  * @cos_enable:	Read: COS Enable
61  *		Write: COS Enable
62  * @soft_reset:	Read: IRQ Output Pin Status
63  *		Write: Software Board Reset
64  */
65 struct idio_24_gpio_reg {
66 	u8 out0_7;
67 	u8 out8_15;
68 	u8 out16_23;
69 	u8 ttl_out0_7;
70 	u8 in0_7;
71 	u8 in8_15;
72 	u8 in16_23;
73 	u8 ttl_in0_7;
74 	u8 cos0_7;
75 	u8 cos8_15;
76 	u8 cos16_23;
77 	u8 cos_ttl0_7;
78 	u8 ctl;
79 	u8 reserved;
80 	u8 cos_enable;
81 	u8 soft_reset;
82 };
83 
84 /**
85  * struct idio_24_gpio - GPIO device private data structure
86  * @chip:	instance of the gpio_chip
87  * @lock:	synchronization lock to prevent I/O race conditions
88  * @reg:	I/O address offset for the GPIO device registers
89  * @irq_mask:	I/O bits affected by interrupts
90  */
91 struct idio_24_gpio {
92 	struct gpio_chip chip;
93 	raw_spinlock_t lock;
94 	struct idio_24_gpio_reg __iomem *reg;
95 	unsigned long irq_mask;
96 };
97 
98 static int idio_24_gpio_get_direction(struct gpio_chip *chip,
99 	unsigned int offset)
100 {
101 	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
102 	const unsigned long out_mode_mask = BIT(1);
103 
104 	/* FET Outputs */
105 	if (offset < 24)
106 		return 0;
107 
108 	/* Isolated Inputs */
109 	if (offset < 48)
110 		return 1;
111 
112 	/* TTL/CMOS I/O */
113 	/* OUT MODE = 1 when TTL/CMOS Output Mode is set */
114 	return !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask);
115 }
116 
117 static int idio_24_gpio_direction_input(struct gpio_chip *chip,
118 	unsigned int offset)
119 {
120 	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
121 	unsigned long flags;
122 	unsigned int ctl_state;
123 	const unsigned long out_mode_mask = BIT(1);
124 
125 	/* TTL/CMOS I/O */
126 	if (offset > 47) {
127 		raw_spin_lock_irqsave(&idio24gpio->lock, flags);
128 
129 		/* Clear TTL/CMOS Output Mode */
130 		ctl_state = ioread8(&idio24gpio->reg->ctl) & ~out_mode_mask;
131 		iowrite8(ctl_state, &idio24gpio->reg->ctl);
132 
133 		raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
134 	}
135 
136 	return 0;
137 }
138 
139 static int idio_24_gpio_direction_output(struct gpio_chip *chip,
140 	unsigned int offset, int value)
141 {
142 	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
143 	unsigned long flags;
144 	unsigned int ctl_state;
145 	const unsigned long out_mode_mask = BIT(1);
146 
147 	/* TTL/CMOS I/O */
148 	if (offset > 47) {
149 		raw_spin_lock_irqsave(&idio24gpio->lock, flags);
150 
151 		/* Set TTL/CMOS Output Mode */
152 		ctl_state = ioread8(&idio24gpio->reg->ctl) | out_mode_mask;
153 		iowrite8(ctl_state, &idio24gpio->reg->ctl);
154 
155 		raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
156 	}
157 
158 	chip->set(chip, offset, value);
159 	return 0;
160 }
161 
162 static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset)
163 {
164 	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
165 	const unsigned long offset_mask = BIT(offset % 8);
166 	const unsigned long out_mode_mask = BIT(1);
167 
168 	/* FET Outputs */
169 	if (offset < 8)
170 		return !!(ioread8(&idio24gpio->reg->out0_7) & offset_mask);
171 
172 	if (offset < 16)
173 		return !!(ioread8(&idio24gpio->reg->out8_15) & offset_mask);
174 
175 	if (offset < 24)
176 		return !!(ioread8(&idio24gpio->reg->out16_23) & offset_mask);
177 
178 	/* Isolated Inputs */
179 	if (offset < 32)
180 		return !!(ioread8(&idio24gpio->reg->in0_7) & offset_mask);
181 
182 	if (offset < 40)
183 		return !!(ioread8(&idio24gpio->reg->in8_15) & offset_mask);
184 
185 	if (offset < 48)
186 		return !!(ioread8(&idio24gpio->reg->in16_23) & offset_mask);
187 
188 	/* TTL/CMOS Outputs */
189 	if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
190 		return !!(ioread8(&idio24gpio->reg->ttl_out0_7) & offset_mask);
191 
192 	/* TTL/CMOS Inputs */
193 	return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask);
194 }
195 
196 static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset,
197 	int value)
198 {
199 	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
200 	const unsigned long out_mode_mask = BIT(1);
201 	void __iomem *base;
202 	const unsigned int mask = BIT(offset % 8);
203 	unsigned long flags;
204 	unsigned int out_state;
205 
206 	/* Isolated Inputs */
207 	if (offset > 23 && offset < 48)
208 		return;
209 
210 	/* TTL/CMOS Inputs */
211 	if (offset > 47 && !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask))
212 		return;
213 
214 	/* TTL/CMOS Outputs */
215 	if (offset > 47)
216 		base = &idio24gpio->reg->ttl_out0_7;
217 	/* FET Outputs */
218 	else if (offset > 15)
219 		base = &idio24gpio->reg->out16_23;
220 	else if (offset > 7)
221 		base = &idio24gpio->reg->out8_15;
222 	else
223 		base = &idio24gpio->reg->out0_7;
224 
225 	raw_spin_lock_irqsave(&idio24gpio->lock, flags);
226 
227 	if (value)
228 		out_state = ioread8(base) | mask;
229 	else
230 		out_state = ioread8(base) & ~mask;
231 
232 	iowrite8(out_state, base);
233 
234 	raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
235 }
236 
237 static void idio_24_irq_ack(struct irq_data *data)
238 {
239 }
240 
241 static void idio_24_irq_mask(struct irq_data *data)
242 {
243 	struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
244 	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
245 	unsigned long flags;
246 	const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
247 	unsigned char new_irq_mask;
248 	const unsigned long bank_offset = bit_offset/8 * 8;
249 	unsigned char cos_enable_state;
250 
251 	raw_spin_lock_irqsave(&idio24gpio->lock, flags);
252 
253 	idio24gpio->irq_mask &= BIT(bit_offset);
254 	new_irq_mask = idio24gpio->irq_mask >> bank_offset;
255 
256 	if (!new_irq_mask) {
257 		cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
258 
259 		/* Disable Rising Edge detection */
260 		cos_enable_state &= ~BIT(bank_offset);
261 		/* Disable Falling Edge detection */
262 		cos_enable_state &= ~BIT(bank_offset + 4);
263 
264 		iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
265 	}
266 
267 	raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
268 }
269 
270 static void idio_24_irq_unmask(struct irq_data *data)
271 {
272 	struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
273 	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
274 	unsigned long flags;
275 	unsigned char prev_irq_mask;
276 	const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
277 	const unsigned long bank_offset = bit_offset/8 * 8;
278 	unsigned char cos_enable_state;
279 
280 	raw_spin_lock_irqsave(&idio24gpio->lock, flags);
281 
282 	prev_irq_mask = idio24gpio->irq_mask >> bank_offset;
283 	idio24gpio->irq_mask |= BIT(bit_offset);
284 
285 	if (!prev_irq_mask) {
286 		cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
287 
288 		/* Enable Rising Edge detection */
289 		cos_enable_state |= BIT(bank_offset);
290 		/* Enable Falling Edge detection */
291 		cos_enable_state |= BIT(bank_offset + 4);
292 
293 		iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
294 	}
295 
296 	raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
297 }
298 
299 static int idio_24_irq_set_type(struct irq_data *data, unsigned int flow_type)
300 {
301 	/* The only valid irq types are none and both-edges */
302 	if (flow_type != IRQ_TYPE_NONE &&
303 		(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
304 		return -EINVAL;
305 
306 	return 0;
307 }
308 
309 static struct irq_chip idio_24_irqchip = {
310 	.name = "pcie-idio-24",
311 	.irq_ack = idio_24_irq_ack,
312 	.irq_mask = idio_24_irq_mask,
313 	.irq_unmask = idio_24_irq_unmask,
314 	.irq_set_type = idio_24_irq_set_type
315 };
316 
317 static irqreturn_t idio_24_irq_handler(int irq, void *dev_id)
318 {
319 	struct idio_24_gpio *const idio24gpio = dev_id;
320 	unsigned long irq_status;
321 	struct gpio_chip *const chip = &idio24gpio->chip;
322 	unsigned long irq_mask;
323 	int gpio;
324 
325 	raw_spin_lock(&idio24gpio->lock);
326 
327 	/* Read Change-Of-State status */
328 	irq_status = ioread32(&idio24gpio->reg->cos0_7);
329 
330 	raw_spin_unlock(&idio24gpio->lock);
331 
332 	/* Make sure our device generated IRQ */
333 	if (!irq_status)
334 		return IRQ_NONE;
335 
336 	/* Handle only unmasked IRQ */
337 	irq_mask = idio24gpio->irq_mask & irq_status;
338 
339 	for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24)
340 		generic_handle_irq(irq_find_mapping(chip->irq.domain,
341 			gpio + 24));
342 
343 	raw_spin_lock(&idio24gpio->lock);
344 
345 	/* Clear Change-Of-State status */
346 	iowrite32(irq_status, &idio24gpio->reg->cos0_7);
347 
348 	raw_spin_unlock(&idio24gpio->lock);
349 
350 	return IRQ_HANDLED;
351 }
352 
353 #define IDIO_24_NGPIO 56
354 static const char *idio_24_names[IDIO_24_NGPIO] = {
355 	"OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
356 	"OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
357 	"OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
358 	"IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
359 	"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
360 	"IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
361 	"TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
362 };
363 
364 static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
365 {
366 	struct device *const dev = &pdev->dev;
367 	struct idio_24_gpio *idio24gpio;
368 	int err;
369 	const size_t pci_bar_index = 2;
370 	const char *const name = pci_name(pdev);
371 
372 	idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL);
373 	if (!idio24gpio)
374 		return -ENOMEM;
375 
376 	err = pcim_enable_device(pdev);
377 	if (err) {
378 		dev_err(dev, "Failed to enable PCI device (%d)\n", err);
379 		return err;
380 	}
381 
382 	err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
383 	if (err) {
384 		dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
385 		return err;
386 	}
387 
388 	idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
389 
390 	idio24gpio->chip.label = name;
391 	idio24gpio->chip.parent = dev;
392 	idio24gpio->chip.owner = THIS_MODULE;
393 	idio24gpio->chip.base = -1;
394 	idio24gpio->chip.ngpio = IDIO_24_NGPIO;
395 	idio24gpio->chip.names = idio_24_names;
396 	idio24gpio->chip.get_direction = idio_24_gpio_get_direction;
397 	idio24gpio->chip.direction_input = idio_24_gpio_direction_input;
398 	idio24gpio->chip.direction_output = idio_24_gpio_direction_output;
399 	idio24gpio->chip.get = idio_24_gpio_get;
400 	idio24gpio->chip.set = idio_24_gpio_set;
401 
402 	raw_spin_lock_init(&idio24gpio->lock);
403 
404 	/* Software board reset */
405 	iowrite8(0, &idio24gpio->reg->soft_reset);
406 
407 	err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio);
408 	if (err) {
409 		dev_err(dev, "GPIO registering failed (%d)\n", err);
410 		return err;
411 	}
412 
413 	err = gpiochip_irqchip_add(&idio24gpio->chip, &idio_24_irqchip, 0,
414 		handle_edge_irq, IRQ_TYPE_NONE);
415 	if (err) {
416 		dev_err(dev, "Could not add irqchip (%d)\n", err);
417 		return err;
418 	}
419 
420 	err = devm_request_irq(dev, pdev->irq, idio_24_irq_handler, IRQF_SHARED,
421 		name, idio24gpio);
422 	if (err) {
423 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
424 		return err;
425 	}
426 
427 	return 0;
428 }
429 
430 static const struct pci_device_id idio_24_pci_dev_id[] = {
431 	{ PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) },
432 	{ PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) },
433 	{ 0 }
434 };
435 MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id);
436 
437 static struct pci_driver idio_24_driver = {
438 	.name = "pcie-idio-24",
439 	.id_table = idio_24_pci_dev_id,
440 	.probe = idio_24_probe
441 };
442 
443 module_pci_driver(idio_24_driver);
444 
445 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
446 MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
447 MODULE_LICENSE("GPL v2");
448