int mv_gpio_configure(device_t dev, uint32_t pin, uint32_t flags, uint32_t mask) { int error; struct mv_gpio_softc *sc; sc = (struct mv_gpio_softc *)device_get_softc(dev); error = 0; if (pin >= sc->pin_num) return (EINVAL); /* check flags consistency */ if (((flags & mask) & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) return (EINVAL); if (mask & MV_GPIO_IN_DEBOUNCE) { if (sc->irq_num == 0) return (EINVAL); error = mv_gpio_debounce_prepare(dev, pin); if (error != 0) return (error); } MV_GPIO_LOCK(); if ((mask & flags) & GPIO_PIN_INPUT) mv_gpio_out_en(dev, pin, 0); if ((mask & flags) & GPIO_PIN_OUTPUT) { if ((flags & mask) & GPIO_PIN_OPENDRAIN) mv_gpio_value_set(dev, pin, 0); else mv_gpio_value_set(dev, pin, 1); mv_gpio_out_en(dev, pin, 1); } if (mask & MV_GPIO_OUT_BLINK) mv_gpio_blink(dev, pin, flags & MV_GPIO_OUT_BLINK); if (mask & MV_GPIO_IN_POL_LOW) mv_gpio_polarity(dev, pin, flags & MV_GPIO_IN_POL_LOW, 0); if (mask & MV_GPIO_IN_DEBOUNCE) { error = mv_gpio_debounce_setup(dev, pin); if (error) { MV_GPIO_UNLOCK(); return (error); } } sc->gpio_setup[pin].gp_flags &= ~(mask); sc->gpio_setup[pin].gp_flags |= (flags & mask); MV_GPIO_UNLOCK(); return (0); }
void mv_gpio_out(device_t dev, uint32_t pin, uint8_t val, uint8_t enable) { struct mv_gpio_softc *sc; sc = (struct mv_gpio_softc *)device_get_softc(dev); MV_GPIO_LOCK(); mv_gpio_value_set(dev, pin, val); mv_gpio_out_en(dev, pin, enable); MV_GPIO_UNLOCK(); }
static int mv_gpio_attach(device_t dev) { int error, i; struct mv_gpio_softc *sc; uint32_t dev_id, rev_id; sc = (struct mv_gpio_softc *)device_get_softc(dev); if (mv_gpio_softc != NULL) return (ENXIO); mv_gpio_softc = sc; /* Get chip id and revision */ soc_id(&dev_id, &rev_id); if (dev_id == MV_DEV_88F5182 || dev_id == MV_DEV_88F5281 || dev_id == MV_DEV_MV78100 || dev_id == MV_DEV_MV78100_Z0 ) { sc->pin_num = 32; sc->irq_num = 4; sc->use_high = 0; } else if (dev_id == MV_DEV_88F6281) { sc->pin_num = 50; sc->irq_num = 7; sc->use_high = 1; } else { device_printf(dev, "unknown chip id=0x%x\n", dev_id); return (ENXIO); } error = bus_alloc_resources(dev, mv_gpio_res, sc->res); if (error) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); } sc->bst = rman_get_bustag(sc->res[0]); sc->bsh = rman_get_bushandle(sc->res[0]); /* Disable and clear all interrupts */ bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_EDGE_MASK, 0); bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_LEV_MASK, 0); bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_CAUSE, 0); if (sc->use_high) { bus_space_write_4(sc->bst, sc->bsh, GPIO_HI_INT_EDGE_MASK, 0); bus_space_write_4(sc->bst, sc->bsh, GPIO_HI_INT_LEV_MASK, 0); bus_space_write_4(sc->bst, sc->bsh, GPIO_HI_INT_CAUSE, 0); } for (i = 0; i < sc->irq_num; i++) { if (bus_setup_intr(dev, sc->res[1 + i], INTR_TYPE_MISC | INTR_FAST, (driver_filter_t *)mv_gpio_intr, NULL, sc, &sc->ih_cookie[i]) != 0) { bus_release_resources(dev, mv_gpio_res, sc->res); device_printf(dev, "could not set up intr %d\n", i); return (ENXIO); } } /* Setup GPIO lines */ for (i = 0; mv_gpio_config[i].gc_gpio >= 0; i++) { mv_gpio_configure(mv_gpio_config[i].gc_gpio, mv_gpio_config[i].gc_flags, ~0u); if (mv_gpio_config[i].gc_output < 0) mv_gpio_out_en(mv_gpio_config[i].gc_gpio, 0); else mv_gpio_out(mv_gpio_config[i].gc_gpio, mv_gpio_config[i].gc_output, 1); } return (0); }