Linux Audio

Check our new training course

Loading...
v6.2
  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/bitmap.h>
 19#include <linux/bitops.h>
 20#include <linux/device.h>
 21#include <linux/errno.h>
 22#include <linux/gpio/driver.h>
 23#include <linux/interrupt.h>
 24#include <linux/irqdesc.h>
 25#include <linux/kernel.h>
 26#include <linux/module.h>
 27#include <linux/pci.h>
 
 28#include <linux/spinlock.h>
 29#include <linux/types.h>
 30
 31/*
 32 * PLX PEX8311 PCI LCS_INTCSR Interrupt Control/Status
 33 *
 34 * Bit: Description
 35 *   0: Enable Interrupt Sources (Bit 0)
 36 *   1: Enable Interrupt Sources (Bit 1)
 37 *   2: Generate Internal PCI Bus Internal SERR# Interrupt
 38 *   3: Mailbox Interrupt Enable
 39 *   4: Power Management Interrupt Enable
 40 *   5: Power Management Interrupt
 41 *   6: Slave Read Local Data Parity Check Error Enable
 42 *   7: Slave Read Local Data Parity Check Error Status
 43 *   8: Internal PCI Wire Interrupt Enable
 44 *   9: PCI Express Doorbell Interrupt Enable
 45 *  10: PCI Abort Interrupt Enable
 46 *  11: Local Interrupt Input Enable
 47 *  12: Retry Abort Enable
 48 *  13: PCI Express Doorbell Interrupt Active
 49 *  14: PCI Abort Interrupt Active
 50 *  15: Local Interrupt Input Active
 51 *  16: Local Interrupt Output Enable
 52 *  17: Local Doorbell Interrupt Enable
 53 *  18: DMA Channel 0 Interrupt Enable
 54 *  19: DMA Channel 1 Interrupt Enable
 55 *  20: Local Doorbell Interrupt Active
 56 *  21: DMA Channel 0 Interrupt Active
 57 *  22: DMA Channel 1 Interrupt Active
 58 *  23: Built-In Self-Test (BIST) Interrupt Active
 59 *  24: Direct Master was the Bus Master during a Master or Target Abort
 60 *  25: DMA Channel 0 was the Bus Master during a Master or Target Abort
 61 *  26: DMA Channel 1 was the Bus Master during a Master or Target Abort
 62 *  27: Target Abort after internal 256 consecutive Master Retrys
 63 *  28: PCI Bus wrote data to LCS_MBOX0
 64 *  29: PCI Bus wrote data to LCS_MBOX1
 65 *  30: PCI Bus wrote data to LCS_MBOX2
 66 *  31: PCI Bus wrote data to LCS_MBOX3
 67 */
 68#define PLX_PEX8311_PCI_LCS_INTCSR  0x68
 69#define INTCSR_INTERNAL_PCI_WIRE    BIT(8)
 70#define INTCSR_LOCAL_INPUT          BIT(11)
 
 71
 72/**
 73 * struct idio_24_gpio_reg - GPIO device registers structure
 74 * @out0_7:	Read: FET Outputs 0-7
 75 *		Write: FET Outputs 0-7
 76 * @out8_15:	Read: FET Outputs 8-15
 77 *		Write: FET Outputs 8-15
 78 * @out16_23:	Read: FET Outputs 16-23
 79 *		Write: FET Outputs 16-23
 80 * @ttl_out0_7:	Read: TTL/CMOS Outputs 0-7
 81 *		Write: TTL/CMOS Outputs 0-7
 82 * @in0_7:	Read: Isolated Inputs 0-7
 83 *		Write: Reserved
 84 * @in8_15:	Read: Isolated Inputs 8-15
 85 *		Write: Reserved
 86 * @in16_23:	Read: Isolated Inputs 16-23
 87 *		Write: Reserved
 88 * @ttl_in0_7:	Read: TTL/CMOS Inputs 0-7
 89 *		Write: Reserved
 90 * @cos0_7:	Read: COS Status Inputs 0-7
 91 *		Write: COS Clear Inputs 0-7
 92 * @cos8_15:	Read: COS Status Inputs 8-15
 93 *		Write: COS Clear Inputs 8-15
 94 * @cos16_23:	Read: COS Status Inputs 16-23
 95 *		Write: COS Clear Inputs 16-23
 96 * @cos_ttl0_7:	Read: COS Status TTL/CMOS 0-7
 97 *		Write: COS Clear TTL/CMOS 0-7
 98 * @ctl:	Read: Control Register
 99 *		Write: Control Register
100 * @reserved:	Read: Reserved
101 *		Write: Reserved
102 * @cos_enable:	Read: COS Enable
103 *		Write: COS Enable
104 * @soft_reset:	Read: IRQ Output Pin Status
105 *		Write: Software Board Reset
106 */
107struct idio_24_gpio_reg {
108	u8 out0_7;
109	u8 out8_15;
110	u8 out16_23;
111	u8 ttl_out0_7;
112	u8 in0_7;
113	u8 in8_15;
114	u8 in16_23;
115	u8 ttl_in0_7;
116	u8 cos0_7;
117	u8 cos8_15;
118	u8 cos16_23;
119	u8 cos_ttl0_7;
120	u8 ctl;
121	u8 reserved;
122	u8 cos_enable;
123	u8 soft_reset;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124};
125
126/**
127 * struct idio_24_gpio - GPIO device private data structure
128 * @chip:	instance of the gpio_chip
129 * @lock:	synchronization lock to prevent I/O race conditions
130 * @reg:	I/O address offset for the GPIO device registers
131 * @irq_mask:	I/O bits affected by interrupts
132 */
133struct idio_24_gpio {
134	struct gpio_chip chip;
135	raw_spinlock_t lock;
136	__u8 __iomem *plx;
137	struct idio_24_gpio_reg __iomem *reg;
138	unsigned long irq_mask;
139};
140
141static int idio_24_gpio_get_direction(struct gpio_chip *chip,
142	unsigned int offset)
143{
144	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
145	const unsigned long out_mode_mask = BIT(1);
 
 
146
147	/* FET Outputs */
148	if (offset < 24)
149		return GPIO_LINE_DIRECTION_OUT;
150
151	/* Isolated Inputs */
152	if (offset < 48)
153		return GPIO_LINE_DIRECTION_IN;
154
155	/* TTL/CMOS I/O */
156	/* OUT MODE = 1 when TTL/CMOS Output Mode is set */
157	if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
158		return GPIO_LINE_DIRECTION_OUT;
159
160	return GPIO_LINE_DIRECTION_IN;
161}
162
163static int idio_24_gpio_direction_input(struct gpio_chip *chip,
164	unsigned int offset)
165{
166	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
167	unsigned long flags;
168	unsigned int ctl_state;
169	const unsigned long out_mode_mask = BIT(1);
170
171	/* TTL/CMOS I/O */
172	if (offset > 47) {
173		raw_spin_lock_irqsave(&idio24gpio->lock, flags);
174
175		/* Clear TTL/CMOS Output Mode */
176		ctl_state = ioread8(&idio24gpio->reg->ctl) & ~out_mode_mask;
177		iowrite8(ctl_state, &idio24gpio->reg->ctl);
178
179		raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
180	}
181
182	return 0;
183}
184
185static int idio_24_gpio_direction_output(struct gpio_chip *chip,
186	unsigned int offset, int value)
187{
188	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
189	unsigned long flags;
190	unsigned int ctl_state;
191	const unsigned long out_mode_mask = BIT(1);
192
193	/* TTL/CMOS I/O */
194	if (offset > 47) {
195		raw_spin_lock_irqsave(&idio24gpio->lock, flags);
196
197		/* Set TTL/CMOS Output Mode */
198		ctl_state = ioread8(&idio24gpio->reg->ctl) | out_mode_mask;
199		iowrite8(ctl_state, &idio24gpio->reg->ctl);
200
201		raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
 
 
 
 
 
 
 
 
202	}
203
204	chip->set(chip, offset, value);
205	return 0;
206}
207
208static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset)
209{
210	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
211	const unsigned long offset_mask = BIT(offset % 8);
212	const unsigned long out_mode_mask = BIT(1);
213
214	/* FET Outputs */
215	if (offset < 8)
216		return !!(ioread8(&idio24gpio->reg->out0_7) & offset_mask);
217
218	if (offset < 16)
219		return !!(ioread8(&idio24gpio->reg->out8_15) & offset_mask);
220
221	if (offset < 24)
222		return !!(ioread8(&idio24gpio->reg->out16_23) & offset_mask);
223
224	/* Isolated Inputs */
225	if (offset < 32)
226		return !!(ioread8(&idio24gpio->reg->in0_7) & offset_mask);
227
228	if (offset < 40)
229		return !!(ioread8(&idio24gpio->reg->in8_15) & offset_mask);
230
231	if (offset < 48)
232		return !!(ioread8(&idio24gpio->reg->in16_23) & offset_mask);
233
234	/* TTL/CMOS Outputs */
235	if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
236		return !!(ioread8(&idio24gpio->reg->ttl_out0_7) & offset_mask);
237
238	/* TTL/CMOS Inputs */
239	return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask);
240}
241
242static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
243	unsigned long *mask, unsigned long *bits)
244{
245	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
246	unsigned long offset;
247	unsigned long gpio_mask;
248	void __iomem *ports[] = {
249		&idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
250		&idio24gpio->reg->out16_23, &idio24gpio->reg->in0_7,
251		&idio24gpio->reg->in8_15, &idio24gpio->reg->in16_23,
252	};
253	size_t index;
254	unsigned long port_state;
255	const unsigned long out_mode_mask = BIT(1);
256
257	/* clear bits array to a clean slate */
258	bitmap_zero(bits, chip->ngpio);
259
260	for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
261		index = offset / 8;
262
263		/* read bits from current gpio port (port 6 is TTL GPIO) */
264		if (index < 6)
265			port_state = ioread8(ports[index]);
266		else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
267			port_state = ioread8(&idio24gpio->reg->ttl_out0_7);
268		else
269			port_state = ioread8(&idio24gpio->reg->ttl_in0_7);
270
271		port_state &= gpio_mask;
 
272
273		bitmap_set_value8(bits, port_state, offset);
 
 
 
 
 
 
 
 
 
274	}
275
276	return 0;
277}
278
279static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset,
280	int value)
281{
282	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
283	const unsigned long out_mode_mask = BIT(1);
284	void __iomem *base;
285	const unsigned int mask = BIT(offset % 8);
286	unsigned long flags;
287	unsigned int out_state;
288
289	/* Isolated Inputs */
290	if (offset > 23 && offset < 48)
291		return;
292
293	/* TTL/CMOS Inputs */
294	if (offset > 47 && !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask))
295		return;
296
297	/* TTL/CMOS Outputs */
298	if (offset > 47)
299		base = &idio24gpio->reg->ttl_out0_7;
300	/* FET Outputs */
301	else if (offset > 15)
302		base = &idio24gpio->reg->out16_23;
303	else if (offset > 7)
304		base = &idio24gpio->reg->out8_15;
305	else
306		base = &idio24gpio->reg->out0_7;
307
308	raw_spin_lock_irqsave(&idio24gpio->lock, flags);
309
310	if (value)
311		out_state = ioread8(base) | mask;
312	else
313		out_state = ioread8(base) & ~mask;
314
315	iowrite8(out_state, base);
316
317	raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
318}
319
320static void idio_24_gpio_set_multiple(struct gpio_chip *chip,
321	unsigned long *mask, unsigned long *bits)
322{
323	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
324	unsigned long offset;
325	unsigned long gpio_mask;
326	void __iomem *ports[] = {
327		&idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
328		&idio24gpio->reg->out16_23
329	};
330	size_t index;
331	unsigned long bitmask;
332	unsigned long flags;
333	unsigned long out_state;
334	const unsigned long out_mode_mask = BIT(1);
335
336	for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
337		index = offset / 8;
338
339		bitmask = bitmap_get_value8(bits, offset) & gpio_mask;
340
341		raw_spin_lock_irqsave(&idio24gpio->lock, flags);
342
343		/* read bits from current gpio port (port 6 is TTL GPIO) */
344		if (index < 6) {
345			out_state = ioread8(ports[index]);
346		} else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) {
347			out_state = ioread8(&idio24gpio->reg->ttl_out0_7);
348		} else {
349			/* skip TTL GPIO if set for input */
350			raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
351			continue;
352		}
353
354		/* set requested bit states */
355		out_state &= ~gpio_mask;
356		out_state |= bitmask;
357
358		/* write bits for current gpio port (port 6 is TTL GPIO) */
359		if (index < 6)
360			iowrite8(out_state, ports[index]);
361		else
362			iowrite8(out_state, &idio24gpio->reg->ttl_out0_7);
363
364		raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
365	}
366}
367
368static void idio_24_irq_ack(struct irq_data *data)
369{
370}
371
372static void idio_24_irq_mask(struct irq_data *data)
 
 
373{
374	struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
375	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
376	unsigned long flags;
377	const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
378	unsigned char new_irq_mask;
379	const unsigned long bank_offset = bit_offset / 8;
380	unsigned char cos_enable_state;
381
382	raw_spin_lock_irqsave(&idio24gpio->lock, flags);
383
384	idio24gpio->irq_mask &= ~BIT(bit_offset);
385	new_irq_mask = idio24gpio->irq_mask >> bank_offset * 8;
386
387	if (!new_irq_mask) {
388		cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
389
390		/* Disable Rising Edge detection */
391		cos_enable_state &= ~BIT(bank_offset);
392		/* Disable Falling Edge detection */
393		cos_enable_state &= ~BIT(bank_offset + 4);
394
395		iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
396	}
397
398	raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
399}
400
401static void idio_24_irq_unmask(struct irq_data *data)
402{
403	struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
404	struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
405	unsigned long flags;
406	unsigned char prev_irq_mask;
407	const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
408	const unsigned long bank_offset = bit_offset / 8;
409	unsigned char cos_enable_state;
410
411	raw_spin_lock_irqsave(&idio24gpio->lock, flags);
412
413	prev_irq_mask = idio24gpio->irq_mask >> bank_offset * 8;
414	idio24gpio->irq_mask |= BIT(bit_offset);
415
416	if (!prev_irq_mask) {
417		cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
418
419		/* Enable Rising Edge detection */
420		cos_enable_state |= BIT(bank_offset);
421		/* Enable Falling Edge detection */
422		cos_enable_state |= BIT(bank_offset + 4);
423
424		iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
425	}
 
 
 
426
427	raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
428}
 
 
 
 
 
 
 
429
430static int idio_24_irq_set_type(struct irq_data *data, unsigned int flow_type)
431{
432	/* The only valid irq types are none and both-edges */
433	if (flow_type != IRQ_TYPE_NONE &&
434		(flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
 
 
 
 
 
 
 
 
435		return -EINVAL;
436
437	return 0;
438}
439
440static struct irq_chip idio_24_irqchip = {
441	.name = "pcie-idio-24",
442	.irq_ack = idio_24_irq_ack,
443	.irq_mask = idio_24_irq_mask,
444	.irq_unmask = idio_24_irq_unmask,
445	.irq_set_type = idio_24_irq_set_type
446};
447
448static irqreturn_t idio_24_irq_handler(int irq, void *dev_id)
449{
450	struct idio_24_gpio *const idio24gpio = dev_id;
451	unsigned long irq_status;
452	struct gpio_chip *const chip = &idio24gpio->chip;
453	unsigned long irq_mask;
454	int gpio;
455
456	raw_spin_lock(&idio24gpio->lock);
457
458	/* Read Change-Of-State status */
459	irq_status = ioread32(&idio24gpio->reg->cos0_7);
460
461	raw_spin_unlock(&idio24gpio->lock);
462
463	/* Make sure our device generated IRQ */
464	if (!irq_status)
465		return IRQ_NONE;
466
467	/* Handle only unmasked IRQ */
468	irq_mask = idio24gpio->irq_mask & irq_status;
469
470	for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24)
471		generic_handle_domain_irq(chip->irq.domain, gpio + 24);
472
473	raw_spin_lock(&idio24gpio->lock);
474
475	/* Clear Change-Of-State status */
476	iowrite32(irq_status, &idio24gpio->reg->cos0_7);
477
478	raw_spin_unlock(&idio24gpio->lock);
479
480	return IRQ_HANDLED;
481}
482
483#define IDIO_24_NGPIO 56
484static const char *idio_24_names[IDIO_24_NGPIO] = {
485	"OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
486	"OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
487	"OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
488	"IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
489	"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
490	"IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
491	"TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
492};
493
494static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
495{
496	struct device *const dev = &pdev->dev;
497	struct idio_24_gpio *idio24gpio;
498	int err;
499	const size_t pci_plx_bar_index = 1;
500	const size_t pci_bar_index = 2;
501	const char *const name = pci_name(pdev);
502	struct gpio_irq_chip *girq;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
503
504	idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL);
505	if (!idio24gpio)
506		return -ENOMEM;
507
508	err = pcim_enable_device(pdev);
509	if (err) {
510		dev_err(dev, "Failed to enable PCI device (%d)\n", err);
511		return err;
512	}
513
514	err = pcim_iomap_regions(pdev, BIT(pci_plx_bar_index) | BIT(pci_bar_index), name);
515	if (err) {
516		dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
517		return err;
518	}
519
520	idio24gpio->plx = pcim_iomap_table(pdev)[pci_plx_bar_index];
521	idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
522
523	idio24gpio->chip.label = name;
524	idio24gpio->chip.parent = dev;
525	idio24gpio->chip.owner = THIS_MODULE;
526	idio24gpio->chip.base = -1;
527	idio24gpio->chip.ngpio = IDIO_24_NGPIO;
528	idio24gpio->chip.names = idio_24_names;
529	idio24gpio->chip.get_direction = idio_24_gpio_get_direction;
530	idio24gpio->chip.direction_input = idio_24_gpio_direction_input;
531	idio24gpio->chip.direction_output = idio_24_gpio_direction_output;
532	idio24gpio->chip.get = idio_24_gpio_get;
533	idio24gpio->chip.get_multiple = idio_24_gpio_get_multiple;
534	idio24gpio->chip.set = idio_24_gpio_set;
535	idio24gpio->chip.set_multiple = idio_24_gpio_set_multiple;
536
537	girq = &idio24gpio->chip.irq;
538	girq->chip = &idio_24_irqchip;
539	/* This will let us handle the parent IRQ in the driver */
540	girq->parent_handler = NULL;
541	girq->num_parents = 0;
542	girq->parents = NULL;
543	girq->default_type = IRQ_TYPE_NONE;
544	girq->handler = handle_edge_irq;
545
546	raw_spin_lock_init(&idio24gpio->lock);
 
 
 
 
 
 
 
 
 
547
548	/* Software board reset */
549	iowrite8(0, &idio24gpio->reg->soft_reset);
 
 
550	/*
551	 * enable PLX PEX8311 internal PCI wire interrupt and local interrupt
552	 * input
553	 */
554	iowrite8((INTCSR_INTERNAL_PCI_WIRE | INTCSR_LOCAL_INPUT) >> 8,
555		 idio24gpio->plx + PLX_PEX8311_PCI_LCS_INTCSR + 1);
556
557	err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio);
558	if (err) {
559		dev_err(dev, "GPIO registering failed (%d)\n", err);
560		return err;
561	}
562
563	err = devm_request_irq(dev, pdev->irq, idio_24_irq_handler, IRQF_SHARED,
564		name, idio24gpio);
565	if (err) {
566		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
567		return err;
568	}
 
 
 
 
 
 
 
 
 
569
570	return 0;
571}
572
573static const struct pci_device_id idio_24_pci_dev_id[] = {
574	{ PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) },
575	{ PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) },
576	{ 0 }
577};
578MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id);
579
580static struct pci_driver idio_24_driver = {
581	.name = "pcie-idio-24",
582	.id_table = idio_24_pci_dev_id,
583	.probe = idio_24_probe
584};
585
586module_pci_driver(idio_24_driver);
587
588MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
589MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
590MODULE_LICENSE("GPL v2");
v6.13.7
  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 driver supports the following ACCES devices: PCIe-IDIO-24,
  7 * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12.
  8 */
  9#include <linux/bits.h>
 
 10#include <linux/device.h>
 11#include <linux/err.h>
 12#include <linux/gpio/regmap.h>
 13#include <linux/irq.h>
 
 14#include <linux/kernel.h>
 15#include <linux/module.h>
 16#include <linux/pci.h>
 17#include <linux/regmap.h>
 18#include <linux/spinlock.h>
 19#include <linux/types.h>
 20
 21/*
 22 * PLX PEX8311 PCI LCS_INTCSR Interrupt Control/Status
 23 *
 24 * Bit: Description
 25 *   0: Enable Interrupt Sources (Bit 0)
 26 *   1: Enable Interrupt Sources (Bit 1)
 27 *   2: Generate Internal PCI Bus Internal SERR# Interrupt
 28 *   3: Mailbox Interrupt Enable
 29 *   4: Power Management Interrupt Enable
 30 *   5: Power Management Interrupt
 31 *   6: Slave Read Local Data Parity Check Error Enable
 32 *   7: Slave Read Local Data Parity Check Error Status
 33 *   8: Internal PCI Wire Interrupt Enable
 34 *   9: PCI Express Doorbell Interrupt Enable
 35 *  10: PCI Abort Interrupt Enable
 36 *  11: Local Interrupt Input Enable
 37 *  12: Retry Abort Enable
 38 *  13: PCI Express Doorbell Interrupt Active
 39 *  14: PCI Abort Interrupt Active
 40 *  15: Local Interrupt Input Active
 41 *  16: Local Interrupt Output Enable
 42 *  17: Local Doorbell Interrupt Enable
 43 *  18: DMA Channel 0 Interrupt Enable
 44 *  19: DMA Channel 1 Interrupt Enable
 45 *  20: Local Doorbell Interrupt Active
 46 *  21: DMA Channel 0 Interrupt Active
 47 *  22: DMA Channel 1 Interrupt Active
 48 *  23: Built-In Self-Test (BIST) Interrupt Active
 49 *  24: Direct Master was the Bus Master during a Master or Target Abort
 50 *  25: DMA Channel 0 was the Bus Master during a Master or Target Abort
 51 *  26: DMA Channel 1 was the Bus Master during a Master or Target Abort
 52 *  27: Target Abort after internal 256 consecutive Master Retrys
 53 *  28: PCI Bus wrote data to LCS_MBOX0
 54 *  29: PCI Bus wrote data to LCS_MBOX1
 55 *  30: PCI Bus wrote data to LCS_MBOX2
 56 *  31: PCI Bus wrote data to LCS_MBOX3
 57 */
 58#define PLX_PEX8311_PCI_LCS_INTCSR  0x68
 59#define INTCSR_INTERNAL_PCI_WIRE    BIT(8)
 60#define INTCSR_LOCAL_INPUT          BIT(11)
 61#define IDIO_24_ENABLE_IRQ          (INTCSR_INTERNAL_PCI_WIRE | INTCSR_LOCAL_INPUT)
 62
 63#define IDIO_24_OUT_BASE 0x0
 64#define IDIO_24_TTLCMOS_OUT_REG 0x3
 65#define IDIO_24_IN_BASE 0x4
 66#define IDIO_24_TTLCMOS_IN_REG 0x7
 67#define IDIO_24_COS_STATUS_BASE 0x8
 68#define IDIO_24_CONTROL_REG 0xC
 69#define IDIO_24_COS_ENABLE 0xE
 70#define IDIO_24_SOFT_RESET 0xF
 71
 72#define CONTROL_REG_OUT_MODE BIT(1)
 73
 74#define COS_ENABLE_RISING BIT(1)
 75#define COS_ENABLE_FALLING BIT(4)
 76#define COS_ENABLE_BOTH (COS_ENABLE_RISING | COS_ENABLE_FALLING)
 77
 78static const struct regmap_config pex8311_intcsr_regmap_config = {
 79	.name = "pex8311_intcsr",
 80	.reg_bits = 32,
 81	.reg_stride = 1,
 82	.reg_base = PLX_PEX8311_PCI_LCS_INTCSR,
 83	.val_bits = 32,
 84	.io_port = true,
 85};
 86
 87static const struct regmap_range idio_24_wr_ranges[] = {
 88	regmap_reg_range(0x0, 0x3), regmap_reg_range(0x8, 0xC),
 89	regmap_reg_range(0xE, 0xF),
 90};
 91static const struct regmap_range idio_24_rd_ranges[] = {
 92	regmap_reg_range(0x0, 0xC), regmap_reg_range(0xE, 0xF),
 93};
 94static const struct regmap_range idio_24_volatile_ranges[] = {
 95	regmap_reg_range(0x4, 0xB), regmap_reg_range(0xF, 0xF),
 96};
 97static const struct regmap_access_table idio_24_wr_table = {
 98	.yes_ranges = idio_24_wr_ranges,
 99	.n_yes_ranges = ARRAY_SIZE(idio_24_wr_ranges),
100};
101static const struct regmap_access_table idio_24_rd_table = {
102	.yes_ranges = idio_24_rd_ranges,
103	.n_yes_ranges = ARRAY_SIZE(idio_24_rd_ranges),
104};
105static const struct regmap_access_table idio_24_volatile_table = {
106	.yes_ranges = idio_24_volatile_ranges,
107	.n_yes_ranges = ARRAY_SIZE(idio_24_volatile_ranges),
108};
109
110static const struct regmap_config idio_24_regmap_config = {
111	.reg_bits = 8,
112	.reg_stride = 1,
113	.val_bits = 8,
114	.io_port = true,
115	.wr_table = &idio_24_wr_table,
116	.rd_table = &idio_24_rd_table,
117	.volatile_table = &idio_24_volatile_table,
118	.cache_type = REGCACHE_FLAT,
119	.use_raw_spinlock = true,
120};
121
122#define IDIO_24_NGPIO_PER_REG 8
123#define IDIO_24_REGMAP_IRQ(_id)						\
124	[24 + _id] = {							\
125		.reg_offset = (_id) / IDIO_24_NGPIO_PER_REG,		\
126		.mask = BIT((_id) % IDIO_24_NGPIO_PER_REG),		\
127		.type = { .types_supported = IRQ_TYPE_EDGE_BOTH },	\
128	}
129#define IDIO_24_IIN_IRQ(_id) IDIO_24_REGMAP_IRQ(_id)
130#define IDIO_24_TTL_IRQ(_id) IDIO_24_REGMAP_IRQ(24 + _id)
131
132static const struct regmap_irq idio_24_regmap_irqs[] = {
133	IDIO_24_IIN_IRQ(0), IDIO_24_IIN_IRQ(1), IDIO_24_IIN_IRQ(2), /* IIN 0-2 */
134	IDIO_24_IIN_IRQ(3), IDIO_24_IIN_IRQ(4), IDIO_24_IIN_IRQ(5), /* IIN 3-5 */
135	IDIO_24_IIN_IRQ(6), IDIO_24_IIN_IRQ(7), IDIO_24_IIN_IRQ(8), /* IIN 6-8 */
136	IDIO_24_IIN_IRQ(9), IDIO_24_IIN_IRQ(10), IDIO_24_IIN_IRQ(11), /* IIN 9-11 */
137	IDIO_24_IIN_IRQ(12), IDIO_24_IIN_IRQ(13), IDIO_24_IIN_IRQ(14), /* IIN 12-14 */
138	IDIO_24_IIN_IRQ(15), IDIO_24_IIN_IRQ(16), IDIO_24_IIN_IRQ(17), /* IIN 15-17 */
139	IDIO_24_IIN_IRQ(18), IDIO_24_IIN_IRQ(19), IDIO_24_IIN_IRQ(20), /* IIN 18-20 */
140	IDIO_24_IIN_IRQ(21), IDIO_24_IIN_IRQ(22), IDIO_24_IIN_IRQ(23), /* IIN 21-23 */
141	IDIO_24_TTL_IRQ(0), IDIO_24_TTL_IRQ(1), IDIO_24_TTL_IRQ(2), /* TTL 0-2 */
142	IDIO_24_TTL_IRQ(3), IDIO_24_TTL_IRQ(4), IDIO_24_TTL_IRQ(5), /* TTL 3-5 */
143	IDIO_24_TTL_IRQ(6), IDIO_24_TTL_IRQ(7), /* TTL 6-7 */
144};
145
146/**
147 * struct idio_24_gpio - GPIO device private data structure
148 * @map:	regmap for the device
149 * @lock:	synchronization lock to prevent I/O race conditions
150 * @irq_type:	type configuration for IRQs
 
151 */
152struct idio_24_gpio {
153	struct regmap *map;
154	raw_spinlock_t lock;
155	u8 irq_type;
 
 
156};
157
158static int idio_24_handle_mask_sync(const int index, const unsigned int mask_buf_def,
159				    const unsigned int mask_buf, void *const irq_drv_data)
160{
161	const unsigned int type_mask = COS_ENABLE_BOTH << index;
162	struct idio_24_gpio *const idio24gpio = irq_drv_data;
163	u8 type;
164	int ret;
165
166	raw_spin_lock(&idio24gpio->lock);
 
 
 
 
 
 
 
 
 
 
 
167
168	/* if all are masked, then disable interrupts, else set to type */
169	type = (mask_buf == mask_buf_def) ? ~type_mask : idio24gpio->irq_type;
170
171	ret = regmap_update_bits(idio24gpio->map, IDIO_24_COS_ENABLE, type_mask, type);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
173	raw_spin_unlock(&idio24gpio->lock);
 
174
175	return ret;
176}
177
178static int idio_24_set_type_config(unsigned int **const buf, const unsigned int type,
179				   const struct regmap_irq *const irq_data, const int idx,
180				   void *const irq_drv_data)
181{
182	const unsigned int offset = irq_data->reg_offset;
183	const unsigned int rising = COS_ENABLE_RISING << offset;
184	const unsigned int falling = COS_ENABLE_FALLING << offset;
185	const unsigned int mask = COS_ENABLE_BOTH << offset;
186	struct idio_24_gpio *const idio24gpio = irq_drv_data;
187	unsigned int new;
188	unsigned int cos_enable;
189	int ret;
190
191	switch (type) {
192	case IRQ_TYPE_EDGE_RISING:
193		new = rising;
194		break;
195	case IRQ_TYPE_EDGE_FALLING:
196		new = falling;
197		break;
198	case IRQ_TYPE_EDGE_BOTH:
199		new = mask;
200		break;
201	default:
202		return -EINVAL;
203	}
204
205	raw_spin_lock(&idio24gpio->lock);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
207	/* replace old bitmap with new bitmap */
208	idio24gpio->irq_type = (idio24gpio->irq_type & ~mask) | (new & mask);
209
210	ret = regmap_read(idio24gpio->map, IDIO_24_COS_ENABLE, &cos_enable);
211	if (ret)
212		goto exit_unlock;
213
214	/* if COS is currently enabled then update the edge type */
215	if (cos_enable & mask) {
216		ret = regmap_update_bits(idio24gpio->map, IDIO_24_COS_ENABLE, mask,
217					 idio24gpio->irq_type);
218		if (ret)
219			goto exit_unlock;
220	}
221
222exit_unlock:
223	raw_spin_unlock(&idio24gpio->lock);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
225	return ret;
 
226}
227
228static int idio_24_reg_mask_xlate(struct gpio_regmap *const gpio, const unsigned int base,
229				  const unsigned int offset, unsigned int *const reg,
230				  unsigned int *const mask)
231{
232	const unsigned int out_stride = offset / IDIO_24_NGPIO_PER_REG;
233	const unsigned int in_stride = (offset - 24) / IDIO_24_NGPIO_PER_REG;
234	struct regmap *const map = gpio_regmap_get_drvdata(gpio);
235	int err;
236	unsigned int ctrl_reg;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
238	switch (base) {
239	case IDIO_24_OUT_BASE:
240		*mask = BIT(offset % IDIO_24_NGPIO_PER_REG);
241
242		/* FET Outputs */
243		if (offset < 24) {
244			*reg = IDIO_24_OUT_BASE + out_stride;
245			return 0;
246		}
 
 
 
 
 
 
 
 
 
 
 
 
 
247
248		/* Isolated Inputs */
249		if (offset < 48) {
250			*reg = IDIO_24_IN_BASE + in_stride;
251			return 0;
252		}
253
254		err = regmap_read(map, IDIO_24_CONTROL_REG, &ctrl_reg);
255		if (err)
256			return err;
257
258		/* TTL/CMOS Outputs */
259		if (ctrl_reg & CONTROL_REG_OUT_MODE) {
260			*reg = IDIO_24_TTLCMOS_OUT_REG;
261			return 0;
262		}
263
264		/* TTL/CMOS Inputs */
265		*reg = IDIO_24_TTLCMOS_IN_REG;
266		return 0;
267	case IDIO_24_CONTROL_REG:
268		/* We can only set direction for TTL/CMOS lines */
269		if (offset < 48)
270			return -ENOTSUPP;
271
272		*reg = IDIO_24_CONTROL_REG;
273		*mask = CONTROL_REG_OUT_MODE;
274		return 0;
275	default:
276		/* Should never reach this path */
277		return -EINVAL;
278	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279}
280
281#define IDIO_24_NGPIO 56
282static const char *idio_24_names[IDIO_24_NGPIO] = {
283	"OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
284	"OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
285	"OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
286	"IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
287	"IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
288	"IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
289	"TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
290};
291
292static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
293{
294	struct device *const dev = &pdev->dev;
295	struct idio_24_gpio *idio24gpio;
296	int err;
297	const size_t pci_plx_bar_index = 1;
298	const size_t pci_bar_index = 2;
299	const char *const name = pci_name(pdev);
300	struct gpio_regmap_config gpio_config = {};
301	void __iomem *pex8311_regs;
302	void __iomem *idio_24_regs;
303	struct regmap *intcsr_map;
304	struct regmap_irq_chip *chip;
305	struct regmap_irq_chip_data *chip_data;
306
307	err = pcim_enable_device(pdev);
308	if (err)
309		return dev_err_probe(dev, err, "Failed to enable PCI device\n");
310
311	pex8311_regs = pcim_iomap_region(pdev, pci_plx_bar_index, "pex8311");
312	if (IS_ERR(pex8311_regs))
313		return dev_err_probe(dev, PTR_ERR(pex8311_regs), "Unable to map PEX 8311 I/O addresses\n");
314
315	idio_24_regs = pcim_iomap_region(pdev, pci_bar_index, name);
316	if (IS_ERR(idio_24_regs))
317		return dev_err_probe(dev, PTR_ERR(idio_24_regs), "Unable to map PCIe-IDIO-24 I/O addresses\n");
318
319	intcsr_map = devm_regmap_init_mmio(dev, pex8311_regs, &pex8311_intcsr_regmap_config);
320	if (IS_ERR(intcsr_map))
321		return dev_err_probe(dev, PTR_ERR(intcsr_map),
322				     "Unable to initialize PEX8311 register map\n");
323
324	idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL);
325	if (!idio24gpio)
326		return -ENOMEM;
327
328	idio24gpio->map = devm_regmap_init_mmio(dev, idio_24_regs, &idio_24_regmap_config);
329	if (IS_ERR(idio24gpio->map))
330		return dev_err_probe(dev, PTR_ERR(idio24gpio->map),
331				     "Unable to initialize register map\n");
 
332
333	raw_spin_lock_init(&idio24gpio->lock);
 
 
 
 
334
335	/* Initialize all IRQ type configuration to IRQ_TYPE_EDGE_BOTH */
336	idio24gpio->irq_type = GENMASK(7, 0);
337
338	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
339	if (!chip)
340		return -ENOMEM;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
342	chip->name = name;
343	chip->status_base = IDIO_24_COS_STATUS_BASE;
344	chip->mask_base = IDIO_24_COS_ENABLE;
345	chip->ack_base = IDIO_24_COS_STATUS_BASE;
346	chip->num_regs = 4;
347	chip->irqs = idio_24_regmap_irqs;
348	chip->num_irqs = ARRAY_SIZE(idio_24_regmap_irqs);
349	chip->handle_mask_sync = idio_24_handle_mask_sync;
350	chip->set_type_config = idio_24_set_type_config;
351	chip->irq_drv_data = idio24gpio;
352
353	/* Software board reset */
354	err = regmap_write(idio24gpio->map, IDIO_24_SOFT_RESET, 0);
355	if (err)
356		return err;
357	/*
358	 * enable PLX PEX8311 internal PCI wire interrupt and local interrupt
359	 * input
360	 */
361	err = regmap_update_bits(intcsr_map, 0x0, IDIO_24_ENABLE_IRQ, IDIO_24_ENABLE_IRQ);
362	if (err)
 
 
 
 
363		return err;
 
364
365	err = devm_regmap_add_irq_chip(dev, idio24gpio->map, pdev->irq, 0, 0, chip, &chip_data);
366	if (err)
367		return dev_err_probe(dev, err, "IRQ registration failed\n");
368
369	gpio_config.parent = dev;
370	gpio_config.regmap = idio24gpio->map;
371	gpio_config.ngpio = IDIO_24_NGPIO;
372	gpio_config.names = idio_24_names;
373	gpio_config.reg_dat_base = GPIO_REGMAP_ADDR(IDIO_24_OUT_BASE);
374	gpio_config.reg_set_base = GPIO_REGMAP_ADDR(IDIO_24_OUT_BASE);
375	gpio_config.reg_dir_out_base = GPIO_REGMAP_ADDR(IDIO_24_CONTROL_REG);
376	gpio_config.ngpio_per_reg = IDIO_24_NGPIO_PER_REG;
377	gpio_config.irq_domain = regmap_irq_get_domain(chip_data);
378	gpio_config.reg_mask_xlate = idio_24_reg_mask_xlate;
379	gpio_config.drvdata = idio24gpio->map;
380
381	return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config));
382}
383
384static const struct pci_device_id idio_24_pci_dev_id[] = {
385	{ PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) },
386	{ PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) },
387	{ 0 }
388};
389MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id);
390
391static struct pci_driver idio_24_driver = {
392	.name = "pcie-idio-24",
393	.id_table = idio_24_pci_dev_id,
394	.probe = idio_24_probe
395};
396
397module_pci_driver(idio_24_driver);
398
399MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
400MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
401MODULE_LICENSE("GPL v2");