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 245249449Sdim /* Check for unwanted flags. */ 246249449Sdim if ((flags & sc->gpio_pins[i].gp_caps) != flags) 247220297Sadrian return (EINVAL); 248220297Sadrian 249220297Sadrian /* Can't mix input/output together */ 250220297Sadrian if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 251220297Sadrian (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) 252220297Sadrian return (EINVAL); 253220297Sadrian 254220297Sadrian rt305x_gpio_pin_configure(sc, &sc->gpio_pins[i], flags); 255220297Sadrian 256220297Sadrian 257220297Sadrian return (0); 258220297Sadrian} 259220297Sadrian 260220297Sadrianstatic int 261220297Sadrianrt305x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 262220297Sadrian{ 263220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 264220297Sadrian int i; 265220297Sadrian 266220297Sadrian for (i = 0; i < sc->gpio_npins; i++) { 267220297Sadrian if (sc->gpio_pins[i].gp_pin == pin) 268220297Sadrian break; 269220297Sadrian } 270220297Sadrian 271220297Sadrian if (i >= sc->gpio_npins) 272220297Sadrian return (EINVAL); 273220297Sadrian 274220297Sadrian 275220297Sadrian GPIO_LOCK(sc); 276220297Sadrian if (value) GPIO_BIT_SET(sc, i, DATA); 277220297Sadrian else GPIO_BIT_CLR(sc, i, DATA); 278220297Sadrian GPIO_UNLOCK(sc); 279220297Sadrian 280220297Sadrian return (0); 281220297Sadrian} 282220297Sadrian 283220297Sadrianstatic int 284220297Sadrianrt305x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 285220297Sadrian{ 286220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 287220297Sadrian int i; 288220297Sadrian 289220297Sadrian for (i = 0; i < sc->gpio_npins; i++) { 290220297Sadrian if (sc->gpio_pins[i].gp_pin == pin) 291220297Sadrian break; 292220297Sadrian } 293220297Sadrian 294220297Sadrian if (i >= sc->gpio_npins) 295220297Sadrian return (EINVAL); 296220297Sadrian 297220297Sadrian GPIO_LOCK(sc); 298220297Sadrian *val = GPIO_BIT_GET(sc, i, DATA); 299220297Sadrian GPIO_UNLOCK(sc); 300220297Sadrian 301220297Sadrian return (0); 302220297Sadrian} 303220297Sadrian 304220297Sadrianstatic int 305220297Sadrianrt305x_gpio_pin_toggle(device_t dev, uint32_t pin) 306220297Sadrian{ 307220297Sadrian int i; 308220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 309220297Sadrian 310220297Sadrian for (i = 0; i < sc->gpio_npins; i++) { 311220297Sadrian if (sc->gpio_pins[i].gp_pin == pin) 312220297Sadrian break; 313220297Sadrian } 314220297Sadrian 315220297Sadrian if (i >= sc->gpio_npins) 316220297Sadrian return (EINVAL); 317220297Sadrian 318220297Sadrian GPIO_LOCK(sc); 319220297Sadrian GPIO_BIT_SET(sc, i, TOG); 320220297Sadrian GPIO_UNLOCK(sc); 321220297Sadrian 322220297Sadrian return (0); 323220297Sadrian} 324220297Sadrian 325220297Sadrianstatic int 326220297Sadrianrt305x_gpio_intr(void *arg) 327220297Sadrian{ 328220297Sadrian struct rt305x_gpio_softc *sc = arg; 329220297Sadrian#ifdef notyet 330220297Sadrian uint32_t i; 331220297Sadrian#endif 332220297Sadrian uint64_t input, value; 333220297Sadrian#ifdef notyet 334220297Sadrian uint64_t reset_pin; 335220297Sadrian char notify[16]; 336220297Sadrian char pinname[6]; 337220297Sadrian#endif 338220297Sadrian 339220297Sadrian /* Read all reported pins */ 340220297Sadrian input = GPIO_READ_ALL(sc, INT); 341220297Sadrian /* Clear int status */ 342220297Sadrian GPIO_WRITE_ALL(sc, INT, input); 343220297Sadrian /* Clear report for OUTs */ 344220297Sadrian input &= ~GPIO_READ_ALL(sc, DIR); 345220297Sadrian value = input & GPIO_READ_ALL(sc, DATA); 346220297Sadrian 347220297Sadrian if (!input) goto intr_done; 348220297Sadrian 349220297Sadrian#ifdef notyet 350220297Sadrian /* if reset_gpio and this pin is input */ 351220297Sadrian if (sc->reset_gpio >= 0 && (input & (1 << sc->reset_gpio))) { 352220297Sadrian /* get reset_gpio pin value */ 353220297Sadrian reset_pin = (value & (1 << sc->reset_gpio))?1:0; 354220297Sadrian if ( sc->reset_gpio_last != reset_pin ) { 355220297Sadrian /* 356220297Sadrian * if now reset is high, check how long 357220297Sadrian * and do reset if less than 2 seconds 358220297Sadrian */ 359220297Sadrian if ( reset_pin && 360220297Sadrian (time_uptime - sc->reset_gpio_ontime) < 2 ) 361220297Sadrian shutdown_nice(0); 362220297Sadrian 363220297Sadrian sc->reset_gpio_last = reset_pin; 364220297Sadrian sc->reset_gpio_ontime = time_uptime; 365220297Sadrian } 366220297Sadrian } 367220297Sadrian 368220297Sadrian for ( i = 0; i < NGPIO; i ++ ) 369220297Sadrian { 370220297Sadrian /* Next if output pin */ 371220297Sadrian if ( !(( input >> i) & 1) ) continue; 372220297Sadrian 373220297Sadrian if ( (((value & input) >> i) & 1) != sc->gpio_pins[i].gp_last ) 374220297Sadrian { 375220297Sadrian /* !system=GPIO subsystem=pin7 type=PIN_HIGH period=3 */ 376220297Sadrian snprintf(notify , sizeof(notify ), "period=%d", 377220297Sadrian (uint32_t)time_uptime - sc->gpio_pins[i].gp_time); 378220297Sadrian snprintf(pinname, sizeof(pinname), "pin%02d", i); 379220297Sadrian devctl_notify("GPIO", pinname, 380220297Sadrian (((value & input) >> i) & 1)?"PIN_HIGH":"PIN_LOW", 381220297Sadrian notify); 382220297Sadrian printf("GPIO[%s] %s %s\n", pinname, 383220297Sadrian (((value & input) >> i) & 1)?"PIN_HIGH":"PIN_LOW", 384220297Sadrian notify); 385220297Sadrian sc->gpio_pins[i].gp_last = ((value & input) >> i) & 1; 386220297Sadrian sc->gpio_pins[i].gp_time = time_uptime; 387220297Sadrian } 388220297Sadrian 389220297Sadrian } 390220297Sadrian#endif 391220297Sadrian 392220297Sadrianintr_done: 393220297Sadrian return (FILTER_HANDLED); 394220297Sadrian} 395220297Sadrian 396220297Sadrianstatic int 397220297Sadrianrt305x_gpio_probe(device_t dev) 398220297Sadrian{ 399220297Sadrian device_set_desc(dev, "RT305X GPIO driver"); 400220297Sadrian return (0); 401220297Sadrian} 402220297Sadrian 403220297Sadrianstatic uint64_t 404220297Sadrianrt305x_gpio_init(device_t dev) 405220297Sadrian{ 406220297Sadrian uint64_t avl = ~0ULL; 407220297Sadrian uint32_t gmode = rt305x_sysctl_get(SYSCTL_GPIOMODE); 408220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_RGMII_GPIO_MODE)) 409220297Sadrian avl &= ~RGMII_GPIO_MODE_MASK; 410220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_SDRAM_GPIO_MODE)) 411220297Sadrian avl &= ~SDRAM_GPIO_MODE_MASK; 412220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_MDIO_GPIO_MODE)) 413220297Sadrian avl &= ~MDIO_GPIO_MODE_MASK; 414220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_JTAG_GPIO_MODE)) 415220297Sadrian avl &= ~JTAG_GPIO_MODE_MASK; 416220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_UARTL_GPIO_MODE)) 417220297Sadrian avl &= ~UARTL_GPIO_MODE_MASK; 418220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_SPI_GPIO_MODE)) 419220297Sadrian avl &= ~SPI_GPIO_MODE_MASK; 420220297Sadrian if (!(gmode & SYSCTL_GPIOMODE_I2C_GPIO_MODE)) 421220297Sadrian avl &= ~I2C_GPIO_MODE_MASK; 422220297Sadrian if ((gmode & SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO) != 423220297Sadrian SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO) 424220297Sadrian avl &= ~I2C_GPIO_MODE_MASK; 425220297Sadrian/* D-Link DAP-1350 Board have 426220297Sadrian * MDIO_GPIO_MODE 427220297Sadrian * UARTF_GPIO_MODE 428220297Sadrian * SPI_GPIO_MODE 429220297Sadrian * I2C_GPIO_MODE 430220297Sadrian * So we have 431220297Sadrian * 00000001 10000000 01111111 11111110 432220297Sadrian*/ 433220297Sadrian return (avl); 434220297Sadrian 435220297Sadrian} 436220297Sadrian 437220297Sadrian#define DAP1350_RESET_GPIO 10 438220297Sadrian 439220297Sadrianstatic int 440220297Sadrianrt305x_gpio_attach(device_t dev) 441220297Sadrian{ 442220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 443220297Sadrian int error = 0, i; 444220297Sadrian uint64_t avlpins = 0; 445220297Sadrian sc->reset_gpio = DAP1350_RESET_GPIO; 446220297Sadrian 447220297Sadrian KASSERT((device_get_unit(dev) == 0), 448220297Sadrian ("rt305x_gpio_gpio: Only one gpio module supported")); 449220297Sadrian 450239351Srpaulo mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 451220297Sadrian 452220297Sadrian /* Map control/status registers. */ 453220297Sadrian sc->gpio_mem_rid = 0; 454220297Sadrian sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 455220297Sadrian &sc->gpio_mem_rid, RF_ACTIVE); 456220297Sadrian 457220297Sadrian if (sc->gpio_mem_res == NULL) { 458220297Sadrian device_printf(dev, "couldn't map memory\n"); 459220297Sadrian error = ENXIO; 460220297Sadrian rt305x_gpio_detach(dev); 461220297Sadrian return(error); 462220297Sadrian } 463220297Sadrian 464220297Sadrian if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 465220297Sadrian &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 466220297Sadrian device_printf(dev, "unable to allocate IRQ resource\n"); 467220297Sadrian return (ENXIO); 468220297Sadrian } 469220297Sadrian 470220297Sadrian if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, 471220297Sadrian /* rt305x_gpio_filter, */ 472220297Sadrian rt305x_gpio_intr, NULL, sc, &sc->gpio_ih))) { 473220297Sadrian device_printf(dev, 474220297Sadrian "WARNING: unable to register interrupt handler\n"); 475220297Sadrian return (ENXIO); 476220297Sadrian } 477220297Sadrian 478220297Sadrian sc->dev = dev; 479220297Sadrian avlpins = rt305x_gpio_init(dev); 480220297Sadrian 481220297Sadrian /* Configure all pins as input */ 482220297Sadrian /* disable interrupts for all pins */ 483220297Sadrian /* TODO */ 484220297Sadrian 485220297Sadrian sc->gpio_npins = NGPIO; 486220297Sadrian resource_int_value(device_get_name(dev), device_get_unit(dev), 487220297Sadrian "pins", &sc->gpio_npins); 488220297Sadrian 489220297Sadrian for (i = 0; i < sc->gpio_npins; i++) { 490220297Sadrian sc->gpio_pins[i].gp_pin = i; 491220297Sadrian sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; 492220297Sadrian sc->gpio_pins[i].gp_flags = 0; 493220297Sadrian } 494220297Sadrian 495220297Sadrian /* Setup reset pin interrupt */ 496220297Sadrian if (TUNABLE_INT_FETCH("reset_gpio", &sc->reset_gpio)) { 497220297Sadrian device_printf(dev, "\tHinted reset_gpio %d\n", sc->reset_gpio); 498220297Sadrian } 499220297Sadrian#ifdef notyet 500220297Sadrian if (sc->reset_gpio != -1) { 501220297Sadrian rt305x_gpio_pin_setflags(dev, sc->reset_gpio, 502220297Sadrian GPIO_PIN_INPUT|GPIO_PIN_INVOUT| 503220297Sadrian GPIO_PIN_INVOUT|GPIO_PIN_REPORT); 504220297Sadrian device_printf(dev, "\tUse reset_gpio %d\n", sc->reset_gpio); 505220297Sadrian } 506220297Sadrian#else 507220297Sadrian if (sc->reset_gpio != -1) { 508220297Sadrian rt305x_gpio_pin_setflags(dev, sc->reset_gpio, 509220297Sadrian GPIO_PIN_INPUT|GPIO_PIN_INVOUT); 510220297Sadrian device_printf(dev, "\tUse reset_gpio %d\n", sc->reset_gpio); 511220297Sadrian } 512220297Sadrian#endif 513220297Sadrian 514220297Sadrian device_add_child(dev, "gpioc", device_get_unit(dev)); 515220297Sadrian device_add_child(dev, "gpiobus", device_get_unit(dev)); 516220297Sadrian 517220297Sadrian 518220297Sadrian return (bus_generic_attach(dev)); 519220297Sadrian} 520220297Sadrian 521220297Sadrianstatic int 522220297Sadrianrt305x_gpio_detach(device_t dev) 523220297Sadrian{ 524220297Sadrian struct rt305x_gpio_softc *sc = device_get_softc(dev); 525220297Sadrian 526220297Sadrian KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); 527220297Sadrian 528220297Sadrian bus_generic_detach(dev); 529220297Sadrian 530220297Sadrian if (sc->gpio_mem_res) 531220297Sadrian bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid, 532220297Sadrian sc->gpio_mem_res); 533220297Sadrian 534220297Sadrian mtx_destroy(&sc->gpio_mtx); 535220297Sadrian 536220297Sadrian return(0); 537220297Sadrian} 538220297Sadrian 539220297Sadrian#ifdef notyet 540220297Sadrianstatic struct resource * 541220297Sadrianrt305x_gpio_alloc_resource(device_t bus, device_t child, int type, int *rid, 542220297Sadrian u_long start, u_long end, u_long count, u_int flags) 543220297Sadrian{ 544220297Sadrian struct obio_softc *sc = device_get_softc(bus); 545220297Sadrian struct resource *rv; 546220297Sadrian struct rman *rm; 547220297Sadrian 548220297Sadrian switch (type) { 549220297Sadrian case SYS_RES_GPIO: 550220297Sadrian rm = &sc->gpio_rman; 551220297Sadrian break; 552220297Sadrian default: 553220297Sadrian printf("%s: unknown resource type %d\n", __func__, type); 554220297Sadrian return (0); 555220297Sadrian } 556220297Sadrian 557220297Sadrian rv = rman_reserve_resource(rm, start, end, count, flags, child); 558220297Sadrian if (rv == 0) { 559220297Sadrian printf("%s: could not reserve resource\n", __func__); 560220297Sadrian return (0); 561220297Sadrian } 562220297Sadrian 563220297Sadrian rman_set_rid(rv, *rid); 564220297Sadrian 565220297Sadrian return (rv); 566220297Sadrian} 567220297Sadrian 568220297Sadrianstatic int 569220297Sadrianrt305x_gpio_activate_resource(device_t bus, device_t child, int type, int rid, 570220297Sadrian struct resource *r) 571220297Sadrian{ 572220297Sadrian 573220297Sadrian return (rman_activate_resource(r)); 574220297Sadrian} 575220297Sadrian 576220297Sadrianstatic int 577220297Sadrianrt305x_gpio_deactivate_resource(device_t bus, device_t child, int type, int rid, 578220297Sadrian struct resource *r) 579220297Sadrian{ 580220297Sadrian 581220297Sadrian return (rman_deactivate_resource(r)); 582220297Sadrian} 583220297Sadrian 584220297Sadrianstatic int 585220297Sadrianrt305x_gpio_release_resource(device_t dev, device_t child, int type, 586220297Sadrian int rid, struct resource *r) 587220297Sadrian{ 588220297Sadrian rman_release_resource(r); 589220297Sadrian return (0); 590220297Sadrian} 591220297Sadrian#endif 592220297Sadrian 593220297Sadrianstatic device_method_t rt305x_gpio_methods[] = { 594220297Sadrian DEVMETHOD(device_probe, rt305x_gpio_probe), 595220297Sadrian DEVMETHOD(device_attach, rt305x_gpio_attach), 596220297Sadrian DEVMETHOD(device_detach, rt305x_gpio_detach), 597220297Sadrian 598220297Sadrian /* GPIO protocol */ 599220297Sadrian DEVMETHOD(gpio_pin_max, rt305x_gpio_pin_max), 600220297Sadrian DEVMETHOD(gpio_pin_getname, rt305x_gpio_pin_getname), 601220297Sadrian DEVMETHOD(gpio_pin_getflags, rt305x_gpio_pin_getflags), 602220297Sadrian DEVMETHOD(gpio_pin_getcaps, rt305x_gpio_pin_getcaps), 603220297Sadrian DEVMETHOD(gpio_pin_setflags, rt305x_gpio_pin_setflags), 604220297Sadrian DEVMETHOD(gpio_pin_get, rt305x_gpio_pin_get), 605220297Sadrian DEVMETHOD(gpio_pin_set, rt305x_gpio_pin_set), 606220297Sadrian DEVMETHOD(gpio_pin_toggle, rt305x_gpio_pin_toggle), 607220297Sadrian {0, 0}, 608220297Sadrian}; 609220297Sadrian 610220297Sadrianstatic driver_t rt305x_gpio_driver = { 611220297Sadrian "gpio", 612220297Sadrian rt305x_gpio_methods, 613220297Sadrian sizeof(struct rt305x_gpio_softc), 614220297Sadrian}; 615220297Sadrianstatic devclass_t rt305x_gpio_devclass; 616220297Sadrian 617220297SadrianDRIVER_MODULE(rt305x_gpio, obio, rt305x_gpio_driver, 618220297Sadrian rt305x_gpio_devclass, 0, 0); 619