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