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