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