Page MenuHomeFreeBSD

D47253.id145367.diff
No OneTemporary

D47253.id145367.diff

diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1740,6 +1740,7 @@
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
--- a/sys/dev/gpio/acpi_gpiobus.c
+++ b/sys/dev/gpio/acpi_gpiobus.c
@@ -35,6 +35,9 @@
#include <dev/acpica/acpivar.h>
#include <dev/gpio/gpiobusvar.h>
+#include <dev/gpio/acpi_gpiobusvar.h>
+
+#include "gpiobus_if.h"
struct acpi_gpiobus_softc {
struct gpiobus_softc super_sc;
@@ -44,6 +47,14 @@
struct acpi_gpiobus_ctx {
struct gpiobus_softc *sc;
ACPI_HANDLE dev_handle;
+ device_t dev;
+};
+
+struct acpi_gpiobus_ivar
+{
+ struct gpiobus_ivar gpiobus; /* Must come first */
+ ACPI_HANDLE dev_handle; /* ACPI handle for bus */
+ struct gpiobus_pin pin; /* Pin for _AEI */
};
static uint32_t
@@ -136,6 +147,57 @@
return (AE_OK);
}
+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->dev;
+ 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", DEVICE_UNIT_ANY);
+ if (child == NULL)
+ return (AE_OK);
+ devi = malloc(sizeof(*devi), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (devi == NULL) {
+ device_delete_child(bus, child);
+ return (AE_OK);
+ }
+ resource_list_init(&devi->gpiobus.rl);
+ device_set_ivars(child, devi);
+
+ /*
+ * Set pin information in bus-managed variables. We need to do
+ * this in two different ways because the device needs the
+ * gpiobus_pin structure to set up interrupts.
+ */
+ devi->pin.pin = gpio_res->PinTable[0];
+ devi->pin.flags = acpi_gpiobus_convflags(gpio_res);
+ if (acpi_quirks & ACPI_Q_AEI_NOPULL)
+ devi->pin.flags &= ~GPIO_PIN_PULLUP;
+ devi->pin.dev = device_get_parent(bus);
+ gpiobus_set_npins(child, 1);
+ gpiobus_set_pins(child, &devi->pin.pin);
+ if (GPIOBUS_PIN_SETFLAGS(bus, child, 0, devi->pin.flags)) {
+ gpiobus_release_pin(bus, devi->pin.pin);
+ 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)
@@ -156,6 +218,9 @@
/* Look for GPIO resources */
AcpiWalkResources(handle, "_CRS", acpi_gpiobus_enumerate_res, context);
+ /* Look for AEI children */
+ AcpiWalkResources(handle, "_AEI", acpi_gpiobus_enumerate_aei, context);
+
return (AE_OK);
}
@@ -263,6 +328,7 @@
return (ENXIO);
}
+ ctx.dev = dev;
ctx.dev_handle = handle;
ctx.sc = &sc->super_sc;
@@ -294,6 +360,25 @@
return (gpiobus_detach(dev));
}
+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;
+ case ACPI_GPIOBUS_IVAR_PIN:
+ *result = (uintptr_t)&devi->pin;
+ 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),
@@ -301,6 +386,7 @@
DEVMETHOD(device_detach, acpi_gpiobus_detach),
/* Bus interface */
+ DEVMETHOD(bus_read_ivar, acpi_gpiobus_read_ivar),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
diff --git a/sys/dev/gpio/acpi_gpiobusvar.h b/sys/dev/gpio/acpi_gpiobusvar.h
new file mode 100644
--- /dev/null
+++ b/sys/dev/gpio/acpi_gpiobusvar.h
@@ -0,0 +1,48 @@
+/*-
+ * 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 <sys/bus.h>
+
+#include <contrib/dev/acpica/include/acpi.h>
+
+enum acpi_gpiobus_ivars {
+ ACPI_GPIOBUS_IVAR_HANDLE = 10600,
+ ACPI_GPIOBUS_IVAR_PIN,
+};
+
+#define ACPI_GPIOBUS_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(acpi_gpiobus, var, ACPI_GPIOBUS, ivar, type)
+
+ACPI_GPIOBUS_ACCESSOR(handle, HANDLE, ACPI_HANDLE)
+ACPI_GPIOBUS_ACCESSOR(pin, PIN, struct gpiobus_pin *)
+
+#undef ACPI_GPIOBUS_ACCESSOR
+
+#endif /* __ACPI_GPIOBUS_H__ */
diff --git a/sys/dev/gpio/gpioaei.c b/sys/dev/gpio/gpioaei.c
new file mode 100644
--- /dev/null
+++ b/sys/dev/gpio/gpioaei.c
@@ -0,0 +1,129 @@
+/*-
+ * 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 <sys/types.h>
+#include <sys/bus.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include "gpiobus_if.h"
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <dev/acpica/acpivar.h>
+
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/gpio/acpi_gpiobusvar.h>
+
+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)
+{
+
+ /* Only handle gpio_aei devices, not anything else on gpiobus. */
+ if (strcmp(device_get_name(dev), "gpio_aei"))
+ return (ENXIO);
+
+ /* This is us. */
+ device_set_desc(dev, "ACPI Event Information Device");
+ return (BUS_PROBE_DEFAULT);
+}
+
+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);
+ struct gpiobus_pin * pin = acpi_gpiobus_get_pin(dev);
+ int err;
+
+ /* 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);
+ }
+
+ /* Store parameters needed by gpio_aei_intr. */
+ sc->handle = acpi_gpiobus_get_handle(dev);
+ sprintf(sc->objname, "_%c%02X",
+ (pin->flags & GPIO_INTR_EDGE_MASK) ? 'E' : 'L', pin->pin);
+
+ /* 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
--- 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
--- /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 <bsd.kmod.mk>

File Metadata

Mime Type
text/plain
Expires
Sun, Oct 27, 5:23 PM (21 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14359505
Default Alt Text
D47253.id145367.diff (10 KB)

Event Timeline