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-timberdale.c (6981B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Timberdale FPGA GPIO driver
      4 * Author: Mocean Laboratories
      5 * Copyright (c) 2009 Intel Corporation
      6 */
      7
      8/* Supports:
      9 * Timberdale FPGA GPIO
     10 */
     11
     12#include <linux/init.h>
     13#include <linux/gpio/driver.h>
     14#include <linux/platform_device.h>
     15#include <linux/irq.h>
     16#include <linux/io.h>
     17#include <linux/timb_gpio.h>
     18#include <linux/interrupt.h>
     19#include <linux/slab.h>
     20
     21#define DRIVER_NAME "timb-gpio"
     22
     23#define TGPIOVAL	0x00
     24#define TGPIODIR	0x04
     25#define TGPIO_IER	0x08
     26#define TGPIO_ISR	0x0c
     27#define TGPIO_IPR	0x10
     28#define TGPIO_ICR	0x14
     29#define TGPIO_FLR	0x18
     30#define TGPIO_LVR	0x1c
     31#define TGPIO_VER	0x20
     32#define TGPIO_BFLR	0x24
     33
     34struct timbgpio {
     35	void __iomem		*membase;
     36	spinlock_t		lock; /* mutual exclusion */
     37	struct gpio_chip	gpio;
     38	int			irq_base;
     39	unsigned long		last_ier;
     40};
     41
     42static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index,
     43	unsigned offset, bool enabled)
     44{
     45	struct timbgpio *tgpio = gpiochip_get_data(gpio);
     46	u32 reg;
     47
     48	spin_lock(&tgpio->lock);
     49	reg = ioread32(tgpio->membase + offset);
     50
     51	if (enabled)
     52		reg |= (1 << index);
     53	else
     54		reg &= ~(1 << index);
     55
     56	iowrite32(reg, tgpio->membase + offset);
     57	spin_unlock(&tgpio->lock);
     58
     59	return 0;
     60}
     61
     62static int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
     63{
     64	return timbgpio_update_bit(gpio, nr, TGPIODIR, true);
     65}
     66
     67static int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
     68{
     69	struct timbgpio *tgpio = gpiochip_get_data(gpio);
     70	u32 value;
     71
     72	value = ioread32(tgpio->membase + TGPIOVAL);
     73	return (value & (1 << nr)) ? 1 : 0;
     74}
     75
     76static int timbgpio_gpio_direction_output(struct gpio_chip *gpio,
     77						unsigned nr, int val)
     78{
     79	return timbgpio_update_bit(gpio, nr, TGPIODIR, false);
     80}
     81
     82static void timbgpio_gpio_set(struct gpio_chip *gpio,
     83				unsigned nr, int val)
     84{
     85	timbgpio_update_bit(gpio, nr, TGPIOVAL, val != 0);
     86}
     87
     88static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset)
     89{
     90	struct timbgpio *tgpio = gpiochip_get_data(gpio);
     91
     92	if (tgpio->irq_base <= 0)
     93		return -EINVAL;
     94
     95	return tgpio->irq_base + offset;
     96}
     97
     98/*
     99 * GPIO IRQ
    100 */
    101static void timbgpio_irq_disable(struct irq_data *d)
    102{
    103	struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
    104	int offset = d->irq - tgpio->irq_base;
    105	unsigned long flags;
    106
    107	spin_lock_irqsave(&tgpio->lock, flags);
    108	tgpio->last_ier &= ~(1UL << offset);
    109	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
    110	spin_unlock_irqrestore(&tgpio->lock, flags);
    111}
    112
    113static void timbgpio_irq_enable(struct irq_data *d)
    114{
    115	struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
    116	int offset = d->irq - tgpio->irq_base;
    117	unsigned long flags;
    118
    119	spin_lock_irqsave(&tgpio->lock, flags);
    120	tgpio->last_ier |= 1UL << offset;
    121	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
    122	spin_unlock_irqrestore(&tgpio->lock, flags);
    123}
    124
    125static int timbgpio_irq_type(struct irq_data *d, unsigned trigger)
    126{
    127	struct timbgpio *tgpio = irq_data_get_irq_chip_data(d);
    128	int offset = d->irq - tgpio->irq_base;
    129	unsigned long flags;
    130	u32 lvr, flr, bflr = 0;
    131	u32 ver;
    132	int ret = 0;
    133
    134	if (offset < 0 || offset > tgpio->gpio.ngpio)
    135		return -EINVAL;
    136
    137	ver = ioread32(tgpio->membase + TGPIO_VER);
    138
    139	spin_lock_irqsave(&tgpio->lock, flags);
    140
    141	lvr = ioread32(tgpio->membase + TGPIO_LVR);
    142	flr = ioread32(tgpio->membase + TGPIO_FLR);
    143	if (ver > 2)
    144		bflr = ioread32(tgpio->membase + TGPIO_BFLR);
    145
    146	if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
    147		bflr &= ~(1 << offset);
    148		flr &= ~(1 << offset);
    149		if (trigger & IRQ_TYPE_LEVEL_HIGH)
    150			lvr |= 1 << offset;
    151		else
    152			lvr &= ~(1 << offset);
    153	}
    154
    155	if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
    156		if (ver < 3) {
    157			ret = -EINVAL;
    158			goto out;
    159		} else {
    160			flr |= 1 << offset;
    161			bflr |= 1 << offset;
    162		}
    163	} else {
    164		bflr &= ~(1 << offset);
    165		flr |= 1 << offset;
    166		if (trigger & IRQ_TYPE_EDGE_FALLING)
    167			lvr &= ~(1 << offset);
    168		else
    169			lvr |= 1 << offset;
    170	}
    171
    172	iowrite32(lvr, tgpio->membase + TGPIO_LVR);
    173	iowrite32(flr, tgpio->membase + TGPIO_FLR);
    174	if (ver > 2)
    175		iowrite32(bflr, tgpio->membase + TGPIO_BFLR);
    176
    177	iowrite32(1 << offset, tgpio->membase + TGPIO_ICR);
    178
    179out:
    180	spin_unlock_irqrestore(&tgpio->lock, flags);
    181	return ret;
    182}
    183
    184static void timbgpio_irq(struct irq_desc *desc)
    185{
    186	struct timbgpio *tgpio = irq_desc_get_handler_data(desc);
    187	struct irq_data *data = irq_desc_get_irq_data(desc);
    188	unsigned long ipr;
    189	int offset;
    190
    191	data->chip->irq_ack(data);
    192	ipr = ioread32(tgpio->membase + TGPIO_IPR);
    193	iowrite32(ipr, tgpio->membase + TGPIO_ICR);
    194
    195	/*
    196	 * Some versions of the hardware trash the IER register if more than
    197	 * one interrupt is received simultaneously.
    198	 */
    199	iowrite32(0, tgpio->membase + TGPIO_IER);
    200
    201	for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio)
    202		generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset));
    203
    204	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
    205}
    206
    207static struct irq_chip timbgpio_irqchip = {
    208	.name		= "GPIO",
    209	.irq_enable	= timbgpio_irq_enable,
    210	.irq_disable	= timbgpio_irq_disable,
    211	.irq_set_type	= timbgpio_irq_type,
    212};
    213
    214static int timbgpio_probe(struct platform_device *pdev)
    215{
    216	int err, i;
    217	struct device *dev = &pdev->dev;
    218	struct gpio_chip *gc;
    219	struct timbgpio *tgpio;
    220	struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
    221	int irq = platform_get_irq(pdev, 0);
    222
    223	if (!pdata || pdata->nr_pins > 32) {
    224		dev_err(dev, "Invalid platform data\n");
    225		return -EINVAL;
    226	}
    227
    228	tgpio = devm_kzalloc(dev, sizeof(*tgpio), GFP_KERNEL);
    229	if (!tgpio)
    230		return -EINVAL;
    231
    232	tgpio->irq_base = pdata->irq_base;
    233
    234	spin_lock_init(&tgpio->lock);
    235
    236	tgpio->membase = devm_platform_ioremap_resource(pdev, 0);
    237	if (IS_ERR(tgpio->membase))
    238		return PTR_ERR(tgpio->membase);
    239
    240	gc = &tgpio->gpio;
    241
    242	gc->label = dev_name(&pdev->dev);
    243	gc->owner = THIS_MODULE;
    244	gc->parent = &pdev->dev;
    245	gc->direction_input = timbgpio_gpio_direction_input;
    246	gc->get = timbgpio_gpio_get;
    247	gc->direction_output = timbgpio_gpio_direction_output;
    248	gc->set = timbgpio_gpio_set;
    249	gc->to_irq = (irq >= 0 && tgpio->irq_base > 0) ? timbgpio_to_irq : NULL;
    250	gc->dbg_show = NULL;
    251	gc->base = pdata->gpio_base;
    252	gc->ngpio = pdata->nr_pins;
    253	gc->can_sleep = false;
    254
    255	err = devm_gpiochip_add_data(&pdev->dev, gc, tgpio);
    256	if (err)
    257		return err;
    258
    259	platform_set_drvdata(pdev, tgpio);
    260
    261	/* make sure to disable interrupts */
    262	iowrite32(0x0, tgpio->membase + TGPIO_IER);
    263
    264	if (irq < 0 || tgpio->irq_base <= 0)
    265		return 0;
    266
    267	for (i = 0; i < pdata->nr_pins; i++) {
    268		irq_set_chip_and_handler(tgpio->irq_base + i,
    269			&timbgpio_irqchip, handle_simple_irq);
    270		irq_set_chip_data(tgpio->irq_base + i, tgpio);
    271		irq_clear_status_flags(tgpio->irq_base + i, IRQ_NOREQUEST | IRQ_NOPROBE);
    272	}
    273
    274	irq_set_chained_handler_and_data(irq, timbgpio_irq, tgpio);
    275
    276	return 0;
    277}
    278
    279static struct platform_driver timbgpio_platform_driver = {
    280	.driver = {
    281		.name			= DRIVER_NAME,
    282		.suppress_bind_attrs	= true,
    283	},
    284	.probe		= timbgpio_probe,
    285};
    286
    287/*--------------------------------------------------------------------------*/
    288
    289builtin_platform_driver(timbgpio_platform_driver);