Date: Sun, 31 Jul 2016 06:51:34 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r303577 - head/sys/mips/atheros Message-ID: <201607310651.u6V6pYx2025165@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201607310651.u6V6pYx2025165>