1*a9880bfeSTakanori Watanabe /*- 2*a9880bfeSTakanori Watanabe * Copyright (c) 2022 Takanori Watanabe 3*a9880bfeSTakanori Watanabe * 4*a9880bfeSTakanori Watanabe * Redistribution and use in source and binary forms, with or without 5*a9880bfeSTakanori Watanabe * modification, are permitted provided that the following conditions 6*a9880bfeSTakanori Watanabe * are met: 7*a9880bfeSTakanori Watanabe * 1. Redistributions of source code must retain the above copyright 8*a9880bfeSTakanori Watanabe * notice, this list of conditions and the following disclaimer. 9*a9880bfeSTakanori Watanabe * 2. Redistributions in binary form must reproduce the above copyright 10*a9880bfeSTakanori Watanabe * notice, this list of conditions and the following disclaimer in the 11*a9880bfeSTakanori Watanabe * documentation and/or other materials provided with the distribution. 12*a9880bfeSTakanori Watanabe * 13*a9880bfeSTakanori Watanabe * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14*a9880bfeSTakanori Watanabe * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15*a9880bfeSTakanori Watanabe * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16*a9880bfeSTakanori Watanabe * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17*a9880bfeSTakanori Watanabe * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18*a9880bfeSTakanori Watanabe * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19*a9880bfeSTakanori Watanabe * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20*a9880bfeSTakanori Watanabe * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21*a9880bfeSTakanori Watanabe * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22*a9880bfeSTakanori Watanabe * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23*a9880bfeSTakanori Watanabe * SUCH DAMAGE. 24*a9880bfeSTakanori Watanabe */ 25*a9880bfeSTakanori Watanabe 26*a9880bfeSTakanori Watanabe #include <sys/cdefs.h> 27*a9880bfeSTakanori Watanabe __FBSDID("$FreeBSD$"); 28*a9880bfeSTakanori Watanabe 29*a9880bfeSTakanori Watanabe #include "opt_acpi.h" 30*a9880bfeSTakanori Watanabe 31*a9880bfeSTakanori Watanabe #include <sys/param.h> 32*a9880bfeSTakanori Watanabe #include <sys/bus.h> 33*a9880bfeSTakanori Watanabe #include <sys/kernel.h> 34*a9880bfeSTakanori Watanabe #include <sys/malloc.h> 35*a9880bfeSTakanori Watanabe #include <sys/module.h> 36*a9880bfeSTakanori Watanabe #include <sys/rman.h> 37*a9880bfeSTakanori Watanabe 38*a9880bfeSTakanori Watanabe #include <contrib/dev/acpica/include/acpi.h> 39*a9880bfeSTakanori Watanabe #include <contrib/dev/acpica/include/accommon.h> 40*a9880bfeSTakanori Watanabe #include <dev/acpica/acpivar.h> 41*a9880bfeSTakanori Watanabe 42*a9880bfeSTakanori Watanabe /* Hooks for the ACPI CA debugging infrastructure */ 43*a9880bfeSTakanori Watanabe #define _COMPONENT ACPI_GED 44*a9880bfeSTakanori Watanabe ACPI_MODULE_NAME("GED") 45*a9880bfeSTakanori Watanabe 46*a9880bfeSTakanori Watanabe static MALLOC_DEFINE(M_ACPIGED, "acpiged", "ACPI Generic event data"); 47*a9880bfeSTakanori Watanabe 48*a9880bfeSTakanori Watanabe struct acpi_ged_event { 49*a9880bfeSTakanori Watanabe device_t dev; 50*a9880bfeSTakanori Watanabe struct resource *r; 51*a9880bfeSTakanori Watanabe int rid; 52*a9880bfeSTakanori Watanabe void *cookie; 53*a9880bfeSTakanori Watanabe ACPI_HANDLE ah; 54*a9880bfeSTakanori Watanabe ACPI_OBJECT_LIST args; 55*a9880bfeSTakanori Watanabe ACPI_OBJECT arg1; 56*a9880bfeSTakanori Watanabe }; 57*a9880bfeSTakanori Watanabe 58*a9880bfeSTakanori Watanabe struct acpi_ged_softc { 59*a9880bfeSTakanori Watanabe int numevts; 60*a9880bfeSTakanori Watanabe struct acpi_ged_event *evts; 61*a9880bfeSTakanori Watanabe }; 62*a9880bfeSTakanori Watanabe 63*a9880bfeSTakanori Watanabe static int acpi_ged_probe(device_t dev); 64*a9880bfeSTakanori Watanabe static int acpi_ged_attach(device_t dev); 65*a9880bfeSTakanori Watanabe static int acpi_ged_detach(device_t dev); 66*a9880bfeSTakanori Watanabe 67*a9880bfeSTakanori Watanabe static char *ged_ids[] = { "ACPI0013", NULL }; 68*a9880bfeSTakanori Watanabe 69*a9880bfeSTakanori Watanabe static device_method_t acpi_ged_methods[] = { 70*a9880bfeSTakanori Watanabe /* Device interface */ 71*a9880bfeSTakanori Watanabe DEVMETHOD(device_probe, acpi_ged_probe), 72*a9880bfeSTakanori Watanabe DEVMETHOD(device_attach, acpi_ged_attach), 73*a9880bfeSTakanori Watanabe DEVMETHOD(device_detach, acpi_ged_detach), 74*a9880bfeSTakanori Watanabe DEVMETHOD_END 75*a9880bfeSTakanori Watanabe }; 76*a9880bfeSTakanori Watanabe 77*a9880bfeSTakanori Watanabe static driver_t acpi_ged_driver = { 78*a9880bfeSTakanori Watanabe "acpi_ged", 79*a9880bfeSTakanori Watanabe acpi_ged_methods, 80*a9880bfeSTakanori Watanabe sizeof(struct acpi_ged_softc), 81*a9880bfeSTakanori Watanabe }; 82*a9880bfeSTakanori Watanabe 83*a9880bfeSTakanori Watanabe DRIVER_MODULE(acpi_ged, acpi, acpi_ged_driver, 0, 0); 84*a9880bfeSTakanori Watanabe MODULE_DEPEND(acpi_ged, acpi, 1, 1, 1); 85*a9880bfeSTakanori Watanabe 86*a9880bfeSTakanori Watanabe static void 87*a9880bfeSTakanori Watanabe acpi_ged_evt(void *arg) 88*a9880bfeSTakanori Watanabe { 89*a9880bfeSTakanori Watanabe struct acpi_ged_event *evt = arg; 90*a9880bfeSTakanori Watanabe 91*a9880bfeSTakanori Watanabe AcpiEvaluateObject(evt->ah, NULL, &evt->args, NULL); 92*a9880bfeSTakanori Watanabe } 93*a9880bfeSTakanori Watanabe 94*a9880bfeSTakanori Watanabe static void 95*a9880bfeSTakanori Watanabe acpi_ged_intr(void *arg) 96*a9880bfeSTakanori Watanabe { 97*a9880bfeSTakanori Watanabe AcpiOsExecute(OSL_GPE_HANDLER, acpi_ged_evt, arg); 98*a9880bfeSTakanori Watanabe } 99*a9880bfeSTakanori Watanabe static int 100*a9880bfeSTakanori Watanabe acpi_ged_probe(device_t dev) 101*a9880bfeSTakanori Watanabe { 102*a9880bfeSTakanori Watanabe int rv; 103*a9880bfeSTakanori Watanabe 104*a9880bfeSTakanori Watanabe if (acpi_disabled("ged")) 105*a9880bfeSTakanori Watanabe return (ENXIO); 106*a9880bfeSTakanori Watanabe rv = ACPI_ID_PROBE(device_get_parent(dev), dev, ged_ids, NULL); 107*a9880bfeSTakanori Watanabe if (rv > 0) 108*a9880bfeSTakanori Watanabe return (ENXIO); 109*a9880bfeSTakanori Watanabe 110*a9880bfeSTakanori Watanabe device_set_desc(dev, "Generic Event Device"); 111*a9880bfeSTakanori Watanabe return (rv); 112*a9880bfeSTakanori Watanabe } 113*a9880bfeSTakanori Watanabe 114*a9880bfeSTakanori Watanabe /*this should be in acpi_resource.*/ 115*a9880bfeSTakanori Watanabe static int 116*a9880bfeSTakanori Watanabe acpi_get_trigger(ACPI_RESOURCE *res) 117*a9880bfeSTakanori Watanabe { 118*a9880bfeSTakanori Watanabe int trig; 119*a9880bfeSTakanori Watanabe 120*a9880bfeSTakanori Watanabe switch (res->Type) { 121*a9880bfeSTakanori Watanabe case ACPI_RESOURCE_TYPE_IRQ: 122*a9880bfeSTakanori Watanabe KASSERT(res->Data.Irq.InterruptCount == 1, 123*a9880bfeSTakanori Watanabe ("%s: multiple interrupts", __func__)); 124*a9880bfeSTakanori Watanabe trig = res->Data.Irq.Triggering; 125*a9880bfeSTakanori Watanabe break; 126*a9880bfeSTakanori Watanabe case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 127*a9880bfeSTakanori Watanabe KASSERT(res->Data.ExtendedIrq.InterruptCount == 1, 128*a9880bfeSTakanori Watanabe ("%s: multiple interrupts", __func__)); 129*a9880bfeSTakanori Watanabe trig = res->Data.ExtendedIrq.Triggering; 130*a9880bfeSTakanori Watanabe break; 131*a9880bfeSTakanori Watanabe default: 132*a9880bfeSTakanori Watanabe panic("%s: bad resource type %u", __func__, res->Type); 133*a9880bfeSTakanori Watanabe } 134*a9880bfeSTakanori Watanabe 135*a9880bfeSTakanori Watanabe return (trig == ACPI_EDGE_SENSITIVE) 136*a9880bfeSTakanori Watanabe ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL; 137*a9880bfeSTakanori Watanabe } 138*a9880bfeSTakanori Watanabe 139*a9880bfeSTakanori Watanabe static int 140*a9880bfeSTakanori Watanabe acpi_ged_attach(device_t dev) 141*a9880bfeSTakanori Watanabe { 142*a9880bfeSTakanori Watanabe struct acpi_ged_softc *sc = device_get_softc(dev); 143*a9880bfeSTakanori Watanabe struct resource_list *rl; 144*a9880bfeSTakanori Watanabe struct resource_list_entry *rle; 145*a9880bfeSTakanori Watanabe ACPI_RESOURCE ares; 146*a9880bfeSTakanori Watanabe ACPI_HANDLE evt_method; 147*a9880bfeSTakanori Watanabe int i; 148*a9880bfeSTakanori Watanabe int rawirq, trig; 149*a9880bfeSTakanori Watanabe char name[] = "_Xnn"; 150*a9880bfeSTakanori Watanabe 151*a9880bfeSTakanori Watanabe ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); 152*a9880bfeSTakanori Watanabe 153*a9880bfeSTakanori Watanabe if (ACPI_FAILURE(AcpiGetHandle(acpi_get_handle(dev), "_EVT", 154*a9880bfeSTakanori Watanabe &evt_method))) { 155*a9880bfeSTakanori Watanabe device_printf(dev, "_EVT not found\n"); 156*a9880bfeSTakanori Watanabe evt_method = NULL; 157*a9880bfeSTakanori Watanabe } 158*a9880bfeSTakanori Watanabe 159*a9880bfeSTakanori Watanabe rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); 160*a9880bfeSTakanori Watanabe STAILQ_FOREACH(rle, rl, link) { 161*a9880bfeSTakanori Watanabe if (rle->type == SYS_RES_IRQ) { 162*a9880bfeSTakanori Watanabe sc->numevts++; 163*a9880bfeSTakanori Watanabe } 164*a9880bfeSTakanori Watanabe } 165*a9880bfeSTakanori Watanabe sc->evts = mallocarray(sc->numevts, sizeof(*sc->evts), M_ACPIGED, 166*a9880bfeSTakanori Watanabe M_WAITOK | M_ZERO); 167*a9880bfeSTakanori Watanabe for (i = 0; i < sc->numevts; i++) { 168*a9880bfeSTakanori Watanabe sc->evts[i].dev = dev; 169*a9880bfeSTakanori Watanabe sc->evts[i].rid = i; 170*a9880bfeSTakanori Watanabe sc->evts[i].r = bus_alloc_resource_any(dev, SYS_RES_IRQ, 171*a9880bfeSTakanori Watanabe &sc->evts[i].rid, RF_ACTIVE | RF_SHAREABLE); 172*a9880bfeSTakanori Watanabe if (sc->evts[i].r == NULL) { 173*a9880bfeSTakanori Watanabe device_printf(dev, "Cannot alloc %dth irq\n", i); 174*a9880bfeSTakanori Watanabe continue; 175*a9880bfeSTakanori Watanabe } 176*a9880bfeSTakanori Watanabe #ifdef INTRNG 177*a9880bfeSTakanori Watanabe { 178*a9880bfeSTakanori Watanabe struct intr_map_data_acpi *ima; 179*a9880bfeSTakanori Watanabe ima = rman_get_virtual(sc->evts[i].r); 180*a9880bfeSTakanori Watanabe if (ima == NULL) { 181*a9880bfeSTakanori Watanabe device_printf(dev, "map not found" 182*a9880bfeSTakanori Watanabe " non-intrng?\n"); 183*a9880bfeSTakanori Watanabe rawirq = rman_get_start(sc->evts[i].r); 184*a9880bfeSTakanori Watanabe trig = INTR_TRIGGER_LEVEL; 185*a9880bfeSTakanori Watanabe if (ACPI_SUCCESS(acpi_lookup_irq_resource 186*a9880bfeSTakanori Watanabe (dev, sc->evts[i].rid, 187*a9880bfeSTakanori Watanabe sc->evts[i].r, &ares))) { 188*a9880bfeSTakanori Watanabe trig = acpi_get_trigger(&ares); 189*a9880bfeSTakanori Watanabe } 190*a9880bfeSTakanori Watanabe } else if (ima->hdr.type == INTR_MAP_DATA_ACPI) { 191*a9880bfeSTakanori Watanabe device_printf(dev, "Raw IRQ %d\n", ima->irq); 192*a9880bfeSTakanori Watanabe rawirq = ima->irq; 193*a9880bfeSTakanori Watanabe trig = ima->trig; 194*a9880bfeSTakanori Watanabe } else { 195*a9880bfeSTakanori Watanabe device_printf(dev, "Not supported intr" 196*a9880bfeSTakanori Watanabe " type%d\n", ima->hdr.type); 197*a9880bfeSTakanori Watanabe continue; 198*a9880bfeSTakanori Watanabe } 199*a9880bfeSTakanori Watanabe } 200*a9880bfeSTakanori Watanabe #else 201*a9880bfeSTakanori Watanabe rawirq = rman_get_start(sc->evt[i].r); 202*a9880bfeSTakanori Watanabe trig = INTR_TRIGGER_LEVEL; 203*a9880bfeSTakanori Watanabe if (ACPI_SUCCESS(acpi_lookup_irq_resource 204*a9880bfeSTakanori Watanabe (dev, sc->evts[i].rid, 205*a9880bfeSTakanori Watanabe sc->evts[i].r, &ares))) { 206*a9880bfeSTakanori Watanabe trig = acpi_get_trigger(&ares); 207*a9880bfeSTakanori Watanabe } 208*a9880bfeSTakanori Watanabe #endif 209*a9880bfeSTakanori Watanabe if (rawirq < 0x100) { 210*a9880bfeSTakanori Watanabe sprintf(name, "_%c%02X", 211*a9880bfeSTakanori Watanabe ((trig == INTR_TRIGGER_EDGE) ? 'E' : 'L'), 212*a9880bfeSTakanori Watanabe rawirq); 213*a9880bfeSTakanori Watanabe if (ACPI_SUCCESS(AcpiGetHandle 214*a9880bfeSTakanori Watanabe (acpi_get_handle(dev), 215*a9880bfeSTakanori Watanabe name, &sc->evts[i].ah))) { 216*a9880bfeSTakanori Watanabe sc->evts[i].args.Count = 0; /* ensure */ 217*a9880bfeSTakanori Watanabe } else { 218*a9880bfeSTakanori Watanabe sc->evts[i].ah = NULL; /* ensure */ 219*a9880bfeSTakanori Watanabe } 220*a9880bfeSTakanori Watanabe } 221*a9880bfeSTakanori Watanabe 222*a9880bfeSTakanori Watanabe if (sc->evts[i].ah == NULL) { 223*a9880bfeSTakanori Watanabe if (evt_method != NULL) { 224*a9880bfeSTakanori Watanabe sc->evts[i].ah = evt_method; 225*a9880bfeSTakanori Watanabe sc->evts[i].arg1.Type = ACPI_TYPE_INTEGER; 226*a9880bfeSTakanori Watanabe sc->evts[i].arg1.Integer.Value = rawirq; 227*a9880bfeSTakanori Watanabe sc->evts[i].args.Count = 1; 228*a9880bfeSTakanori Watanabe sc->evts[i].args.Pointer = &sc->evts[i].arg1; 229*a9880bfeSTakanori Watanabe } else{ 230*a9880bfeSTakanori Watanabe device_printf 231*a9880bfeSTakanori Watanabe (dev, 232*a9880bfeSTakanori Watanabe "Cannot find handler method %d\n", 233*a9880bfeSTakanori Watanabe i); 234*a9880bfeSTakanori Watanabe continue; 235*a9880bfeSTakanori Watanabe } 236*a9880bfeSTakanori Watanabe } 237*a9880bfeSTakanori Watanabe 238*a9880bfeSTakanori Watanabe if (bus_setup_intr(dev, sc->evts[i].r, 239*a9880bfeSTakanori Watanabe INTR_TYPE_MISC | INTR_MPSAFE, NULL, acpi_ged_intr, 240*a9880bfeSTakanori Watanabe &sc->evts[i], &sc->evts[i].cookie) != 0) { 241*a9880bfeSTakanori Watanabe device_printf(dev, "Failed to setup intr %d\n", i); 242*a9880bfeSTakanori Watanabe } 243*a9880bfeSTakanori Watanabe } 244*a9880bfeSTakanori Watanabe 245*a9880bfeSTakanori Watanabe return_VALUE(0); 246*a9880bfeSTakanori Watanabe } 247*a9880bfeSTakanori Watanabe 248*a9880bfeSTakanori Watanabe static int 249*a9880bfeSTakanori Watanabe acpi_ged_detach(device_t dev) 250*a9880bfeSTakanori Watanabe { 251*a9880bfeSTakanori Watanabe struct acpi_ged_softc *sc = device_get_softc(dev); 252*a9880bfeSTakanori Watanabe int i; 253*a9880bfeSTakanori Watanabe 254*a9880bfeSTakanori Watanabe for (i = 0; i < sc->numevts; i++) { 255*a9880bfeSTakanori Watanabe if (sc->evts[i].cookie) { 256*a9880bfeSTakanori Watanabe bus_teardown_intr(dev, sc->evts[i].r, 257*a9880bfeSTakanori Watanabe sc->evts[i].cookie); 258*a9880bfeSTakanori Watanabe } 259*a9880bfeSTakanori Watanabe if (sc->evts[i].r) { 260*a9880bfeSTakanori Watanabe bus_release_resource(dev, SYS_RES_IRQ, sc->evts[i].rid, 261*a9880bfeSTakanori Watanabe sc->evts[i].r); 262*a9880bfeSTakanori Watanabe } 263*a9880bfeSTakanori Watanabe } 264*a9880bfeSTakanori Watanabe free(sc->evts, M_ACPIGED); 265*a9880bfeSTakanori Watanabe 266*a9880bfeSTakanori Watanabe return (0); 267*a9880bfeSTakanori Watanabe } 268