VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

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