ti_gpio.c revision 266148
1239281Sgonzo/*- 2239281Sgonzo * Copyright (c) 2011 3239281Sgonzo * Ben Gray <ben.r.gray@gmail.com>. 4239281Sgonzo * All rights reserved. 5239281Sgonzo * 6239281Sgonzo * Redistribution and use in source and binary forms, with or without 7239281Sgonzo * modification, are permitted provided that the following conditions 8239281Sgonzo * are met: 9239281Sgonzo * 1. Redistributions of source code must retain the above copyright 10239281Sgonzo * notice, this list of conditions and the following disclaimer. 11239281Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 12239281Sgonzo * notice, this list of conditions and the following disclaimer in the 13239281Sgonzo * documentation and/or other materials provided with the distribution. 14239281Sgonzo * 15239281Sgonzo * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16239281Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17239281Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18239281Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 19239281Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20239281Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21239281Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22239281Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23239281Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24239281Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25239281Sgonzo * SUCH DAMAGE. 26239281Sgonzo */ 27239281Sgonzo 28239281Sgonzo/** 29239281Sgonzo * Very simple GPIO (general purpose IO) driver module for TI OMAP SoC's. 30239281Sgonzo * 31239281Sgonzo * Currently this driver only does the basics, get a value on a pin & set a 32239281Sgonzo * value on a pin. Hopefully over time I'll expand this to be a bit more generic 33239281Sgonzo * and support interrupts and other various bits on the SoC can do ... in the 34239281Sgonzo * meantime this is all you get. 35239281Sgonzo * 36239281Sgonzo * Beware the OMA datasheet(s) lists GPIO banks 1-6, whereas I've used 0-5 here 37239281Sgonzo * in the code. 38239281Sgonzo * 39239281Sgonzo * 40239281Sgonzo */ 41239281Sgonzo 42239281Sgonzo#include <sys/cdefs.h> 43239281Sgonzo__FBSDID("$FreeBSD: stable/10/sys/arm/ti/ti_gpio.c 266148 2014-05-15 15:47:52Z loos $"); 44239281Sgonzo 45239281Sgonzo#include <sys/param.h> 46239281Sgonzo#include <sys/systm.h> 47239281Sgonzo#include <sys/bus.h> 48239281Sgonzo 49239281Sgonzo#include <sys/kernel.h> 50239281Sgonzo#include <sys/module.h> 51239281Sgonzo#include <sys/rman.h> 52239281Sgonzo#include <sys/lock.h> 53239281Sgonzo#include <sys/mutex.h> 54239281Sgonzo#include <sys/gpio.h> 55239281Sgonzo 56239281Sgonzo#include <machine/bus.h> 57239281Sgonzo#include <machine/resource.h> 58239281Sgonzo 59239281Sgonzo#include <arm/ti/ti_scm.h> 60239281Sgonzo#include <arm/ti/ti_prcm.h> 61239281Sgonzo 62239281Sgonzo#include <dev/fdt/fdt_common.h> 63239281Sgonzo#include <dev/ofw/openfirm.h> 64239281Sgonzo#include <dev/ofw/ofw_bus.h> 65239281Sgonzo#include <dev/ofw/ofw_bus_subr.h> 66239281Sgonzo 67239281Sgonzo#include "gpio_if.h" 68239281Sgonzo 69266148Sloos/* Register definitions */ 70266148Sloos#define TI_GPIO_REVISION 0x0000 71266148Sloos#define TI_GPIO_SYSCONFIG 0x0010 72239281Sgonzo#if defined(SOC_OMAP3) 73266148Sloos#define TI_GPIO_SYSSTATUS 0x0014 74266148Sloos#define TI_GPIO_IRQSTATUS1 0x0018 75266148Sloos#define TI_GPIO_IRQENABLE1 0x001C 76266148Sloos#define TI_GPIO_WAKEUPENABLE 0x0020 77266148Sloos#define TI_GPIO_IRQSTATUS2 0x0028 78266148Sloos#define TI_GPIO_IRQENABLE2 0x002C 79266148Sloos#define TI_GPIO_CTRL 0x0030 80266148Sloos#define TI_GPIO_OE 0x0034 81266148Sloos#define TI_GPIO_DATAIN 0x0038 82266148Sloos#define TI_GPIO_DATAOUT 0x003C 83266148Sloos#define TI_GPIO_LEVELDETECT0 0x0040 84266148Sloos#define TI_GPIO_LEVELDETECT1 0x0044 85266148Sloos#define TI_GPIO_RISINGDETECT 0x0048 86266148Sloos#define TI_GPIO_FALLINGDETECT 0x004C 87266148Sloos#define TI_GPIO_DEBOUNCENABLE 0x0050 88266148Sloos#define TI_GPIO_DEBOUNCINGTIME 0x0054 89266148Sloos#define TI_GPIO_CLEARIRQENABLE1 0x0060 90266148Sloos#define TI_GPIO_SETIRQENABLE1 0x0064 91266148Sloos#define TI_GPIO_CLEARIRQENABLE2 0x0070 92266148Sloos#define TI_GPIO_SETIRQENABLE2 0x0074 93266148Sloos#define TI_GPIO_CLEARWKUENA 0x0080 94266148Sloos#define TI_GPIO_SETWKUENA 0x0084 95266148Sloos#define TI_GPIO_CLEARDATAOUT 0x0090 96266148Sloos#define TI_GPIO_SETDATAOUT 0x0094 97239281Sgonzo#elif defined(SOC_OMAP4) || defined(SOC_TI_AM335X) 98266148Sloos#define TI_GPIO_IRQSTATUS_RAW_0 0x0024 99266148Sloos#define TI_GPIO_IRQSTATUS_RAW_1 0x0028 100266148Sloos#define TI_GPIO_IRQSTATUS_0 0x002C 101266148Sloos#define TI_GPIO_IRQSTATUS_1 0x0030 102266148Sloos#define TI_GPIO_IRQSTATUS_SET_0 0x0034 103266148Sloos#define TI_GPIO_IRQSTATUS_SET_1 0x0038 104266148Sloos#define TI_GPIO_IRQSTATUS_CLR_0 0x003C 105266148Sloos#define TI_GPIO_IRQSTATUS_CLR_1 0x0040 106266148Sloos#define TI_GPIO_IRQWAKEN_0 0x0044 107266148Sloos#define TI_GPIO_IRQWAKEN_1 0x0048 108266148Sloos#define TI_GPIO_SYSSTATUS 0x0114 109266148Sloos#define TI_GPIO_IRQSTATUS1 0x0118 110266148Sloos#define TI_GPIO_IRQENABLE1 0x011C 111266148Sloos#define TI_GPIO_WAKEUPENABLE 0x0120 112266148Sloos#define TI_GPIO_IRQSTATUS2 0x0128 113266148Sloos#define TI_GPIO_IRQENABLE2 0x012C 114266148Sloos#define TI_GPIO_CTRL 0x0130 115266148Sloos#define TI_GPIO_OE 0x0134 116266148Sloos#define TI_GPIO_DATAIN 0x0138 117266148Sloos#define TI_GPIO_DATAOUT 0x013C 118266148Sloos#define TI_GPIO_LEVELDETECT0 0x0140 119266148Sloos#define TI_GPIO_LEVELDETECT1 0x0144 120266148Sloos#define TI_GPIO_RISINGDETECT 0x0148 121266148Sloos#define TI_GPIO_FALLINGDETECT 0x014C 122266148Sloos#define TI_GPIO_DEBOUNCENABLE 0x0150 123266148Sloos#define TI_GPIO_DEBOUNCINGTIME 0x0154 124266148Sloos#define TI_GPIO_CLEARWKUPENA 0x0180 125266148Sloos#define TI_GPIO_SETWKUENA 0x0184 126266148Sloos#define TI_GPIO_CLEARDATAOUT 0x0190 127266148Sloos#define TI_GPIO_SETDATAOUT 0x0194 128239281Sgonzo#else 129239281Sgonzo#error "Unknown SoC" 130239281Sgonzo#endif 131239281Sgonzo 132266148Sloos/* Other SoC Specific definitions */ 133239281Sgonzo#if defined(SOC_OMAP3) 134266148Sloos#define MAX_GPIO_BANKS 6 135266148Sloos#define FIRST_GPIO_BANK 1 136266148Sloos#define INTR_PER_BANK 1 137266148Sloos#define TI_GPIO_REV 0x00000025 138239281Sgonzo#elif defined(SOC_OMAP4) 139266148Sloos#define MAX_GPIO_BANKS 6 140266148Sloos#define FIRST_GPIO_BANK 1 141266148Sloos#define INTR_PER_BANK 1 142266148Sloos#define TI_GPIO_REV 0x50600801 143239281Sgonzo#elif defined(SOC_TI_AM335X) 144266148Sloos#define MAX_GPIO_BANKS 4 145266148Sloos#define FIRST_GPIO_BANK 0 146266148Sloos#define INTR_PER_BANK 2 147266148Sloos#define TI_GPIO_REV 0x50600801 148239281Sgonzo#endif 149266148Sloos#define PINS_PER_BANK 32 150266148Sloos#define MAX_GPIO_INTRS MAX_GPIO_BANKS * INTR_PER_BANK 151239281Sgonzo 152239281Sgonzo/** 153239281Sgonzo * ti_gpio_mem_spec - Resource specification used when allocating resources 154239281Sgonzo * ti_gpio_irq_spec - Resource specification used when allocating resources 155239281Sgonzo * 156239281Sgonzo * This driver module can have up to six independent memory regions, each 157239281Sgonzo * region typically controls 32 GPIO pins. 158266148Sloos * 159266148Sloos * On OMAP3 and OMAP4 there is only one physical interrupt line per bank, 160266148Sloos * but there are two set of registers which control the interrupt delivery 161266148Sloos * to internal subsystems. The first set of registers control the 162266148Sloos * interrupts delivery to the MPU and the second set control the 163266148Sloos * interrupts delivery to the DSP. 164266148Sloos * 165266148Sloos * On AM335x there are two physical interrupt lines for each GPIO module. 166266148Sloos * Each interrupt line is controlled by a set of registers. 167239281Sgonzo */ 168239281Sgonzostatic struct resource_spec ti_gpio_mem_spec[] = { 169239281Sgonzo { SYS_RES_MEMORY, 0, RF_ACTIVE }, 170239281Sgonzo { SYS_RES_MEMORY, 1, RF_ACTIVE | RF_OPTIONAL }, 171239281Sgonzo { SYS_RES_MEMORY, 2, RF_ACTIVE | RF_OPTIONAL }, 172239281Sgonzo { SYS_RES_MEMORY, 3, RF_ACTIVE | RF_OPTIONAL }, 173239281Sgonzo#if !defined(SOC_TI_AM335X) 174239281Sgonzo { SYS_RES_MEMORY, 4, RF_ACTIVE | RF_OPTIONAL }, 175239281Sgonzo { SYS_RES_MEMORY, 5, RF_ACTIVE | RF_OPTIONAL }, 176239281Sgonzo#endif 177239281Sgonzo { -1, 0, 0 } 178239281Sgonzo}; 179239281Sgonzostatic struct resource_spec ti_gpio_irq_spec[] = { 180239281Sgonzo { SYS_RES_IRQ, 0, RF_ACTIVE }, 181239281Sgonzo { SYS_RES_IRQ, 1, RF_ACTIVE | RF_OPTIONAL }, 182239281Sgonzo { SYS_RES_IRQ, 2, RF_ACTIVE | RF_OPTIONAL }, 183239281Sgonzo { SYS_RES_IRQ, 3, RF_ACTIVE | RF_OPTIONAL }, 184239281Sgonzo { SYS_RES_IRQ, 4, RF_ACTIVE | RF_OPTIONAL }, 185239281Sgonzo { SYS_RES_IRQ, 5, RF_ACTIVE | RF_OPTIONAL }, 186266148Sloos#if defined(SOC_TI_AM335X) 187266148Sloos { SYS_RES_IRQ, 6, RF_ACTIVE | RF_OPTIONAL }, 188266148Sloos { SYS_RES_IRQ, 7, RF_ACTIVE | RF_OPTIONAL }, 189239281Sgonzo#endif 190239281Sgonzo { -1, 0, 0 } 191239281Sgonzo}; 192239281Sgonzo 193239281Sgonzo/** 194239281Sgonzo * Structure that stores the driver context. 195239281Sgonzo * 196239281Sgonzo * This structure is allocated during driver attach. 197239281Sgonzo */ 198239281Sgonzostruct ti_gpio_softc { 199266148Sloos device_t sc_dev; 200239281Sgonzo 201266148Sloos /* 202266148Sloos * The memory resource(s) for the PRCM register set, when the device is 203266148Sloos * created the caller can assign up to 6 memory regions depending on 204266148Sloos * the SoC type. 205239281Sgonzo */ 206266148Sloos struct resource *sc_mem_res[MAX_GPIO_BANKS]; 207266148Sloos struct resource *sc_irq_res[MAX_GPIO_INTRS]; 208239281Sgonzo 209266148Sloos /* The handle for the register IRQ handlers. */ 210266148Sloos void *sc_irq_hdl[MAX_GPIO_INTRS]; 211239281Sgonzo 212266148Sloos /* 213266148Sloos * The following describes the H/W revision of each of the GPIO banks. 214266148Sloos */ 215266148Sloos uint32_t sc_revision[MAX_GPIO_BANKS]; 216239281Sgonzo 217266148Sloos struct mtx sc_mtx; 218239281Sgonzo}; 219239281Sgonzo 220239281Sgonzo/** 221239281Sgonzo * Macros for driver mutex locking 222239281Sgonzo */ 223266148Sloos#define TI_GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 224266148Sloos#define TI_GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 225266148Sloos#define TI_GPIO_LOCK_INIT(_sc) \ 226239281Sgonzo mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \ 227266148Sloos "ti_gpio", MTX_DEF) 228266148Sloos#define TI_GPIO_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx) 229266148Sloos#define TI_GPIO_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED) 230266148Sloos#define TI_GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED) 231239281Sgonzo 232239281Sgonzo/** 233239281Sgonzo * ti_gpio_read_4 - reads a 16-bit value from one of the PADCONFS registers 234239281Sgonzo * @sc: GPIO device context 235239281Sgonzo * @bank: The bank to read from 236239281Sgonzo * @off: The offset of a register from the GPIO register address range 237239281Sgonzo * 238239281Sgonzo * 239239281Sgonzo * RETURNS: 240239281Sgonzo * 32-bit value read from the register. 241239281Sgonzo */ 242239281Sgonzostatic inline uint32_t 243239281Sgonzoti_gpio_read_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off) 244239281Sgonzo{ 245239281Sgonzo return (bus_read_4(sc->sc_mem_res[bank], off)); 246239281Sgonzo} 247239281Sgonzo 248239281Sgonzo/** 249239281Sgonzo * ti_gpio_write_4 - writes a 32-bit value to one of the PADCONFS registers 250239281Sgonzo * @sc: GPIO device context 251239281Sgonzo * @bank: The bank to write to 252239281Sgonzo * @off: The offset of a register from the GPIO register address range 253239281Sgonzo * @val: The value to write into the register 254239281Sgonzo * 255239281Sgonzo * RETURNS: 256239281Sgonzo * nothing 257239281Sgonzo */ 258239281Sgonzostatic inline void 259239281Sgonzoti_gpio_write_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off, 260239281Sgonzo uint32_t val) 261239281Sgonzo{ 262239281Sgonzo bus_write_4(sc->sc_mem_res[bank], off, val); 263239281Sgonzo} 264239281Sgonzo 265266148Sloosstatic inline void 266266148Sloosti_gpio_intr_clr(struct ti_gpio_softc *sc, unsigned int bank, uint32_t mask) 267266148Sloos{ 268266148Sloos 269266148Sloos /* We clear both set of registers. */ 270266148Sloos#if defined(SOC_OMAP4) || defined(SOC_TI_AM335X) 271266148Sloos ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_CLR_0, mask); 272266148Sloos ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_CLR_1, mask); 273266148Sloos#else 274266148Sloos ti_gpio_write_4(sc, bank, TI_GPIO_CLEARIRQENABLE1, mask); 275266148Sloos ti_gpio_write_4(sc, bank, TI_GPIO_CLEARIRQENABLE2, mask); 276266148Sloos#endif 277266148Sloos} 278266148Sloos 279239281Sgonzo/** 280239281Sgonzo * ti_gpio_pin_max - Returns the maximum number of GPIO pins 281239281Sgonzo * @dev: gpio device handle 282239281Sgonzo * @maxpin: pointer to a value that upon return will contain the maximum number 283239281Sgonzo * of pins in the device. 284239281Sgonzo * 285239281Sgonzo * 286239281Sgonzo * LOCKING: 287239281Sgonzo * Internally locks the context 288239281Sgonzo * 289239281Sgonzo * RETURNS: 290239281Sgonzo * Returns 0 on success otherwise an error code 291239281Sgonzo */ 292239281Sgonzostatic int 293239281Sgonzoti_gpio_pin_max(device_t dev, int *maxpin) 294239281Sgonzo{ 295239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 296239281Sgonzo unsigned int i; 297239281Sgonzo unsigned int banks = 0; 298239281Sgonzo 299239281Sgonzo TI_GPIO_LOCK(sc); 300239281Sgonzo 301239281Sgonzo /* Calculate how many valid banks we have and then multiply that by 32 to 302239281Sgonzo * give use the total number of pins. 303239281Sgonzo */ 304239281Sgonzo for (i = 0; i < MAX_GPIO_BANKS; i++) { 305239281Sgonzo if (sc->sc_mem_res[i] != NULL) 306239281Sgonzo banks++; 307239281Sgonzo } 308239281Sgonzo 309247252Sgonzo *maxpin = (banks * PINS_PER_BANK) - 1; 310239281Sgonzo 311239281Sgonzo TI_GPIO_UNLOCK(sc); 312239281Sgonzo 313239281Sgonzo return (0); 314239281Sgonzo} 315239281Sgonzo 316239281Sgonzo/** 317239281Sgonzo * ti_gpio_pin_getcaps - Gets the capabilties of a given pin 318239281Sgonzo * @dev: gpio device handle 319239281Sgonzo * @pin: the number of the pin 320239281Sgonzo * @caps: pointer to a value that upon return will contain the capabilities 321239281Sgonzo * 322239281Sgonzo * Currently all pins have the same capability, notably: 323239281Sgonzo * - GPIO_PIN_INPUT 324239281Sgonzo * - GPIO_PIN_OUTPUT 325239281Sgonzo * - GPIO_PIN_PULLUP 326239281Sgonzo * - GPIO_PIN_PULLDOWN 327239281Sgonzo * 328239281Sgonzo * LOCKING: 329239281Sgonzo * Internally locks the context 330239281Sgonzo * 331239281Sgonzo * RETURNS: 332239281Sgonzo * Returns 0 on success otherwise an error code 333239281Sgonzo */ 334239281Sgonzostatic int 335239281Sgonzoti_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 336239281Sgonzo{ 337239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 338239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 339239281Sgonzo 340239281Sgonzo TI_GPIO_LOCK(sc); 341239281Sgonzo 342239281Sgonzo /* Sanity check the pin number is valid */ 343247259Sgonzo if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 344239281Sgonzo TI_GPIO_UNLOCK(sc); 345239281Sgonzo return (EINVAL); 346239281Sgonzo } 347239281Sgonzo 348239281Sgonzo *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |GPIO_PIN_PULLUP | 349239281Sgonzo GPIO_PIN_PULLDOWN); 350239281Sgonzo 351239281Sgonzo TI_GPIO_UNLOCK(sc); 352239281Sgonzo 353239281Sgonzo return (0); 354239281Sgonzo} 355239281Sgonzo 356239281Sgonzo/** 357239281Sgonzo * ti_gpio_pin_getflags - Gets the current flags of a given pin 358239281Sgonzo * @dev: gpio device handle 359239281Sgonzo * @pin: the number of the pin 360239281Sgonzo * @flags: upon return will contain the current flags of the pin 361239281Sgonzo * 362239281Sgonzo * Reads the current flags of a given pin, here we actually read the H/W 363239281Sgonzo * registers to determine the flags, rather than storing the value in the 364239281Sgonzo * setflags call. 365239281Sgonzo * 366239281Sgonzo * LOCKING: 367239281Sgonzo * Internally locks the context 368239281Sgonzo * 369239281Sgonzo * RETURNS: 370239281Sgonzo * Returns 0 on success otherwise an error code 371239281Sgonzo */ 372239281Sgonzostatic int 373239281Sgonzoti_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 374239281Sgonzo{ 375239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 376239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 377239281Sgonzo 378239281Sgonzo TI_GPIO_LOCK(sc); 379239281Sgonzo 380239281Sgonzo /* Sanity check the pin number is valid */ 381247259Sgonzo if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 382239281Sgonzo TI_GPIO_UNLOCK(sc); 383239281Sgonzo return (EINVAL); 384239281Sgonzo } 385239281Sgonzo 386239281Sgonzo /* Get the current pin state */ 387239281Sgonzo ti_scm_padconf_get_gpioflags(pin, flags); 388239281Sgonzo 389239281Sgonzo TI_GPIO_UNLOCK(sc); 390239281Sgonzo 391239281Sgonzo return (0); 392239281Sgonzo} 393239281Sgonzo 394239281Sgonzo/** 395239281Sgonzo * ti_gpio_pin_getname - Gets the name of a given pin 396239281Sgonzo * @dev: gpio device handle 397239281Sgonzo * @pin: the number of the pin 398239281Sgonzo * @name: buffer to put the name in 399239281Sgonzo * 400239281Sgonzo * The driver simply calls the pins gpio_n, where 'n' is obviously the number 401239281Sgonzo * of the pin. 402239281Sgonzo * 403239281Sgonzo * LOCKING: 404239281Sgonzo * Internally locks the context 405239281Sgonzo * 406239281Sgonzo * RETURNS: 407239281Sgonzo * Returns 0 on success otherwise an error code 408239281Sgonzo */ 409239281Sgonzostatic int 410239281Sgonzoti_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 411239281Sgonzo{ 412239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 413239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 414239281Sgonzo 415239281Sgonzo TI_GPIO_LOCK(sc); 416239281Sgonzo 417239281Sgonzo /* Sanity check the pin number is valid */ 418247259Sgonzo if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 419239281Sgonzo TI_GPIO_UNLOCK(sc); 420239281Sgonzo return (EINVAL); 421239281Sgonzo } 422239281Sgonzo 423239281Sgonzo /* Set a very simple name */ 424239281Sgonzo snprintf(name, GPIOMAXNAME, "gpio_%u", pin); 425239281Sgonzo name[GPIOMAXNAME - 1] = '\0'; 426239281Sgonzo 427239281Sgonzo TI_GPIO_UNLOCK(sc); 428239281Sgonzo 429239281Sgonzo return (0); 430239281Sgonzo} 431239281Sgonzo 432239281Sgonzo/** 433239281Sgonzo * ti_gpio_pin_setflags - Sets the flags for a given pin 434239281Sgonzo * @dev: gpio device handle 435239281Sgonzo * @pin: the number of the pin 436239281Sgonzo * @flags: the flags to set 437239281Sgonzo * 438239281Sgonzo * The flags of the pin correspond to things like input/output mode, pull-ups, 439239281Sgonzo * pull-downs, etc. This driver doesn't support all flags, only the following: 440239281Sgonzo * - GPIO_PIN_INPUT 441239281Sgonzo * - GPIO_PIN_OUTPUT 442239281Sgonzo * - GPIO_PIN_PULLUP 443239281Sgonzo * - GPIO_PIN_PULLDOWN 444239281Sgonzo * 445239281Sgonzo * LOCKING: 446239281Sgonzo * Internally locks the context 447239281Sgonzo * 448239281Sgonzo * RETURNS: 449239281Sgonzo * Returns 0 on success otherwise an error code 450239281Sgonzo */ 451239281Sgonzostatic int 452239281Sgonzoti_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 453239281Sgonzo{ 454239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 455239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 456239281Sgonzo uint32_t mask = (1UL << (pin % PINS_PER_BANK)); 457239281Sgonzo uint32_t reg_val; 458239281Sgonzo 459239281Sgonzo /* Sanity check the flags supplied are valid, i.e. not input and output */ 460239281Sgonzo if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 0x0000) 461239281Sgonzo return (EINVAL); 462239281Sgonzo if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 463239281Sgonzo (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) 464239281Sgonzo return (EINVAL); 465239281Sgonzo if ((flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) == 466239281Sgonzo (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) 467239281Sgonzo return (EINVAL); 468239281Sgonzo 469239281Sgonzo TI_GPIO_LOCK(sc); 470239281Sgonzo 471239281Sgonzo /* Sanity check the pin number is valid */ 472247259Sgonzo if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 473239281Sgonzo TI_GPIO_UNLOCK(sc); 474239281Sgonzo return (EINVAL); 475239281Sgonzo } 476239281Sgonzo 477239281Sgonzo /* Set the GPIO mode and state */ 478239281Sgonzo if (ti_scm_padconf_set_gpioflags(pin, flags) != 0) { 479239281Sgonzo TI_GPIO_UNLOCK(sc); 480239281Sgonzo return (EINVAL); 481239281Sgonzo } 482239281Sgonzo 483239281Sgonzo /* If configuring as an output set the "output enable" bit */ 484239281Sgonzo reg_val = ti_gpio_read_4(sc, bank, TI_GPIO_OE); 485239281Sgonzo if (flags & GPIO_PIN_INPUT) 486239281Sgonzo reg_val |= mask; 487239281Sgonzo else 488239281Sgonzo reg_val &= ~mask; 489239281Sgonzo ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_val); 490239281Sgonzo 491239281Sgonzo TI_GPIO_UNLOCK(sc); 492239281Sgonzo 493239281Sgonzo return (0); 494239281Sgonzo} 495239281Sgonzo 496239281Sgonzo/** 497239281Sgonzo * ti_gpio_pin_set - Sets the current level on a GPIO pin 498239281Sgonzo * @dev: gpio device handle 499239281Sgonzo * @pin: the number of the pin 500239281Sgonzo * @value: non-zero value will drive the pin high, otherwise the pin is 501239281Sgonzo * driven low. 502239281Sgonzo * 503239281Sgonzo * 504239281Sgonzo * LOCKING: 505239281Sgonzo * Internally locks the context 506239281Sgonzo * 507239281Sgonzo * RETURNS: 508239281Sgonzo * Returns 0 on success otherwise a error code 509239281Sgonzo */ 510239281Sgonzostatic int 511239281Sgonzoti_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 512239281Sgonzo{ 513239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 514239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 515239281Sgonzo uint32_t mask = (1UL << (pin % PINS_PER_BANK)); 516239281Sgonzo 517239281Sgonzo TI_GPIO_LOCK(sc); 518239281Sgonzo 519239281Sgonzo /* Sanity check the pin number is valid */ 520247259Sgonzo if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 521239281Sgonzo TI_GPIO_UNLOCK(sc); 522239281Sgonzo return (EINVAL); 523239281Sgonzo } 524239281Sgonzo 525239281Sgonzo ti_gpio_write_4(sc, bank, (value == GPIO_PIN_LOW) ? TI_GPIO_CLEARDATAOUT 526239281Sgonzo : TI_GPIO_SETDATAOUT, mask); 527239281Sgonzo 528239281Sgonzo TI_GPIO_UNLOCK(sc); 529239281Sgonzo 530239281Sgonzo return (0); 531239281Sgonzo} 532239281Sgonzo 533239281Sgonzo/** 534239281Sgonzo * ti_gpio_pin_get - Gets the current level on a GPIO pin 535239281Sgonzo * @dev: gpio device handle 536239281Sgonzo * @pin: the number of the pin 537239281Sgonzo * @value: pointer to a value that upond return will contain the pin value 538239281Sgonzo * 539239281Sgonzo * The pin must be configured as an input pin beforehand, otherwise this 540239281Sgonzo * function will fail. 541239281Sgonzo * 542239281Sgonzo * LOCKING: 543239281Sgonzo * Internally locks the context 544239281Sgonzo * 545239281Sgonzo * RETURNS: 546239281Sgonzo * Returns 0 on success otherwise a error code 547239281Sgonzo */ 548239281Sgonzostatic int 549239281Sgonzoti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) 550239281Sgonzo{ 551239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 552239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 553239281Sgonzo uint32_t mask = (1UL << (pin % PINS_PER_BANK)); 554239281Sgonzo uint32_t val = 0; 555239281Sgonzo 556239281Sgonzo TI_GPIO_LOCK(sc); 557239281Sgonzo 558239281Sgonzo /* Sanity check the pin number is valid */ 559247259Sgonzo if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 560239281Sgonzo TI_GPIO_UNLOCK(sc); 561239281Sgonzo return (EINVAL); 562239281Sgonzo } 563239281Sgonzo 564239281Sgonzo /* Sanity check the pin is not configured as an output */ 565239281Sgonzo val = ti_gpio_read_4(sc, bank, TI_GPIO_OE); 566239281Sgonzo 567239281Sgonzo /* Read the value on the pin */ 568247252Sgonzo if (val & mask) 569266105Sloos *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAIN) & mask) ? 1 : 0; 570266105Sloos else 571247252Sgonzo *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT) & mask) ? 1 : 0; 572239281Sgonzo 573239281Sgonzo TI_GPIO_UNLOCK(sc); 574239281Sgonzo 575239281Sgonzo return (0); 576239281Sgonzo} 577239281Sgonzo 578239281Sgonzo/** 579239281Sgonzo * ti_gpio_pin_toggle - Toggles a given GPIO pin 580239281Sgonzo * @dev: gpio device handle 581239281Sgonzo * @pin: the number of the pin 582239281Sgonzo * 583239281Sgonzo * 584239281Sgonzo * LOCKING: 585239281Sgonzo * Internally locks the context 586239281Sgonzo * 587239281Sgonzo * RETURNS: 588239281Sgonzo * Returns 0 on success otherwise a error code 589239281Sgonzo */ 590239281Sgonzostatic int 591239281Sgonzoti_gpio_pin_toggle(device_t dev, uint32_t pin) 592239281Sgonzo{ 593239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 594239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 595239281Sgonzo uint32_t mask = (1UL << (pin % PINS_PER_BANK)); 596239281Sgonzo uint32_t val; 597239281Sgonzo 598239281Sgonzo TI_GPIO_LOCK(sc); 599239281Sgonzo 600239281Sgonzo /* Sanity check the pin number is valid */ 601247259Sgonzo if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 602239281Sgonzo TI_GPIO_UNLOCK(sc); 603239281Sgonzo return (EINVAL); 604239281Sgonzo } 605239281Sgonzo 606239281Sgonzo /* Toggle the pin */ 607239281Sgonzo val = ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT); 608239281Sgonzo if (val & mask) 609239281Sgonzo ti_gpio_write_4(sc, bank, TI_GPIO_CLEARDATAOUT, mask); 610239281Sgonzo else 611239281Sgonzo ti_gpio_write_4(sc, bank, TI_GPIO_SETDATAOUT, mask); 612239281Sgonzo 613239281Sgonzo TI_GPIO_UNLOCK(sc); 614239281Sgonzo 615239281Sgonzo return (0); 616239281Sgonzo} 617239281Sgonzo 618239281Sgonzo/** 619239281Sgonzo * ti_gpio_intr - ISR for all GPIO modules 620239281Sgonzo * @arg: the soft context pointer 621239281Sgonzo * 622239281Sgonzo * Unsused 623239281Sgonzo * 624239281Sgonzo * LOCKING: 625239281Sgonzo * Internally locks the context 626239281Sgonzo * 627239281Sgonzo */ 628239281Sgonzostatic void 629239281Sgonzoti_gpio_intr(void *arg) 630239281Sgonzo{ 631239281Sgonzo struct ti_gpio_softc *sc = arg; 632239281Sgonzo 633239281Sgonzo TI_GPIO_LOCK(sc); 634239281Sgonzo /* TODO: something useful */ 635239281Sgonzo TI_GPIO_UNLOCK(sc); 636239281Sgonzo} 637239281Sgonzo 638239281Sgonzo/** 639239281Sgonzo * ti_gpio_probe - probe function for the driver 640239281Sgonzo * @dev: gpio device handle 641239281Sgonzo * 642239281Sgonzo * Simply sets the name of the driver 643239281Sgonzo * 644239281Sgonzo * LOCKING: 645239281Sgonzo * None 646239281Sgonzo * 647239281Sgonzo * RETURNS: 648239281Sgonzo * Always returns 0 649239281Sgonzo */ 650239281Sgonzostatic int 651239281Sgonzoti_gpio_probe(device_t dev) 652239281Sgonzo{ 653239281Sgonzo if (!ofw_bus_is_compatible(dev, "ti,gpio")) 654239281Sgonzo return (ENXIO); 655239281Sgonzo 656239281Sgonzo device_set_desc(dev, "TI General Purpose I/O (GPIO)"); 657266148Sloos 658239281Sgonzo return (0); 659239281Sgonzo} 660239281Sgonzo 661266148Sloosstatic int 662266148Sloosti_gpio_attach_intr(device_t dev) 663266148Sloos{ 664266148Sloos int i; 665266148Sloos struct ti_gpio_softc *sc; 666266148Sloos 667266148Sloos sc = device_get_softc(dev); 668266148Sloos for (i = 0; i < MAX_GPIO_INTRS; i++) { 669266148Sloos if (sc->sc_irq_res[i] == NULL) 670266148Sloos break; 671266148Sloos 672266148Sloos /* 673266148Sloos * Register our interrupt handler for each of the IRQ resources. 674266148Sloos */ 675266148Sloos if (bus_setup_intr(dev, sc->sc_irq_res[i], 676266148Sloos INTR_TYPE_MISC | INTR_MPSAFE, NULL, ti_gpio_intr, sc, 677266148Sloos &sc->sc_irq_hdl[i]) != 0) { 678266148Sloos device_printf(dev, 679266148Sloos "WARNING: unable to register interrupt handler\n"); 680266148Sloos return (-1); 681266148Sloos } 682266148Sloos } 683266148Sloos 684266148Sloos return (0); 685266148Sloos} 686266148Sloos 687266148Sloosstatic int 688266148Sloosti_gpio_detach_intr(device_t dev) 689266148Sloos{ 690266148Sloos int i; 691266148Sloos struct ti_gpio_softc *sc; 692266148Sloos 693266148Sloos /* Teardown our interrupt handlers. */ 694266148Sloos sc = device_get_softc(dev); 695266148Sloos for (i = 0; i < MAX_GPIO_INTRS; i++) { 696266148Sloos if (sc->sc_irq_res[i] == NULL) 697266148Sloos break; 698266148Sloos 699266148Sloos if (sc->sc_irq_hdl[i]) { 700266148Sloos bus_teardown_intr(dev, sc->sc_irq_res[i], 701266148Sloos sc->sc_irq_hdl[i]); 702266148Sloos } 703266148Sloos } 704266148Sloos 705266148Sloos return (0); 706266148Sloos} 707266148Sloos 708266148Sloosstatic int 709266148Sloosti_gpio_bank_init(device_t dev, int bank) 710266148Sloos{ 711266148Sloos int pin; 712266148Sloos struct ti_gpio_softc *sc; 713266148Sloos uint32_t flags, reg_oe; 714266148Sloos 715266148Sloos sc = device_get_softc(dev); 716266148Sloos 717266148Sloos /* Enable the interface and functional clocks for the module. */ 718266148Sloos ti_prcm_clk_enable(GPIO0_CLK + FIRST_GPIO_BANK + bank); 719266148Sloos 720266148Sloos /* 721266148Sloos * Read the revision number of the module. TI don't publish the 722266148Sloos * actual revision numbers, so instead the values have been 723266148Sloos * determined by experimentation. 724266148Sloos */ 725266148Sloos sc->sc_revision[bank] = ti_gpio_read_4(sc, bank, TI_GPIO_REVISION); 726266148Sloos 727266148Sloos /* Check the revision. */ 728266148Sloos if (sc->sc_revision[bank] != TI_GPIO_REV) { 729266148Sloos device_printf(dev, "Warning: could not determine the revision " 730266148Sloos "of %u GPIO module (revision:0x%08x)\n", 731266148Sloos bank, sc->sc_revision[bank]); 732266148Sloos return (EINVAL); 733266148Sloos } 734266148Sloos 735266148Sloos /* Disable interrupts for all pins. */ 736266148Sloos ti_gpio_intr_clr(sc, bank, 0xffffffff); 737266148Sloos 738266148Sloos /* Init OE register based on pads configuration. */ 739266148Sloos reg_oe = 0xffffffff; 740266148Sloos for (pin = 0; pin < PINS_PER_BANK; pin++) { 741266148Sloos ti_scm_padconf_get_gpioflags(PINS_PER_BANK * bank + pin, 742266148Sloos &flags); 743266148Sloos if (flags & GPIO_PIN_OUTPUT) 744266148Sloos reg_oe &= ~(1UL << pin); 745266148Sloos } 746266148Sloos ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_oe); 747266148Sloos 748266148Sloos return (0); 749266148Sloos} 750266148Sloos 751239281Sgonzo/** 752239281Sgonzo * ti_gpio_attach - attach function for the driver 753239281Sgonzo * @dev: gpio device handle 754239281Sgonzo * 755239281Sgonzo * Allocates and sets up the driver context for all GPIO banks. This function 756239281Sgonzo * expects the memory ranges and IRQs to already be allocated to the driver. 757239281Sgonzo * 758239281Sgonzo * LOCKING: 759239281Sgonzo * None 760239281Sgonzo * 761239281Sgonzo * RETURNS: 762239281Sgonzo * Always returns 0 763239281Sgonzo */ 764239281Sgonzostatic int 765239281Sgonzoti_gpio_attach(device_t dev) 766239281Sgonzo{ 767266148Sloos struct ti_gpio_softc *sc; 768239281Sgonzo unsigned int i; 769266148Sloos int err; 770239281Sgonzo 771266148Sloos sc = device_get_softc(dev); 772239281Sgonzo sc->sc_dev = dev; 773239281Sgonzo 774239281Sgonzo TI_GPIO_LOCK_INIT(sc); 775239281Sgonzo 776239281Sgonzo /* There are up to 6 different GPIO register sets located in different 777239281Sgonzo * memory areas on the chip. The memory range should have been set for 778239281Sgonzo * the driver when it was added as a child. 779239281Sgonzo */ 780266148Sloos if (bus_alloc_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res) != 0) { 781239281Sgonzo device_printf(dev, "Error: could not allocate mem resources\n"); 782239281Sgonzo return (ENXIO); 783239281Sgonzo } 784239281Sgonzo 785239281Sgonzo /* Request the IRQ resources */ 786266148Sloos if (bus_alloc_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res) != 0) { 787266148Sloos bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res); 788239281Sgonzo device_printf(dev, "Error: could not allocate irq resources\n"); 789239281Sgonzo return (ENXIO); 790239281Sgonzo } 791239281Sgonzo 792239281Sgonzo /* Setup the IRQ resources */ 793266148Sloos if (ti_gpio_attach_intr(dev) != 0) { 794266148Sloos ti_gpio_detach_intr(dev); 795266148Sloos bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res); 796266148Sloos bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res); 797266148Sloos return (ENXIO); 798239281Sgonzo } 799239281Sgonzo 800239281Sgonzo /* We need to go through each block and ensure the clocks are running and 801239281Sgonzo * the module is enabled. It might be better to do this only when the 802239281Sgonzo * pins are configured which would result in less power used if the GPIO 803239281Sgonzo * pins weren't used ... 804239281Sgonzo */ 805266148Sloos for (i = 0; i < MAX_GPIO_BANKS; i++) { 806239281Sgonzo if (sc->sc_mem_res[i] != NULL) { 807266148Sloos /* Initialize the GPIO module. */ 808266148Sloos err = ti_gpio_bank_init(dev, i); 809266148Sloos if (err != 0) { 810266148Sloos ti_gpio_detach_intr(dev); 811266148Sloos bus_release_resources(dev, ti_gpio_irq_spec, 812266148Sloos sc->sc_irq_res); 813266148Sloos bus_release_resources(dev, ti_gpio_mem_spec, 814266148Sloos sc->sc_mem_res); 815266148Sloos return (err); 816239281Sgonzo } 817239281Sgonzo } 818239281Sgonzo } 819239281Sgonzo 820239281Sgonzo /* Finish of the probe call */ 821239281Sgonzo device_add_child(dev, "gpioc", device_get_unit(dev)); 822239281Sgonzo device_add_child(dev, "gpiobus", device_get_unit(dev)); 823247252Sgonzo 824239281Sgonzo return (bus_generic_attach(dev)); 825239281Sgonzo} 826239281Sgonzo 827239281Sgonzo/** 828239281Sgonzo * ti_gpio_detach - detach function for the driver 829239281Sgonzo * @dev: scm device handle 830239281Sgonzo * 831239281Sgonzo * Allocates and sets up the driver context, this simply entails creating a 832239281Sgonzo * bus mappings for the SCM register set. 833239281Sgonzo * 834239281Sgonzo * LOCKING: 835239281Sgonzo * None 836239281Sgonzo * 837239281Sgonzo * RETURNS: 838239281Sgonzo * Always returns 0 839239281Sgonzo */ 840239281Sgonzostatic int 841239281Sgonzoti_gpio_detach(device_t dev) 842239281Sgonzo{ 843239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 844239281Sgonzo unsigned int i; 845239281Sgonzo 846239281Sgonzo KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized")); 847239281Sgonzo 848239281Sgonzo /* Disable all interrupts */ 849266148Sloos for (i = 0; i < MAX_GPIO_BANKS; i++) { 850266148Sloos if (sc->sc_mem_res[i] != NULL) 851266148Sloos ti_gpio_intr_clr(sc, i, 0xffffffff); 852239281Sgonzo } 853239281Sgonzo 854239281Sgonzo bus_generic_detach(dev); 855239281Sgonzo 856266148Sloos /* Release the memory and IRQ resources. */ 857266148Sloos ti_gpio_detach_intr(dev); 858266148Sloos bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res); 859266148Sloos bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res); 860239281Sgonzo 861239281Sgonzo TI_GPIO_LOCK_DESTROY(sc); 862239281Sgonzo 863266148Sloos return (0); 864239281Sgonzo} 865239281Sgonzo 866266105Sloosstatic phandle_t 867266105Sloosti_gpio_get_node(device_t bus, device_t dev) 868266105Sloos{ 869266105Sloos 870266105Sloos /* We only have one child, the GPIO bus, which needs our own node. */ 871266105Sloos return (ofw_bus_get_node(bus)); 872266105Sloos} 873266105Sloos 874239281Sgonzostatic device_method_t ti_gpio_methods[] = { 875239281Sgonzo DEVMETHOD(device_probe, ti_gpio_probe), 876239281Sgonzo DEVMETHOD(device_attach, ti_gpio_attach), 877239281Sgonzo DEVMETHOD(device_detach, ti_gpio_detach), 878239281Sgonzo 879239281Sgonzo /* GPIO protocol */ 880239281Sgonzo DEVMETHOD(gpio_pin_max, ti_gpio_pin_max), 881239281Sgonzo DEVMETHOD(gpio_pin_getname, ti_gpio_pin_getname), 882239281Sgonzo DEVMETHOD(gpio_pin_getflags, ti_gpio_pin_getflags), 883239281Sgonzo DEVMETHOD(gpio_pin_getcaps, ti_gpio_pin_getcaps), 884239281Sgonzo DEVMETHOD(gpio_pin_setflags, ti_gpio_pin_setflags), 885239281Sgonzo DEVMETHOD(gpio_pin_get, ti_gpio_pin_get), 886239281Sgonzo DEVMETHOD(gpio_pin_set, ti_gpio_pin_set), 887239281Sgonzo DEVMETHOD(gpio_pin_toggle, ti_gpio_pin_toggle), 888266105Sloos 889266105Sloos /* ofw_bus interface */ 890266105Sloos DEVMETHOD(ofw_bus_get_node, ti_gpio_get_node), 891266105Sloos 892239281Sgonzo {0, 0}, 893239281Sgonzo}; 894239281Sgonzo 895239281Sgonzostatic driver_t ti_gpio_driver = { 896239281Sgonzo "gpio", 897239281Sgonzo ti_gpio_methods, 898239281Sgonzo sizeof(struct ti_gpio_softc), 899239281Sgonzo}; 900239281Sgonzostatic devclass_t ti_gpio_devclass; 901239281Sgonzo 902239281SgonzoDRIVER_MODULE(ti_gpio, simplebus, ti_gpio_driver, ti_gpio_devclass, 0, 0); 903