1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-02 12:20:51 +00:00

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.
This commit is contained in:
Adrian Chadd 2015-03-21 06:08:35 +00:00
parent 358811c4e3
commit 753370121e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=280315

View File

@ -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 dev, uint32_t pin, unsigned int value);
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 *maxpin)
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);