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 686f489d43SJustin Hibbits static void *fdt; 696f489d43SJustin Hibbits int ofw_real_mode; 706f489d43SJustin Hibbits 71629aa519SNathan Whitehorn #ifdef AIM 72fe3b4685SNathan Whitehorn extern register_t ofmsr[5]; 7317879090SNathan Whitehorn extern void *openfirmware_entry; 74bb808254SNathan Whitehorn char save_trap_init[0x2f00]; /* EXC_LAST */ 75f367ffdeSAndreas Tobler char save_trap_of[0x2f00]; /* EXC_LAST */ 76fe3b4685SNathan Whitehorn 77d8c6808aSNathan Whitehorn int ofwcall(void *); 78fe3b4685SNathan Whitehorn static int openfirmware(void *args); 79fe3b4685SNathan Whitehorn 80f367ffdeSAndreas Tobler __inline void 81f367ffdeSAndreas Tobler ofw_save_trap_vec(char *save_trap_vec) 82f367ffdeSAndreas Tobler { 83c1cb22d7SNathan Whitehorn if (!ofw_real_mode) 84f367ffdeSAndreas Tobler return; 85f367ffdeSAndreas Tobler 86f367ffdeSAndreas Tobler bcopy((void *)EXC_RST, save_trap_vec, EXC_LAST - EXC_RST); 87f367ffdeSAndreas Tobler } 88f367ffdeSAndreas Tobler 89f367ffdeSAndreas Tobler static __inline void 90f367ffdeSAndreas Tobler ofw_restore_trap_vec(char *restore_trap_vec) 91f367ffdeSAndreas Tobler { 92c1cb22d7SNathan Whitehorn if (!ofw_real_mode) 93f367ffdeSAndreas Tobler return; 94f367ffdeSAndreas Tobler 95f367ffdeSAndreas Tobler bcopy(restore_trap_vec, (void *)EXC_RST, EXC_LAST - EXC_RST); 96f367ffdeSAndreas Tobler __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD); 97f367ffdeSAndreas Tobler } 984aa3cee6SNathan Whitehorn 994aa3cee6SNathan Whitehorn /* 1004aa3cee6SNathan Whitehorn * Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback. 1014aa3cee6SNathan Whitehorn */ 1024aa3cee6SNathan Whitehorn register_t ofw_sprg0_save; 1034aa3cee6SNathan Whitehorn 1044aa3cee6SNathan Whitehorn static __inline void 1054aa3cee6SNathan Whitehorn ofw_sprg_prepare(void) 1064aa3cee6SNathan Whitehorn { 1074aa3cee6SNathan Whitehorn if (ofw_real_mode) 1084aa3cee6SNathan Whitehorn return; 1094aa3cee6SNathan Whitehorn 1104aa3cee6SNathan Whitehorn /* 1114aa3cee6SNathan Whitehorn * Assume that interrupt are disabled at this point, or 1124aa3cee6SNathan Whitehorn * SPRG1-3 could be trashed 1134aa3cee6SNathan Whitehorn */ 1144aa3cee6SNathan Whitehorn __asm __volatile("mfsprg0 %0\n\t" 1154aa3cee6SNathan Whitehorn "mtsprg0 %1\n\t" 1164aa3cee6SNathan Whitehorn "mtsprg1 %2\n\t" 1174aa3cee6SNathan Whitehorn "mtsprg2 %3\n\t" 1184aa3cee6SNathan Whitehorn "mtsprg3 %4\n\t" 1194aa3cee6SNathan Whitehorn : "=&r"(ofw_sprg0_save) 1204aa3cee6SNathan Whitehorn : "r"(ofmsr[1]), 1214aa3cee6SNathan Whitehorn "r"(ofmsr[2]), 1224aa3cee6SNathan Whitehorn "r"(ofmsr[3]), 1234aa3cee6SNathan Whitehorn "r"(ofmsr[4])); 1244aa3cee6SNathan Whitehorn } 1254aa3cee6SNathan Whitehorn 1264aa3cee6SNathan Whitehorn static __inline void 1274aa3cee6SNathan Whitehorn ofw_sprg_restore(void) 1284aa3cee6SNathan Whitehorn { 1294aa3cee6SNathan Whitehorn if (ofw_real_mode) 1304aa3cee6SNathan Whitehorn return; 1314aa3cee6SNathan Whitehorn 1324aa3cee6SNathan Whitehorn /* 1334aa3cee6SNathan Whitehorn * Note that SPRG1-3 contents are irrelevant. They are scratch 1344aa3cee6SNathan Whitehorn * registers used in the early portion of trap handling when 1354aa3cee6SNathan Whitehorn * interrupts are disabled. 1364aa3cee6SNathan Whitehorn * 1374aa3cee6SNathan Whitehorn * PCPU data cannot be used until this routine is called ! 1384aa3cee6SNathan Whitehorn */ 1394aa3cee6SNathan Whitehorn __asm __volatile("mtsprg0 %0" :: "r"(ofw_sprg0_save)); 1404aa3cee6SNathan Whitehorn } 141c7291bdcSNathan Whitehorn #endif 142f367ffdeSAndreas Tobler 143fe3b4685SNathan Whitehorn static int 144fe3b4685SNathan Whitehorn parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output) 145fe3b4685SNathan Whitehorn { 146fe3b4685SNathan Whitehorn cell_t address_cells, size_cells; 147d8c6808aSNathan Whitehorn cell_t OFmem[4 * PHYS_AVAIL_SZ]; 148fe3b4685SNathan Whitehorn int sz, i, j; 149fe3b4685SNathan Whitehorn phandle_t phandle; 150fe3b4685SNathan Whitehorn 151fe3b4685SNathan Whitehorn sz = 0; 152fe3b4685SNathan Whitehorn 153fe3b4685SNathan Whitehorn /* 154fe3b4685SNathan Whitehorn * Get #address-cells from root node, defaulting to 1 if it cannot 155fe3b4685SNathan Whitehorn * be found. 156fe3b4685SNathan Whitehorn */ 157fe3b4685SNathan Whitehorn phandle = OF_finddevice("/"); 158509142e1SNathan Whitehorn if (OF_getencprop(phandle, "#address-cells", &address_cells, 1598bab0d80SNathan Whitehorn sizeof(address_cells)) < (ssize_t)sizeof(address_cells)) 160fe3b4685SNathan Whitehorn address_cells = 1; 161509142e1SNathan Whitehorn if (OF_getencprop(phandle, "#size-cells", &size_cells, 1628bab0d80SNathan Whitehorn sizeof(size_cells)) < (ssize_t)sizeof(size_cells)) 163fe3b4685SNathan Whitehorn size_cells = 1; 164fe3b4685SNathan Whitehorn 165fe3b4685SNathan Whitehorn /* 166fe3b4685SNathan Whitehorn * Get memory. 167fe3b4685SNathan Whitehorn */ 168509142e1SNathan Whitehorn if (node == -1 || (sz = OF_getencprop(node, prop, 169d8c6808aSNathan Whitehorn OFmem, sizeof(OFmem))) <= 0) 170fe3b4685SNathan Whitehorn panic("Physical memory map not found"); 171fe3b4685SNathan Whitehorn 172fe3b4685SNathan Whitehorn i = 0; 173fe3b4685SNathan Whitehorn j = 0; 174fe3b4685SNathan Whitehorn while (i < sz/sizeof(cell_t)) { 175fe3b4685SNathan Whitehorn #ifndef __powerpc64__ 176fe3b4685SNathan Whitehorn /* On 32-bit PPC, ignore regions starting above 4 GB */ 177fe3b4685SNathan Whitehorn if (address_cells > 1 && OFmem[i] > 0) { 178fe3b4685SNathan Whitehorn i += address_cells + size_cells; 179fe3b4685SNathan Whitehorn continue; 180fe3b4685SNathan Whitehorn } 181fe3b4685SNathan Whitehorn #endif 182fe3b4685SNathan Whitehorn 183fe3b4685SNathan Whitehorn output[j].mr_start = OFmem[i++]; 184fe3b4685SNathan Whitehorn if (address_cells == 2) { 185fe3b4685SNathan Whitehorn #ifdef __powerpc64__ 186fe3b4685SNathan Whitehorn output[j].mr_start <<= 32; 187fe3b4685SNathan Whitehorn #endif 188fe3b4685SNathan Whitehorn output[j].mr_start += OFmem[i++]; 189fe3b4685SNathan Whitehorn } 190fe3b4685SNathan Whitehorn 191fe3b4685SNathan Whitehorn output[j].mr_size = OFmem[i++]; 192fe3b4685SNathan Whitehorn if (size_cells == 2) { 193fe3b4685SNathan Whitehorn #ifdef __powerpc64__ 194fe3b4685SNathan Whitehorn output[j].mr_size <<= 32; 195fe3b4685SNathan Whitehorn #endif 196fe3b4685SNathan Whitehorn output[j].mr_size += OFmem[i++]; 197fe3b4685SNathan Whitehorn } 198fe3b4685SNathan Whitehorn 199fe3b4685SNathan Whitehorn #ifndef __powerpc64__ 200fe3b4685SNathan Whitehorn /* 201fe3b4685SNathan Whitehorn * Check for memory regions extending above 32-bit 202fe3b4685SNathan Whitehorn * memory space, and restrict them to stay there. 203fe3b4685SNathan Whitehorn */ 204fe3b4685SNathan Whitehorn if (((uint64_t)output[j].mr_start + 205fe3b4685SNathan Whitehorn (uint64_t)output[j].mr_size) > 206fe3b4685SNathan Whitehorn BUS_SPACE_MAXADDR_32BIT) { 207fe3b4685SNathan Whitehorn output[j].mr_size = BUS_SPACE_MAXADDR_32BIT - 208fe3b4685SNathan Whitehorn output[j].mr_start; 209fe3b4685SNathan Whitehorn } 210fe3b4685SNathan Whitehorn #endif 211fe3b4685SNathan Whitehorn 212fe3b4685SNathan Whitehorn j++; 213fe3b4685SNathan Whitehorn } 214fe3b4685SNathan Whitehorn sz = j*sizeof(output[0]); 215fe3b4685SNathan Whitehorn 216fe3b4685SNathan Whitehorn return (sz); 217fe3b4685SNathan Whitehorn } 218fe3b4685SNathan Whitehorn 219b9d056f3SNathan Whitehorn static int 220b9d056f3SNathan Whitehorn excise_fdt_reserved(struct mem_region *avail, int asz) 221b9d056f3SNathan Whitehorn { 222b9d056f3SNathan Whitehorn struct { 223b9d056f3SNathan Whitehorn uint64_t address; 224b9d056f3SNathan Whitehorn uint64_t size; 225b9d056f3SNathan Whitehorn } fdtmap[16]; 226b9d056f3SNathan Whitehorn ssize_t fdtmapsize; 227b9d056f3SNathan Whitehorn phandle_t chosen; 228b9d056f3SNathan Whitehorn int i, j, k; 229b9d056f3SNathan Whitehorn 230b9d056f3SNathan Whitehorn chosen = OF_finddevice("/chosen"); 231b9d056f3SNathan Whitehorn fdtmapsize = OF_getprop(chosen, "fdtmemreserv", fdtmap, sizeof(fdtmap)); 232b9d056f3SNathan Whitehorn 233b9d056f3SNathan Whitehorn for (j = 0; j < fdtmapsize/sizeof(fdtmap[0]); j++) { 234b9d056f3SNathan Whitehorn fdtmap[j].address = be64toh(fdtmap[j].address); 235b9d056f3SNathan Whitehorn fdtmap[j].size = be64toh(fdtmap[j].size); 236b9d056f3SNathan Whitehorn } 237b9d056f3SNathan Whitehorn 238b9d056f3SNathan Whitehorn for (i = 0; i < asz; i++) { 239b9d056f3SNathan Whitehorn for (j = 0; j < fdtmapsize/sizeof(fdtmap[0]); j++) { 240b9d056f3SNathan Whitehorn /* 241b9d056f3SNathan Whitehorn * Case 1: Exclusion region encloses complete 242b9d056f3SNathan Whitehorn * available entry. Drop it and move on. 243b9d056f3SNathan Whitehorn */ 244b9d056f3SNathan Whitehorn if (fdtmap[j].address <= avail[i].mr_start && 245b9d056f3SNathan Whitehorn fdtmap[j].address + fdtmap[j].size >= 246b9d056f3SNathan Whitehorn avail[i].mr_start + avail[i].mr_size) { 247b9d056f3SNathan Whitehorn for (k = i+1; k < asz; k++) 248b9d056f3SNathan Whitehorn avail[k-1] = avail[k]; 249b9d056f3SNathan Whitehorn asz--; 250b9d056f3SNathan Whitehorn i--; /* Repeat some entries */ 251b9d056f3SNathan Whitehorn continue; 252b9d056f3SNathan Whitehorn } 253b9d056f3SNathan Whitehorn 254b9d056f3SNathan Whitehorn /* 255b9d056f3SNathan Whitehorn * Case 2: Exclusion region starts in available entry. 256b9d056f3SNathan Whitehorn * Trim it to where the entry begins and append 257b9d056f3SNathan Whitehorn * a new available entry with the region after 258b9d056f3SNathan Whitehorn * the excluded region, if any. 259b9d056f3SNathan Whitehorn */ 260b9d056f3SNathan Whitehorn if (fdtmap[j].address >= avail[i].mr_start && 261b9d056f3SNathan Whitehorn fdtmap[j].address < avail[i].mr_start + 262b9d056f3SNathan Whitehorn avail[i].mr_size) { 263b9d056f3SNathan Whitehorn if (fdtmap[j].address + fdtmap[j].size < 264b9d056f3SNathan Whitehorn avail[i].mr_start + avail[i].mr_size) { 265b9d056f3SNathan Whitehorn avail[asz].mr_start = 266922a3152SNathan Whitehorn fdtmap[j].address + fdtmap[j].size; 267b9d056f3SNathan Whitehorn avail[asz].mr_size = avail[i].mr_start + 268b9d056f3SNathan Whitehorn avail[i].mr_size - 269b9d056f3SNathan Whitehorn avail[asz].mr_start; 270b9d056f3SNathan Whitehorn asz++; 271b9d056f3SNathan Whitehorn } 272b9d056f3SNathan Whitehorn 273922a3152SNathan Whitehorn avail[i].mr_size = fdtmap[j].address - 274b9d056f3SNathan Whitehorn avail[i].mr_start; 275b9d056f3SNathan Whitehorn } 276b9d056f3SNathan Whitehorn 277b9d056f3SNathan Whitehorn /* 278b9d056f3SNathan Whitehorn * Case 3: Exclusion region ends in available entry. 279b9d056f3SNathan Whitehorn * Move start point to where the exclusion zone ends. 280b9d056f3SNathan Whitehorn * The case of a contained exclusion zone has already 281b9d056f3SNathan Whitehorn * been caught in case 2. 282b9d056f3SNathan Whitehorn */ 283b9d056f3SNathan Whitehorn if (fdtmap[j].address + fdtmap[j].size >= 284b9d056f3SNathan Whitehorn avail[i].mr_start && fdtmap[j].address + 285b9d056f3SNathan Whitehorn fdtmap[j].size < avail[i].mr_start + 286b9d056f3SNathan Whitehorn avail[i].mr_size) { 287922a3152SNathan Whitehorn avail[i].mr_size += avail[i].mr_start; 288b9d056f3SNathan Whitehorn avail[i].mr_start = 289922a3152SNathan Whitehorn fdtmap[j].address + fdtmap[j].size; 290922a3152SNathan Whitehorn avail[i].mr_size -= avail[i].mr_start; 291b9d056f3SNathan Whitehorn } 292b9d056f3SNathan Whitehorn } 293b9d056f3SNathan Whitehorn } 294b9d056f3SNathan Whitehorn 295b9d056f3SNathan Whitehorn return (asz); 296b9d056f3SNathan Whitehorn } 297b9d056f3SNathan Whitehorn 298fe3b4685SNathan Whitehorn /* 299fe3b4685SNathan Whitehorn * This is called during powerpc_init, before the system is really initialized. 300fe3b4685SNathan Whitehorn * It shall provide the total and the available regions of RAM. 301b9d056f3SNathan Whitehorn * The available regions need not take the kernel into account. 302fe3b4685SNathan Whitehorn */ 303fe3b4685SNathan Whitehorn void 304c1cb22d7SNathan Whitehorn ofw_mem_regions(struct mem_region *memp, int *memsz, 305c1cb22d7SNathan Whitehorn struct mem_region *availp, int *availsz) 306fe3b4685SNathan Whitehorn { 307fe3b4685SNathan Whitehorn phandle_t phandle; 308c1cb22d7SNathan Whitehorn int asz, msz; 309c1cb22d7SNathan Whitehorn int res; 310d8c6808aSNathan Whitehorn char name[31]; 311fe3b4685SNathan Whitehorn 312fe3b4685SNathan Whitehorn asz = msz = 0; 313fe3b4685SNathan Whitehorn 314fe3b4685SNathan Whitehorn /* 315d8c6808aSNathan Whitehorn * Get memory from all the /memory nodes. 316fe3b4685SNathan Whitehorn */ 317d8c6808aSNathan Whitehorn for (phandle = OF_child(OF_peer(0)); phandle != 0; 318d8c6808aSNathan Whitehorn phandle = OF_peer(phandle)) { 319d8c6808aSNathan Whitehorn if (OF_getprop(phandle, "name", name, sizeof(name)) <= 0) 320d8c6808aSNathan Whitehorn continue; 321b9d056f3SNathan Whitehorn if (strncmp(name, "memory", sizeof(name)) != 0 && 322b9d056f3SNathan Whitehorn strncmp(name, "memory@", strlen("memory@")) != 0) 323d8c6808aSNathan Whitehorn continue; 324fe3b4685SNathan Whitehorn 325c1cb22d7SNathan Whitehorn res = parse_ofw_memory(phandle, "reg", &memp[msz]); 326d8c6808aSNathan Whitehorn msz += res/sizeof(struct mem_region); 327d8c6808aSNathan Whitehorn if (OF_getproplen(phandle, "available") >= 0) 328d8c6808aSNathan Whitehorn res = parse_ofw_memory(phandle, "available", 329c1cb22d7SNathan Whitehorn &availp[asz]); 330d8c6808aSNathan Whitehorn else 331c1cb22d7SNathan Whitehorn res = parse_ofw_memory(phandle, "reg", &availp[asz]); 332d8c6808aSNathan Whitehorn asz += res/sizeof(struct mem_region); 333d8c6808aSNathan Whitehorn } 334d8c6808aSNathan Whitehorn 335b9d056f3SNathan Whitehorn phandle = OF_finddevice("/chosen"); 336b9d056f3SNathan Whitehorn if (OF_hasprop(phandle, "fdtmemreserv")) 337b9d056f3SNathan Whitehorn asz = excise_fdt_reserved(availp, asz); 338b9d056f3SNathan Whitehorn 339d8c6808aSNathan Whitehorn *memsz = msz; 340c1cb22d7SNathan Whitehorn *availsz = asz; 341fe3b4685SNathan Whitehorn } 342fe3b4685SNathan Whitehorn 343fe3b4685SNathan Whitehorn void 344fe3b4685SNathan Whitehorn OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *)) 345fe3b4685SNathan Whitehorn { 3466f489d43SJustin Hibbits #ifdef AIM 347bb808254SNathan Whitehorn ofmsr[0] = mfmsr(); 348bb808254SNathan Whitehorn #ifdef __powerpc64__ 349bb808254SNathan Whitehorn ofmsr[0] &= ~PSL_SF; 350bb808254SNathan Whitehorn #endif 351bb808254SNathan Whitehorn __asm __volatile("mfsprg0 %0" : "=&r"(ofmsr[1])); 352bb808254SNathan Whitehorn __asm __volatile("mfsprg1 %0" : "=&r"(ofmsr[2])); 353bb808254SNathan Whitehorn __asm __volatile("mfsprg2 %0" : "=&r"(ofmsr[3])); 354bb808254SNathan Whitehorn __asm __volatile("mfsprg3 %0" : "=&r"(ofmsr[4])); 3556f489d43SJustin Hibbits openfirmware_entry = openfirm; 356bb808254SNathan Whitehorn 357fe3b4685SNathan Whitehorn if (ofmsr[0] & PSL_DR) 358fe3b4685SNathan Whitehorn ofw_real_mode = 0; 359fe3b4685SNathan Whitehorn else 360fe3b4685SNathan Whitehorn ofw_real_mode = 1; 361fe3b4685SNathan Whitehorn 3626f489d43SJustin Hibbits ofw_save_trap_vec(save_trap_init); 3636f489d43SJustin Hibbits #else 3646f489d43SJustin Hibbits ofw_real_mode = 1; 3656f489d43SJustin Hibbits #endif 3666f489d43SJustin Hibbits 367fe3b4685SNathan Whitehorn fdt = fdt_ptr; 368fe3b4685SNathan Whitehorn 369fe3b4685SNathan Whitehorn #ifdef FDT_DTB_STATIC 370fe3b4685SNathan Whitehorn /* Check for a statically included blob */ 371fe3b4685SNathan Whitehorn if (fdt == NULL) 372fe3b4685SNathan Whitehorn fdt = &fdt_static_dtb; 373fe3b4685SNathan Whitehorn #endif 374fe3b4685SNathan Whitehorn } 375fe3b4685SNathan Whitehorn 376fe3b4685SNathan Whitehorn boolean_t 377fe3b4685SNathan Whitehorn OF_bootstrap() 378fe3b4685SNathan Whitehorn { 379fe3b4685SNathan Whitehorn boolean_t status = FALSE; 380fe3b4685SNathan Whitehorn 3816f489d43SJustin Hibbits #ifdef AIM 38217879090SNathan Whitehorn if (openfirmware_entry != NULL) { 383fe3b4685SNathan Whitehorn if (ofw_real_mode) { 384fe3b4685SNathan Whitehorn status = OF_install(OFW_STD_REAL, 0); 385fe3b4685SNathan Whitehorn } else { 386fe3b4685SNathan Whitehorn #ifdef __powerpc64__ 387fe3b4685SNathan Whitehorn status = OF_install(OFW_STD_32BIT, 0); 388fe3b4685SNathan Whitehorn #else 389fe3b4685SNathan Whitehorn status = OF_install(OFW_STD_DIRECT, 0); 390fe3b4685SNathan Whitehorn #endif 391fe3b4685SNathan Whitehorn } 392fe3b4685SNathan Whitehorn 393fe3b4685SNathan Whitehorn if (status != TRUE) 394fe3b4685SNathan Whitehorn return status; 395fe3b4685SNathan Whitehorn 396fe3b4685SNathan Whitehorn OF_init(openfirmware); 3976f489d43SJustin Hibbits } else 3986f489d43SJustin Hibbits #endif 3996f489d43SJustin Hibbits if (fdt != NULL) { 400fe3b4685SNathan Whitehorn status = OF_install(OFW_FDT, 0); 401fe3b4685SNathan Whitehorn 402fe3b4685SNathan Whitehorn if (status != TRUE) 403fe3b4685SNathan Whitehorn return status; 404fe3b4685SNathan Whitehorn 405fe3b4685SNathan Whitehorn OF_init(fdt); 4066f489d43SJustin Hibbits OF_interpret("perform-fixup", 0); 407fe3b4685SNathan Whitehorn } 408fe3b4685SNathan Whitehorn 409fe3b4685SNathan Whitehorn return (status); 410fe3b4685SNathan Whitehorn } 411fe3b4685SNathan Whitehorn 4126f489d43SJustin Hibbits #ifdef AIM 4139f706727SNathan Whitehorn void 414fe3b4685SNathan Whitehorn ofw_quiesce(void) 415fe3b4685SNathan Whitehorn { 416fe3b4685SNathan Whitehorn struct { 417fe3b4685SNathan Whitehorn cell_t name; 418fe3b4685SNathan Whitehorn cell_t nargs; 419fe3b4685SNathan Whitehorn cell_t nreturns; 420fe3b4685SNathan Whitehorn } args; 421fe3b4685SNathan Whitehorn 4229f706727SNathan Whitehorn KASSERT(!pmap_bootstrapped, ("Cannot call ofw_quiesce after VM is up")); 423fe3b4685SNathan Whitehorn 424fe3b4685SNathan Whitehorn args.name = (cell_t)(uintptr_t)"quiesce"; 425fe3b4685SNathan Whitehorn args.nargs = 0; 426fe3b4685SNathan Whitehorn args.nreturns = 0; 427fe3b4685SNathan Whitehorn openfirmware(&args); 428fe3b4685SNathan Whitehorn } 429fe3b4685SNathan Whitehorn 430fe3b4685SNathan Whitehorn static int 431fe3b4685SNathan Whitehorn openfirmware_core(void *args) 432fe3b4685SNathan Whitehorn { 433fe3b4685SNathan Whitehorn int result; 434fe3b4685SNathan Whitehorn register_t oldmsr; 435fe3b4685SNathan Whitehorn 43644d29d47SNathan Whitehorn if (openfirmware_entry == NULL) 43744d29d47SNathan Whitehorn return (-1); 43844d29d47SNathan Whitehorn 439fe3b4685SNathan Whitehorn /* 440fe3b4685SNathan Whitehorn * Turn off exceptions - we really don't want to end up 4414aa3cee6SNathan Whitehorn * anywhere unexpected with PCPU set to something strange 4424aa3cee6SNathan Whitehorn * or the stack pointer wrong. 443fe3b4685SNathan Whitehorn */ 444fe3b4685SNathan Whitehorn oldmsr = intr_disable(); 445fe3b4685SNathan Whitehorn 4464aa3cee6SNathan Whitehorn ofw_sprg_prepare(); 4474aa3cee6SNathan Whitehorn 448f367ffdeSAndreas Tobler /* Save trap vectors */ 449f367ffdeSAndreas Tobler ofw_save_trap_vec(save_trap_of); 450f367ffdeSAndreas Tobler 451f367ffdeSAndreas Tobler /* Restore initially saved trap vectors */ 452f367ffdeSAndreas Tobler ofw_restore_trap_vec(save_trap_init); 453f367ffdeSAndreas Tobler 454fe3b4685SNathan Whitehorn #if defined(AIM) && !defined(__powerpc64__) 455fe3b4685SNathan Whitehorn /* 456fe3b4685SNathan Whitehorn * Clear battable[] translations 457fe3b4685SNathan Whitehorn */ 458fe3b4685SNathan Whitehorn if (!(cpu_features & PPC_FEATURE_64)) 459fe3b4685SNathan Whitehorn __asm __volatile("mtdbatu 2, %0\n" 460fe3b4685SNathan Whitehorn "mtdbatu 3, %0" : : "r" (0)); 461fe3b4685SNathan Whitehorn isync(); 462fe3b4685SNathan Whitehorn #endif 463fe3b4685SNathan Whitehorn 464fe3b4685SNathan Whitehorn result = ofwcall(args); 465f367ffdeSAndreas Tobler 466f367ffdeSAndreas Tobler /* Restore trap vecotrs */ 467f367ffdeSAndreas Tobler ofw_restore_trap_vec(save_trap_of); 468f367ffdeSAndreas Tobler 4694aa3cee6SNathan Whitehorn ofw_sprg_restore(); 4704aa3cee6SNathan Whitehorn 471fe3b4685SNathan Whitehorn intr_restore(oldmsr); 472fe3b4685SNathan Whitehorn 473fe3b4685SNathan Whitehorn return (result); 474fe3b4685SNathan Whitehorn } 475fe3b4685SNathan Whitehorn 476fe3b4685SNathan Whitehorn #ifdef SMP 477fe3b4685SNathan Whitehorn struct ofw_rv_args { 478fe3b4685SNathan Whitehorn void *args; 479fe3b4685SNathan Whitehorn int retval; 480fe3b4685SNathan Whitehorn volatile int in_progress; 481fe3b4685SNathan Whitehorn }; 482fe3b4685SNathan Whitehorn 483fe3b4685SNathan Whitehorn static void 484fe3b4685SNathan Whitehorn ofw_rendezvous_dispatch(void *xargs) 485fe3b4685SNathan Whitehorn { 486fe3b4685SNathan Whitehorn struct ofw_rv_args *rv_args = xargs; 487fe3b4685SNathan Whitehorn 488fe3b4685SNathan Whitehorn /* NOTE: Interrupts are disabled here */ 489fe3b4685SNathan Whitehorn 490fe3b4685SNathan Whitehorn if (PCPU_GET(cpuid) == 0) { 491fe3b4685SNathan Whitehorn /* 492fe3b4685SNathan Whitehorn * Execute all OF calls on CPU 0 493fe3b4685SNathan Whitehorn */ 494fe3b4685SNathan Whitehorn rv_args->retval = openfirmware_core(rv_args->args); 495fe3b4685SNathan Whitehorn rv_args->in_progress = 0; 496fe3b4685SNathan Whitehorn } else { 497fe3b4685SNathan Whitehorn /* 498fe3b4685SNathan Whitehorn * Spin with interrupts off on other CPUs while OF has 499fe3b4685SNathan Whitehorn * control of the machine. 500fe3b4685SNathan Whitehorn */ 501fe3b4685SNathan Whitehorn while (rv_args->in_progress) 502fe3b4685SNathan Whitehorn cpu_spinwait(); 503fe3b4685SNathan Whitehorn } 504fe3b4685SNathan Whitehorn } 505fe3b4685SNathan Whitehorn #endif 506fe3b4685SNathan Whitehorn 507fe3b4685SNathan Whitehorn static int 508fe3b4685SNathan Whitehorn openfirmware(void *args) 509fe3b4685SNathan Whitehorn { 510fe3b4685SNathan Whitehorn int result; 511fe3b4685SNathan Whitehorn #ifdef SMP 512fe3b4685SNathan Whitehorn struct ofw_rv_args rv_args; 51344d29d47SNathan Whitehorn #endif 514fe3b4685SNathan Whitehorn 51544d29d47SNathan Whitehorn if (openfirmware_entry == NULL) 51644d29d47SNathan Whitehorn return (-1); 51744d29d47SNathan Whitehorn 51844d29d47SNathan Whitehorn #ifdef SMP 519fe3b4685SNathan Whitehorn rv_args.args = args; 520fe3b4685SNathan Whitehorn rv_args.in_progress = 1; 521fe3b4685SNathan Whitehorn smp_rendezvous(smp_no_rendevous_barrier, ofw_rendezvous_dispatch, 522fe3b4685SNathan Whitehorn smp_no_rendevous_barrier, &rv_args); 523fe3b4685SNathan Whitehorn result = rv_args.retval; 524fe3b4685SNathan Whitehorn #else 525fe3b4685SNathan Whitehorn result = openfirmware_core(args); 526fe3b4685SNathan Whitehorn #endif 527fe3b4685SNathan Whitehorn 528fe3b4685SNathan Whitehorn return (result); 529fe3b4685SNathan Whitehorn } 530fe3b4685SNathan Whitehorn 531fe3b4685SNathan Whitehorn void 532fe3b4685SNathan Whitehorn OF_reboot() 533fe3b4685SNathan Whitehorn { 534fe3b4685SNathan Whitehorn struct { 535fe3b4685SNathan Whitehorn cell_t name; 536fe3b4685SNathan Whitehorn cell_t nargs; 537fe3b4685SNathan Whitehorn cell_t nreturns; 538fe3b4685SNathan Whitehorn cell_t arg; 539fe3b4685SNathan Whitehorn } args; 540fe3b4685SNathan Whitehorn 541fe3b4685SNathan Whitehorn args.name = (cell_t)(uintptr_t)"interpret"; 542fe3b4685SNathan Whitehorn args.nargs = 1; 543fe3b4685SNathan Whitehorn args.nreturns = 0; 544fe3b4685SNathan Whitehorn args.arg = (cell_t)(uintptr_t)"reset-all"; 545fe3b4685SNathan Whitehorn openfirmware_core(&args); /* Don't do rendezvous! */ 546fe3b4685SNathan Whitehorn 547fe3b4685SNathan Whitehorn for (;;); /* just in case */ 548fe3b4685SNathan Whitehorn } 549fe3b4685SNathan Whitehorn 550629aa519SNathan Whitehorn #endif /* AIM */ 551629aa519SNathan Whitehorn 552fe3b4685SNathan Whitehorn void 553fe3b4685SNathan Whitehorn OF_getetheraddr(device_t dev, u_char *addr) 554fe3b4685SNathan Whitehorn { 555fe3b4685SNathan Whitehorn phandle_t node; 556fe3b4685SNathan Whitehorn 557fe3b4685SNathan Whitehorn node = ofw_bus_get_node(dev); 558fe3b4685SNathan Whitehorn OF_getprop(node, "local-mac-address", addr, ETHER_ADDR_LEN); 559fe3b4685SNathan Whitehorn } 560fe3b4685SNathan Whitehorn 561fe3b4685SNathan Whitehorn /* 562fe3b4685SNathan Whitehorn * Return a bus handle and bus tag that corresponds to the register 563fe3b4685SNathan Whitehorn * numbered regno for the device referenced by the package handle 564fe3b4685SNathan Whitehorn * dev. This function is intended to be used by console drivers in 565fe3b4685SNathan Whitehorn * early boot only. It works by mapping the address of the device's 566fe3b4685SNathan Whitehorn * register in the address space of its parent and recursively walk 567fe3b4685SNathan Whitehorn * the device tree upward this way. 568fe3b4685SNathan Whitehorn */ 569fe3b4685SNathan Whitehorn int 570fe3b4685SNathan Whitehorn OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag, 571fe3b4685SNathan Whitehorn bus_space_handle_t *handle) 572fe3b4685SNathan Whitehorn { 573bc7b9300SIan Lepore bus_addr_t addr; 574bc7b9300SIan Lepore bus_size_t size; 575bc7b9300SIan Lepore pcell_t pci_hi; 576bc7b9300SIan Lepore int flags, res; 577fe3b4685SNathan Whitehorn 578bc7b9300SIan Lepore res = ofw_reg_to_paddr(dev, regno, &addr, &size, &pci_hi); 579bc7b9300SIan Lepore if (res < 0) 580bc7b9300SIan Lepore return (res); 581fe3b4685SNathan Whitehorn 582bc7b9300SIan Lepore if (pci_hi == OFW_PADDR_NOT_PCI) { 58343a581e1SNathan Whitehorn *tag = &bs_be_tag; 584bc7b9300SIan Lepore flags = 0; 585bc7b9300SIan Lepore } else { 58643a581e1SNathan Whitehorn *tag = &bs_le_tag; 587bc7b9300SIan Lepore flags = (pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) ? 588bc7b9300SIan Lepore BUS_SPACE_MAP_PREFETCHABLE: 0; 589fe3b4685SNathan Whitehorn } 590fe3b4685SNathan Whitehorn 591bc7b9300SIan Lepore return (bus_space_map(*tag, addr, size, flags, handle)); 592fe3b4685SNathan Whitehorn } 593fe3b4685SNathan Whitehorn 594