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$"); 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> 44213239Sgonzo#include <sys/mutex.h> 45213239Sgonzo#include <sys/gpio.h> 46213239Sgonzo 47213239Sgonzo#include <machine/bus.h> 48213239Sgonzo#include <machine/resource.h> 49213239Sgonzo#include <mips/atheros/ar71xxreg.h> 50221518Sadrian#include <mips/atheros/ar71xx_setup.h> 51213239Sgonzo#include <mips/atheros/ar71xx_gpiovar.h> 52213239Sgonzo 53213239Sgonzo#include "gpio_if.h" 54213239Sgonzo 55213239Sgonzo#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT) 56213239Sgonzo 57213239Sgonzostruct ar71xx_gpio_pin { 58213239Sgonzo const char *name; 59213239Sgonzo int pin; 60213239Sgonzo int flags; 61213239Sgonzo}; 62213239Sgonzo 63213239Sgonzostatic struct ar71xx_gpio_pin ar71xx_gpio_pins[] = { 64213239Sgonzo { "RFled", 2, GPIO_PIN_OUTPUT}, 65213239Sgonzo { "SW4", 8, GPIO_PIN_INPUT}, 66213239Sgonzo { NULL, 0, 0}, 67213239Sgonzo}; 68213239Sgonzo 69213239Sgonzo/* 70213239Sgonzo * Helpers 71213239Sgonzo */ 72213239Sgonzostatic void ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, 73213239Sgonzo uint32_t mask); 74213239Sgonzostatic void ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, 75213239Sgonzo uint32_t mask); 76213239Sgonzostatic void ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, 77213239Sgonzo struct gpio_pin *pin, uint32_t flags); 78213239Sgonzo 79213239Sgonzo/* 80213239Sgonzo * Driver stuff 81213239Sgonzo */ 82213239Sgonzostatic int ar71xx_gpio_probe(device_t dev); 83213239Sgonzostatic int ar71xx_gpio_attach(device_t dev); 84213239Sgonzostatic int ar71xx_gpio_detach(device_t dev); 85213239Sgonzostatic int ar71xx_gpio_filter(void *arg); 86213239Sgonzostatic void ar71xx_gpio_intr(void *arg); 87213239Sgonzo 88213239Sgonzo/* 89213239Sgonzo * GPIO interface 90213239Sgonzo */ 91213239Sgonzostatic int ar71xx_gpio_pin_max(device_t dev, int *maxpin); 92213239Sgonzostatic int ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps); 93213239Sgonzostatic int ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t 94213239Sgonzo *flags); 95213239Sgonzostatic int ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name); 96213239Sgonzostatic int ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags); 97213239Sgonzostatic int ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value); 98213239Sgonzostatic int ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val); 99213239Sgonzostatic int ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin); 100213239Sgonzo 101213239Sgonzostatic void 102213239Sgonzoar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, uint32_t mask) 103213239Sgonzo{ 104213239Sgonzo GPIO_LOCK(sc); 105213239Sgonzo GPIO_SET_BITS(sc, AR71XX_GPIO_FUNCTION, mask); 106213239Sgonzo GPIO_UNLOCK(sc); 107213239Sgonzo} 108213239Sgonzo 109213239Sgonzostatic void 110213239Sgonzoar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, uint32_t mask) 111213239Sgonzo{ 112213239Sgonzo GPIO_LOCK(sc); 113213239Sgonzo GPIO_CLEAR_BITS(sc, AR71XX_GPIO_FUNCTION, mask); 114213239Sgonzo GPIO_UNLOCK(sc); 115213239Sgonzo} 116213239Sgonzo 117213239Sgonzostatic void 118213239Sgonzoar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin, 119213239Sgonzo unsigned int flags) 120213239Sgonzo{ 121213239Sgonzo uint32_t mask; 122213239Sgonzo 123213239Sgonzo mask = 1 << pin->gp_pin; 124213239Sgonzo GPIO_LOCK(sc); 125213239Sgonzo 126213239Sgonzo /* 127213239Sgonzo * Manage input/output 128213239Sgonzo */ 129213239Sgonzo if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { 130213239Sgonzo pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); 131213239Sgonzo if (flags & GPIO_PIN_OUTPUT) { 132213239Sgonzo pin->gp_flags |= GPIO_PIN_OUTPUT; 133213239Sgonzo GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask); 134213239Sgonzo } 135213239Sgonzo else { 136213239Sgonzo pin->gp_flags |= GPIO_PIN_INPUT; 137213239Sgonzo GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask); 138213239Sgonzo } 139213239Sgonzo } 140213239Sgonzo 141213239Sgonzo GPIO_UNLOCK(sc); 142213239Sgonzo} 143213239Sgonzo 144213239Sgonzostatic int 145213239Sgonzoar71xx_gpio_pin_max(device_t dev, int *maxpin) 146213239Sgonzo{ 147213239Sgonzo 148221518Sadrian switch (ar71xx_soc) { 149221518Sadrian case AR71XX_SOC_AR9130: 150221518Sadrian case AR71XX_SOC_AR9132: 151221518Sadrian *maxpin = AR91XX_GPIO_PINS - 1; 152221518Sadrian break; 153221518Sadrian case AR71XX_SOC_AR7240: 154221518Sadrian case AR71XX_SOC_AR7241: 155221518Sadrian case AR71XX_SOC_AR7242: 156221518Sadrian *maxpin = AR724X_GPIO_PINS - 1; 157221518Sadrian break; 158221518Sadrian default: 159221518Sadrian *maxpin = AR71XX_GPIO_PINS - 1; 160221518Sadrian } 161213239Sgonzo return (0); 162213239Sgonzo} 163213239Sgonzo 164213239Sgonzostatic int 165213239Sgonzoar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 166213239Sgonzo{ 167213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 168213239Sgonzo int i; 169213239Sgonzo 170213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 171213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 172213239Sgonzo break; 173213239Sgonzo } 174213239Sgonzo 175213239Sgonzo if (i >= sc->gpio_npins) 176213239Sgonzo return (EINVAL); 177213239Sgonzo 178213239Sgonzo GPIO_LOCK(sc); 179213239Sgonzo *caps = sc->gpio_pins[i].gp_caps; 180213239Sgonzo GPIO_UNLOCK(sc); 181213239Sgonzo 182213239Sgonzo return (0); 183213239Sgonzo} 184213239Sgonzo 185213239Sgonzostatic int 186213239Sgonzoar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 187213239Sgonzo{ 188213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 189213239Sgonzo int i; 190213239Sgonzo 191213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 192213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 193213239Sgonzo break; 194213239Sgonzo } 195213239Sgonzo 196213239Sgonzo if (i >= sc->gpio_npins) 197213239Sgonzo return (EINVAL); 198213239Sgonzo 199213239Sgonzo GPIO_LOCK(sc); 200213239Sgonzo *flags = sc->gpio_pins[i].gp_flags; 201213239Sgonzo GPIO_UNLOCK(sc); 202213239Sgonzo 203213239Sgonzo return (0); 204213239Sgonzo} 205213239Sgonzo 206213239Sgonzostatic int 207213239Sgonzoar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 208213239Sgonzo{ 209213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 210213239Sgonzo int i; 211213239Sgonzo 212213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 213213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 214213239Sgonzo break; 215213239Sgonzo } 216213239Sgonzo 217213239Sgonzo if (i >= sc->gpio_npins) 218213239Sgonzo return (EINVAL); 219213239Sgonzo 220213239Sgonzo GPIO_LOCK(sc); 221213239Sgonzo memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME); 222213239Sgonzo GPIO_UNLOCK(sc); 223213239Sgonzo 224213239Sgonzo return (0); 225213239Sgonzo} 226213239Sgonzo 227213239Sgonzostatic int 228213239Sgonzoar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 229213239Sgonzo{ 230213239Sgonzo int i; 231213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 232213239Sgonzo 233213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 234213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 235213239Sgonzo break; 236213239Sgonzo } 237213239Sgonzo 238213239Sgonzo if (i >= sc->gpio_npins) 239213239Sgonzo return (EINVAL); 240213239Sgonzo 241249550Sdim /* Check for unwanted flags. */ 242249550Sdim if ((flags & sc->gpio_pins[i].gp_caps) != flags) 243213239Sgonzo return (EINVAL); 244213239Sgonzo 245213239Sgonzo /* Can't mix input/output together */ 246213239Sgonzo if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 247213239Sgonzo (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) 248213239Sgonzo return (EINVAL); 249213239Sgonzo 250213239Sgonzo ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], flags); 251213239Sgonzo return (0); 252213239Sgonzo} 253213239Sgonzo 254213239Sgonzostatic int 255213239Sgonzoar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 256213239Sgonzo{ 257213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 258213239Sgonzo int i; 259213239Sgonzo 260213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 261213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 262213239Sgonzo break; 263213239Sgonzo } 264213239Sgonzo 265213239Sgonzo if (i >= sc->gpio_npins) 266213239Sgonzo return (EINVAL); 267213239Sgonzo 268213239Sgonzo GPIO_LOCK(sc); 269213239Sgonzo if (value) 270213239Sgonzo GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin)); 271213239Sgonzo else 272213239Sgonzo GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin)); 273213239Sgonzo GPIO_UNLOCK(sc); 274213239Sgonzo 275213239Sgonzo return (0); 276213239Sgonzo} 277213239Sgonzo 278213239Sgonzostatic int 279213239Sgonzoar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 280213239Sgonzo{ 281213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 282213239Sgonzo int i; 283213239Sgonzo 284213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 285213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 286213239Sgonzo break; 287213239Sgonzo } 288213239Sgonzo 289213239Sgonzo if (i >= sc->gpio_npins) 290213239Sgonzo return (EINVAL); 291213239Sgonzo 292213239Sgonzo GPIO_LOCK(sc); 293213239Sgonzo *val = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0; 294213239Sgonzo GPIO_UNLOCK(sc); 295213239Sgonzo 296213239Sgonzo return (0); 297213239Sgonzo} 298213239Sgonzo 299213239Sgonzostatic int 300213239Sgonzoar71xx_gpio_pin_toggle(device_t dev, uint32_t pin) 301213239Sgonzo{ 302213239Sgonzo int res, i; 303213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 304213239Sgonzo 305213239Sgonzo for (i = 0; i < sc->gpio_npins; i++) { 306213239Sgonzo if (sc->gpio_pins[i].gp_pin == pin) 307213239Sgonzo break; 308213239Sgonzo } 309213239Sgonzo 310213239Sgonzo if (i >= sc->gpio_npins) 311213239Sgonzo return (EINVAL); 312213239Sgonzo 313213239Sgonzo GPIO_LOCK(sc); 314213239Sgonzo res = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0; 315213239Sgonzo if (res) 316213239Sgonzo GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin)); 317213239Sgonzo else 318213239Sgonzo GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin)); 319213239Sgonzo GPIO_UNLOCK(sc); 320213239Sgonzo 321213239Sgonzo return (0); 322213239Sgonzo} 323213239Sgonzo 324213239Sgonzostatic int 325213239Sgonzoar71xx_gpio_filter(void *arg) 326213239Sgonzo{ 327213239Sgonzo 328213239Sgonzo /* TODO: something useful */ 329213239Sgonzo return (FILTER_STRAY); 330213239Sgonzo} 331213239Sgonzo 332213239Sgonzo 333213239Sgonzo 334213239Sgonzostatic void 335213239Sgonzoar71xx_gpio_intr(void *arg) 336213239Sgonzo{ 337213239Sgonzo struct ar71xx_gpio_softc *sc = arg; 338213239Sgonzo GPIO_LOCK(sc); 339213239Sgonzo /* TODO: something useful */ 340213239Sgonzo GPIO_UNLOCK(sc); 341213239Sgonzo} 342213239Sgonzo 343213239Sgonzostatic int 344213239Sgonzoar71xx_gpio_probe(device_t dev) 345213239Sgonzo{ 346213239Sgonzo 347213239Sgonzo device_set_desc(dev, "Atheros AR71XX GPIO driver"); 348213239Sgonzo return (0); 349213239Sgonzo} 350213239Sgonzo 351213239Sgonzostatic int 352213239Sgonzoar71xx_gpio_attach(device_t dev) 353213239Sgonzo{ 354213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 355213239Sgonzo int error = 0; 356213239Sgonzo struct ar71xx_gpio_pin *pinp; 357213239Sgonzo int i; 358213239Sgonzo 359213239Sgonzo KASSERT((device_get_unit(dev) == 0), 360213239Sgonzo ("ar71xx_gpio: Only one gpio module supported")); 361213239Sgonzo 362213239Sgonzo mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 363213239Sgonzo MTX_DEF); 364213239Sgonzo 365213239Sgonzo /* Map control/status registers. */ 366213239Sgonzo sc->gpio_mem_rid = 0; 367213239Sgonzo sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 368213239Sgonzo &sc->gpio_mem_rid, RF_ACTIVE); 369213239Sgonzo 370213239Sgonzo if (sc->gpio_mem_res == NULL) { 371213239Sgonzo device_printf(dev, "couldn't map memory\n"); 372213239Sgonzo error = ENXIO; 373213239Sgonzo ar71xx_gpio_detach(dev); 374213239Sgonzo return(error); 375213239Sgonzo } 376213239Sgonzo 377213239Sgonzo if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 378213239Sgonzo &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 379213239Sgonzo device_printf(dev, "unable to allocate IRQ resource\n"); 380213239Sgonzo return (ENXIO); 381213239Sgonzo } 382213239Sgonzo 383213239Sgonzo if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, 384213239Sgonzo ar71xx_gpio_filter, ar71xx_gpio_intr, sc, &sc->gpio_ih))) { 385213239Sgonzo device_printf(dev, 386213239Sgonzo "WARNING: unable to register interrupt handler\n"); 387213239Sgonzo return (ENXIO); 388213239Sgonzo } 389213239Sgonzo 390213239Sgonzo sc->dev = dev; 391213286Sgonzo ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS1_EN); 392213286Sgonzo ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS2_EN); 393213239Sgonzo /* Configure all pins as input */ 394213239Sgonzo /* disable interrupts for all pins */ 395213239Sgonzo GPIO_WRITE(sc, AR71XX_GPIO_INT_MASK, 0); 396213239Sgonzo pinp = ar71xx_gpio_pins; 397213239Sgonzo i = 0; 398213239Sgonzo while (pinp->name) { 399213239Sgonzo strncpy(sc->gpio_pins[i].gp_name, pinp->name, GPIOMAXNAME); 400213239Sgonzo sc->gpio_pins[i].gp_pin = pinp->pin; 401213239Sgonzo sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; 402213239Sgonzo sc->gpio_pins[i].gp_flags = 0; 403213239Sgonzo ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], pinp->flags); 404213239Sgonzo pinp++; 405213239Sgonzo i++; 406213239Sgonzo } 407213239Sgonzo 408213239Sgonzo sc->gpio_npins = i; 409213239Sgonzo 410213239Sgonzo device_add_child(dev, "gpioc", device_get_unit(dev)); 411213239Sgonzo device_add_child(dev, "gpiobus", device_get_unit(dev)); 412213239Sgonzo return (bus_generic_attach(dev)); 413213239Sgonzo} 414213239Sgonzo 415213239Sgonzostatic int 416213239Sgonzoar71xx_gpio_detach(device_t dev) 417213239Sgonzo{ 418213239Sgonzo struct ar71xx_gpio_softc *sc = device_get_softc(dev); 419213239Sgonzo 420213239Sgonzo KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); 421213239Sgonzo 422213286Sgonzo ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS1_EN); 423213286Sgonzo ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS2_EN); 424213239Sgonzo bus_generic_detach(dev); 425213239Sgonzo 426213239Sgonzo if (sc->gpio_mem_res) 427213239Sgonzo bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid, 428213239Sgonzo sc->gpio_mem_res); 429213239Sgonzo 430213239Sgonzo mtx_destroy(&sc->gpio_mtx); 431213239Sgonzo 432213239Sgonzo return(0); 433213239Sgonzo} 434213239Sgonzo 435213239Sgonzostatic device_method_t ar71xx_gpio_methods[] = { 436213239Sgonzo DEVMETHOD(device_probe, ar71xx_gpio_probe), 437213239Sgonzo DEVMETHOD(device_attach, ar71xx_gpio_attach), 438213239Sgonzo DEVMETHOD(device_detach, ar71xx_gpio_detach), 439213239Sgonzo 440213239Sgonzo /* GPIO protocol */ 441213239Sgonzo DEVMETHOD(gpio_pin_max, ar71xx_gpio_pin_max), 442213239Sgonzo DEVMETHOD(gpio_pin_getname, ar71xx_gpio_pin_getname), 443213239Sgonzo DEVMETHOD(gpio_pin_getflags, ar71xx_gpio_pin_getflags), 444213239Sgonzo DEVMETHOD(gpio_pin_getcaps, ar71xx_gpio_pin_getcaps), 445213239Sgonzo DEVMETHOD(gpio_pin_setflags, ar71xx_gpio_pin_setflags), 446213239Sgonzo DEVMETHOD(gpio_pin_get, ar71xx_gpio_pin_get), 447213239Sgonzo DEVMETHOD(gpio_pin_set, ar71xx_gpio_pin_set), 448213239Sgonzo DEVMETHOD(gpio_pin_toggle, ar71xx_gpio_pin_toggle), 449213239Sgonzo {0, 0}, 450213239Sgonzo}; 451213239Sgonzo 452213239Sgonzostatic driver_t ar71xx_gpio_driver = { 453213239Sgonzo "gpio", 454213239Sgonzo ar71xx_gpio_methods, 455213239Sgonzo sizeof(struct ar71xx_gpio_softc), 456213239Sgonzo}; 457213239Sgonzostatic devclass_t ar71xx_gpio_devclass; 458213239Sgonzo 459213239SgonzoDRIVER_MODULE(ar71xx_gpio, apb, ar71xx_gpio_driver, ar71xx_gpio_devclass, 0, 0); 460