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