xref: /freebsd/sys/dev/amdgpio/amdgpio.c (revision 88b8b7f0c4e9948667a2279e78e975a784049cba)
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