svn commit: r303577 - head/sys/mips/atheros
Adrian Chadd
adrian at FreeBSD.org
Sun Jul 31 06:51:35 UTC 2016
Author: adrian
Date: Sun Jul 31 06:51:34 2016
New Revision: 303577
URL: https://svnweb.freebsd.org/changeset/base/303577
Log:
[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.
Modified:
head/sys/mips/atheros/ar71xx_gpio.c
Modified: head/sys/mips/atheros/ar71xx_gpio.c
==============================================================================
--- head/sys/mips/atheros/ar71xx_gpio.c Sun Jul 31 06:34:49 2016 (r303576)
+++ head/sys/mips/atheros/ar71xx_gpio.c Sun Jul 31 06:51:34 2016 (r303577)
@@ -138,13 +138,56 @@ ar71xx_gpio_function_disable(struct ar71
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_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin,
- unsigned int flags)
+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 << pin->gp_pin;
+ 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)
+{
/*
* Manage input/output
@@ -153,11 +196,10 @@ ar71xx_gpio_pin_configure(struct ar71xx_
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);
}
More information about the svn-src-head
mailing list