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 dprintf("pin %d\n", pin); 183 if (!amdgpio_valid_pin(sc, pin)) 184 return (EINVAL); 185 186 AMDGPIO_LOCK(sc); 187 188 *flags = sc->sc_gpio_pins[pin].gp_flags; 189 190 dprintf("pin %d flags 0x%x\n", pin, *flags); 191 192 AMDGPIO_UNLOCK(sc); 193 194 return (0); 195 } 196 197 static int 198 amdgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 199 { 200 struct amdgpio_softc *sc; 201 uint32_t reg, val, allowed; 202 203 sc = device_get_softc(dev); 204 205 dprintf("pin %d flags 0x%x\n", pin, flags); 206 if (!amdgpio_valid_pin(sc, pin)) 207 return (EINVAL); 208 209 allowed = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; 210 211 /* 212 * Only directtion flag allowed 213 */ 214 if (flags & ~allowed) 215 return (EINVAL); 216 217 /* 218 * Not both directions simultaneously 219 */ 220 if ((flags & allowed) == allowed) 221 return (EINVAL); 222 223 /* Set the GPIO mode and state */ 224 AMDGPIO_LOCK(sc); 225 226 reg = AMDGPIO_PIN_REGISTER(pin); 227 val = amdgpio_read_4(sc, reg); 228 229 if (flags & GPIO_PIN_INPUT) { 230 val &= ~BIT(OUTPUT_ENABLE_OFF); 231 sc->sc_gpio_pins[pin].gp_flags = GPIO_PIN_INPUT; 232 } else { 233 val |= BIT(OUTPUT_ENABLE_OFF); 234 sc->sc_gpio_pins[pin].gp_flags = GPIO_PIN_OUTPUT; 235 } 236 237 amdgpio_write_4(sc, reg, val); 238 239 dprintf("pin %d flags 0x%x val 0x%x gp_flags 0x%x\n", 240 pin, flags, val, sc->sc_gpio_pins[pin].gp_flags); 241 242 AMDGPIO_UNLOCK(sc); 243 244 return (0); 245 } 246 247 static int 248 amdgpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) 249 { 250 struct amdgpio_softc *sc; 251 uint32_t reg, val; 252 253 sc = device_get_softc(dev); 254 255 dprintf("pin %d\n", pin); 256 if (!amdgpio_valid_pin(sc, pin)) 257 return (EINVAL); 258 259 *value = 0; 260 261 AMDGPIO_LOCK(sc); 262 263 reg = AMDGPIO_PIN_REGISTER(pin); 264 val = amdgpio_read_4(sc, reg); 265 266 if ((sc->sc_gpio_pins[pin].gp_flags & GPIO_PIN_OUTPUT) != 0) { 267 if (val & BIT(OUTPUT_VALUE_OFF)) 268 *value = GPIO_PIN_HIGH; 269 else 270 *value = GPIO_PIN_LOW; 271 } else { 272 if (val & BIT(PIN_STS_OFF)) 273 *value = GPIO_PIN_HIGH; 274 else 275 *value = GPIO_PIN_LOW; 276 } 277 278 dprintf("pin %d value 0x%x\n", pin, *value); 279 280 AMDGPIO_UNLOCK(sc); 281 282 return (0); 283 } 284 285 static int 286 amdgpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 287 { 288 struct amdgpio_softc *sc; 289 uint32_t reg, val; 290 291 sc = device_get_softc(dev); 292 293 dprintf("pin %d value 0x%x\n", pin, value); 294 if (!amdgpio_valid_pin(sc, pin)) 295 return (EINVAL); 296 297 if (!amdgpio_is_pin_output(sc, pin)) 298 return (EINVAL); 299 300 AMDGPIO_LOCK(sc); 301 302 reg = AMDGPIO_PIN_REGISTER(pin); 303 val = amdgpio_read_4(sc, reg); 304 305 if (value == GPIO_PIN_LOW) 306 val &= ~BIT(OUTPUT_VALUE_OFF); 307 else 308 val |= BIT(OUTPUT_VALUE_OFF); 309 310 amdgpio_write_4(sc, reg, val); 311 312 dprintf("pin %d value 0x%x val 0x%x\n", pin, value, val); 313 314 AMDGPIO_UNLOCK(sc); 315 316 return (0); 317 } 318 319 static int 320 amdgpio_pin_toggle(device_t dev, uint32_t pin) 321 { 322 struct amdgpio_softc *sc; 323 uint32_t reg, val; 324 325 sc = device_get_softc(dev); 326 327 dprintf("pin %d\n", pin); 328 if (!amdgpio_valid_pin(sc, pin)) 329 return (EINVAL); 330 331 if (!amdgpio_is_pin_output(sc, pin)) 332 return (EINVAL); 333 334 /* Toggle the pin */ 335 AMDGPIO_LOCK(sc); 336 337 reg = AMDGPIO_PIN_REGISTER(pin); 338 val = amdgpio_read_4(sc, reg); 339 dprintf("pin %d value before 0x%x\n", pin, val); 340 val = val ^ BIT(OUTPUT_VALUE_OFF); 341 dprintf("pin %d value after 0x%x\n", pin, val); 342 amdgpio_write_4(sc, reg, val); 343 344 AMDGPIO_UNLOCK(sc); 345 346 return (0); 347 } 348 349 static int 350 amdgpio_probe(device_t dev) 351 { 352 static char *gpio_ids[] = { "AMD0030", "AMDI0030", NULL }; 353 int rv; 354 355 if (acpi_disabled("gpio")) 356 return (ENXIO); 357 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids, NULL); 358 if (rv <= 0) 359 device_set_desc(dev, "AMD GPIO Controller"); 360 361 return (rv); 362 } 363 364 static int 365 amdgpio_attach(device_t dev) 366 { 367 struct amdgpio_softc *sc; 368 int i, pin, bank; 369 370 sc = device_get_softc(dev); 371 sc->sc_dev = dev; 372 sc->sc_handle = acpi_get_handle(dev); 373 374 AMDGPIO_LOCK_INIT(sc); 375 376 sc->sc_nbanks = AMD_GPIO_NUM_PIN_BANK; 377 sc->sc_npins = AMD_GPIO_PINS_MAX; 378 sc->sc_bank_prefix = AMD_GPIO_PREFIX; 379 sc->sc_pin_info = kernzp_pins; 380 sc->sc_ngroups = nitems(kernzp_groups); 381 sc->sc_groups = kernzp_groups; 382 383 if (bus_alloc_resources(dev, amdgpio_spec, sc->sc_res)) { 384 device_printf(dev, "could not allocate resources\n"); 385 goto err_rsrc; 386 } 387 388 sc->sc_bst = rman_get_bustag(sc->sc_res[0]); 389 sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); 390 391 /* Initialize all possible pins to be Invalid */ 392 for (i = 0; i < AMD_GPIO_PINS_MAX ; i++) { 393 snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME, 394 "Unexposed PIN %d", i); 395 sc->sc_gpio_pins[i].gp_pin = -1; 396 sc->sc_gpio_pins[i].gp_caps = 0; 397 sc->sc_gpio_pins[i].gp_flags = 0; 398 } 399 400 /* Initialize only driver exposed pins with appropriate capabilities */ 401 for (i = 0; i < AMD_GPIO_PINS_EXPOSED ; i++) { 402 pin = kernzp_pins[i].pin_num; 403 bank = pin/AMD_GPIO_PINS_PER_BANK; 404 snprintf(sc->sc_gpio_pins[pin].gp_name, GPIOMAXNAME, "%s%d_%s", 405 AMD_GPIO_PREFIX, bank, kernzp_pins[i].pin_name); 406 sc->sc_gpio_pins[pin].gp_pin = pin; 407 sc->sc_gpio_pins[pin].gp_caps = AMDGPIO_DEFAULT_CAPS; 408 sc->sc_gpio_pins[pin].gp_flags = 409 amdgpio_is_pin_output(sc, pin) ? 410 GPIO_PIN_OUTPUT : GPIO_PIN_INPUT; 411 } 412 413 sc->sc_busdev = gpiobus_attach_bus(dev); 414 if (sc->sc_busdev == NULL) { 415 device_printf(dev, "could not attach gpiobus\n"); 416 goto err_bus; 417 } 418 419 return (0); 420 421 err_bus: 422 bus_release_resources(dev, amdgpio_spec, sc->sc_res); 423 424 err_rsrc: 425 AMDGPIO_LOCK_DESTROY(sc); 426 427 return (ENXIO); 428 } 429 430 static int 431 amdgpio_detach(device_t dev) 432 { 433 struct amdgpio_softc *sc; 434 sc = device_get_softc(dev); 435 436 if (sc->sc_busdev) 437 gpiobus_detach_bus(dev); 438 439 bus_release_resources(dev, amdgpio_spec, sc->sc_res); 440 441 AMDGPIO_LOCK_DESTROY(sc); 442 443 return (0); 444 } 445 446 static device_method_t amdgpio_methods[] = { 447 /* Device interface */ 448 DEVMETHOD(device_probe, amdgpio_probe), 449 DEVMETHOD(device_attach, amdgpio_attach), 450 DEVMETHOD(device_detach, amdgpio_detach), 451 452 /* GPIO protocol */ 453 DEVMETHOD(gpio_get_bus, amdgpio_get_bus), 454 DEVMETHOD(gpio_pin_max, amdgpio_pin_max), 455 DEVMETHOD(gpio_pin_getname, amdgpio_pin_getname), 456 DEVMETHOD(gpio_pin_getcaps, amdgpio_pin_getcaps), 457 DEVMETHOD(gpio_pin_getflags, amdgpio_pin_getflags), 458 DEVMETHOD(gpio_pin_setflags, amdgpio_pin_setflags), 459 DEVMETHOD(gpio_pin_get, amdgpio_pin_get), 460 DEVMETHOD(gpio_pin_set, amdgpio_pin_set), 461 DEVMETHOD(gpio_pin_toggle, amdgpio_pin_toggle), 462 463 DEVMETHOD_END 464 }; 465 466 static driver_t amdgpio_driver = { 467 "gpio", 468 amdgpio_methods, 469 sizeof(struct amdgpio_softc), 470 }; 471 472 DRIVER_MODULE(amdgpio, acpi, amdgpio_driver, 0, 0); 473 MODULE_DEPEND(amdgpio, acpi, 1, 1, 1); 474 MODULE_DEPEND(amdgpio, gpiobus, 1, 1, 1); 475 MODULE_VERSION(amdgpio, 1); 476