1*471aeecfSnaddy /* $OpenBSD: acpige.c,v 1.2 2022/04/06 18:59:27 naddy Exp $ */
2c399e7a9Spatrick /*
3c399e7a9Spatrick * Copyright (c) 2020 Patrick Wildt <patrick@blueri.se>
4c399e7a9Spatrick *
5c399e7a9Spatrick * Permission to use, copy, modify, and distribute this software for any
6c399e7a9Spatrick * purpose with or without fee is hereby granted, provided that the above
7c399e7a9Spatrick * copyright notice and this permission notice appear in all copies.
8c399e7a9Spatrick *
9c399e7a9Spatrick * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10c399e7a9Spatrick * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11c399e7a9Spatrick * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12c399e7a9Spatrick * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13c399e7a9Spatrick * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14c399e7a9Spatrick * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15c399e7a9Spatrick * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16c399e7a9Spatrick */
17c399e7a9Spatrick
18c399e7a9Spatrick #include <sys/param.h>
19c399e7a9Spatrick #include <sys/malloc.h>
20c399e7a9Spatrick #include <sys/systm.h>
21c399e7a9Spatrick #include <sys/tty.h>
22c399e7a9Spatrick
23c399e7a9Spatrick #include <dev/acpi/acpireg.h>
24c399e7a9Spatrick #include <dev/acpi/acpivar.h>
25c399e7a9Spatrick #include <dev/acpi/acpidev.h>
26c399e7a9Spatrick #include <dev/acpi/amltypes.h>
27c399e7a9Spatrick #include <dev/acpi/dsdt.h>
28c399e7a9Spatrick
29c399e7a9Spatrick struct acpige_softc;
30c399e7a9Spatrick struct acpige_irq {
31c399e7a9Spatrick struct acpige_softc *ai_sc;
32c399e7a9Spatrick void *ai_ih;
33c399e7a9Spatrick uint32_t ai_irq;
34c399e7a9Spatrick };
35c399e7a9Spatrick
36c399e7a9Spatrick struct acpige_softc {
37c399e7a9Spatrick struct device sc_dev;
38c399e7a9Spatrick struct acpi_softc *sc_acpi;
39c399e7a9Spatrick struct aml_node *sc_devnode;
40c399e7a9Spatrick struct acpige_irq *sc_irq;
41c399e7a9Spatrick };
42c399e7a9Spatrick
43c399e7a9Spatrick int acpige_match(struct device *, void *, void *);
44c399e7a9Spatrick void acpige_attach(struct device *, struct device *, void *);
45c399e7a9Spatrick
46c399e7a9Spatrick int acpige_intr(void *);
47c399e7a9Spatrick void acpige_event_task(void *, int);
48c399e7a9Spatrick
49*471aeecfSnaddy const struct cfattach acpige_ca = {
50c399e7a9Spatrick sizeof(struct acpige_softc), acpige_match, acpige_attach
51c399e7a9Spatrick };
52c399e7a9Spatrick
53c399e7a9Spatrick struct cfdriver acpige_cd = {
54c399e7a9Spatrick NULL, "acpige", DV_DULL
55c399e7a9Spatrick };
56c399e7a9Spatrick
57c399e7a9Spatrick const char *acpige_hids[] = {
58c399e7a9Spatrick "ACPI0013",
59c399e7a9Spatrick NULL
60c399e7a9Spatrick };
61c399e7a9Spatrick
62c399e7a9Spatrick int
acpige_match(struct device * parent,void * match,void * aux)63c399e7a9Spatrick acpige_match(struct device *parent, void *match, void *aux)
64c399e7a9Spatrick {
65c399e7a9Spatrick struct acpi_attach_args *aaa = aux;
66c399e7a9Spatrick struct cfdata *cf = match;
67c399e7a9Spatrick
68c399e7a9Spatrick return acpi_matchhids(aaa, acpige_hids, cf->cf_driver->cd_name);
69c399e7a9Spatrick }
70c399e7a9Spatrick
71c399e7a9Spatrick void
acpige_attach(struct device * parent,struct device * self,void * aux)72c399e7a9Spatrick acpige_attach(struct device *parent, struct device *self, void *aux)
73c399e7a9Spatrick {
74c399e7a9Spatrick struct acpige_softc *sc = (struct acpige_softc *)self;
75c399e7a9Spatrick struct acpi_attach_args *aaa = aux;
76c399e7a9Spatrick struct acpige_irq *ai;
77c399e7a9Spatrick int i;
78c399e7a9Spatrick
79c399e7a9Spatrick sc->sc_acpi = (struct acpi_softc *)parent;
80c399e7a9Spatrick sc->sc_devnode = aaa->aaa_node;
81c399e7a9Spatrick
82c399e7a9Spatrick if (aaa->aaa_nirq < 1) {
83c399e7a9Spatrick printf(": no interrupt\n");
84c399e7a9Spatrick return;
85c399e7a9Spatrick }
86c399e7a9Spatrick
87c399e7a9Spatrick sc->sc_irq = mallocarray(aaa->aaa_nirq, sizeof(struct acpige_irq),
88c399e7a9Spatrick M_DEVBUF, M_WAITOK);
89c399e7a9Spatrick
90c399e7a9Spatrick for (i = 0; i < aaa->aaa_nirq; i++) {
91c399e7a9Spatrick printf("%s %d", i ? "," : " irq", aaa->aaa_irq[i]);
92c399e7a9Spatrick ai = &sc->sc_irq[i];
93c399e7a9Spatrick ai->ai_sc = sc;
94c399e7a9Spatrick ai->ai_irq = aaa->aaa_irq[i];
95c399e7a9Spatrick ai->ai_ih = acpi_intr_establish(aaa->aaa_irq[i],
96c399e7a9Spatrick aaa->aaa_irq_flags[i], IPL_BIO, acpige_intr, ai,
97c399e7a9Spatrick sc->sc_dev.dv_xname);
98c399e7a9Spatrick if (ai->ai_ih == NULL) {
99c399e7a9Spatrick printf(": can't establish interrupt\n");
100c399e7a9Spatrick return;
101c399e7a9Spatrick }
102c399e7a9Spatrick }
103c399e7a9Spatrick
104c399e7a9Spatrick printf("\n");
105c399e7a9Spatrick }
106c399e7a9Spatrick
107c399e7a9Spatrick int
acpige_intr(void * arg)108c399e7a9Spatrick acpige_intr(void *arg)
109c399e7a9Spatrick {
110c399e7a9Spatrick struct acpige_irq *ai = arg;
111c399e7a9Spatrick struct acpige_softc *sc = ai->ai_sc;
112c399e7a9Spatrick
113c399e7a9Spatrick acpi_addtask(sc->sc_acpi, acpige_event_task, sc, ai->ai_irq);
114c399e7a9Spatrick acpi_wakeup(sc->sc_acpi);
115c399e7a9Spatrick return 1;
116c399e7a9Spatrick }
117c399e7a9Spatrick
118c399e7a9Spatrick void
acpige_event_task(void * arg0,int irq)119c399e7a9Spatrick acpige_event_task(void *arg0, int irq)
120c399e7a9Spatrick {
121c399e7a9Spatrick struct acpige_softc *sc = arg0;
122c399e7a9Spatrick struct aml_value cmd;
123c399e7a9Spatrick
124c399e7a9Spatrick memset(&cmd, 0, sizeof cmd);
125c399e7a9Spatrick cmd.v_integer = irq;
126c399e7a9Spatrick cmd.type = AML_OBJTYPE_INTEGER;
127c399e7a9Spatrick aml_evalname(sc->sc_acpi, sc->sc_devnode, "_EVT", 1, &cmd, NULL);
128c399e7a9Spatrick }
129