cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gpio-pci-idio-16.c (10011B)


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