From nobody Sun Nov 03 16:16:56 2024 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4XhKVc6rSrz5cNtb; Sun, 03 Nov 2024 16:16:56 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4XhKVc52ryz4RyB; Sun, 3 Nov 2024 16:16:56 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1730650616; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=LR1lrfBrdfP10BcAZVl2/2o9v3tMkJOm/Usl1zNQqMo=; b=KzeFk5mLXO/FiaT4/G3I5Zr0lJ0/N74k0fe6YH5Tfy+uuJALsYqfyaUSy4mTsTRpPdON2m N+Fy7ZVpO3dHJOVuVKiaCvRI4iOTJMmSke2ZFpeNbR0MacWkjrP3WiXw4nMtN/h3kiDOJb lrqH7FWKW3nCWWH9PNOXOhM5pvESYPAFEo3JQ8kf78YHfcxuh84jUpi8Mr255aDohgHEEk KP8hTx57X0q/ue6/bizb07PKBSurLNQJyj9Y5cIVrG2aX3nS78WNsGaufLqPdkpHd+MLoT DPUU4gDyI0Wf5Ext9RYMGBzz7QtyksTnEAQxJnhSUHFG5AkqqMyR+WoFQE1j5A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1730650616; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=LR1lrfBrdfP10BcAZVl2/2o9v3tMkJOm/Usl1zNQqMo=; b=A0lUD8CGjmkyEpTfW48bvFZ7N66mbmO4nzbaXOsbfhce4kGwRLjdVxhe09jXEKozdA0e78 EgS3n6kh+tKjA5/GmHx1L7pYcg1QTGtBXdn6U4u3zBzsrjgzCCj5U73j1dOLsSNkwd0le7 jrnvqx8TT4mxWonWz8c63kTh8wAf+bdG9iqi3jq+ua8cxBuMm74rkWcnBr08AzSf0EmSI0 jMExr8wcZbsbgghy6hxn6zDtor1thH+QjC/c0PDrCEjnwQIEKCW8qSKFbi0m/+aDFaaLdK trfipF2oIbQTYz624Ho/US2OrBBrQ5HdHdvLVfxI9mzxbCmAsv7mepHJf2zE9g== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1730650616; a=rsa-sha256; cv=none; b=u/A6pnpdi9vWWgAjXG6Bdfi9MUA8nahO/tOKyrp3S0acVx6tG6fabQaIbCqsdl6ZUowH14 gpQAncWikF8dBA79RoS7h2/rBjj6YFbRIZNPZCVqfJGcq6j8Y/H9tHEXeUGxFlqgj3BsAm /A/3q0IjrYVE9szGsQynpHrI3dRhsb5lpOMqN52/4WOG2uLBOTHi+N4md7fhmM65KP3rIi IjMSr3HU6DGvzGINQ6ve9kkfRu59hzwRJp1fPRN3ex7aahJ8V6bdQDg6Tf7lIjxq/GLsjR D7mSevn1baHsyUFx3S+JFwcvrvtxL84Kc1YBlZKCAyLmGIBJj6p7d/FeCcucxw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4XhKVc4fXxzw7s; Sun, 3 Nov 2024 16:16:56 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 4A3GGugr036623; Sun, 3 Nov 2024 16:16:56 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 4A3GGunL036619; Sun, 3 Nov 2024 16:16:56 GMT (envelope-from git) Date: Sun, 3 Nov 2024 16:16:56 GMT Message-Id: <202411031616.4A3GGunL036619@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Colin Percival Subject: git: 1db6ffb2a482 - releng/14.2 - GPIO: Add ACPI _AEI support List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: cperciva X-Git-Repository: src X-Git-Refname: refs/heads/releng/14.2 X-Git-Reftype: branch X-Git-Commit: 1db6ffb2a482dee109bbb596f31e9d8d035153c4 Auto-Submitted: auto-generated The branch releng/14.2 has been updated by cperciva: URL: https://cgit.FreeBSD.org/src/commit/?id=1db6ffb2a482dee109bbb596f31e9d8d035153c4 commit 1db6ffb2a482dee109bbb596f31e9d8d035153c4 Author: Colin Percival AuthorDate: 2024-10-22 18:53:55 +0000 Commit: Colin Percival CommitDate: 2024-11-03 16:15:39 +0000 GPIO: Add ACPI _AEI support Changes to acpi_gpiobus.c handle discovering and parsing the _AEI objects and storing necessary data in device ivars. A new gpioaei.c file implements the device, which simply requests an interrupt when the pin is triggered and invokes the appropriate _Exx or _Lxx ACPI method. This makes the GPIO "power button" work on arm64 Graviton systems, allowing EC2 "Stop"/"Reboot" instance calls to be handled cleanly. (Prior to this change, those requests would time out after 4 minutes and the instance would be forcibly killed.) Reviewed by: imp, andrew, Ahmad Khalifa Approved by: re (kib) MFC after: 3 days Sponsored by: Amazon Differential Revision: https://reviews.freebsd.org/D47253 Co-authored-by: Andrew Turner (cherry picked from commit 9709bda03cd0f20eba0ba4276fc3c2e06354a54f) (cherry picked from commit c2cd78d9446ebe79accf6c1862230dfbe7276525) --- sys/conf/files | 1 + sys/dev/gpio/acpi_gpiobus.c | 121 +++++++++++++++++++++++++++++++++++ sys/dev/gpio/acpi_gpiobusvar.h | 49 ++++++++++++++ sys/dev/gpio/gpioaei.c | 131 ++++++++++++++++++++++++++++++++++++++ sys/modules/gpio/Makefile | 2 +- sys/modules/gpio/gpioaei/Makefile | 14 ++++ 6 files changed, 317 insertions(+), 1 deletion(-) diff --git a/sys/conf/files b/sys/conf/files index 5239f38d5154..3810032f7094 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1745,6 +1745,7 @@ dev/gpio/acpi_gpiobus.c optional acpi gpio dev/gpio/dwgpio/dwgpio.c optional gpio dwgpio fdt dev/gpio/dwgpio/dwgpio_bus.c optional gpio dwgpio fdt dev/gpio/dwgpio/dwgpio_if.m optional gpio dwgpio fdt +dev/gpio/gpioaei.c optional acpi gpio dev/gpio/gpiobacklight.c optional gpiobacklight fdt dev/gpio/gpiokeys.c optional gpiokeys fdt dev/gpio/gpiokeys_codes.c optional gpiokeys fdt diff --git a/sys/dev/gpio/acpi_gpiobus.c b/sys/dev/gpio/acpi_gpiobus.c index 9828170daeca..14ded4539a5e 100644 --- a/sys/dev/gpio/acpi_gpiobus.c +++ b/sys/dev/gpio/acpi_gpiobus.c @@ -35,6 +35,9 @@ #include #include +#include + +#include "gpiobus_if.h" struct acpi_gpiobus_softc { struct gpiobus_softc super_sc; @@ -46,6 +49,13 @@ struct acpi_gpiobus_ctx { ACPI_HANDLE dev_handle; }; +struct acpi_gpiobus_ivar +{ + struct gpiobus_ivar gpiobus; /* Must come first */ + ACPI_HANDLE dev_handle; /* ACPI handle for bus */ + uint32_t flags; +}; + static uint32_t acpi_gpiobus_convflags(ACPI_RESOURCE_GPIO *gpio_res) { @@ -136,6 +146,74 @@ acpi_gpiobus_enumerate_res(ACPI_RESOURCE *res, void *context) return (AE_OK); } +static struct acpi_gpiobus_ivar * +acpi_gpiobus_setup_devinfo(device_t bus, device_t child, + ACPI_RESOURCE_GPIO *gpio_res) +{ + struct acpi_gpiobus_ivar *devi; + + devi = malloc(sizeof(*devi), M_DEVBUF, M_NOWAIT | M_ZERO); + if (devi == NULL) + return (NULL); + resource_list_init(&devi->gpiobus.rl); + + devi->flags = acpi_gpiobus_convflags(gpio_res); + if (acpi_quirks & ACPI_Q_AEI_NOPULL) + devi->flags &= ~GPIO_PIN_PULLUP; + + devi->gpiobus.npins = 1; + if (gpiobus_alloc_ivars(&devi->gpiobus) != 0) { + free(devi, M_DEVBUF); + return (NULL); + } + + for (int i = 0; i < devi->gpiobus.npins; i++) + devi->gpiobus.pins[i] = gpio_res->PinTable[i]; + + return (devi); +} + +static ACPI_STATUS +acpi_gpiobus_enumerate_aei(ACPI_RESOURCE *res, void *context) +{ + ACPI_RESOURCE_GPIO *gpio_res = &res->Data.Gpio; + struct acpi_gpiobus_ctx *ctx = context; + device_t bus = ctx->sc->sc_busdev; + device_t child; + struct acpi_gpiobus_ivar *devi; + + /* Check that we have a GpioInt object. */ + if (res->Type != ACPI_RESOURCE_TYPE_GPIO) + return (AE_OK); + if (gpio_res->ConnectionType != ACPI_RESOURCE_GPIO_TYPE_INT) + return (AE_OK); + + /* Add a child. */ + child = device_add_child_ordered(bus, 0, "gpio_aei", -1); + if (child == NULL) + return (AE_OK); + devi = acpi_gpiobus_setup_devinfo(bus, child, gpio_res); + if (devi == NULL) { + device_delete_child(bus, child); + return (AE_OK); + } + device_set_ivars(child, devi); + + for (int i = 0; i < devi->gpiobus.npins; i++) { + if (GPIOBUS_PIN_SETFLAGS(bus, child, 0, devi->flags)) { + gpiobus_free_ivars(&devi->gpiobus); + free(devi, M_DEVBUF); + device_delete_child(bus, child); + return (AE_OK); + } + } + + /* Pass ACPI information to children. */ + devi->dev_handle = ctx->dev_handle; + + return (AE_OK); +} + static ACPI_STATUS acpi_gpiobus_enumerate(ACPI_HANDLE handle, UINT32 depth, void *context, void **result) @@ -272,6 +350,13 @@ acpi_gpiobus_attach(device_t dev) if (ACPI_FAILURE(status)) device_printf(dev, "Failed to enumerate GPIO resources\n"); + /* Look for AEI children */ + status = AcpiWalkResources(handle, "_AEI", acpi_gpiobus_enumerate_aei, + &ctx); + + if (ACPI_FAILURE(status)) + device_printf(dev, "Failed to enumerate GPIO resources\n"); + return (0); } @@ -294,12 +379,48 @@ acpi_gpiobus_detach(device_t dev) return (gpiobus_detach(dev)); } +int +gpio_pin_get_by_acpi_index(device_t consumer, uint32_t idx, + gpio_pin_t *out_pin) +{ + struct acpi_gpiobus_ivar *devi; + int rv; + + rv = gpio_pin_get_by_child_index(consumer, idx, out_pin); + if (rv != 0) + return (rv); + + devi = device_get_ivars(consumer); + (*out_pin)->flags = devi->flags; + + return (0); +} + +static int +acpi_gpiobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct acpi_gpiobus_ivar *devi = device_get_ivars(child); + + switch (which) { + case ACPI_GPIOBUS_IVAR_HANDLE: + *result = (uintptr_t)devi->dev_handle; + break; + default: + return (gpiobus_read_ivar(dev, child, which, result)); + } + + return (0); +} + static device_method_t acpi_gpiobus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, acpi_gpiobus_probe), DEVMETHOD(device_attach, acpi_gpiobus_attach), DEVMETHOD(device_detach, acpi_gpiobus_detach), + /* Bus interface */ + DEVMETHOD(bus_read_ivar, acpi_gpiobus_read_ivar), + DEVMETHOD_END }; diff --git a/sys/dev/gpio/acpi_gpiobusvar.h b/sys/dev/gpio/acpi_gpiobusvar.h new file mode 100644 index 000000000000..77cb91110cb5 --- /dev/null +++ b/sys/dev/gpio/acpi_gpiobusvar.h @@ -0,0 +1,49 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Colin Percival + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __ACPI_GPIOBUS_H__ +#define __ACPI_GPIOBUS_H__ + +#include + +#include + +enum acpi_gpiobus_ivars { + ACPI_GPIOBUS_IVAR_HANDLE = 10600, +}; + +#define ACPI_GPIOBUS_ACCESSOR(var, ivar, type) \ + __BUS_ACCESSOR(acpi_gpiobus, var, ACPI_GPIOBUS, ivar, type) + +ACPI_GPIOBUS_ACCESSOR(handle, HANDLE, ACPI_HANDLE) + +#undef ACPI_GPIOBUS_ACCESSOR + +int gpio_pin_get_by_acpi_index(device_t consumer, uint32_t idx, + gpio_pin_t *out_pin); + +#endif /* __ACPI_GPIOBUS_H__ */ diff --git a/sys/dev/gpio/gpioaei.c b/sys/dev/gpio/gpioaei.c new file mode 100644 index 000000000000..050f259a2127 --- /dev/null +++ b/sys/dev/gpio/gpioaei.c @@ -0,0 +1,131 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Colin Percival + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include "gpiobus_if.h" + +#include +#include + +#include +#include + +struct gpio_aei_softc { + ACPI_HANDLE handle; + char objname[5]; /* "_EXX" or "_LXX" */ + struct resource * intr_res; + int intr_rid; + void * intr_cookie; +}; + +static int +gpio_aei_probe(device_t dev) +{ + + /* We only match when gpiobus explicitly requested gpio_aei. */ + return (BUS_PROBE_NOWILDCARD); +} + +static void +gpio_aei_intr(void * arg) +{ + struct gpio_aei_softc * sc = arg; + + /* Ask ACPI to run the appropriate _Exx or _Lxx method. */ + AcpiEvaluateObject(sc->handle, sc->objname, NULL, NULL); +} + +static int +gpio_aei_attach(device_t dev) +{ + struct gpio_aei_softc * sc = device_get_softc(dev); + gpio_pin_t pin; + int err; + + /* This is us. */ + device_set_desc(dev, "ACPI Event Information Device"); + + /* Store parameters needed by gpio_aei_intr. */ + sc->handle = acpi_gpiobus_get_handle(dev); + if (gpio_pin_get_by_acpi_index(dev, 0, &pin) != 0) { + device_printf(dev, "Unable to get the input pin\n"); + return (ENXIO); + } + sprintf(sc->objname, "_%c%02X", + (pin->flags & GPIO_INTR_EDGE_MASK) ? 'E' : 'L', pin->pin); + + /* Support for GPIO pins > 255 is not implemented. */ + if (pin->pin > 255) { + device_printf(dev, "ACPI Event Information Device does not support pins > 255"); + return (ENOTSUP); + } + + /* Set up the interrupt. */ + if ((sc->intr_res = gpio_alloc_intr_resource(dev, &sc->intr_rid, + RF_ACTIVE, pin, pin->flags & GPIO_INTR_MASK)) == NULL) { + device_printf(dev, "Cannot allocate an IRQ\n"); + return (ENOTSUP); + } + err = bus_setup_intr(dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, + NULL, gpio_aei_intr, sc, &sc->intr_cookie); + if (err != 0) { + device_printf(dev, "Cannot set up IRQ\n"); + bus_release_resource(dev, SYS_RES_IRQ, sc->intr_rid, + sc->intr_res); + return (err); + } + + return (0); +} + +static int +gpio_aei_detach(device_t dev) +{ + struct gpio_aei_softc * sc = device_get_softc(dev); + + bus_teardown_intr(dev, sc->intr_res, sc->intr_cookie); + bus_release_resource(dev, SYS_RES_IRQ, sc->intr_rid, sc->intr_res); + return (0); +} + +static device_method_t gpio_aei_methods[] = { + /* Device interface. */ + DEVMETHOD(device_probe, gpio_aei_probe), + DEVMETHOD(device_attach, gpio_aei_attach), + DEVMETHOD(device_detach, gpio_aei_detach), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(gpio_aei, gpio_aei_driver, gpio_aei_methods, sizeof(struct gpio_aei_softc)); +DRIVER_MODULE(gpio_aei, gpiobus, gpio_aei_driver, NULL, NULL); +MODULE_DEPEND(gpio_aei, acpi_gpiobus, 1, 1, 1); diff --git a/sys/modules/gpio/Makefile b/sys/modules/gpio/Makefile index ffb3581d1f01..1d7f69f1836d 100644 --- a/sys/modules/gpio/Makefile +++ b/sys/modules/gpio/Makefile @@ -24,7 +24,7 @@ # SUCH DAMAGE. # -SUBDIR = gpiobus gpioiic gpioled gpiospi gpioths +SUBDIR = gpioaei gpiobus gpioiic gpioled gpiospi gpioths .if !empty(OPT_FDT) SUBDIR += gpiokeys gpiopps diff --git a/sys/modules/gpio/gpioaei/Makefile b/sys/modules/gpio/gpioaei/Makefile new file mode 100644 index 000000000000..514dcd80a35e --- /dev/null +++ b/sys/modules/gpio/gpioaei/Makefile @@ -0,0 +1,14 @@ +.PATH: ${SRCTOP}/sys/dev/gpio/ + +KMOD= gpioaei +SRCS= gpioaei.c + +SRCS+= \ + bus_if.h \ + device_if.h \ + gpio_if.h \ + gpiobus_if.h + +CFLAGS+= -I. -I${SRCTOP}/sys/dev/gpio/ + +.include