From owner-svn-src-head@FreeBSD.ORG Sat Mar 21 06:08:36 2015 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id DA4BB3BD; Sat, 21 Mar 2015 06:08:36 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C4F20A0B; Sat, 21 Mar 2015 06:08:36 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t2L68ahS009549; Sat, 21 Mar 2015 06:08:36 GMT (envelope-from adrian@FreeBSD.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t2L68aQQ009548; Sat, 21 Mar 2015 06:08:36 GMT (envelope-from adrian@FreeBSD.org) Message-Id: <201503210608.t2L68aQQ009548@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: adrian set sender to adrian@FreeBSD.org using -f From: Adrian Chadd Date: Sat, 21 Mar 2015 06:08:36 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r280315 - head/sys/mips/atheros X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 21 Mar 2015 06:08:37 -0000 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 #include #include +#include #include #include #include @@ -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..gpiofunc= + * hint.gpio.X.func..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);