static void ssb_gpio_irq_extif_mask(struct irq_data *d) { struct ssb_bus *bus = irq_data_get_irq_chip_data(d); int gpio = irqd_to_hwirq(d); ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), 0); }
static void ssb_gpio_irq_extif_unmask(struct irq_data *d) { struct ssb_bus *bus = irq_data_get_irq_chip_data(d); int gpio = irqd_to_hwirq(d); u32 val = ssb_extif_gpio_in(&bus->extif, BIT(gpio)); ssb_extif_gpio_polarity(&bus->extif, BIT(gpio), val); ssb_extif_gpio_intmask(&bus->extif, BIT(gpio), BIT(gpio)); }
u32 ssb_gpio_intmask(struct ssb_bus *bus, u32 mask, u32 value) { unsigned long flags; u32 res = 0; spin_lock_irqsave(&bus->gpio_lock, flags); if (ssb_chipco_available(&bus->chipco)) res = ssb_chipco_gpio_intmask(&bus->chipco, mask, value); else if (ssb_extif_available(&bus->extif)) res = ssb_extif_gpio_intmask(&bus->extif, mask, value); else SSB_WARN_ON(1); spin_unlock_irqrestore(&bus->gpio_lock, flags); return res; }
static int ssb_gpio_irq_extif_domain_init(struct ssb_bus *bus) { struct ssb_extif *extif = &bus->extif; struct gpio_chip *chip = &bus->gpio; int gpio, hwirq, err; if (bus->bustype != SSB_BUSTYPE_SSB) return 0; bus->irq_domain = irq_domain_add_linear(NULL, chip->ngpio, &irq_domain_simple_ops, extif); if (!bus->irq_domain) { err = -ENODEV; goto err_irq_domain; } for (gpio = 0; gpio < chip->ngpio; gpio++) { int irq = irq_create_mapping(bus->irq_domain, gpio); irq_set_chip_data(irq, bus); irq_set_chip_and_handler(irq, &ssb_gpio_irq_extif_chip, handle_simple_irq); } hwirq = ssb_mips_irq(bus->extif.dev) + 2; err = request_irq(hwirq, ssb_gpio_irq_extif_handler, IRQF_SHARED, "gpio", bus); if (err) goto err_req_irq; ssb_extif_gpio_intmask(&bus->extif, ~0, 0); return 0; err_req_irq: for (gpio = 0; gpio < chip->ngpio; gpio++) { int irq = irq_find_mapping(bus->irq_domain, gpio); irq_dispose_mapping(irq); } irq_domain_remove(bus->irq_domain); err_irq_domain: return err; }