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