1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2018 Advanced Micro Devices 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 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include "opt_acpi.h" 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/bus.h> 37 #include <sys/gpio.h> 38 #include <sys/interrupt.h> 39 #include <sys/kernel.h> 40 #include <sys/lock.h> 41 #include <sys/module.h> 42 #include <sys/mutex.h> 43 #include <sys/proc.h> 44 #include <sys/rman.h> 45 #include <sys/sysctl.h> 46 47 #include <machine/bus.h> 48 #include <machine/resource.h> 49 50 #include <contrib/dev/acpica/include/acpi.h> 51 #include <contrib/dev/acpica/include/accommon.h> 52 53 #include <dev/acpica/acpivar.h> 54 #include <dev/gpio/gpiobusvar.h> 55 56 #include "gpio_if.h" 57 #include "amdgpio.h" 58 59 static struct resource_spec amdgpio_spec[] = { 60 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 61 { -1, 0, 0 } 62 }; 63 64 static inline uint32_t 65 amdgpio_read_4(struct amdgpio_softc *sc, bus_size_t off) 66 { 67 return (bus_read_4(sc->sc_res[0], off)); 68 } 69 70 static inline void 71 amdgpio_write_4(struct amdgpio_softc *sc, bus_size_t off, 72 uint32_t val) 73 { 74 bus_write_4(sc->sc_res[0], off, val); 75 } 76 77 static bool 78 amdgpio_is_pin_output(struct amdgpio_softc *sc, uint32_t pin) 79 { 80 uint32_t reg, val; 81 bool ret; 82 83 /* Get the current pin state */ 84 AMDGPIO_LOCK(sc); 85 86 reg = AMDGPIO_PIN_REGISTER(pin); 87 val = amdgpio_read_4(sc, reg); 88 89 if (val & BIT(OUTPUT_ENABLE_OFF)) 90 ret = true; 91 else 92 ret = false; 93 94 AMDGPIO_UNLOCK(sc); 95 96 return (ret); 97 } 98 99 static device_t 100 amdgpio_get_bus(device_t dev) 101 { 102 struct amdgpio_softc *sc; 103 104 sc = device_get_softc(dev); 105 106 dprintf("busdev %p\n", sc->sc_busdev); 107 return (sc->sc_busdev); 108 } 109 110 static int 111 amdgpio_pin_max(device_t dev, int *maxpin) 112 { 113 struct amdgpio_softc *sc; 114 115 sc = device_get_softc(dev); 116 117 *maxpin = sc->sc_npins - 1; 118 dprintf("npins %d maxpin %d\n", sc->sc_npins, *maxpin); 119 120 return (0); 121 } 122 123 static bool 124 amdgpio_valid_pin(struct amdgpio_softc *sc, int pin) 125 { 126 dprintf("pin %d\n", pin); 127 if (sc->sc_res[0] == NULL) 128 return (false); 129 130 if ((sc->sc_gpio_pins[pin].gp_pin == pin) && 131 (sc->sc_gpio_pins[pin].gp_caps != 0)) 132 return (true); 133 134 return (false); 135 } 136 137 static int 138 amdgpio_pin_getname(device_t dev, uint32_t pin, char *name) 139 { 140 struct amdgpio_softc *sc; 141 142 dprintf("pin %d\n", pin); 143 sc = device_get_softc(dev); 144 145 if (!amdgpio_valid_pin(sc, pin)) 146 return (EINVAL); 147 148 /* Set a very simple name */ 149 snprintf(name, GPIOMAXNAME, "%s", sc->sc_gpio_pins[pin].gp_name); 150 name[GPIOMAXNAME - 1] = '\0'; 151 152 dprintf("pin %d name %s\n", pin, name); 153 154 return (0); 155 } 156 157 static int 158 amdgpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 159 { 160 struct amdgpio_softc *sc; 161 162 sc = device_get_softc(dev); 163 164 dprintf("pin %d\n", pin); 165 if (!amdgpio_valid_pin(sc, pin)) 166 return (EINVAL); 167 168 *caps = sc->sc_gpio_pins[pin].gp_caps; 169 170 dprintf("pin %d caps 0x%x\n", pin, *caps); 171 172 return (0); 173 } 174 175 static int 176 amdgpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 177 { 178 struct amdgpio_softc *sc; 179 180 sc = device_get_softc(dev); 181 182 183 dprintf("pin %d\n", pin); 184 if (!amdgpio_valid_pin(sc, pin)) 185 return (EINVAL); 186 187 AMDGPIO_LOCK(sc); 188 189 *flags = sc->sc_gpio_pins[pin].gp_flags; 190 191 dprintf("pin %d flags 0x%x\n", pin, *flags); 192 193 AMDGPIO_UNLOCK(sc); 194 195 return (0); 196 } 197 198 static int 199 amdgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 200 { 201 struct amdgpio_softc *sc; 202 uint32_t reg, val, allowed; 203 204 sc = device_get_softc(dev); 205 206 dprintf("pin %d flags 0x%x\n", pin, flags); 207 if (!amdgpio_valid_pin(sc, pin)) 208 return (EINVAL); 209 210 allowed = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; 211 212 /* 213 * Only directtion flag allowed 214 */ 215 if (flags & ~allowed) 216 return (EINVAL); 217 218 /* 219 * Not both directions simultaneously 220 */ 221 if ((flags & allowed) == allowed) 222 return (EINVAL); 223 224 /* Set the GPIO mode and state */ 225 AMDGPIO_LOCK(sc); 226 227 reg = AMDGPIO_PIN_REGISTER(pin); 228 val = amdgpio_read_4(sc, reg); 229 230 if (flags & GPIO_PIN_INPUT) { 231 val &= ~BIT(OUTPUT_ENABLE_OFF); 232 sc->sc_gpio_pins[pin].gp_flags = GPIO_PIN_INPUT; 233 } else { 234 val |= BIT(OUTPUT_ENABLE_OFF); 235 sc->sc_gpio_pins[pin].gp_flags = GPIO_PIN_OUTPUT; 236 } 237 238 amdgpio_write_4(sc, reg, val); 239 240 dprintf("pin %d flags 0x%x val 0x%x gp_flags 0x%x\n", 241 pin, flags, val, sc->sc_gpio_pins[pin].gp_flags); 242 243 AMDGPIO_UNLOCK(sc); 244 245 return (0); 246 } 247 248 static int 249 amdgpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) 250 { 251 struct amdgpio_softc *sc; 252 uint32_t reg, val; 253 254 sc = device_get_softc(dev); 255 256 dprintf("pin %d\n", pin); 257 if (!amdgpio_valid_pin(sc, pin)) 258 return (EINVAL); 259 260 *value = 0; 261 262 AMDGPIO_LOCK(sc); 263 264 reg = AMDGPIO_PIN_REGISTER(pin); 265 val = amdgpio_read_4(sc, reg); 266 267 if ((sc->sc_gpio_pins[pin].gp_flags & GPIO_PIN_OUTPUT) != 0) { 268 if (val & BIT(OUTPUT_VALUE_OFF)) 269 *value = GPIO_PIN_HIGH; 270 else 271 *value = GPIO_PIN_LOW; 272 } else { 273 if (val & BIT(PIN_STS_OFF)) 274 *value = GPIO_PIN_HIGH; 275 else 276 *value = GPIO_PIN_LOW; 277 } 278 279 dprintf("pin %d value 0x%x\n", pin, *value); 280 281 AMDGPIO_UNLOCK(sc); 282 283 return (0); 284 } 285 286 static int 287 amdgpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 288 { 289 struct amdgpio_softc *sc; 290 uint32_t reg, val; 291 292 sc = device_get_softc(dev); 293 294 dprintf("pin %d value 0x%x\n", pin, value); 295 if (!amdgpio_valid_pin(sc, pin)) 296 return (EINVAL); 297 298 if (!amdgpio_is_pin_output(sc, pin)) 299 return (EINVAL); 300 301 AMDGPIO_LOCK(sc); 302 303 reg = AMDGPIO_PIN_REGISTER(pin); 304 val = amdgpio_read_4(sc, reg); 305 306 if (value == GPIO_PIN_LOW) 307 val &= ~BIT(OUTPUT_VALUE_OFF); 308 else 309 val |= BIT(OUTPUT_VALUE_OFF); 310 311 amdgpio_write_4(sc, reg, val); 312 313 dprintf("pin %d value 0x%x val 0x%x\n", pin, value, val); 314 315 AMDGPIO_UNLOCK(sc); 316 317 return (0); 318 } 319 320 static int 321 amdgpio_pin_toggle(device_t dev, uint32_t pin) 322 { 323 struct amdgpio_softc *sc; 324 uint32_t reg, val; 325 326 sc = device_get_softc(dev); 327 328 dprintf("pin %d\n", pin); 329 if (!amdgpio_valid_pin(sc, pin)) 330 return (EINVAL); 331 332 if (!amdgpio_is_pin_output(sc, pin)) 333 return (EINVAL); 334 335 /* Toggle the pin */ 336 AMDGPIO_LOCK(sc); 337 338 reg = AMDGPIO_PIN_REGISTER(pin); 339 val = amdgpio_read_4(sc, reg); 340 dprintf("pin %d value before 0x%x\n", pin, val); 341 val = val ^ BIT(OUTPUT_VALUE_OFF); 342 dprintf("pin %d value after 0x%x\n", pin, val); 343 amdgpio_write_4(sc, reg, val); 344 345 AMDGPIO_UNLOCK(sc); 346 347 return (0); 348 } 349 350 static int 351 amdgpio_probe(device_t dev) 352 { 353 static char *gpio_ids[] = { "AMD0030", "AMDI0030", NULL }; 354 int rv; 355 356 if (acpi_disabled("gpio")) 357 return (ENXIO); 358 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids, NULL); 359 if (rv <= 0) 360 device_set_desc(dev, "AMD GPIO Controller"); 361 362 return (rv); 363 } 364 365 static int 366 amdgpio_attach(device_t dev) 367 { 368 struct amdgpio_softc *sc; 369 int i, pin, bank; 370 371 sc = device_get_softc(dev); 372 sc->sc_dev = dev; 373 sc->sc_handle = acpi_get_handle(dev); 374 375 AMDGPIO_LOCK_INIT(sc); 376 377 sc->sc_nbanks = AMD_GPIO_NUM_PIN_BANK; 378 sc->sc_npins = AMD_GPIO_PINS_MAX; 379 sc->sc_bank_prefix = AMD_GPIO_PREFIX; 380 sc->sc_pin_info = kernzp_pins; 381 sc->sc_ngroups = nitems(kernzp_groups); 382 sc->sc_groups = kernzp_groups; 383 384 if (bus_alloc_resources(dev, amdgpio_spec, sc->sc_res)) { 385 device_printf(dev, "could not allocate resources\n"); 386 goto err_rsrc; 387 } 388 389 sc->sc_bst = rman_get_bustag(sc->sc_res[0]); 390 sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); 391 392 /* Initialize all possible pins to be Invalid */ 393 for (i = 0; i < AMD_GPIO_PINS_MAX ; i++) { 394 snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME, 395 "Unexposed PIN %d", i); 396 sc->sc_gpio_pins[i].gp_pin = -1; 397 sc->sc_gpio_pins[i].gp_caps = 0; 398 sc->sc_gpio_pins[i].gp_flags = 0; 399 } 400 401 /* Initialize only driver exposed pins with appropriate capabilities */ 402 for (i = 0; i < AMD_GPIO_PINS_EXPOSED ; i++) { 403 pin = kernzp_pins[i].pin_num; 404 bank = pin/AMD_GPIO_PINS_PER_BANK; 405 snprintf(sc->sc_gpio_pins[pin].gp_name, GPIOMAXNAME, "%s%d_%s", 406 AMD_GPIO_PREFIX, bank, kernzp_pins[i].pin_name); 407 sc->sc_gpio_pins[pin].gp_pin = pin; 408 sc->sc_gpio_pins[pin].gp_caps = AMDGPIO_DEFAULT_CAPS; 409 sc->sc_gpio_pins[pin].gp_flags = 410 amdgpio_is_pin_output(sc, pin) ? 411 GPIO_PIN_OUTPUT : GPIO_PIN_INPUT; 412 } 413 414 sc->sc_busdev = gpiobus_attach_bus(dev); 415 if (sc->sc_busdev == NULL) { 416 device_printf(dev, "could not attach gpiobus\n"); 417 goto err_bus; 418 } 419 420 return (0); 421 422 err_bus: 423 bus_release_resources(dev, amdgpio_spec, sc->sc_res); 424 425 err_rsrc: 426 AMDGPIO_LOCK_DESTROY(sc); 427 428 return (ENXIO); 429 } 430 431 432 static int 433 amdgpio_detach(device_t dev) 434 { 435 struct amdgpio_softc *sc; 436 sc = device_get_softc(dev); 437 438 if (sc->sc_busdev) 439 gpiobus_detach_bus(dev); 440 441 bus_release_resources(dev, amdgpio_spec, sc->sc_res); 442 443 AMDGPIO_LOCK_DESTROY(sc); 444 445 return (0); 446 } 447 448 static device_method_t amdgpio_methods[] = { 449 /* Device interface */ 450 DEVMETHOD(device_probe, amdgpio_probe), 451 DEVMETHOD(device_attach, amdgpio_attach), 452 DEVMETHOD(device_detach, amdgpio_detach), 453 454 /* GPIO protocol */ 455 DEVMETHOD(gpio_get_bus, amdgpio_get_bus), 456 DEVMETHOD(gpio_pin_max, amdgpio_pin_max), 457 DEVMETHOD(gpio_pin_getname, amdgpio_pin_getname), 458 DEVMETHOD(gpio_pin_getcaps, amdgpio_pin_getcaps), 459 DEVMETHOD(gpio_pin_getflags, amdgpio_pin_getflags), 460 DEVMETHOD(gpio_pin_setflags, amdgpio_pin_setflags), 461 DEVMETHOD(gpio_pin_get, amdgpio_pin_get), 462 DEVMETHOD(gpio_pin_set, amdgpio_pin_set), 463 DEVMETHOD(gpio_pin_toggle, amdgpio_pin_toggle), 464 465 DEVMETHOD_END 466 }; 467 468 static driver_t amdgpio_driver = { 469 "gpio", 470 amdgpio_methods, 471 sizeof(struct amdgpio_softc), 472 }; 473 474 static devclass_t amdgpio_devclass; 475 DRIVER_MODULE(amdgpio, acpi, amdgpio_driver, amdgpio_devclass, 0, 0); 476 MODULE_DEPEND(amdgpio, acpi, 1, 1, 1); 477 MODULE_DEPEND(amdgpio, gpiobus, 1, 1, 1); 478 MODULE_VERSION(amdgpio, 1); 479