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$"); 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 TI_GPIO_LOCK(sc); 460239281Sgonzo 461239281Sgonzo /* Sanity check the pin number is valid */ 462247259Sgonzo if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 463239281Sgonzo TI_GPIO_UNLOCK(sc); 464239281Sgonzo return (EINVAL); 465239281Sgonzo } 466239281Sgonzo 467239281Sgonzo /* Set the GPIO mode and state */ 468239281Sgonzo if (ti_scm_padconf_set_gpioflags(pin, flags) != 0) { 469239281Sgonzo TI_GPIO_UNLOCK(sc); 470239281Sgonzo return (EINVAL); 471239281Sgonzo } 472239281Sgonzo 473239281Sgonzo /* If configuring as an output set the "output enable" bit */ 474239281Sgonzo reg_val = ti_gpio_read_4(sc, bank, TI_GPIO_OE); 475239281Sgonzo if (flags & GPIO_PIN_INPUT) 476239281Sgonzo reg_val |= mask; 477239281Sgonzo else 478239281Sgonzo reg_val &= ~mask; 479239281Sgonzo ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_val); 480239281Sgonzo 481239281Sgonzo TI_GPIO_UNLOCK(sc); 482239281Sgonzo 483239281Sgonzo return (0); 484239281Sgonzo} 485239281Sgonzo 486239281Sgonzo/** 487239281Sgonzo * ti_gpio_pin_set - Sets the current level on a GPIO pin 488239281Sgonzo * @dev: gpio device handle 489239281Sgonzo * @pin: the number of the pin 490239281Sgonzo * @value: non-zero value will drive the pin high, otherwise the pin is 491239281Sgonzo * driven low. 492239281Sgonzo * 493239281Sgonzo * 494239281Sgonzo * LOCKING: 495239281Sgonzo * Internally locks the context 496239281Sgonzo * 497239281Sgonzo * RETURNS: 498239281Sgonzo * Returns 0 on success otherwise a error code 499239281Sgonzo */ 500239281Sgonzostatic int 501239281Sgonzoti_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 502239281Sgonzo{ 503239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 504239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 505239281Sgonzo uint32_t mask = (1UL << (pin % PINS_PER_BANK)); 506239281Sgonzo 507239281Sgonzo TI_GPIO_LOCK(sc); 508239281Sgonzo 509239281Sgonzo /* Sanity check the pin number is valid */ 510247259Sgonzo if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 511239281Sgonzo TI_GPIO_UNLOCK(sc); 512239281Sgonzo return (EINVAL); 513239281Sgonzo } 514239281Sgonzo 515239281Sgonzo ti_gpio_write_4(sc, bank, (value == GPIO_PIN_LOW) ? TI_GPIO_CLEARDATAOUT 516239281Sgonzo : TI_GPIO_SETDATAOUT, mask); 517239281Sgonzo 518239281Sgonzo TI_GPIO_UNLOCK(sc); 519239281Sgonzo 520239281Sgonzo return (0); 521239281Sgonzo} 522239281Sgonzo 523239281Sgonzo/** 524239281Sgonzo * ti_gpio_pin_get - Gets the current level on a GPIO pin 525239281Sgonzo * @dev: gpio device handle 526239281Sgonzo * @pin: the number of the pin 527239281Sgonzo * @value: pointer to a value that upond return will contain the pin value 528239281Sgonzo * 529239281Sgonzo * The pin must be configured as an input pin beforehand, otherwise this 530239281Sgonzo * function will fail. 531239281Sgonzo * 532239281Sgonzo * LOCKING: 533239281Sgonzo * Internally locks the context 534239281Sgonzo * 535239281Sgonzo * RETURNS: 536239281Sgonzo * Returns 0 on success otherwise a error code 537239281Sgonzo */ 538239281Sgonzostatic int 539239281Sgonzoti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) 540239281Sgonzo{ 541239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 542239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 543239281Sgonzo uint32_t mask = (1UL << (pin % PINS_PER_BANK)); 544239281Sgonzo uint32_t val = 0; 545239281Sgonzo 546239281Sgonzo TI_GPIO_LOCK(sc); 547239281Sgonzo 548239281Sgonzo /* Sanity check the pin number is valid */ 549247259Sgonzo if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 550239281Sgonzo TI_GPIO_UNLOCK(sc); 551239281Sgonzo return (EINVAL); 552239281Sgonzo } 553239281Sgonzo 554239281Sgonzo /* Sanity check the pin is not configured as an output */ 555239281Sgonzo val = ti_gpio_read_4(sc, bank, TI_GPIO_OE); 556239281Sgonzo 557239281Sgonzo /* Read the value on the pin */ 558247252Sgonzo if (val & mask) 559266105Sloos *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAIN) & mask) ? 1 : 0; 560266105Sloos else 561247252Sgonzo *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT) & mask) ? 1 : 0; 562239281Sgonzo 563239281Sgonzo TI_GPIO_UNLOCK(sc); 564239281Sgonzo 565239281Sgonzo return (0); 566239281Sgonzo} 567239281Sgonzo 568239281Sgonzo/** 569239281Sgonzo * ti_gpio_pin_toggle - Toggles a given GPIO pin 570239281Sgonzo * @dev: gpio device handle 571239281Sgonzo * @pin: the number of the pin 572239281Sgonzo * 573239281Sgonzo * 574239281Sgonzo * LOCKING: 575239281Sgonzo * Internally locks the context 576239281Sgonzo * 577239281Sgonzo * RETURNS: 578239281Sgonzo * Returns 0 on success otherwise a error code 579239281Sgonzo */ 580239281Sgonzostatic int 581239281Sgonzoti_gpio_pin_toggle(device_t dev, uint32_t pin) 582239281Sgonzo{ 583239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 584239281Sgonzo uint32_t bank = (pin / PINS_PER_BANK); 585239281Sgonzo uint32_t mask = (1UL << (pin % PINS_PER_BANK)); 586239281Sgonzo uint32_t val; 587239281Sgonzo 588239281Sgonzo TI_GPIO_LOCK(sc); 589239281Sgonzo 590239281Sgonzo /* Sanity check the pin number is valid */ 591247259Sgonzo if ((bank >= MAX_GPIO_BANKS) || (sc->sc_mem_res[bank] == NULL)) { 592239281Sgonzo TI_GPIO_UNLOCK(sc); 593239281Sgonzo return (EINVAL); 594239281Sgonzo } 595239281Sgonzo 596239281Sgonzo /* Toggle the pin */ 597239281Sgonzo val = ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT); 598239281Sgonzo if (val & mask) 599239281Sgonzo ti_gpio_write_4(sc, bank, TI_GPIO_CLEARDATAOUT, mask); 600239281Sgonzo else 601239281Sgonzo ti_gpio_write_4(sc, bank, TI_GPIO_SETDATAOUT, mask); 602239281Sgonzo 603239281Sgonzo TI_GPIO_UNLOCK(sc); 604239281Sgonzo 605239281Sgonzo return (0); 606239281Sgonzo} 607239281Sgonzo 608239281Sgonzo/** 609239281Sgonzo * ti_gpio_intr - ISR for all GPIO modules 610239281Sgonzo * @arg: the soft context pointer 611239281Sgonzo * 612239281Sgonzo * Unsused 613239281Sgonzo * 614239281Sgonzo * LOCKING: 615239281Sgonzo * Internally locks the context 616239281Sgonzo * 617239281Sgonzo */ 618239281Sgonzostatic void 619239281Sgonzoti_gpio_intr(void *arg) 620239281Sgonzo{ 621239281Sgonzo struct ti_gpio_softc *sc = arg; 622239281Sgonzo 623239281Sgonzo TI_GPIO_LOCK(sc); 624239281Sgonzo /* TODO: something useful */ 625239281Sgonzo TI_GPIO_UNLOCK(sc); 626239281Sgonzo} 627239281Sgonzo 628239281Sgonzo/** 629239281Sgonzo * ti_gpio_probe - probe function for the driver 630239281Sgonzo * @dev: gpio device handle 631239281Sgonzo * 632239281Sgonzo * Simply sets the name of the driver 633239281Sgonzo * 634239281Sgonzo * LOCKING: 635239281Sgonzo * None 636239281Sgonzo * 637239281Sgonzo * RETURNS: 638239281Sgonzo * Always returns 0 639239281Sgonzo */ 640239281Sgonzostatic int 641239281Sgonzoti_gpio_probe(device_t dev) 642239281Sgonzo{ 643266152Sian 644266152Sian if (!ofw_bus_status_okay(dev)) 645266152Sian return (ENXIO); 646266152Sian 647239281Sgonzo if (!ofw_bus_is_compatible(dev, "ti,gpio")) 648239281Sgonzo return (ENXIO); 649239281Sgonzo 650239281Sgonzo device_set_desc(dev, "TI General Purpose I/O (GPIO)"); 651266148Sloos 652239281Sgonzo return (0); 653239281Sgonzo} 654239281Sgonzo 655266148Sloosstatic int 656266148Sloosti_gpio_attach_intr(device_t dev) 657266148Sloos{ 658266148Sloos int i; 659266148Sloos struct ti_gpio_softc *sc; 660266148Sloos 661266148Sloos sc = device_get_softc(dev); 662266148Sloos for (i = 0; i < MAX_GPIO_INTRS; i++) { 663266148Sloos if (sc->sc_irq_res[i] == NULL) 664266148Sloos break; 665266148Sloos 666266148Sloos /* 667266148Sloos * Register our interrupt handler for each of the IRQ resources. 668266148Sloos */ 669266148Sloos if (bus_setup_intr(dev, sc->sc_irq_res[i], 670266148Sloos INTR_TYPE_MISC | INTR_MPSAFE, NULL, ti_gpio_intr, sc, 671266148Sloos &sc->sc_irq_hdl[i]) != 0) { 672266148Sloos device_printf(dev, 673266148Sloos "WARNING: unable to register interrupt handler\n"); 674266148Sloos return (-1); 675266148Sloos } 676266148Sloos } 677266148Sloos 678266148Sloos return (0); 679266148Sloos} 680266148Sloos 681266148Sloosstatic int 682266148Sloosti_gpio_detach_intr(device_t dev) 683266148Sloos{ 684266148Sloos int i; 685266148Sloos struct ti_gpio_softc *sc; 686266148Sloos 687266148Sloos /* Teardown our interrupt handlers. */ 688266148Sloos sc = device_get_softc(dev); 689266148Sloos for (i = 0; i < MAX_GPIO_INTRS; i++) { 690266148Sloos if (sc->sc_irq_res[i] == NULL) 691266148Sloos break; 692266148Sloos 693266148Sloos if (sc->sc_irq_hdl[i]) { 694266148Sloos bus_teardown_intr(dev, sc->sc_irq_res[i], 695266148Sloos sc->sc_irq_hdl[i]); 696266148Sloos } 697266148Sloos } 698266148Sloos 699266148Sloos return (0); 700266148Sloos} 701266148Sloos 702266148Sloosstatic int 703266148Sloosti_gpio_bank_init(device_t dev, int bank) 704266148Sloos{ 705266148Sloos int pin; 706266148Sloos struct ti_gpio_softc *sc; 707266148Sloos uint32_t flags, reg_oe; 708266148Sloos 709266148Sloos sc = device_get_softc(dev); 710266148Sloos 711266148Sloos /* Enable the interface and functional clocks for the module. */ 712266148Sloos ti_prcm_clk_enable(GPIO0_CLK + FIRST_GPIO_BANK + bank); 713266148Sloos 714266148Sloos /* 715266148Sloos * Read the revision number of the module. TI don't publish the 716266148Sloos * actual revision numbers, so instead the values have been 717266148Sloos * determined by experimentation. 718266148Sloos */ 719266148Sloos sc->sc_revision[bank] = ti_gpio_read_4(sc, bank, TI_GPIO_REVISION); 720266148Sloos 721266148Sloos /* Check the revision. */ 722266148Sloos if (sc->sc_revision[bank] != TI_GPIO_REV) { 723266148Sloos device_printf(dev, "Warning: could not determine the revision " 724266148Sloos "of %u GPIO module (revision:0x%08x)\n", 725266148Sloos bank, sc->sc_revision[bank]); 726266148Sloos return (EINVAL); 727266148Sloos } 728266148Sloos 729266148Sloos /* Disable interrupts for all pins. */ 730266148Sloos ti_gpio_intr_clr(sc, bank, 0xffffffff); 731266148Sloos 732266148Sloos /* Init OE register based on pads configuration. */ 733266148Sloos reg_oe = 0xffffffff; 734266148Sloos for (pin = 0; pin < PINS_PER_BANK; pin++) { 735266148Sloos ti_scm_padconf_get_gpioflags(PINS_PER_BANK * bank + pin, 736266148Sloos &flags); 737266148Sloos if (flags & GPIO_PIN_OUTPUT) 738266148Sloos reg_oe &= ~(1UL << pin); 739266148Sloos } 740266148Sloos ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_oe); 741266148Sloos 742266148Sloos return (0); 743266148Sloos} 744266148Sloos 745239281Sgonzo/** 746239281Sgonzo * ti_gpio_attach - attach function for the driver 747239281Sgonzo * @dev: gpio device handle 748239281Sgonzo * 749239281Sgonzo * Allocates and sets up the driver context for all GPIO banks. This function 750239281Sgonzo * expects the memory ranges and IRQs to already be allocated to the driver. 751239281Sgonzo * 752239281Sgonzo * LOCKING: 753239281Sgonzo * None 754239281Sgonzo * 755239281Sgonzo * RETURNS: 756239281Sgonzo * Always returns 0 757239281Sgonzo */ 758239281Sgonzostatic int 759239281Sgonzoti_gpio_attach(device_t dev) 760239281Sgonzo{ 761266148Sloos struct ti_gpio_softc *sc; 762239281Sgonzo unsigned int i; 763266148Sloos int err; 764239281Sgonzo 765266148Sloos sc = device_get_softc(dev); 766239281Sgonzo sc->sc_dev = dev; 767239281Sgonzo 768239281Sgonzo TI_GPIO_LOCK_INIT(sc); 769239281Sgonzo 770239281Sgonzo /* There are up to 6 different GPIO register sets located in different 771239281Sgonzo * memory areas on the chip. The memory range should have been set for 772239281Sgonzo * the driver when it was added as a child. 773239281Sgonzo */ 774266148Sloos if (bus_alloc_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res) != 0) { 775239281Sgonzo device_printf(dev, "Error: could not allocate mem resources\n"); 776239281Sgonzo return (ENXIO); 777239281Sgonzo } 778239281Sgonzo 779239281Sgonzo /* Request the IRQ resources */ 780266148Sloos if (bus_alloc_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res) != 0) { 781266148Sloos bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res); 782239281Sgonzo device_printf(dev, "Error: could not allocate irq resources\n"); 783239281Sgonzo return (ENXIO); 784239281Sgonzo } 785239281Sgonzo 786239281Sgonzo /* Setup the IRQ resources */ 787266148Sloos if (ti_gpio_attach_intr(dev) != 0) { 788266148Sloos ti_gpio_detach_intr(dev); 789266148Sloos bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res); 790266148Sloos bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res); 791266148Sloos return (ENXIO); 792239281Sgonzo } 793239281Sgonzo 794239281Sgonzo /* We need to go through each block and ensure the clocks are running and 795239281Sgonzo * the module is enabled. It might be better to do this only when the 796239281Sgonzo * pins are configured which would result in less power used if the GPIO 797239281Sgonzo * pins weren't used ... 798239281Sgonzo */ 799266148Sloos for (i = 0; i < MAX_GPIO_BANKS; i++) { 800239281Sgonzo if (sc->sc_mem_res[i] != NULL) { 801266148Sloos /* Initialize the GPIO module. */ 802266148Sloos err = ti_gpio_bank_init(dev, i); 803266148Sloos if (err != 0) { 804266148Sloos ti_gpio_detach_intr(dev); 805266148Sloos bus_release_resources(dev, ti_gpio_irq_spec, 806266148Sloos sc->sc_irq_res); 807266148Sloos bus_release_resources(dev, ti_gpio_mem_spec, 808266148Sloos sc->sc_mem_res); 809266148Sloos return (err); 810239281Sgonzo } 811239281Sgonzo } 812239281Sgonzo } 813239281Sgonzo 814239281Sgonzo /* Finish of the probe call */ 815278782Sloos device_add_child(dev, "gpioc", -1); 816278782Sloos device_add_child(dev, "gpiobus", -1); 817247252Sgonzo 818239281Sgonzo return (bus_generic_attach(dev)); 819239281Sgonzo} 820239281Sgonzo 821239281Sgonzo/** 822239281Sgonzo * ti_gpio_detach - detach function for the driver 823239281Sgonzo * @dev: scm device handle 824239281Sgonzo * 825239281Sgonzo * Allocates and sets up the driver context, this simply entails creating a 826239281Sgonzo * bus mappings for the SCM register set. 827239281Sgonzo * 828239281Sgonzo * LOCKING: 829239281Sgonzo * None 830239281Sgonzo * 831239281Sgonzo * RETURNS: 832239281Sgonzo * Always returns 0 833239281Sgonzo */ 834239281Sgonzostatic int 835239281Sgonzoti_gpio_detach(device_t dev) 836239281Sgonzo{ 837239281Sgonzo struct ti_gpio_softc *sc = device_get_softc(dev); 838239281Sgonzo unsigned int i; 839239281Sgonzo 840239281Sgonzo KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized")); 841239281Sgonzo 842239281Sgonzo /* Disable all interrupts */ 843266148Sloos for (i = 0; i < MAX_GPIO_BANKS; i++) { 844266148Sloos if (sc->sc_mem_res[i] != NULL) 845266148Sloos ti_gpio_intr_clr(sc, i, 0xffffffff); 846239281Sgonzo } 847239281Sgonzo 848239281Sgonzo bus_generic_detach(dev); 849239281Sgonzo 850266148Sloos /* Release the memory and IRQ resources. */ 851266148Sloos ti_gpio_detach_intr(dev); 852266148Sloos bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res); 853266148Sloos bus_release_resources(dev, ti_gpio_mem_spec, sc->sc_mem_res); 854239281Sgonzo 855239281Sgonzo TI_GPIO_LOCK_DESTROY(sc); 856239281Sgonzo 857266148Sloos return (0); 858239281Sgonzo} 859239281Sgonzo 860266105Sloosstatic phandle_t 861266105Sloosti_gpio_get_node(device_t bus, device_t dev) 862266105Sloos{ 863266105Sloos 864266105Sloos /* We only have one child, the GPIO bus, which needs our own node. */ 865266105Sloos return (ofw_bus_get_node(bus)); 866266105Sloos} 867266105Sloos 868239281Sgonzostatic device_method_t ti_gpio_methods[] = { 869239281Sgonzo DEVMETHOD(device_probe, ti_gpio_probe), 870239281Sgonzo DEVMETHOD(device_attach, ti_gpio_attach), 871239281Sgonzo DEVMETHOD(device_detach, ti_gpio_detach), 872239281Sgonzo 873239281Sgonzo /* GPIO protocol */ 874239281Sgonzo DEVMETHOD(gpio_pin_max, ti_gpio_pin_max), 875239281Sgonzo DEVMETHOD(gpio_pin_getname, ti_gpio_pin_getname), 876239281Sgonzo DEVMETHOD(gpio_pin_getflags, ti_gpio_pin_getflags), 877239281Sgonzo DEVMETHOD(gpio_pin_getcaps, ti_gpio_pin_getcaps), 878239281Sgonzo DEVMETHOD(gpio_pin_setflags, ti_gpio_pin_setflags), 879239281Sgonzo DEVMETHOD(gpio_pin_get, ti_gpio_pin_get), 880239281Sgonzo DEVMETHOD(gpio_pin_set, ti_gpio_pin_set), 881239281Sgonzo DEVMETHOD(gpio_pin_toggle, ti_gpio_pin_toggle), 882266105Sloos 883266105Sloos /* ofw_bus interface */ 884266105Sloos DEVMETHOD(ofw_bus_get_node, ti_gpio_get_node), 885266105Sloos 886239281Sgonzo {0, 0}, 887239281Sgonzo}; 888239281Sgonzo 889239281Sgonzostatic driver_t ti_gpio_driver = { 890239281Sgonzo "gpio", 891239281Sgonzo ti_gpio_methods, 892239281Sgonzo sizeof(struct ti_gpio_softc), 893239281Sgonzo}; 894239281Sgonzostatic devclass_t ti_gpio_devclass; 895239281Sgonzo 896239281SgonzoDRIVER_MODULE(ti_gpio, simplebus, ti_gpio_driver, ti_gpio_devclass, 0, 0); 897