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) }