xref: /openbsd-src/sys/arch/arm64/dev/mainbus.c (revision b0d2811898b6af5f105845a12bf9d62865077da0)
1*b0d28118Sjsg /* $OpenBSD: mainbus.c,v 1.32 2024/11/18 05:32:39 jsg Exp $ */
2f24071e5Spatrick /*
3f24071e5Spatrick  * Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
43f173131Skettenis  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
5f24071e5Spatrick  *
6f24071e5Spatrick  * Permission to use, copy, modify, and distribute this software for any
7f24071e5Spatrick  * purpose with or without fee is hereby granted, provided that the above
8f24071e5Spatrick  * copyright notice and this permission notice appear in all copies.
9f24071e5Spatrick  *
10f24071e5Spatrick  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11f24071e5Spatrick  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12f24071e5Spatrick  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13f24071e5Spatrick  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14f24071e5Spatrick  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15f24071e5Spatrick  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16f24071e5Spatrick  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17f24071e5Spatrick  */
18f24071e5Spatrick 
19f24071e5Spatrick #include <sys/param.h>
20f24071e5Spatrick #include <sys/systm.h>
21f24071e5Spatrick #include <sys/kernel.h>
22f24071e5Spatrick #include <sys/device.h>
23f24071e5Spatrick #include <sys/malloc.h>
24f24071e5Spatrick 
25f24071e5Spatrick #include <machine/fdt.h>
26f24071e5Spatrick #include <dev/ofw/openfirm.h>
27f24071e5Spatrick #include <dev/ofw/fdt.h>
281d276ec2Spatrick #include <dev/ofw/ofw_misc.h>
29b4264e16Skettenis #include <dev/ofw/ofw_thermal.h>
30f24071e5Spatrick 
31f24071e5Spatrick int mainbus_match(struct device *, void *, void *);
32f24071e5Spatrick void mainbus_attach(struct device *, struct device *, void *);
33f24071e5Spatrick 
343f173131Skettenis void mainbus_attach_node(struct device *, int, cfmatch_t);
353f173131Skettenis int mainbus_match_status(struct device *, void *, void *);
363f173131Skettenis void mainbus_attach_cpus(struct device *, cfmatch_t);
373f173131Skettenis int mainbus_match_primary(struct device *, void *, void *);
383f173131Skettenis int mainbus_match_secondary(struct device *, void *, void *);
39d3ae5f18Skettenis void mainbus_attach_psci(struct device *);
40f937ff16Skettenis void mainbus_attach_efi(struct device *);
41edbb6e97Sphessler void mainbus_attach_apm(struct device *);
427f3d6940Skettenis void mainbus_attach_framebuffer(struct device *);
43b7307cadSpatrick void mainbus_attach_firmware(struct device *);
44e81ec5d9Spatrick void mainbus_attach_resvmem(struct device *);
45f24071e5Spatrick 
46f24071e5Spatrick struct mainbus_softc {
47f24071e5Spatrick 	struct device		 sc_dev;
48bc8204c3Skettenis 	int			 sc_node;
49f24071e5Spatrick 	bus_space_tag_t		 sc_iot;
50f24071e5Spatrick 	bus_dma_tag_t		 sc_dmat;
51f24071e5Spatrick 	int			 sc_acells;
52f24071e5Spatrick 	int			 sc_scells;
53f24071e5Spatrick 	int			*sc_ranges;
54f24071e5Spatrick 	int			 sc_rangeslen;
55bc8204c3Skettenis 	int			 sc_early;
5659e1682fSkettenis 	int			 sc_early_nodes[64];
57f24071e5Spatrick };
58f24071e5Spatrick 
599fdf0c62Smpi const struct cfattach mainbus_ca = {
60130ea1ecSderaadt 	sizeof(struct mainbus_softc), mainbus_match, mainbus_attach
61f24071e5Spatrick };
62f24071e5Spatrick 
63f24071e5Spatrick struct cfdriver mainbus_cd = {
64f24071e5Spatrick 	NULL, "mainbus", DV_DULL
65f24071e5Spatrick };
66f24071e5Spatrick 
67f24071e5Spatrick struct machine_bus_dma_tag mainbus_dma_tag = {
68f24071e5Spatrick 	NULL,
692d784deaSpatrick 	0,
70f24071e5Spatrick 	_dmamap_create,
71f24071e5Spatrick 	_dmamap_destroy,
72f24071e5Spatrick 	_dmamap_load,
73f24071e5Spatrick 	_dmamap_load_mbuf,
74f24071e5Spatrick 	_dmamap_load_uio,
75f24071e5Spatrick 	_dmamap_load_raw,
76f24071e5Spatrick 	_dmamap_load_buffer,
77f24071e5Spatrick 	_dmamap_unload,
78f24071e5Spatrick 	_dmamap_sync,
79f24071e5Spatrick 	_dmamem_alloc,
80f86ce5abSkettenis 	_dmamem_alloc_range,
81f24071e5Spatrick 	_dmamem_free,
82f24071e5Spatrick 	_dmamem_map,
83f24071e5Spatrick 	_dmamem_unmap,
84f24071e5Spatrick 	_dmamem_mmap,
85f24071e5Spatrick };
86f24071e5Spatrick 
87f24071e5Spatrick /*
88f24071e5Spatrick  * Mainbus takes care of FDT and non-FDT machines, so we
89f24071e5Spatrick  * always attach.
90f24071e5Spatrick  */
91f24071e5Spatrick int
92f24071e5Spatrick mainbus_match(struct device *parent, void *cfdata, void *aux)
93f24071e5Spatrick {
94f24071e5Spatrick 	return (1);
95f24071e5Spatrick }
96f24071e5Spatrick 
97c3d704d4Spatrick void agtimer_init(void);
98f24071e5Spatrick 
99f24071e5Spatrick void
100f24071e5Spatrick mainbus_attach(struct device *parent, struct device *self, void *aux)
101f24071e5Spatrick {
102f24071e5Spatrick 	struct mainbus_softc *sc = (struct mainbus_softc *)self;
103aaf7ae02Spatrick 	char prop[128];
104f24071e5Spatrick 	int node, len;
105f24071e5Spatrick 
106f24071e5Spatrick 	arm_intr_init_fdt();
107c3d704d4Spatrick 	agtimer_init();
108f24071e5Spatrick 
109bc8204c3Skettenis 	sc->sc_node = OF_peer(0);
110f24071e5Spatrick 	sc->sc_iot = &arm64_bs_tag;
111f24071e5Spatrick 	sc->sc_dmat = &mainbus_dma_tag;
112f24071e5Spatrick 	sc->sc_acells = OF_getpropint(OF_peer(0), "#address-cells", 1);
113f24071e5Spatrick 	sc->sc_scells = OF_getpropint(OF_peer(0), "#size-cells", 1);
114f24071e5Spatrick 
115aaf7ae02Spatrick 	len = OF_getprop(sc->sc_node, "model", prop, sizeof(prop));
116bc8204c3Skettenis 	if (len > 0) {
117aaf7ae02Spatrick 		printf(": %s\n", prop);
118f24071e5Spatrick 		hw_prod = malloc(len, M_DEVBUF, M_NOWAIT);
119f24071e5Spatrick 		if (hw_prod)
120aaf7ae02Spatrick 			strlcpy(hw_prod, prop, len);
121f24071e5Spatrick 	} else
122f24071e5Spatrick 		printf(": unknown model\n");
123f24071e5Spatrick 
124aaf7ae02Spatrick 	len = OF_getprop(sc->sc_node, "serial-number", prop, sizeof(prop));
125aaf7ae02Spatrick 	if (len > 0) {
126aaf7ae02Spatrick 		hw_serial = malloc(len, M_DEVBUF, M_NOWAIT);
127aaf7ae02Spatrick 		if (hw_serial)
128aaf7ae02Spatrick 			strlcpy(hw_serial, prop, len);
129aaf7ae02Spatrick 	}
130aaf7ae02Spatrick 
131d3ae5f18Skettenis 	mainbus_attach_psci(self);
13283e0a8eeSkettenis 	mainbus_attach_efi(self);
133d3ae5f18Skettenis 
1343f173131Skettenis 	/* Attach primary CPU first. */
1353f173131Skettenis 	mainbus_attach_cpus(self, mainbus_match_primary);
136f24071e5Spatrick 
137d3ae5f18Skettenis 	/* Attach secondary CPUs. */
138d3ae5f18Skettenis 	mainbus_attach_cpus(self, mainbus_match_secondary);
139d3ae5f18Skettenis 
140b7307cadSpatrick 	mainbus_attach_firmware(self);
141e81ec5d9Spatrick 	mainbus_attach_resvmem(self);
142f937ff16Skettenis 
143f24071e5Spatrick 	sc->sc_rangeslen = OF_getproplen(OF_peer(0), "ranges");
144f24071e5Spatrick 	if (sc->sc_rangeslen > 0 && !(sc->sc_rangeslen % sizeof(uint32_t))) {
145f24071e5Spatrick 		sc->sc_ranges = malloc(sc->sc_rangeslen, M_TEMP, M_WAITOK);
146f24071e5Spatrick 		OF_getpropintarray(OF_peer(0), "ranges", sc->sc_ranges,
147f24071e5Spatrick 		    sc->sc_rangeslen);
148f24071e5Spatrick 	}
149f24071e5Spatrick 
150edbb6e97Sphessler 	mainbus_attach_apm(self);
151edbb6e97Sphessler 
152f24071e5Spatrick 	/* Scan the whole tree. */
153159e7744Skettenis 	for (sc->sc_early = 2; sc->sc_early >= 0; sc->sc_early--) {
154159e7744Skettenis 		for (node = OF_child(sc->sc_node); node; node = OF_peer(node))
155bc8204c3Skettenis 			mainbus_attach_node(self, node, NULL);
156159e7744Skettenis 	}
15779109fa9Skettenis 	sc->sc_early = 0;
1583f173131Skettenis 
159d788c4b2Skettenis 	/*
160d788c4b2Skettenis 	 * Delay attaching the framebuffer to give other drivers a
161d788c4b2Skettenis 	 * chance to claim it.
162d788c4b2Skettenis 	 */
163d788c4b2Skettenis 	config_mountroot(self, mainbus_attach_framebuffer);
1647f3d6940Skettenis 
165b4264e16Skettenis 	thermal_init();
166f24071e5Spatrick }
167f24071e5Spatrick 
16859e1682fSkettenis int
16959e1682fSkettenis mainbus_print(void *aux, const char *pnp)
17059e1682fSkettenis {
17159e1682fSkettenis 	struct fdt_attach_args *fa = aux;
172cd634a72Skettenis 	char buf[32];
17359e1682fSkettenis 
17459e1682fSkettenis 	if (!pnp)
17559e1682fSkettenis 		return (QUIET);
17659e1682fSkettenis 
177cd634a72Skettenis 	if (OF_getprop(fa->fa_node, "status", buf, sizeof(buf)) > 0 &&
178cd634a72Skettenis 	    strcmp(buf, "disabled") == 0)
17959e1682fSkettenis 		return (QUIET);
180cd634a72Skettenis 
181cd634a72Skettenis 	if (OF_getprop(fa->fa_node, "name", buf, sizeof(buf)) > 0) {
182cd634a72Skettenis 		buf[sizeof(buf) - 1] = 0;
183cd634a72Skettenis 		if (strcmp(buf, "aliases") == 0 ||
184cd634a72Skettenis 		    strcmp(buf, "chosen") == 0 ||
185cd634a72Skettenis 		    strcmp(buf, "cpus") == 0 ||
186b6d66b48Skettenis 		    strcmp(buf, "memory") == 0 ||
187b6d66b48Skettenis 		    strcmp(buf, "reserved-memory") == 0 ||
188b6d66b48Skettenis 		    strcmp(buf, "thermal-zones") == 0 ||
189b6d66b48Skettenis 		    strncmp(buf, "__", 2) == 0)
190cd634a72Skettenis 			return (QUIET);
191cd634a72Skettenis 		printf("\"%s\"", buf);
19259e1682fSkettenis 	} else
19359e1682fSkettenis 		printf("node %u", fa->fa_node);
19459e1682fSkettenis 
19559e1682fSkettenis 	printf(" at %s", pnp);
19659e1682fSkettenis 
19759e1682fSkettenis 	return (UNCONF);
19859e1682fSkettenis }
19959e1682fSkettenis 
200f24071e5Spatrick /*
201f24071e5Spatrick  * Look for a driver that wants to be attached to this node.
202f24071e5Spatrick  */
203f24071e5Spatrick void
2043f173131Skettenis mainbus_attach_node(struct device *self, int node, cfmatch_t submatch)
205f24071e5Spatrick {
206f24071e5Spatrick 	struct mainbus_softc	*sc = (struct mainbus_softc *)self;
207f24071e5Spatrick 	struct fdt_attach_args	 fa;
208f24071e5Spatrick 	int			 i, len, line;
209f24071e5Spatrick 	uint32_t		*cell, *reg;
21059e1682fSkettenis 	struct device		*child;
21159e1682fSkettenis 	cfprint_t		 print = NULL;
21259e1682fSkettenis 
21359e1682fSkettenis 	/* Skip if already attached early. */
21459e1682fSkettenis 	for (i = 0; i < nitems(sc->sc_early_nodes); i++) {
21559e1682fSkettenis 		if (sc->sc_early_nodes[i] == node)
21659e1682fSkettenis 			return;
21759e1682fSkettenis 		if (sc->sc_early_nodes[i] == 0)
21859e1682fSkettenis 			break;
21959e1682fSkettenis 	}
220f24071e5Spatrick 
221f24071e5Spatrick 	memset(&fa, 0, sizeof(fa));
222f24071e5Spatrick 	fa.fa_name = "";
223f24071e5Spatrick 	fa.fa_node = node;
224f24071e5Spatrick 	fa.fa_iot = sc->sc_iot;
225f24071e5Spatrick 	fa.fa_dmat = sc->sc_dmat;
226f24071e5Spatrick 	fa.fa_acells = sc->sc_acells;
227f24071e5Spatrick 	fa.fa_scells = sc->sc_scells;
228f24071e5Spatrick 
229f24071e5Spatrick 	len = OF_getproplen(node, "reg");
230f24071e5Spatrick 	line = (sc->sc_acells + sc->sc_scells) * sizeof(uint32_t);
231f24071e5Spatrick 	if (len > 0 && (len % line) == 0) {
232f24071e5Spatrick 		reg = malloc(len, M_TEMP, M_WAITOK);
233f24071e5Spatrick 		OF_getpropintarray(node, "reg", reg, len);
234f24071e5Spatrick 
235f24071e5Spatrick 		fa.fa_reg = malloc((len / line) * sizeof(struct fdt_reg),
236f24071e5Spatrick 		    M_DEVBUF, M_WAITOK);
237f24071e5Spatrick 		fa.fa_nreg = (len / line);
238f24071e5Spatrick 
239f24071e5Spatrick 		for (i = 0, cell = reg; i < len / line; i++) {
240f24071e5Spatrick 			if (sc->sc_acells >= 1)
241f24071e5Spatrick 				fa.fa_reg[i].addr = cell[0];
242f24071e5Spatrick 			if (sc->sc_acells == 2) {
243f24071e5Spatrick 				fa.fa_reg[i].addr <<= 32;
244f24071e5Spatrick 				fa.fa_reg[i].addr |= cell[1];
245f24071e5Spatrick 			}
246f24071e5Spatrick 			cell += sc->sc_acells;
247f24071e5Spatrick 			if (sc->sc_scells >= 1)
248f24071e5Spatrick 				fa.fa_reg[i].size = cell[0];
249f24071e5Spatrick 			if (sc->sc_scells == 2) {
250f24071e5Spatrick 				fa.fa_reg[i].size <<= 32;
251f24071e5Spatrick 				fa.fa_reg[i].size |= cell[1];
252f24071e5Spatrick 			}
253f24071e5Spatrick 			cell += sc->sc_scells;
254f24071e5Spatrick 		}
255f24071e5Spatrick 
256f24071e5Spatrick 		free(reg, M_TEMP, len);
257f24071e5Spatrick 	}
258f24071e5Spatrick 
259f24071e5Spatrick 	len = OF_getproplen(node, "interrupts");
260f24071e5Spatrick 	if (len > 0 && (len % sizeof(uint32_t)) == 0) {
261f24071e5Spatrick 		fa.fa_intr = malloc(len, M_DEVBUF, M_WAITOK);
262f24071e5Spatrick 		fa.fa_nintr = len / sizeof(uint32_t);
263f24071e5Spatrick 
264f24071e5Spatrick 		OF_getpropintarray(node, "interrupts", fa.fa_intr, len);
265f24071e5Spatrick 	}
266f24071e5Spatrick 
26748bd625bSkettenis 	if (OF_getproplen(node, "dma-coherent") >= 0) {
26848bd625bSkettenis 		fa.fa_dmat = malloc(sizeof(*sc->sc_dmat),
26948bd625bSkettenis 		    M_DEVBUF, M_WAITOK | M_ZERO);
27048bd625bSkettenis 		memcpy(fa.fa_dmat, sc->sc_dmat, sizeof(*sc->sc_dmat));
27148bd625bSkettenis 		fa.fa_dmat->_flags |= BUS_DMA_COHERENT;
27248bd625bSkettenis 	}
27348bd625bSkettenis 
2741d276ec2Spatrick 	fa.fa_dmat = iommu_device_map(fa.fa_node, fa.fa_dmat);
2751d276ec2Spatrick 
27659e1682fSkettenis 	if (submatch == NULL && sc->sc_early == 0)
27759e1682fSkettenis 		print = mainbus_print;
2783f173131Skettenis 	if (submatch == NULL)
2793f173131Skettenis 		submatch = mainbus_match_status;
28059e1682fSkettenis 
28159e1682fSkettenis 	child = config_found_sm(self, &fa, print, submatch);
28259e1682fSkettenis 
28359e1682fSkettenis 	/* Record nodes that we attach early. */
28459e1682fSkettenis 	if (child && sc->sc_early) {
28559e1682fSkettenis 		for (i = 0; i < nitems(sc->sc_early_nodes); i++) {
28659e1682fSkettenis 			if (sc->sc_early_nodes[i] != 0)
28759e1682fSkettenis 				continue;
28859e1682fSkettenis 			sc->sc_early_nodes[i] = node;
28959e1682fSkettenis 			break;
29059e1682fSkettenis 		}
29159e1682fSkettenis 	}
292f24071e5Spatrick 
293f24071e5Spatrick 	free(fa.fa_reg, M_DEVBUF, fa.fa_nreg * sizeof(struct fdt_reg));
294f24071e5Spatrick 	free(fa.fa_intr, M_DEVBUF, fa.fa_nintr * sizeof(uint32_t));
295f24071e5Spatrick }
296f24071e5Spatrick 
2973f173131Skettenis int
2983f173131Skettenis mainbus_match_status(struct device *parent, void *match, void *aux)
299f24071e5Spatrick {
300bc8204c3Skettenis 	struct mainbus_softc *sc = (struct mainbus_softc *)parent;
3013f173131Skettenis 	struct fdt_attach_args *fa = aux;
3023f173131Skettenis 	struct cfdata *cf = match;
3033f173131Skettenis 	char buf[32];
304f24071e5Spatrick 
3053f173131Skettenis 	if (OF_getprop(fa->fa_node, "status", buf, sizeof(buf)) > 0 &&
3063f173131Skettenis 	    strcmp(buf, "disabled") == 0)
3073f173131Skettenis 		return 0;
308f24071e5Spatrick 
309bc8204c3Skettenis 	if (cf->cf_loc[0] == sc->sc_early)
3103f173131Skettenis 		return (*cf->cf_attach->ca_match)(parent, match, aux);
31159e1682fSkettenis 
312bc8204c3Skettenis 	return 0;
3133f173131Skettenis }
3143f173131Skettenis 
3153f173131Skettenis void
3163f173131Skettenis mainbus_attach_cpus(struct device *self, cfmatch_t match)
3173f173131Skettenis {
3183f173131Skettenis 	struct mainbus_softc *sc = (struct mainbus_softc *)self;
3193f173131Skettenis 	int node = OF_finddevice("/cpus");
3203f173131Skettenis 	int acells, scells;
321b1ea6db3Skettenis 	char buf[32];
3223f173131Skettenis 
3236690d8f5Skettenis 	if (node == -1)
3243f173131Skettenis 		return;
3253f173131Skettenis 
3263f173131Skettenis 	acells = sc->sc_acells;
3273f173131Skettenis 	scells = sc->sc_scells;
3283f173131Skettenis 	sc->sc_acells = OF_getpropint(node, "#address-cells", 2);
3293f173131Skettenis 	sc->sc_scells = OF_getpropint(node, "#size-cells", 0);
3303f173131Skettenis 
331b1ea6db3Skettenis 	ncpusfound = 0;
332b1ea6db3Skettenis 	for (node = OF_child(node); node != 0; node = OF_peer(node)) {
333b1ea6db3Skettenis 		if (OF_getprop(node, "device_type", buf, sizeof(buf)) > 0 &&
334b1ea6db3Skettenis 		    strcmp(buf, "cpu") == 0)
335b1ea6db3Skettenis 			ncpusfound++;
336b1ea6db3Skettenis 
3373f173131Skettenis 		mainbus_attach_node(self, node, match);
338b1ea6db3Skettenis 	}
3393f173131Skettenis 
3403f173131Skettenis 	sc->sc_acells = acells;
3413f173131Skettenis 	sc->sc_scells = scells;
3423f173131Skettenis }
3433f173131Skettenis 
3443f173131Skettenis int
3453f173131Skettenis mainbus_match_primary(struct device *parent, void *match, void *aux)
3463f173131Skettenis {
3473f173131Skettenis 	struct fdt_attach_args *fa = aux;
3483f173131Skettenis 	struct cfdata *cf = match;
3493f173131Skettenis 	uint64_t mpidr = READ_SPECIALREG(mpidr_el1);
3503f173131Skettenis 
3513f173131Skettenis 	if (fa->fa_nreg < 1 || fa->fa_reg[0].addr != (mpidr & MPIDR_AFF))
3523f173131Skettenis 		return 0;
3533f173131Skettenis 
3543f173131Skettenis 	return (*cf->cf_attach->ca_match)(parent, match, aux);
3553f173131Skettenis }
3563f173131Skettenis 
3573f173131Skettenis int
3583f173131Skettenis mainbus_match_secondary(struct device *parent, void *match, void *aux)
3593f173131Skettenis {
3603f173131Skettenis 	struct fdt_attach_args *fa = aux;
3613f173131Skettenis 	struct cfdata *cf = match;
3623f173131Skettenis 	uint64_t mpidr = READ_SPECIALREG(mpidr_el1);
3633f173131Skettenis 
3643f173131Skettenis 	if (fa->fa_nreg < 1 || fa->fa_reg[0].addr == (mpidr & MPIDR_AFF))
3653f173131Skettenis 		return 0;
3663f173131Skettenis 
3673f173131Skettenis 	return (*cf->cf_attach->ca_match)(parent, match, aux);
368f24071e5Spatrick }
3697f3d6940Skettenis 
3707f3d6940Skettenis void
371d3ae5f18Skettenis mainbus_attach_psci(struct device *self)
372d3ae5f18Skettenis {
373d3ae5f18Skettenis 	struct mainbus_softc *sc = (struct mainbus_softc *)self;
374d3ae5f18Skettenis 	int node = OF_finddevice("/psci");
375d3ae5f18Skettenis 
3766690d8f5Skettenis 	if (node == -1)
377d3ae5f18Skettenis 		return;
378d3ae5f18Skettenis 
379d3ae5f18Skettenis 	sc->sc_early = 1;
380d3ae5f18Skettenis 	mainbus_attach_node(self, node, NULL);
381d3ae5f18Skettenis 	sc->sc_early = 0;
382d3ae5f18Skettenis }
383d3ae5f18Skettenis 
384d3ae5f18Skettenis void
385f937ff16Skettenis mainbus_attach_efi(struct device *self)
386f937ff16Skettenis {
387f937ff16Skettenis 	struct mainbus_softc *sc = (struct mainbus_softc *)self;
388f937ff16Skettenis 	struct fdt_attach_args fa;
389f937ff16Skettenis 	int node = OF_finddevice("/chosen");
390f937ff16Skettenis 
3916690d8f5Skettenis 	if (node == -1 ||
3926690d8f5Skettenis 	    OF_getproplen(node, "openbsd,uefi-system-table") <= 0)
393f937ff16Skettenis 		return;
394f937ff16Skettenis 
395f937ff16Skettenis 	memset(&fa, 0, sizeof(fa));
396f937ff16Skettenis 	fa.fa_name = "efi";
397f937ff16Skettenis 	fa.fa_iot = sc->sc_iot;
398f937ff16Skettenis 	fa.fa_dmat = sc->sc_dmat;
399f937ff16Skettenis 	config_found(self, &fa, NULL);
400f937ff16Skettenis }
401f937ff16Skettenis 
402f937ff16Skettenis void
403edbb6e97Sphessler mainbus_attach_apm(struct device *self)
404edbb6e97Sphessler {
405edbb6e97Sphessler 	struct fdt_attach_args fa;
406edbb6e97Sphessler 
407edbb6e97Sphessler 	memset(&fa, 0, sizeof(fa));
408edbb6e97Sphessler 	fa.fa_name = "apm";
409edbb6e97Sphessler 
410edbb6e97Sphessler 	config_found(self, &fa, NULL);
411edbb6e97Sphessler }
412edbb6e97Sphessler 
413edbb6e97Sphessler void
4147f3d6940Skettenis mainbus_attach_framebuffer(struct device *self)
4157f3d6940Skettenis {
4167f3d6940Skettenis 	int node = OF_finddevice("/chosen");
4177f3d6940Skettenis 
4186690d8f5Skettenis 	if (node == -1)
4197f3d6940Skettenis 		return;
4207f3d6940Skettenis 
4217f3d6940Skettenis 	for (node = OF_child(node); node != 0; node = OF_peer(node))
4227f3d6940Skettenis 		mainbus_attach_node(self, node, NULL);
4237f3d6940Skettenis }
424b7307cadSpatrick 
425b7307cadSpatrick void
426b7307cadSpatrick mainbus_attach_firmware(struct device *self)
427b7307cadSpatrick {
428b7307cadSpatrick 	int node = OF_finddevice("/firmware");
429b7307cadSpatrick 
430b7307cadSpatrick 	if (node == -1)
431b7307cadSpatrick 		return;
432b7307cadSpatrick 
433b7307cadSpatrick 	for (node = OF_child(node); node != 0; node = OF_peer(node))
434b7307cadSpatrick 		mainbus_attach_node(self, node, NULL);
435b7307cadSpatrick }
436e81ec5d9Spatrick 
437e81ec5d9Spatrick void
438e81ec5d9Spatrick mainbus_attach_resvmem(struct device *self)
439e81ec5d9Spatrick {
440e81ec5d9Spatrick 	int node = OF_finddevice("/reserved-memory");
441e81ec5d9Spatrick 
442e81ec5d9Spatrick 	if (node == -1)
443e81ec5d9Spatrick 		return;
444e81ec5d9Spatrick 
445e81ec5d9Spatrick 	for (node = OF_child(node); node != 0; node = OF_peer(node))
446e81ec5d9Spatrick 		mainbus_attach_node(self, node, NULL);
447e81ec5d9Spatrick }
448