1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2018 Advanced Micro Devices 5 * All rights reserved. 6 * Copyright (c) 2025 The FreeBSD Foundation 7 * 8 * Portions of this software were developed by Aymeric Wibo 9 * <obiwac@freebsd.org> under sponsorship from the FreeBSD Foundation. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 #include "opt_acpi.h" 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/bus.h> 39 #include <sys/gpio.h> 40 #include <sys/interrupt.h> 41 #include <sys/kernel.h> 42 #include <sys/lock.h> 43 #include <sys/module.h> 44 #include <sys/mutex.h> 45 #include <sys/proc.h> 46 #include <sys/rman.h> 47 #include <sys/sysctl.h> 48 49 #include <machine/bus.h> 50 #include <machine/resource.h> 51 52 #include <contrib/dev/acpica/include/acpi.h> 53 #include <contrib/dev/acpica/include/accommon.h> 54 55 #include <dev/acpica/acpivar.h> 56 #include <dev/gpio/gpiobusvar.h> 57 58 #include "amdgpio.h" 59 60 static struct resource_spec amdgpio_spec[] = { 61 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 62 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE }, 63 { -1, 0, 0 } 64 }; 65 66 static inline uint32_t 67 amdgpio_read_4(struct amdgpio_softc *sc, bus_size_t off) 68 { 69 return (bus_read_4(sc->sc_res[0], off)); 70 } 71 72 static inline void 73 amdgpio_write_4(struct amdgpio_softc *sc, bus_size_t off, 74 uint32_t val) 75 { 76 bus_write_4(sc->sc_res[0], off, val); 77 } 78 79 static bool 80 amdgpio_is_pin_output(struct amdgpio_softc *sc, uint32_t pin) 81 { 82 uint32_t reg, val; 83 bool ret; 84 85 /* Get the current pin state */ 86 AMDGPIO_LOCK(sc); 87 88 reg = AMDGPIO_PIN_REGISTER(pin); 89 val = amdgpio_read_4(sc, reg); 90 91 if (val & BIT(OUTPUT_ENABLE_OFF)) 92 ret = true; 93 else 94 ret = false; 95 96 AMDGPIO_UNLOCK(sc); 97 98 return (ret); 99 } 100 101 static device_t 102 amdgpio_get_bus(device_t dev) 103 { 104 struct amdgpio_softc *sc; 105 106 sc = device_get_softc(dev); 107 108 dprintf("busdev %p\n", sc->sc_busdev); 109 return (sc->sc_busdev); 110 } 111 112 static int 113 amdgpio_pin_max(device_t dev, int *maxpin) 114 { 115 struct amdgpio_softc *sc; 116 117 sc = device_get_softc(dev); 118 119 *maxpin = sc->sc_npins - 1; 120 dprintf("npins %d maxpin %d\n", sc->sc_npins, *maxpin); 121 122 return (0); 123 } 124 125 static bool 126 amdgpio_valid_pin(struct amdgpio_softc *sc, int pin) 127 { 128 dprintf("pin %d\n", pin); 129 if (sc->sc_res[0] == NULL) 130 return (false); 131 132 if ((sc->sc_gpio_pins[pin].gp_pin == pin) && 133 (sc->sc_gpio_pins[pin].gp_caps != 0)) 134 return (true); 135 136 return (false); 137 } 138 139 static int 140 amdgpio_pin_getname(device_t dev, uint32_t pin, char *name) 141 { 142 struct amdgpio_softc *sc; 143 144 dprintf("pin %d\n", pin); 145 sc = device_get_softc(dev); 146 147 if (!amdgpio_valid_pin(sc, pin)) 148 return (EINVAL); 149 150 /* Set a very simple name */ 151 snprintf(name, GPIOMAXNAME, "%s", sc->sc_gpio_pins[pin].gp_name); 152 name[GPIOMAXNAME - 1] = '\0'; 153 154 dprintf("pin %d name %s\n", pin, name); 155 156 return (0); 157 } 158 159 static int 160 amdgpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 161 { 162 struct amdgpio_softc *sc; 163 164 sc = device_get_softc(dev); 165 166 dprintf("pin %d\n", pin); 167 if (!amdgpio_valid_pin(sc, pin)) 168 return (EINVAL); 169 170 *caps = sc->sc_gpio_pins[pin].gp_caps; 171 172 dprintf("pin %d caps 0x%x\n", pin, *caps); 173 174 return (0); 175 } 176 177 static int 178 amdgpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 179 { 180 struct amdgpio_softc *sc; 181 182 sc = device_get_softc(dev); 183 184 dprintf("pin %d\n", pin); 185 if (!amdgpio_valid_pin(sc, pin)) 186 return (EINVAL); 187 188 AMDGPIO_LOCK(sc); 189 190 *flags = sc->sc_gpio_pins[pin].gp_flags; 191 192 dprintf("pin %d flags 0x%x\n", pin, *flags); 193 194 AMDGPIO_UNLOCK(sc); 195 196 return (0); 197 } 198 199 static int 200 amdgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 201 { 202 struct amdgpio_softc *sc; 203 uint32_t reg, val; 204 205 sc = device_get_softc(dev); 206 207 dprintf("pin %d flags 0x%x\n", pin, flags); 208 if (!amdgpio_valid_pin(sc, pin)) 209 return (EINVAL); 210 211 if ((flags & ~AMDGPIO_DEFAULT_CAPS) != 0) { 212 device_printf(dev, "disallowed flags (0x%x) trying to be set " 213 "(allowed is 0x%x)\n", flags, AMDGPIO_DEFAULT_CAPS); 214 return (EINVAL); 215 } 216 217 /* Either input or output must be selected. */ 218 if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == 0) 219 return (EINVAL); 220 221 /* Not both directions simultaneously. */ 222 if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == 223 (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) 224 return (EINVAL); 225 226 /* Set the GPIO mode and state */ 227 AMDGPIO_LOCK(sc); 228 229 reg = AMDGPIO_PIN_REGISTER(pin); 230 val = amdgpio_read_4(sc, reg); 231 232 if ((flags & GPIO_PIN_INPUT) != 0) 233 val &= ~BIT(OUTPUT_ENABLE_OFF); 234 else 235 val |= BIT(OUTPUT_ENABLE_OFF); 236 237 val &= ~(BIT(PULL_DOWN_ENABLE_OFF) | BIT(PULL_UP_ENABLE_OFF)); 238 239 if ((flags & GPIO_PIN_PULLDOWN) != 0) 240 val |= BIT(PULL_DOWN_ENABLE_OFF); 241 if ((flags & GPIO_PIN_PULLUP) != 0) 242 val |= BIT(PULL_UP_ENABLE_OFF); 243 244 amdgpio_write_4(sc, reg, val); 245 246 sc->sc_gpio_pins[pin].gp_flags = flags; 247 dprintf("pin %d flags 0x%x val 0x%x gp_flags 0x%x\n", 248 pin, flags, val, sc->sc_gpio_pins[pin].gp_flags); 249 250 AMDGPIO_UNLOCK(sc); 251 252 return (0); 253 } 254 255 static int 256 amdgpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) 257 { 258 struct amdgpio_softc *sc; 259 uint32_t reg, val; 260 261 sc = device_get_softc(dev); 262 263 dprintf("pin %d\n", pin); 264 if (!amdgpio_valid_pin(sc, pin)) 265 return (EINVAL); 266 267 *value = 0; 268 269 AMDGPIO_LOCK(sc); 270 271 reg = AMDGPIO_PIN_REGISTER(pin); 272 val = amdgpio_read_4(sc, reg); 273 274 if ((sc->sc_gpio_pins[pin].gp_flags & GPIO_PIN_OUTPUT) != 0) { 275 if (val & BIT(OUTPUT_VALUE_OFF)) 276 *value = GPIO_PIN_HIGH; 277 else 278 *value = GPIO_PIN_LOW; 279 } else { 280 if (val & BIT(PIN_STS_OFF)) 281 *value = GPIO_PIN_HIGH; 282 else 283 *value = GPIO_PIN_LOW; 284 } 285 286 dprintf("pin %d value 0x%x\n", pin, *value); 287 288 AMDGPIO_UNLOCK(sc); 289 290 return (0); 291 } 292 293 static int 294 amdgpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 295 { 296 struct amdgpio_softc *sc; 297 uint32_t reg, val; 298 299 sc = device_get_softc(dev); 300 301 dprintf("pin %d value 0x%x\n", pin, value); 302 if (!amdgpio_valid_pin(sc, pin)) 303 return (EINVAL); 304 305 if (!amdgpio_is_pin_output(sc, pin)) 306 return (EINVAL); 307 308 AMDGPIO_LOCK(sc); 309 310 reg = AMDGPIO_PIN_REGISTER(pin); 311 val = amdgpio_read_4(sc, reg); 312 313 if (value == GPIO_PIN_LOW) 314 val &= ~BIT(OUTPUT_VALUE_OFF); 315 else 316 val |= BIT(OUTPUT_VALUE_OFF); 317 318 amdgpio_write_4(sc, reg, val); 319 320 dprintf("pin %d value 0x%x val 0x%x\n", pin, value, val); 321 322 AMDGPIO_UNLOCK(sc); 323 324 return (0); 325 } 326 327 static int 328 amdgpio_pin_toggle(device_t dev, uint32_t pin) 329 { 330 struct amdgpio_softc *sc; 331 uint32_t reg, val; 332 333 sc = device_get_softc(dev); 334 335 dprintf("pin %d\n", pin); 336 if (!amdgpio_valid_pin(sc, pin)) 337 return (EINVAL); 338 339 if (!amdgpio_is_pin_output(sc, pin)) 340 return (EINVAL); 341 342 /* Toggle the pin */ 343 AMDGPIO_LOCK(sc); 344 345 reg = AMDGPIO_PIN_REGISTER(pin); 346 val = amdgpio_read_4(sc, reg); 347 dprintf("pin %d value before 0x%x\n", pin, val); 348 val = val ^ BIT(OUTPUT_VALUE_OFF); 349 dprintf("pin %d value after 0x%x\n", pin, val); 350 amdgpio_write_4(sc, reg, val); 351 352 AMDGPIO_UNLOCK(sc); 353 354 return (0); 355 } 356 357 static int 358 amdgpio_probe(device_t dev) 359 { 360 static char *gpio_ids[] = { "AMD0030", "AMDI0030", NULL }; 361 int rv; 362 363 if (acpi_disabled("gpio")) 364 return (ENXIO); 365 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids, NULL); 366 if (rv <= 0) 367 device_set_desc(dev, "AMD GPIO Controller"); 368 369 return (rv); 370 } 371 372 static void 373 amdgpio_eoi_locked(struct amdgpio_softc *sc) 374 { 375 uint32_t master_reg = amdgpio_read_4(sc, WAKE_INT_MASTER_REG); 376 377 AMDGPIO_ASSERT_LOCKED(sc); 378 master_reg |= EOI_MASK; 379 amdgpio_write_4(sc, WAKE_INT_MASTER_REG, master_reg); 380 } 381 382 static void 383 amdgpio_eoi(struct amdgpio_softc *sc) 384 { 385 AMDGPIO_LOCK(sc); 386 amdgpio_eoi_locked(sc); 387 AMDGPIO_UNLOCK(sc); 388 } 389 390 static int 391 amdgpio_intr_filter(void *arg) 392 { 393 struct amdgpio_softc *sc = arg; 394 int off, rv = FILTER_STRAY; 395 uint32_t reg; 396 397 /* We can lock in the filter routine as it is MTX_SPIN. */ 398 AMDGPIO_LOCK(sc); 399 400 /* 401 * TODO Instead of just reading the registers of all pins, we should 402 * read WAKE_INT_STATUS_REG0/1. A bit set in here denotes a group of 403 * 4 pins where at least one has an interrupt for us. Then we can just 404 * iterate over those 4 pins. 405 * 406 * See GPIO_Interrupt_Status_Index_0 in BKDG. 407 */ 408 for (size_t pin = 0; pin < AMD_GPIO_PINS_EXPOSED; pin++) { 409 off = AMDGPIO_PIN_REGISTER(pin); 410 reg = amdgpio_read_4(sc, off); 411 if ((reg & UNSERVICED_INTERRUPT_MASK) == 0) 412 continue; 413 /* 414 * Must write 1's to wake/interrupt status bits to clear them. 415 * We can do this simply by writing back to the register. 416 */ 417 amdgpio_write_4(sc, off, reg); 418 } 419 420 amdgpio_eoi_locked(sc); 421 AMDGPIO_UNLOCK(sc); 422 423 rv = FILTER_HANDLED; 424 return (rv); 425 } 426 427 static void 428 amdgpio_intr_handler(void *arg) 429 { 430 /* TODO */ 431 } 432 433 static int 434 amdgpio_attach(device_t dev) 435 { 436 struct amdgpio_softc *sc; 437 int i, pin, bank, reg; 438 uint32_t flags; 439 440 sc = device_get_softc(dev); 441 sc->sc_dev = dev; 442 sc->sc_handle = acpi_get_handle(dev); 443 444 AMDGPIO_LOCK_INIT(sc); 445 446 sc->sc_nbanks = AMD_GPIO_NUM_PIN_BANK; 447 sc->sc_npins = AMD_GPIO_PINS_MAX; 448 sc->sc_bank_prefix = AMD_GPIO_PREFIX; 449 sc->sc_pin_info = kernzp_pins; 450 sc->sc_ngroups = nitems(kernzp_groups); 451 sc->sc_groups = kernzp_groups; 452 453 if (bus_alloc_resources(dev, amdgpio_spec, sc->sc_res)) { 454 device_printf(dev, "could not allocate resources\n"); 455 goto err_rsrc; 456 } 457 458 sc->sc_bst = rman_get_bustag(sc->sc_res[0]); 459 sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); 460 461 /* Set up interrupt handler. */ 462 if (bus_setup_intr(dev, sc->sc_res[1], INTR_TYPE_MISC | INTR_MPSAFE, 463 amdgpio_intr_filter, amdgpio_intr_handler, sc, &sc->sc_intr_handle) 464 != 0) { 465 device_printf(dev, "couldn't set up interrupt\n"); 466 goto err_intr; 467 } 468 469 /* Initialize all possible pins to be Invalid */ 470 for (i = 0; i < AMD_GPIO_PINS_MAX ; i++) { 471 snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME, 472 "Unexposed PIN %d", i); 473 sc->sc_gpio_pins[i].gp_pin = -1; 474 sc->sc_gpio_pins[i].gp_caps = 0; 475 sc->sc_gpio_pins[i].gp_flags = 0; 476 } 477 478 /* 479 * Initialize only driver exposed pins with appropriate capabilities. 480 * 481 * XXX Also mask and disable interrupts on all pins, since we don't 482 * support them at the moment. 483 */ 484 for (i = 0; i < AMD_GPIO_PINS_EXPOSED ; i++) { 485 pin = kernzp_pins[i].pin_num; 486 bank = pin/AMD_GPIO_PINS_PER_BANK; 487 snprintf(sc->sc_gpio_pins[pin].gp_name, GPIOMAXNAME, "%s%d_%s", 488 AMD_GPIO_PREFIX, bank, kernzp_pins[i].pin_name); 489 sc->sc_gpio_pins[pin].gp_pin = pin; 490 sc->sc_gpio_pins[pin].gp_caps = AMDGPIO_DEFAULT_CAPS; 491 sc->sc_gpio_pins[pin].gp_flags = 492 amdgpio_is_pin_output(sc, pin) ? 493 GPIO_PIN_OUTPUT : GPIO_PIN_INPUT; 494 495 reg = AMDGPIO_PIN_REGISTER(pin); 496 flags = amdgpio_read_4(sc, reg); 497 flags &= ~(1 << INTERRUPT_ENABLE_OFF); 498 flags &= ~(1 << INTERRUPT_MASK_OFF); 499 amdgpio_write_4(sc, reg, flags); 500 } 501 amdgpio_eoi(sc); 502 503 sc->sc_busdev = gpiobus_add_bus(dev); 504 if (sc->sc_busdev == NULL) { 505 device_printf(dev, "could not attach gpiobus\n"); 506 goto err_bus; 507 } 508 509 bus_attach_children(dev); 510 return (0); 511 512 err_bus: 513 bus_teardown_intr(dev, sc->sc_res[1], sc->sc_intr_handle); 514 err_intr: 515 bus_release_resources(dev, amdgpio_spec, sc->sc_res); 516 err_rsrc: 517 AMDGPIO_LOCK_DESTROY(sc); 518 519 return (ENXIO); 520 } 521 522 static int 523 amdgpio_detach(device_t dev) 524 { 525 struct amdgpio_softc *sc; 526 sc = device_get_softc(dev); 527 528 if (sc->sc_busdev) 529 gpiobus_detach_bus(dev); 530 if (sc->sc_intr_handle) 531 bus_teardown_intr(dev, sc->sc_res[1], sc->sc_intr_handle); 532 bus_release_resources(dev, amdgpio_spec, sc->sc_res); 533 534 AMDGPIO_LOCK_DESTROY(sc); 535 536 return (0); 537 } 538 539 static device_method_t amdgpio_methods[] = { 540 /* Device interface */ 541 DEVMETHOD(device_probe, amdgpio_probe), 542 DEVMETHOD(device_attach, amdgpio_attach), 543 DEVMETHOD(device_detach, amdgpio_detach), 544 545 /* GPIO protocol */ 546 DEVMETHOD(gpio_get_bus, amdgpio_get_bus), 547 DEVMETHOD(gpio_pin_max, amdgpio_pin_max), 548 DEVMETHOD(gpio_pin_getname, amdgpio_pin_getname), 549 DEVMETHOD(gpio_pin_getcaps, amdgpio_pin_getcaps), 550 DEVMETHOD(gpio_pin_getflags, amdgpio_pin_getflags), 551 DEVMETHOD(gpio_pin_setflags, amdgpio_pin_setflags), 552 DEVMETHOD(gpio_pin_get, amdgpio_pin_get), 553 DEVMETHOD(gpio_pin_set, amdgpio_pin_set), 554 DEVMETHOD(gpio_pin_toggle, amdgpio_pin_toggle), 555 556 DEVMETHOD_END 557 }; 558 559 static driver_t amdgpio_driver = { 560 "gpio", 561 amdgpio_methods, 562 sizeof(struct amdgpio_softc), 563 }; 564 565 DRIVER_MODULE(amdgpio, acpi, amdgpio_driver, 0, 0); 566 MODULE_DEPEND(amdgpio, acpi, 1, 1, 1); 567 MODULE_DEPEND(amdgpio, gpiobus, 1, 1, 1); 568 MODULE_VERSION(amdgpio, 1); 569