1ec43b08bSHauke Mehrtens /* 2ec43b08bSHauke Mehrtens * Sonics Silicon Backplane 3ec43b08bSHauke Mehrtens * GPIO driver 4ec43b08bSHauke Mehrtens * 5ec43b08bSHauke Mehrtens * Copyright 2011, Broadcom Corporation 6ec43b08bSHauke Mehrtens * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de> 7ec43b08bSHauke Mehrtens * 8ec43b08bSHauke Mehrtens * Licensed under the GNU/GPL. See COPYING for details. 9ec43b08bSHauke Mehrtens */ 10ec43b08bSHauke Mehrtens 112d4443beSLinus Walleij #include <linux/gpio/driver.h> 127c1bc0daSRafał Miłecki #include <linux/irq.h> 137c1bc0daSRafał Miłecki #include <linux/interrupt.h> 147c1bc0daSRafał Miłecki #include <linux/irqdomain.h> 15ec43b08bSHauke Mehrtens #include <linux/export.h> 16ec43b08bSHauke Mehrtens #include <linux/ssb/ssb.h> 17ec43b08bSHauke Mehrtens 18ec43b08bSHauke Mehrtens #include "ssb_private.h" 19ec43b08bSHauke Mehrtens 207c1bc0daSRafał Miłecki 217c1bc0daSRafał Miłecki /************************************************** 227c1bc0daSRafał Miłecki * Shared 237c1bc0daSRafał Miłecki **************************************************/ 247c1bc0daSRafał Miłecki 257c1bc0daSRafał Miłecki #if IS_ENABLED(CONFIG_SSB_EMBEDDED) 26c683ffe2SHugh Sipière static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned int gpio) 277c1bc0daSRafał Miłecki { 282d4443beSLinus Walleij struct ssb_bus *bus = gpiochip_get_data(chip); 297c1bc0daSRafał Miłecki 307c1bc0daSRafał Miłecki if (bus->bustype == SSB_BUSTYPE_SSB) 317c1bc0daSRafał Miłecki return irq_find_mapping(bus->irq_domain, gpio); 327c1bc0daSRafał Miłecki else 337c1bc0daSRafał Miłecki return -EINVAL; 347c1bc0daSRafał Miłecki } 357c1bc0daSRafał Miłecki #endif 367c1bc0daSRafał Miłecki 377c1bc0daSRafał Miłecki /************************************************** 387c1bc0daSRafał Miłecki * ChipCommon 397c1bc0daSRafał Miłecki **************************************************/ 407c1bc0daSRafał Miłecki 41c683ffe2SHugh Sipière static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned int gpio) 42ec43b08bSHauke Mehrtens { 432d4443beSLinus Walleij struct ssb_bus *bus = gpiochip_get_data(chip); 44ec43b08bSHauke Mehrtens 45ec43b08bSHauke Mehrtens return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio); 46ec43b08bSHauke Mehrtens } 47ec43b08bSHauke Mehrtens 48c683ffe2SHugh Sipière static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned int gpio, 49ec43b08bSHauke Mehrtens int value) 50ec43b08bSHauke Mehrtens { 512d4443beSLinus Walleij struct ssb_bus *bus = gpiochip_get_data(chip); 52ec43b08bSHauke Mehrtens 53ec43b08bSHauke Mehrtens ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); 54ec43b08bSHauke Mehrtens } 55ec43b08bSHauke Mehrtens 56ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip, 57c683ffe2SHugh Sipière unsigned int gpio) 58ec43b08bSHauke Mehrtens { 592d4443beSLinus Walleij struct ssb_bus *bus = gpiochip_get_data(chip); 60ec43b08bSHauke Mehrtens 61ec43b08bSHauke Mehrtens ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0); 62ec43b08bSHauke Mehrtens return 0; 63ec43b08bSHauke Mehrtens } 64ec43b08bSHauke Mehrtens 65ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip, 66c683ffe2SHugh Sipière unsigned int gpio, int value) 67ec43b08bSHauke Mehrtens { 682d4443beSLinus Walleij struct ssb_bus *bus = gpiochip_get_data(chip); 69ec43b08bSHauke Mehrtens 70ec43b08bSHauke Mehrtens ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio); 71ec43b08bSHauke Mehrtens ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); 72ec43b08bSHauke Mehrtens return 0; 73ec43b08bSHauke Mehrtens } 74ec43b08bSHauke Mehrtens 75c683ffe2SHugh Sipière static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned int gpio) 76ec43b08bSHauke Mehrtens { 772d4443beSLinus Walleij struct ssb_bus *bus = gpiochip_get_data(chip); 78ec43b08bSHauke Mehrtens 79ec43b08bSHauke Mehrtens ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0); 80ec43b08bSHauke Mehrtens /* clear pulldown */ 81ec43b08bSHauke Mehrtens ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0); 82ec43b08bSHauke Mehrtens /* Set pullup */ 83ec43b08bSHauke Mehrtens ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio); 84ec43b08bSHauke Mehrtens 85ec43b08bSHauke Mehrtens return 0; 86ec43b08bSHauke Mehrtens } 87ec43b08bSHauke Mehrtens 88c683ffe2SHugh Sipière static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned int gpio) 89ec43b08bSHauke Mehrtens { 902d4443beSLinus Walleij struct ssb_bus *bus = gpiochip_get_data(chip); 91ec43b08bSHauke Mehrtens 92ec43b08bSHauke Mehrtens /* clear pullup */ 93ec43b08bSHauke Mehrtens ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0); 94ec43b08bSHauke Mehrtens } 95ec43b08bSHauke Mehrtens 967c1bc0daSRafał Miłecki #if IS_ENABLED(CONFIG_SSB_EMBEDDED) 977c1bc0daSRafał Miłecki static void ssb_gpio_irq_chipco_mask(struct irq_data *d) 98a6ca2e10SHauke Mehrtens { 997c1bc0daSRafał Miłecki struct ssb_bus *bus = irq_data_get_irq_chip_data(d); 1007c1bc0daSRafał Miłecki int gpio = irqd_to_hwirq(d); 101a6ca2e10SHauke Mehrtens 1027c1bc0daSRafał Miłecki ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), 0); 103a6ca2e10SHauke Mehrtens } 104a6ca2e10SHauke Mehrtens 1057c1bc0daSRafał Miłecki static void ssb_gpio_irq_chipco_unmask(struct irq_data *d) 1067c1bc0daSRafał Miłecki { 1077c1bc0daSRafał Miłecki struct ssb_bus *bus = irq_data_get_irq_chip_data(d); 1087c1bc0daSRafał Miłecki int gpio = irqd_to_hwirq(d); 1097c1bc0daSRafał Miłecki u32 val = ssb_chipco_gpio_in(&bus->chipco, BIT(gpio)); 1107c1bc0daSRafał Miłecki 1117c1bc0daSRafał Miłecki ssb_chipco_gpio_polarity(&bus->chipco, BIT(gpio), val); 1127c1bc0daSRafał Miłecki ssb_chipco_gpio_intmask(&bus->chipco, BIT(gpio), BIT(gpio)); 1137c1bc0daSRafał Miłecki } 1147c1bc0daSRafał Miłecki 1157c1bc0daSRafał Miłecki static struct irq_chip ssb_gpio_irq_chipco_chip = { 1167c1bc0daSRafał Miłecki .name = "SSB-GPIO-CC", 1177c1bc0daSRafał Miłecki .irq_mask = ssb_gpio_irq_chipco_mask, 1187c1bc0daSRafał Miłecki .irq_unmask = ssb_gpio_irq_chipco_unmask, 1197c1bc0daSRafał Miłecki }; 1207c1bc0daSRafał Miłecki 1217c1bc0daSRafał Miłecki static irqreturn_t ssb_gpio_irq_chipco_handler(int irq, void *dev_id) 1227c1bc0daSRafał Miłecki { 1237c1bc0daSRafał Miłecki struct ssb_bus *bus = dev_id; 1247c1bc0daSRafał Miłecki struct ssb_chipcommon *chipco = &bus->chipco; 1257c1bc0daSRafał Miłecki u32 val = chipco_read32(chipco, SSB_CHIPCO_GPIOIN); 1267c1bc0daSRafał Miłecki u32 mask = chipco_read32(chipco, SSB_CHIPCO_GPIOIRQ); 1277c1bc0daSRafał Miłecki u32 pol = chipco_read32(chipco, SSB_CHIPCO_GPIOPOL); 1287c1bc0daSRafał Miłecki unsigned long irqs = (val ^ pol) & mask; 1297c1bc0daSRafał Miłecki int gpio; 1307c1bc0daSRafał Miłecki 1317c1bc0daSRafał Miłecki if (!irqs) 1327c1bc0daSRafał Miłecki return IRQ_NONE; 1337c1bc0daSRafał Miłecki 1347c1bc0daSRafał Miłecki for_each_set_bit(gpio, &irqs, bus->gpio.ngpio) 1357c1bc0daSRafał Miłecki generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio)); 1367c1bc0daSRafał Miłecki ssb_chipco_gpio_polarity(chipco, irqs, val & irqs); 1377c1bc0daSRafał Miłecki 1387c1bc0daSRafał Miłecki return IRQ_HANDLED; 1397c1bc0daSRafał Miłecki } 1407c1bc0daSRafał Miłecki 1417c1bc0daSRafał Miłecki static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus) 1427c1bc0daSRafał Miłecki { 1437c1bc0daSRafał Miłecki struct ssb_chipcommon *chipco = &bus->chipco; 1447c1bc0daSRafał Miłecki struct gpio_chip *chip = &bus->gpio; 1457c1bc0daSRafał Miłecki int gpio, hwirq, err; 1467c1bc0daSRafał Miłecki 1477c1bc0daSRafał Miłecki if (bus->bustype != SSB_BUSTYPE_SSB) 1487c1bc0daSRafał Miłecki return 0; 1497c1bc0daSRafał Miłecki 1507c1bc0daSRafał Miłecki bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio, 1517c1bc0daSRafał Miłecki &irq_domain_simple_ops, chipco); 1527c1bc0daSRafał Miłecki if (!bus->irq_domain) { 1537c1bc0daSRafał Miłecki err = -ENODEV; 1547c1bc0daSRafał Miłecki goto err_irq_domain; 1557c1bc0daSRafał Miłecki } 1567c1bc0daSRafał Miłecki for (gpio = 0; gpio < chip->ngpio; gpio++) { 1577c1bc0daSRafał Miłecki int irq = irq_create_mapping(bus->irq_domain, gpio); 1587c1bc0daSRafał Miłecki 1597c1bc0daSRafał Miłecki irq_set_chip_data(irq, bus); 1607c1bc0daSRafał Miłecki irq_set_chip_and_handler(irq, &ssb_gpio_irq_chipco_chip, 1617c1bc0daSRafał Miłecki handle_simple_irq); 1627c1bc0daSRafał Miłecki } 1637c1bc0daSRafał Miłecki 1647c1bc0daSRafał Miłecki hwirq = ssb_mips_irq(bus->chipco.dev) + 2; 1657c1bc0daSRafał Miłecki err = request_irq(hwirq, ssb_gpio_irq_chipco_handler, IRQF_SHARED, 1667c1bc0daSRafał Miłecki "gpio", bus); 1677c1bc0daSRafał Miłecki if (err) 1687c1bc0daSRafał Miłecki goto err_req_irq; 1697c1bc0daSRafał Miłecki 1707c1bc0daSRafał Miłecki ssb_chipco_gpio_intmask(&bus->chipco, ~0, 0); 1717c1bc0daSRafał Miłecki chipco_set32(chipco, SSB_CHIPCO_IRQMASK, SSB_CHIPCO_IRQ_GPIO); 1727c1bc0daSRafał Miłecki 1737c1bc0daSRafał Miłecki return 0; 1747c1bc0daSRafał Miłecki 1757c1bc0daSRafał Miłecki err_req_irq: 1767c1bc0daSRafał Miłecki for (gpio = 0; gpio < chip->ngpio; gpio++) { 1777c1bc0daSRafał Miłecki int irq = irq_find_mapping(bus->irq_domain, gpio); 1787c1bc0daSRafał Miłecki 1797c1bc0daSRafał Miłecki irq_dispose_mapping(irq); 1807c1bc0daSRafał Miłecki } 1817c1bc0daSRafał Miłecki irq_domain_remove(bus->irq_domain); 1827c1bc0daSRafał Miłecki err_irq_domain: 1837c1bc0daSRafał Miłecki return err; 1847c1bc0daSRafał Miłecki } 1857c1bc0daSRafał Miłecki 1867c1bc0daSRafał Miłecki static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus) 1877c1bc0daSRafał Miłecki { 1887c1bc0daSRafał Miłecki struct ssb_chipcommon *chipco = &bus->chipco; 1897c1bc0daSRafał Miłecki struct gpio_chip *chip = &bus->gpio; 1907c1bc0daSRafał Miłecki int gpio; 1917c1bc0daSRafał Miłecki 1927c1bc0daSRafał Miłecki if (bus->bustype != SSB_BUSTYPE_SSB) 1937c1bc0daSRafał Miłecki return; 1947c1bc0daSRafał Miłecki 1957c1bc0daSRafał Miłecki chipco_mask32(chipco, SSB_CHIPCO_IRQMASK, ~SSB_CHIPCO_IRQ_GPIO); 1967c1bc0daSRafał Miłecki free_irq(ssb_mips_irq(bus->chipco.dev) + 2, chipco); 1977c1bc0daSRafał Miłecki for (gpio = 0; gpio < chip->ngpio; gpio++) { 1987c1bc0daSRafał Miłecki int irq = irq_find_mapping(bus->irq_domain, gpio); 1997c1bc0daSRafał Miłecki 2007c1bc0daSRafał Miłecki irq_dispose_mapping(irq); 2017c1bc0daSRafał Miłecki } 2027c1bc0daSRafał Miłecki irq_domain_remove(bus->irq_domain); 2037c1bc0daSRafał Miłecki } 2047c1bc0daSRafał Miłecki #else 2057c1bc0daSRafał Miłecki static int ssb_gpio_irq_chipco_domain_init(struct ssb_bus *bus) 2067c1bc0daSRafał Miłecki { 2077c1bc0daSRafał Miłecki return 0; 2087c1bc0daSRafał Miłecki } 2097c1bc0daSRafał Miłecki 2107c1bc0daSRafał Miłecki static void ssb_gpio_irq_chipco_domain_exit(struct ssb_bus *bus) 2117c1bc0daSRafał Miłecki { 2127c1bc0daSRafał Miłecki } 2137c1bc0daSRafał Miłecki #endif 2147c1bc0daSRafał Miłecki 215ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_init(struct ssb_bus *bus) 216ec43b08bSHauke Mehrtens { 217ec43b08bSHauke Mehrtens struct gpio_chip *chip = &bus->gpio; 2187c1bc0daSRafał Miłecki int err; 219ec43b08bSHauke Mehrtens 220ec43b08bSHauke Mehrtens chip->label = "ssb_chipco_gpio"; 221ec43b08bSHauke Mehrtens chip->owner = THIS_MODULE; 222ec43b08bSHauke Mehrtens chip->request = ssb_gpio_chipco_request; 223ec43b08bSHauke Mehrtens chip->free = ssb_gpio_chipco_free; 224ec43b08bSHauke Mehrtens chip->get = ssb_gpio_chipco_get_value; 225ec43b08bSHauke Mehrtens chip->set = ssb_gpio_chipco_set_value; 226ec43b08bSHauke Mehrtens chip->direction_input = ssb_gpio_chipco_direction_input; 227ec43b08bSHauke Mehrtens chip->direction_output = ssb_gpio_chipco_direction_output; 2287c1bc0daSRafał Miłecki #if IS_ENABLED(CONFIG_SSB_EMBEDDED) 2297c1bc0daSRafał Miłecki chip->to_irq = ssb_gpio_to_irq; 2307c1bc0daSRafał Miłecki #endif 231ec43b08bSHauke Mehrtens chip->ngpio = 16; 232ec43b08bSHauke Mehrtens /* There is just one SoC in one device and its GPIO addresses should be 233ec43b08bSHauke Mehrtens * deterministic to address them more easily. The other buses could get 234ec43b08bSHauke Mehrtens * a random base number. */ 235ec43b08bSHauke Mehrtens if (bus->bustype == SSB_BUSTYPE_SSB) 236ec43b08bSHauke Mehrtens chip->base = 0; 237ec43b08bSHauke Mehrtens else 238ec43b08bSHauke Mehrtens chip->base = -1; 239ec43b08bSHauke Mehrtens 2407c1bc0daSRafał Miłecki err = ssb_gpio_irq_chipco_domain_init(bus); 2417c1bc0daSRafał Miłecki if (err) 2427c1bc0daSRafał Miłecki return err; 2437c1bc0daSRafał Miłecki 2442d4443beSLinus Walleij err = gpiochip_add_data(chip, bus); 2457c1bc0daSRafał Miłecki if (err) { 2467c1bc0daSRafał Miłecki ssb_gpio_irq_chipco_domain_exit(bus); 2477c1bc0daSRafał Miłecki return err; 248ec43b08bSHauke Mehrtens } 249ec43b08bSHauke Mehrtens 2507c1bc0daSRafał Miłecki return 0; 2517c1bc0daSRafał Miłecki } 2527c1bc0daSRafał Miłecki 2537c1bc0daSRafał Miłecki /************************************************** 2547c1bc0daSRafał Miłecki * EXTIF 2557c1bc0daSRafał Miłecki **************************************************/ 2567c1bc0daSRafał Miłecki 257ec43b08bSHauke Mehrtens #ifdef CONFIG_SSB_DRIVER_EXTIF 258ec43b08bSHauke Mehrtens 259c683ffe2SHugh Sipière static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned int gpio) 260ec43b08bSHauke Mehrtens { 2612d4443beSLinus Walleij struct ssb_bus *bus = gpiochip_get_data(chip); 262ec43b08bSHauke Mehrtens 263ec43b08bSHauke Mehrtens return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio); 264ec43b08bSHauke Mehrtens } 265ec43b08bSHauke Mehrtens 266c683ffe2SHugh Sipière static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned int gpio, 267ec43b08bSHauke Mehrtens int value) 268ec43b08bSHauke Mehrtens { 2692d4443beSLinus Walleij struct ssb_bus *bus = gpiochip_get_data(chip); 270ec43b08bSHauke Mehrtens 271ec43b08bSHauke Mehrtens ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); 272ec43b08bSHauke Mehrtens } 273ec43b08bSHauke Mehrtens 274ec43b08bSHauke Mehrtens static int ssb_gpio_extif_direction_input(struct gpio_chip *chip, 275c683ffe2SHugh Sipière unsigned int gpio) 276ec43b08bSHauke Mehrtens { 2772d4443beSLinus Walleij struct ssb_bus *bus = gpiochip_get_data(chip); 278ec43b08bSHauke Mehrtens 279ec43b08bSHauke Mehrtens ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0); 280ec43b08bSHauke Mehrtens return 0; 281ec43b08bSHauke Mehrtens } 282ec43b08bSHauke Mehrtens 283ec43b08bSHauke Mehrtens static int ssb_gpio_extif_direction_output(struct gpio_chip *chip, 284c683ffe2SHugh Sipière unsigned int gpio, int value) 285ec43b08bSHauke Mehrtens { 2862d4443beSLinus Walleij struct ssb_bus *bus = gpiochip_get_data(chip); 287ec43b08bSHauke Mehrtens 288ec43b08bSHauke Mehrtens ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio); 289ec43b08bSHauke Mehrtens ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); 290ec43b08bSHauke Mehrtens return 0; 291ec43b08bSHauke Mehrtens } 292ec43b08bSHauke Mehrtens 2937c1bc0daSRafał Miłecki #if IS_ENABLED(CONFIG_SSB_EMBEDDED) 2947c1bc0daSRafał Miłecki static void ssb_gpio_irq_extif_mask(struct irq_data *d) 295a6ca2e10SHauke Mehrtens { 2967c1bc0daSRafał Miłecki struct ssb_bus *bus = irq_data_get_irq_chip_data(d); 2977c1bc0daSRafał Miłecki int gpio = irqd_to_hwirq(d); 298a6ca2e10SHauke Mehrtens 2997c1bc0daSRafał Miłecki ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), 0); 300a6ca2e10SHauke Mehrtens } 301a6ca2e10SHauke Mehrtens 3027c1bc0daSRafał Miłecki static void ssb_gpio_irq_extif_unmask(struct irq_data *d) 3037c1bc0daSRafał Miłecki { 3047c1bc0daSRafał Miłecki struct ssb_bus *bus = irq_data_get_irq_chip_data(d); 3057c1bc0daSRafał Miłecki int gpio = irqd_to_hwirq(d); 3067c1bc0daSRafał Miłecki u32 val = ssb_extif_gpio_in(&bus->extif, BIT(gpio)); 3077c1bc0daSRafał Miłecki 3087c1bc0daSRafał Miłecki ssb_extif_gpio_polarity(&bus->extif, BIT(gpio), val); 3097c1bc0daSRafał Miłecki ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), BIT(gpio)); 3107c1bc0daSRafał Miłecki } 3117c1bc0daSRafał Miłecki 3127c1bc0daSRafał Miłecki static struct irq_chip ssb_gpio_irq_extif_chip = { 3137c1bc0daSRafał Miłecki .name = "SSB-GPIO-EXTIF", 3147c1bc0daSRafał Miłecki .irq_mask = ssb_gpio_irq_extif_mask, 3157c1bc0daSRafał Miłecki .irq_unmask = ssb_gpio_irq_extif_unmask, 3167c1bc0daSRafał Miłecki }; 3177c1bc0daSRafał Miłecki 3187c1bc0daSRafał Miłecki static irqreturn_t ssb_gpio_irq_extif_handler(int irq, void *dev_id) 3197c1bc0daSRafał Miłecki { 3207c1bc0daSRafał Miłecki struct ssb_bus *bus = dev_id; 3217c1bc0daSRafał Miłecki struct ssb_extif *extif = &bus->extif; 3227c1bc0daSRafał Miłecki u32 val = ssb_read32(extif->dev, SSB_EXTIF_GPIO_IN); 3237c1bc0daSRafał Miłecki u32 mask = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTMASK); 3247c1bc0daSRafał Miłecki u32 pol = ssb_read32(extif->dev, SSB_EXTIF_GPIO_INTPOL); 3257c1bc0daSRafał Miłecki unsigned long irqs = (val ^ pol) & mask; 3267c1bc0daSRafał Miłecki int gpio; 3277c1bc0daSRafał Miłecki 3287c1bc0daSRafał Miłecki if (!irqs) 3297c1bc0daSRafał Miłecki return IRQ_NONE; 3307c1bc0daSRafał Miłecki 3317c1bc0daSRafał Miłecki for_each_set_bit(gpio, &irqs, bus->gpio.ngpio) 3327c1bc0daSRafał Miłecki generic_handle_irq(ssb_gpio_to_irq(&bus->gpio, gpio)); 3337c1bc0daSRafał Miłecki ssb_extif_gpio_polarity(extif, irqs, val & irqs); 3347c1bc0daSRafał Miłecki 3357c1bc0daSRafał Miłecki return IRQ_HANDLED; 3367c1bc0daSRafał Miłecki } 3377c1bc0daSRafał Miłecki 3387c1bc0daSRafał Miłecki static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus) 3397c1bc0daSRafał Miłecki { 3407c1bc0daSRafał Miłecki struct ssb_extif *extif = &bus->extif; 3417c1bc0daSRafał Miłecki struct gpio_chip *chip = &bus->gpio; 3427c1bc0daSRafał Miłecki int gpio, hwirq, err; 3437c1bc0daSRafał Miłecki 3447c1bc0daSRafał Miłecki if (bus->bustype != SSB_BUSTYPE_SSB) 3457c1bc0daSRafał Miłecki return 0; 3467c1bc0daSRafał Miłecki 3477c1bc0daSRafał Miłecki bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio, 3487c1bc0daSRafał Miłecki &irq_domain_simple_ops, extif); 3497c1bc0daSRafał Miłecki if (!bus->irq_domain) { 3507c1bc0daSRafał Miłecki err = -ENODEV; 3517c1bc0daSRafał Miłecki goto err_irq_domain; 3527c1bc0daSRafał Miłecki } 3537c1bc0daSRafał Miłecki for (gpio = 0; gpio < chip->ngpio; gpio++) { 3547c1bc0daSRafał Miłecki int irq = irq_create_mapping(bus->irq_domain, gpio); 3557c1bc0daSRafał Miłecki 3567c1bc0daSRafał Miłecki irq_set_chip_data(irq, bus); 3577c1bc0daSRafał Miłecki irq_set_chip_and_handler(irq, &ssb_gpio_irq_extif_chip, 3587c1bc0daSRafał Miłecki handle_simple_irq); 3597c1bc0daSRafał Miłecki } 3607c1bc0daSRafał Miłecki 3617c1bc0daSRafał Miłecki hwirq = ssb_mips_irq(bus->extif.dev) + 2; 3627c1bc0daSRafał Miłecki err = request_irq(hwirq, ssb_gpio_irq_extif_handler, IRQF_SHARED, 3637c1bc0daSRafał Miłecki "gpio", bus); 3647c1bc0daSRafał Miłecki if (err) 3657c1bc0daSRafał Miłecki goto err_req_irq; 3667c1bc0daSRafał Miłecki 3677c1bc0daSRafał Miłecki ssb_extif_gpio_intmask(&bus->extif, ~0, 0); 3687c1bc0daSRafał Miłecki 3697c1bc0daSRafał Miłecki return 0; 3707c1bc0daSRafał Miłecki 3717c1bc0daSRafał Miłecki err_req_irq: 3727c1bc0daSRafał Miłecki for (gpio = 0; gpio < chip->ngpio; gpio++) { 3737c1bc0daSRafał Miłecki int irq = irq_find_mapping(bus->irq_domain, gpio); 3747c1bc0daSRafał Miłecki 3757c1bc0daSRafał Miłecki irq_dispose_mapping(irq); 3767c1bc0daSRafał Miłecki } 3777c1bc0daSRafał Miłecki irq_domain_remove(bus->irq_domain); 3787c1bc0daSRafał Miłecki err_irq_domain: 3797c1bc0daSRafał Miłecki return err; 3807c1bc0daSRafał Miłecki } 3817c1bc0daSRafał Miłecki 3827c1bc0daSRafał Miłecki static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus) 3837c1bc0daSRafał Miłecki { 3847c1bc0daSRafał Miłecki struct ssb_extif *extif = &bus->extif; 3857c1bc0daSRafał Miłecki struct gpio_chip *chip = &bus->gpio; 3867c1bc0daSRafał Miłecki int gpio; 3877c1bc0daSRafał Miłecki 3887c1bc0daSRafał Miłecki if (bus->bustype != SSB_BUSTYPE_SSB) 3897c1bc0daSRafał Miłecki return; 3907c1bc0daSRafał Miłecki 3917c1bc0daSRafał Miłecki free_irq(ssb_mips_irq(bus->extif.dev) + 2, extif); 3927c1bc0daSRafał Miłecki for (gpio = 0; gpio < chip->ngpio; gpio++) { 3937c1bc0daSRafał Miłecki int irq = irq_find_mapping(bus->irq_domain, gpio); 3947c1bc0daSRafał Miłecki 3957c1bc0daSRafał Miłecki irq_dispose_mapping(irq); 3967c1bc0daSRafał Miłecki } 3977c1bc0daSRafał Miłecki irq_domain_remove(bus->irq_domain); 3987c1bc0daSRafał Miłecki } 3997c1bc0daSRafał Miłecki #else 4007c1bc0daSRafał Miłecki static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus) 4017c1bc0daSRafał Miłecki { 4027c1bc0daSRafał Miłecki return 0; 4037c1bc0daSRafał Miłecki } 4047c1bc0daSRafał Miłecki 4057c1bc0daSRafał Miłecki static void ssb_gpio_irq_extif_domain_exit(struct ssb_bus *bus) 4067c1bc0daSRafał Miłecki { 4077c1bc0daSRafał Miłecki } 4087c1bc0daSRafał Miłecki #endif 4097c1bc0daSRafał Miłecki 410ec43b08bSHauke Mehrtens static int ssb_gpio_extif_init(struct ssb_bus *bus) 411ec43b08bSHauke Mehrtens { 412ec43b08bSHauke Mehrtens struct gpio_chip *chip = &bus->gpio; 4137c1bc0daSRafał Miłecki int err; 414ec43b08bSHauke Mehrtens 415ec43b08bSHauke Mehrtens chip->label = "ssb_extif_gpio"; 416ec43b08bSHauke Mehrtens chip->owner = THIS_MODULE; 417ec43b08bSHauke Mehrtens chip->get = ssb_gpio_extif_get_value; 418ec43b08bSHauke Mehrtens chip->set = ssb_gpio_extif_set_value; 419ec43b08bSHauke Mehrtens chip->direction_input = ssb_gpio_extif_direction_input; 420ec43b08bSHauke Mehrtens chip->direction_output = ssb_gpio_extif_direction_output; 4217c1bc0daSRafał Miłecki #if IS_ENABLED(CONFIG_SSB_EMBEDDED) 4227c1bc0daSRafał Miłecki chip->to_irq = ssb_gpio_to_irq; 4237c1bc0daSRafał Miłecki #endif 424ec43b08bSHauke Mehrtens chip->ngpio = 5; 425ec43b08bSHauke Mehrtens /* There is just one SoC in one device and its GPIO addresses should be 426ec43b08bSHauke Mehrtens * deterministic to address them more easily. The other buses could get 427ec43b08bSHauke Mehrtens * a random base number. */ 428ec43b08bSHauke Mehrtens if (bus->bustype == SSB_BUSTYPE_SSB) 429ec43b08bSHauke Mehrtens chip->base = 0; 430ec43b08bSHauke Mehrtens else 431ec43b08bSHauke Mehrtens chip->base = -1; 432ec43b08bSHauke Mehrtens 4337c1bc0daSRafał Miłecki err = ssb_gpio_irq_extif_domain_init(bus); 4347c1bc0daSRafał Miłecki if (err) 4357c1bc0daSRafał Miłecki return err; 4367c1bc0daSRafał Miłecki 4372d4443beSLinus Walleij err = gpiochip_add_data(chip, bus); 4387c1bc0daSRafał Miłecki if (err) { 4397c1bc0daSRafał Miłecki ssb_gpio_irq_extif_domain_exit(bus); 4407c1bc0daSRafał Miłecki return err; 4417c1bc0daSRafał Miłecki } 4427c1bc0daSRafał Miłecki 4437c1bc0daSRafał Miłecki return 0; 444ec43b08bSHauke Mehrtens } 445ec43b08bSHauke Mehrtens 446ec43b08bSHauke Mehrtens #else 447ec43b08bSHauke Mehrtens static int ssb_gpio_extif_init(struct ssb_bus *bus) 448ec43b08bSHauke Mehrtens { 449ec43b08bSHauke Mehrtens return -ENOTSUPP; 450ec43b08bSHauke Mehrtens } 451ec43b08bSHauke Mehrtens #endif 452ec43b08bSHauke Mehrtens 4537c1bc0daSRafał Miłecki /************************************************** 4547c1bc0daSRafał Miłecki * Init 4557c1bc0daSRafał Miłecki **************************************************/ 4567c1bc0daSRafał Miłecki 457ec43b08bSHauke Mehrtens int ssb_gpio_init(struct ssb_bus *bus) 458ec43b08bSHauke Mehrtens { 459ec43b08bSHauke Mehrtens if (ssb_chipco_available(&bus->chipco)) 460ec43b08bSHauke Mehrtens return ssb_gpio_chipco_init(bus); 461ec43b08bSHauke Mehrtens else if (ssb_extif_available(&bus->extif)) 462ec43b08bSHauke Mehrtens return ssb_gpio_extif_init(bus); 463ec43b08bSHauke Mehrtens else 464ec43b08bSHauke Mehrtens SSB_WARN_ON(1); 465ec43b08bSHauke Mehrtens 466ec43b08bSHauke Mehrtens return -1; 467ec43b08bSHauke Mehrtens } 468600485edSHauke Mehrtens 469600485edSHauke Mehrtens int ssb_gpio_unregister(struct ssb_bus *bus) 470600485edSHauke Mehrtens { 471600485edSHauke Mehrtens if (ssb_chipco_available(&bus->chipco) || 472600485edSHauke Mehrtens ssb_extif_available(&bus->extif)) { 47388d5e520Sabdoulaye berthe gpiochip_remove(&bus->gpio); 47488d5e520Sabdoulaye berthe return 0; 475600485edSHauke Mehrtens } else { 476600485edSHauke Mehrtens SSB_WARN_ON(1); 477600485edSHauke Mehrtens } 478600485edSHauke Mehrtens 479600485edSHauke Mehrtens return -1; 480600485edSHauke Mehrtens } 481