xref: /openbsd/sys/arch/amd64/pci/acpipci.c (revision 4bdff4be)
1 /*	$OpenBSD: acpipci.c,v 1.7 2022/02/21 11:03:39 mpi Exp $	*/
2 /*
3  * Copyright (c) 2018 Mark Kettenis
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/device.h>
20 #include <sys/extent.h>
21 #include <sys/malloc.h>
22 #include <sys/systm.h>
23 
24 #include <dev/acpi/acpireg.h>
25 #include <dev/acpi/acpivar.h>
26 #include <dev/acpi/acpidev.h>
27 #include <dev/acpi/amltypes.h>
28 #include <dev/acpi/dsdt.h>
29 
30 #include <dev/pci/pcidevs.h>
31 #include <dev/pci/pcireg.h>
32 #include <dev/pci/pcivar.h>
33 
34 /* 33DB4D5B-1FF7-401C-9657-7441C03DD766 */
35 #define ACPI_PCI_UUID \
36   { 0x5b, 0x4d, 0xdb, 0x33, \
37     0xf7, 0x1f, \
38     0x1c, 0x40, \
39     0x96, 0x57, \
40     0x74, 0x41, 0xc0, 0x3d, 0xd7, 0x66 }
41 
42 /* Support field. */
43 #define ACPI_PCI_PCIE_CONFIG	0x00000001
44 #define ACPI_PCI_ASPM		0x00000002
45 #define ACPI_PCI_CPMC		0x00000004
46 #define ACPI_PCI_SEGMENTS	0x00000008
47 #define ACPI_PCI_MSI		0x00000010
48 
49 /* Control field. */
50 #define ACPI_PCI_PCIE_HOTPLUG	0x00000001
51 
52 struct acpipci_softc {
53 	struct device	sc_dev;
54 	struct acpi_softc *sc_acpi;
55 	struct aml_node *sc_node;
56 
57 	bus_space_tag_t	sc_iot;
58 	bus_space_tag_t	sc_memt;
59 	bus_dma_tag_t	sc_dmat;
60 
61 	struct extent	*sc_busex;
62 	struct extent	*sc_memex;
63 	struct extent	*sc_ioex;
64 	char		sc_busex_name[32];
65 	char		sc_ioex_name[32];
66 	char		sc_memex_name[32];
67 	int		sc_bus;
68 	uint32_t	sc_seg;
69 };
70 
71 int	acpipci_match(struct device *, void *, void *);
72 void	acpipci_attach(struct device *, struct device *, void *);
73 
74 const struct cfattach acpipci_ca = {
75 	sizeof(struct acpipci_softc), acpipci_match, acpipci_attach
76 };
77 
78 struct cfdriver acpipci_cd = {
79 	NULL, "acpipci", DV_DULL
80 };
81 
82 const char *acpipci_hids[] = {
83 	"PNP0A08",
84 	"PNP0A03",
85 	NULL
86 };
87 
88 void	acpipci_attach_deferred(struct device *);
89 int	acpipci_print(void *, const char *);
90 int	acpipci_parse_resources(int, union acpi_resource *, void *);
91 void	acpipci_osc(struct acpipci_softc *);
92 
93 int
94 acpipci_match(struct device *parent, void *match, void *aux)
95 {
96 	struct acpi_attach_args *aaa = aux;
97 	struct cfdata *cf = match;
98 
99 	return acpi_matchhids(aaa, acpipci_hids, cf->cf_driver->cd_name);
100 }
101 
102 void
103 acpipci_attach(struct device *parent, struct device *self, void *aux)
104 {
105 	struct acpi_attach_args *aaa = aux;
106 	struct acpipci_softc *sc = (struct acpipci_softc *)self;
107 	struct aml_value res;
108 	uint64_t bbn = 0;
109 	uint64_t seg = 0;
110 
111 	acpi_haspci = 1;
112 
113 	sc->sc_iot = aaa->aaa_iot;
114 	sc->sc_memt = aaa->aaa_memt;
115 	sc->sc_dmat = aaa->aaa_dmat;
116 
117 	sc->sc_acpi = (struct acpi_softc *)parent;
118 	sc->sc_node = aaa->aaa_node;
119 	printf(" %s", sc->sc_node->name);
120 
121 	acpipci_osc(sc);
122 
123 	aml_evalinteger(sc->sc_acpi, sc->sc_node, "_BBN", 0, NULL, &bbn);
124 	sc->sc_bus = bbn;
125 
126 	aml_evalinteger(sc->sc_acpi, sc->sc_node, "_SEG", 0, NULL, &seg);
127 	sc->sc_seg = seg;
128 
129 	if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) {
130 		printf(": can't find resources\n");
131 
132 		pci_init_extents();
133 		sc->sc_busex = pcibus_ex;
134 		sc->sc_ioex = pciio_ex;
135 		sc->sc_memex = pcimem_ex;
136 
137 		return;
138 	}
139 
140 	/* Create extents for our address spaces. */
141 	snprintf(sc->sc_busex_name, sizeof(sc->sc_busex_name),
142 	    "%s pcibus", sc->sc_dev.dv_xname);
143 	snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name),
144 	    "%s pciio", sc->sc_dev.dv_xname);
145 	snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name),
146 	    "%s pcimem", sc->sc_dev.dv_xname);
147 	sc->sc_busex = extent_create(sc->sc_busex_name, 0, 255,
148 	    M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
149 	sc->sc_ioex = extent_create(sc->sc_ioex_name, 0, 0xffffffff,
150 	    M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
151 	sc->sc_memex = extent_create(sc->sc_memex_name, 0, (u_long)-1,
152 	    M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED);
153 
154 	aml_parse_resource(&res, acpipci_parse_resources, sc);
155 
156 	if (sc->sc_acpi->sc_major < 5) {
157 		extent_destroy(sc->sc_ioex);
158 		extent_destroy(sc->sc_memex);
159 
160 		pci_init_extents();
161 		sc->sc_ioex =  pciio_ex;
162 		sc->sc_memex = pcimem_ex;
163 	}
164 
165 	printf("\n");
166 
167 #ifdef ACPIPCI_DEBUG
168 	extent_print(sc->sc_busex);
169 	extent_print(sc->sc_ioex);
170 	extent_print(sc->sc_memex);
171 #endif
172 }
173 
174 void
175 acpipci_attach_bus(struct device *parent, struct acpipci_softc *sc)
176 {
177 	struct pcibus_attach_args pba;
178 	pcitag_t tag;
179 	pcireg_t id, class;
180 
181 	memset(&pba, 0, sizeof(pba));
182 	pba.pba_busname = "pci";
183 	pba.pba_iot = sc->sc_iot;
184 	pba.pba_memt = sc->sc_memt;
185 	pba.pba_dmat = sc->sc_dmat;
186 	pba.pba_busex = sc->sc_busex;
187 	pba.pba_ioex = sc->sc_ioex;
188 	pba.pba_memex = sc->sc_memex;
189 	pba.pba_pmemex = sc->sc_memex;
190 	pba.pba_domain = pci_ndomains++;
191 	pba.pba_bus = sc->sc_bus;
192 
193 	/* Enable MSI in ACPI 2.0 and above, unless we're told not to. */
194 	if (sc->sc_acpi->sc_fadt->hdr.revision >= 2 &&
195 	    (sc->sc_acpi->sc_fadt->iapc_boot_arch & FADT_NO_MSI) == 0)
196 		pba.pba_flags |= PCI_FLAGS_MSI_ENABLED;
197 
198 	/*
199 	 * Don't enable MSI on chipsets from low-end manufacturers
200 	 * like VIA and SiS.  We do this by looking at the host
201 	 * bridge, which should be device 0 function 0.
202 	 */
203 	tag = pci_make_tag(pba.pba_pc, sc->sc_bus, 0, 0);
204 	id = pci_conf_read(pba.pba_pc, tag, PCI_ID_REG);
205 	class = pci_conf_read(pba.pba_pc, tag, PCI_CLASS_REG);
206 	if (PCI_CLASS(class) == PCI_CLASS_BRIDGE &&
207 	    PCI_SUBCLASS(class) != PCI_SUBCLASS_BRIDGE_HOST &&
208 	    PCI_VENDOR(id) != PCI_VENDOR_AMD &&
209 	    PCI_VENDOR(id) != PCI_VENDOR_NVIDIA &&
210 	    PCI_VENDOR(id) != PCI_VENDOR_INTEL)
211 		pba.pba_flags &= ~PCI_FLAGS_MSI_ENABLED;
212 
213 	/*
214 	 * Don't enable MSI on a HyperTransport bus.  In order to
215 	 * determine that a bus is a HyperTransport bus, we look at
216 	 * device 24 function 0, which is the HyperTransport
217 	 * host/primary interface integrated on most 64-bit AMD CPUs.
218 	 * If that device has a HyperTransport capability, this must
219 	 * be a HyperTransport bus and we disable MSI.
220 	 */
221 	tag = pci_make_tag(pba.pba_pc, sc->sc_bus, 24, 0);
222 	if (pci_get_capability(pba.pba_pc, tag, PCI_CAP_HT, NULL, NULL))
223 		pba.pba_flags &= ~PCI_FLAGS_MSI_ENABLED;
224 
225 	config_found(parent, &pba, acpipci_print);
226 }
227 
228 void
229 acpipci_attach_busses(struct device *parent)
230 {
231 	int i;
232 
233 	for (i = 0; i < acpipci_cd.cd_ndevs; i++) {
234 		if (acpipci_cd.cd_devs[i])
235 			acpipci_attach_bus(parent, acpipci_cd.cd_devs[i]);
236 	}
237 }
238 
239 int
240 acpipci_print(void *aux, const char *pnp)
241 {
242 	struct pcibus_attach_args *pba = aux;
243 
244 	if (pnp)
245 		printf("%s at %s", pba->pba_busname, pnp);
246 	printf(" bus %d", pba->pba_bus);
247 	return (UNCONF);
248 }
249 
250 int
251 acpipci_parse_resources(int crsidx, union acpi_resource *crs, void *arg)
252 {
253 	struct acpipci_softc *sc = arg;
254 	int type = AML_CRSTYPE(crs);
255 	int restype, tflags = 0;
256 	u_long min, len = 0, tra = 0;
257 
258 	switch (type) {
259 	case LR_WORD:
260 		restype = crs->lr_word.type;
261 		tflags = crs->lr_word.tflags;
262 		min = crs->lr_word._min;
263 		len = crs->lr_word._len;
264 		tra = crs->lr_word._tra;
265 		break;
266 	case LR_DWORD:
267 		restype = crs->lr_dword.type;
268 		tflags = crs->lr_dword.tflags;
269 		min = crs->lr_dword._min;
270 		len = crs->lr_dword._len;
271 		tra = crs->lr_dword._tra;
272 		break;
273 	case LR_QWORD:
274 		restype = crs->lr_qword.type;
275 		tflags = crs->lr_qword.tflags;
276 		min = crs->lr_qword._min;
277 		len = crs->lr_qword._len;
278 		tra = crs->lr_qword._tra;
279 		break;
280 	case LR_MEM32FIXED:
281 		/*
282 		 * Coreboot on the PC Engines apu2 incorrectly uses a
283 		 * Memory32Fixed resource descriptor to describe mmio
284 		 * address space forwarded to the PCI bus.
285 		 */
286 		restype = LR_TYPE_MEMORY;
287 		min = crs->lr_m32fixed._bas;
288 		len = crs->lr_m32fixed._len;
289 		break;
290 	}
291 
292 	if (len == 0)
293 		return 0;
294 
295 	switch (restype) {
296 	case LR_TYPE_MEMORY:
297 		if (tflags & LR_MEMORY_TTP)
298 			return 0;
299 		extent_free(sc->sc_memex, min, len, EX_WAITOK | EX_CONFLICTOK);
300 		break;
301 	case LR_TYPE_IO:
302 		if (tflags & LR_IO_TTP)
303 			return 0;
304 		extent_free(sc->sc_ioex, min, len, EX_WAITOK | EX_CONFLICTOK);
305 		break;
306 	case LR_TYPE_BUS:
307 		extent_free(sc->sc_busex, min, len, EX_WAITOK);
308 		/*
309 		 * Let _CRS minimum bus number override _BBN.
310 		 */
311 		sc->sc_bus = min;
312 		break;
313 	}
314 
315 	return 0;
316 }
317 
318 void
319 acpipci_osc(struct acpipci_softc *sc)
320 {
321 	struct aml_value args[4];
322 	struct aml_value res;
323 	static uint8_t uuid[16] = ACPI_PCI_UUID;
324 	uint32_t buf[3];
325 
326 	memset(args, 0, sizeof(args));
327 	args[0].type = AML_OBJTYPE_BUFFER;
328 	args[0].v_buffer = uuid;
329 	args[0].length = sizeof(uuid);
330 	args[1].type = AML_OBJTYPE_INTEGER;
331 	args[1].v_integer = 1;
332 	args[2].type = AML_OBJTYPE_INTEGER;
333 	args[2].v_integer = 3;
334 	args[3].type = AML_OBJTYPE_BUFFER;
335 	args[3].v_buffer = (uint8_t *)buf;
336 	args[3].length = sizeof(buf);
337 
338 	memset(buf, 0, sizeof(buf));
339 	buf[0] = 0x0;
340 	buf[1] = ACPI_PCI_PCIE_CONFIG | ACPI_PCI_MSI;
341 	buf[2] = ACPI_PCI_PCIE_HOTPLUG;
342 
343 	if (aml_evalname(sc->sc_acpi, sc->sc_node, "_OSC", 4, args, &res))
344 		return;
345 
346 	if (res.type == AML_OBJTYPE_BUFFER) {
347 		size_t len = res.length;
348 		uint32_t *p = (uint32_t *)res.v_buffer;
349 
350 		printf(":");
351 		while (len >= 4) {
352 			printf(" 0x%08x", *p);
353 			p++;
354 			len -= 4;
355 		}
356 	}
357 }
358