static void mtk_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) { struct mtk_gpio_softc *sc; struct mtk_gpio_pin_irqsrc *pisrc; uint32_t pin, mask, val; sc = device_get_softc(dev); pisrc = (struct mtk_gpio_pin_irqsrc *)isrc; pin = pisrc->irq; mask = 1u << pin; MTK_GPIO_LOCK(sc); if (sc->pins[pin].intr_polarity == INTR_POLARITY_LOW) { val = MTK_READ_4(sc, GPIO_PIORENA) & ~mask; MTK_WRITE_4(sc, GPIO_PIORENA, val); val = MTK_READ_4(sc, GPIO_PIOFENA) | mask; MTK_WRITE_4(sc, GPIO_PIOFENA, val); } else { val = MTK_READ_4(sc, GPIO_PIOFENA) & ~mask; MTK_WRITE_4(sc, GPIO_PIOFENA, val); val = MTK_READ_4(sc, GPIO_PIORENA) | mask; MTK_WRITE_4(sc, GPIO_PIORENA, val); } MTK_GPIO_UNLOCK(sc); }
static int mtk_gpio_pin_toggle(device_t dev, uint32_t pin) { struct mtk_gpio_softc *sc; uint32_t val; int ret; if (pin >= sc->num_pins) return (EINVAL); sc = device_get_softc(dev); ret = 0; MTK_GPIO_LOCK(sc); if(!(sc->pins[pin].pin_flags & GPIO_PIN_OUTPUT)) { ret = EINVAL; goto out; } val = MTK_READ_4(sc, GPIO_PIODATA(sc)); val &= (1u << pin); if (val) MTK_WRITE_4(sc, GPIO_PIORESET(sc), (1u << pin)); else MTK_WRITE_4(sc, GPIO_PIOSET(sc), (1u << pin)); out: MTK_GPIO_UNLOCK(sc); return (ret); }
static int mtk_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) { struct mtk_gpio_softc *sc; uint32_t data; int ret; if (pin >= sc->num_pins) return (EINVAL); sc = device_get_softc(dev); ret = 0; MTK_GPIO_LOCK(sc); if (!(sc->pins[pin].pin_flags & GPIO_PIN_INPUT)) { ret = EINVAL; goto out; } data = MTK_READ_4(sc, GPIO_PIODATA(sc)); *val = (data & (1u << pin)) ? 1 : 0; out: MTK_GPIO_UNLOCK(sc); return (ret); }
static int mtk_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { struct mtk_gpio_softc *sc; uint32_t val; int error; uint32_t mode; u_int irq; if (data == NULL) return (ENOTSUP); sc = device_get_softc(dev); switch (data->type) { case INTR_MAP_DATA_FDT: error = mtk_gpio_pic_map_fdt(sc, (struct intr_map_data_fdt *)data, &irq, &mode); break; case INTR_MAP_DATA_GPIO: error = mtk_gpio_pic_map_gpio(sc, (struct intr_map_data_gpio *)data, &irq, &mode); break; default: error = ENOTSUP; break; } if (error != 0) return (error); MTK_GPIO_LOCK(sc); if (mode == GPIO_INTR_EDGE_BOTH || mode == GPIO_INTR_EDGE_RISING) { val = MTK_READ_4(sc, GPIO_PIORENA) | (1u << irq); MTK_WRITE_4(sc, GPIO_PIORENA, val); } if (mode == GPIO_INTR_EDGE_BOTH || mode == GPIO_INTR_EDGE_FALLING) { val = MTK_READ_4(sc, GPIO_PIOFENA) | (1u << irq); MTK_WRITE_4(sc, GPIO_PIOFENA, val); } MTK_GPIO_UNLOCK(sc); return (0); }
static void mtk_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc) { struct mtk_gpio_softc *sc; struct mtk_gpio_pin_irqsrc *pisrc; uint32_t pin, mask, val; sc = device_get_softc(dev); pisrc = (struct mtk_gpio_pin_irqsrc *)isrc; pin = pisrc->irq; mask = 1u << pin; MTK_GPIO_LOCK(sc); val = MTK_READ_4(sc, GPIO_PIORENA) & ~mask; MTK_WRITE_4(sc, GPIO_PIORENA, val); val = MTK_READ_4(sc, GPIO_PIOFENA) & ~mask; MTK_WRITE_4(sc, GPIO_PIOFENA, val); MTK_GPIO_UNLOCK(sc); }
static void mtk_gpio_pin_probe(struct mtk_gpio_softc *sc, uint32_t pin) { uint32_t mask = (1u << pin); uint32_t val; /* Clear cached gpio config */ sc->pins[pin].pin_flags = 0; val = MTK_READ_4(sc, GPIO_PIORENA) | MTK_READ_4(sc, GPIO_PIOFENA); if (val & mask) { /* Pin is in interrupt mode */ sc->pins[pin].intr_trigger = INTR_TRIGGER_EDGE; val = MTK_READ_4(sc, GPIO_PIORENA); if (val & mask) sc->pins[pin].intr_polarity = INTR_POLARITY_HIGH; else sc->pins[pin].intr_polarity = INTR_POLARITY_LOW; } val = MTK_READ_4(sc, GPIO_PIODIR); if (val & mask) sc->pins[pin].pin_flags |= GPIO_PIN_OUTPUT; else sc->pins[pin].pin_flags |= GPIO_PIN_INPUT; val = MTK_READ_4(sc, GPIO_PIOPOL); if (val & mask) { if (sc->pins[pin].pin_flags & GPIO_PIN_INPUT) { sc->pins[pin].pin_flags |= GPIO_PIN_INVIN; } else { sc->pins[pin].pin_flags |= GPIO_PIN_INVOUT; } } }
static int mtk_gpio_pin_set_invert(struct mtk_gpio_softc *sc, uint32_t pin, uint32_t val) { uint32_t regval, mask = (1u << pin); regval = MTK_READ_4(sc, GPIO_PIOPOL); if (val) regval |= mask; else regval &= ~mask; MTK_WRITE_4(sc, GPIO_PIOPOL, regval); sc->pins[pin].pin_flags &= ~(GPIO_PIN_INVIN | GPIO_PIN_INVOUT); sc->pins[pin].pin_flags |= val; return (0); }
static int mtk_gpio_intr(void *arg) { struct mtk_gpio_softc *sc; uint32_t i, interrupts; sc = arg; interrupts = MTK_READ_4(sc, GPIO_PIOINT); for (i = 0; interrupts != 0; i++, interrupts >>= 1) { if ((interrupts & 0x1) == 0) continue; if (intr_isrc_dispatch(PIC_INTR_ISRC(sc, i), curthread->td_intr_frame) != 0) { device_printf(sc->dev, "spurious interrupt %d\n", i); } } return (FILTER_HANDLED); }
static int mtk_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) { struct mtk_gpio_softc *sc; uint32_t data; int ret; sc = device_get_softc(dev); ret = 0; if (pin >= sc->num_pins) return (EINVAL); MTK_GPIO_LOCK(sc); data = MTK_READ_4(sc, GPIO_PIODATA); *val = (data & (1u << pin)) ? 1 : 0; MTK_GPIO_UNLOCK(sc); return (ret); }
static int mtk_gpio_pin_set_direction(struct mtk_gpio_softc *sc, uint32_t pin, uint32_t dir) { uint32_t regval, mask = (1u << pin); if (!(sc->pins[pin].pin_caps & dir)) return (EINVAL); regval = MTK_READ_4(sc, GPIO_PIODIR); if (dir == GPIO_PIN_INPUT) regval &= ~mask; else regval |= mask; MTK_WRITE_4(sc, GPIO_PIODIR, regval); sc->pins[pin].pin_flags &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT); sc->pins[pin].pin_flags |= dir; return (0); }