1fe3b4685SNathan Whitehorn /*- 2fe3b4685SNathan Whitehorn * Copyright (C) 1996 Wolfgang Solfrank. 3fe3b4685SNathan Whitehorn * Copyright (C) 1996 TooLs GmbH. 4fe3b4685SNathan Whitehorn * All rights reserved. 5fe3b4685SNathan Whitehorn * 6fe3b4685SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 7fe3b4685SNathan Whitehorn * modification, are permitted provided that the following conditions 8fe3b4685SNathan Whitehorn * are met: 9fe3b4685SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 10fe3b4685SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 11fe3b4685SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 12fe3b4685SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 13fe3b4685SNathan Whitehorn * documentation and/or other materials provided with the distribution. 14fe3b4685SNathan Whitehorn * 3. All advertising materials mentioning features or use of this software 15fe3b4685SNathan Whitehorn * must display the following acknowledgement: 16fe3b4685SNathan Whitehorn * This product includes software developed by TooLs GmbH. 17fe3b4685SNathan Whitehorn * 4. The name of TooLs GmbH may not be used to endorse or promote products 18fe3b4685SNathan Whitehorn * derived from this software without specific prior written permission. 19fe3b4685SNathan Whitehorn * 20fe3b4685SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 21fe3b4685SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22fe3b4685SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23fe3b4685SNathan Whitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24fe3b4685SNathan Whitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25fe3b4685SNathan Whitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26fe3b4685SNathan Whitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27fe3b4685SNathan Whitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28fe3b4685SNathan Whitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29fe3b4685SNathan Whitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30fe3b4685SNathan Whitehorn * 31fe3b4685SNathan Whitehorn * $NetBSD: ofw_machdep.c,v 1.5 2000/05/23 13:25:43 tsubai Exp $ 32fe3b4685SNathan Whitehorn */ 33fe3b4685SNathan Whitehorn 34fe3b4685SNathan Whitehorn #include <sys/cdefs.h> 35fe3b4685SNathan Whitehorn __FBSDID("$FreeBSD$"); 36fe3b4685SNathan Whitehorn 378c092157SJustin Hibbits #include "opt_platform.h" 38fe3b4685SNathan Whitehorn #include <sys/param.h> 39fe3b4685SNathan Whitehorn #include <sys/bus.h> 40fe3b4685SNathan Whitehorn #include <sys/systm.h> 41fe3b4685SNathan Whitehorn #include <sys/conf.h> 42fe3b4685SNathan Whitehorn #include <sys/disk.h> 43fe3b4685SNathan Whitehorn #include <sys/fcntl.h> 44fe3b4685SNathan Whitehorn #include <sys/malloc.h> 45fe3b4685SNathan Whitehorn #include <sys/smp.h> 46fe3b4685SNathan Whitehorn #include <sys/stat.h> 47b9d056f3SNathan Whitehorn #include <sys/endian.h> 48fe3b4685SNathan Whitehorn 49fe3b4685SNathan Whitehorn #include <net/ethernet.h> 50fe3b4685SNathan Whitehorn 518c092157SJustin Hibbits #include <dev/fdt/fdt_common.h> 52fe3b4685SNathan Whitehorn #include <dev/ofw/openfirm.h> 53fe3b4685SNathan Whitehorn #include <dev/ofw/ofw_pci.h> 54fe3b4685SNathan Whitehorn #include <dev/ofw/ofw_bus.h> 55bc7b9300SIan Lepore #include <dev/ofw/ofw_subr.h> 56fe3b4685SNathan Whitehorn 57fe3b4685SNathan Whitehorn #include <vm/vm.h> 58fe3b4685SNathan Whitehorn #include <vm/vm_param.h> 59fe3b4685SNathan Whitehorn #include <vm/vm_page.h> 60fe3b4685SNathan Whitehorn 61fe3b4685SNathan Whitehorn #include <machine/bus.h> 62fe3b4685SNathan Whitehorn #include <machine/cpu.h> 63fe3b4685SNathan Whitehorn #include <machine/md_var.h> 64fe3b4685SNathan Whitehorn #include <machine/platform.h> 65fe3b4685SNathan Whitehorn #include <machine/ofw_machdep.h> 66f367ffdeSAndreas Tobler #include <machine/trap.h> 67fe3b4685SNathan Whitehorn 68c0650b2fSNathan Whitehorn #include <contrib/libfdt/libfdt.h> 69c0650b2fSNathan Whitehorn 706f489d43SJustin Hibbits static void *fdt; 716f489d43SJustin Hibbits int ofw_real_mode; 726f489d43SJustin Hibbits 73629aa519SNathan Whitehorn #ifdef AIM 74fe3b4685SNathan Whitehorn extern register_t ofmsr[5]; 7517879090SNathan Whitehorn extern void *openfirmware_entry; 76bb808254SNathan Whitehorn char save_trap_init[0x2f00]; /* EXC_LAST */ 77f367ffdeSAndreas Tobler char save_trap_of[0x2f00]; /* EXC_LAST */ 78fe3b4685SNathan Whitehorn 79d8c6808aSNathan Whitehorn int ofwcall(void *); 80fe3b4685SNathan Whitehorn static int openfirmware(void *args); 81fe3b4685SNathan Whitehorn 82f367ffdeSAndreas Tobler __inline void 83f367ffdeSAndreas Tobler ofw_save_trap_vec(char *save_trap_vec) 84f367ffdeSAndreas Tobler { 85c1cb22d7SNathan Whitehorn if (!ofw_real_mode) 86f367ffdeSAndreas Tobler return; 87f367ffdeSAndreas Tobler 88f367ffdeSAndreas Tobler bcopy((void *)EXC_RST, save_trap_vec, EXC_LAST - EXC_RST); 89f367ffdeSAndreas Tobler } 90f367ffdeSAndreas Tobler 91f367ffdeSAndreas Tobler static __inline void 92f367ffdeSAndreas Tobler ofw_restore_trap_vec(char *restore_trap_vec) 93f367ffdeSAndreas Tobler { 94c1cb22d7SNathan Whitehorn if (!ofw_real_mode) 95f367ffdeSAndreas Tobler return; 96f367ffdeSAndreas Tobler 97f367ffdeSAndreas Tobler bcopy(restore_trap_vec, (void *)EXC_RST, EXC_LAST - EXC_RST); 98f367ffdeSAndreas Tobler __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD); 99f367ffdeSAndreas Tobler } 1004aa3cee6SNathan Whitehorn 1014aa3cee6SNathan Whitehorn /* 1024aa3cee6SNathan Whitehorn * Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback. 1034aa3cee6SNathan Whitehorn */ 1044aa3cee6SNathan Whitehorn register_t ofw_sprg0_save; 1054aa3cee6SNathan Whitehorn 1064aa3cee6SNathan Whitehorn static __inline void 1074aa3cee6SNathan Whitehorn ofw_sprg_prepare(void) 1084aa3cee6SNathan Whitehorn { 1094aa3cee6SNathan Whitehorn if (ofw_real_mode) 1104aa3cee6SNathan Whitehorn return; 1114aa3cee6SNathan Whitehorn 1124aa3cee6SNathan Whitehorn /* 1134aa3cee6SNathan Whitehorn * Assume that interrupt are disabled at this point, or 1144aa3cee6SNathan Whitehorn * SPRG1-3 could be trashed 1154aa3cee6SNathan Whitehorn */ 11662c6b30eSJustin Hibbits #ifdef __powerpc64__ 11762c6b30eSJustin Hibbits __asm __volatile("mtsprg1 %0\n\t" 11862c6b30eSJustin Hibbits "mtsprg2 %1\n\t" 11962c6b30eSJustin Hibbits "mtsprg3 %2\n\t" 12062c6b30eSJustin Hibbits : 12162c6b30eSJustin Hibbits : "r"(ofmsr[2]), 12262c6b30eSJustin Hibbits "r"(ofmsr[3]), 12362c6b30eSJustin Hibbits "r"(ofmsr[4])); 12462c6b30eSJustin Hibbits #else 1254aa3cee6SNathan Whitehorn __asm __volatile("mfsprg0 %0\n\t" 1264aa3cee6SNathan Whitehorn "mtsprg0 %1\n\t" 1274aa3cee6SNathan Whitehorn "mtsprg1 %2\n\t" 1284aa3cee6SNathan Whitehorn "mtsprg2 %3\n\t" 1294aa3cee6SNathan Whitehorn "mtsprg3 %4\n\t" 1304aa3cee6SNathan Whitehorn : "=&r"(ofw_sprg0_save) 1314aa3cee6SNathan Whitehorn : "r"(ofmsr[1]), 1324aa3cee6SNathan Whitehorn "r"(ofmsr[2]), 1334aa3cee6SNathan Whitehorn "r"(ofmsr[3]), 1344aa3cee6SNathan Whitehorn "r"(ofmsr[4])); 13562c6b30eSJustin Hibbits #endif 1364aa3cee6SNathan Whitehorn } 1374aa3cee6SNathan Whitehorn 1384aa3cee6SNathan Whitehorn static __inline void 1394aa3cee6SNathan Whitehorn ofw_sprg_restore(void) 1404aa3cee6SNathan Whitehorn { 1414aa3cee6SNathan Whitehorn if (ofw_real_mode) 1424aa3cee6SNathan Whitehorn return; 1434aa3cee6SNathan Whitehorn 1444aa3cee6SNathan Whitehorn /* 1454aa3cee6SNathan Whitehorn * Note that SPRG1-3 contents are irrelevant. They are scratch 1464aa3cee6SNathan Whitehorn * registers used in the early portion of trap handling when 1474aa3cee6SNathan Whitehorn * interrupts are disabled. 1484aa3cee6SNathan Whitehorn * 1494aa3cee6SNathan Whitehorn * PCPU data cannot be used until this routine is called ! 1504aa3cee6SNathan Whitehorn */ 15162c6b30eSJustin Hibbits #ifndef __powerpc64__ 1524aa3cee6SNathan Whitehorn __asm __volatile("mtsprg0 %0" :: "r"(ofw_sprg0_save)); 15362c6b30eSJustin Hibbits #endif 1544aa3cee6SNathan Whitehorn } 155c7291bdcSNathan Whitehorn #endif 156f367ffdeSAndreas Tobler 157fe3b4685SNathan Whitehorn static int 158fe3b4685SNathan Whitehorn parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output) 159fe3b4685SNathan Whitehorn { 160fe3b4685SNathan Whitehorn cell_t address_cells, size_cells; 161d8c6808aSNathan Whitehorn cell_t OFmem[4 * PHYS_AVAIL_SZ]; 162fe3b4685SNathan Whitehorn int sz, i, j; 163fe3b4685SNathan Whitehorn phandle_t phandle; 164fe3b4685SNathan Whitehorn 165fe3b4685SNathan Whitehorn sz = 0; 166fe3b4685SNathan Whitehorn 167fe3b4685SNathan Whitehorn /* 168fe3b4685SNathan Whitehorn * Get #address-cells from root node, defaulting to 1 if it cannot 169fe3b4685SNathan Whitehorn * be found. 170fe3b4685SNathan Whitehorn */ 171fe3b4685SNathan Whitehorn phandle = OF_finddevice("/"); 172509142e1SNathan Whitehorn if (OF_getencprop(phandle, "#address-cells", &address_cells, 1738bab0d80SNathan Whitehorn sizeof(address_cells)) < (ssize_t)sizeof(address_cells)) 174fe3b4685SNathan Whitehorn address_cells = 1; 175509142e1SNathan Whitehorn if (OF_getencprop(phandle, "#size-cells", &size_cells, 1768bab0d80SNathan Whitehorn sizeof(size_cells)) < (ssize_t)sizeof(size_cells)) 177fe3b4685SNathan Whitehorn size_cells = 1; 178fe3b4685SNathan Whitehorn 179fe3b4685SNathan Whitehorn /* 180fe3b4685SNathan Whitehorn * Get memory. 181fe3b4685SNathan Whitehorn */ 182509142e1SNathan Whitehorn if (node == -1 || (sz = OF_getencprop(node, prop, 183d8c6808aSNathan Whitehorn OFmem, sizeof(OFmem))) <= 0) 184fe3b4685SNathan Whitehorn panic("Physical memory map not found"); 185fe3b4685SNathan Whitehorn 186fe3b4685SNathan Whitehorn i = 0; 187fe3b4685SNathan Whitehorn j = 0; 188fe3b4685SNathan Whitehorn while (i < sz/sizeof(cell_t)) { 189fe3b4685SNathan Whitehorn output[j].mr_start = OFmem[i++]; 190fe3b4685SNathan Whitehorn if (address_cells == 2) { 191fe3b4685SNathan Whitehorn output[j].mr_start <<= 32; 192fe3b4685SNathan Whitehorn output[j].mr_start += OFmem[i++]; 193fe3b4685SNathan Whitehorn } 194fe3b4685SNathan Whitehorn 195fe3b4685SNathan Whitehorn output[j].mr_size = OFmem[i++]; 196fe3b4685SNathan Whitehorn if (size_cells == 2) { 197fe3b4685SNathan Whitehorn output[j].mr_size <<= 32; 198fe3b4685SNathan Whitehorn output[j].mr_size += OFmem[i++]; 199fe3b4685SNathan Whitehorn } 200fe3b4685SNathan Whitehorn 201bb7137e1SJustin Hibbits if (output[j].mr_start > BUS_SPACE_MAXADDR) 202bb7137e1SJustin Hibbits continue; 203bb7137e1SJustin Hibbits 204fe3b4685SNathan Whitehorn /* 205bb7137e1SJustin Hibbits * Constrain memory to that which we can access. 206bb7137e1SJustin Hibbits * 32-bit AIM can only reference 32 bits of address currently, 207bb7137e1SJustin Hibbits * but Book-E can access 36 bits. 208fe3b4685SNathan Whitehorn */ 209fe3b4685SNathan Whitehorn if (((uint64_t)output[j].mr_start + 210bb7137e1SJustin Hibbits (uint64_t)output[j].mr_size - 1) > 211bb7137e1SJustin Hibbits BUS_SPACE_MAXADDR) { 212bb7137e1SJustin Hibbits output[j].mr_size = BUS_SPACE_MAXADDR - 213bb7137e1SJustin Hibbits output[j].mr_start + 1; 214fe3b4685SNathan Whitehorn } 215fe3b4685SNathan Whitehorn 216fe3b4685SNathan Whitehorn j++; 217fe3b4685SNathan Whitehorn } 218fe3b4685SNathan Whitehorn sz = j*sizeof(output[0]); 219fe3b4685SNathan Whitehorn 220fe3b4685SNathan Whitehorn return (sz); 221fe3b4685SNathan Whitehorn } 222fe3b4685SNathan Whitehorn 223b9d056f3SNathan Whitehorn static int 224b9d056f3SNathan Whitehorn excise_fdt_reserved(struct mem_region *avail, int asz) 225b9d056f3SNathan Whitehorn { 226b9d056f3SNathan Whitehorn struct { 227b9d056f3SNathan Whitehorn uint64_t address; 228b9d056f3SNathan Whitehorn uint64_t size; 229b9d056f3SNathan Whitehorn } fdtmap[16]; 230b9d056f3SNathan Whitehorn ssize_t fdtmapsize; 231b9d056f3SNathan Whitehorn phandle_t chosen; 232b9d056f3SNathan Whitehorn int i, j, k; 233b9d056f3SNathan Whitehorn 234b9d056f3SNathan Whitehorn chosen = OF_finddevice("/chosen"); 235b9d056f3SNathan Whitehorn fdtmapsize = OF_getprop(chosen, "fdtmemreserv", fdtmap, sizeof(fdtmap)); 236b9d056f3SNathan Whitehorn 237b9d056f3SNathan Whitehorn for (j = 0; j < fdtmapsize/sizeof(fdtmap[0]); j++) { 238c0650b2fSNathan Whitehorn fdtmap[j].address = be64toh(fdtmap[j].address) & ~PAGE_MASK; 239c0650b2fSNathan Whitehorn fdtmap[j].size = round_page(be64toh(fdtmap[j].size)); 240c0650b2fSNathan Whitehorn } 241c0650b2fSNathan Whitehorn 242c0650b2fSNathan Whitehorn KASSERT(j*sizeof(fdtmap[0]) < sizeof(fdtmap), 243c0650b2fSNathan Whitehorn ("Exceeded number of FDT reservations")); 244c0650b2fSNathan Whitehorn /* Add a virtual entry for the FDT itself */ 245c0650b2fSNathan Whitehorn if (fdt != NULL) { 246c0650b2fSNathan Whitehorn fdtmap[j].address = (vm_offset_t)fdt & ~PAGE_MASK; 247c0650b2fSNathan Whitehorn fdtmap[j].size = round_page(fdt_totalsize(fdt)); 248c0650b2fSNathan Whitehorn fdtmapsize += sizeof(fdtmap[0]); 249b9d056f3SNathan Whitehorn } 250b9d056f3SNathan Whitehorn 251b9d056f3SNathan Whitehorn for (i = 0; i < asz; i++) { 252b9d056f3SNathan Whitehorn for (j = 0; j < fdtmapsize/sizeof(fdtmap[0]); j++) { 253b9d056f3SNathan Whitehorn /* 254b9d056f3SNathan Whitehorn * Case 1: Exclusion region encloses complete 255b9d056f3SNathan Whitehorn * available entry. Drop it and move on. 256b9d056f3SNathan Whitehorn */ 257b9d056f3SNathan Whitehorn if (fdtmap[j].address <= avail[i].mr_start && 258b9d056f3SNathan Whitehorn fdtmap[j].address + fdtmap[j].size >= 259b9d056f3SNathan Whitehorn avail[i].mr_start + avail[i].mr_size) { 260b9d056f3SNathan Whitehorn for (k = i+1; k < asz; k++) 261b9d056f3SNathan Whitehorn avail[k-1] = avail[k]; 262b9d056f3SNathan Whitehorn asz--; 263b9d056f3SNathan Whitehorn i--; /* Repeat some entries */ 264b9d056f3SNathan Whitehorn continue; 265b9d056f3SNathan Whitehorn } 266b9d056f3SNathan Whitehorn 267b9d056f3SNathan Whitehorn /* 268b9d056f3SNathan Whitehorn * Case 2: Exclusion region starts in available entry. 269b9d056f3SNathan Whitehorn * Trim it to where the entry begins and append 270b9d056f3SNathan Whitehorn * a new available entry with the region after 271b9d056f3SNathan Whitehorn * the excluded region, if any. 272b9d056f3SNathan Whitehorn */ 273b9d056f3SNathan Whitehorn if (fdtmap[j].address >= avail[i].mr_start && 274b9d056f3SNathan Whitehorn fdtmap[j].address < avail[i].mr_start + 275b9d056f3SNathan Whitehorn avail[i].mr_size) { 276b9d056f3SNathan Whitehorn if (fdtmap[j].address + fdtmap[j].size < 277b9d056f3SNathan Whitehorn avail[i].mr_start + avail[i].mr_size) { 278b9d056f3SNathan Whitehorn avail[asz].mr_start = 279922a3152SNathan Whitehorn fdtmap[j].address + fdtmap[j].size; 280b9d056f3SNathan Whitehorn avail[asz].mr_size = avail[i].mr_start + 281b9d056f3SNathan Whitehorn avail[i].mr_size - 282b9d056f3SNathan Whitehorn avail[asz].mr_start; 283b9d056f3SNathan Whitehorn asz++; 284b9d056f3SNathan Whitehorn } 285b9d056f3SNathan Whitehorn 286922a3152SNathan Whitehorn avail[i].mr_size = fdtmap[j].address - 287b9d056f3SNathan Whitehorn avail[i].mr_start; 288b9d056f3SNathan Whitehorn } 289b9d056f3SNathan Whitehorn 290b9d056f3SNathan Whitehorn /* 291b9d056f3SNathan Whitehorn * Case 3: Exclusion region ends in available entry. 292b9d056f3SNathan Whitehorn * Move start point to where the exclusion zone ends. 293b9d056f3SNathan Whitehorn * The case of a contained exclusion zone has already 294b9d056f3SNathan Whitehorn * been caught in case 2. 295b9d056f3SNathan Whitehorn */ 296b9d056f3SNathan Whitehorn if (fdtmap[j].address + fdtmap[j].size >= 297b9d056f3SNathan Whitehorn avail[i].mr_start && fdtmap[j].address + 298b9d056f3SNathan Whitehorn fdtmap[j].size < avail[i].mr_start + 299b9d056f3SNathan Whitehorn avail[i].mr_size) { 300922a3152SNathan Whitehorn avail[i].mr_size += avail[i].mr_start; 301b9d056f3SNathan Whitehorn avail[i].mr_start = 302922a3152SNathan Whitehorn fdtmap[j].address + fdtmap[j].size; 303922a3152SNathan Whitehorn avail[i].mr_size -= avail[i].mr_start; 304b9d056f3SNathan Whitehorn } 305b9d056f3SNathan Whitehorn } 306b9d056f3SNathan Whitehorn } 307b9d056f3SNathan Whitehorn 308b9d056f3SNathan Whitehorn return (asz); 309b9d056f3SNathan Whitehorn } 310b9d056f3SNathan Whitehorn 311fe3b4685SNathan Whitehorn /* 312fe3b4685SNathan Whitehorn * This is called during powerpc_init, before the system is really initialized. 313fe3b4685SNathan Whitehorn * It shall provide the total and the available regions of RAM. 314b9d056f3SNathan Whitehorn * The available regions need not take the kernel into account. 315fe3b4685SNathan Whitehorn */ 316fe3b4685SNathan Whitehorn void 317c1cb22d7SNathan Whitehorn ofw_mem_regions(struct mem_region *memp, int *memsz, 318c1cb22d7SNathan Whitehorn struct mem_region *availp, int *availsz) 319fe3b4685SNathan Whitehorn { 320fe3b4685SNathan Whitehorn phandle_t phandle; 321c1cb22d7SNathan Whitehorn int asz, msz; 322c1cb22d7SNathan Whitehorn int res; 323d8c6808aSNathan Whitehorn char name[31]; 324fe3b4685SNathan Whitehorn 325fe3b4685SNathan Whitehorn asz = msz = 0; 326fe3b4685SNathan Whitehorn 327fe3b4685SNathan Whitehorn /* 328d8c6808aSNathan Whitehorn * Get memory from all the /memory nodes. 329fe3b4685SNathan Whitehorn */ 330d8c6808aSNathan Whitehorn for (phandle = OF_child(OF_peer(0)); phandle != 0; 331d8c6808aSNathan Whitehorn phandle = OF_peer(phandle)) { 332d8c6808aSNathan Whitehorn if (OF_getprop(phandle, "name", name, sizeof(name)) <= 0) 333d8c6808aSNathan Whitehorn continue; 334b9d056f3SNathan Whitehorn if (strncmp(name, "memory", sizeof(name)) != 0 && 335b9d056f3SNathan Whitehorn strncmp(name, "memory@", strlen("memory@")) != 0) 336d8c6808aSNathan Whitehorn continue; 337fe3b4685SNathan Whitehorn 338c1cb22d7SNathan Whitehorn res = parse_ofw_memory(phandle, "reg", &memp[msz]); 339d8c6808aSNathan Whitehorn msz += res/sizeof(struct mem_region); 340d8c6808aSNathan Whitehorn if (OF_getproplen(phandle, "available") >= 0) 341d8c6808aSNathan Whitehorn res = parse_ofw_memory(phandle, "available", 342c1cb22d7SNathan Whitehorn &availp[asz]); 343d8c6808aSNathan Whitehorn else 344c1cb22d7SNathan Whitehorn res = parse_ofw_memory(phandle, "reg", &availp[asz]); 345d8c6808aSNathan Whitehorn asz += res/sizeof(struct mem_region); 346d8c6808aSNathan Whitehorn } 347d8c6808aSNathan Whitehorn 348b9d056f3SNathan Whitehorn phandle = OF_finddevice("/chosen"); 349b9d056f3SNathan Whitehorn if (OF_hasprop(phandle, "fdtmemreserv")) 350b9d056f3SNathan Whitehorn asz = excise_fdt_reserved(availp, asz); 351b9d056f3SNathan Whitehorn 352d8c6808aSNathan Whitehorn *memsz = msz; 353c1cb22d7SNathan Whitehorn *availsz = asz; 354fe3b4685SNathan Whitehorn } 355fe3b4685SNathan Whitehorn 356fe3b4685SNathan Whitehorn void 357fe3b4685SNathan Whitehorn OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *)) 358fe3b4685SNathan Whitehorn { 3596f489d43SJustin Hibbits #ifdef AIM 360bb808254SNathan Whitehorn ofmsr[0] = mfmsr(); 361bb808254SNathan Whitehorn #ifdef __powerpc64__ 362bb808254SNathan Whitehorn ofmsr[0] &= ~PSL_SF; 36362c6b30eSJustin Hibbits #else 364bb808254SNathan Whitehorn __asm __volatile("mfsprg0 %0" : "=&r"(ofmsr[1])); 36562c6b30eSJustin Hibbits #endif 366bb808254SNathan Whitehorn __asm __volatile("mfsprg1 %0" : "=&r"(ofmsr[2])); 367bb808254SNathan Whitehorn __asm __volatile("mfsprg2 %0" : "=&r"(ofmsr[3])); 368bb808254SNathan Whitehorn __asm __volatile("mfsprg3 %0" : "=&r"(ofmsr[4])); 3696f489d43SJustin Hibbits openfirmware_entry = openfirm; 370bb808254SNathan Whitehorn 371fe3b4685SNathan Whitehorn if (ofmsr[0] & PSL_DR) 372fe3b4685SNathan Whitehorn ofw_real_mode = 0; 373fe3b4685SNathan Whitehorn else 374fe3b4685SNathan Whitehorn ofw_real_mode = 1; 375fe3b4685SNathan Whitehorn 3766f489d43SJustin Hibbits ofw_save_trap_vec(save_trap_init); 3776f489d43SJustin Hibbits #else 3786f489d43SJustin Hibbits ofw_real_mode = 1; 3796f489d43SJustin Hibbits #endif 3806f489d43SJustin Hibbits 381fe3b4685SNathan Whitehorn fdt = fdt_ptr; 382fe3b4685SNathan Whitehorn 383fe3b4685SNathan Whitehorn #ifdef FDT_DTB_STATIC 384fe3b4685SNathan Whitehorn /* Check for a statically included blob */ 385fe3b4685SNathan Whitehorn if (fdt == NULL) 386fe3b4685SNathan Whitehorn fdt = &fdt_static_dtb; 387fe3b4685SNathan Whitehorn #endif 388fe3b4685SNathan Whitehorn } 389fe3b4685SNathan Whitehorn 390fe3b4685SNathan Whitehorn boolean_t 391fe3b4685SNathan Whitehorn OF_bootstrap() 392fe3b4685SNathan Whitehorn { 393fe3b4685SNathan Whitehorn boolean_t status = FALSE; 394fe3b4685SNathan Whitehorn 3956f489d43SJustin Hibbits #ifdef AIM 39617879090SNathan Whitehorn if (openfirmware_entry != NULL) { 397fe3b4685SNathan Whitehorn if (ofw_real_mode) { 398fe3b4685SNathan Whitehorn status = OF_install(OFW_STD_REAL, 0); 399fe3b4685SNathan Whitehorn } else { 400fe3b4685SNathan Whitehorn #ifdef __powerpc64__ 401fe3b4685SNathan Whitehorn status = OF_install(OFW_STD_32BIT, 0); 402fe3b4685SNathan Whitehorn #else 403fe3b4685SNathan Whitehorn status = OF_install(OFW_STD_DIRECT, 0); 404fe3b4685SNathan Whitehorn #endif 405fe3b4685SNathan Whitehorn } 406fe3b4685SNathan Whitehorn 407fe3b4685SNathan Whitehorn if (status != TRUE) 408fe3b4685SNathan Whitehorn return status; 409fe3b4685SNathan Whitehorn 410fe3b4685SNathan Whitehorn OF_init(openfirmware); 4116f489d43SJustin Hibbits } else 4126f489d43SJustin Hibbits #endif 4136f489d43SJustin Hibbits if (fdt != NULL) { 414fe3b4685SNathan Whitehorn status = OF_install(OFW_FDT, 0); 415fe3b4685SNathan Whitehorn 416fe3b4685SNathan Whitehorn if (status != TRUE) 417fe3b4685SNathan Whitehorn return status; 418fe3b4685SNathan Whitehorn 419fe3b4685SNathan Whitehorn OF_init(fdt); 4206f489d43SJustin Hibbits OF_interpret("perform-fixup", 0); 421fe3b4685SNathan Whitehorn } 422fe3b4685SNathan Whitehorn 423fe3b4685SNathan Whitehorn return (status); 424fe3b4685SNathan Whitehorn } 425fe3b4685SNathan Whitehorn 4266f489d43SJustin Hibbits #ifdef AIM 4279f706727SNathan Whitehorn void 428fe3b4685SNathan Whitehorn ofw_quiesce(void) 429fe3b4685SNathan Whitehorn { 430fe3b4685SNathan Whitehorn struct { 431fe3b4685SNathan Whitehorn cell_t name; 432fe3b4685SNathan Whitehorn cell_t nargs; 433fe3b4685SNathan Whitehorn cell_t nreturns; 434fe3b4685SNathan Whitehorn } args; 435fe3b4685SNathan Whitehorn 4369f706727SNathan Whitehorn KASSERT(!pmap_bootstrapped, ("Cannot call ofw_quiesce after VM is up")); 437fe3b4685SNathan Whitehorn 438fe3b4685SNathan Whitehorn args.name = (cell_t)(uintptr_t)"quiesce"; 439fe3b4685SNathan Whitehorn args.nargs = 0; 440fe3b4685SNathan Whitehorn args.nreturns = 0; 441fe3b4685SNathan Whitehorn openfirmware(&args); 442fe3b4685SNathan Whitehorn } 443fe3b4685SNathan Whitehorn 444fe3b4685SNathan Whitehorn static int 445fe3b4685SNathan Whitehorn openfirmware_core(void *args) 446fe3b4685SNathan Whitehorn { 447fe3b4685SNathan Whitehorn int result; 448fe3b4685SNathan Whitehorn register_t oldmsr; 449fe3b4685SNathan Whitehorn 45044d29d47SNathan Whitehorn if (openfirmware_entry == NULL) 45144d29d47SNathan Whitehorn return (-1); 45244d29d47SNathan Whitehorn 453fe3b4685SNathan Whitehorn /* 454fe3b4685SNathan Whitehorn * Turn off exceptions - we really don't want to end up 4554aa3cee6SNathan Whitehorn * anywhere unexpected with PCPU set to something strange 4564aa3cee6SNathan Whitehorn * or the stack pointer wrong. 457fe3b4685SNathan Whitehorn */ 458fe3b4685SNathan Whitehorn oldmsr = intr_disable(); 459fe3b4685SNathan Whitehorn 4604aa3cee6SNathan Whitehorn ofw_sprg_prepare(); 4614aa3cee6SNathan Whitehorn 462f367ffdeSAndreas Tobler /* Save trap vectors */ 463f367ffdeSAndreas Tobler ofw_save_trap_vec(save_trap_of); 464f367ffdeSAndreas Tobler 465f367ffdeSAndreas Tobler /* Restore initially saved trap vectors */ 466f367ffdeSAndreas Tobler ofw_restore_trap_vec(save_trap_init); 467f367ffdeSAndreas Tobler 46895ce4c00SJustin Hibbits #ifndef __powerpc64__ 469fe3b4685SNathan Whitehorn /* 470fe3b4685SNathan Whitehorn * Clear battable[] translations 471fe3b4685SNathan Whitehorn */ 472fe3b4685SNathan Whitehorn if (!(cpu_features & PPC_FEATURE_64)) 473fe3b4685SNathan Whitehorn __asm __volatile("mtdbatu 2, %0\n" 474fe3b4685SNathan Whitehorn "mtdbatu 3, %0" : : "r" (0)); 475fe3b4685SNathan Whitehorn isync(); 476fe3b4685SNathan Whitehorn #endif 477fe3b4685SNathan Whitehorn 478fe3b4685SNathan Whitehorn result = ofwcall(args); 479f367ffdeSAndreas Tobler 480f367ffdeSAndreas Tobler /* Restore trap vecotrs */ 481f367ffdeSAndreas Tobler ofw_restore_trap_vec(save_trap_of); 482f367ffdeSAndreas Tobler 4834aa3cee6SNathan Whitehorn ofw_sprg_restore(); 4844aa3cee6SNathan Whitehorn 485fe3b4685SNathan Whitehorn intr_restore(oldmsr); 486fe3b4685SNathan Whitehorn 487fe3b4685SNathan Whitehorn return (result); 488fe3b4685SNathan Whitehorn } 489fe3b4685SNathan Whitehorn 490fe3b4685SNathan Whitehorn #ifdef SMP 491fe3b4685SNathan Whitehorn struct ofw_rv_args { 492fe3b4685SNathan Whitehorn void *args; 493fe3b4685SNathan Whitehorn int retval; 494fe3b4685SNathan Whitehorn volatile int in_progress; 495fe3b4685SNathan Whitehorn }; 496fe3b4685SNathan Whitehorn 497fe3b4685SNathan Whitehorn static void 498fe3b4685SNathan Whitehorn ofw_rendezvous_dispatch(void *xargs) 499fe3b4685SNathan Whitehorn { 500fe3b4685SNathan Whitehorn struct ofw_rv_args *rv_args = xargs; 501fe3b4685SNathan Whitehorn 502fe3b4685SNathan Whitehorn /* NOTE: Interrupts are disabled here */ 503fe3b4685SNathan Whitehorn 504fe3b4685SNathan Whitehorn if (PCPU_GET(cpuid) == 0) { 505fe3b4685SNathan Whitehorn /* 506fe3b4685SNathan Whitehorn * Execute all OF calls on CPU 0 507fe3b4685SNathan Whitehorn */ 508fe3b4685SNathan Whitehorn rv_args->retval = openfirmware_core(rv_args->args); 509fe3b4685SNathan Whitehorn rv_args->in_progress = 0; 510fe3b4685SNathan Whitehorn } else { 511fe3b4685SNathan Whitehorn /* 512fe3b4685SNathan Whitehorn * Spin with interrupts off on other CPUs while OF has 513fe3b4685SNathan Whitehorn * control of the machine. 514fe3b4685SNathan Whitehorn */ 515fe3b4685SNathan Whitehorn while (rv_args->in_progress) 516fe3b4685SNathan Whitehorn cpu_spinwait(); 517fe3b4685SNathan Whitehorn } 518fe3b4685SNathan Whitehorn } 519fe3b4685SNathan Whitehorn #endif 520fe3b4685SNathan Whitehorn 521fe3b4685SNathan Whitehorn static int 522fe3b4685SNathan Whitehorn openfirmware(void *args) 523fe3b4685SNathan Whitehorn { 524fe3b4685SNathan Whitehorn int result; 525fe3b4685SNathan Whitehorn #ifdef SMP 526fe3b4685SNathan Whitehorn struct ofw_rv_args rv_args; 52744d29d47SNathan Whitehorn #endif 528fe3b4685SNathan Whitehorn 52944d29d47SNathan Whitehorn if (openfirmware_entry == NULL) 53044d29d47SNathan Whitehorn return (-1); 53144d29d47SNathan Whitehorn 53244d29d47SNathan Whitehorn #ifdef SMP 53391419bdaSNathan Whitehorn if (cold) { 53491419bdaSNathan Whitehorn result = openfirmware_core(args); 53591419bdaSNathan Whitehorn } else { 536fe3b4685SNathan Whitehorn rv_args.args = args; 537fe3b4685SNathan Whitehorn rv_args.in_progress = 1; 53891419bdaSNathan Whitehorn smp_rendezvous(smp_no_rendezvous_barrier, 53991419bdaSNathan Whitehorn ofw_rendezvous_dispatch, smp_no_rendezvous_barrier, 54091419bdaSNathan Whitehorn &rv_args); 541fe3b4685SNathan Whitehorn result = rv_args.retval; 54291419bdaSNathan Whitehorn } 543fe3b4685SNathan Whitehorn #else 544fe3b4685SNathan Whitehorn result = openfirmware_core(args); 545fe3b4685SNathan Whitehorn #endif 546fe3b4685SNathan Whitehorn 547fe3b4685SNathan Whitehorn return (result); 548fe3b4685SNathan Whitehorn } 549fe3b4685SNathan Whitehorn 550fe3b4685SNathan Whitehorn void 551fe3b4685SNathan Whitehorn OF_reboot() 552fe3b4685SNathan Whitehorn { 553fe3b4685SNathan Whitehorn struct { 554fe3b4685SNathan Whitehorn cell_t name; 555fe3b4685SNathan Whitehorn cell_t nargs; 556fe3b4685SNathan Whitehorn cell_t nreturns; 557fe3b4685SNathan Whitehorn cell_t arg; 558fe3b4685SNathan Whitehorn } args; 559fe3b4685SNathan Whitehorn 560fe3b4685SNathan Whitehorn args.name = (cell_t)(uintptr_t)"interpret"; 561fe3b4685SNathan Whitehorn args.nargs = 1; 562fe3b4685SNathan Whitehorn args.nreturns = 0; 563fe3b4685SNathan Whitehorn args.arg = (cell_t)(uintptr_t)"reset-all"; 564fe3b4685SNathan Whitehorn openfirmware_core(&args); /* Don't do rendezvous! */ 565fe3b4685SNathan Whitehorn 566fe3b4685SNathan Whitehorn for (;;); /* just in case */ 567fe3b4685SNathan Whitehorn } 568fe3b4685SNathan Whitehorn 569629aa519SNathan Whitehorn #endif /* AIM */ 570629aa519SNathan Whitehorn 571fe3b4685SNathan Whitehorn void 572fe3b4685SNathan Whitehorn OF_getetheraddr(device_t dev, u_char *addr) 573fe3b4685SNathan Whitehorn { 574fe3b4685SNathan Whitehorn phandle_t node; 575fe3b4685SNathan Whitehorn 576fe3b4685SNathan Whitehorn node = ofw_bus_get_node(dev); 577fe3b4685SNathan Whitehorn OF_getprop(node, "local-mac-address", addr, ETHER_ADDR_LEN); 578fe3b4685SNathan Whitehorn } 579fe3b4685SNathan Whitehorn 580fe3b4685SNathan Whitehorn /* 581fe3b4685SNathan Whitehorn * Return a bus handle and bus tag that corresponds to the register 582fe3b4685SNathan Whitehorn * numbered regno for the device referenced by the package handle 583fe3b4685SNathan Whitehorn * dev. This function is intended to be used by console drivers in 584fe3b4685SNathan Whitehorn * early boot only. It works by mapping the address of the device's 585fe3b4685SNathan Whitehorn * register in the address space of its parent and recursively walk 586fe3b4685SNathan Whitehorn * the device tree upward this way. 587fe3b4685SNathan Whitehorn */ 588fe3b4685SNathan Whitehorn int 589fe3b4685SNathan Whitehorn OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag, 59045fd1862SAndrew Turner bus_space_handle_t *handle, bus_size_t *sz) 591fe3b4685SNathan Whitehorn { 592bc7b9300SIan Lepore bus_addr_t addr; 593bc7b9300SIan Lepore bus_size_t size; 594bc7b9300SIan Lepore pcell_t pci_hi; 595bc7b9300SIan Lepore int flags, res; 596fe3b4685SNathan Whitehorn 597bc7b9300SIan Lepore res = ofw_reg_to_paddr(dev, regno, &addr, &size, &pci_hi); 598bc7b9300SIan Lepore if (res < 0) 599bc7b9300SIan Lepore return (res); 600fe3b4685SNathan Whitehorn 601bc7b9300SIan Lepore if (pci_hi == OFW_PADDR_NOT_PCI) { 60243a581e1SNathan Whitehorn *tag = &bs_be_tag; 603bc7b9300SIan Lepore flags = 0; 604bc7b9300SIan Lepore } else { 60543a581e1SNathan Whitehorn *tag = &bs_le_tag; 606bc7b9300SIan Lepore flags = (pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) ? 607bc7b9300SIan Lepore BUS_SPACE_MAP_PREFETCHABLE: 0; 608fe3b4685SNathan Whitehorn } 609fe3b4685SNathan Whitehorn 61045fd1862SAndrew Turner if (sz != NULL) 61145fd1862SAndrew Turner *sz = size; 61245fd1862SAndrew Turner 613bc7b9300SIan Lepore return (bus_space_map(*tag, addr, size, flags, handle)); 614fe3b4685SNathan Whitehorn } 615fe3b4685SNathan Whitehorn 616