diff options
author | adrian <adrian@FreeBSD.org> | 2011-12-15 01:03:49 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2011-12-15 01:03:49 +0000 |
commit | 1af383c5f6fceadf05a48b89f197d7031db17f5f (patch) | |
tree | 86022f3889ca5adb09c22c09555019a17c415244 /sys/mips | |
parent | 7c11417460b479740a44ec589a200214c10af10b (diff) | |
download | FreeBSD-src-1af383c5f6fceadf05a48b89f197d7031db17f5f.zip FreeBSD-src-1af383c5f6fceadf05a48b89f197d7031db17f5f.tar.gz |
Re-jiggle the GPIO code a little to remove the hard-coded AR71xx GPIO
config and function mask setup.
* "gpiomask" now specifies which GPIO pins to enable, for devices to bind to.
* "function_set" allows bits in the function register to be set at GPIO setup.
* "function_clear" allows bits in the function register to be cleared at
GPIO setup.
The function_set/function_clear bits allow for individual GPIO pins to either
drive a GPIO line or an alternate function - eg USB, JTAG, etc. This allows
for things like CS1/CS2 be enabled for those boards w/ >1 SPI device connected,
or disabling JTAG for the AR7240 (which is apparently needed ..)
I've verified this on the AR71xx.
Diffstat (limited to 'sys/mips')
-rw-r--r-- | sys/mips/atheros/ar71xx_gpio.c | 63 |
1 files changed, 38 insertions, 25 deletions
diff --git a/sys/mips/atheros/ar71xx_gpio.c b/sys/mips/atheros/ar71xx_gpio.c index 09b4d50..11906ff 100644 --- a/sys/mips/atheros/ar71xx_gpio.c +++ b/sys/mips/atheros/ar71xx_gpio.c @@ -54,18 +54,6 @@ __FBSDID("$FreeBSD$"); #define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT) -struct ar71xx_gpio_pin { - const char *name; - int pin; - int flags; -}; - -static struct ar71xx_gpio_pin ar71xx_gpio_pins[] = { - { "RFled", 2, GPIO_PIN_OUTPUT}, - { "SW4", 8, GPIO_PIN_INPUT}, - { NULL, 0, 0}, -}; - /* * Helpers */ @@ -353,8 +341,9 @@ ar71xx_gpio_attach(device_t dev) { struct ar71xx_gpio_softc *sc = device_get_softc(dev); int error = 0; - struct ar71xx_gpio_pin *pinp; - int i; + int i, j, maxpin; + int mask; + int old = 0; KASSERT((device_get_unit(dev) == 0), ("ar71xx_gpio: Only one gpio module supported")); @@ -388,25 +377,49 @@ ar71xx_gpio_attach(device_t dev) } sc->dev = dev; - ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS1_EN); - ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS2_EN); + + /* Enable function bits that are required */ + if (resource_int_value(device_get_name(dev), device_get_unit(dev), + "function_set", &mask) == 0) { + device_printf(dev, "function_set: 0x%x\n", mask); + ar71xx_gpio_function_enable(sc, mask); + old = 1; + } + /* Disable function bits that are required */ + if (resource_int_value(device_get_name(dev), device_get_unit(dev), + "function_clear", &mask) == 0) { + device_printf(dev, "function_clear: 0x%x\n", mask); + ar71xx_gpio_function_disable(sc, mask); + old = 1; + } + /* Handle previous behaviour */ + if (old == 0) { + ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS1_EN); + ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS2_EN); + } + /* Configure all pins as input */ /* disable interrupts for all pins */ GPIO_WRITE(sc, AR71XX_GPIO_INT_MASK, 0); - pinp = ar71xx_gpio_pins; - i = 0; - while (pinp->name) { - strncpy(sc->gpio_pins[i].gp_name, pinp->name, GPIOMAXNAME); - sc->gpio_pins[i].gp_pin = pinp->pin; + + /* Initialise all pins specified in the mask, up to the pin count */ + (void) ar71xx_gpio_pin_max(dev, &maxpin); + if (resource_int_value(device_get_name(dev), device_get_unit(dev), + "pinmask", &mask) != 0) + mask = 0; + device_printf(dev, "gpio pinmask=0x%x\n", mask); + for (i = 0, j = 0; j < maxpin; j++) { + if ((mask & (1 << j)) == 0) + continue; + snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, + "pin %d", j); + sc->gpio_pins[i].gp_pin = j; sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; sc->gpio_pins[i].gp_flags = 0; - ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], pinp->flags); - pinp++; + ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], DEFAULT_CAPS); i++; } - sc->gpio_npins = i; - device_add_child(dev, "gpioc", device_get_unit(dev)); device_add_child(dev, "gpiobus", device_get_unit(dev)); return (bus_generic_attach(dev)); |