1 /*- 2 * Copyright (c) 2020 Alstom Group. 3 * Copyright (c) 2020 Semihalf. 4 * Copyright (c) 2015 Justin Hibbits 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/conf.h> 37 #include <sys/bus.h> 38 #include <sys/kernel.h> 39 #include <sys/module.h> 40 #include <sys/mutex.h> 41 #include <sys/rman.h> 42 #include <sys/gpio.h> 43 44 #include <machine/bus.h> 45 #include <machine/resource.h> 46 #include <machine/stdarg.h> 47 48 #include <dev/gpio/gpiobusvar.h> 49 #include <dev/ofw/ofw_bus.h> 50 #include <dev/ofw/ofw_bus_subr.h> 51 52 #include "gpio_if.h" 53 54 #define MAXPIN (31) 55 56 #define VALID_PIN(u) ((u) >= 0 && (u) <= MAXPIN) 57 #define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ 58 GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL) 59 60 #define GPIO_LOCK(sc) mtx_lock(&(sc)->sc_mtx) 61 #define GPIO_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) 62 #define GPIO_LOCK_INIT(sc) \ 63 mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), \ 64 "gpio", MTX_DEF) 65 #define GPIO_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); 66 67 #define GPIO_GPDIR 0x0 68 #define GPIO_GPODR 0x4 69 #define GPIO_GPDAT 0x8 70 #define GPIO_GPIER 0xc 71 #define GPIO_GPIMR 0x10 72 #define GPIO_GPICR 0x14 73 #define GPIO_GPIBE 0x18 74 75 struct qoriq_gpio_softc { 76 device_t dev; 77 device_t busdev; 78 struct mtx sc_mtx; 79 struct resource *sc_mem; /* Memory resource */ 80 struct gpio_pin sc_pins[MAXPIN + 1]; 81 }; 82 83 static device_t 84 qoriq_gpio_get_bus(device_t dev) 85 { 86 struct qoriq_gpio_softc *sc; 87 88 sc = device_get_softc(dev); 89 90 return (sc->busdev); 91 } 92 93 static int 94 qoriq_gpio_pin_max(device_t dev, int *maxpin) 95 { 96 97 *maxpin = MAXPIN; 98 return (0); 99 } 100 101 /* Get a specific pin's capabilities. */ 102 static int 103 qoriq_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 104 { 105 struct qoriq_gpio_softc *sc; 106 107 sc = device_get_softc(dev); 108 109 if (!VALID_PIN(pin)) 110 return (EINVAL); 111 112 GPIO_LOCK(sc); 113 *caps = sc->sc_pins[pin].gp_caps; 114 GPIO_UNLOCK(sc); 115 116 return (0); 117 } 118 119 /* Get a specific pin's name. */ 120 static int 121 qoriq_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 122 { 123 124 if (!VALID_PIN(pin)) 125 return (EINVAL); 126 127 snprintf(name, GPIOMAXNAME, "qoriq_gpio%d.%d", 128 device_get_unit(dev), pin); 129 name[GPIOMAXNAME-1] = '\0'; 130 131 return (0); 132 } 133 134 static int 135 qoriq_gpio_pin_configure(device_t dev, uint32_t pin, uint32_t flags) 136 { 137 struct qoriq_gpio_softc *sc; 138 uint32_t reg; 139 140 sc = device_get_softc(dev); 141 142 if ((flags & sc->sc_pins[pin].gp_caps) != flags) { 143 return (EINVAL); 144 } 145 146 if (flags & GPIO_PIN_INPUT) { 147 reg = bus_read_4(sc->sc_mem, GPIO_GPDIR); 148 reg &= ~(1 << (31 - pin)); 149 bus_write_4(sc->sc_mem, GPIO_GPDIR, reg); 150 } 151 else if (flags & GPIO_PIN_OUTPUT) { 152 reg = bus_read_4(sc->sc_mem, GPIO_GPDIR); 153 reg |= (1 << (31 - pin)); 154 bus_write_4(sc->sc_mem, GPIO_GPDIR, reg); 155 reg = bus_read_4(sc->sc_mem, GPIO_GPODR); 156 if (flags & GPIO_PIN_OPENDRAIN) 157 reg |= (1 << (31 - pin)); 158 else 159 reg &= ~(1 << (31 - pin)); 160 bus_write_4(sc->sc_mem, GPIO_GPODR, reg); 161 } 162 sc->sc_pins[pin].gp_flags = flags; 163 164 return (0); 165 } 166 167 /* Set flags for the pin. */ 168 static int 169 qoriq_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 170 { 171 struct qoriq_gpio_softc *sc = device_get_softc(dev); 172 uint32_t ret; 173 174 if (!VALID_PIN(pin)) 175 return (EINVAL); 176 177 if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == 178 (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) 179 return (EINVAL); 180 181 GPIO_LOCK(sc); 182 ret = qoriq_gpio_pin_configure(dev, pin, flags); 183 GPIO_UNLOCK(sc); 184 return (0); 185 } 186 187 static int 188 qoriq_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *pflags) 189 { 190 struct qoriq_gpio_softc *sc; 191 192 if (!VALID_PIN(pin)) 193 return (EINVAL); 194 195 sc = device_get_softc(dev); 196 197 GPIO_LOCK(sc); 198 *pflags = sc->sc_pins[pin].gp_flags; 199 GPIO_UNLOCK(sc); 200 201 return (0); 202 } 203 204 /* Set a specific output pin's value. */ 205 static int 206 qoriq_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 207 { 208 struct qoriq_gpio_softc *sc = device_get_softc(dev); 209 uint32_t outvals; 210 uint8_t pinbit; 211 212 if (!VALID_PIN(pin) || value > 1) 213 return (EINVAL); 214 215 GPIO_LOCK(sc); 216 pinbit = 31 - pin; 217 218 outvals = bus_read_4(sc->sc_mem, GPIO_GPDAT); 219 outvals &= ~(1 << pinbit); 220 outvals |= (value << pinbit); 221 bus_write_4(sc->sc_mem, GPIO_GPDAT, outvals); 222 223 GPIO_UNLOCK(sc); 224 225 return (0); 226 } 227 228 /* Get a specific pin's input value. */ 229 static int 230 qoriq_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) 231 { 232 struct qoriq_gpio_softc *sc = device_get_softc(dev); 233 234 if (!VALID_PIN(pin)) 235 return (EINVAL); 236 237 *value = (bus_read_4(sc->sc_mem, GPIO_GPDAT) >> (31 - pin)) & 1; 238 239 return (0); 240 } 241 242 /* Toggle a pin's output value. */ 243 static int 244 qoriq_gpio_pin_toggle(device_t dev, uint32_t pin) 245 { 246 struct qoriq_gpio_softc *sc = device_get_softc(dev); 247 uint32_t val; 248 249 if (!VALID_PIN(pin)) 250 return (EINVAL); 251 252 GPIO_LOCK(sc); 253 254 val = bus_read_4(sc->sc_mem, GPIO_GPDAT); 255 val ^= (1 << (31 - pin)); 256 bus_write_4(sc->sc_mem, GPIO_GPDAT, val); 257 258 GPIO_UNLOCK(sc); 259 260 return (0); 261 } 262 263 static struct ofw_compat_data gpio_matches[] = { 264 {"fsl,qoriq-gpio", 1}, 265 {"fsl,pq3-gpio", 1}, 266 {"fsl,mpc8572-gpio", 1}, 267 {0, 0} 268 }; 269 270 static int 271 qoriq_gpio_probe(device_t dev) 272 { 273 274 if (ofw_bus_search_compatible(dev, gpio_matches)->ocd_data == 0) 275 return (ENXIO); 276 277 device_set_desc(dev, "Freescale QorIQ GPIO driver"); 278 279 return (0); 280 } 281 282 static int 283 qoriq_gpio_pin_access_32(device_t dev, uint32_t first_pin, uint32_t clear_pins, 284 uint32_t change_pins, uint32_t *orig_pins) 285 { 286 struct qoriq_gpio_softc *sc; 287 uint32_t hwstate; 288 289 sc = device_get_softc(dev); 290 291 if (first_pin != 0) 292 return (EINVAL); 293 294 GPIO_LOCK(sc); 295 hwstate = bus_read_4(sc->sc_mem, GPIO_GPDAT); 296 bus_write_4(sc->sc_mem, GPIO_GPDAT, 297 (hwstate & ~clear_pins) ^ change_pins); 298 GPIO_UNLOCK(sc); 299 300 if (orig_pins != NULL) 301 *orig_pins = hwstate; 302 303 return (0); 304 } 305 306 static int 307 qoriq_gpio_pin_config_32(device_t dev, uint32_t first_pin, uint32_t num_pins, 308 uint32_t *pin_flags) 309 { 310 uint32_t dir, odr, mask, reg; 311 struct qoriq_gpio_softc *sc; 312 uint32_t newflags[32]; 313 int i; 314 315 if (first_pin != 0 || !VALID_PIN(num_pins)) 316 return (EINVAL); 317 318 sc = device_get_softc(dev); 319 320 dir = odr = mask = 0; 321 322 for (i = 0; i < num_pins; i++) { 323 newflags[i] = 0; 324 mask |= (1 << i); 325 326 if (pin_flags[i] & GPIO_PIN_INPUT) { 327 newflags[i] = GPIO_PIN_INPUT; 328 dir &= ~(1 << i); 329 } else { 330 newflags[i] = GPIO_PIN_OUTPUT; 331 dir |= (1 << i); 332 333 if (pin_flags[i] & GPIO_PIN_OPENDRAIN) { 334 newflags[i] |= GPIO_PIN_OPENDRAIN; 335 odr |= (1 << i); 336 } else { 337 newflags[i] |= GPIO_PIN_PUSHPULL; 338 odr &= ~(1 << i); 339 } 340 } 341 } 342 343 GPIO_LOCK(sc); 344 345 reg = (bus_read_4(sc->sc_mem, GPIO_GPDIR) & ~mask) | dir; 346 bus_write_4(sc->sc_mem, GPIO_GPDIR, reg); 347 348 reg = (bus_read_4(sc->sc_mem, GPIO_GPODR) & ~mask) | odr; 349 bus_write_4(sc->sc_mem, GPIO_GPODR, reg); 350 351 for (i = 0; i < num_pins; i++) 352 sc->sc_pins[i].gp_flags = newflags[i]; 353 354 GPIO_UNLOCK(sc); 355 356 return (0); 357 } 358 359 static int 360 qoriq_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells, 361 pcell_t *gpios, uint32_t *pin, uint32_t *flags) 362 { 363 struct qoriq_gpio_softc *sc; 364 int err; 365 366 if (!VALID_PIN(gpios[0])) 367 return (EINVAL); 368 369 sc = device_get_softc(bus); 370 GPIO_LOCK(sc); 371 err = qoriq_gpio_pin_configure(bus, gpios[0], gpios[1]); 372 GPIO_UNLOCK(sc); 373 374 if (err == 0) { 375 *pin = gpios[0]; 376 *flags = gpios[1]; 377 } 378 379 return (err); 380 } 381 382 static int qoriq_gpio_detach(device_t dev); 383 384 static int 385 qoriq_gpio_attach(device_t dev) 386 { 387 struct qoriq_gpio_softc *sc = device_get_softc(dev); 388 int i, rid; 389 390 sc->dev = dev; 391 392 GPIO_LOCK_INIT(sc); 393 394 /* Allocate memory. */ 395 rid = 0; 396 sc->sc_mem = bus_alloc_resource_any(dev, 397 SYS_RES_MEMORY, &rid, RF_ACTIVE); 398 if (sc->sc_mem == NULL) { 399 device_printf(dev, "Can't allocate memory for device output port"); 400 qoriq_gpio_detach(dev); 401 return (ENOMEM); 402 } 403 404 for (i = 0; i <= MAXPIN; i++) 405 sc->sc_pins[i].gp_caps = DEFAULT_CAPS; 406 407 sc->busdev = gpiobus_attach_bus(dev); 408 if (sc->busdev == NULL) { 409 qoriq_gpio_detach(dev); 410 return (ENOMEM); 411 } 412 /* 413 * Enable the GPIO Input Buffer for all GPIOs. 414 * This is safe on devices without a GPIBE register, because those 415 * devices ignore writes and read 0's in undefined portions of the map. 416 */ 417 if (ofw_bus_is_compatible(dev, "fsl,qoriq-gpio")) 418 bus_write_4(sc->sc_mem, GPIO_GPIBE, 0xffffffff); 419 420 OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev); 421 422 return (0); 423 } 424 425 static int 426 qoriq_gpio_detach(device_t dev) 427 { 428 struct qoriq_gpio_softc *sc = device_get_softc(dev); 429 430 gpiobus_detach_bus(dev); 431 432 if (sc->sc_mem != NULL) { 433 /* Release output port resource. */ 434 bus_release_resource(dev, SYS_RES_MEMORY, 435 rman_get_rid(sc->sc_mem), sc->sc_mem); 436 } 437 438 GPIO_LOCK_DESTROY(sc); 439 440 return (0); 441 } 442 443 static device_method_t qoriq_gpio_methods[] = { 444 /* device_if */ 445 DEVMETHOD(device_probe, qoriq_gpio_probe), 446 DEVMETHOD(device_attach, qoriq_gpio_attach), 447 DEVMETHOD(device_detach, qoriq_gpio_detach), 448 449 /* GPIO protocol */ 450 DEVMETHOD(gpio_get_bus, qoriq_gpio_get_bus), 451 DEVMETHOD(gpio_pin_max, qoriq_gpio_pin_max), 452 DEVMETHOD(gpio_pin_getname, qoriq_gpio_pin_getname), 453 DEVMETHOD(gpio_pin_getcaps, qoriq_gpio_pin_getcaps), 454 DEVMETHOD(gpio_pin_get, qoriq_gpio_pin_get), 455 DEVMETHOD(gpio_pin_set, qoriq_gpio_pin_set), 456 DEVMETHOD(gpio_pin_getflags, qoriq_gpio_pin_getflags), 457 DEVMETHOD(gpio_pin_setflags, qoriq_gpio_pin_setflags), 458 DEVMETHOD(gpio_pin_toggle, qoriq_gpio_pin_toggle), 459 460 DEVMETHOD(gpio_map_gpios, qoriq_gpio_map_gpios), 461 DEVMETHOD(gpio_pin_access_32, qoriq_gpio_pin_access_32), 462 DEVMETHOD(gpio_pin_config_32, qoriq_gpio_pin_config_32), 463 464 DEVMETHOD_END 465 }; 466 467 static driver_t qoriq_gpio_driver = { 468 "gpio", 469 qoriq_gpio_methods, 470 sizeof(struct qoriq_gpio_softc), 471 }; 472 static devclass_t qoriq_gpio_devclass; 473 474 EARLY_DRIVER_MODULE(qoriq_gpio, simplebus, qoriq_gpio_driver, 475 qoriq_gpio_devclass, NULL, NULL, 476 BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE); 477