Fix the handling of pull-up and pull-down for RK3188.

For this to work the driver needs to know the bank it has attached to since
the registers for the first 12 pins are at a different location.

Move the lock initialization to simplify the code.
This commit is contained in:
Luiz Otavio O Souza 2015-01-07 19:15:11 +00:00
parent 47a80b9264
commit 60245f5103

View File

@ -79,10 +79,14 @@ struct rk30_gpio_softc {
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh;
void * sc_intrhand;
int sc_bank;
int sc_gpio_npins;
struct gpio_pin sc_gpio_pins[RK30_GPIO_PINS];
};
/* We use our base address to find out our bank number. */
static unsigned long rk30_gpio_base_addr[4] =
{ 0x2000a000, 0x2003c000, 0x2003e000, 0x20080000 };
static struct rk30_gpio_softc *rk30_gpio_sc = NULL;
typedef int (*gpios_phandler_t)(phandle_t, pcell_t *, int);
@ -153,17 +157,28 @@ rk30_gpio_set_function(struct rk30_gpio_softc *sc, uint32_t pin, uint32_t func)
static void
rk30_gpio_set_pud(struct rk30_gpio_softc *sc, uint32_t pin, uint32_t state)
{
uint32_t bank;
bank = pin / 32;
uint32_t pud;
/* Must be called with lock held. */
RK30_GPIO_LOCK_ASSERT(sc);
if (bank == 0 && pin < 12)
rk30_pmu_gpio_pud(pin, state);
switch (state) {
case GPIO_PIN_PULLUP:
pud = RK30_GPIO_PULLUP;
break;
case GPIO_PIN_PULLDOWN:
pud = RK30_GPIO_PULLDOWN;
break;
default:
pud = RK30_GPIO_NONE;
}
/*
* The pull up/down registers for GPIO0A and half of GPIO0B
* (the first 12 pins on bank 0) are at a different location.
*/
if (sc->sc_bank == 0 && pin < 12)
rk30_pmu_gpio_pud(pin, pud);
else
rk30_grf_gpio_pud(bank, pin, state);
rk30_grf_gpio_pud(sc->sc_bank, pin, pud);
}
static void
@ -183,22 +198,15 @@ rk30_gpio_pin_configure(struct rk30_gpio_softc *sc, struct gpio_pin *pin,
pin->gp_flags |= GPIO_PIN_INPUT;
rk30_gpio_set_function(sc, pin->gp_pin, pin->gp_flags);
}
/* Manage Pull-up/pull-down. */
pin->gp_flags &= ~(GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN);
if (flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) {
if (flags & GPIO_PIN_PULLUP) {
pin->gp_flags &= ~(GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
if (flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) {
if (flags & GPIO_PIN_PULLUP)
pin->gp_flags |= GPIO_PIN_PULLUP;
rk30_gpio_set_pud(sc, pin->gp_pin,
RK30_GPIO_PULLUP);
} else {
else
pin->gp_flags |= GPIO_PIN_PULLDOWN;
rk30_gpio_set_pud(sc, pin->gp_pin,
RK30_GPIO_PULLDOWN);
}
} else
rk30_gpio_set_pud(sc, pin->gp_pin, RK30_GPIO_NONE);
}
rk30_gpio_set_pud(sc, pin->gp_pin, pin->gp_flags);
RK30_GPIO_UNLOCK(sc);
}
@ -386,14 +394,12 @@ rk30_gpio_attach(device_t dev)
struct rk30_gpio_softc *sc = device_get_softc(dev);
int i, rid;
phandle_t gpio;
unsigned long start;
if (rk30_gpio_sc)
return (ENXIO);
sc->sc_dev = dev;
mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF);
rid = 0;
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
@ -401,9 +407,23 @@ rk30_gpio_attach(device_t dev)
device_printf(dev, "cannot allocate memory window\n");
return (ENXIO);
}
sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
/* Check the unit we are attaching by our base address. */
sc->sc_bank = -1;
start = rman_get_start(sc->sc_mem_res);
for (i = 0; i < nitems(rk30_gpio_base_addr); i++) {
if (rk30_gpio_base_addr[i] == start) {
sc->sc_bank = i;
break;
}
}
if (sc->sc_bank == -1) {
device_printf(dev,
"unsupported device unit (only GPIO0..3 are supported)\n");
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
return (ENXIO);
}
rid = 0;
sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
@ -421,6 +441,8 @@ rk30_gpio_attach(device_t dev)
/* Node is not a GPIO controller. */
goto fail;
mtx_init(&sc->sc_mtx, "rk30 gpio", "gpio", MTX_DEF);
/* Initialize the software controlled pins. */
for (i = 0; i < RK30_GPIO_PINS; i++) {
snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,