static inline void intr_write_modify(struct tegra_gpio_softc *sc, bus_addr_t reg, struct tegra_gpio_irqsrc *tgi, uint32_t val, uint32_t mask) { uint32_t tmp; int bit; bit = GPIO_BIT(tgi->irq); GPIO_LOCK(sc); tmp = bus_read_4(sc->mem_res, reg + GPIO_REGNUM(tgi->irq)); tmp &= ~(mask << bit); tmp |= val << bit; bus_write_4(sc->mem_res, reg + GPIO_REGNUM(tgi->irq), tmp); GPIO_UNLOCK(sc); }
static inline uint32_t gpio_read(struct tegra_gpio_softc *sc, bus_size_t reg, struct gpio_pin *pin) { int bit; uint32_t val; bit = GPIO_BIT(pin->gp_pin); val = bus_read_4(sc->mem_res, reg + GPIO_REGNUM(pin->gp_pin)); return (val >> bit) & 1; }
static int tegra_gpio_intr(void *arg) { u_int irq, i, j, val, basepin; struct tegra_gpio_softc *sc; struct trapframe *tf; struct tegra_gpio_irqsrc *tgi; struct tegra_gpio_irq_cookie *cookie; cookie = (struct tegra_gpio_irq_cookie *)arg; sc = cookie->sc; tf = curthread->td_intr_frame; for (i = 0; i < GPIO_REGS_IN_BANK; i++) { basepin = cookie->bank_num * GPIO_REGS_IN_BANK * GPIO_PINS_IN_REG + i * GPIO_PINS_IN_REG; val = bus_read_4(sc->mem_res, GPIO_INT_STA + GPIO_REGNUM(basepin)); val &= bus_read_4(sc->mem_res, GPIO_INT_ENB + GPIO_REGNUM(basepin)); /* Interrupt handling */ for (j = 0; j < GPIO_PINS_IN_REG; j++) { if ((val & (1 << j)) == 0) continue; irq = basepin + j; tgi = &sc->isrcs[irq]; if (!tegra_gpio_isrc_is_level(tgi)) tegra_gpio_isrc_eoi(sc, tgi); if (intr_isrc_dispatch(&tgi->isrc, tf) != 0) { tegra_gpio_isrc_mask(sc, tgi, 0); if (tegra_gpio_isrc_is_level(tgi)) tegra_gpio_isrc_eoi(sc, tgi); device_printf(sc->dev, "Stray irq %u disabled\n", irq); } } } return (FILTER_HANDLED); }
/* -------------------------------------------------------------------------- * * Interrupts * */ static inline void intr_write_masked(struct tegra_gpio_softc *sc, bus_addr_t reg, struct tegra_gpio_irqsrc *tgi, uint32_t val) { uint32_t tmp; int bit; bit = GPIO_BIT(tgi->irq); tmp = 0x100 << bit; /* mask */ tmp |= (val & 1) << bit; /* value */ bus_write_4(sc->mem_res, reg + GPIO_REGNUM(tgi->irq), tmp); }
/* -------------------------------------------------------------------------- * * GPIO * */ static inline void gpio_write_masked(struct tegra_gpio_softc *sc, bus_size_t reg, struct gpio_pin *pin, uint32_t val) { uint32_t tmp; int bit; bit = GPIO_BIT(pin->gp_pin); tmp = 0x100 << bit; /* mask */ tmp |= (val & 1) << bit; /* value */ bus_write_4(sc->mem_res, reg + GPIO_REGNUM(pin->gp_pin), tmp); }
static int tegra_gpio_intr(void *arg) { struct tegra_gpio_softc *sc; uint32_t val; int i; sc = arg; for (i = 0; i < NGPIO; i += GPIO_PINS_IN_REG) { /* Clear interrupt */ val = bus_read_4(sc->mem_res, GPIO_INT_STA + GPIO_REGNUM(i)); val &= bus_read_4(sc->mem_res, GPIO_INT_ENB + GPIO_REGNUM(i)); bus_write_4(sc->mem_res, GPIO_INT_CLR + GPIO_REGNUM(i), val); /* Interrupt handling */ #ifdef not_yet for (j = 0; j < GPIO_PINS_IN_REG; j++) { if (val & (1 << j)) handle_irq(i + j); } */ #endif } return (FILTER_HANDLED); }
static int tegra_gpio_attach(device_t dev) { struct tegra_gpio_softc *sc; int i, rid; sc = device_get_softc(dev); sc->dev = dev; GPIO_LOCK_INIT(sc); /* Allocate bus_space resources. */ rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->mem_res == NULL) { device_printf(dev, "Cannot allocate memory resources\n"); tegra_gpio_detach(dev); return (ENXIO); } sc->gpio_npins = NGPIO; for (i = 0; i < sc->gpio_npins; i++) { sc->gpio_pins[i].gp_pin = i; sc->gpio_pins[i].gp_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_INTR_LEVEL_LOW | GPIO_INTR_LEVEL_HIGH | GPIO_INTR_EDGE_RISING | GPIO_INTR_EDGE_FALLING | GPIO_INTR_EDGE_BOTH; snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, "gpio_%s.%d", tegra_gpio_port_names[ i / GPIO_PINS_IN_REG], i % GPIO_PINS_IN_REG); sc->gpio_pins[i].gp_flags = gpio_read(sc, GPIO_OE, &sc->gpio_pins[i]) != 0 ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT; } /* Init interrupt related registes. */ for (i = 0; i < sc->gpio_npins; i += GPIO_PINS_IN_REG) { bus_write_4(sc->mem_res, GPIO_INT_ENB + GPIO_REGNUM(i), 0); bus_write_4(sc->mem_res, GPIO_INT_STA + GPIO_REGNUM(i), 0xFF); bus_write_4(sc->mem_res, GPIO_INT_CLR + GPIO_REGNUM(i), 0xFF); } /* Allocate interrupts. */ for (i = 0; i < GPIO_NUM_BANKS; i++) { sc->irq_cookies[i].sc = sc; sc->irq_cookies[i].bank_num = i; rid = i; sc->irq_res[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->irq_res[i] == NULL) { device_printf(dev, "Cannot allocate IRQ resources\n"); tegra_gpio_detach(dev); return (ENXIO); } if ((bus_setup_intr(dev, sc->irq_res[i], INTR_TYPE_MISC | INTR_MPSAFE, tegra_gpio_intr, NULL, &sc->irq_cookies[i], &sc->irq_ih[i]))) { device_printf(dev, "WARNING: unable to register interrupt handler\n"); tegra_gpio_detach(dev); return (ENXIO); } } if (tegra_gpio_pic_attach(sc) != 0) { device_printf(dev, "WARNING: unable to attach PIC\n"); tegra_gpio_detach(dev); return (ENXIO); } sc->busdev = gpiobus_attach_bus(dev); if (sc->busdev == NULL) { tegra_gpio_detach(dev); return (ENXIO); } return (bus_generic_attach(dev)); }