svn commit: r280315 - head/sys/mips/atheros

Adrian Chadd adrian at FreeBSD.org
Sat Mar 21 06:08:37 UTC 2015


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);


More information about the svn-src-head mailing list