1220297Sadrian/*- 2220297Sadrian * Copyright (c) 2010-2011, Aleksandr Rybalko <ray@ddteam.net> 3220297Sadrian * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org> 4220297Sadrian * Copyright (c) 2009, Luiz Otavio O Souza. 5220297Sadrian * All rights reserved. 6220297Sadrian * 7220297Sadrian * Redistribution and use in source and binary forms, with or without 8220297Sadrian * modification, are permitted provided that the following conditions 9220297Sadrian * are met: 10220297Sadrian * 1. Redistributions of source code must retain the above copyright 11220297Sadrian * notice unmodified, this list of conditions, and the following 12220297Sadrian * disclaimer. 13220297Sadrian * 2. Redistributions in binary form must reproduce the above copyright 14220297Sadrian * notice, this list of conditions and the following disclaimer in the 15220297Sadrian * documentation and/or other materials provided with the distribution. 16220297Sadrian * 17220297Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18220297Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19220297Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20220297Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21220297Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22220297Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23220297Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24220297Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25220297Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26220297Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27220297Sadrian * SUCH DAMAGE. 28220297Sadrian */ 29220297Sadrian 30220297Sadrian/* 31220297Sadrian * GPIO driver for RT305X SoC. 32220297Sadrian */ 33220297Sadrian 34220297Sadrian#include <sys/cdefs.h> 35220297Sadrian__FBSDID("$FreeBSD$"); 36220297Sadrian 37220297Sadrian#include <sys/param.h> 38220297Sadrian#include <sys/systm.h> 39220297Sadrian#include <sys/bus.h> 40220297Sadrian 41220297Sadrian#include <sys/kernel.h> 42220297Sadrian#include <sys/module.h> 43220297Sadrian#include <sys/rman.h> 44220297Sadrian#include <sys/lock.h> 45220297Sadrian#include <sys/mutex.h> 46220297Sadrian#include <sys/gpio.h> 47220297Sadrian 48220297Sadrian#include <machine/bus.h> 49220297Sadrian#include <machine/resource.h> 50220297Sadrian#include <mips/rt305x/rt305xreg.h> 51220297Sadrian#include <mips/rt305x/rt305x_gpio.h> 52220297Sadrian#include <mips/rt305x/rt305x_gpiovar.h> 53220297Sadrian#include <mips/rt305x/rt305x_sysctlvar.h> 54220297Sadrian 55220297Sadrian#include "gpio_if.h" 56220297Sadrian 57220297Sadrian#ifdef notyet 58220297Sadrian#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INVIN | \ 59220297Sadrian GPIO_PIN_INVOUT | GPIO_PIN_REPORT ) 60220297Sadrian#else 61220297Sadrian#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INVIN | \ 62220297Sadrian GPIO_PIN_INVOUT ) 63220297Sadrian#endif 64220297Sadrian 65220297Sadrian/* 66220297Sadrian * Helpers 67220297Sadrian */ 68220297Sadrianstatic void rt305x_gpio_pin_configure(struct rt305x_gpio_softc *sc, 69220297Sadrian struct gpio_pin *pin, uint32_t flags); 70220297Sadrian 71220297Sadrian/* 72220297Sadrian * Driver stuff 73220297Sadrian */ 74220297Sadrianstatic int rt305x_gpio_probe(device_t dev); 75220297Sadrianstatic int rt305x_gpio_attach(device_t dev); 76220297Sadrianstatic int rt305x_gpio_detach(device_t dev); 77220297Sadrianstatic int rt305x_gpio_intr(void *arg); 78220297Sadrian 79220297Sadrianint rt305x_get_int_mask (device_t); 80220297Sadrianvoid rt305x_set_int_mask (device_t, uint32_t); 81220297Sadrianint rt305x_get_int_status(device_t); 82220297Sadrianvoid rt305x_set_int_status(device_t, uint32_t); 83220297Sadrian 84220297Sadrian/* 85220297Sadrian * GPIO interface 86220297Sadrian */ 87220297Sadrianstatic int rt305x_gpio_pin_max(device_t dev, int *maxpin); 88220297Sadrianstatic int rt305x_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps); 89220297Sadrianstatic int rt305x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t 90220297Sadrian *flags); 91220297Sadrianstatic int rt305x_gpio_pin_getname(device_t dev, uint32_t pin, char *name); 92220297Sadrianstatic int rt305x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags); 93220297Sadrianstatic int rt305x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value); 94220297Sadrianstatic int rt305x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val); 95220297Sadrianstatic int rt305x_gpio_pin_toggle(device_t dev, uint32_t pin); 96220297Sadrian 97220297Sadrianstatic void 98220297Sadrianrt305x_gpio_pin_configure(struct rt305x_gpio_softc *sc, struct gpio_pin *pin, 99220297Sadrian unsigned int flags) 100220297Sadrian{ 101220297Sadrian GPIO_LOCK(sc); 102220297Sadrian 103220297Sadrian /* 104220297Sadrian * Manage input/output 105220297Sadrian */ 106220297Sadrian if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { 107220297Sadrian pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); 108220297Sadrian if (flags & GPIO_PIN_OUTPUT) { 109220297Sadrian pin->gp_flags |= GPIO_PIN_OUTPUT; 110220297Sadrian GPIO_BIT_SET(sc, pin->gp_pin, DIR); 111220297Sadrian } 112220297Sadrian else { 113220297Sadrian pin->gp_flags |= GPIO_PIN_INPUT; 114220297Sadrian GPIO_BIT_CLR(sc, pin->gp_pin, DIR); 115220297Sadrian } 116220297Sadrian } 117220297Sadrian 118220297Sadrian if (flags & GPIO_PIN_INVOUT) { 119220297Sadrian pin->gp_flags |= GPIO_PIN_INVOUT; 120220297Sadrian GPIO_BIT_SET(sc, pin->gp_pin, POL); 121220297Sadrian } 122220297Sadrian else { 123220297Sadrian pin->gp_flags &= ~GPIO_PIN_INVOUT; 124220297Sadrian GPIO_BIT_CLR(sc, pin->gp_pin, POL); 125220297Sadrian } 126220297Sadrian 127220297Sadrian if (flags & GPIO_PIN_INVIN) { 128220297Sadrian pin->gp_flags |= GPIO_PIN_INVIN; 129220297Sadrian GPIO_BIT_SET(sc, pin->gp_pin, POL); 130220297Sadrian } 131220297Sadrian else { 132220297Sadrian pin->gp_flags &= ~GPIO_PIN_INVIN; 133220297Sadrian GPIO_BIT_CLR(sc, pin->gp_pin, POL); 134220297Sadrian } 135220297Sadrian 136220297Sadrian#ifdef notyet 137220297Sadrian /* Enable interrupt bits for rising/falling transitions */ 138220297Sadrian if (flags & GPIO_PIN_REPORT) { 139220297Sadrian pin->gp_flags |= GPIO_PIN_REPORT; 140220297Sadrian GPIO_BIT_SET(sc, pin->gp_pin, RENA); 141220297Sadrian GPIO_BIT_SET(sc, pin->gp_pin, FENA); 142220297Sadrian device_printf(sc->dev, "Will report interrupt on pin %d\n", 143220297Sadrian pin->gp_pin); 144220297Sadrian 145220297Sadrian } 146220297Sadrian else { 147220297Sadrian pin->gp_flags &= ~GPIO_PIN_REPORT; 148220297Sadrian GPIO_BIT_CLR(sc, pin->gp_pin, RENA); 149220297Sadrian GPIO_BIT_CLR(sc, pin->gp_pin, FENA); 150220297Sadrian } 151220297Sadrian#else 152220297Sadrian /* Disable generating interrupts for now */ 153220297Sadrian GPIO_BIT_CLR(sc, pin->gp_pin, RENA); 154220297Sadrian GPIO_BIT_CLR(sc, pin->gp_pin, FENA); 155220297Sadrian#endif 156220297Sadrian 157220297Sadrian GPIO_UNLOCK(sc); 158220297Sadrian} 159220297Sadrian 160220297Sadrianstatic int 161220297Sadrianrt305x_gpio_pin_max(device_t dev, int *maxpin) 162220297Sadrian{ 163220297Sadrian 164220297Sadrian *maxpin = NGPIO - 1; 165220297Sadrian return (0); 166220297Sadrian} 167220297Sadrian 168220297Sadrianstatic int 169220297Sadrianrt305x_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 170220297Sadrian{ 171220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 172220297Sadrian int i; 173220297Sadrian 174220297Sadrian for (i = 0; i < sc->gpio_npins; i++) { 175220297Sadrian if (sc->gpio_pins[i].gp_pin == pin) 176220297Sadrian break; 177220297Sadrian } 178220297Sadrian 179220297Sadrian if (i >= sc->gpio_npins) 180220297Sadrian return (EINVAL); 181220297Sadrian 182220297Sadrian GPIO_LOCK(sc); 183220297Sadrian *caps = sc->gpio_pins[i].gp_caps; 184220297Sadrian GPIO_UNLOCK(sc); 185220297Sadrian 186220297Sadrian return (0); 187220297Sadrian} 188220297Sadrian 189220297Sadrianstatic int 190220297Sadrianrt305x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 191220297Sadrian{ 192220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 193220297Sadrian int i; 194220297Sadrian 195220297Sadrian for (i = 0; i < sc->gpio_npins; i++) { 196220297Sadrian if (sc->gpio_pins[i].gp_pin == pin) 197220297Sadrian break; 198220297Sadrian } 199220297Sadrian 200220297Sadrian if (i >= sc->gpio_npins) 201220297Sadrian return (EINVAL); 202220297Sadrian 203220297Sadrian GPIO_LOCK(sc); 204220297Sadrian *flags = sc->gpio_pins[i].gp_flags; 205220297Sadrian GPIO_UNLOCK(sc); 206220297Sadrian 207220297Sadrian return (0); 208220297Sadrian} 209220297Sadrian 210220297Sadrianstatic int 211220297Sadrianrt305x_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 212220297Sadrian{ 213220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 214220297Sadrian int i; 215220297Sadrian 216220297Sadrian for (i = 0; i < sc->gpio_npins; i++) { 217220297Sadrian if (sc->gpio_pins[i].gp_pin == pin) 218220297Sadrian break; 219220297Sadrian } 220220297Sadrian 221220297Sadrian if (i >= sc->gpio_npins) 222220297Sadrian return (EINVAL); 223220297Sadrian 224220297Sadrian GPIO_LOCK(sc); 225220297Sadrian memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME); 226220297Sadrian GPIO_UNLOCK(sc); 227220297Sadrian 228220297Sadrian return (0); 229220297Sadrian} 230220297Sadrian 231220297Sadrianstatic int 232220297Sadrianrt305x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 233220297Sadrian{ 234220297Sadrian int i; 235220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 236220297Sadrian 237220297Sadrian for (i = 0; i < sc->gpio_npins; i++) { 238220297Sadrian if (sc->gpio_pins[i].gp_pin == pin) 239220297Sadrian break; 240220297Sadrian } 241220297Sadrian 242220297Sadrian if (i >= sc->gpio_npins) 243220297Sadrian return (EINVAL); 244220297Sadrian 245220297Sadrian rt305x_gpio_pin_configure(sc, &sc->gpio_pins[i], flags); 246220297Sadrian 247220297Sadrian return (0); 248220297Sadrian} 249220297Sadrian 250220297Sadrianstatic int 251220297Sadrianrt305x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 252220297Sadrian{ 253220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 254220297Sadrian int i; 255220297Sadrian 256220297Sadrian for (i = 0; i < sc->gpio_npins; i++) { 257220297Sadrian if (sc->gpio_pins[i].gp_pin == pin) 258220297Sadrian break; 259220297Sadrian } 260220297Sadrian 261220297Sadrian if (i >= sc->gpio_npins) 262220297Sadrian return (EINVAL); 263220297Sadrian 264220297Sadrian 265220297Sadrian GPIO_LOCK(sc); 266220297Sadrian if (value) GPIO_BIT_SET(sc, i, DATA); 267220297Sadrian else GPIO_BIT_CLR(sc, i, DATA); 268220297Sadrian GPIO_UNLOCK(sc); 269220297Sadrian 270220297Sadrian return (0); 271220297Sadrian} 272220297Sadrian 273220297Sadrianstatic int 274220297Sadrianrt305x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 275220297Sadrian{ 276220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 277220297Sadrian int i; 278220297Sadrian 279220297Sadrian for (i = 0; i < sc->gpio_npins; i++) { 280220297Sadrian if (sc->gpio_pins[i].gp_pin == pin) 281220297Sadrian break; 282220297Sadrian } 283220297Sadrian 284220297Sadrian if (i >= sc->gpio_npins) 285220297Sadrian return (EINVAL); 286220297Sadrian 287220297Sadrian GPIO_LOCK(sc); 288220297Sadrian *val = GPIO_BIT_GET(sc, i, DATA); 289220297Sadrian GPIO_UNLOCK(sc); 290220297Sadrian 291220297Sadrian return (0); 292220297Sadrian} 293220297Sadrian 294220297Sadrianstatic int 295220297Sadrianrt305x_gpio_pin_toggle(device_t dev, uint32_t pin) 296220297Sadrian{ 297220297Sadrian int i; 298220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 299220297Sadrian 300220297Sadrian for (i = 0; i < sc->gpio_npins; i++) { 301220297Sadrian if (sc->gpio_pins[i].gp_pin == pin) 302220297Sadrian break; 303220297Sadrian } 304220297Sadrian 305220297Sadrian if (i >= sc->gpio_npins) 306220297Sadrian return (EINVAL); 307220297Sadrian 308220297Sadrian GPIO_LOCK(sc); 309220297Sadrian GPIO_BIT_SET(sc, i, TOG); 310220297Sadrian GPIO_UNLOCK(sc); 311220297Sadrian 312220297Sadrian return (0); 313220297Sadrian} 314220297Sadrian 315220297Sadrianstatic int 316220297Sadrianrt305x_gpio_intr(void *arg) 317220297Sadrian{ 318220297Sadrian struct rt305x_gpio_softc *sc = arg; 319220297Sadrian#ifdef notyet 320220297Sadrian uint32_t i; 321220297Sadrian#endif 322220297Sadrian uint64_t input, value; 323220297Sadrian#ifdef notyet 324220297Sadrian uint64_t reset_pin; 325220297Sadrian char notify[16]; 326220297Sadrian char pinname[6]; 327220297Sadrian#endif 328220297Sadrian 329220297Sadrian /* Read all reported pins */ 330220297Sadrian input = GPIO_READ_ALL(sc, INT); 331220297Sadrian /* Clear int status */ 332220297Sadrian GPIO_WRITE_ALL(sc, INT, input); 333220297Sadrian /* Clear report for OUTs */ 334220297Sadrian input &= ~GPIO_READ_ALL(sc, DIR); 335220297Sadrian value = input & GPIO_READ_ALL(sc, DATA); 336220297Sadrian 337220297Sadrian if (!input) goto intr_done; 338220297Sadrian 339220297Sadrian#ifdef notyet 340220297Sadrian /* if reset_gpio and this pin is input */ 341220297Sadrian if (sc->reset_gpio >= 0 && (input & (1 << sc->reset_gpio))) { 342220297Sadrian /* get reset_gpio pin value */ 343220297Sadrian reset_pin = (value & (1 << sc->reset_gpio))?1:0; 344220297Sadrian if ( sc->reset_gpio_last != reset_pin ) { 345220297Sadrian /* 346220297Sadrian * if now reset is high, check how long 347220297Sadrian * and do reset if less than 2 seconds 348220297Sadrian */ 349220297Sadrian if ( reset_pin && 350220297Sadrian (time_uptime - sc->reset_gpio_ontime) < 2 ) 351220297Sadrian shutdown_nice(0); 352220297Sadrian 353220297Sadrian sc->reset_gpio_last = reset_pin; 354220297Sadrian sc->reset_gpio_ontime = time_uptime; 355220297Sadrian } 356220297Sadrian } 357220297Sadrian 358220297Sadrian for ( i = 0; i < NGPIO; i ++ ) 359220297Sadrian { 360220297Sadrian /* Next if output pin */ 361220297Sadrian if ( !(( input >> i) & 1) ) continue; 362220297Sadrian 363220297Sadrian if ( (((value & input) >> i) & 1) != sc->gpio_pins[i].gp_last ) 364220297Sadrian { 365220297Sadrian /* !system=GPIO subsystem=pin7 type=PIN_HIGH period=3 */ 366220297Sadrian snprintf(notify , sizeof(notify ), "period=%d", 367220297Sadrian (uint32_t)time_uptime - sc->gpio_pins[i].gp_time); 368220297Sadrian snprintf(pinname, sizeof(pinname), "pin%02d", i); 369220297Sadrian devctl_notify("GPIO", pinname, 370220297Sadrian (((value & input) >> i) & 1)?"PIN_HIGH":"PIN_LOW", 371220297Sadrian notify); 372220297Sadrian printf("GPIO[%s] %s %s\n", pinname, 373220297Sadrian (((value & input) >> i) & 1)?"PIN_HIGH":"PIN_LOW", 374220297Sadrian notify); 375220297Sadrian sc->gpio_pins[i].gp_last = ((value & input) >> i) & 1; 376220297Sadrian sc->gpio_pins[i].gp_time = time_uptime; 377220297Sadrian } 378220297Sadrian 379220297Sadrian } 380220297Sadrian#endif 381220297Sadrian 382220297Sadrianintr_done: 383220297Sadrian return (FILTER_HANDLED); 384220297Sadrian} 385220297Sadrian 386220297Sadrianstatic int 387220297Sadrianrt305x_gpio_probe(device_t dev) 388220297Sadrian{ 389220297Sadrian device_set_desc(dev, "RT305X GPIO driver"); 390220297Sadrian return (0); 391220297Sadrian} 392220297Sadrian 393220297Sadrianstatic uint64_t 394220297Sadrianrt305x_gpio_init(device_t dev) 395220297Sadrian{ 396220297Sadrian uint64_t avl = ~0ULL; 397220297Sadrian uint32_t gmode = rt305x_sysctl_get(SYSCTL_GPIOMODE); 398220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_RGMII_GPIO_MODE)) 399220297Sadrian avl &= ~RGMII_GPIO_MODE_MASK; 400220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_SDRAM_GPIO_MODE)) 401220297Sadrian avl &= ~SDRAM_GPIO_MODE_MASK; 402220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_MDIO_GPIO_MODE)) 403220297Sadrian avl &= ~MDIO_GPIO_MODE_MASK; 404220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_JTAG_GPIO_MODE)) 405220297Sadrian avl &= ~JTAG_GPIO_MODE_MASK; 406220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_UARTL_GPIO_MODE)) 407220297Sadrian avl &= ~UARTL_GPIO_MODE_MASK; 408220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_SPI_GPIO_MODE)) 409220297Sadrian avl &= ~SPI_GPIO_MODE_MASK; 410220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_I2C_GPIO_MODE)) 411220297Sadrian avl &= ~I2C_GPIO_MODE_MASK; 412220297Sadrian if ((gmode & SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO) != 413220297Sadrian SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO) 414220297Sadrian avl &= ~I2C_GPIO_MODE_MASK; 415220297Sadrian/* D-Link DAP-1350 Board have 416220297Sadrian * MDIO_GPIO_MODE 417220297Sadrian * UARTF_GPIO_MODE 418220297Sadrian * SPI_GPIO_MODE 419220297Sadrian * I2C_GPIO_MODE 420220297Sadrian * So we have 421220297Sadrian * 00000001 10000000 01111111 11111110 422220297Sadrian*/ 423220297Sadrian return (avl); 424220297Sadrian 425220297Sadrian} 426220297Sadrian 427220297Sadrian#define DAP1350_RESET_GPIO 10 428220297Sadrian 429220297Sadrianstatic int 430220297Sadrianrt305x_gpio_attach(device_t dev) 431220297Sadrian{ 432220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 433220297Sadrian int error = 0, i; 434220297Sadrian uint64_t avlpins = 0; 435220297Sadrian sc->reset_gpio = DAP1350_RESET_GPIO; 436220297Sadrian 437220297Sadrian KASSERT((device_get_unit(dev) == 0), 438220297Sadrian ("rt305x_gpio_gpio: Only one gpio module supported")); 439220297Sadrian 440239351Srpaulo mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 441220297Sadrian 442220297Sadrian /* Map control/status registers. */ 443220297Sadrian sc->gpio_mem_rid = 0; 444220297Sadrian sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 445220297Sadrian &sc->gpio_mem_rid, RF_ACTIVE); 446220297Sadrian 447220297Sadrian if (sc->gpio_mem_res == NULL) { 448220297Sadrian device_printf(dev, "couldn't map memory\n"); 449220297Sadrian error = ENXIO; 450220297Sadrian rt305x_gpio_detach(dev); 451220297Sadrian return(error); 452220297Sadrian } 453220297Sadrian 454220297Sadrian if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 455220297Sadrian &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 456220297Sadrian device_printf(dev, "unable to allocate IRQ resource\n"); 457220297Sadrian return (ENXIO); 458220297Sadrian } 459220297Sadrian 460220297Sadrian if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, 461220297Sadrian /* rt305x_gpio_filter, */ 462220297Sadrian rt305x_gpio_intr, NULL, sc, &sc->gpio_ih))) { 463220297Sadrian device_printf(dev, 464220297Sadrian "WARNING: unable to register interrupt handler\n"); 465220297Sadrian return (ENXIO); 466220297Sadrian } 467220297Sadrian 468220297Sadrian sc->dev = dev; 469220297Sadrian avlpins = rt305x_gpio_init(dev); 470220297Sadrian 471220297Sadrian /* Configure all pins as input */ 472220297Sadrian /* disable interrupts for all pins */ 473220297Sadrian /* TODO */ 474220297Sadrian 475220297Sadrian sc->gpio_npins = NGPIO; 476220297Sadrian resource_int_value(device_get_name(dev), device_get_unit(dev), 477220297Sadrian "pins", &sc->gpio_npins); 478220297Sadrian 479220297Sadrian for (i = 0; i < sc->gpio_npins; i++) { 480220297Sadrian sc->gpio_pins[i].gp_pin = i; 481220297Sadrian sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; 482220297Sadrian sc->gpio_pins[i].gp_flags = 0; 483220297Sadrian } 484220297Sadrian 485220297Sadrian /* Setup reset pin interrupt */ 486220297Sadrian if (TUNABLE_INT_FETCH("reset_gpio", &sc->reset_gpio)) { 487220297Sadrian device_printf(dev, "\tHinted reset_gpio %d\n", sc->reset_gpio); 488220297Sadrian } 489220297Sadrian#ifdef notyet 490220297Sadrian if (sc->reset_gpio != -1) { 491220297Sadrian rt305x_gpio_pin_setflags(dev, sc->reset_gpio, 492220297Sadrian GPIO_PIN_INPUT|GPIO_PIN_INVOUT| 493220297Sadrian GPIO_PIN_INVOUT|GPIO_PIN_REPORT); 494220297Sadrian device_printf(dev, "\tUse reset_gpio %d\n", sc->reset_gpio); 495220297Sadrian } 496220297Sadrian#else 497220297Sadrian if (sc->reset_gpio != -1) { 498220297Sadrian rt305x_gpio_pin_setflags(dev, sc->reset_gpio, 499220297Sadrian GPIO_PIN_INPUT|GPIO_PIN_INVOUT); 500220297Sadrian device_printf(dev, "\tUse reset_gpio %d\n", sc->reset_gpio); 501220297Sadrian } 502220297Sadrian#endif 503220297Sadrian 504278782Sloos device_add_child(dev, "gpioc", -1); 505278782Sloos device_add_child(dev, "gpiobus", -1); 506220297Sadrian 507220297Sadrian return (bus_generic_attach(dev)); 508220297Sadrian} 509220297Sadrian 510220297Sadrianstatic int 511220297Sadrianrt305x_gpio_detach(device_t dev) 512220297Sadrian{ 513220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 514220297Sadrian 515220297Sadrian KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); 516220297Sadrian 517220297Sadrian bus_generic_detach(dev); 518220297Sadrian 519220297Sadrian if (sc->gpio_mem_res) 520220297Sadrian bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid, 521220297Sadrian sc->gpio_mem_res); 522220297Sadrian 523220297Sadrian mtx_destroy(&sc->gpio_mtx); 524220297Sadrian 525220297Sadrian return(0); 526220297Sadrian} 527220297Sadrian 528220297Sadrian#ifdef notyet 529220297Sadrianstatic struct resource * 530220297Sadrianrt305x_gpio_alloc_resource(device_t bus, device_t child, int type, int *rid, 531220297Sadrian u_long start, u_long end, u_long count, u_int flags) 532220297Sadrian{ 533220297Sadrian struct obio_softc *sc = device_get_softc(bus); 534220297Sadrian struct resource *rv; 535220297Sadrian struct rman *rm; 536220297Sadrian 537220297Sadrian switch (type) { 538220297Sadrian case SYS_RES_GPIO: 539220297Sadrian rm = &sc->gpio_rman; 540220297Sadrian break; 541220297Sadrian default: 542220297Sadrian printf("%s: unknown resource type %d\n", __func__, type); 543220297Sadrian return (0); 544220297Sadrian } 545220297Sadrian 546220297Sadrian rv = rman_reserve_resource(rm, start, end, count, flags, child); 547220297Sadrian if (rv == 0) { 548220297Sadrian printf("%s: could not reserve resource\n", __func__); 549220297Sadrian return (0); 550220297Sadrian } 551220297Sadrian 552220297Sadrian rman_set_rid(rv, *rid); 553220297Sadrian 554220297Sadrian return (rv); 555220297Sadrian} 556220297Sadrian 557220297Sadrianstatic int 558220297Sadrianrt305x_gpio_activate_resource(device_t bus, device_t child, int type, int rid, 559220297Sadrian struct resource *r) 560220297Sadrian{ 561220297Sadrian 562220297Sadrian return (rman_activate_resource(r)); 563220297Sadrian} 564220297Sadrian 565220297Sadrianstatic int 566220297Sadrianrt305x_gpio_deactivate_resource(device_t bus, device_t child, int type, int rid, 567220297Sadrian struct resource *r) 568220297Sadrian{ 569220297Sadrian 570220297Sadrian return (rman_deactivate_resource(r)); 571220297Sadrian} 572220297Sadrian 573220297Sadrianstatic int 574220297Sadrianrt305x_gpio_release_resource(device_t dev, device_t child, int type, 575220297Sadrian int rid, struct resource *r) 576220297Sadrian{ 577220297Sadrian rman_release_resource(r); 578220297Sadrian return (0); 579220297Sadrian} 580220297Sadrian#endif 581220297Sadrian 582220297Sadrianstatic device_method_t rt305x_gpio_methods[] = { 583220297Sadrian DEVMETHOD(device_probe, rt305x_gpio_probe), 584220297Sadrian DEVMETHOD(device_attach, rt305x_gpio_attach), 585220297Sadrian DEVMETHOD(device_detach, rt305x_gpio_detach), 586220297Sadrian 587220297Sadrian /* GPIO protocol */ 588220297Sadrian DEVMETHOD(gpio_pin_max, rt305x_gpio_pin_max), 589220297Sadrian DEVMETHOD(gpio_pin_getname, rt305x_gpio_pin_getname), 590220297Sadrian DEVMETHOD(gpio_pin_getflags, rt305x_gpio_pin_getflags), 591220297Sadrian DEVMETHOD(gpio_pin_getcaps, rt305x_gpio_pin_getcaps), 592220297Sadrian DEVMETHOD(gpio_pin_setflags, rt305x_gpio_pin_setflags), 593220297Sadrian DEVMETHOD(gpio_pin_get, rt305x_gpio_pin_get), 594220297Sadrian DEVMETHOD(gpio_pin_set, rt305x_gpio_pin_set), 595220297Sadrian DEVMETHOD(gpio_pin_toggle, rt305x_gpio_pin_toggle), 596220297Sadrian {0, 0}, 597220297Sadrian}; 598220297Sadrian 599220297Sadrianstatic driver_t rt305x_gpio_driver = { 600220297Sadrian "gpio", 601220297Sadrian rt305x_gpio_methods, 602220297Sadrian sizeof(struct rt305x_gpio_softc), 603220297Sadrian}; 604220297Sadrianstatic devclass_t rt305x_gpio_devclass; 605220297Sadrian 606220297SadrianDRIVER_MODULE(rt305x_gpio, obio, rt305x_gpio_driver, 607220297Sadrian rt305x_gpio_devclass, 0, 0); 608