ti_gpio.c revision 247252
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: head/sys/arm/ti/ti_gpio.c 247252 2013-02-25 08:04:47Z gonzo $"); 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 69239281Sgonzo /* Register definitions */ 70239281Sgonzo#define TI_GPIO_REVISION 0x0000 71239281Sgonzo#define TI_GPIO_SYSCONFIG 0x0010 72239281Sgonzo#if defined(SOC_OMAP3) 73239281Sgonzo#define TI_GPIO_REVISION 0x0000 74239281Sgonzo#define TI_GPIO_SYSCONFIG 0x0010 75239281Sgonzo#define TI_GPIO_SYSSTATUS 0x0014 76239281Sgonzo#define TI_GPIO_IRQSTATUS1 0x0018 77239281Sgonzo#define TI_GPIO_IRQENABLE1 0x001C 78239281Sgonzo#define TI_GPIO_WAKEUPENABLE 0x0020 79239281Sgonzo#define TI_GPIO_IRQSTATUS2 0x0028 80239281Sgonzo#define TI_GPIO_IRQENABLE2 0x002C 81239281Sgonzo#define TI_GPIO_CTRL 0x0030 82239281Sgonzo#define TI_GPIO_OE 0x0034 83239281Sgonzo#define TI_GPIO_DATAIN 0x0038 84239281Sgonzo#define TI_GPIO_DATAOUT 0x003C 85239281Sgonzo#define TI_GPIO_LEVELDETECT0 0x0040 86239281Sgonzo#define TI_GPIO_LEVELDETECT1 0x0044 87239281Sgonzo#define TI_GPIO_RISINGDETECT 0x0048 88239281Sgonzo#define TI_GPIO_FALLINGDETECT 0x004C 89239281Sgonzo#define TI_GPIO_DEBOUNCENABLE 0x0050 90239281Sgonzo#define TI_GPIO_DEBOUNCINGTIME 0x0054 91239281Sgonzo#define TI_GPIO_CLEARIRQENABLE1 0x0060 92239281Sgonzo#define TI_GPIO_SETIRQENABLE1 0x0064 93239281Sgonzo#define TI_GPIO_CLEARIRQENABLE2 0x0070 94239281Sgonzo#define TI_GPIO_SETIRQENABLE2 0x0074 95239281Sgonzo#define TI_GPIO_CLEARWKUENA 0x0080 96239281Sgonzo#define TI_GPIO_SETWKUENA 0x0084 97239281Sgonzo#define TI_GPIO_CLEARDATAOUT 0x0090 98239281Sgonzo#define TI_GPIO_SETDATAOUT 0x0094 99239281Sgonzo#elif defined(SOC_OMAP4) || defined(SOC_TI_AM335X) 100239281Sgonzo#define TI_GPIO_IRQSTATUS_RAW_0 0x0024 101239281Sgonzo#define TI_GPIO_IRQSTATUS_RAW_1 0x0028 102239281Sgonzo#define TI_GPIO_IRQSTATUS_0 0x002C 103239281Sgonzo#define TI_GPIO_IRQSTATUS_1 0x0030 104239281Sgonzo#define TI_GPIO_IRQSTATUS_SET_0 0x0034 105239281Sgonzo#define TI_GPIO_IRQSTATUS_SET_1 0x0038 106239281Sgonzo#define TI_GPIO_IRQSTATUS_CLR_0 0x003C 107239281Sgonzo#define TI_GPIO_IRQSTATUS_CLR_1 0x0040 108239281Sgonzo#define TI_GPIO_IRQWAKEN_0 0x0044 109239281Sgonzo#define TI_GPIO_IRQWAKEN_1 0x0048 110239281Sgonzo#define TI_GPIO_SYSSTATUS 0x0114 111239281Sgonzo#define TI_GPIO_IRQSTATUS1 0x0118 112239281Sgonzo#define TI_GPIO_IRQENABLE1 0x011C 113239281Sgonzo#define TI_GPIO_WAKEUPENABLE 0x0120 114239281Sgonzo#define TI_GPIO_IRQSTATUS2 0x0128 115239281Sgonzo#define TI_GPIO_IRQENABLE2 0x012C 116239281Sgonzo#define TI_GPIO_CTRL 0x0130 117239281Sgonzo#define TI_GPIO_OE 0x0134 118239281Sgonzo#define TI_GPIO_DATAIN 0x0138 119239281Sgonzo#define TI_GPIO_DATAOUT 0x013C 120239281Sgonzo#define TI_GPIO_LEVELDETECT0 0x0140 121239281Sgonzo#define TI_GPIO_LEVELDETECT1 0x0144 122239281Sgonzo#define TI_GPIO_RISINGDETECT 0x0148 123239281Sgonzo#define TI_GPIO_FALLINGDETECT 0x014C 124239281Sgonzo#define TI_GPIO_DEBOUNCENABLE 0x0150 125239281Sgonzo#define TI_GPIO_DEBOUNCINGTIME 0x0154 126239281Sgonzo#define TI_GPIO_CLEARIRQENABLE1 0x0160 127239281Sgonzo#define TI_GPIO_SETIRQENABLE1 0x0164 128239281Sgonzo#define TI_GPIO_CLEARIRQENABLE2 0x0170 129239281Sgonzo#define TI_GPIO_SETIRQENABLE2 0x0174 130239281Sgonzo#define TI_GPIO_CLEARWKUPENA 0x0180 131239281Sgonzo#define TI_GPIO_SETWKUENA 0x0184 132239281Sgonzo#define TI_GPIO_CLEARDATAOUT 0x0190 133239281Sgonzo#define TI_GPIO_SETDATAOUT 0x0194 134239281Sgonzo#else 135239281Sgonzo#error "Unknown SoC" 136239281Sgonzo#endif 137239281Sgonzo 138239281Sgonzo /*Other SoC Specific definitions*/ 139239281Sgonzo#if defined(SOC_OMAP3) 140239281Sgonzo#define MAX_GPIO_BANKS 6 141239281Sgonzo#define FIRST_GPIO_BANK 1 142239281Sgonzo#define PINS_PER_BANK 32 143239281Sgonzo#define TI_GPIO_REV 0x00000025 144239281Sgonzo#elif defined(SOC_OMAP4) 145239281Sgonzo#define MAX_GPIO_BANKS 6 146239281Sgonzo#define FIRST_GPIO_BANK 1 147239281Sgonzo#define PINS_PER_BANK 32 148239281Sgonzo#define TI_GPIO_REV 0x50600801 149239281Sgonzo#elif defined(SOC_TI_AM335X) 150239281Sgonzo#define MAX_GPIO_BANKS 4 151239281Sgonzo#define FIRST_GPIO_BANK 0 152239281Sgonzo#define PINS_PER_BANK 32 153239281Sgonzo#define TI_GPIO_REV 0x50600801 154239281Sgonzo#endif 155239281Sgonzo 156239281Sgonzo/** 157239281Sgonzo * ti_gpio_mem_spec - Resource specification used when allocating resources 158239281Sgonzo * ti_gpio_irq_spec - Resource specification used when allocating resources 159239281Sgonzo * 160239281Sgonzo * This driver module can have up to six independent memory regions, each 161239281Sgonzo * region typically controls 32 GPIO pins. 162239281Sgonzo */ 163239281Sgonzostatic struct resource_spec ti_gpio_mem_spec[] = { 164239281Sgonzo { SYS_RES_MEMORY, 0, RF_ACTIVE }, 165239281Sgonzo { SYS_RES_MEMORY, 1, RF_ACTIVE | RF_OPTIONAL }, 166239281Sgonzo { SYS_RES_MEMORY, 2, RF_ACTIVE | RF_OPTIONAL }, 167239281Sgonzo { SYS_RES_MEMORY, 3, RF_ACTIVE | RF_OPTIONAL }, 168239281Sgonzo#if !defined(SOC_TI_AM335X) 169239281Sgonzo { SYS_RES_MEMORY, 4, RF_ACTIVE | RF_OPTIONAL }, 170239281Sgonzo { SYS_RES_MEMORY, 5, RF_ACTIVE | RF_OPTIONAL }, 171239281Sgonzo#endif 172239281Sgonzo { -1, 0, 0 } 173239281Sgonzo}; 174239281Sgonzostatic struct resource_spec ti_gpio_irq_spec[] = { 175239281Sgonzo { SYS_RES_IRQ, 0, RF_ACTIVE }, 176239281Sgonzo { SYS_RES_IRQ, 1, RF_ACTIVE | RF_OPTIONAL }, 177239281Sgonzo { SYS_RES_IRQ, 2, RF_ACTIVE | RF_OPTIONAL }, 178239281Sgonzo { SYS_RES_IRQ, 3, RF_ACTIVE | RF_OPTIONAL }, 179239281Sgonzo#if !defined(SOC_TI_AM335X) 180239281Sgonzo { SYS_RES_IRQ, 4, RF_ACTIVE | RF_OPTIONAL }, 181239281Sgonzo { SYS_RES_IRQ, 5, RF_ACTIVE | RF_OPTIONAL }, 182239281Sgonzo#endif 183239281Sgonzo { -1, 0, 0 } 184239281Sgonzo}; 185239281Sgonzo 186239281Sgonzo/** 187239281Sgonzo * Structure that stores the driver context. 188239281Sgonzo * 189239281Sgonzo * This structure is allocated during driver attach. 190239281Sgonzo */ 191239281Sgonzostruct ti_gpio_softc { 192239281Sgonzo device_t sc_dev; 193239281Sgonzo 194239281Sgonzo /* The memory resource(s) for the PRCM register set, when the device is 195239281Sgonzo * created the caller can assign up to 4 memory regions. 196239281Sgonzo */ 197239281Sgonzo struct resource* sc_mem_res[MAX_GPIO_BANKS]; 198239281Sgonzo struct resource* sc_irq_res[MAX_GPIO_BANKS]; 199239281Sgonzo 200239281Sgonzo /* The handle for the register IRQ handlers */ 201239281Sgonzo void* sc_irq_hdl[MAX_GPIO_BANKS]; 202239281Sgonzo 203239281Sgonzo /* The following describes the H/W revision of each of the GPIO banks */ 204239281Sgonzo uint32_t sc_revision[MAX_GPIO_BANKS]; 205239281Sgonzo 206239281Sgonzo struct mtx sc_mtx; 207239281Sgonzo}; 208239281Sgonzo 209239281Sgonzo/** 210239281Sgonzo * Macros for driver mutex locking 211239281Sgonzo */ 212239281Sgonzo#define TI_GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 213239281Sgonzo#define TI_GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 214239281Sgonzo#define TI_GPIO_LOCK_INIT(_sc) \ 215239281Sgonzo mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \ 216239281Sgonzo "ti_gpio", MTX_DEF) 217239281Sgonzo#define TI_GPIO_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); 218239281Sgonzo#define TI_GPIO_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); 219239281Sgonzo#define TI_GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); 220239281Sgonzo 221239281Sgonzo/** 222239281Sgonzo * ti_gpio_read_4 - reads a 16-bit value from one of the PADCONFS registers 223239281Sgonzo * @sc: GPIO device context 224239281Sgonzo * @bank: The bank to read from 225239281Sgonzo * @off: The offset of a register from the GPIO register address range 226239281Sgonzo * 227239281Sgonzo * 228239281Sgonzo * RETURNS: 229239281Sgonzo * 32-bit value read from the register. 230239281Sgonzo */ 231239281Sgonzostatic inline uint32_t 232239281Sgonzoti_gpio_read_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off) 233239281Sgonzo{ 234239281Sgonzo return (bus_read_4(sc->sc_mem_res[bank], off)); 235239281Sgonzo} 236239281Sgonzo 237239281Sgonzo/** 238239281Sgonzo * ti_gpio_write_4 - writes a 32-bit value to one of the PADCONFS registers 239239281Sgonzo * @sc: GPIO device context 240239281Sgonzo * @bank: The bank to write to 241239281Sgonzo * @off: The offset of a register from the GPIO register address range 242239281Sgonzo * @val: The value to write into the register 243239281Sgonzo * 244239281Sgonzo * RETURNS: 245239281Sgonzo * nothing 246239281Sgonzo */ 247239281Sgonzostatic inline void 248239281Sgonzoti_gpio_write_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off, 249239281Sgonzo uint32_t val) 250239281Sgonzo{ 251239281Sgonzo bus_write_4(sc->sc_mem_res[bank], off, val); 252239281Sgonzo} 253239281Sgonzo 254239281Sgonzo/** 255239281Sgonzo * ti_gpio_pin_max - Returns the maximum number of GPIO pins 256239281Sgonzo * @dev: gpio device handle 257239281Sgonzo * @maxpin: pointer to a value that upon return will contain the maximum number 258239281Sgonzo * of pins in the device. 259239281Sgonzo * 260239281Sgonzo * 261239281Sgonzo * LOCKING: 262239281Sgonzo * Internally locks the context 263239281Sgonzo * 264239281Sgonzo * RETURNS: 265239281Sgonzo * Returns 0 on success otherwise an error code 266239281Sgonzo */ 267239281Sgonzostatic int 268239281Sgonzoti_gpio_pin_max(device_t dev, int *maxpin) 269239281Sgonzo{ 270239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 271239281Sgonzo unsigned int i; 272239281Sgonzo unsigned int banks = 0; 273239281Sgonzo 274239281Sgonzo TI_GPIO_LOCK(sc); 275239281Sgonzo 276239281Sgonzo /* Calculate how many valid banks we have and then multiply that by 32 to 277239281Sgonzo * give use the total number of pins. 278239281Sgonzo */ 279239281Sgonzo for (i = 0; i < MAX_GPIO_BANKS; i++) { 280239281Sgonzo if (sc->sc_mem_res[i] != NULL) 281239281Sgonzo banks++; 282239281Sgonzo } 283239281Sgonzo 284247252Sgonzo *maxpin = (banks * PINS_PER_BANK) - 1; 285239281Sgonzo 286239281Sgonzo TI_GPIO_UNLOCK(sc); 287239281Sgonzo 288239281Sgonzo return (0); 289239281Sgonzo} 290239281Sgonzo 291239281Sgonzo/** 292239281Sgonzo * ti_gpio_pin_getcaps - Gets the capabilties of a given pin 293239281Sgonzo * @dev: gpio device handle 294239281Sgonzo * @pin: the number of the pin 295239281Sgonzo * @caps: pointer to a value that upon return will contain the capabilities 296239281Sgonzo * 297239281Sgonzo * Currently all pins have the same capability, notably: 298239281Sgonzo * - GPIO_PIN_INPUT 299239281Sgonzo * - GPIO_PIN_OUTPUT 300239281Sgonzo * - GPIO_PIN_PULLUP 301239281Sgonzo * - GPIO_PIN_PULLDOWN 302239281Sgonzo * 303239281Sgonzo * LOCKING: 304239281Sgonzo * Internally locks the context 305239281Sgonzo * 306239281Sgonzo * RETURNS: 307239281Sgonzo * Returns 0 on success otherwise an error code 308239281Sgonzo */ 309239281Sgonzostatic int 310239281Sgonzoti_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 311239281Sgonzo{ 312239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 313239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 314239281Sgonzo 315239281Sgonzo TI_GPIO_LOCK(sc); 316239281Sgonzo 317239281Sgonzo /* Sanity check the pin number is valid */ 318239281Sgonzo if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 319239281Sgonzo TI_GPIO_UNLOCK(sc); 320239281Sgonzo return (EINVAL); 321239281Sgonzo } 322239281Sgonzo 323239281Sgonzo *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |GPIO_PIN_PULLUP | 324239281Sgonzo GPIO_PIN_PULLDOWN); 325239281Sgonzo 326239281Sgonzo TI_GPIO_UNLOCK(sc); 327239281Sgonzo 328239281Sgonzo return (0); 329239281Sgonzo} 330239281Sgonzo 331239281Sgonzo/** 332239281Sgonzo * ti_gpio_pin_getflags - Gets the current flags of a given pin 333239281Sgonzo * @dev: gpio device handle 334239281Sgonzo * @pin: the number of the pin 335239281Sgonzo * @flags: upon return will contain the current flags of the pin 336239281Sgonzo * 337239281Sgonzo * Reads the current flags of a given pin, here we actually read the H/W 338239281Sgonzo * registers to determine the flags, rather than storing the value in the 339239281Sgonzo * setflags call. 340239281Sgonzo * 341239281Sgonzo * LOCKING: 342239281Sgonzo * Internally locks the context 343239281Sgonzo * 344239281Sgonzo * RETURNS: 345239281Sgonzo * Returns 0 on success otherwise an error code 346239281Sgonzo */ 347239281Sgonzostatic int 348239281Sgonzoti_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 349239281Sgonzo{ 350239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 351239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 352239281Sgonzo 353239281Sgonzo TI_GPIO_LOCK(sc); 354239281Sgonzo 355239281Sgonzo /* Sanity check the pin number is valid */ 356239281Sgonzo if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 357239281Sgonzo TI_GPIO_UNLOCK(sc); 358239281Sgonzo return (EINVAL); 359239281Sgonzo } 360239281Sgonzo 361239281Sgonzo /* Get the current pin state */ 362239281Sgonzo ti_scm_padconf_get_gpioflags(pin, flags); 363239281Sgonzo 364239281Sgonzo TI_GPIO_UNLOCK(sc); 365239281Sgonzo 366239281Sgonzo return (0); 367239281Sgonzo} 368239281Sgonzo 369239281Sgonzo/** 370239281Sgonzo * ti_gpio_pin_getname - Gets the name of a given pin 371239281Sgonzo * @dev: gpio device handle 372239281Sgonzo * @pin: the number of the pin 373239281Sgonzo * @name: buffer to put the name in 374239281Sgonzo * 375239281Sgonzo * The driver simply calls the pins gpio_n, where 'n' is obviously the number 376239281Sgonzo * of the pin. 377239281Sgonzo * 378239281Sgonzo * LOCKING: 379239281Sgonzo * Internally locks the context 380239281Sgonzo * 381239281Sgonzo * RETURNS: 382239281Sgonzo * Returns 0 on success otherwise an error code 383239281Sgonzo */ 384239281Sgonzostatic int 385239281Sgonzoti_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 386239281Sgonzo{ 387239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 388239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 389239281Sgonzo 390239281Sgonzo TI_GPIO_LOCK(sc); 391239281Sgonzo 392239281Sgonzo /* Sanity check the pin number is valid */ 393239281Sgonzo if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 394239281Sgonzo TI_GPIO_UNLOCK(sc); 395239281Sgonzo return (EINVAL); 396239281Sgonzo } 397239281Sgonzo 398239281Sgonzo /* Set a very simple name */ 399239281Sgonzo snprintf(name, GPIOMAXNAME, "gpio_%u", pin); 400239281Sgonzo name[GPIOMAXNAME - 1] = '\0'; 401239281Sgonzo 402239281Sgonzo TI_GPIO_UNLOCK(sc); 403239281Sgonzo 404239281Sgonzo return (0); 405239281Sgonzo} 406239281Sgonzo 407239281Sgonzo/** 408239281Sgonzo * ti_gpio_pin_setflags - Sets the flags for a given pin 409239281Sgonzo * @dev: gpio device handle 410239281Sgonzo * @pin: the number of the pin 411239281Sgonzo * @flags: the flags to set 412239281Sgonzo * 413239281Sgonzo * The flags of the pin correspond to things like input/output mode, pull-ups, 414239281Sgonzo * pull-downs, etc. This driver doesn't support all flags, only the following: 415239281Sgonzo * - GPIO_PIN_INPUT 416239281Sgonzo * - GPIO_PIN_OUTPUT 417239281Sgonzo * - GPIO_PIN_PULLUP 418239281Sgonzo * - GPIO_PIN_PULLDOWN 419239281Sgonzo * 420239281Sgonzo * LOCKING: 421239281Sgonzo * Internally locks the context 422239281Sgonzo * 423239281Sgonzo * RETURNS: 424239281Sgonzo * Returns 0 on success otherwise an error code 425239281Sgonzo */ 426239281Sgonzostatic int 427239281Sgonzoti_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 428239281Sgonzo{ 429239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 430239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 431239281Sgonzo uint32_t mask = (1UL << (pin % PINS_PER_BANK)); 432239281Sgonzo uint32_t reg_val; 433239281Sgonzo 434239281Sgonzo /* Sanity check the flags supplied are valid, i.e. not input and output */ 435239281Sgonzo if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 0x0000) 436239281Sgonzo return (EINVAL); 437239281Sgonzo if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 438239281Sgonzo (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) 439239281Sgonzo return (EINVAL); 440239281Sgonzo if ((flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) == 441239281Sgonzo (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) 442239281Sgonzo return (EINVAL); 443239281Sgonzo 444239281Sgonzo 445239281Sgonzo TI_GPIO_LOCK(sc); 446239281Sgonzo 447239281Sgonzo /* Sanity check the pin number is valid */ 448239281Sgonzo if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 449239281Sgonzo TI_GPIO_UNLOCK(sc); 450239281Sgonzo return (EINVAL); 451239281Sgonzo } 452239281Sgonzo 453239281Sgonzo /* Set the GPIO mode and state */ 454239281Sgonzo if (ti_scm_padconf_set_gpioflags(pin, flags) != 0) { 455239281Sgonzo TI_GPIO_UNLOCK(sc); 456239281Sgonzo return (EINVAL); 457239281Sgonzo } 458239281Sgonzo 459239281Sgonzo /* If configuring as an output set the "output enable" bit */ 460239281Sgonzo reg_val = ti_gpio_read_4(sc, bank, TI_GPIO_OE); 461239281Sgonzo if (flags & GPIO_PIN_INPUT) 462239281Sgonzo reg_val |= mask; 463239281Sgonzo else 464239281Sgonzo reg_val &= ~mask; 465239281Sgonzo ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_val); 466239281Sgonzo 467239281Sgonzo 468239281Sgonzo TI_GPIO_UNLOCK(sc); 469239281Sgonzo 470239281Sgonzo return (0); 471239281Sgonzo} 472239281Sgonzo 473239281Sgonzo/** 474239281Sgonzo * ti_gpio_pin_set - Sets the current level on a GPIO pin 475239281Sgonzo * @dev: gpio device handle 476239281Sgonzo * @pin: the number of the pin 477239281Sgonzo * @value: non-zero value will drive the pin high, otherwise the pin is 478239281Sgonzo * driven low. 479239281Sgonzo * 480239281Sgonzo * 481239281Sgonzo * LOCKING: 482239281Sgonzo * Internally locks the context 483239281Sgonzo * 484239281Sgonzo * RETURNS: 485239281Sgonzo * Returns 0 on success otherwise a error code 486239281Sgonzo */ 487239281Sgonzostatic int 488239281Sgonzoti_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 489239281Sgonzo{ 490239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 491239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 492239281Sgonzo uint32_t mask = (1UL << (pin % PINS_PER_BANK)); 493239281Sgonzo 494239281Sgonzo TI_GPIO_LOCK(sc); 495239281Sgonzo 496239281Sgonzo /* Sanity check the pin number is valid */ 497239281Sgonzo if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 498239281Sgonzo TI_GPIO_UNLOCK(sc); 499239281Sgonzo return (EINVAL); 500239281Sgonzo } 501239281Sgonzo 502239281Sgonzo ti_gpio_write_4(sc, bank, (value == GPIO_PIN_LOW) ? TI_GPIO_CLEARDATAOUT 503239281Sgonzo : TI_GPIO_SETDATAOUT, mask); 504239281Sgonzo 505239281Sgonzo TI_GPIO_UNLOCK(sc); 506239281Sgonzo 507239281Sgonzo return (0); 508239281Sgonzo} 509239281Sgonzo 510239281Sgonzo/** 511239281Sgonzo * ti_gpio_pin_get - Gets the current level on a GPIO pin 512239281Sgonzo * @dev: gpio device handle 513239281Sgonzo * @pin: the number of the pin 514239281Sgonzo * @value: pointer to a value that upond return will contain the pin value 515239281Sgonzo * 516239281Sgonzo * The pin must be configured as an input pin beforehand, otherwise this 517239281Sgonzo * function will fail. 518239281Sgonzo * 519239281Sgonzo * LOCKING: 520239281Sgonzo * Internally locks the context 521239281Sgonzo * 522239281Sgonzo * RETURNS: 523239281Sgonzo * Returns 0 on success otherwise a error code 524239281Sgonzo */ 525239281Sgonzostatic int 526239281Sgonzoti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) 527239281Sgonzo{ 528239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 529239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 530239281Sgonzo uint32_t mask = (1UL << (pin % PINS_PER_BANK)); 531239281Sgonzo uint32_t val = 0; 532239281Sgonzo 533239281Sgonzo TI_GPIO_LOCK(sc); 534239281Sgonzo 535239281Sgonzo /* Sanity check the pin number is valid */ 536239281Sgonzo if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 537239281Sgonzo TI_GPIO_UNLOCK(sc); 538239281Sgonzo return (EINVAL); 539239281Sgonzo } 540239281Sgonzo 541239281Sgonzo /* Sanity check the pin is not configured as an output */ 542239281Sgonzo val = ti_gpio_read_4(sc, bank, TI_GPIO_OE); 543239281Sgonzo 544239281Sgonzo /* Read the value on the pin */ 545247252Sgonzo if (val & mask) 546247252Sgonzo *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT) & mask) ? 1 : 0; 547247252Sgonzo else 548247252Sgonzo *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAIN) & mask) ? 1 : 0; 549239281Sgonzo 550239281Sgonzo TI_GPIO_UNLOCK(sc); 551239281Sgonzo 552239281Sgonzo return (0); 553239281Sgonzo} 554239281Sgonzo 555239281Sgonzo/** 556239281Sgonzo * ti_gpio_pin_toggle - Toggles a given GPIO pin 557239281Sgonzo * @dev: gpio device handle 558239281Sgonzo * @pin: the number of the pin 559239281Sgonzo * 560239281Sgonzo * 561239281Sgonzo * LOCKING: 562239281Sgonzo * Internally locks the context 563239281Sgonzo * 564239281Sgonzo * RETURNS: 565239281Sgonzo * Returns 0 on success otherwise a error code 566239281Sgonzo */ 567239281Sgonzostatic int 568239281Sgonzoti_gpio_pin_toggle(device_t dev, uint32_t pin) 569239281Sgonzo{ 570239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 571239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 572239281Sgonzo uint32_t mask = (1UL << (pin % PINS_PER_BANK)); 573239281Sgonzo uint32_t val; 574239281Sgonzo 575239281Sgonzo TI_GPIO_LOCK(sc); 576239281Sgonzo 577239281Sgonzo /* Sanity check the pin number is valid */ 578239281Sgonzo if ((bank > MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 579239281Sgonzo TI_GPIO_UNLOCK(sc); 580239281Sgonzo return (EINVAL); 581239281Sgonzo } 582239281Sgonzo 583239281Sgonzo /* Toggle the pin */ 584239281Sgonzo val = ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT); 585239281Sgonzo if (val & mask) 586239281Sgonzo ti_gpio_write_4(sc, bank, TI_GPIO_CLEARDATAOUT, mask); 587239281Sgonzo else 588239281Sgonzo ti_gpio_write_4(sc, bank, TI_GPIO_SETDATAOUT, mask); 589239281Sgonzo 590239281Sgonzo TI_GPIO_UNLOCK(sc); 591239281Sgonzo 592239281Sgonzo return (0); 593239281Sgonzo} 594239281Sgonzo 595239281Sgonzo/** 596239281Sgonzo * ti_gpio_intr - ISR for all GPIO modules 597239281Sgonzo * @arg: the soft context pointer 598239281Sgonzo * 599239281Sgonzo * Unsused 600239281Sgonzo * 601239281Sgonzo * LOCKING: 602239281Sgonzo * Internally locks the context 603239281Sgonzo * 604239281Sgonzo */ 605239281Sgonzostatic void 606239281Sgonzoti_gpio_intr(void *arg) 607239281Sgonzo{ 608239281Sgonzo struct ti_gpio_softc *sc = arg; 609239281Sgonzo 610239281Sgonzo TI_GPIO_LOCK(sc); 611239281Sgonzo /* TODO: something useful */ 612239281Sgonzo TI_GPIO_UNLOCK(sc); 613239281Sgonzo} 614239281Sgonzo 615239281Sgonzo/** 616239281Sgonzo * ti_gpio_probe - probe function for the driver 617239281Sgonzo * @dev: gpio device handle 618239281Sgonzo * 619239281Sgonzo * Simply sets the name of the driver 620239281Sgonzo * 621239281Sgonzo * LOCKING: 622239281Sgonzo * None 623239281Sgonzo * 624239281Sgonzo * RETURNS: 625239281Sgonzo * Always returns 0 626239281Sgonzo */ 627239281Sgonzostatic int 628239281Sgonzoti_gpio_probe(device_t dev) 629239281Sgonzo{ 630239281Sgonzo if (!ofw_bus_is_compatible(dev, "ti,gpio")) 631239281Sgonzo return (ENXIO); 632239281Sgonzo 633239281Sgonzo device_set_desc(dev, "TI General Purpose I/O (GPIO)"); 634239281Sgonzo return (0); 635239281Sgonzo} 636239281Sgonzo 637239281Sgonzo/** 638239281Sgonzo * ti_gpio_attach - attach function for the driver 639239281Sgonzo * @dev: gpio device handle 640239281Sgonzo * 641239281Sgonzo * Allocates and sets up the driver context for all GPIO banks. This function 642239281Sgonzo * expects the memory ranges and IRQs to already be allocated to the driver. 643239281Sgonzo * 644239281Sgonzo * LOCKING: 645239281Sgonzo * None 646239281Sgonzo * 647239281Sgonzo * RETURNS: 648239281Sgonzo * Always returns 0 649239281Sgonzo */ 650239281Sgonzostatic int 651239281Sgonzoti_gpio_attach(device_t dev) 652239281Sgonzo{ 653239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 654239281Sgonzo unsigned int i; 655239281Sgonzo int err = 0; 656239281Sgonzo 657239281Sgonzo sc->sc_dev = dev; 658239281Sgonzo 659239281Sgonzo TI_GPIO_LOCK_INIT(sc); 660239281Sgonzo 661239281Sgonzo 662239281Sgonzo /* There are up to 6 different GPIO register sets located in different 663239281Sgonzo * memory areas on the chip. The memory range should have been set for 664239281Sgonzo * the driver when it was added as a child. 665239281Sgonzo */ 666239281Sgonzo err = bus_alloc_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res); 667239281Sgonzo if (err) { 668239281Sgonzo device_printf(dev, "Error: could not allocate mem resources\n"); 669239281Sgonzo return (ENXIO); 670239281Sgonzo } 671239281Sgonzo 672239281Sgonzo /* Request the IRQ resources */ 673239281Sgonzo err = bus_alloc_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res); 674239281Sgonzo if (err) { 675239281Sgonzo device_printf(dev, "Error: could not allocate irq resources\n"); 676239281Sgonzo return (ENXIO); 677239281Sgonzo } 678239281Sgonzo 679239281Sgonzo /* Setup the IRQ resources */ 680239281Sgonzo for (i = 0; i < MAX_GPIO_BANKS; i++) { 681239281Sgonzo if (sc->sc_irq_res[i] == NULL) 682239281Sgonzo break; 683239281Sgonzo 684239281Sgonzo /* Register an interrupt handler for each of the IRQ resources */ 685239281Sgonzo if ((bus_setup_intr(dev, sc->sc_irq_res[i], INTR_TYPE_MISC | INTR_MPSAFE, 686239281Sgonzo NULL, ti_gpio_intr, sc, &(sc->sc_irq_hdl[i])))) { 687239281Sgonzo device_printf(dev, "WARNING: unable to register interrupt handler\n"); 688239281Sgonzo return (ENXIO); 689239281Sgonzo } 690239281Sgonzo } 691239281Sgonzo 692239281Sgonzo /* Store the device handle back in the sc */ 693239281Sgonzo sc->sc_dev = dev; 694239281Sgonzo 695239281Sgonzo /* We need to go through each block and ensure the clocks are running and 696239281Sgonzo * the module is enabled. It might be better to do this only when the 697239281Sgonzo * pins are configured which would result in less power used if the GPIO 698239281Sgonzo * pins weren't used ... 699239281Sgonzo */ 700239281Sgonzo for (i = 0; i < MAX_GPIO_BANKS; i++) { 701239281Sgonzo if (sc->sc_mem_res[i] != NULL) { 702239281Sgonzo 703239281Sgonzo /* Enable the interface and functional clocks for the module */ 704239281Sgonzo ti_prcm_clk_enable(GPIO0_CLK + FIRST_GPIO_BANK + i); 705239281Sgonzo 706239281Sgonzo /* Read the revision number of the module. TI don't publish the 707239281Sgonzo * actual revision numbers, so instead the values have been 708239281Sgonzo * determined by experimentation. 709239281Sgonzo */ 710239281Sgonzo sc->sc_revision[i] = ti_gpio_read_4(sc, i, TI_GPIO_REVISION); 711239281Sgonzo 712239281Sgonzo /* Check the revision */ 713239281Sgonzo if (sc->sc_revision[i] != TI_GPIO_REV) { 714239281Sgonzo device_printf(dev, "Warning: could not determine the revision" 715239281Sgonzo "of %u GPIO module (revision:0x%08x)\n", 716239281Sgonzo i, sc->sc_revision[i]); 717239281Sgonzo continue; 718239281Sgonzo } 719239281Sgonzo 720239281Sgonzo /* Disable interrupts for all pins */ 721239281Sgonzo ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE1, 0xffffffff); 722239281Sgonzo ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE2, 0xffffffff); 723239281Sgonzo } 724239281Sgonzo } 725239281Sgonzo 726239281Sgonzo /* Finish of the probe call */ 727239281Sgonzo device_add_child(dev, "gpioc", device_get_unit(dev)); 728239281Sgonzo device_add_child(dev, "gpiobus", device_get_unit(dev)); 729247252Sgonzo 730239281Sgonzo return (bus_generic_attach(dev)); 731239281Sgonzo} 732239281Sgonzo 733239281Sgonzo/** 734239281Sgonzo * ti_gpio_detach - detach function for the driver 735239281Sgonzo * @dev: scm device handle 736239281Sgonzo * 737239281Sgonzo * Allocates and sets up the driver context, this simply entails creating a 738239281Sgonzo * bus mappings for the SCM register set. 739239281Sgonzo * 740239281Sgonzo * LOCKING: 741239281Sgonzo * None 742239281Sgonzo * 743239281Sgonzo * RETURNS: 744239281Sgonzo * Always returns 0 745239281Sgonzo */ 746239281Sgonzostatic int 747239281Sgonzoti_gpio_detach(device_t dev) 748239281Sgonzo{ 749239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 750239281Sgonzo unsigned int i; 751239281Sgonzo 752239281Sgonzo KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized")); 753239281Sgonzo 754239281Sgonzo /* Disable all interrupts */ 755239281Sgonzo for (i = 0; i < MAX_GPIO_BANKS; i++) { 756239281Sgonzo if (sc->sc_mem_res[i] != NULL) { 757239281Sgonzo ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE1, 0xffffffff); 758239281Sgonzo ti_gpio_write_4(sc, i, TI_GPIO_CLEARIRQENABLE2, 0xffffffff); 759239281Sgonzo } 760239281Sgonzo } 761239281Sgonzo 762239281Sgonzo bus_generic_detach(dev); 763239281Sgonzo 764239281Sgonzo /* Release the memory and IRQ resources */ 765239281Sgonzo for (i = 0; i < MAX_GPIO_BANKS; i++) { 766239281Sgonzo if (sc->sc_mem_res[i] != NULL) 767239281Sgonzo bus_release_resource(dev, SYS_RES_MEMORY, i, sc->sc_mem_res[i]); 768239281Sgonzo if (sc->sc_irq_res[i] != NULL) 769239281Sgonzo bus_release_resource(dev, SYS_RES_IRQ, i, sc->sc_irq_res[i]); 770239281Sgonzo } 771239281Sgonzo 772239281Sgonzo TI_GPIO_LOCK_DESTROY(sc); 773239281Sgonzo 774239281Sgonzo return(0); 775239281Sgonzo} 776239281Sgonzo 777239281Sgonzostatic device_method_t ti_gpio_methods[] = { 778239281Sgonzo DEVMETHOD(device_probe, ti_gpio_probe), 779239281Sgonzo DEVMETHOD(device_attach, ti_gpio_attach), 780239281Sgonzo DEVMETHOD(device_detach, ti_gpio_detach), 781239281Sgonzo 782239281Sgonzo /* GPIO protocol */ 783239281Sgonzo DEVMETHOD(gpio_pin_max, ti_gpio_pin_max), 784239281Sgonzo DEVMETHOD(gpio_pin_getname, ti_gpio_pin_getname), 785239281Sgonzo DEVMETHOD(gpio_pin_getflags, ti_gpio_pin_getflags), 786239281Sgonzo DEVMETHOD(gpio_pin_getcaps, ti_gpio_pin_getcaps), 787239281Sgonzo DEVMETHOD(gpio_pin_setflags, ti_gpio_pin_setflags), 788239281Sgonzo DEVMETHOD(gpio_pin_get, ti_gpio_pin_get), 789239281Sgonzo DEVMETHOD(gpio_pin_set, ti_gpio_pin_set), 790239281Sgonzo DEVMETHOD(gpio_pin_toggle, ti_gpio_pin_toggle), 791239281Sgonzo {0, 0}, 792239281Sgonzo}; 793239281Sgonzo 794239281Sgonzostatic driver_t ti_gpio_driver = { 795239281Sgonzo "gpio", 796239281Sgonzo ti_gpio_methods, 797239281Sgonzo sizeof(struct ti_gpio_softc), 798239281Sgonzo}; 799239281Sgonzostatic devclass_t ti_gpio_devclass; 800239281Sgonzo 801239281SgonzoDRIVER_MODULE(ti_gpio, simplebus, ti_gpio_driver, ti_gpio_devclass, 0, 0); 802