1 /*- 2 * Copyright (c) 2015 Rubicon Communications, LLC (Netgate) 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 #include <sys/cdefs.h> 27 /* 28 * GPIO driver for the ADI Engineering RCC-VE and RCC-DFF/DFFv2. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/bus.h> 34 #include <sys/gpio.h> 35 #include <sys/kernel.h> 36 #include <sys/module.h> 37 #include <sys/rman.h> 38 39 #include <machine/bus.h> 40 41 #include <dev/gpio/gpiobusvar.h> 42 #include <isa/isavar.h> 43 44 #include "gpio_if.h" 45 46 #define RCC_GPIO_BASE 0x500 47 #define RCC_GPIO_USE_SEL 0x00 48 #define RCC_GPIO_IO_SEL 0x04 49 #define RCC_GPIO_GP_LVL 0x08 50 51 struct rcc_gpio_pin { 52 uint32_t pin; 53 const char *name; 54 uint32_t caps; 55 }; 56 57 static struct rcc_gpio_pin rcc_pins[] = { 58 { .pin = (1 << 11), .name = "reset switch", .caps = GPIO_PIN_INPUT }, 59 { .pin = (1 << 15), .name = "red LED", .caps = GPIO_PIN_OUTPUT }, 60 { .pin = (1 << 17), .name = "green LED", .caps = GPIO_PIN_OUTPUT }, 61 #if 0 62 { .pin = (1 << 16), .name = "HD1 LED", .caps = GPIO_PIN_OUTPUT }, 63 { .pin = (1 << 18), .name = "HD2 LED", .caps = GPIO_PIN_OUTPUT }, 64 #endif 65 }; 66 67 struct rcc_gpio_softc { 68 device_t sc_dev; 69 device_t sc_busdev; 70 struct mtx sc_mtx; 71 struct resource *sc_io_res; 72 bus_space_tag_t sc_bst; 73 bus_space_handle_t sc_bsh; 74 uint32_t sc_output; 75 int sc_io_rid; 76 int sc_gpio_npins; 77 }; 78 79 #define RCC_GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 80 #define RCC_GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 81 #define RCC_WRITE(_sc, _off, _val) \ 82 bus_space_write_4((_sc)->sc_bst, (_sc)->sc_bsh, _off, _val) 83 #define RCC_READ(_sc, _off) \ 84 bus_space_read_4((_sc)->sc_bst, (_sc)->sc_bsh, _off) 85 86 static void 87 rcc_gpio_modify_bits(struct rcc_gpio_softc *sc, uint32_t reg, uint32_t mask, 88 uint32_t writebits) 89 { 90 uint32_t value; 91 92 RCC_GPIO_LOCK(sc); 93 value = RCC_READ(sc, reg); 94 value &= ~mask; 95 value |= writebits; 96 RCC_WRITE(sc, reg, value); 97 RCC_GPIO_UNLOCK(sc); 98 } 99 100 static device_t 101 rcc_gpio_get_bus(device_t dev) 102 { 103 struct rcc_gpio_softc *sc; 104 105 sc = device_get_softc(dev); 106 107 return (sc->sc_busdev); 108 } 109 110 static int 111 rcc_gpio_pin_max(device_t dev, int *maxpin) 112 { 113 struct rcc_gpio_softc *sc; 114 115 sc = device_get_softc(dev); 116 *maxpin = sc->sc_gpio_npins - 1; 117 118 return (0); 119 } 120 121 static int 122 rcc_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 123 { 124 struct rcc_gpio_softc *sc; 125 126 sc = device_get_softc(dev); 127 if (pin >= sc->sc_gpio_npins) 128 return (EINVAL); 129 130 *caps = rcc_pins[pin].caps; 131 132 return (0); 133 } 134 135 static int 136 rcc_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 137 { 138 struct rcc_gpio_softc *sc; 139 140 sc = device_get_softc(dev); 141 if (pin >= sc->sc_gpio_npins) 142 return (EINVAL); 143 144 /* Flags cannot be changed. */ 145 *flags = rcc_pins[pin].caps; 146 147 return (0); 148 } 149 150 static int 151 rcc_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 152 { 153 struct rcc_gpio_softc *sc; 154 155 sc = device_get_softc(dev); 156 if (pin >= sc->sc_gpio_npins) 157 return (EINVAL); 158 159 memcpy(name, rcc_pins[pin].name, GPIOMAXNAME); 160 161 return (0); 162 } 163 164 static int 165 rcc_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 166 { 167 struct rcc_gpio_softc *sc; 168 169 sc = device_get_softc(dev); 170 if (pin >= sc->sc_gpio_npins) 171 return (EINVAL); 172 173 /* Flags cannot be changed - risk of short-circuit!!! */ 174 175 return (0); 176 } 177 178 static int 179 rcc_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 180 { 181 struct rcc_gpio_softc *sc; 182 183 sc = device_get_softc(dev); 184 if (pin >= sc->sc_gpio_npins) 185 return (EINVAL); 186 187 if ((rcc_pins[pin].caps & GPIO_PIN_OUTPUT) == 0) 188 return (EINVAL); 189 190 RCC_GPIO_LOCK(sc); 191 if (value) 192 sc->sc_output |= (1 << rcc_pins[pin].pin); 193 else 194 sc->sc_output &= ~(1 << rcc_pins[pin].pin); 195 RCC_WRITE(sc, RCC_GPIO_GP_LVL, sc->sc_output); 196 RCC_GPIO_UNLOCK(sc); 197 198 return (0); 199 } 200 201 static int 202 rcc_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 203 { 204 struct rcc_gpio_softc *sc; 205 uint32_t value; 206 207 sc = device_get_softc(dev); 208 if (pin >= sc->sc_gpio_npins) 209 return (EINVAL); 210 211 RCC_GPIO_LOCK(sc); 212 if (rcc_pins[pin].caps & GPIO_PIN_INPUT) 213 value = RCC_READ(sc, RCC_GPIO_GP_LVL); 214 else 215 value = sc->sc_output; 216 RCC_GPIO_UNLOCK(sc); 217 *val = (value & (1 << rcc_pins[pin].pin)) ? 1 : 0; 218 219 return (0); 220 } 221 222 static int 223 rcc_gpio_pin_toggle(device_t dev, uint32_t pin) 224 { 225 struct rcc_gpio_softc *sc; 226 227 sc = device_get_softc(dev); 228 if (pin >= sc->sc_gpio_npins) 229 return (EINVAL); 230 231 if ((rcc_pins[pin].caps & GPIO_PIN_OUTPUT) == 0) 232 return (EINVAL); 233 234 RCC_GPIO_LOCK(sc); 235 if ((sc->sc_output & (1 << rcc_pins[pin].pin)) == 0) 236 sc->sc_output |= (1 << rcc_pins[pin].pin); 237 else 238 sc->sc_output &= ~(1 << rcc_pins[pin].pin); 239 RCC_WRITE(sc, RCC_GPIO_GP_LVL, sc->sc_output); 240 RCC_GPIO_UNLOCK(sc); 241 242 return (0); 243 } 244 245 static int 246 rcc_gpio_probe(device_t dev) 247 { 248 char *prod; 249 int port; 250 251 /* 252 * We don't know of any PnP ID's for this GPIO controller. 253 */ 254 if (isa_get_logicalid(dev) != 0) 255 return (ENXIO); 256 257 /* 258 * We have to have an IO port hint that is valid. 259 */ 260 port = isa_get_port(dev); 261 if (port != RCC_GPIO_BASE) 262 return (ENXIO); 263 264 prod = kern_getenv("smbios.system.product"); 265 if (prod == NULL || 266 (strcmp(prod, "RCC-VE") != 0 && strcmp(prod, "RCC-DFF") != 0)) 267 return (ENXIO); 268 269 device_set_desc(dev, "RCC-VE/DFF GPIO controller"); 270 271 return (BUS_PROBE_DEFAULT); 272 } 273 274 static int 275 rcc_gpio_attach(device_t dev) 276 { 277 int i; 278 struct rcc_gpio_softc *sc; 279 280 sc = device_get_softc(dev); 281 sc->sc_dev = dev; 282 283 /* Allocate IO resources. */ 284 sc->sc_io_rid = 0; 285 sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 286 &sc->sc_io_rid, RF_ACTIVE); 287 if (sc->sc_io_res == NULL) { 288 device_printf(dev, "cannot allocate memory window\n"); 289 return (ENXIO); 290 } 291 sc->sc_bst = rman_get_bustag(sc->sc_io_res); 292 sc->sc_bsh = rman_get_bushandle(sc->sc_io_res); 293 mtx_init(&sc->sc_mtx, "rcc-gpio", "gpio", MTX_DEF); 294 295 /* Initialize the pins. */ 296 sc->sc_gpio_npins = nitems(rcc_pins); 297 for (i = 0; i < sc->sc_gpio_npins; i++) { 298 /* Enable it for GPIO. */ 299 rcc_gpio_modify_bits(sc, RCC_GPIO_USE_SEL, 0, rcc_pins[i].pin); 300 /* Set the pin as input or output. */ 301 if (rcc_pins[i].caps & GPIO_PIN_OUTPUT) 302 rcc_gpio_modify_bits(sc, RCC_GPIO_IO_SEL, 303 rcc_pins[i].pin, 0); 304 else 305 rcc_gpio_modify_bits(sc, RCC_GPIO_IO_SEL, 306 0, rcc_pins[i].pin); 307 } 308 RCC_WRITE(sc, RCC_GPIO_GP_LVL, sc->sc_output); 309 310 /* Attach the gpiobus. */ 311 sc->sc_busdev = gpiobus_attach_bus(dev); 312 if (sc->sc_busdev == NULL) { 313 bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_io_rid, 314 sc->sc_io_res); 315 mtx_destroy(&sc->sc_mtx); 316 return (ENXIO); 317 } 318 319 return (0); 320 } 321 322 static int 323 rcc_gpio_detach(device_t dev) 324 { 325 int i; 326 struct rcc_gpio_softc *sc; 327 328 sc = device_get_softc(dev); 329 gpiobus_detach_bus(dev); 330 331 /* Disable the GPIO function. */ 332 for (i = 0; i < sc->sc_gpio_npins; i++) 333 rcc_gpio_modify_bits(sc, RCC_GPIO_USE_SEL, rcc_pins[i].pin, 0); 334 335 if (sc->sc_io_res != NULL) 336 bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_io_rid, 337 sc->sc_io_res); 338 mtx_destroy(&sc->sc_mtx); 339 340 return (0); 341 } 342 343 static device_method_t rcc_gpio_methods[] = { 344 /* Device interface */ 345 DEVMETHOD(device_probe, rcc_gpio_probe), 346 DEVMETHOD(device_attach, rcc_gpio_attach), 347 DEVMETHOD(device_detach, rcc_gpio_detach), 348 349 /* GPIO protocol */ 350 DEVMETHOD(gpio_get_bus, rcc_gpio_get_bus), 351 DEVMETHOD(gpio_pin_max, rcc_gpio_pin_max), 352 DEVMETHOD(gpio_pin_getname, rcc_gpio_pin_getname), 353 DEVMETHOD(gpio_pin_getflags, rcc_gpio_pin_getflags), 354 DEVMETHOD(gpio_pin_getcaps, rcc_gpio_pin_getcaps), 355 DEVMETHOD(gpio_pin_setflags, rcc_gpio_pin_setflags), 356 DEVMETHOD(gpio_pin_get, rcc_gpio_pin_get), 357 DEVMETHOD(gpio_pin_set, rcc_gpio_pin_set), 358 DEVMETHOD(gpio_pin_toggle, rcc_gpio_pin_toggle), 359 360 DEVMETHOD_END 361 }; 362 363 static driver_t rcc_gpio_driver = { 364 "gpio", 365 rcc_gpio_methods, 366 sizeof(struct rcc_gpio_softc), 367 }; 368 369 DRIVER_MODULE(rcc_gpio, isa, rcc_gpio_driver, 0, 0); 370 MODULE_DEPEND(rcc_gpio, gpiobus, 1, 1, 1); 371