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