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_pin_set(device_t dev, uint32_t pin, unsigned int value) { struct mtk_gpio_softc *sc; 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; } if (value) MTK_WRITE_4(sc, GPIO_PIOSET(sc), (1u << pin)); else MTK_WRITE_4(sc, GPIO_PIORESET(sc), (1u << pin)); out: MTK_GPIO_UNLOCK(sc); return (ret); }
static void mtk_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc) { struct mtk_gpio_softc *sc; struct mtk_gpio_pin_irqsrc *pisrc; pisrc = (struct mtk_gpio_pin_irqsrc *)isrc; sc = device_get_softc(dev); MTK_GPIO_LOCK(sc); MTK_WRITE_4(sc, GPIO_PIOINT, 1u << pisrc->irq); MTK_GPIO_UNLOCK(sc); }
static int mtk_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) { struct mtk_gpio_softc *sc = device_get_softc(dev); if (pin >= sc->num_pins) return (EINVAL); MTK_GPIO_LOCK(sc); *flags = sc->pins[pin].pin_flags; MTK_GPIO_UNLOCK(sc); return (0); }
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 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(device_t dev, uint32_t pin, unsigned int value) { struct mtk_gpio_softc *sc; int ret; sc = device_get_softc(dev); ret = 0; if (pin >= sc->num_pins) return (EINVAL); MTK_GPIO_LOCK(sc); if (value) MTK_WRITE_4(sc, GPIO_PIOSET, (1u << pin)); else MTK_WRITE_4(sc, GPIO_PIORESET, (1u << pin)); MTK_GPIO_UNLOCK(sc); return (ret); }
static int mtk_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) { struct mtk_gpio_softc *sc; int retval; sc = device_get_softc(dev); if (pin >= sc->num_pins) return (EINVAL); MTK_GPIO_LOCK(sc); retval = mtk_gpio_pin_set_direction(sc, pin, flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)); if (retval == 0) retval = mtk_gpio_pin_set_invert(sc, pin, flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)); MTK_GPIO_UNLOCK(sc); return (retval); }
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 int mtk_gpio_pin_toggle(device_t dev, uint32_t pin) { struct mtk_gpio_softc *sc; int ret; sc = device_get_softc(dev); ret = 0; if (pin >= sc->num_pins) return (EINVAL); MTK_GPIO_LOCK(sc); if (!(sc->pins[pin].pin_flags & GPIO_PIN_OUTPUT)) { ret = EINVAL; goto out; } MTK_WRITE_4(sc, GPIO_PIOTOG, (1u << pin)); out: MTK_GPIO_UNLOCK(sc); return (ret); }