Commit a575b807 authored by Paul Mackerras's avatar Paul Mackerras

powerpc: Run on old powermacs.

Old powermacs have a number of differences from current machines:
- there is no interrupt tree in the device tree, just interrupt
  or AAPL,interrupt properties
- the chosen node in the device tree is called /chosen@0
- the OF claim method doesn't map the memory, so we have to do
  an explicit map call as well
- there is no /chosen/cpu property on SMP machines
- the NVRAM isn't structured as a set of partitions.

This adapts the merged powermac support code to cope with these
issues.
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 96c44507
...@@ -309,6 +309,37 @@ static int __devinit finish_node_interrupts(struct device_node *np, ...@@ -309,6 +309,37 @@ static int __devinit finish_node_interrupts(struct device_node *np,
unsigned int *irq, virq; unsigned int *irq, virq;
struct device_node *ic; struct device_node *ic;
if (num_interrupt_controllers == 0) {
/*
* Old machines just have a list of interrupt numbers
* and no interrupt-controller nodes.
*/
ints = (unsigned int *) get_property(np, "AAPL,interrupts",
&intlen);
/* XXX old interpret_pci_props looked in parent too */
/* XXX old interpret_macio_props looked for interrupts
before AAPL,interrupts */
if (ints == NULL)
ints = (unsigned int *) get_property(np, "interrupts",
&intlen);
if (ints == NULL)
return 0;
np->n_intrs = intlen / sizeof(unsigned int);
np->intrs = prom_alloc(np->n_intrs * sizeof(np->intrs[0]),
mem_start);
if (!np->intrs)
return -ENOMEM;
if (measure_only)
return 0;
for (i = 0; i < np->n_intrs; ++i) {
np->intrs[i].line = *ints++;
np->intrs[i].sense = 1;
}
return 0;
}
ints = (unsigned int *) get_property(np, "interrupts", &intlen); ints = (unsigned int *) get_property(np, "interrupts", &intlen);
if (ints == NULL) if (ints == NULL)
return 0; return 0;
...@@ -1024,6 +1055,8 @@ void __init unflatten_device_tree(void) ...@@ -1024,6 +1055,8 @@ void __init unflatten_device_tree(void)
/* Get pointer to OF "/chosen" node for use everywhere */ /* Get pointer to OF "/chosen" node for use everywhere */
of_chosen = of_find_node_by_path("/chosen"); of_chosen = of_find_node_by_path("/chosen");
if (of_chosen == NULL)
of_chosen = of_find_node_by_path("/chosen@0");
/* Retreive command line */ /* Retreive command line */
if (of_chosen != NULL) { if (of_chosen != NULL) {
...@@ -1123,7 +1156,8 @@ static int __init early_init_dt_scan_chosen(unsigned long node, ...@@ -1123,7 +1156,8 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname); DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
if (depth != 1 || strcmp(uname, "chosen") != 0) if (depth != 1 ||
(strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
return 0; return 0;
/* get platform type */ /* get platform type */
......
...@@ -132,6 +132,7 @@ struct prom_t { ...@@ -132,6 +132,7 @@ struct prom_t {
ihandle chosen; ihandle chosen;
int cpu; int cpu;
ihandle stdout; ihandle stdout;
ihandle mmumap;
}; };
struct mem_map_entry { struct mem_map_entry {
...@@ -274,14 +275,6 @@ static int __init call_prom_ret(const char *service, int nargs, int nret, ...@@ -274,14 +275,6 @@ static int __init call_prom_ret(const char *service, int nargs, int nret,
} }
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) static void __init prom_print(const char *msg)
{ {
const char *p, *q; const char *p, *q;
...@@ -363,6 +356,21 @@ static void __init prom_printf(const char *format, ...) ...@@ -363,6 +356,21 @@ static void __init prom_printf(const char *format, ...)
} }
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) static void __init __attribute__((noreturn)) prom_panic(const char *reason)
{ {
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
...@@ -1323,7 +1331,37 @@ static void __init prom_init_client_services(unsigned long pp) ...@@ -1323,7 +1331,37 @@ static void __init prom_init_client_services(unsigned long pp)
_prom->root = call_prom("finddevice", 1, 1, ADDR("/")); _prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
if (!PHANDLE_VALID(_prom->root)) if (!PHANDLE_VALID(_prom->root))
prom_panic("cannot find device tree root"); /* msg won't be printed :( */ 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) static void __init prom_init_stdout(void)
{ {
...@@ -1379,7 +1417,7 @@ static int __init prom_find_machine_type(void) ...@@ -1379,7 +1417,7 @@ static int __init prom_find_machine_type(void)
if (sl == 0) if (sl == 0)
break; break;
if (strstr(p, RELOC("Power Macintosh")) || if (strstr(p, RELOC("Power Macintosh")) ||
strstr(p, RELOC("MacRISC4"))) strstr(p, RELOC("MacRISC")))
return PLATFORM_POWERMAC; return PLATFORM_POWERMAC;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
if (strstr(p, RELOC("Momentum,Maple"))) if (strstr(p, RELOC("Momentum,Maple")))
...@@ -1618,22 +1656,17 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, ...@@ -1618,22 +1656,17 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
namep[l] = '\0'; namep[l] = '\0';
/* Fixup an Apple bug where they have bogus \0 chars in the /* 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++) for (lp = 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++)
if (*p == '/') if (*p == '/')
lp = p + 1; lp = namep;
if (lp != NULL) else if (*p != 0)
memmove(namep, lp, strlen(lp) + 1); *lp++ = *p;
*mem_start = _ALIGN(((unsigned long) namep) + }
strlen(namep) + 1, 4); *lp = 0;
*mem_start = _ALIGN((unsigned long)lp + 1, 4);
} }
/* get it again for debugging */ /* get it again for debugging */
...@@ -1858,8 +1891,9 @@ static void __init prom_find_boot_cpu(void) ...@@ -1858,8 +1891,9 @@ static void __init prom_find_boot_cpu(void)
ihandle prom_cpu; ihandle prom_cpu;
phandle cpu_pkg; phandle cpu_pkg;
_prom->cpu = 0;
if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(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); cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
...@@ -1933,6 +1967,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, ...@@ -1933,6 +1967,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*/ */
prom_init_stdout(); prom_init_stdout();
/*
* See if this OF is old enough that we need to do explicit maps
*/
prom_find_mmu();
/* /*
* Check for an initrd * Check for an initrd
*/ */
......
...@@ -225,7 +225,7 @@ int find_via_pmu(void) ...@@ -225,7 +225,7 @@ int find_via_pmu(void)
return 0; return 0;
printk("WARNING ! Your machine is PMU-based but your kernel\n"); printk("WARNING ! Your machine is PMU-based but your kernel\n");
printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); printk(" wasn't compiled with CONFIG_ADB_PMU option !\n");
return; return 0;
} }
#endif #endif
...@@ -293,7 +293,7 @@ static void __init l2cr_init(void) ...@@ -293,7 +293,7 @@ static void __init l2cr_init(void)
void __init pmac_setup_arch(void) void __init pmac_setup_arch(void)
{ {
struct device_node *cpu; struct device_node *cpu, *ic;
int *fp; int *fp;
unsigned long pvr; unsigned long pvr;
...@@ -319,6 +319,12 @@ void __init pmac_setup_arch(void) ...@@ -319,6 +319,12 @@ void __init pmac_setup_arch(void)
of_node_put(cpu); of_node_put(cpu);
} }
/* See if newworld or oldworld */
ic = of_find_node_by_name(NULL, "interrupt-controller");
pmac_newworld = (ic != NULL);
if (ic)
of_node_put(ic);
/* Lookup PCI hosts */ /* Lookup PCI hosts */
pmac_pci_init(); pmac_pci_init();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment