Index: head/sys/arm/mv/gpio.c =================================================================== --- head/sys/arm/mv/gpio.c +++ head/sys/arm/mv/gpio.c @@ -71,13 +71,14 @@ int mem_rid; struct resource * irq_res[GPIO_MAX_INTR_COUNT]; int irq_rid[GPIO_MAX_INTR_COUNT]; + struct intr_event * gpio_events[MV_GPIO_MAX_NPINS]; void *ih_cookie[GPIO_MAX_INTR_COUNT]; bus_space_tag_t bst; bus_space_handle_t bsh; struct mtx mutex; uint8_t pin_num; /* number of GPIO pins */ uint8_t irq_num; /* number of real IRQs occupied by GPIO controller */ - uint8_t use_high; + struct gpio_pin gpio_setup[MV_GPIO_MAX_NPINS]; /* Used for debouncing. */ uint32_t debounced_state_lo; @@ -86,52 +87,56 @@ int *debounce_counters; }; -static struct mv_gpio_softc *mv_gpio_softc = NULL; -static uint32_t gpio_setup[MV_GPIO_MAX_NPINS]; +struct mv_gpio_pindev { + device_t dev; + int pin; +}; static int mv_gpio_probe(device_t); static int mv_gpio_attach(device_t); -static int mv_gpio_intr(void *); -static int mv_gpio_init(void); +static int mv_gpio_intr(device_t, void *); +static int mv_gpio_init(device_t); -static void mv_gpio_double_edge_init(int pin); +static void mv_gpio_double_edge_init(device_t, int); -static int mv_gpio_debounce_setup(int pin); -static int mv_gpio_debounce_init(int pin); -static void mv_gpio_debounce_start(int pin); -static int mv_gpio_debounce_prepare(int pin); -static void mv_gpio_debounce(void *arg); -static void mv_gpio_debounced_state_set(int pin, uint8_t new_state); -static uint32_t mv_gpio_debounced_state_get(int pin); +static int mv_gpio_debounce_setup(device_t, int); +static int mv_gpio_debounce_prepare(device_t, int); +static int mv_gpio_debounce_init(device_t, int); +static void mv_gpio_debounce_start(device_t, int); +static void mv_gpio_debounce(void *); +static void mv_gpio_debounced_state_set(device_t, int, uint8_t); +static uint32_t mv_gpio_debounced_state_get(device_t, int); -static void mv_gpio_exec_intr_handlers(uint32_t status, int high); -static void mv_gpio_intr_handler(int pin); -static uint32_t mv_gpio_reg_read(uint32_t reg); -static void mv_gpio_reg_write(uint32_t reg, uint32_t val); -static void mv_gpio_reg_set(uint32_t reg, uint32_t val); -static void mv_gpio_reg_clear(uint32_t reg, uint32_t val); +static void mv_gpio_exec_intr_handlers(device_t, uint32_t, int); +static void mv_gpio_intr_handler(device_t, int); +static uint32_t mv_gpio_reg_read(device_t, uint32_t); +static void mv_gpio_reg_write(device_t, uint32_t, uint32_t); +static void mv_gpio_reg_set(device_t, uint32_t, uint32_t); +static void mv_gpio_reg_clear(device_t, uint32_t, uint32_t); -static void mv_gpio_blink(uint32_t pin, uint8_t enable); -static void mv_gpio_polarity(uint32_t pin, uint8_t enable, uint8_t toggle); -static void mv_gpio_level(uint32_t pin, uint8_t enable); -static void mv_gpio_edge(uint32_t pin, uint8_t enable); -static void mv_gpio_out_en(uint32_t pin, uint8_t enable); -static void mv_gpio_int_ack(uint32_t pin); -static void mv_gpio_value_set(uint32_t pin, uint8_t val); -static uint32_t mv_gpio_value_get(uint32_t pin, uint8_t exclude_polar); +static void mv_gpio_blink(device_t, uint32_t, uint8_t); +static void mv_gpio_polarity(device_t, uint32_t, uint8_t, uint8_t); +static void mv_gpio_level(device_t, uint32_t, uint8_t); +static void mv_gpio_edge(device_t, uint32_t, uint8_t); +static void mv_gpio_out_en(device_t, uint32_t, uint8_t); +static void mv_gpio_int_ack(struct mv_gpio_pindev *); +static void mv_gpio_value_set(device_t, uint32_t, uint8_t); +static uint32_t mv_gpio_value_get(device_t, uint32_t, uint8_t); -static void mv_gpio_intr_mask(int pin); -static void mv_gpio_intr_unmask(int pin); -int mv_gpio_setup_intrhandler(const char *name, driver_filter_t *filt, - void (*hand)(void *), void *arg, int pin, int flags, void **cookiep); +static void mv_gpio_intr_mask(struct mv_gpio_pindev *); +static void mv_gpio_intr_unmask(struct mv_gpio_pindev *); -int mv_gpio_configure(uint32_t pin, uint32_t flags, uint32_t mask); -void mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable); -uint8_t mv_gpio_in(uint32_t pin); +void mv_gpio_finish_intrhandler(struct mv_gpio_pindev *); +int mv_gpio_setup_intrhandler(device_t, const char *, + driver_filter_t *, void (*)(void *), void *, + int, int, void **); +int mv_gpio_configure(device_t, uint32_t, uint32_t, uint32_t); +void mv_gpio_out(device_t, uint32_t, uint8_t, uint8_t); +uint8_t mv_gpio_in(device_t, uint32_t); -#define MV_GPIO_LOCK() mtx_lock_spin(&mv_gpio_softc->mutex) -#define MV_GPIO_UNLOCK() mtx_unlock_spin(&mv_gpio_softc->mutex) -#define MV_GPIO_ASSERT_LOCKED() mtx_assert(&mv_gpio_softc->mutex, MA_OWNED) +#define MV_GPIO_LOCK() mtx_lock_spin(&sc->mutex) +#define MV_GPIO_UNLOCK() mtx_unlock_spin(&sc->mutex) +#define MV_GPIO_ASSERT_LOCKED() mtx_assert(&sc->mutex, MA_OWNED) static device_method_t mv_gpio_methods[] = { DEVMETHOD(device_probe, mv_gpio_probe), @@ -149,14 +154,14 @@ DRIVER_MODULE(gpio, simplebus, mv_gpio_driver, mv_gpio_devclass, 0, 0); -typedef int (*gpios_phandler_t)(phandle_t, pcell_t *, int); +typedef int (*gpios_phandler_t)(device_t, phandle_t, pcell_t *, int); struct gpio_ctrl_entry { const char *compat; gpios_phandler_t handler; }; -static int mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len); +static int mv_handle_gpios_prop(device_t, phandle_t, pcell_t *, int); int gpio_get_config_from_dt(void); struct gpio_ctrl_entry gpio_controllers[] = { @@ -192,10 +197,6 @@ if (sc == NULL) return (ENXIO); - if (mv_gpio_softc != NULL) - return (ENXIO); - mv_gpio_softc = sc; - /* Get chip id and revision */ soc_id(&dev_id, &rev_id); @@ -205,13 +206,11 @@ 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 || dev_id == MV_DEV_88F6282) { sc->pin_num = 50; sc->irq_num = 7; - sc->use_high = 1; } else { if (OF_getencprop(ofw_bus_get_node(dev), "pin-count", &pincnt, @@ -294,15 +293,6 @@ 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); - 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->irq_res[i], INTR_TYPE_MISC, @@ -316,7 +306,7 @@ } } - error = mv_gpio_init(); + error = mv_gpio_init(dev); if (error) { device_printf(dev, "WARNING: failed to initialize GPIO pins, " "error = %d\n", error); @@ -325,14 +315,18 @@ /* Clear interrupt status. */ bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_CAUSE, 0); + device_add_child(dev, "gpioc", device_get_unit(dev)); + device_add_child(dev, "gpiobus", device_get_unit(dev)); + return (0); } static int -mv_gpio_intr(void *arg) +mv_gpio_intr(device_t dev, void *arg) { uint32_t int_cause, gpio_val; - uint32_t int_cause_hi, gpio_val_hi; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); MV_GPIO_LOCK(); @@ -340,31 +334,18 @@ * According to documentation, edge sensitive interrupts are asserted * when unmasked GPIO_INT_CAUSE register bits are set. */ - int_cause = mv_gpio_reg_read(GPIO_INT_CAUSE); - int_cause &= mv_gpio_reg_read(GPIO_INT_EDGE_MASK); + int_cause = mv_gpio_reg_read(dev, GPIO_INT_CAUSE); + int_cause &= mv_gpio_reg_read(dev, GPIO_INT_EDGE_MASK); /* * Level sensitive interrupts are asserted when unmasked GPIO_DATA_IN * register bits are set. */ - gpio_val = mv_gpio_reg_read(GPIO_DATA_IN); - gpio_val &= mv_gpio_reg_read(GPIO_INT_LEV_MASK); + gpio_val = mv_gpio_reg_read(dev, GPIO_DATA_IN); + gpio_val &= mv_gpio_reg_read(dev, GPIO_INT_LEV_MASK); - int_cause_hi = 0; - gpio_val_hi = 0; - if (mv_gpio_softc->use_high) { - int_cause_hi = mv_gpio_reg_read(GPIO_HI_INT_CAUSE); - int_cause_hi &= mv_gpio_reg_read(GPIO_HI_INT_EDGE_MASK); + mv_gpio_exec_intr_handlers(dev, int_cause | gpio_val, 0); - gpio_val_hi = mv_gpio_reg_read(GPIO_HI_DATA_IN); - gpio_val_hi &= mv_gpio_reg_read(GPIO_HI_INT_LEV_MASK); - } - - mv_gpio_exec_intr_handlers(int_cause | gpio_val, 0); - - if (mv_gpio_softc->use_high) - mv_gpio_exec_intr_handlers(int_cause_hi | gpio_val_hi, 1); - MV_GPIO_UNLOCK(); return (FILTER_HANDLED); @@ -374,31 +355,47 @@ * GPIO interrupt handling */ -static struct intr_event *gpio_events[MV_GPIO_MAX_NPINS]; +void +mv_gpio_finish_intrhandler(struct mv_gpio_pindev *s) +{ + /* When we acheive full interrupt support + * This function will be opposite to + * mv_gpio_setup_intrhandler + */ + /* Now it exists only to remind that + * there should be place to free mv_gpio_pindev + * allocated by mv_gpio_setup_intrhandler + */ + free(s, M_DEVBUF); +} + int -mv_gpio_setup_intrhandler(const char *name, driver_filter_t *filt, +mv_gpio_setup_intrhandler(device_t dev, const char *name, driver_filter_t *filt, void (*hand)(void *), void *arg, int pin, int flags, void **cookiep) { struct intr_event *event; int error; + struct mv_gpio_pindev *s; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); + s = malloc(sizeof(struct mv_gpio_pindev), M_DEVBUF, M_NOWAIT | M_ZERO); - if (pin < 0 || pin >= mv_gpio_softc->pin_num) + if (pin < 0 || pin >= sc->pin_num) return (ENXIO); - event = gpio_events[pin]; + event = sc->gpio_events[pin]; if (event == NULL) { MV_GPIO_LOCK(); - if (gpio_setup[pin] & MV_GPIO_IN_DEBOUNCE) { - error = mv_gpio_debounce_init(pin); + if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE) { + error = mv_gpio_debounce_init(dev, pin); if (error != 0) { MV_GPIO_UNLOCK(); return (error); } - } else if (gpio_setup[pin] & MV_GPIO_IN_IRQ_DOUBLE_EDGE) - mv_gpio_double_edge_init(pin); + } else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE) + mv_gpio_double_edge_init(dev, pin); MV_GPIO_UNLOCK(); - - error = intr_event_create(&event, (void *)pin, 0, pin, + error = intr_event_create(&event, (void *)s, 0, pin, (void (*)(void *))mv_gpio_intr_mask, (void (*)(void *))mv_gpio_intr_unmask, (void (*)(void *))mv_gpio_int_ack, @@ -406,7 +403,7 @@ "gpio%d:", pin); if (error != 0) return (error); - gpio_events[pin] = event; + sc->gpio_events[pin] = event; } intr_event_add_handler(event, name, filt, hand, arg, @@ -414,19 +411,22 @@ return (0); } -void -mv_gpio_intr_mask(int pin) +static void +mv_gpio_intr_mask(struct mv_gpio_pindev *s) { + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(s->dev); - if (pin >= mv_gpio_softc->pin_num) + if (s->pin >= sc->pin_num) return; MV_GPIO_LOCK(); - if (gpio_setup[pin] & (MV_GPIO_IN_IRQ_EDGE | MV_GPIO_IN_IRQ_DOUBLE_EDGE)) - mv_gpio_edge(pin, 0); + if (sc->gpio_setup[s->pin].gp_flags & (MV_GPIO_IN_IRQ_EDGE | + MV_GPIO_IN_IRQ_DOUBLE_EDGE)) + mv_gpio_edge(s->dev, s->pin, 0); else - mv_gpio_level(pin, 0); + mv_gpio_level(s->dev, s->pin, 0); /* * The interrupt has to be acknowledged before scheduling an interrupt @@ -434,32 +434,41 @@ * (which can happen with shared IRQs e.g. PCI) while processing the * current event. */ - mv_gpio_int_ack(pin); + mv_gpio_int_ack(s); MV_GPIO_UNLOCK(); + + return; } -void -mv_gpio_intr_unmask(int pin) +static void +mv_gpio_intr_unmask(struct mv_gpio_pindev *s) { + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(s->dev); - if (pin >= mv_gpio_softc->pin_num) + if (s->pin >= sc->pin_num) return; MV_GPIO_LOCK(); - if (gpio_setup[pin] & (MV_GPIO_IN_IRQ_EDGE | MV_GPIO_IN_IRQ_DOUBLE_EDGE)) - mv_gpio_edge(pin, 1); + if (sc->gpio_setup[s->pin].gp_flags & (MV_GPIO_IN_IRQ_EDGE | + MV_GPIO_IN_IRQ_DOUBLE_EDGE)) + mv_gpio_edge(s->dev, s->pin, 1); else - mv_gpio_level(pin, 1); + mv_gpio_level(s->dev, s->pin, 1); MV_GPIO_UNLOCK(); + + return; } static void -mv_gpio_exec_intr_handlers(uint32_t status, int high) +mv_gpio_exec_intr_handlers(device_t dev, uint32_t status, int high) { int i, pin; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); MV_GPIO_ASSERT_LOCKED(); @@ -467,13 +476,13 @@ while (status != 0) { if (status & 1) { pin = (high ? (i + GPIO_PINS_PER_REG) : i); - if (gpio_setup[pin] & MV_GPIO_IN_DEBOUNCE) - mv_gpio_debounce_start(pin); - else if (gpio_setup[pin] & MV_GPIO_IN_IRQ_DOUBLE_EDGE) { - mv_gpio_polarity(pin, 0, 1); - mv_gpio_intr_handler(pin); + if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE) + mv_gpio_debounce_start(dev, pin); + else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE) { + mv_gpio_polarity(dev, pin, 0, 1); + mv_gpio_intr_handler(dev, pin); } else - mv_gpio_intr_handler(pin); + mv_gpio_intr_handler(dev, pin); } status >>= 1; i++; @@ -481,17 +490,19 @@ } static void -mv_gpio_intr_handler(int pin) +mv_gpio_intr_handler(device_t dev, int pin) { #ifdef INTRNG struct intr_irqsrc isrc; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); MV_GPIO_ASSERT_LOCKED(); #ifdef INTR_SOLO isrc.isrc_filter = NULL; #endif - isrc.isrc_event = gpio_events[pin]; + isrc.isrc_event = sc->gpio_events[pin]; if (isrc.isrc_event == NULL || TAILQ_EMPTY(&isrc.isrc_event->ie_handlers)) return; @@ -501,11 +512,14 @@ } int -mv_gpio_configure(uint32_t pin, uint32_t flags, uint32_t mask) +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 >= mv_gpio_softc->pin_num) + if (pin >= sc->pin_num) return (EINVAL); /* check flags consistency */ @@ -514,7 +528,7 @@ return (EINVAL); if (mask & MV_GPIO_IN_DEBOUNCE) { - error = mv_gpio_debounce_prepare(pin); + error = mv_gpio_debounce_prepare(dev, pin); if (error != 0) return (error); } @@ -522,19 +536,19 @@ MV_GPIO_LOCK(); if (mask & MV_GPIO_OUT_BLINK) - mv_gpio_blink(pin, flags & MV_GPIO_OUT_BLINK); + mv_gpio_blink(dev, pin, flags & MV_GPIO_OUT_BLINK); if (mask & MV_GPIO_IN_POL_LOW) - mv_gpio_polarity(pin, flags & MV_GPIO_IN_POL_LOW, 0); + mv_gpio_polarity(dev, pin, flags & MV_GPIO_IN_POL_LOW, 0); if (mask & MV_GPIO_IN_DEBOUNCE) { - error = mv_gpio_debounce_setup(pin); + error = mv_gpio_debounce_setup(dev, pin); if (error) { MV_GPIO_UNLOCK(); return (error); } } - gpio_setup[pin] &= ~(mask); - gpio_setup[pin] |= (flags & mask); + sc->gpio_setup[pin].gp_flags &= ~(mask); + sc->gpio_setup[pin].gp_flags |= (flags & mask); MV_GPIO_UNLOCK(); @@ -542,28 +556,33 @@ } static void -mv_gpio_double_edge_init(int pin) +mv_gpio_double_edge_init(device_t dev, int pin) { uint8_t raw_read; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); MV_GPIO_ASSERT_LOCKED(); - raw_read = (mv_gpio_value_get(pin, 1) ? 1 : 0); + raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0); if (raw_read) - mv_gpio_polarity(pin, 1, 0); + mv_gpio_polarity(dev, pin, 1, 0); else - mv_gpio_polarity(pin, 0, 0); + mv_gpio_polarity(dev, pin, 0, 0); } static int -mv_gpio_debounce_setup(int pin) +mv_gpio_debounce_setup(device_t dev, int pin) { struct callout *c; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); + MV_GPIO_ASSERT_LOCKED(); - c = mv_gpio_softc->debounce_callouts[pin]; + c = sc->debounce_callouts[pin]; if (c == NULL) return (ENXIO); @@ -576,12 +595,12 @@ } static int -mv_gpio_debounce_prepare(int pin) +mv_gpio_debounce_prepare(device_t dev, int pin) { struct callout *c; struct mv_gpio_softc *sc; - sc = (struct mv_gpio_softc *)mv_gpio_softc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); c = sc->debounce_callouts[pin]; if (c == NULL) { @@ -597,58 +616,63 @@ } static int -mv_gpio_debounce_init(int pin) +mv_gpio_debounce_init(device_t dev, int pin) { uint8_t raw_read; int *cnt; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); + MV_GPIO_ASSERT_LOCKED(); - cnt = &mv_gpio_softc->debounce_counters[pin]; - - raw_read = (mv_gpio_value_get(pin, 1) ? 1 : 0); + cnt = &sc->debounce_counters[pin]; + raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0); if (raw_read) { - mv_gpio_polarity(pin, 1, 0); + mv_gpio_polarity(dev, pin, 1, 0); *cnt = DEBOUNCE_HI_LO_MS / DEBOUNCE_CHECK_MS; } else { - mv_gpio_polarity(pin, 0, 0); + mv_gpio_polarity(dev, pin, 0, 0); *cnt = DEBOUNCE_LO_HI_MS / DEBOUNCE_CHECK_MS; } - mv_gpio_debounced_state_set(pin, raw_read); + mv_gpio_debounced_state_set(dev, pin, raw_read); return (0); } static void -mv_gpio_debounce_start(int pin) +mv_gpio_debounce_start(device_t dev, int pin) { struct callout *c; - int *debounced_pin; + struct mv_gpio_pindev s = {dev, pin}; + struct mv_gpio_pindev *sd; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); MV_GPIO_ASSERT_LOCKED(); - c = mv_gpio_softc->debounce_callouts[pin]; + c = sc->debounce_callouts[pin]; if (c == NULL) { - mv_gpio_int_ack(pin); + mv_gpio_int_ack(&s); return; } if (callout_pending(c) || callout_active(c)) { - mv_gpio_int_ack(pin); + mv_gpio_int_ack(&s); return; } - debounced_pin = (int *)malloc(sizeof(int), M_DEVBUF, - M_WAITOK); - if (debounced_pin == NULL) { - mv_gpio_int_ack(pin); + sd = (struct mv_gpio_pindev *)malloc(sizeof(struct mv_gpio_pindev), + M_DEVBUF, M_WAITOK); + if (sd == NULL) { + mv_gpio_int_ack(&s); return; } - *debounced_pin = pin; + sd->pin = pin; + sd->dev = dev; - callout_reset(c, DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, - debounced_pin); + callout_reset(c, DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, sd); } static void @@ -656,15 +680,21 @@ { uint8_t raw_read, last_state; int pin; + device_t dev; int *debounce_counter; + struct mv_gpio_softc *sc; + struct mv_gpio_pindev *s; - pin = *((int *)arg); + s = (struct mv_gpio_pindev *)arg; + dev = s->dev; + pin = s->pin; + sc = (struct mv_gpio_softc *)device_get_softc(dev); MV_GPIO_LOCK(); - raw_read = (mv_gpio_value_get(pin, 1) ? 1 : 0); - last_state = (mv_gpio_debounced_state_get(pin) ? 1 : 0); - debounce_counter = &mv_gpio_softc->debounce_counters[pin]; + raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0); + last_state = (mv_gpio_debounced_state_get(dev, pin) ? 1 : 0); + debounce_counter = &sc->debounce_counters[pin]; if (raw_read == last_state) { if (last_state) @@ -674,15 +704,15 @@ *debounce_counter = DEBOUNCE_LO_HI_MS / DEBOUNCE_CHECK_MS; - callout_reset(mv_gpio_softc->debounce_callouts[pin], + callout_reset(sc->debounce_callouts[pin], DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, arg); } else { *debounce_counter = *debounce_counter - 1; if (*debounce_counter != 0) - callout_reset(mv_gpio_softc->debounce_callouts[pin], + callout_reset(sc->debounce_callouts[pin], DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, arg); else { - mv_gpio_debounced_state_set(pin, raw_read); + mv_gpio_debounced_state_set(dev, pin, raw_read); if (last_state) *debounce_counter = DEBOUNCE_HI_LO_MS / @@ -691,19 +721,18 @@ *debounce_counter = DEBOUNCE_LO_HI_MS / DEBOUNCE_CHECK_MS; - if (((gpio_setup[pin] & MV_GPIO_IN_POL_LOW) && + if (((sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW) && (raw_read == 0)) || - (((gpio_setup[pin] & MV_GPIO_IN_POL_LOW) == 0) && + (((sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW) == 0) && raw_read) || - (gpio_setup[pin] & MV_GPIO_IN_IRQ_DOUBLE_EDGE)) - mv_gpio_intr_handler(pin); + (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE)) + mv_gpio_intr_handler(dev, pin); /* Toggle polarity for next edge. */ - mv_gpio_polarity(pin, 0, 1); + mv_gpio_polarity(dev, pin, 0, 1); free(arg, M_DEVBUF); - callout_deactivate(mv_gpio_softc-> - debounce_callouts[pin]); + callout_deactivate(sc->debounce_callouts[pin]); } } @@ -711,17 +740,19 @@ } static void -mv_gpio_debounced_state_set(int pin, uint8_t new_state) +mv_gpio_debounced_state_set(device_t dev, int pin, uint8_t new_state) { uint32_t *old_state; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); MV_GPIO_ASSERT_LOCKED(); if (pin >= GPIO_PINS_PER_REG) { - old_state = &mv_gpio_softc->debounced_state_hi; + old_state = &sc->debounced_state_hi; pin -= GPIO_PINS_PER_REG; } else - old_state = &mv_gpio_softc->debounced_state_lo; + old_state = &sc->debounced_state_lo; if (new_state) *old_state |= (1 << pin); @@ -730,265 +761,255 @@ } static uint32_t -mv_gpio_debounced_state_get(int pin) +mv_gpio_debounced_state_get(device_t dev, int pin) { uint32_t *state; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); MV_GPIO_ASSERT_LOCKED(); if (pin >= GPIO_PINS_PER_REG) { - state = &mv_gpio_softc->debounced_state_hi; + state = &sc->debounced_state_hi; pin -= GPIO_PINS_PER_REG; } else - state = &mv_gpio_softc->debounced_state_lo; + state = &sc->debounced_state_lo; return (*state & (1 << pin)); } void -mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable) +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(pin, val); - mv_gpio_out_en(pin, enable); + mv_gpio_value_set(dev, pin, val); + mv_gpio_out_en(dev, pin, enable); MV_GPIO_UNLOCK(); } uint8_t -mv_gpio_in(uint32_t pin) +mv_gpio_in(device_t dev, uint32_t pin) { uint8_t state; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); MV_GPIO_LOCK(); - if (gpio_setup[pin] & MV_GPIO_IN_DEBOUNCE) { - if (gpio_setup[pin] & MV_GPIO_IN_POL_LOW) - state = (mv_gpio_debounced_state_get(pin) ? 0 : 1); + if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE) { + if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW) + state = (mv_gpio_debounced_state_get(dev, pin) ? 0 : 1); else - state = (mv_gpio_debounced_state_get(pin) ? 1 : 0); - } else if (gpio_setup[pin] & MV_GPIO_IN_IRQ_DOUBLE_EDGE) { - if (gpio_setup[pin] & MV_GPIO_IN_POL_LOW) - state = (mv_gpio_value_get(pin, 1) ? 0 : 1); + state = (mv_gpio_debounced_state_get(dev, pin) ? 1 : 0); + } else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE) { + if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW) + state = (mv_gpio_value_get(dev, pin, 1) ? 0 : 1); else - state = (mv_gpio_value_get(pin, 1) ? 1 : 0); + state = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0); } else - state = (mv_gpio_value_get(pin, 0) ? 1 : 0); + state = (mv_gpio_value_get(dev, pin, 0) ? 1 : 0); - MV_GPIO_UNLOCK(); return (state); } static uint32_t -mv_gpio_reg_read(uint32_t reg) +mv_gpio_reg_read(device_t dev, uint32_t reg) { + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); - return (bus_space_read_4(mv_gpio_softc->bst, - mv_gpio_softc->bsh, reg)); + return (bus_space_read_4(sc->bst, sc->bsh, reg)); } static void -mv_gpio_reg_write(uint32_t reg, uint32_t val) +mv_gpio_reg_write(device_t dev, uint32_t reg, uint32_t val) { + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); - bus_space_write_4(mv_gpio_softc->bst, - mv_gpio_softc->bsh, reg, val); + bus_space_write_4(sc->bst, sc->bsh, reg, val); } static void -mv_gpio_reg_set(uint32_t reg, uint32_t pin) +mv_gpio_reg_set(device_t dev, uint32_t reg, uint32_t pin) { uint32_t reg_val; - reg_val = mv_gpio_reg_read(reg); + reg_val = mv_gpio_reg_read(dev, reg); reg_val |= GPIO(pin); - mv_gpio_reg_write(reg, reg_val); + mv_gpio_reg_write(dev, reg, reg_val); } static void -mv_gpio_reg_clear(uint32_t reg, uint32_t pin) +mv_gpio_reg_clear(device_t dev, uint32_t reg, uint32_t pin) { uint32_t reg_val; - reg_val = mv_gpio_reg_read(reg); + reg_val = mv_gpio_reg_read(dev, reg); reg_val &= ~(GPIO(pin)); - mv_gpio_reg_write(reg, reg_val); + mv_gpio_reg_write(dev, reg, reg_val); } static void -mv_gpio_out_en(uint32_t pin, uint8_t enable) +mv_gpio_out_en(device_t dev, uint32_t pin, uint8_t enable) { uint32_t reg; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); - if (pin >= mv_gpio_softc->pin_num) + if (pin >= sc->pin_num) return; - if (pin >= GPIO_PINS_PER_REG) { - reg = GPIO_HI_DATA_OUT_EN_CTRL; - pin -= GPIO_PINS_PER_REG; - } else - reg = GPIO_DATA_OUT_EN_CTRL; + reg = GPIO_DATA_OUT_EN_CTRL; if (enable) - mv_gpio_reg_clear(reg, pin); + mv_gpio_reg_clear(dev, reg, pin); else - mv_gpio_reg_set(reg, pin); + mv_gpio_reg_set(dev, reg, pin); } static void -mv_gpio_blink(uint32_t pin, uint8_t enable) +mv_gpio_blink(device_t dev, uint32_t pin, uint8_t enable) { uint32_t reg; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); - if (pin >= mv_gpio_softc->pin_num) + if (pin >= sc->pin_num) return; - if (pin >= GPIO_PINS_PER_REG) { - reg = GPIO_HI_BLINK_EN; - pin -= GPIO_PINS_PER_REG; - } else - reg = GPIO_BLINK_EN; + reg = GPIO_BLINK_EN; if (enable) - mv_gpio_reg_set(reg, pin); + mv_gpio_reg_set(dev, reg, pin); else - mv_gpio_reg_clear(reg, pin); + mv_gpio_reg_clear(dev, reg, pin); } static void -mv_gpio_polarity(uint32_t pin, uint8_t enable, uint8_t toggle) +mv_gpio_polarity(device_t dev, uint32_t pin, uint8_t enable, uint8_t toggle) { uint32_t reg, reg_val; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); - if (pin >= mv_gpio_softc->pin_num) + if (pin >= sc->pin_num) return; - if (pin >= GPIO_PINS_PER_REG) { - reg = GPIO_HI_DATA_IN_POLAR; - pin -= GPIO_PINS_PER_REG; - } else - reg = GPIO_DATA_IN_POLAR; + reg = GPIO_DATA_IN_POLAR; if (toggle) { - reg_val = mv_gpio_reg_read(reg) & GPIO(pin); + reg_val = mv_gpio_reg_read(dev, reg) & GPIO(pin); if (reg_val) - mv_gpio_reg_clear(reg, pin); + mv_gpio_reg_clear(dev, reg, pin); else - mv_gpio_reg_set(reg, pin); + mv_gpio_reg_set(dev, reg, pin); } else if (enable) - mv_gpio_reg_set(reg, pin); + mv_gpio_reg_set(dev, reg, pin); else - mv_gpio_reg_clear(reg, pin); + mv_gpio_reg_clear(dev, reg, pin); } static void -mv_gpio_level(uint32_t pin, uint8_t enable) +mv_gpio_level(device_t dev, uint32_t pin, uint8_t enable) { uint32_t reg; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); - if (pin >= mv_gpio_softc->pin_num) + if (pin >= sc->pin_num) return; - if (pin >= GPIO_PINS_PER_REG) { - reg = GPIO_HI_INT_LEV_MASK; - pin -= GPIO_PINS_PER_REG; - } else - reg = GPIO_INT_LEV_MASK; + reg = GPIO_INT_LEV_MASK; if (enable) - mv_gpio_reg_set(reg, pin); + mv_gpio_reg_set(dev, reg, pin); else - mv_gpio_reg_clear(reg, pin); + mv_gpio_reg_clear(dev, reg, pin); } static void -mv_gpio_edge(uint32_t pin, uint8_t enable) +mv_gpio_edge(device_t dev, uint32_t pin, uint8_t enable) { uint32_t reg; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); - if (pin >= mv_gpio_softc->pin_num) + if (pin >= sc->pin_num) return; - if (pin >= GPIO_PINS_PER_REG) { - reg = GPIO_HI_INT_EDGE_MASK; - pin -= GPIO_PINS_PER_REG; - } else - reg = GPIO_INT_EDGE_MASK; + reg = GPIO_INT_EDGE_MASK; if (enable) - mv_gpio_reg_set(reg, pin); + mv_gpio_reg_set(dev, reg, pin); else - mv_gpio_reg_clear(reg, pin); + mv_gpio_reg_clear(dev, reg, pin); } static void -mv_gpio_int_ack(uint32_t pin) +mv_gpio_int_ack(struct mv_gpio_pindev *s) { - uint32_t reg; + uint32_t reg, pin; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(s->dev); + pin = s->pin; - if (pin >= mv_gpio_softc->pin_num) + if (pin >= sc->pin_num) return; - if (pin >= GPIO_PINS_PER_REG) { - reg = GPIO_HI_INT_CAUSE; - pin -= GPIO_PINS_PER_REG; - } else - reg = GPIO_INT_CAUSE; + reg = GPIO_INT_CAUSE; - mv_gpio_reg_clear(reg, pin); + mv_gpio_reg_clear(s->dev, reg, pin); } static uint32_t -mv_gpio_value_get(uint32_t pin, uint8_t exclude_polar) +mv_gpio_value_get(device_t dev, uint32_t pin, uint8_t exclude_polar) { uint32_t reg, polar_reg, reg_val, polar_reg_val; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); - if (pin >= mv_gpio_softc->pin_num) + if (pin >= sc->pin_num) return (0); - if (pin >= GPIO_PINS_PER_REG) { - reg = GPIO_HI_DATA_IN; - pin -= GPIO_PINS_PER_REG; - polar_reg = GPIO_HI_DATA_IN_POLAR; - } else { - reg = GPIO_DATA_IN; - polar_reg = GPIO_DATA_IN_POLAR; - } + reg = GPIO_DATA_IN; + polar_reg = GPIO_DATA_IN_POLAR; - reg_val = mv_gpio_reg_read(reg); + reg_val = mv_gpio_reg_read(dev, reg); if (exclude_polar) { - polar_reg_val = mv_gpio_reg_read(polar_reg); + polar_reg_val = mv_gpio_reg_read(dev, polar_reg); return ((reg_val & GPIO(pin)) ^ (polar_reg_val & GPIO(pin))); } else return (reg_val & GPIO(pin)); } static void -mv_gpio_value_set(uint32_t pin, uint8_t val) +mv_gpio_value_set(device_t dev, uint32_t pin, uint8_t val) { uint32_t reg; + struct mv_gpio_softc *sc; + sc = (struct mv_gpio_softc *)device_get_softc(dev); - if (pin >= mv_gpio_softc->pin_num) + if (pin >= sc->pin_num) return; - if (pin >= GPIO_PINS_PER_REG) { - reg = GPIO_HI_DATA_OUT; - pin -= GPIO_PINS_PER_REG; - } else - reg = GPIO_DATA_OUT; + reg = GPIO_DATA_OUT; if (val) - mv_gpio_reg_set(reg, pin); + mv_gpio_reg_set(dev, reg, pin); else - mv_gpio_reg_clear(reg, pin); + mv_gpio_reg_clear(dev, reg, pin); } static int -mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len) +mv_handle_gpios_prop(device_t dev, phandle_t ctrl, pcell_t *gpios, int len) { pcell_t gpio_cells, pincnt; int inc, t, tuples, tuple_size; @@ -1028,18 +1049,18 @@ dir = gpios[1]; flags = gpios[2]; - mv_gpio_configure(pin, flags, ~0); + mv_gpio_configure(dev, pin, flags, ~0); if (dir == 1) /* Input. */ - mv_gpio_out_en(pin, 0); + mv_gpio_out_en(dev, pin, 0); else { /* Output. */ if (flags & MV_GPIO_OUT_OPEN_DRAIN) - mv_gpio_out(pin, 0, 1); + mv_gpio_out(dev, pin, 0, 1); if (flags & MV_GPIO_OUT_OPEN_SRC) - mv_gpio_out(pin, 1, 1); + mv_gpio_out(dev, pin, 1, 1); } gpios += gpio_cells + inc; } @@ -1050,7 +1071,7 @@ #define MAX_PINS_PER_NODE 5 #define GPIOS_PROP_CELLS 4 static int -mv_gpio_init(void) +mv_gpio_init(device_t dev) { phandle_t child, parent, root, ctrl; pcell_t gpios[MAX_PINS_PER_NODE * GPIOS_PROP_CELLS]; @@ -1090,7 +1111,7 @@ if (ofw_bus_node_is_compatible(ctrl, e->compat)) /* Call a handler. */ - if ((rv = e->handler(ctrl, + if ((rv = e->handler(dev, ctrl, (pcell_t *)&gpios, len))) return (rv); } Index: head/sys/arm/mv/mvreg.h =================================================================== --- head/sys/arm/mv/mvreg.h +++ head/sys/arm/mv/mvreg.h @@ -296,15 +296,6 @@ #define GPIO_INT_EDGE_MASK 0x18 #define GPIO_INT_LEV_MASK 0x1c -#define GPIO_HI_DATA_OUT 0x40 -#define GPIO_HI_DATA_OUT_EN_CTRL 0x44 -#define GPIO_HI_BLINK_EN 0x48 -#define GPIO_HI_DATA_IN_POLAR 0x4c -#define GPIO_HI_DATA_IN 0x50 -#define GPIO_HI_INT_CAUSE 0x54 -#define GPIO_HI_INT_EDGE_MASK 0x58 -#define GPIO_HI_INT_LEV_MASK 0x5c - #define GPIO(n) (1 << (n)) #define MV_GPIO_MAX_NPINS 64