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 (val & BIT(OUTPUT_VALUE_OFF)) 268 *value = GPIO_PIN_HIGH; 269 else 270 *value = GPIO_PIN_LOW; 271 272 dprintf("pin %d value 0x%x\n", pin, *value); 273 274 AMDGPIO_UNLOCK(sc); 275 276 return (0); 277 } 278 279 static int 280 amdgpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 281 { 282 struct amdgpio_softc *sc; 283 uint32_t reg, val; 284 285 sc = device_get_softc(dev); 286 287 dprintf("pin %d value 0x%x\n", pin, value); 288 if (!amdgpio_valid_pin(sc, pin)) 289 return (EINVAL); 290 291 if (!amdgpio_is_pin_output(sc, pin)) 292 return (EINVAL); 293 294 AMDGPIO_LOCK(sc); 295 296 reg = AMDGPIO_PIN_REGISTER(pin); 297 val = amdgpio_read_4(sc, reg); 298 299 if (value == GPIO_PIN_LOW) 300 val &= ~BIT(OUTPUT_VALUE_OFF); 301 else 302 val |= BIT(OUTPUT_VALUE_OFF); 303 304 amdgpio_write_4(sc, reg, val); 305 306 dprintf("pin %d value 0x%x val 0x%x\n", pin, value, val); 307 308 AMDGPIO_UNLOCK(sc); 309 310 return (0); 311 } 312 313 static int 314 amdgpio_pin_toggle(device_t dev, uint32_t pin) 315 { 316 struct amdgpio_softc *sc; 317 uint32_t reg, val; 318 319 sc = device_get_softc(dev); 320 321 dprintf("pin %d\n", pin); 322 if (!amdgpio_valid_pin(sc, pin)) 323 return (EINVAL); 324 325 if (!amdgpio_is_pin_output(sc, pin)) 326 return (EINVAL); 327 328 /* Toggle the pin */ 329 AMDGPIO_LOCK(sc); 330 331 reg = AMDGPIO_PIN_REGISTER(pin); 332 val = amdgpio_read_4(sc, reg); 333 dprintf("pin %d value before 0x%x\n", pin, val); 334 val = val ^ BIT(OUTPUT_VALUE_OFF); 335 dprintf("pin %d value after 0x%x\n", pin, val); 336 amdgpio_write_4(sc, reg, val); 337 338 AMDGPIO_UNLOCK(sc); 339 340 return (0); 341 } 342 343 static int 344 amdgpio_probe(device_t dev) 345 { 346 static char *gpio_ids[] = { "AMD0030", "AMDI0030", NULL }; 347 int rv; 348 349 if (acpi_disabled("gpio")) 350 return (ENXIO); 351 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids, NULL); 352 353 if (rv <= 0) 354 device_set_desc(dev, "AMD GPIO Controller"); 355 356 return (rv); 357 } 358 359 static int 360 amdgpio_attach(device_t dev) 361 { 362 struct amdgpio_softc *sc; 363 int i, pin, bank; 364 365 sc = device_get_softc(dev); 366 sc->sc_dev = dev; 367 sc->sc_handle = acpi_get_handle(dev); 368 369 AMDGPIO_LOCK_INIT(sc); 370 371 sc->sc_nbanks = AMD_GPIO_NUM_PIN_BANK; 372 sc->sc_npins = AMD_GPIO_PINS_MAX; 373 sc->sc_bank_prefix = AMD_GPIO_PREFIX; 374 sc->sc_pin_info = kernzp_pins; 375 sc->sc_ngroups = nitems(kernzp_groups); 376 sc->sc_groups = kernzp_groups; 377 378 if (bus_alloc_resources(dev, amdgpio_spec, sc->sc_res)) { 379 device_printf(dev, "could not allocate resources\n"); 380 goto err_rsrc; 381 } 382 383 sc->sc_bst = rman_get_bustag(sc->sc_res[0]); 384 sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); 385 386 /* Initialize all possible pins to be Invalid */ 387 for (i = 0; i < AMD_GPIO_PINS_MAX ; i++) { 388 snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME, 389 "Unexposed PIN %d\n", i); 390 sc->sc_gpio_pins[i].gp_pin = -1; 391 sc->sc_gpio_pins[i].gp_caps = 0; 392 sc->sc_gpio_pins[i].gp_flags = 0; 393 } 394 395 /* Initialize only driver exposed pins with appropriate capabilities */ 396 for (i = 0; i < AMD_GPIO_PINS_EXPOSED ; i++) { 397 pin = kernzp_pins[i].pin_num; 398 bank = pin/AMD_GPIO_PINS_PER_BANK; 399 snprintf(sc->sc_gpio_pins[pin].gp_name, GPIOMAXNAME, "%s%d_%s\n", 400 AMD_GPIO_PREFIX, bank, kernzp_pins[i].pin_name); 401 sc->sc_gpio_pins[pin].gp_pin = pin; 402 sc->sc_gpio_pins[pin].gp_caps = AMDGPIO_DEFAULT_CAPS; 403 sc->sc_gpio_pins[pin].gp_flags = (amdgpio_is_pin_output(sc, pin)? 404 GPIO_PIN_OUTPUT : GPIO_PIN_INPUT); 405 } 406 407 sc->sc_busdev = gpiobus_attach_bus(dev); 408 if (sc->sc_busdev == NULL) { 409 device_printf(dev, "could not attach gpiobus\n"); 410 goto err_bus; 411 } 412 413 return (0); 414 415 err_bus: 416 bus_release_resources(dev, amdgpio_spec, sc->sc_res); 417 418 err_rsrc: 419 AMDGPIO_LOCK_DESTROY(sc); 420 421 return (ENXIO); 422 } 423 424 425 static int 426 amdgpio_detach(device_t dev) 427 { 428 struct amdgpio_softc *sc; 429 sc = device_get_softc(dev); 430 431 if (sc->sc_busdev) 432 gpiobus_detach_bus(dev); 433 434 bus_release_resources(dev, amdgpio_spec, sc->sc_res); 435 436 AMDGPIO_LOCK_DESTROY(sc); 437 438 return (0); 439 } 440 441 static device_method_t amdgpio_methods[] = { 442 /* Device interface */ 443 DEVMETHOD(device_probe, amdgpio_probe), 444 DEVMETHOD(device_attach, amdgpio_attach), 445 DEVMETHOD(device_detach, amdgpio_detach), 446 447 /* GPIO protocol */ 448 DEVMETHOD(gpio_get_bus, amdgpio_get_bus), 449 DEVMETHOD(gpio_pin_max, amdgpio_pin_max), 450 DEVMETHOD(gpio_pin_getname, amdgpio_pin_getname), 451 DEVMETHOD(gpio_pin_getcaps, amdgpio_pin_getcaps), 452 DEVMETHOD(gpio_pin_getflags, amdgpio_pin_getflags), 453 DEVMETHOD(gpio_pin_setflags, amdgpio_pin_setflags), 454 DEVMETHOD(gpio_pin_get, amdgpio_pin_get), 455 DEVMETHOD(gpio_pin_set, amdgpio_pin_set), 456 DEVMETHOD(gpio_pin_toggle, amdgpio_pin_toggle), 457 458 DEVMETHOD_END 459 }; 460 461 static driver_t amdgpio_driver = { 462 "gpio", 463 amdgpio_methods, 464 sizeof(struct amdgpio_softc), 465 }; 466 467 static devclass_t amdgpio_devclass; 468 DRIVER_MODULE(amdgpio, acpi, amdgpio_driver, amdgpio_devclass, 0, 0); 469 MODULE_DEPEND(amdgpio, acpi, 1, 1, 1); 470 MODULE_DEPEND(amdgpio, gpiobus, 1, 1, 1); 471 MODULE_VERSION(amdgpio, 1); 472