[ar71xx_gpio] handle AR934x and QCA953x GPIO OE polarity.
For reasons I won't comment on, the AR934x and QCA953x GPIO_OE register value is inverted - bit set == input, bit clear == output. So, fix this in the output setting, in reading the initial state from the boot loader, and also setting any gpiofunc pins that are necessary.
This commit is contained in:
parent
4fcae4df7e
commit
accdd12e71
@ -138,13 +138,56 @@ ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, uint32_t mask)
|
||||
GPIO_CLEAR_BITS(sc, AR71XX_GPIO_FUNCTION, mask);
|
||||
}
|
||||
|
||||
/*
|
||||
* On most platforms, GPIO_OE is a bitmap where the bit set
|
||||
* means "enable output."
|
||||
*
|
||||
* On AR934x and QCA953x, it's the opposite - the bit set means
|
||||
* "input enable".
|
||||
*/
|
||||
static int
|
||||
ar71xx_gpio_oe_is_high(void)
|
||||
{
|
||||
switch (ar71xx_soc) {
|
||||
case AR71XX_SOC_AR9344:
|
||||
case AR71XX_SOC_QCA9533:
|
||||
case AR71XX_SOC_QCA9533_V2:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ar71xx_gpio_oe_set_output(struct ar71xx_gpio_softc *sc, int b)
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
mask = 1 << b;
|
||||
|
||||
if (ar71xx_gpio_oe_is_high())
|
||||
GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask);
|
||||
else
|
||||
GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask);
|
||||
}
|
||||
|
||||
static void
|
||||
ar71xx_gpio_oe_set_input(struct ar71xx_gpio_softc *sc, int b)
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
mask = 1 << b;
|
||||
|
||||
if (ar71xx_gpio_oe_is_high())
|
||||
GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask);
|
||||
else
|
||||
GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask);
|
||||
}
|
||||
|
||||
static void
|
||||
ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin,
|
||||
unsigned int flags)
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
mask = 1 << pin->gp_pin;
|
||||
|
||||
/*
|
||||
* Manage input/output
|
||||
@ -153,11 +196,10 @@ ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin,
|
||||
pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
|
||||
if (flags & GPIO_PIN_OUTPUT) {
|
||||
pin->gp_flags |= GPIO_PIN_OUTPUT;
|
||||
GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask);
|
||||
}
|
||||
else {
|
||||
ar71xx_gpio_oe_set_output(sc, pin->gp_pin);
|
||||
} else {
|
||||
pin->gp_flags |= GPIO_PIN_INPUT;
|
||||
GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask);
|
||||
ar71xx_gpio_oe_set_input(sc, pin->gp_pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -455,6 +497,14 @@ ar71xx_gpio_attach(device_t dev)
|
||||
}
|
||||
/* Iniatilize the GPIO pins, keep the loader settings. */
|
||||
oe = GPIO_READ(sc, AR71XX_GPIO_OE);
|
||||
/*
|
||||
* For AR934x and QCA953x, the meaning of oe is inverted;
|
||||
* so flip it the right way around so we can parse the GPIO
|
||||
* state.
|
||||
*/
|
||||
if (!ar71xx_gpio_oe_is_high())
|
||||
oe = ~oe;
|
||||
|
||||
sc->gpio_pins = malloc(sizeof(*sc->gpio_pins) * sc->gpio_npins,
|
||||
M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
for (i = 0, j = 0; j <= maxpin; j++) {
|
||||
@ -515,16 +565,14 @@ ar71xx_gpio_attach(device_t dev)
|
||||
gpiofunc,
|
||||
gpiomode);
|
||||
|
||||
/* Set output (bit == 0) */
|
||||
oe = GPIO_READ(sc, AR71XX_GPIO_OE);
|
||||
oe &= ~ (1 << i);
|
||||
GPIO_WRITE(sc, AR71XX_GPIO_OE, oe);
|
||||
|
||||
/* Set pin value = 0, so it stays low by default */
|
||||
oe = GPIO_READ(sc, AR71XX_GPIO_OUT);
|
||||
oe &= ~ (1 << i);
|
||||
GPIO_WRITE(sc, AR71XX_GPIO_OUT, oe);
|
||||
|
||||
/* Set output */
|
||||
ar71xx_gpio_oe_set_output(sc, i);
|
||||
|
||||
/* Finally: Set the output config */
|
||||
ar71xx_gpio_ouput_configure(i, gpiofunc);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user