ar71xx_gpio.c revision 278782
1213239Sgonzo/*- 2213239Sgonzo * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org> 3213239Sgonzo * Copyright (c) 2009, Luiz Otavio O Souza. 4213239Sgonzo * All rights reserved. 5213239Sgonzo * 6213239Sgonzo * Redistribution and use in source and binary forms, with or without 7213239Sgonzo * modification, are permitted provided that the following conditions 8213239Sgonzo * are met: 9213239Sgonzo * 1. Redistributions of source code must retain the above copyright 10213239Sgonzo * notice unmodified, this list of conditions, and the following 11213239Sgonzo * disclaimer. 12213239Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 13213239Sgonzo * notice, this list of conditions and the following disclaimer in the 14213239Sgonzo * documentation and/or other materials provided with the distribution. 15213239Sgonzo * 16213239Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17213239Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18213239Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19213239Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20213239Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21213239Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22213239Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23213239Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24213239Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25213239Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26213239Sgonzo * SUCH DAMAGE. 27213239Sgonzo */ 28213239Sgonzo 29213239Sgonzo/* 30213239Sgonzo * GPIO driver for AR71xx 31213239Sgonzo */ 32213239Sgonzo 33213239Sgonzo#include <sys/cdefs.h> 34213239Sgonzo__FBSDID("$FreeBSD: stable/10/sys/mips/atheros/ar71xx_gpio.c 278782 2015-02-14 20:37:33Z loos $"); 35213239Sgonzo 36213239Sgonzo#include <sys/param.h> 37213239Sgonzo#include <sys/systm.h> 38213239Sgonzo#include <sys/bus.h> 39213239Sgonzo 40213239Sgonzo#include <sys/kernel.h> 41213239Sgonzo#include <sys/module.h> 42213239Sgonzo#include <sys/rman.h> 43213239Sgonzo#include <sys/lock.h> 44255335Sloos#include <sys/malloc.h> 45213239Sgonzo#include <sys/mutex.h> 46213239Sgonzo#include <sys/gpio.h> 47213239Sgonzo 48213239Sgonzo#include <machine/bus.h> 49213239Sgonzo#include <machine/resource.h> 50213239Sgonzo#include <mips/atheros/ar71xxreg.h> 51221518Sadrian#include <mips/atheros/ar71xx_setup.h> 52213239Sgonzo#include <mips/atheros/ar71xx_gpiovar.h> 53250165Sadrian#include <mips/atheros/ar933xreg.h> 54253510Sadrian#include <mips/atheros/ar934xreg.h> 55213239Sgonzo 56213239Sgonzo#include "gpio_if.h" 57213239Sgonzo 58213239Sgonzo#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT) 59213239Sgonzo 60213239Sgonzo/* 61213239Sgonzo * Helpers 62213239Sgonzo */ 63213239Sgonzostatic void ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, 64213239Sgonzo uint32_t mask); 65213239Sgonzostatic void ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, 66213239Sgonzo uint32_t mask); 67213239Sgonzostatic void ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, 68213239Sgonzo struct gpio_pin *pin, uint32_t flags); 69213239Sgonzo 70213239Sgonzo/* 71213239Sgonzo * Driver stuff 72213239Sgonzo */ 73213239Sgonzostatic int ar71xx_gpio_probe(device_t dev); 74213239Sgonzostatic int ar71xx_gpio_attach(device_t dev); 75213239Sgonzostatic int ar71xx_gpio_detach(device_t dev); 76213239Sgonzostatic int ar71xx_gpio_filter(void *arg); 77213239Sgonzostatic void ar71xx_gpio_intr(void *arg); 78213239Sgonzo 79213239Sgonzo/* 80213239Sgonzo * GPIO interface 81213239Sgonzo */ 82213239Sgonzostatic int ar71xx_gpio_pin_max(device_t dev, int *maxpin); 83213239Sgonzostatic int ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps); 84213239Sgonzostatic int ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t 85213239Sgonzo *flags); 86213239Sgonzostatic int ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name); 87213239Sgonzostatic int ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags); 88213239Sgonzostatic int ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value); 89213239Sgonzostatic int ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val); 90213239Sgonzostatic int ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin); 91213239Sgonzo 92213239Sgonzostatic void 93213239Sgonzoar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, uint32_t mask) 94213239Sgonzo{ 95253510Sadrian if (ar71xx_soc == AR71XX_SOC_AR9341 || 96253510Sadrian ar71xx_soc == AR71XX_SOC_AR9342 || 97253510Sadrian ar71xx_soc == AR71XX_SOC_AR9344) 98253510Sadrian GPIO_SET_BITS(sc, AR934X_GPIO_REG_FUNC, mask); 99253510Sadrian else 100253510Sadrian GPIO_SET_BITS(sc, AR71XX_GPIO_FUNCTION, mask); 101213239Sgonzo} 102213239Sgonzo 103213239Sgonzostatic void 104213239Sgonzoar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, uint32_t mask) 105213239Sgonzo{ 106253510Sadrian if (ar71xx_soc == AR71XX_SOC_AR9341 || 107253510Sadrian ar71xx_soc == AR71XX_SOC_AR9342 || 108253510Sadrian ar71xx_soc == AR71XX_SOC_AR9344) 109253510Sadrian GPIO_CLEAR_BITS(sc, AR934X_GPIO_REG_FUNC, mask); 110253510Sadrian else 111253510Sadrian GPIO_CLEAR_BITS(sc, AR71XX_GPIO_FUNCTION, mask); 112213239Sgonzo} 113213239Sgonzo 114213239Sgonzostatic void 115213239Sgonzoar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin, 116213239Sgonzo unsigned int flags) 117213239Sgonzo{ 118213239Sgonzo uint32_t mask; 119213239Sgonzo 120213239Sgonzo mask = 1 << pin->gp_pin; 121213239Sgonzo 122213239Sgonzo /* 123213239Sgonzo * Manage input/output 124213239Sgonzo */ 125213239Sgonzo if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { 126213239Sgonzo pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); 127213239Sgonzo if (flags & GPIO_PIN_OUTPUT) { 128213239Sgonzo pin->gp_flags |= GPIO_PIN_OUTPUT; 129213239Sgonzo GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask); 130213239Sgonzo } 131213239Sgonzo else { 132213239Sgonzo pin->gp_flags |= GPIO_PIN_INPUT; 133213239Sgonzo GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask); 134213239Sgonzo } 135213239Sgonzo } 136213239Sgonzo} 137213239Sgonzo 138213239Sgonzostatic int 139213239Sgonzoar71xx_gpio_pin_max(device_t dev, int *maxpin) 140213239Sgonzo{ 141213239Sgonzo 142221518Sadrian switch (ar71xx_soc) { 143221518Sadrian case AR71XX_SOC_AR9130: 144221518Sadrian case AR71XX_SOC_AR9132: 145221518Sadrian *maxpin = AR91XX_GPIO_PINS - 1; 146221518Sadrian break; 147221518Sadrian case AR71XX_SOC_AR7240: 148221518Sadrian case AR71XX_SOC_AR7241: 149221518Sadrian case AR71XX_SOC_AR7242: 150221518Sadrian *maxpin = AR724X_GPIO_PINS - 1; 151221518Sadrian break; 152250165Sadrian case AR71XX_SOC_AR9330: 153250165Sadrian case AR71XX_SOC_AR9331: 154250165Sadrian *maxpin = AR933X_GPIO_COUNT - 1; 155250165Sadrian break; 156253510Sadrian case AR71XX_SOC_AR9341: 157253510Sadrian case AR71XX_SOC_AR9342: 158253510Sadrian case AR71XX_SOC_AR9344: 159253510Sadrian *maxpin = AR934X_GPIO_COUNT - 1; 160254234Sadrian break; 161221518Sadrian default: 162221518Sadrian *maxpin = AR71XX_GPIO_PINS - 1; 163221518Sadrian } 164213239Sgonzo return (0); 165213239Sgonzo} 166213239Sgonzo 167213239Sgonzostatic int 168213239Sgonzoar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 169213239Sgonzo{ 170213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 171213239Sgonzo int i; 172213239Sgonzo 173213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 174213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 175213239Sgonzo break; 176213239Sgonzo } 177213239Sgonzo 178213239Sgonzo if (i >= sc->gpio_npins) 179213239Sgonzo return (EINVAL); 180213239Sgonzo 181213239Sgonzo GPIO_LOCK(sc); 182213239Sgonzo *caps = sc->gpio_pins[i].gp_caps; 183213239Sgonzo GPIO_UNLOCK(sc); 184213239Sgonzo 185213239Sgonzo return (0); 186213239Sgonzo} 187213239Sgonzo 188213239Sgonzostatic int 189213239Sgonzoar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 190213239Sgonzo{ 191213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 192213239Sgonzo int i; 193213239Sgonzo 194213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 195213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 196213239Sgonzo break; 197213239Sgonzo } 198213239Sgonzo 199213239Sgonzo if (i >= sc->gpio_npins) 200213239Sgonzo return (EINVAL); 201213239Sgonzo 202213239Sgonzo GPIO_LOCK(sc); 203213239Sgonzo *flags = sc->gpio_pins[i].gp_flags; 204213239Sgonzo GPIO_UNLOCK(sc); 205213239Sgonzo 206213239Sgonzo return (0); 207213239Sgonzo} 208213239Sgonzo 209213239Sgonzostatic int 210213239Sgonzoar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 211213239Sgonzo{ 212213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 213213239Sgonzo int i; 214213239Sgonzo 215213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 216213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 217213239Sgonzo break; 218213239Sgonzo } 219213239Sgonzo 220213239Sgonzo if (i >= sc->gpio_npins) 221213239Sgonzo return (EINVAL); 222213239Sgonzo 223213239Sgonzo GPIO_LOCK(sc); 224213239Sgonzo memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME); 225213239Sgonzo GPIO_UNLOCK(sc); 226213239Sgonzo 227213239Sgonzo return (0); 228213239Sgonzo} 229213239Sgonzo 230213239Sgonzostatic int 231213239Sgonzoar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 232213239Sgonzo{ 233213239Sgonzo int i; 234213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 235213239Sgonzo 236213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 237213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 238213239Sgonzo break; 239213239Sgonzo } 240213239Sgonzo 241213239Sgonzo if (i >= sc->gpio_npins) 242213239Sgonzo return (EINVAL); 243213239Sgonzo 244249449Sdim /* Check for unwanted flags. */ 245249449Sdim if ((flags & sc->gpio_pins[i].gp_caps) != flags) 246213239Sgonzo return (EINVAL); 247213239Sgonzo 248213239Sgonzo /* Can't mix input/output together */ 249213239Sgonzo if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 250213239Sgonzo (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) 251213239Sgonzo return (EINVAL); 252213239Sgonzo 253213239Sgonzo ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], flags); 254213239Sgonzo return (0); 255213239Sgonzo} 256213239Sgonzo 257213239Sgonzostatic int 258213239Sgonzoar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 259213239Sgonzo{ 260213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 261213239Sgonzo int i; 262213239Sgonzo 263213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 264213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 265213239Sgonzo break; 266213239Sgonzo } 267213239Sgonzo 268213239Sgonzo if (i >= sc->gpio_npins) 269213239Sgonzo return (EINVAL); 270213239Sgonzo 271213239Sgonzo if (value) 272213239Sgonzo GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin)); 273213239Sgonzo else 274213239Sgonzo GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin)); 275213239Sgonzo 276213239Sgonzo return (0); 277213239Sgonzo} 278213239Sgonzo 279213239Sgonzostatic int 280213239Sgonzoar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 281213239Sgonzo{ 282213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 283213239Sgonzo int i; 284213239Sgonzo 285213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 286213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 287213239Sgonzo break; 288213239Sgonzo } 289213239Sgonzo 290213239Sgonzo if (i >= sc->gpio_npins) 291213239Sgonzo return (EINVAL); 292213239Sgonzo 293213239Sgonzo *val = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0; 294213239Sgonzo 295213239Sgonzo return (0); 296213239Sgonzo} 297213239Sgonzo 298213239Sgonzostatic int 299213239Sgonzoar71xx_gpio_pin_toggle(device_t dev, uint32_t pin) 300213239Sgonzo{ 301213239Sgonzo int res, i; 302213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 303213239Sgonzo 304213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 305213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 306213239Sgonzo break; 307213239Sgonzo } 308213239Sgonzo 309213239Sgonzo if (i >= sc->gpio_npins) 310213239Sgonzo return (EINVAL); 311213239Sgonzo 312213239Sgonzo res = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0; 313213239Sgonzo if (res) 314213239Sgonzo GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin)); 315213239Sgonzo else 316213239Sgonzo GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin)); 317213239Sgonzo 318213239Sgonzo return (0); 319213239Sgonzo} 320213239Sgonzo 321213239Sgonzostatic int 322213239Sgonzoar71xx_gpio_filter(void *arg) 323213239Sgonzo{ 324213239Sgonzo 325213239Sgonzo /* TODO: something useful */ 326213239Sgonzo return (FILTER_STRAY); 327213239Sgonzo} 328213239Sgonzo 329213239Sgonzo 330213239Sgonzo 331213239Sgonzostatic void 332213239Sgonzoar71xx_gpio_intr(void *arg) 333213239Sgonzo{ 334213239Sgonzo struct ar71xx_gpio_softc *sc = arg; 335213239Sgonzo GPIO_LOCK(sc); 336213239Sgonzo /* TODO: something useful */ 337213239Sgonzo GPIO_UNLOCK(sc); 338213239Sgonzo} 339213239Sgonzo 340213239Sgonzostatic int 341213239Sgonzoar71xx_gpio_probe(device_t dev) 342213239Sgonzo{ 343213239Sgonzo 344213239Sgonzo device_set_desc(dev, "Atheros AR71XX GPIO driver"); 345213239Sgonzo return (0); 346213239Sgonzo} 347213239Sgonzo 348213239Sgonzostatic int 349213239Sgonzoar71xx_gpio_attach(device_t dev) 350213239Sgonzo{ 351213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 352213239Sgonzo int error = 0; 353228518Sadrian int i, j, maxpin; 354234515Sadrian int mask, pinon; 355228518Sadrian int old = 0; 356213239Sgonzo 357213239Sgonzo KASSERT((device_get_unit(dev) == 0), 358213239Sgonzo ("ar71xx_gpio: Only one gpio module supported")); 359213239Sgonzo 360239351Srpaulo mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 361213239Sgonzo 362213239Sgonzo /* Map control/status registers. */ 363213239Sgonzo sc->gpio_mem_rid = 0; 364213239Sgonzo sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 365213239Sgonzo &sc->gpio_mem_rid, RF_ACTIVE); 366213239Sgonzo 367213239Sgonzo if (sc->gpio_mem_res == NULL) { 368213239Sgonzo device_printf(dev, "couldn't map memory\n"); 369213239Sgonzo error = ENXIO; 370213239Sgonzo ar71xx_gpio_detach(dev); 371213239Sgonzo return(error); 372213239Sgonzo } 373213239Sgonzo 374213239Sgonzo if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 375213239Sgonzo &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 376213239Sgonzo device_printf(dev, "unable to allocate IRQ resource\n"); 377213239Sgonzo return (ENXIO); 378213239Sgonzo } 379213239Sgonzo 380213239Sgonzo if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, 381213239Sgonzo ar71xx_gpio_filter, ar71xx_gpio_intr, sc, &sc->gpio_ih))) { 382213239Sgonzo device_printf(dev, 383213239Sgonzo "WARNING: unable to register interrupt handler\n"); 384213239Sgonzo return (ENXIO); 385213239Sgonzo } 386213239Sgonzo 387213239Sgonzo sc->dev = dev; 388228518Sadrian 389228518Sadrian /* Enable function bits that are required */ 390228518Sadrian if (resource_int_value(device_get_name(dev), device_get_unit(dev), 391228518Sadrian "function_set", &mask) == 0) { 392228518Sadrian device_printf(dev, "function_set: 0x%x\n", mask); 393228518Sadrian ar71xx_gpio_function_enable(sc, mask); 394228518Sadrian old = 1; 395228518Sadrian } 396228518Sadrian /* Disable function bits that are required */ 397228518Sadrian if (resource_int_value(device_get_name(dev), device_get_unit(dev), 398228518Sadrian "function_clear", &mask) == 0) { 399228518Sadrian device_printf(dev, "function_clear: 0x%x\n", mask); 400228518Sadrian ar71xx_gpio_function_disable(sc, mask); 401228518Sadrian old = 1; 402228518Sadrian } 403228518Sadrian /* Handle previous behaviour */ 404228518Sadrian if (old == 0) { 405228518Sadrian ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS1_EN); 406228518Sadrian ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS2_EN); 407228518Sadrian } 408228518Sadrian 409213239Sgonzo /* Configure all pins as input */ 410213239Sgonzo /* disable interrupts for all pins */ 411213239Sgonzo GPIO_WRITE(sc, AR71XX_GPIO_INT_MASK, 0); 412228518Sadrian 413228518Sadrian /* Initialise all pins specified in the mask, up to the pin count */ 414228518Sadrian (void) ar71xx_gpio_pin_max(dev, &maxpin); 415228518Sadrian if (resource_int_value(device_get_name(dev), device_get_unit(dev), 416228518Sadrian "pinmask", &mask) != 0) 417228518Sadrian mask = 0; 418234515Sadrian if (resource_int_value(device_get_name(dev), device_get_unit(dev), 419234515Sadrian "pinon", &pinon) != 0) 420234515Sadrian pinon = 0; 421228518Sadrian device_printf(dev, "gpio pinmask=0x%x\n", mask); 422255335Sloos for (j = 0; j <= maxpin; j++) { 423255335Sloos if ((mask & (1 << j)) == 0) 424255335Sloos continue; 425255335Sloos sc->gpio_npins++; 426255335Sloos } 427255335Sloos sc->gpio_pins = malloc(sizeof(*sc->gpio_pins) * sc->gpio_npins, 428255335Sloos M_DEVBUF, M_WAITOK | M_ZERO); 429255334Sloos for (i = 0, j = 0; j <= maxpin; j++) { 430228518Sadrian if ((mask & (1 << j)) == 0) 431228518Sadrian continue; 432228518Sadrian snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, 433228518Sadrian "pin %d", j); 434228518Sadrian sc->gpio_pins[i].gp_pin = j; 435213239Sgonzo sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; 436213239Sgonzo sc->gpio_pins[i].gp_flags = 0; 437228518Sadrian ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], DEFAULT_CAPS); 438213239Sgonzo i++; 439213239Sgonzo } 440234515Sadrian for (i = 0; i < sc->gpio_npins; i++) { 441234515Sadrian j = sc->gpio_pins[i].gp_pin; 442234515Sadrian if ((pinon & (1 << j)) != 0) 443234515Sadrian ar71xx_gpio_pin_set(dev, j, 1); 444234515Sadrian } 445278782Sloos device_add_child(dev, "gpioc", -1); 446278782Sloos device_add_child(dev, "gpiobus", -1); 447278782Sloos 448213239Sgonzo return (bus_generic_attach(dev)); 449213239Sgonzo} 450213239Sgonzo 451213239Sgonzostatic int 452213239Sgonzoar71xx_gpio_detach(device_t dev) 453213239Sgonzo{ 454213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 455213239Sgonzo 456213239Sgonzo KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); 457213239Sgonzo 458213286Sgonzo ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS1_EN); 459213286Sgonzo ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS2_EN); 460213239Sgonzo bus_generic_detach(dev); 461213239Sgonzo 462213239Sgonzo if (sc->gpio_mem_res) 463213239Sgonzo bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid, 464213239Sgonzo sc->gpio_mem_res); 465213239Sgonzo 466255335Sloos free(sc->gpio_pins, M_DEVBUF); 467213239Sgonzo mtx_destroy(&sc->gpio_mtx); 468213239Sgonzo 469213239Sgonzo return(0); 470213239Sgonzo} 471213239Sgonzo 472213239Sgonzostatic device_method_t ar71xx_gpio_methods[] = { 473213239Sgonzo DEVMETHOD(device_probe, ar71xx_gpio_probe), 474213239Sgonzo DEVMETHOD(device_attach, ar71xx_gpio_attach), 475213239Sgonzo DEVMETHOD(device_detach, ar71xx_gpio_detach), 476213239Sgonzo 477213239Sgonzo /* GPIO protocol */ 478213239Sgonzo DEVMETHOD(gpio_pin_max, ar71xx_gpio_pin_max), 479213239Sgonzo DEVMETHOD(gpio_pin_getname, ar71xx_gpio_pin_getname), 480213239Sgonzo DEVMETHOD(gpio_pin_getflags, ar71xx_gpio_pin_getflags), 481213239Sgonzo DEVMETHOD(gpio_pin_getcaps, ar71xx_gpio_pin_getcaps), 482213239Sgonzo DEVMETHOD(gpio_pin_setflags, ar71xx_gpio_pin_setflags), 483213239Sgonzo DEVMETHOD(gpio_pin_get, ar71xx_gpio_pin_get), 484213239Sgonzo DEVMETHOD(gpio_pin_set, ar71xx_gpio_pin_set), 485213239Sgonzo DEVMETHOD(gpio_pin_toggle, ar71xx_gpio_pin_toggle), 486213239Sgonzo {0, 0}, 487213239Sgonzo}; 488213239Sgonzo 489213239Sgonzostatic driver_t ar71xx_gpio_driver = { 490213239Sgonzo "gpio", 491213239Sgonzo ar71xx_gpio_methods, 492213239Sgonzo sizeof(struct ar71xx_gpio_softc), 493213239Sgonzo}; 494213239Sgonzostatic devclass_t ar71xx_gpio_devclass; 495213239Sgonzo 496213239SgonzoDRIVER_MODULE(ar71xx_gpio, apb, ar71xx_gpio_driver, ar71xx_gpio_devclass, 0, 0); 497