rt305x_gpio.c revision 278782
1273562Smarcel/*- 2273562Smarcel * Copyright (c) 2010-2011, Aleksandr Rybalko <ray@ddteam.net> 3273562Smarcel * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org> 4273562Smarcel * Copyright (c) 2009, Luiz Otavio O Souza. 5273562Smarcel * All rights reserved. 6273562Smarcel * 7273562Smarcel * Redistribution and use in source and binary forms, with or without 8273562Smarcel * modification, are permitted provided that the following conditions 9273562Smarcel * are met: 10273562Smarcel * 1. Redistributions of source code must retain the above copyright 11273562Smarcel * notice unmodified, this list of conditions, and the following 12273562Smarcel * disclaimer. 13273562Smarcel * 2. Redistributions in binary form must reproduce the above copyright 14273562Smarcel * notice, this list of conditions and the following disclaimer in the 15273562Smarcel * documentation and/or other materials provided with the distribution. 16273562Smarcel * 17273562Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18273562Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19273562Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20273562Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21273562Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22273562Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23273562Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24273562Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25273562Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26273562Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27273562Smarcel * SUCH DAMAGE. 28273562Smarcel */ 29273562Smarcel 30273562Smarcel/* 31274672Smarcel * GPIO driver for RT305X SoC. 32274672Smarcel */ 33274672Smarcel 34274672Smarcel#include <sys/cdefs.h> 35274672Smarcel__FBSDID("$FreeBSD: stable/10/sys/mips/rt305x/rt305x_gpio.c 278782 2015-02-14 20:37:33Z loos $"); 36274672Smarcel 37274672Smarcel#include <sys/param.h> 38274672Smarcel#include <sys/systm.h> 39274672Smarcel#include <sys/bus.h> 40274672Smarcel 41274672Smarcel#include <sys/kernel.h> 42274672Smarcel#include <sys/module.h> 43274672Smarcel#include <sys/rman.h> 44273562Smarcel#include <sys/lock.h> 45273562Smarcel#include <sys/mutex.h> 46273562Smarcel#include <sys/gpio.h> 47273562Smarcel 48273562Smarcel#include <machine/bus.h> 49273562Smarcel#include <machine/resource.h> 50273562Smarcel#include <mips/rt305x/rt305xreg.h> 51273562Smarcel#include <mips/rt305x/rt305x_gpio.h> 52273562Smarcel#include <mips/rt305x/rt305x_gpiovar.h> 53273562Smarcel#include <mips/rt305x/rt305x_sysctlvar.h> 54273562Smarcel 55273562Smarcel#include "gpio_if.h" 56273562Smarcel 57273562Smarcel#ifdef notyet 58273562Smarcel#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INVIN | \ 59273562Smarcel GPIO_PIN_INVOUT | GPIO_PIN_REPORT ) 60273562Smarcel#else 61273562Smarcel#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INVIN | \ 62273562Smarcel GPIO_PIN_INVOUT ) 63273562Smarcel#endif 64273562Smarcel 65273562Smarcel/* 66273562Smarcel * Helpers 67273562Smarcel */ 68273562Smarcelstatic void rt305x_gpio_pin_configure(struct rt305x_gpio_softc *sc, 69273562Smarcel struct gpio_pin *pin, uint32_t flags); 70273562Smarcel 71273562Smarcel/* 72273562Smarcel * Driver stuff 73273562Smarcel */ 74273562Smarcelstatic int rt305x_gpio_probe(device_t dev); 75273562Smarcelstatic int rt305x_gpio_attach(device_t dev); 76273562Smarcelstatic int rt305x_gpio_detach(device_t dev); 77273562Smarcelstatic int rt305x_gpio_intr(void *arg); 78273562Smarcel 79273562Smarcelint rt305x_get_int_mask (device_t); 80273562Smarcelvoid rt305x_set_int_mask (device_t, uint32_t); 81273562Smarcelint rt305x_get_int_status(device_t); 82273562Smarcelvoid rt305x_set_int_status(device_t, uint32_t); 83273562Smarcel 84273562Smarcel/* 85273562Smarcel * GPIO interface 86273562Smarcel */ 87273562Smarcelstatic int rt305x_gpio_pin_max(device_t dev, int *maxpin); 88273562Smarcelstatic int rt305x_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps); 89273562Smarcelstatic int rt305x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t 90273562Smarcel *flags); 91273562Smarcelstatic int rt305x_gpio_pin_getname(device_t dev, uint32_t pin, char *name); 92273562Smarcelstatic int rt305x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags); 93273562Smarcelstatic int rt305x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value); 94273562Smarcelstatic int rt305x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val); 95273562Smarcelstatic int rt305x_gpio_pin_toggle(device_t dev, uint32_t pin); 96273562Smarcel 97273562Smarcelstatic void 98273562Smarcelrt305x_gpio_pin_configure(struct rt305x_gpio_softc *sc, struct gpio_pin *pin, 99273562Smarcel unsigned int flags) 100273562Smarcel{ 101273562Smarcel GPIO_LOCK(sc); 102273562Smarcel 103273562Smarcel /* 104273562Smarcel * Manage input/output 105273562Smarcel */ 106273562Smarcel if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { 107273562Smarcel pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); 108273562Smarcel if (flags & GPIO_PIN_OUTPUT) { 109273562Smarcel pin->gp_flags |= GPIO_PIN_OUTPUT; 110273562Smarcel GPIO_BIT_SET(sc, pin->gp_pin, DIR); 111273562Smarcel } 112273562Smarcel else { 113273562Smarcel pin->gp_flags |= GPIO_PIN_INPUT; 114273562Smarcel GPIO_BIT_CLR(sc, pin->gp_pin, DIR); 115273562Smarcel } 116273562Smarcel } 117273562Smarcel 118273562Smarcel if (flags & GPIO_PIN_INVOUT) { 119273562Smarcel pin->gp_flags |= GPIO_PIN_INVOUT; 120273562Smarcel GPIO_BIT_SET(sc, pin->gp_pin, POL); 121273562Smarcel } 122273562Smarcel else { 123273562Smarcel pin->gp_flags &= ~GPIO_PIN_INVOUT; 124273562Smarcel GPIO_BIT_CLR(sc, pin->gp_pin, POL); 125273562Smarcel } 126273562Smarcel 127273562Smarcel if (flags & GPIO_PIN_INVIN) { 128273562Smarcel pin->gp_flags |= GPIO_PIN_INVIN; 129273562Smarcel GPIO_BIT_SET(sc, pin->gp_pin, POL); 130273562Smarcel } 131273562Smarcel else { 132273562Smarcel pin->gp_flags &= ~GPIO_PIN_INVIN; 133273562Smarcel GPIO_BIT_CLR(sc, pin->gp_pin, POL); 134273562Smarcel } 135273562Smarcel 136273562Smarcel#ifdef notyet 137273562Smarcel /* Enable interrupt bits for rising/falling transitions */ 138273562Smarcel if (flags & GPIO_PIN_REPORT) { 139273562Smarcel pin->gp_flags |= GPIO_PIN_REPORT; 140273562Smarcel GPIO_BIT_SET(sc, pin->gp_pin, RENA); 141273562Smarcel GPIO_BIT_SET(sc, pin->gp_pin, FENA); 142273562Smarcel device_printf(sc->dev, "Will report interrupt on pin %d\n", 143273562Smarcel pin->gp_pin); 144273562Smarcel 145273562Smarcel } 146273562Smarcel else { 147273562Smarcel pin->gp_flags &= ~GPIO_PIN_REPORT; 148273562Smarcel GPIO_BIT_CLR(sc, pin->gp_pin, RENA); 149273562Smarcel GPIO_BIT_CLR(sc, pin->gp_pin, FENA); 150273562Smarcel } 151273562Smarcel#else 152273562Smarcel /* Disable generating interrupts for now */ 153273562Smarcel GPIO_BIT_CLR(sc, pin->gp_pin, RENA); 154273562Smarcel GPIO_BIT_CLR(sc, pin->gp_pin, FENA); 155273562Smarcel#endif 156273562Smarcel 157273562Smarcel GPIO_UNLOCK(sc); 158273562Smarcel} 159273562Smarcel 160273562Smarcelstatic int 161273562Smarcelrt305x_gpio_pin_max(device_t dev, int *maxpin) 162273562Smarcel{ 163273562Smarcel 164273562Smarcel *maxpin = NGPIO - 1; 165273562Smarcel return (0); 166273562Smarcel} 167273562Smarcel 168273562Smarcelstatic int 169273562Smarcelrt305x_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 170273562Smarcel{ 171273562Smarcel struct rt305x_gpio_softc *sc = device_get_softc(dev); 172273562Smarcel int i; 173273562Smarcel 174273562Smarcel for (i = 0; i < sc->gpio_npins; i++) { 175273562Smarcel if (sc->gpio_pins[i].gp_pin == pin) 176273562Smarcel break; 177273562Smarcel } 178273562Smarcel 179273562Smarcel if (i >= sc->gpio_npins) 180273562Smarcel return (EINVAL); 181273562Smarcel 182273562Smarcel GPIO_LOCK(sc); 183273562Smarcel *caps = sc->gpio_pins[i].gp_caps; 184273562Smarcel GPIO_UNLOCK(sc); 185273562Smarcel 186273562Smarcel return (0); 187273562Smarcel} 188273562Smarcel 189273562Smarcelstatic int 190273562Smarcelrt305x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 191273562Smarcel{ 192273562Smarcel struct rt305x_gpio_softc *sc = device_get_softc(dev); 193273562Smarcel int i; 194273562Smarcel 195273562Smarcel for (i = 0; i < sc->gpio_npins; i++) { 196273562Smarcel if (sc->gpio_pins[i].gp_pin == pin) 197273562Smarcel break; 198273562Smarcel } 199273562Smarcel 200273562Smarcel if (i >= sc->gpio_npins) 201273562Smarcel return (EINVAL); 202273562Smarcel 203273562Smarcel GPIO_LOCK(sc); 204273562Smarcel *flags = sc->gpio_pins[i].gp_flags; 205273562Smarcel GPIO_UNLOCK(sc); 206273562Smarcel 207273562Smarcel return (0); 208273562Smarcel} 209273562Smarcel 210273562Smarcelstatic int 211273562Smarcelrt305x_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 212273562Smarcel{ 213273562Smarcel struct rt305x_gpio_softc *sc = device_get_softc(dev); 214273562Smarcel int i; 215273562Smarcel 216273562Smarcel for (i = 0; i < sc->gpio_npins; i++) { 217273562Smarcel if (sc->gpio_pins[i].gp_pin == pin) 218273562Smarcel break; 219273562Smarcel } 220273562Smarcel 221273562Smarcel if (i >= sc->gpio_npins) 222273562Smarcel return (EINVAL); 223273562Smarcel 224273562Smarcel GPIO_LOCK(sc); 225273562Smarcel memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME); 226273562Smarcel GPIO_UNLOCK(sc); 227273562Smarcel 228273562Smarcel return (0); 229273562Smarcel} 230273562Smarcel 231273562Smarcelstatic int 232273562Smarcelrt305x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 233273562Smarcel{ 234273562Smarcel int i; 235273562Smarcel struct rt305x_gpio_softc *sc = device_get_softc(dev); 236273562Smarcel 237273562Smarcel for (i = 0; i < sc->gpio_npins; i++) { 238273562Smarcel if (sc->gpio_pins[i].gp_pin == pin) 239273562Smarcel break; 240273562Smarcel } 241273562Smarcel 242273562Smarcel if (i >= sc->gpio_npins) 243273562Smarcel return (EINVAL); 244273562Smarcel 245273562Smarcel /* Check for unwanted flags. */ 246273562Smarcel if ((flags & sc->gpio_pins[i].gp_caps) != flags) 247273562Smarcel return (EINVAL); 248273562Smarcel 249273562Smarcel /* Can't mix input/output together */ 250273562Smarcel if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 251273562Smarcel (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) 252273562Smarcel return (EINVAL); 253273562Smarcel 254273562Smarcel rt305x_gpio_pin_configure(sc, &sc->gpio_pins[i], flags); 255273562Smarcel 256273562Smarcel 257273562Smarcel return (0); 258273562Smarcel} 259273562Smarcel 260273562Smarcelstatic int 261273562Smarcelrt305x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 262273562Smarcel{ 263273562Smarcel struct rt305x_gpio_softc *sc = device_get_softc(dev); 264273562Smarcel int i; 265273562Smarcel 266273562Smarcel for (i = 0; i < sc->gpio_npins; i++) { 267273562Smarcel if (sc->gpio_pins[i].gp_pin == pin) 268273562Smarcel break; 269273562Smarcel } 270273562Smarcel 271273562Smarcel if (i >= sc->gpio_npins) 272273562Smarcel return (EINVAL); 273273562Smarcel 274273562Smarcel 275273562Smarcel GPIO_LOCK(sc); 276273562Smarcel if (value) GPIO_BIT_SET(sc, i, DATA); 277273562Smarcel else GPIO_BIT_CLR(sc, i, DATA); 278273562Smarcel GPIO_UNLOCK(sc); 279273562Smarcel 280273562Smarcel return (0); 281273562Smarcel} 282273562Smarcel 283273562Smarcelstatic int 284273562Smarcelrt305x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 285274672Smarcel{ 286273562Smarcel struct rt305x_gpio_softc *sc = device_get_softc(dev); 287273562Smarcel int i; 288273562Smarcel 289273562Smarcel for (i = 0; i < sc->gpio_npins; i++) { 290273562Smarcel if (sc->gpio_pins[i].gp_pin == pin) 291273562Smarcel break; 292273562Smarcel } 293273562Smarcel 294273562Smarcel if (i >= sc->gpio_npins) 295273562Smarcel return (EINVAL); 296273562Smarcel 297273562Smarcel GPIO_LOCK(sc); 298273562Smarcel *val = GPIO_BIT_GET(sc, i, DATA); 299273562Smarcel GPIO_UNLOCK(sc); 300273562Smarcel 301273562Smarcel return (0); 302273562Smarcel} 303273562Smarcel 304273562Smarcelstatic int 305273562Smarcelrt305x_gpio_pin_toggle(device_t dev, uint32_t pin) 306273562Smarcel{ 307273562Smarcel int i; 308273562Smarcel struct rt305x_gpio_softc *sc = device_get_softc(dev); 309273562Smarcel 310273562Smarcel for (i = 0; i < sc->gpio_npins; i++) { 311273562Smarcel if (sc->gpio_pins[i].gp_pin == pin) 312273562Smarcel break; 313273562Smarcel } 314273562Smarcel 315273562Smarcel if (i >= sc->gpio_npins) 316273562Smarcel return (EINVAL); 317273562Smarcel 318273562Smarcel GPIO_LOCK(sc); 319273562Smarcel GPIO_BIT_SET(sc, i, TOG); 320273562Smarcel GPIO_UNLOCK(sc); 321273562Smarcel 322273562Smarcel return (0); 323273562Smarcel} 324273562Smarcel 325273562Smarcelstatic int 326273562Smarcelrt305x_gpio_intr(void *arg) 327273562Smarcel{ 328273562Smarcel struct rt305x_gpio_softc *sc = arg; 329273562Smarcel#ifdef notyet 330273562Smarcel uint32_t i; 331273562Smarcel#endif 332273562Smarcel uint64_t input, value; 333273562Smarcel#ifdef notyet 334273562Smarcel uint64_t reset_pin; 335273562Smarcel char notify[16]; 336273562Smarcel char pinname[6]; 337273562Smarcel#endif 338273562Smarcel 339273562Smarcel /* Read all reported pins */ 340273562Smarcel input = GPIO_READ_ALL(sc, INT); 341273562Smarcel /* Clear int status */ 342273562Smarcel GPIO_WRITE_ALL(sc, INT, input); 343273562Smarcel /* Clear report for OUTs */ 344273562Smarcel input &= ~GPIO_READ_ALL(sc, DIR); 345273562Smarcel value = input & GPIO_READ_ALL(sc, DATA); 346273562Smarcel 347273562Smarcel if (!input) goto intr_done; 348273562Smarcel 349273562Smarcel#ifdef notyet 350282100Smarcel /* if reset_gpio and this pin is input */ 351282100Smarcel if (sc->reset_gpio >= 0 && (input & (1 << sc->reset_gpio))) { 352273562Smarcel /* get reset_gpio pin value */ 353282100Smarcel reset_pin = (value & (1 << sc->reset_gpio))?1:0; 354273562Smarcel if ( sc->reset_gpio_last != reset_pin ) { 355273562Smarcel /* 356273562Smarcel * if now reset is high, check how long 357273562Smarcel * and do reset if less than 2 seconds 358273562Smarcel */ 359282100Smarcel if ( reset_pin && 360273562Smarcel (time_uptime - sc->reset_gpio_ontime) < 2 ) 361273562Smarcel shutdown_nice(0); 362273562Smarcel 363273562Smarcel sc->reset_gpio_last = reset_pin; 364282100Smarcel sc->reset_gpio_ontime = time_uptime; 365273562Smarcel } 366273562Smarcel } 367273562Smarcel 368273562Smarcel for ( i = 0; i < NGPIO; i ++ ) 369273562Smarcel { 370273562Smarcel /* Next if output pin */ 371282100Smarcel if ( !(( input >> i) & 1) ) continue; 372282100Smarcel 373282100Smarcel if ( (((value & input) >> i) & 1) != sc->gpio_pins[i].gp_last ) 374274672Smarcel { 375282100Smarcel /* !system=GPIO subsystem=pin7 type=PIN_HIGH period=3 */ 376274672Smarcel snprintf(notify , sizeof(notify ), "period=%d", 377274672Smarcel (uint32_t)time_uptime - sc->gpio_pins[i].gp_time); 378274672Smarcel snprintf(pinname, sizeof(pinname), "pin%02d", i); 379274672Smarcel devctl_notify("GPIO", pinname, 380274672Smarcel (((value & input) >> i) & 1)?"PIN_HIGH":"PIN_LOW", 381274672Smarcel notify); 382274672Smarcel printf("GPIO[%s] %s %s\n", pinname, 383274672Smarcel (((value & input) >> i) & 1)?"PIN_HIGH":"PIN_LOW", 384274672Smarcel notify); 385274672Smarcel sc->gpio_pins[i].gp_last = ((value & input) >> i) & 1; 386282100Smarcel sc->gpio_pins[i].gp_time = time_uptime; 387282100Smarcel } 388282100Smarcel 389282100Smarcel } 390282100Smarcel#endif 391282100Smarcel 392282100Smarcelintr_done: 393282100Smarcel return (FILTER_HANDLED); 394282100Smarcel} 395282100Smarcel 396282100Smarcelstatic int 397282100Smarcelrt305x_gpio_probe(device_t dev) 398282100Smarcel{ 399282100Smarcel device_set_desc(dev, "RT305X GPIO driver"); 400282100Smarcel return (0); 401282100Smarcel} 402282100Smarcel 403282100Smarcelstatic uint64_t 404282100Smarcelrt305x_gpio_init(device_t dev) 405282100Smarcel{ 406282100Smarcel uint64_t avl = ~0ULL; 407282100Smarcel uint32_t gmode = rt305x_sysctl_get(SYSCTL_GPIOMODE); 408282100Smarcel if (!(gmode & SYSCTL_GPIOMODE_RGMII_GPIO_MODE)) 409282100Smarcel avl &= ~RGMII_GPIO_MODE_MASK; 410282100Smarcel if (!(gmode & SYSCTL_GPIOMODE_SDRAM_GPIO_MODE)) 411282100Smarcel avl &= ~SDRAM_GPIO_MODE_MASK; 412282100Smarcel if (!(gmode & SYSCTL_GPIOMODE_MDIO_GPIO_MODE)) 413282100Smarcel avl &= ~MDIO_GPIO_MODE_MASK; 414282100Smarcel if (!(gmode & SYSCTL_GPIOMODE_JTAG_GPIO_MODE)) 415282100Smarcel avl &= ~JTAG_GPIO_MODE_MASK; 416282100Smarcel if (!(gmode & SYSCTL_GPIOMODE_UARTL_GPIO_MODE)) 417282100Smarcel avl &= ~UARTL_GPIO_MODE_MASK; 418282100Smarcel if (!(gmode & SYSCTL_GPIOMODE_SPI_GPIO_MODE)) 419282100Smarcel avl &= ~SPI_GPIO_MODE_MASK; 420282100Smarcel if (!(gmode & SYSCTL_GPIOMODE_I2C_GPIO_MODE)) 421282100Smarcel avl &= ~I2C_GPIO_MODE_MASK; 422282100Smarcel if ((gmode & SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO) != 423282100Smarcel SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO) 424282100Smarcel avl &= ~I2C_GPIO_MODE_MASK; 425282100Smarcel/* D-Link DAP-1350 Board have 426282100Smarcel * MDIO_GPIO_MODE 427282100Smarcel * UARTF_GPIO_MODE 428282100Smarcel * SPI_GPIO_MODE 429273562Smarcel * I2C_GPIO_MODE 430273562Smarcel * So we have 431273562Smarcel * 00000001 10000000 01111111 11111110 432273562Smarcel*/ 433273562Smarcel return (avl); 434273562Smarcel 435273562Smarcel} 436273562Smarcel 437273562Smarcel#define DAP1350_RESET_GPIO 10 438273562Smarcel 439273562Smarcelstatic int 440273562Smarcelrt305x_gpio_attach(device_t dev) 441273562Smarcel{ 442273562Smarcel struct rt305x_gpio_softc *sc = device_get_softc(dev); 443273562Smarcel int error = 0, i; 444273562Smarcel uint64_t avlpins = 0; 445273562Smarcel sc->reset_gpio = DAP1350_RESET_GPIO; 446273562Smarcel 447273562Smarcel KASSERT((device_get_unit(dev) == 0), 448273562Smarcel ("rt305x_gpio_gpio: Only one gpio module supported")); 449273562Smarcel 450273562Smarcel mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 451273562Smarcel 452273562Smarcel /* Map control/status registers. */ 453273562Smarcel sc->gpio_mem_rid = 0; 454273562Smarcel sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 455273562Smarcel &sc->gpio_mem_rid, RF_ACTIVE); 456273562Smarcel 457273562Smarcel if (sc->gpio_mem_res == NULL) { 458273562Smarcel device_printf(dev, "couldn't map memory\n"); 459273562Smarcel error = ENXIO; 460273562Smarcel rt305x_gpio_detach(dev); 461273562Smarcel return(error); 462273562Smarcel } 463273562Smarcel 464273562Smarcel if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 465273562Smarcel &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 466273562Smarcel device_printf(dev, "unable to allocate IRQ resource\n"); 467273562Smarcel return (ENXIO); 468273562Smarcel } 469273562Smarcel 470273562Smarcel if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, 471273562Smarcel /* rt305x_gpio_filter, */ 472273562Smarcel rt305x_gpio_intr, NULL, sc, &sc->gpio_ih))) { 473273562Smarcel device_printf(dev, 474273562Smarcel "WARNING: unable to register interrupt handler\n"); 475273562Smarcel return (ENXIO); 476273562Smarcel } 477273562Smarcel 478273562Smarcel sc->dev = dev; 479273562Smarcel avlpins = rt305x_gpio_init(dev); 480273562Smarcel 481273562Smarcel /* Configure all pins as input */ 482273562Smarcel /* disable interrupts for all pins */ 483273562Smarcel /* TODO */ 484273562Smarcel 485273562Smarcel sc->gpio_npins = NGPIO; 486273562Smarcel resource_int_value(device_get_name(dev), device_get_unit(dev), 487273562Smarcel "pins", &sc->gpio_npins); 488273562Smarcel 489273562Smarcel for (i = 0; i < sc->gpio_npins; i++) { 490273562Smarcel sc->gpio_pins[i].gp_pin = i; 491273562Smarcel sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; 492273562Smarcel sc->gpio_pins[i].gp_flags = 0; 493273562Smarcel } 494273562Smarcel 495273562Smarcel /* Setup reset pin interrupt */ 496273562Smarcel if (TUNABLE_INT_FETCH("reset_gpio", &sc->reset_gpio)) { 497273562Smarcel device_printf(dev, "\tHinted reset_gpio %d\n", sc->reset_gpio); 498273562Smarcel } 499273562Smarcel#ifdef notyet 500273562Smarcel if (sc->reset_gpio != -1) { 501273562Smarcel rt305x_gpio_pin_setflags(dev, sc->reset_gpio, 502282100Smarcel GPIO_PIN_INPUT|GPIO_PIN_INVOUT| 503273562Smarcel GPIO_PIN_INVOUT|GPIO_PIN_REPORT); 504273562Smarcel device_printf(dev, "\tUse reset_gpio %d\n", sc->reset_gpio); 505273562Smarcel } 506273562Smarcel#else 507273562Smarcel if (sc->reset_gpio != -1) { 508273562Smarcel rt305x_gpio_pin_setflags(dev, sc->reset_gpio, 509273562Smarcel GPIO_PIN_INPUT|GPIO_PIN_INVOUT); 510273562Smarcel device_printf(dev, "\tUse reset_gpio %d\n", sc->reset_gpio); 511273562Smarcel } 512273562Smarcel#endif 513273562Smarcel 514273562Smarcel device_add_child(dev, "gpioc", -1); 515273562Smarcel device_add_child(dev, "gpiobus", -1); 516273562Smarcel 517273562Smarcel return (bus_generic_attach(dev)); 518273562Smarcel} 519273562Smarcel 520273562Smarcelstatic int 521273562Smarcelrt305x_gpio_detach(device_t dev) 522273562Smarcel{ 523273562Smarcel struct rt305x_gpio_softc *sc = device_get_softc(dev); 524273562Smarcel 525273562Smarcel KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); 526273562Smarcel 527273562Smarcel bus_generic_detach(dev); 528273562Smarcel 529273562Smarcel if (sc->gpio_mem_res) 530273562Smarcel bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid, 531273562Smarcel sc->gpio_mem_res); 532273562Smarcel 533273562Smarcel mtx_destroy(&sc->gpio_mtx); 534273562Smarcel 535273562Smarcel return(0); 536273562Smarcel} 537273562Smarcel 538273562Smarcel#ifdef notyet 539273562Smarcelstatic struct resource * 540273562Smarcelrt305x_gpio_alloc_resource(device_t bus, device_t child, int type, int *rid, 541273562Smarcel u_long start, u_long end, u_long count, u_int flags) 542273562Smarcel{ 543273562Smarcel struct obio_softc *sc = device_get_softc(bus); 544273562Smarcel struct resource *rv; 545273562Smarcel struct rman *rm; 546273562Smarcel 547273562Smarcel switch (type) { 548273562Smarcel case SYS_RES_GPIO: 549273562Smarcel rm = &sc->gpio_rman; 550273562Smarcel break; 551273562Smarcel default: 552273562Smarcel printf("%s: unknown resource type %d\n", __func__, type); 553273562Smarcel return (0); 554273562Smarcel } 555273562Smarcel 556273562Smarcel rv = rman_reserve_resource(rm, start, end, count, flags, child); 557273562Smarcel if (rv == 0) { 558273562Smarcel printf("%s: could not reserve resource\n", __func__); 559273562Smarcel return (0); 560273562Smarcel } 561273562Smarcel 562273562Smarcel rman_set_rid(rv, *rid); 563273562Smarcel 564273562Smarcel return (rv); 565273562Smarcel} 566273562Smarcel 567273562Smarcelstatic int 568273562Smarcelrt305x_gpio_activate_resource(device_t bus, device_t child, int type, int rid, 569273562Smarcel struct resource *r) 570273562Smarcel{ 571273562Smarcel 572273562Smarcel return (rman_activate_resource(r)); 573273562Smarcel} 574273562Smarcel 575273562Smarcelstatic int 576273562Smarcelrt305x_gpio_deactivate_resource(device_t bus, device_t child, int type, int rid, 577273562Smarcel struct resource *r) 578273562Smarcel{ 579273562Smarcel 580273562Smarcel return (rman_deactivate_resource(r)); 581273562Smarcel} 582273562Smarcel 583273562Smarcelstatic int 584273562Smarcelrt305x_gpio_release_resource(device_t dev, device_t child, int type, 585273562Smarcel int rid, struct resource *r) 586273562Smarcel{ 587273562Smarcel rman_release_resource(r); 588273562Smarcel return (0); 589274672Smarcel} 590273562Smarcel#endif 591273562Smarcel 592273562Smarcelstatic device_method_t rt305x_gpio_methods[] = { 593273562Smarcel DEVMETHOD(device_probe, rt305x_gpio_probe), 594273562Smarcel DEVMETHOD(device_attach, rt305x_gpio_attach), 595273562Smarcel DEVMETHOD(device_detach, rt305x_gpio_detach), 596273562Smarcel 597273562Smarcel /* GPIO protocol */ 598273562Smarcel DEVMETHOD(gpio_pin_max, rt305x_gpio_pin_max), 599273562Smarcel DEVMETHOD(gpio_pin_getname, rt305x_gpio_pin_getname), 600273562Smarcel DEVMETHOD(gpio_pin_getflags, rt305x_gpio_pin_getflags), 601273562Smarcel DEVMETHOD(gpio_pin_getcaps, rt305x_gpio_pin_getcaps), 602273562Smarcel DEVMETHOD(gpio_pin_setflags, rt305x_gpio_pin_setflags), 603273562Smarcel DEVMETHOD(gpio_pin_get, rt305x_gpio_pin_get), 604273562Smarcel DEVMETHOD(gpio_pin_set, rt305x_gpio_pin_set), 605273562Smarcel DEVMETHOD(gpio_pin_toggle, rt305x_gpio_pin_toggle), 606273562Smarcel {0, 0}, 607273562Smarcel}; 608273562Smarcel 609273562Smarcelstatic driver_t rt305x_gpio_driver = { 610273562Smarcel "gpio", 611273562Smarcel rt305x_gpio_methods, 612273562Smarcel sizeof(struct rt305x_gpio_softc), 613273562Smarcel}; 614273562Smarcelstatic devclass_t rt305x_gpio_devclass; 615273562Smarcel 616DRIVER_MODULE(rt305x_gpio, obio, rt305x_gpio_driver, 617 rt305x_gpio_devclass, 0, 0); 618