Date: Sat, 21 Mar 2015 06:08:36 +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: r280315 - head/sys/mips/atheros Message-ID: <201503210608.t2L68aQQ009548@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Sat Mar 21 06:08:35 2015 New Revision: 280315 URL: https://svnweb.freebsd.org/changeset/base/280315 Log: Add GPIO function mux configuration for AR934x SoCs. The AR934x (and maybe others in this family) have a more complicated GPIO mux. The AR71xx just has a single function register for a handful of "GPIO or X" options, however the AR934x allows for one of roughly 100 behaviours for each GPIO pin. So, this adds a quick hints based mechanism to configure the output functions, which is required for some of the more interesting board configurations. Specifically, some use external LNAs to improve RX, and without the MUX/output configured right, the 2GHz RX side will be plain terrible. It doesn't yet configure the "input" side yet; I'll add that if it's required. Tested: * TP-Link TL-WDR3600, testing 2GHz STA/AP modes, checking some basic RX sensitivity things (ie, "can I see the AP on the other side of the apartment that intentionally has poor signal reception from where I am right now.") Whilst here, fix a silly bug in the maxpin routine; I was missing a break. Modified: head/sys/mips/atheros/ar71xx_gpio.c Modified: head/sys/mips/atheros/ar71xx_gpio.c ============================================================================== --- head/sys/mips/atheros/ar71xx_gpio.c Sat Mar 21 06:00:46 2015 (r280314) +++ head/sys/mips/atheros/ar71xx_gpio.c Sat Mar 21 06:08:35 2015 (r280315) @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <machine/resource.h> #include <mips/atheros/ar71xxreg.h> #include <mips/atheros/ar71xx_setup.h> +#include <mips/atheros/ar71xx_cpudef.h> #include <mips/atheros/ar71xx_gpiovar.h> #include <dev/gpio/gpiobusvar.h> #include <mips/atheros/ar933xreg.h> @@ -92,6 +93,12 @@ static int ar71xx_gpio_pin_set(device_t static int ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val); static int ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin); +/* + * Enable/disable the GPIO function control space. + * + * This is primarily for the AR71xx, which has SPI CS1/CS2, UART, SLIC, I2S + * as GPIO pin options. + */ static void ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, uint32_t mask) { @@ -174,6 +181,7 @@ ar71xx_gpio_pin_max(device_t dev, int *m case AR71XX_SOC_AR9342: case AR71XX_SOC_AR9344: *maxpin = AR934X_GPIO_COUNT - 1; + break; case AR71XX_SOC_QCA9556: case AR71XX_SOC_QCA9558: *maxpin = QCA955X_GPIO_COUNT - 1; @@ -445,6 +453,7 @@ ar71xx_gpio_attach(device_t dev) sc->gpio_pins[i].gp_flags = GPIO_PIN_INPUT; i++; } + /* Turn on the hinted pins. */ for (i = 0; i < sc->gpio_npins; i++) { j = sc->gpio_pins[i].gp_pin; @@ -453,6 +462,56 @@ ar71xx_gpio_attach(device_t dev) ar71xx_gpio_pin_set(dev, j, 1); } } + + /* + * Search through the function hints, in case there's some + * overrides such as LNA control. + * + * hint.gpio.X.func.<pin>.gpiofunc=<func value> + * hint.gpio.X.func.<pin>.gpiomode=1 (for output, default low) + */ + for (i = 0; i <= maxpin; i++) { + char buf[32]; + int gpiofunc, gpiomode; + + snprintf(buf, 32, "func.%d.gpiofunc", i); + if (resource_int_value(device_get_name(dev), + device_get_unit(dev), + buf, + &gpiofunc) != 0) + continue; + /* Get the mode too */ + snprintf(buf, 32, "func.%d.gpiomode", i); + if (resource_int_value(device_get_name(dev), + device_get_unit(dev), + buf, + &gpiomode) != 0) + continue; + + /* We only handle mode=1 for now */ + if (gpiomode != 1) + continue; + + device_printf(dev, "%s: GPIO %d: func=%d, mode=%d\n", + __func__, + i, + 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); + + /* Finally: Set the output config */ + ar71xx_gpio_ouput_configure(i, gpiofunc); + } + sc->busdev = gpiobus_attach_bus(dev); if (sc->busdev == NULL) { ar71xx_gpio_detach(dev);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201503210608.t2L68aQQ009548>