#include <asm/pgtable.h>
#include <asm/pci.h>
#include <asm/iommu.h>
-#include <asm/bootinfo.h>
#include <asm/btext.h>
#include <asm/sections.h>
#include <asm/machdep.h>
ihandle chosen;
int cpu;
ihandle stdout;
+ ihandle mmumap;
};
struct mem_map_entry {
extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
#ifdef CONFIG_PPC64
-extern void enter_prom(struct prom_args *args, unsigned long entry);
+extern int enter_prom(struct prom_args *args, unsigned long entry);
#else
-static inline void enter_prom(struct prom_args *args, unsigned long entry)
+static inline int enter_prom(struct prom_args *args, unsigned long entry)
{
- ((void (*)(struct prom_args *))entry)(args);
+ return ((int (*)(struct prom_args *))entry)(args);
}
#endif
for (i = 0; i < nret; i++)
args.args[nargs+i] = 0;
- enter_prom(&args, RELOC(prom_entry));
+ if (enter_prom(&args, RELOC(prom_entry)) < 0)
+ return PROM_ERROR;
return (nret > 0) ? args.args[nargs] : 0;
}
for (i = 0; i < nret; i++)
rets[nargs+i] = 0;
- enter_prom(&args, RELOC(prom_entry));
+ if (enter_prom(&args, RELOC(prom_entry)) < 0)
+ return PROM_ERROR;
if (rets != NULL)
for (i = 1; i < nret; ++i)
}
-static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
- unsigned long align)
-{
- return (unsigned int)call_prom("claim", 3, 1,
- (prom_arg_t)virt, (prom_arg_t)size,
- (prom_arg_t)align);
-}
-
static void __init prom_print(const char *msg)
{
const char *p, *q;
}
+static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
+ unsigned long align)
+{
+ int ret;
+ struct prom_t *_prom = &RELOC(prom);
+
+ ret = call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
+ (prom_arg_t)align);
+ if (ret != -1 && _prom->mmumap != 0)
+ /* old pmacs need us to map as well */
+ call_prom("call-method", 6, 1,
+ ADDR("map"), _prom->mmumap, 0, size, virt, virt);
+ return ret;
+}
+
static void __init __attribute__((noreturn)) prom_panic(const char *reason)
{
#ifdef CONFIG_PPC64
*/
static unsigned long __init alloc_up(unsigned long size, unsigned long align)
{
- unsigned long base = _ALIGN_UP(RELOC(alloc_bottom), align);
+ unsigned long base = RELOC(alloc_bottom);
unsigned long addr = 0;
+ if (align)
+ base = _ALIGN_UP(base, align);
prom_debug("alloc_up(%x, %x)\n", size, align);
if (RELOC(ram_top) == 0)
prom_panic("alloc_up() called with mem not initialized\n");
base = _ALIGN_UP(base + 0x100000, align)) {
prom_debug(" trying: 0x%x\n\r", base);
addr = (unsigned long)prom_claim(base, size, 0);
- if (addr != PROM_ERROR)
+ if (addr != PROM_ERROR && addr != 0)
break;
addr = 0;
if (align == 0)
base = _ALIGN_DOWN(base - 0x100000, align)) {
prom_debug(" trying: 0x%x\n\r", base);
addr = (unsigned long)prom_claim(base, size, 0);
- if (addr != PROM_ERROR)
+ if (addr != PROM_ERROR && addr != 0)
break;
addr = 0;
}
}
r = *p++;
#ifdef CONFIG_PPC64
- if (s) {
+ if (s > 1) {
r <<= 32;
r |= *(p++);
}
type[0] = 0;
prom_getprop(node, "device_type", type, sizeof(type));
+ if (type[0] == 0) {
+ /*
+ * CHRP Longtrail machines have no device_type
+ * on the memory node, so check the name instead...
+ */
+ prom_getprop(node, "name", type, sizeof(type));
+ }
if (strcmp(type, RELOC("memory")))
continue;
-
+
plen = prom_getprop(node, "reg", RELOC(regbuf), sizeof(regbuf));
if (plen > sizeof(regbuf)) {
prom_printf("memory node too large for buffer !\n");
*
* -- Cort
*/
+extern void __secondary_hold(void);
+extern unsigned long __secondary_hold_spinloop;
+extern unsigned long __secondary_hold_acknowledge;
+
+/*
+ * We want to reference the copy of __secondary_hold_* in the
+ * 0 - 0x100 address range
+ */
+#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
+
static void __init prom_hold_cpus(void)
{
-#ifdef CONFIG_PPC64
unsigned long i;
unsigned int reg;
phandle node;
unsigned int interrupt_server[MAX_CPU_THREADS];
unsigned int cpu_threads, hw_cpu_num;
int propsize;
- extern void __secondary_hold(void);
- extern unsigned long __secondary_hold_spinloop;
- extern unsigned long __secondary_hold_acknowledge;
+ struct prom_t *_prom = &RELOC(prom);
unsigned long *spinloop
- = (void *) __pa(&__secondary_hold_spinloop);
+ = (void *) LOW_ADDR(__secondary_hold_spinloop);
unsigned long *acknowledge
- = (void *) __pa(&__secondary_hold_acknowledge);
+ = (void *) LOW_ADDR(__secondary_hold_acknowledge);
#ifdef CONFIG_PPC64
+ /* __secondary_hold is actually a descriptor, not the text address */
unsigned long secondary_hold
= __pa(*PTRRELOC((unsigned long *)__secondary_hold));
#else
- unsigned long secondary_hold = __pa(&__secondary_hold);
+ unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
#endif
- struct prom_t *_prom = &RELOC(prom);
prom_debug("prom_hold_cpus: start...\n");
prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop);
*spinloop = 0;
#ifdef CONFIG_HMT
- for (i = 0; i < NR_CPUS; i++) {
+ for (i = 0; i < NR_CPUS; i++)
RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;
- }
#endif
/* look for cpus */
for (node = 0; prom_next_node(&node); ) {
call_prom("start-cpu", 3, 0, node,
secondary_hold, reg);
- for ( i = 0 ; (i < 100000000) &&
- (*acknowledge == ((unsigned long)-1)); i++ )
+ for (i = 0; (i < 100000000) &&
+ (*acknowledge == ((unsigned long)-1)); i++ )
mb();
- if (*acknowledge == reg) {
+ if (*acknowledge == reg)
prom_printf("done\n");
- /* We have to get every CPU out of OF,
- * even if we never start it. */
- if (cpuid >= NR_CPUS)
- goto next;
- } else {
+ else
prom_printf("failed: %x\n", *acknowledge);
- }
}
#ifdef CONFIG_SMP
else
prom_printf("%x : boot cpu %x\n", cpuid, reg);
-#endif
-next:
-#ifdef CONFIG_SMP
- /* Init paca for secondary threads. They start later. */
- for (i=1; i < cpu_threads; i++) {
- cpuid++;
- if (cpuid >= NR_CPUS)
- continue;
- }
#endif /* CONFIG_SMP */
- cpuid++;
+
+ /* Reserve cpu #s for secondary threads. They start later. */
+ cpuid += cpu_threads;
}
#ifdef CONFIG_HMT
/* Only enable HMT on processors that provide support. */
") exceeded: ignoring extras\n");
prom_debug("prom_hold_cpus: end...\n");
-#endif
}
_prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
if (!PHANDLE_VALID(_prom->root))
prom_panic("cannot find device tree root"); /* msg won't be printed :( */
+
+ _prom->mmumap = 0;
+}
+
+#ifdef CONFIG_PPC32
+/*
+ * For really old powermacs, we need to map things we claim.
+ * For that, we need the ihandle of the mmu.
+ */
+static void __init prom_find_mmu(void)
+{
+ struct prom_t *_prom = &RELOC(prom);
+ phandle oprom;
+ char version[64];
+
+ oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
+ if (!PHANDLE_VALID(oprom))
+ return;
+ if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
+ return;
+ version[sizeof(version) - 1] = 0;
+ prom_printf("OF version is '%s'\n", version);
+ /* XXX might need to add other versions here */
+ if (strcmp(version, "Open Firmware, 1.0.5") != 0)
+ return;
+ prom_getprop(_prom->chosen, "mmu", &_prom->mmumap,
+ sizeof(_prom->mmumap));
}
+#else
+#define prom_find_mmu()
+#endif
static void __init prom_init_stdout(void)
{
if (sl == 0)
break;
if (strstr(p, RELOC("Power Macintosh")) ||
- strstr(p, RELOC("MacRISC4")))
+ strstr(p, RELOC("MacRISC")))
return PLATFORM_POWERMAC;
#ifdef CONFIG_PPC64
if (strstr(p, RELOC("Momentum,Maple")))
#endif
}
-static int __init setup_disp(phandle dp)
-{
-#if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32)
- int width = 640, height = 480, depth = 8, pitch;
- unsigned address;
- u32 addrs[8][5];
- int i, naddrs;
- char name[32];
- char *getprop = "getprop";
-
- prom_printf("Initializing screen: ");
-
- memset(name, 0, sizeof(name));
- call_prom(getprop, 4, 1, dp, "name", name, sizeof(name));
- name[sizeof(name)-1] = 0;
- prom_print(name);
- prom_print("\n");
- call_prom(getprop, 4, 1, dp, "width", &width, sizeof(width));
- call_prom(getprop, 4, 1, dp, "height", &height, sizeof(height));
- call_prom(getprop, 4, 1, dp, "depth", &depth, sizeof(depth));
- pitch = width * ((depth + 7) / 8);
- call_prom(getprop, 4, 1, dp, "linebytes",
- &pitch, sizeof(pitch));
- if (pitch == 1)
- pitch = 0x1000; /* for strange IBM display */
- address = 0;
- call_prom(getprop, 4, 1, dp, "address", &address, sizeof(address));
- if (address == 0) {
- /* look for an assigned address with a size of >= 1MB */
- naddrs = call_prom(getprop, 4, 1, dp, "assigned-addresses",
- addrs, sizeof(addrs));
- naddrs /= 20;
- for (i = 0; i < naddrs; ++i) {
- if (addrs[i][4] >= (1 << 20)) {
- address = addrs[i][2];
- /* use the BE aperture if possible */
- if (addrs[i][4] >= (16 << 20))
- address += (8 << 20);
- break;
- }
- }
- if (address == 0) {
- prom_print("Failed to get address\n");
- return 0;
- }
- }
- /* kludge for valkyrie */
- if (strcmp(name, "valkyrie") == 0)
- address += 0x1000;
-
- prom_printf("\n\n\n\naddress = %x\n", address);
- btext_setup_display(width, height, depth, pitch, address);
-#endif /* CONFIG_BOOTX_TEXT && CONFIG_PPC32 */
- return 1;
-}
-
static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
{
return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
phandle node;
ihandle ih;
int i;
- int got_display = 0;
static unsigned char default_colors[] = {
0x00, 0x00, 0x00,
clut[2]) != 0)
break;
#endif /* CONFIG_LOGO_LINUX_CLUT224 */
- if (!got_display)
- got_display = setup_disp(node);
}
}
unsigned long soff;
unsigned char *valp;
static char pname[MAX_PROPERTY_NAME];
- int l;
+ int l, room;
dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
/* get the node's full name */
namep = (char *)*mem_start;
- l = call_prom("package-to-path", 3, 1, node,
- namep, *mem_end - *mem_start);
+ room = *mem_end - *mem_start;
+ if (room > 255)
+ room = 255;
+ l = call_prom("package-to-path", 3, 1, node, namep, room);
if (l >= 0) {
/* Didn't fit? Get more room. */
- if ((l+1) > (*mem_end - *mem_start)) {
- namep = make_room(mem_start, mem_end, l+1, 1);
+ if (l >= room) {
+ if (l >= *mem_end - *mem_start)
+ namep = make_room(mem_start, mem_end, l+1, 1);
call_prom("package-to-path", 3, 1, node, namep, l);
}
namep[l] = '\0';
/* Fixup an Apple bug where they have bogus \0 chars in the
- * middle of the path in some properties
+ * middle of the path in some properties, and extract
+ * the unit name (everything after the last '/').
*/
- for (p = namep, ep = namep + l; p < ep; p++)
- if (*p == '\0') {
- memmove(p, p+1, ep - p);
- ep--; l--; p--;
- }
-
- /* now try to extract the unit name in that mess */
- for (p = namep, lp = NULL; *p; p++)
+ for (lp = p = namep, ep = namep + l; p < ep; p++) {
if (*p == '/')
- lp = p + 1;
- if (lp != NULL)
- memmove(namep, lp, strlen(lp) + 1);
- *mem_start = _ALIGN(((unsigned long) namep) +
- strlen(namep) + 1, 4);
+ lp = namep;
+ else if (*p != 0)
+ *lp++ = *p;
+ }
+ *lp = 0;
+ *mem_start = _ALIGN((unsigned long)lp + 1, 4);
}
/* get it again for debugging */
ihandle prom_cpu;
phandle cpu_pkg;
+ _prom->cpu = 0;
if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0)
- prom_panic("cannot find boot cpu");
+ return;
cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
unsigned long r6, unsigned long r7)
{
struct prom_t *_prom;
- extern char _stext[];
unsigned long hdr;
u32 getprop_rval;
unsigned long offset = reloc_offset();
*/
prom_init_stdout();
+ /*
+ * See if this OF is old enough that we need to do explicit maps
+ */
+ prom_find_mmu();
+
/*
* Check for an initrd
*/
prom_send_capabilities();
#endif
-#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_BPA)
/*
- * On pSeries and BPA, copy the CPU hold code
+ * Copy the CPU hold code
*/
- if (RELOC(of_platform) & (PLATFORM_PSERIES | PLATFORM_BPA))
+ if (RELOC(of_platform) != PLATFORM_POWERMAC)
copy_and_flush(0, KERNELBASE + offset, 0x100, 0);
-#endif
/*
* Do early parsing of command line
reloc_got2(-offset);
#endif
- __start(hdr, 0, 0);
+ __start(hdr, KERNELBASE + offset, 0);
return 0;
}