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

driver_gpio.c (11972B)


      1/*
      2 * Sonics Silicon Backplane
      3 * GPIO driver
      4 *
      5 * Copyright 2011, Broadcom Corporation
      6 * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
      7 *
      8 * Licensed under the GNU/GPL. See COPYING for details.
      9 */
     10
     11#include "ssb_private.h"
     12
     13#include <linux/gpio/driver.h>
     14#include <linux/irq.h>
     15#include <linux/interrupt.h>
     16#include <linux/irqdomain.h>
     17#include <linux/export.h>
     18#include <linux/ssb/ssb.h>
     19
     20
     21/**************************************************
     22 * Shared
     23 **************************************************/
     24
     25#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
     26static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned int gpio)
     27{
     28	struct ssb_bus *bus = gpiochip_get_data(chip);
     29
     30	if (bus->bustype == SSB_BUSTYPE_SSB)
     31		return irq_find_mapping(bus->irq_domain, gpio);
     32	else
     33		return -EINVAL;
     34}
     35#endif
     36
     37/**************************************************
     38 * ChipCommon
     39 **************************************************/
     40
     41static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned int gpio)
     42{
     43	struct ssb_bus *bus = gpiochip_get_data(chip);
     44
     45	return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio);
     46}
     47
     48static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned int gpio,
     49				      int value)
     50{
     51	struct ssb_bus *bus = gpiochip_get_data(chip);
     52
     53	ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
     54}
     55
     56static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip,
     57					   unsigned int gpio)
     58{
     59	struct ssb_bus *bus = gpiochip_get_data(chip);
     60
     61	ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0);
     62	return 0;
     63}
     64
     65static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip,
     66					    unsigned int gpio, int value)
     67{
     68	struct ssb_bus *bus = gpiochip_get_data(chip);
     69
     70	ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio);
     71	ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
     72	return 0;
     73}
     74
     75static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned int gpio)
     76{
     77	struct ssb_bus *bus = gpiochip_get_data(chip);
     78
     79	ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0);
     80	/* clear pulldown */
     81	ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0);
     82	/* Set pullup */
     83	ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio);
     84
     85	return 0;
     86}
     87
     88static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned int gpio)
     89{
     90	struct ssb_bus *bus = gpiochip_get_data(chip);
     91
     92	/* clear pullup */
     93	ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0);
     94}
     95
     96#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
     97static void ssb_gpio_irq_chipco_mask(struct irq_data *d)
     98{
     99	struct ssb_bus *bus = irq_data_get_irq_chip_data(d);
    100	int gpio = irqd_to_hwirq(d);
    101
    102	ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), 0);
    103}
    104
    105static void ssb_gpio_irq_chipco_unmask(struct irq_data *d)
    106{
    107	struct ssb_bus *bus = irq_data_get_irq_chip_data(d);
    108	int gpio = irqd_to_hwirq(d);
    109	u32 val = ssb_chipco_gpio_in(&bus->chipco, BIT(gpio));
    110
    111	ssb_chipco_gpio_polarity(&bus->chipco, BIT(gpio), val);
    112	ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), BIT(gpio));
    113}
    114
    115static struct irq_chip ssb_gpio_irq_chipco_chip = {
    116	.name		= "SSB-GPIO-CC",
    117	.irq_mask	= ssb_gpio_irq_chipco_mask,
    118	.irq_unmask	= ssb_gpio_irq_chipco_unmask,
    119};
    120
    121static irqreturn_t ssb_gpio_irq_chipco_handler(int irq, void *dev_id)
    122{
    123	struct ssb_bus *bus = dev_id;
    124	struct ssb_chipcommon *chipco = &bus->chipco;
    125	u32 val = chipco_read32(chipco, SSB_CHIPCO_GPIOIN);
    126	u32 mask = chipco_read32(chipco, SSB_CHIPCO_GPIOIRQ);
    127	u32 pol = chipco_read32(chipco, SSB_CHIPCO_GPIOPOL);
    128	unsigned long irqs = (val ^ pol) & mask;
    129	int gpio;
    130
    131	if (!irqs)
    132		return IRQ_NONE;
    133
    134	for_each_set_bit(gpio, &irqs, bus->gpio.ngpio)
    135		generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio));
    136	ssb_chipco_gpio_polarity(chipco, irqs, val & irqs);
    137
    138	return IRQ_HANDLED;
    139}
    140
    141static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus)
    142{
    143	struct ssb_chipcommon *chipco = &bus->chipco;
    144	struct gpio_chip *chip = &bus->gpio;
    145	int gpio, hwirq, err;
    146
    147	if (bus->bustype != SSB_BUSTYPE_SSB)
    148		return 0;
    149
    150	bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio,
    151						&irq_domain_simple_ops, chipco);
    152	if (!bus->irq_domain) {
    153		err = -ENODEV;
    154		goto err_irq_domain;
    155	}
    156	for (gpio = 0; gpio < chip->ngpio; gpio++) {
    157		int irq = irq_create_mapping(bus->irq_domain, gpio);
    158
    159		irq_set_chip_data(irq, bus);
    160		irq_set_chip_and_handler(irq, &ssb_gpio_irq_chipco_chip,
    161					 handle_simple_irq);
    162	}
    163
    164	hwirq = ssb_mips_irq(bus->chipco.dev) + 2;
    165	err = request_irq(hwirq, ssb_gpio_irq_chipco_handler, IRQF_SHARED,
    166			  "gpio", bus);
    167	if (err)
    168		goto err_req_irq;
    169
    170	ssb_chipco_gpio_intmask(&bus->chipco, ~0, 0);
    171	chipco_set32(chipco, SSB_CHIPCO_IRQMASK, SSB_CHIPCO_IRQ_GPIO);
    172
    173	return 0;
    174
    175err_req_irq:
    176	for (gpio = 0; gpio < chip->ngpio; gpio++) {
    177		int irq = irq_find_mapping(bus->irq_domain, gpio);
    178
    179		irq_dispose_mapping(irq);
    180	}
    181	irq_domain_remove(bus->irq_domain);
    182err_irq_domain:
    183	return err;
    184}
    185
    186static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus)
    187{
    188	struct ssb_chipcommon *chipco = &bus->chipco;
    189	struct gpio_chip *chip = &bus->gpio;
    190	int gpio;
    191
    192	if (bus->bustype != SSB_BUSTYPE_SSB)
    193		return;
    194
    195	chipco_mask32(chipco, SSB_CHIPCO_IRQMASK, ~SSB_CHIPCO_IRQ_GPIO);
    196	free_irq(ssb_mips_irq(bus->chipco.dev) + 2, chipco);
    197	for (gpio = 0; gpio < chip->ngpio; gpio++) {
    198		int irq = irq_find_mapping(bus->irq_domain, gpio);
    199
    200		irq_dispose_mapping(irq);
    201	}
    202	irq_domain_remove(bus->irq_domain);
    203}
    204#else
    205static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus)
    206{
    207	return 0;
    208}
    209
    210static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus)
    211{
    212}
    213#endif
    214
    215static int ssb_gpio_chipco_init(struct ssb_bus *bus)
    216{
    217	struct gpio_chip *chip = &bus->gpio;
    218	int err;
    219
    220	chip->label		= "ssb_chipco_gpio";
    221	chip->owner		= THIS_MODULE;
    222	chip->request		= ssb_gpio_chipco_request;
    223	chip->free		= ssb_gpio_chipco_free;
    224	chip->get		= ssb_gpio_chipco_get_value;
    225	chip->set		= ssb_gpio_chipco_set_value;
    226	chip->direction_input	= ssb_gpio_chipco_direction_input;
    227	chip->direction_output	= ssb_gpio_chipco_direction_output;
    228#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
    229	chip->to_irq		= ssb_gpio_to_irq;
    230#endif
    231	chip->ngpio		= 16;
    232	/* There is just one SoC in one device and its GPIO addresses should be
    233	 * deterministic to address them more easily. The other buses could get
    234	 * a random base number.
    235	 */
    236	if (bus->bustype == SSB_BUSTYPE_SSB)
    237		chip->base		= 0;
    238	else
    239		chip->base		= -1;
    240
    241	err = ssb_gpio_irq_chipco_domain_init(bus);
    242	if (err)
    243		return err;
    244
    245	err = gpiochip_add_data(chip, bus);
    246	if (err) {
    247		ssb_gpio_irq_chipco_domain_exit(bus);
    248		return err;
    249	}
    250
    251	return 0;
    252}
    253
    254/**************************************************
    255 * EXTIF
    256 **************************************************/
    257
    258#ifdef CONFIG_SSB_DRIVER_EXTIF
    259
    260static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned int gpio)
    261{
    262	struct ssb_bus *bus = gpiochip_get_data(chip);
    263
    264	return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio);
    265}
    266
    267static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned int gpio,
    268				     int value)
    269{
    270	struct ssb_bus *bus = gpiochip_get_data(chip);
    271
    272	ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
    273}
    274
    275static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
    276					  unsigned int gpio)
    277{
    278	struct ssb_bus *bus = gpiochip_get_data(chip);
    279
    280	ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0);
    281	return 0;
    282}
    283
    284static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
    285					   unsigned int gpio, int value)
    286{
    287	struct ssb_bus *bus = gpiochip_get_data(chip);
    288
    289	ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio);
    290	ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
    291	return 0;
    292}
    293
    294#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
    295static void ssb_gpio_irq_extif_mask(struct irq_data *d)
    296{
    297	struct ssb_bus *bus = irq_data_get_irq_chip_data(d);
    298	int gpio = irqd_to_hwirq(d);
    299
    300	ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), 0);
    301}
    302
    303static void ssb_gpio_irq_extif_unmask(struct irq_data *d)
    304{
    305	struct ssb_bus *bus = irq_data_get_irq_chip_data(d);
    306	int gpio = irqd_to_hwirq(d);
    307	u32 val = ssb_extif_gpio_in(&bus->extif, BIT(gpio));
    308
    309	ssb_extif_gpio_polarity(&bus->extif, BIT(gpio), val);
    310	ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), BIT(gpio));
    311}
    312
    313static struct irq_chip ssb_gpio_irq_extif_chip = {
    314	.name		= "SSB-GPIO-EXTIF",
    315	.irq_mask	= ssb_gpio_irq_extif_mask,
    316	.irq_unmask	= ssb_gpio_irq_extif_unmask,
    317};
    318
    319static irqreturn_t ssb_gpio_irq_extif_handler(int irq, void *dev_id)
    320{
    321	struct ssb_bus *bus = dev_id;
    322	struct ssb_extif *extif = &bus->extif;
    323	u32 val = ssb_read32(extif->dev, SSB_EXTIF_GPIO_IN);
    324	u32 mask = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTMASK);
    325	u32 pol = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTPOL);
    326	unsigned long irqs = (val ^ pol) & mask;
    327	int gpio;
    328
    329	if (!irqs)
    330		return IRQ_NONE;
    331
    332	for_each_set_bit(gpio, &irqs, bus->gpio.ngpio)
    333		generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio));
    334	ssb_extif_gpio_polarity(extif, irqs, val & irqs);
    335
    336	return IRQ_HANDLED;
    337}
    338
    339static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus)
    340{
    341	struct ssb_extif *extif = &bus->extif;
    342	struct gpio_chip *chip = &bus->gpio;
    343	int gpio, hwirq, err;
    344
    345	if (bus->bustype != SSB_BUSTYPE_SSB)
    346		return 0;
    347
    348	bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio,
    349						&irq_domain_simple_ops, extif);
    350	if (!bus->irq_domain) {
    351		err = -ENODEV;
    352		goto err_irq_domain;
    353	}
    354	for (gpio = 0; gpio < chip->ngpio; gpio++) {
    355		int irq = irq_create_mapping(bus->irq_domain, gpio);
    356
    357		irq_set_chip_data(irq, bus);
    358		irq_set_chip_and_handler(irq, &ssb_gpio_irq_extif_chip,
    359					 handle_simple_irq);
    360	}
    361
    362	hwirq = ssb_mips_irq(bus->extif.dev) + 2;
    363	err = request_irq(hwirq, ssb_gpio_irq_extif_handler, IRQF_SHARED,
    364			  "gpio", bus);
    365	if (err)
    366		goto err_req_irq;
    367
    368	ssb_extif_gpio_intmask(&bus->extif, ~0, 0);
    369
    370	return 0;
    371
    372err_req_irq:
    373	for (gpio = 0; gpio < chip->ngpio; gpio++) {
    374		int irq = irq_find_mapping(bus->irq_domain, gpio);
    375
    376		irq_dispose_mapping(irq);
    377	}
    378	irq_domain_remove(bus->irq_domain);
    379err_irq_domain:
    380	return err;
    381}
    382
    383static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus)
    384{
    385	struct ssb_extif *extif = &bus->extif;
    386	struct gpio_chip *chip = &bus->gpio;
    387	int gpio;
    388
    389	if (bus->bustype != SSB_BUSTYPE_SSB)
    390		return;
    391
    392	free_irq(ssb_mips_irq(bus->extif.dev) + 2, extif);
    393	for (gpio = 0; gpio < chip->ngpio; gpio++) {
    394		int irq = irq_find_mapping(bus->irq_domain, gpio);
    395
    396		irq_dispose_mapping(irq);
    397	}
    398	irq_domain_remove(bus->irq_domain);
    399}
    400#else
    401static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus)
    402{
    403	return 0;
    404}
    405
    406static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus)
    407{
    408}
    409#endif
    410
    411static int ssb_gpio_extif_init(struct ssb_bus *bus)
    412{
    413	struct gpio_chip *chip = &bus->gpio;
    414	int err;
    415
    416	chip->label		= "ssb_extif_gpio";
    417	chip->owner		= THIS_MODULE;
    418	chip->get		= ssb_gpio_extif_get_value;
    419	chip->set		= ssb_gpio_extif_set_value;
    420	chip->direction_input	= ssb_gpio_extif_direction_input;
    421	chip->direction_output	= ssb_gpio_extif_direction_output;
    422#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
    423	chip->to_irq		= ssb_gpio_to_irq;
    424#endif
    425	chip->ngpio		= 5;
    426	/* There is just one SoC in one device and its GPIO addresses should be
    427	 * deterministic to address them more easily. The other buses could get
    428	 * a random base number.
    429	 */
    430	if (bus->bustype == SSB_BUSTYPE_SSB)
    431		chip->base		= 0;
    432	else
    433		chip->base		= -1;
    434
    435	err = ssb_gpio_irq_extif_domain_init(bus);
    436	if (err)
    437		return err;
    438
    439	err = gpiochip_add_data(chip, bus);
    440	if (err) {
    441		ssb_gpio_irq_extif_domain_exit(bus);
    442		return err;
    443	}
    444
    445	return 0;
    446}
    447
    448#else
    449static int ssb_gpio_extif_init(struct ssb_bus *bus)
    450{
    451	return -ENOTSUPP;
    452}
    453#endif
    454
    455/**************************************************
    456 * Init
    457 **************************************************/
    458
    459int ssb_gpio_init(struct ssb_bus *bus)
    460{
    461	if (ssb_chipco_available(&bus->chipco))
    462		return ssb_gpio_chipco_init(bus);
    463	else if (ssb_extif_available(&bus->extif))
    464		return ssb_gpio_extif_init(bus);
    465	return -1;
    466}
    467
    468int ssb_gpio_unregister(struct ssb_bus *bus)
    469{
    470	if (ssb_chipco_available(&bus->chipco) ||
    471	    ssb_extif_available(&bus->extif)) {
    472		gpiochip_remove(&bus->gpio);
    473		return 0;
    474	}
    475	return -1;
    476}