xref: /openbsd-src/sys/dev/acpi/ipmi_acpi.c (revision e012216e8ad275af806b64ba937f97650f03c8a5)
1*e012216eSyasuoka /* $OpenBSD: ipmi_acpi.c,v 1.7 2025/01/28 02:20:49 yasuoka Exp $ */
2a74532a1Spatrick /*
3a74532a1Spatrick  * Copyright (c) 2018 Patrick Wildt <patrick@blueri.se>
4a74532a1Spatrick  *
5a74532a1Spatrick  * Permission to use, copy, modify, and distribute this software for any
6a74532a1Spatrick  * purpose with or without fee is hereby granted, provided that the above
7a74532a1Spatrick  * copyright notice and this permission notice appear in all copies.
8a74532a1Spatrick  *
9a74532a1Spatrick  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10a74532a1Spatrick  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11a74532a1Spatrick  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12a74532a1Spatrick  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13a74532a1Spatrick  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14a74532a1Spatrick  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15a74532a1Spatrick  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16a74532a1Spatrick  */
17a74532a1Spatrick 
18a74532a1Spatrick #include <sys/param.h>
19a74532a1Spatrick #include <sys/signalvar.h>
20a74532a1Spatrick #include <sys/systm.h>
21a74532a1Spatrick #include <sys/device.h>
22a74532a1Spatrick #include <sys/malloc.h>
23a74532a1Spatrick 
24a74532a1Spatrick #include <machine/bus.h>
25a74532a1Spatrick #include <machine/apmvar.h>
26a74532a1Spatrick 
27a74532a1Spatrick #include <dev/acpi/acpireg.h>
28a74532a1Spatrick #include <dev/acpi/acpivar.h>
29a74532a1Spatrick #include <dev/acpi/acpidev.h>
30a74532a1Spatrick #include <dev/acpi/amltypes.h>
31a74532a1Spatrick #include <dev/acpi/dsdt.h>
32a74532a1Spatrick #undef DEVNAME
33a74532a1Spatrick 
34a74532a1Spatrick #include <dev/ipmivar.h>
35a74532a1Spatrick 
36a74532a1Spatrick #define DEVNAME(s)		((s)->sc.sc_dev.dv_xname)
37a74532a1Spatrick 
38a74532a1Spatrick int	ipmi_acpi_match(struct device *, void *, void *);
39a74532a1Spatrick void	ipmi_acpi_attach(struct device *, struct device *, void *);
40a74532a1Spatrick int	ipmi_acpi_parse_crs(int, union acpi_resource *, void *);
41a74532a1Spatrick 
42a74532a1Spatrick struct ipmi_acpi_softc {
43a74532a1Spatrick 	struct ipmi_softc	 sc;
44a74532a1Spatrick 
45a74532a1Spatrick 	struct acpi_softc	*sc_acpi;
46a74532a1Spatrick 	struct aml_node		*sc_devnode;
47a74532a1Spatrick 
48a74532a1Spatrick 	int			 sc_ift;
4902af067eSkettenis 	int			 sc_srv;
50a74532a1Spatrick 
51a74532a1Spatrick 	bus_size_t		 sc_iobase;
52a74532a1Spatrick 	int			 sc_iospacing;
53a74532a1Spatrick 	char			 sc_iotype;
54a74532a1Spatrick };
55a74532a1Spatrick 
56471aeecfSnaddy const struct cfattach ipmi_acpi_ca = {
57a74532a1Spatrick 	sizeof(struct ipmi_acpi_softc), ipmi_acpi_match, ipmi_acpi_attach,
583a3d566bSjsg 	NULL, ipmi_activate
59a74532a1Spatrick };
60a74532a1Spatrick 
61a74532a1Spatrick const char *ipmi_acpi_hids[] = { ACPI_DEV_IPMI, NULL };
62a74532a1Spatrick 
63a74532a1Spatrick int
64a74532a1Spatrick ipmi_acpi_match(struct device *parent, void *match, void *aux)
65a74532a1Spatrick {
66a74532a1Spatrick 	struct acpi_attach_args *aa = aux;
67a74532a1Spatrick 	struct cfdata *cf = match;
68a74532a1Spatrick 
69a74532a1Spatrick 	/* sanity */
70a74532a1Spatrick 	return (acpi_matchhids(aa, ipmi_acpi_hids, cf->cf_driver->cd_name));
71a74532a1Spatrick }
72a74532a1Spatrick 
73a74532a1Spatrick void
74a74532a1Spatrick ipmi_acpi_attach(struct device *parent, struct device *self, void *aux)
75a74532a1Spatrick {
76a74532a1Spatrick 	struct ipmi_acpi_softc *sc = (struct ipmi_acpi_softc *)self;
77a74532a1Spatrick 	struct acpi_attach_args *aa = aux;
78a74532a1Spatrick 	struct ipmi_attach_args ia;
79a74532a1Spatrick 	struct aml_value res;
8002af067eSkettenis 	int64_t ift, srv = 0;
81a74532a1Spatrick 	int rc;
82a74532a1Spatrick 
83a74532a1Spatrick 	sc->sc_acpi = (struct acpi_softc *)parent;
84a74532a1Spatrick 	sc->sc_devnode = aa->aaa_node;
85a74532a1Spatrick 
86a74532a1Spatrick 	rc = aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_IFT", 0, NULL, &ift);
87a74532a1Spatrick 	if (rc) {
88a74532a1Spatrick 		printf(": no _IFT\n");
89a74532a1Spatrick 		return;
90a74532a1Spatrick 	}
91a74532a1Spatrick 	sc->sc_ift = ift;
92a74532a1Spatrick 
9302af067eSkettenis 	aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_SRV", 0, NULL, &srv);
9402af067eSkettenis 	sc->sc_srv = srv;
9502af067eSkettenis 
96a74532a1Spatrick 	if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CRS", 0, NULL, &res)) {
97a74532a1Spatrick 		printf(": no _CRS method\n");
98a74532a1Spatrick 		return;
99a74532a1Spatrick 	}
100a74532a1Spatrick 	if (res.type != AML_OBJTYPE_BUFFER) {
101a74532a1Spatrick 		printf(": invalid _CRS object (type %d len %d)\n",
102a74532a1Spatrick 		    res.type, res.length);
103a74532a1Spatrick 		aml_freevalue(&res);
104a74532a1Spatrick 		return;
105a74532a1Spatrick 	}
106a74532a1Spatrick 
107a74532a1Spatrick 	aml_parse_resource(&res, ipmi_acpi_parse_crs, sc);
108a74532a1Spatrick 	aml_freevalue(&res);
109a74532a1Spatrick 
11002af067eSkettenis 	if (sc->sc_iotype == 0) {
111a74532a1Spatrick 		printf("%s: incomplete resources (ift %d)\n",
112a74532a1Spatrick 		    DEVNAME(sc), sc->sc_ift);
113a74532a1Spatrick 		return;
114a74532a1Spatrick 	}
115a74532a1Spatrick 
116c08dc278Skettenis 	memset(&ia, 0, sizeof(ia));
11702af067eSkettenis 	ia.iaa_iot = sc->sc_acpi->sc_iot;
11802af067eSkettenis 	ia.iaa_memt = sc->sc_acpi->sc_memt;
119a74532a1Spatrick 	ia.iaa_if_type = sc->sc_ift;
12002af067eSkettenis 	ia.iaa_if_rev = (sc->sc_srv >> 4);
121a74532a1Spatrick 	ia.iaa_if_irq = -1;
122a74532a1Spatrick 	ia.iaa_if_irqlvl = 0;
123cda7789cSkettenis 	ia.iaa_if_iosize = 1;
124a74532a1Spatrick 	ia.iaa_if_iospacing = sc->sc_iospacing;
125a74532a1Spatrick 	ia.iaa_if_iobase = sc->sc_iobase;
126a74532a1Spatrick 	ia.iaa_if_iotype = sc->sc_iotype;
127a74532a1Spatrick 
128c08dc278Skettenis 	ipmi_attach_common(&sc->sc, &ia);
129a74532a1Spatrick }
130a74532a1Spatrick 
131a74532a1Spatrick int
132a74532a1Spatrick ipmi_acpi_parse_crs(int crsidx, union acpi_resource *crs, void *arg)
133a74532a1Spatrick {
134a74532a1Spatrick 	struct ipmi_acpi_softc *sc = arg;
135a74532a1Spatrick 	int type = AML_CRSTYPE(crs);
13602af067eSkettenis 	bus_size_t addr;
13702af067eSkettenis 	char iotype;
13802af067eSkettenis 
13902af067eSkettenis 	switch (type) {
140*e012216eSyasuoka 	case SR_IRQ:
141*e012216eSyasuoka 		/* Ignore for now. */
142*e012216eSyasuoka 		return 0;
14302af067eSkettenis 	case SR_IOPORT:
14402af067eSkettenis 		addr = crs->sr_ioport._max;
14502af067eSkettenis 		iotype = 'i';
14602af067eSkettenis 		break;
14702af067eSkettenis 	case LR_MEM32FIXED:
14802af067eSkettenis 		addr = crs->lr_m32fixed._bas;
14902af067eSkettenis 		iotype = 'm';
15002af067eSkettenis 		break;
15102af067eSkettenis 	case LR_EXTIRQ:
15202af067eSkettenis 		/* Ignore for now. */
15302af067eSkettenis 		return 0;
15402af067eSkettenis 	default:
15502af067eSkettenis 		printf("\n%s: unexpected resource #%d type %d",
15602af067eSkettenis 		    DEVNAME(sc), crsidx, type);
15702af067eSkettenis 		sc->sc_iotype = 0;
15802af067eSkettenis 		return -1;
15902af067eSkettenis 	}
160a74532a1Spatrick 
161a74532a1Spatrick 	switch (crsidx) {
162a74532a1Spatrick 	case 0:
16302af067eSkettenis 		sc->sc_iobase = addr;
164a74532a1Spatrick 		sc->sc_iospacing = 1;
16502af067eSkettenis 		sc->sc_iotype = iotype;
166a74532a1Spatrick 		break;
167a74532a1Spatrick 	case 1:
16802af067eSkettenis 		if (sc->sc_iotype != iotype) {
16902af067eSkettenis 			printf("\n%s: unexpected resource #%d type %d\n",
170a74532a1Spatrick 			    DEVNAME(sc), crsidx, type);
17102af067eSkettenis 			sc->sc_iotype = 0;
17202af067eSkettenis 			return -1;
173a74532a1Spatrick 		}
17402af067eSkettenis 		if (addr <= sc->sc_iobase) {
17502af067eSkettenis 			sc->sc_iotype = 0;
17602af067eSkettenis 			return -1;
17702af067eSkettenis 		}
17802af067eSkettenis 		sc->sc_iospacing = addr - sc->sc_iobase;
179a74532a1Spatrick 		break;
180a74532a1Spatrick 	default:
18102af067eSkettenis 		printf("\n%s: invalid resource #%d type %d (ift %d)",
182a74532a1Spatrick 		    DEVNAME(sc), crsidx, type, sc->sc_ift);
18302af067eSkettenis 		sc->sc_iotype = 0;
18402af067eSkettenis 		return -1;
185a74532a1Spatrick 	}
186a74532a1Spatrick 
187a74532a1Spatrick 	return 0;
188a74532a1Spatrick }
189