xref: /freebsd/sys/dev/acpica/acpi_ged.c (revision a9880bfe1181b7a32d026339bae113f24300e5e1)
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