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-vr41xx.c (11831B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 *  Driver for NEC VR4100 series General-purpose I/O Unit.
      4 *
      5 *  Copyright (C) 2002 MontaVista Software Inc.
      6 *	Author: Yoichi Yuasa <source@mvista.com>
      7 *  Copyright (C) 2003-2009  Yoichi Yuasa <yuasa@linux-mips.org>
      8 */
      9#include <linux/errno.h>
     10#include <linux/fs.h>
     11#include <linux/gpio/driver.h>
     12#include <linux/init.h>
     13#include <linux/interrupt.h>
     14#include <linux/io.h>
     15#include <linux/irq.h>
     16#include <linux/kernel.h>
     17#include <linux/module.h>
     18#include <linux/platform_device.h>
     19#include <linux/spinlock.h>
     20#include <linux/types.h>
     21
     22#include <asm/vr41xx/giu.h>
     23#include <asm/vr41xx/irq.h>
     24#include <asm/vr41xx/vr41xx.h>
     25
     26MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
     27MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
     28MODULE_LICENSE("GPL");
     29
     30#define GIUIOSELL	0x00
     31#define GIUIOSELH	0x02
     32#define GIUPIODL	0x04
     33#define GIUPIODH	0x06
     34#define GIUINTSTATL	0x08
     35#define GIUINTSTATH	0x0a
     36#define GIUINTENL	0x0c
     37#define GIUINTENH	0x0e
     38#define GIUINTTYPL	0x10
     39#define GIUINTTYPH	0x12
     40#define GIUINTALSELL	0x14
     41#define GIUINTALSELH	0x16
     42#define GIUINTHTSELL	0x18
     43#define GIUINTHTSELH	0x1a
     44#define GIUPODATL	0x1c
     45#define GIUPODATEN	0x1c
     46#define GIUPODATH	0x1e
     47 #define PIOEN0		0x0100
     48 #define PIOEN1		0x0200
     49#define GIUPODAT	0x1e
     50#define GIUFEDGEINHL	0x20
     51#define GIUFEDGEINHH	0x22
     52#define GIUREDGEINHL	0x24
     53#define GIUREDGEINHH	0x26
     54
     55#define GIUUSEUPDN	0x1e0
     56#define GIUTERMUPDN	0x1e2
     57
     58#define GPIO_HAS_PULLUPDOWN_IO		0x0001
     59#define GPIO_HAS_OUTPUT_ENABLE		0x0002
     60#define GPIO_HAS_INTERRUPT_EDGE_SELECT	0x0100
     61
     62enum {
     63	GPIO_INPUT,
     64	GPIO_OUTPUT,
     65};
     66
     67static DEFINE_SPINLOCK(giu_lock);
     68static unsigned long giu_flags;
     69
     70static void __iomem *giu_base;
     71static struct gpio_chip vr41xx_gpio_chip;
     72
     73#define giu_read(offset)		readw(giu_base + (offset))
     74#define giu_write(offset, value)	writew((value), giu_base + (offset))
     75
     76#define GPIO_PIN_OF_IRQ(irq)	((irq) - GIU_IRQ_BASE)
     77#define GIUINT_HIGH_OFFSET	16
     78#define GIUINT_HIGH_MAX		32
     79
     80static inline u16 giu_set(u16 offset, u16 set)
     81{
     82	u16 data;
     83
     84	data = giu_read(offset);
     85	data |= set;
     86	giu_write(offset, data);
     87
     88	return data;
     89}
     90
     91static inline u16 giu_clear(u16 offset, u16 clear)
     92{
     93	u16 data;
     94
     95	data = giu_read(offset);
     96	data &= ~clear;
     97	giu_write(offset, data);
     98
     99	return data;
    100}
    101
    102static void ack_giuint_low(struct irq_data *d)
    103{
    104	giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(d->irq));
    105}
    106
    107static void mask_giuint_low(struct irq_data *d)
    108{
    109	giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
    110}
    111
    112static void mask_ack_giuint_low(struct irq_data *d)
    113{
    114	unsigned int pin;
    115
    116	pin = GPIO_PIN_OF_IRQ(d->irq);
    117	giu_clear(GIUINTENL, 1 << pin);
    118	giu_write(GIUINTSTATL, 1 << pin);
    119}
    120
    121static void unmask_giuint_low(struct irq_data *d)
    122{
    123	giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));
    124}
    125
    126static unsigned int startup_giuint(struct irq_data *data)
    127{
    128	int ret;
    129
    130	ret = gpiochip_lock_as_irq(&vr41xx_gpio_chip, irqd_to_hwirq(data));
    131	if (ret) {
    132		dev_err(vr41xx_gpio_chip.parent,
    133			"unable to lock HW IRQ %lu for IRQ\n",
    134			data->hwirq);
    135		return ret;
    136	}
    137
    138	/* Satisfy the .enable semantics by unmasking the line */
    139	unmask_giuint_low(data);
    140	return 0;
    141}
    142
    143static void shutdown_giuint(struct irq_data *data)
    144{
    145	mask_giuint_low(data);
    146	gpiochip_unlock_as_irq(&vr41xx_gpio_chip, data->hwirq);
    147}
    148
    149static struct irq_chip giuint_low_irq_chip = {
    150	.name		= "GIUINTL",
    151	.irq_ack	= ack_giuint_low,
    152	.irq_mask	= mask_giuint_low,
    153	.irq_mask_ack	= mask_ack_giuint_low,
    154	.irq_unmask	= unmask_giuint_low,
    155	.irq_startup	= startup_giuint,
    156	.irq_shutdown	= shutdown_giuint,
    157};
    158
    159static void ack_giuint_high(struct irq_data *d)
    160{
    161	giu_write(GIUINTSTATH,
    162		  1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
    163}
    164
    165static void mask_giuint_high(struct irq_data *d)
    166{
    167	giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
    168}
    169
    170static void mask_ack_giuint_high(struct irq_data *d)
    171{
    172	unsigned int pin;
    173
    174	pin = GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET;
    175	giu_clear(GIUINTENH, 1 << pin);
    176	giu_write(GIUINTSTATH, 1 << pin);
    177}
    178
    179static void unmask_giuint_high(struct irq_data *d)
    180{
    181	giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET));
    182}
    183
    184static struct irq_chip giuint_high_irq_chip = {
    185	.name		= "GIUINTH",
    186	.irq_ack	= ack_giuint_high,
    187	.irq_mask	= mask_giuint_high,
    188	.irq_mask_ack	= mask_ack_giuint_high,
    189	.irq_unmask	= unmask_giuint_high,
    190};
    191
    192static int giu_get_irq(unsigned int irq)
    193{
    194	u16 pendl, pendh, maskl, maskh;
    195	int i;
    196
    197	pendl = giu_read(GIUINTSTATL);
    198	pendh = giu_read(GIUINTSTATH);
    199	maskl = giu_read(GIUINTENL);
    200	maskh = giu_read(GIUINTENH);
    201
    202	maskl &= pendl;
    203	maskh &= pendh;
    204
    205	if (maskl) {
    206		for (i = 0; i < 16; i++) {
    207			if (maskl & (1 << i))
    208				return GIU_IRQ(i);
    209		}
    210	} else if (maskh) {
    211		for (i = 0; i < 16; i++) {
    212			if (maskh & (1 << i))
    213				return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
    214		}
    215	}
    216
    217	printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
    218	       maskl, pendl, maskh, pendh);
    219
    220	return -EINVAL;
    221}
    222
    223void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
    224			    irq_signal_t signal)
    225{
    226	u16 mask;
    227
    228	if (pin < GIUINT_HIGH_OFFSET) {
    229		mask = 1 << pin;
    230		if (trigger != IRQ_TRIGGER_LEVEL) {
    231			giu_set(GIUINTTYPL, mask);
    232			if (signal == IRQ_SIGNAL_HOLD)
    233				giu_set(GIUINTHTSELL, mask);
    234			else
    235				giu_clear(GIUINTHTSELL, mask);
    236			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
    237				switch (trigger) {
    238				case IRQ_TRIGGER_EDGE_FALLING:
    239					giu_set(GIUFEDGEINHL, mask);
    240					giu_clear(GIUREDGEINHL, mask);
    241					break;
    242				case IRQ_TRIGGER_EDGE_RISING:
    243					giu_clear(GIUFEDGEINHL, mask);
    244					giu_set(GIUREDGEINHL, mask);
    245					break;
    246				default:
    247					giu_set(GIUFEDGEINHL, mask);
    248					giu_set(GIUREDGEINHL, mask);
    249					break;
    250				}
    251			}
    252			irq_set_chip_and_handler(GIU_IRQ(pin),
    253						 &giuint_low_irq_chip,
    254						 handle_edge_irq);
    255		} else {
    256			giu_clear(GIUINTTYPL, mask);
    257			giu_clear(GIUINTHTSELL, mask);
    258			irq_set_chip_and_handler(GIU_IRQ(pin),
    259						 &giuint_low_irq_chip,
    260						 handle_level_irq);
    261		}
    262		giu_write(GIUINTSTATL, mask);
    263	} else if (pin < GIUINT_HIGH_MAX) {
    264		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
    265		if (trigger != IRQ_TRIGGER_LEVEL) {
    266			giu_set(GIUINTTYPH, mask);
    267			if (signal == IRQ_SIGNAL_HOLD)
    268				giu_set(GIUINTHTSELH, mask);
    269			else
    270				giu_clear(GIUINTHTSELH, mask);
    271			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
    272				switch (trigger) {
    273				case IRQ_TRIGGER_EDGE_FALLING:
    274					giu_set(GIUFEDGEINHH, mask);
    275					giu_clear(GIUREDGEINHH, mask);
    276					break;
    277				case IRQ_TRIGGER_EDGE_RISING:
    278					giu_clear(GIUFEDGEINHH, mask);
    279					giu_set(GIUREDGEINHH, mask);
    280					break;
    281				default:
    282					giu_set(GIUFEDGEINHH, mask);
    283					giu_set(GIUREDGEINHH, mask);
    284					break;
    285				}
    286			}
    287			irq_set_chip_and_handler(GIU_IRQ(pin),
    288						 &giuint_high_irq_chip,
    289						 handle_edge_irq);
    290		} else {
    291			giu_clear(GIUINTTYPH, mask);
    292			giu_clear(GIUINTHTSELH, mask);
    293			irq_set_chip_and_handler(GIU_IRQ(pin),
    294						 &giuint_high_irq_chip,
    295						 handle_level_irq);
    296		}
    297		giu_write(GIUINTSTATH, mask);
    298	}
    299}
    300EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
    301
    302void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
    303{
    304	u16 mask;
    305
    306	if (pin < GIUINT_HIGH_OFFSET) {
    307		mask = 1 << pin;
    308		if (level == IRQ_LEVEL_HIGH)
    309			giu_set(GIUINTALSELL, mask);
    310		else
    311			giu_clear(GIUINTALSELL, mask);
    312		giu_write(GIUINTSTATL, mask);
    313	} else if (pin < GIUINT_HIGH_MAX) {
    314		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
    315		if (level == IRQ_LEVEL_HIGH)
    316			giu_set(GIUINTALSELH, mask);
    317		else
    318			giu_clear(GIUINTALSELH, mask);
    319		giu_write(GIUINTSTATH, mask);
    320	}
    321}
    322EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
    323
    324static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir)
    325{
    326	u16 offset, mask, reg;
    327	unsigned long flags;
    328
    329	if (pin >= chip->ngpio)
    330		return -EINVAL;
    331
    332	if (pin < 16) {
    333		offset = GIUIOSELL;
    334		mask = 1 << pin;
    335	} else if (pin < 32) {
    336		offset = GIUIOSELH;
    337		mask = 1 << (pin - 16);
    338	} else {
    339		if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
    340			offset = GIUPODATEN;
    341			mask = 1 << (pin - 32);
    342		} else {
    343			switch (pin) {
    344			case 48:
    345				offset = GIUPODATH;
    346				mask = PIOEN0;
    347				break;
    348			case 49:
    349				offset = GIUPODATH;
    350				mask = PIOEN1;
    351				break;
    352			default:
    353				return -EINVAL;
    354			}
    355		}
    356	}
    357
    358	spin_lock_irqsave(&giu_lock, flags);
    359
    360	reg = giu_read(offset);
    361	if (dir == GPIO_OUTPUT)
    362		reg |= mask;
    363	else
    364		reg &= ~mask;
    365	giu_write(offset, reg);
    366
    367	spin_unlock_irqrestore(&giu_lock, flags);
    368
    369	return 0;
    370}
    371
    372static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin)
    373{
    374	u16 reg, mask;
    375
    376	if (pin >= chip->ngpio)
    377		return -EINVAL;
    378
    379	if (pin < 16) {
    380		reg = giu_read(GIUPIODL);
    381		mask = 1 << pin;
    382	} else if (pin < 32) {
    383		reg = giu_read(GIUPIODH);
    384		mask = 1 << (pin - 16);
    385	} else if (pin < 48) {
    386		reg = giu_read(GIUPODATL);
    387		mask = 1 << (pin - 32);
    388	} else {
    389		reg = giu_read(GIUPODATH);
    390		mask = 1 << (pin - 48);
    391	}
    392
    393	if (reg & mask)
    394		return 1;
    395
    396	return 0;
    397}
    398
    399static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin,
    400			    int value)
    401{
    402	u16 offset, mask, reg;
    403	unsigned long flags;
    404
    405	if (pin >= chip->ngpio)
    406		return;
    407
    408	if (pin < 16) {
    409		offset = GIUPIODL;
    410		mask = 1 << pin;
    411	} else if (pin < 32) {
    412		offset = GIUPIODH;
    413		mask = 1 << (pin - 16);
    414	} else if (pin < 48) {
    415		offset = GIUPODATL;
    416		mask = 1 << (pin - 32);
    417	} else {
    418		offset = GIUPODATH;
    419		mask = 1 << (pin - 48);
    420	}
    421
    422	spin_lock_irqsave(&giu_lock, flags);
    423
    424	reg = giu_read(offset);
    425	if (value)
    426		reg |= mask;
    427	else
    428		reg &= ~mask;
    429	giu_write(offset, reg);
    430
    431	spin_unlock_irqrestore(&giu_lock, flags);
    432}
    433
    434
    435static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
    436{
    437	return giu_set_direction(chip, offset, GPIO_INPUT);
    438}
    439
    440static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
    441				int value)
    442{
    443	vr41xx_gpio_set(chip, offset, value);
    444
    445	return giu_set_direction(chip, offset, GPIO_OUTPUT);
    446}
    447
    448static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
    449{
    450	if (offset >= chip->ngpio)
    451		return -EINVAL;
    452
    453	return GIU_IRQ_BASE + offset;
    454}
    455
    456static struct gpio_chip vr41xx_gpio_chip = {
    457	.label			= "vr41xx",
    458	.owner			= THIS_MODULE,
    459	.direction_input	= vr41xx_gpio_direction_input,
    460	.get			= vr41xx_gpio_get,
    461	.direction_output	= vr41xx_gpio_direction_output,
    462	.set			= vr41xx_gpio_set,
    463	.to_irq			= vr41xx_gpio_to_irq,
    464};
    465
    466static int giu_probe(struct platform_device *pdev)
    467{
    468	unsigned int trigger, i, pin;
    469	struct irq_chip *chip;
    470	int irq;
    471
    472	switch (pdev->id) {
    473	case GPIO_50PINS_PULLUPDOWN:
    474		giu_flags = GPIO_HAS_PULLUPDOWN_IO;
    475		vr41xx_gpio_chip.ngpio = 50;
    476		break;
    477	case GPIO_36PINS:
    478		vr41xx_gpio_chip.ngpio = 36;
    479		break;
    480	case GPIO_48PINS_EDGE_SELECT:
    481		giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
    482		vr41xx_gpio_chip.ngpio = 48;
    483		break;
    484	default:
    485		dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id);
    486		return -ENODEV;
    487	}
    488
    489	giu_base = devm_platform_ioremap_resource(pdev, 0);
    490	if (IS_ERR(giu_base))
    491		return PTR_ERR(giu_base);
    492
    493	vr41xx_gpio_chip.parent = &pdev->dev;
    494
    495	if (gpiochip_add_data(&vr41xx_gpio_chip, NULL))
    496		return -ENODEV;
    497
    498	giu_write(GIUINTENL, 0);
    499	giu_write(GIUINTENH, 0);
    500
    501	trigger = giu_read(GIUINTTYPH) << 16;
    502	trigger |= giu_read(GIUINTTYPL);
    503	for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
    504		pin = GPIO_PIN_OF_IRQ(i);
    505		if (pin < GIUINT_HIGH_OFFSET)
    506			chip = &giuint_low_irq_chip;
    507		else
    508			chip = &giuint_high_irq_chip;
    509
    510		if (trigger & (1 << pin))
    511			irq_set_chip_and_handler(i, chip, handle_edge_irq);
    512		else
    513			irq_set_chip_and_handler(i, chip, handle_level_irq);
    514
    515	}
    516
    517	irq = platform_get_irq(pdev, 0);
    518	if (irq < 0 || irq >= nr_irqs)
    519		return -EBUSY;
    520
    521	return cascade_irq(irq, giu_get_irq);
    522}
    523
    524static int giu_remove(struct platform_device *pdev)
    525{
    526	if (giu_base) {
    527		giu_base = NULL;
    528	}
    529
    530	return 0;
    531}
    532
    533static struct platform_driver giu_device_driver = {
    534	.probe		= giu_probe,
    535	.remove		= giu_remove,
    536	.driver		= {
    537		.name	= "GIU",
    538	},
    539};
    540
    541module_platform_driver(giu_device_driver);