aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-23 03:23:21 -0400
committerPaul Mackerras <paulus@samba.org>2005-10-23 03:23:21 -0400
commita575b807172ca7d8850e6e979c8e83d4258e8c43 (patch)
tree83c3a6be6f16e4e1d325ecb9b43d26bb4d3d1ab7
parent96c44507601d64f29b8ccc867637292e326c7019 (diff)
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: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/kernel/prom.c36
-rw-r--r--arch/powerpc/kernel/prom_init.c87
-rw-r--r--arch/powerpc/platforms/powermac/setup.c10
3 files changed, 106 insertions, 27 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index c8d288457b4c..69f69c38fd27 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -309,6 +309,37 @@ static int __devinit finish_node_interrupts(struct device_node *np,
309 unsigned int *irq, virq; 309 unsigned int *irq, virq;
310 struct device_node *ic; 310 struct device_node *ic;
311 311
312 if (num_interrupt_controllers == 0) {
313 /*
314 * Old machines just have a list of interrupt numbers
315 * and no interrupt-controller nodes.
316 */
317 ints = (unsigned int *) get_property(np, "AAPL,interrupts",
318 &intlen);
319 /* XXX old interpret_pci_props looked in parent too */
320 /* XXX old interpret_macio_props looked for interrupts
321 before AAPL,interrupts */
322 if (ints == NULL)
323 ints = (unsigned int *) get_property(np, "interrupts",
324 &intlen);
325 if (ints == NULL)
326 return 0;
327
328 np->n_intrs = intlen / sizeof(unsigned int);
329 np->intrs = prom_alloc(np->n_intrs * sizeof(np->intrs[0]),
330 mem_start);
331 if (!np->intrs)
332 return -ENOMEM;
333 if (measure_only)
334 return 0;
335
336 for (i = 0; i < np->n_intrs; ++i) {
337 np->intrs[i].line = *ints++;
338 np->intrs[i].sense = 1;
339 }
340 return 0;
341 }
342
312 ints = (unsigned int *) get_property(np, "interrupts", &intlen); 343 ints = (unsigned int *) get_property(np, "interrupts", &intlen);
313 if (ints == NULL) 344 if (ints == NULL)
314 return 0; 345 return 0;
@@ -1024,6 +1055,8 @@ void __init unflatten_device_tree(void)
1024 1055
1025 /* Get pointer to OF "/chosen" node for use everywhere */ 1056 /* Get pointer to OF "/chosen" node for use everywhere */
1026 of_chosen = of_find_node_by_path("/chosen"); 1057 of_chosen = of_find_node_by_path("/chosen");
1058 if (of_chosen == NULL)
1059 of_chosen = of_find_node_by_path("/chosen@0");
1027 1060
1028 /* Retreive command line */ 1061 /* Retreive command line */
1029 if (of_chosen != NULL) { 1062 if (of_chosen != NULL) {
@@ -1123,7 +1156,8 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
1123 1156
1124 DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname); 1157 DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
1125 1158
1126 if (depth != 1 || strcmp(uname, "chosen") != 0) 1159 if (depth != 1 ||
1160 (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
1127 return 0; 1161 return 0;
1128 1162
1129 /* get platform type */ 1163 /* get platform type */
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 095659d51b4b..18d266d8935d 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -132,6 +132,7 @@ struct prom_t {
132 ihandle chosen; 132 ihandle chosen;
133 int cpu; 133 int cpu;
134 ihandle stdout; 134 ihandle stdout;
135 ihandle mmumap;
135}; 136};
136 137
137struct mem_map_entry { 138struct mem_map_entry {
@@ -274,14 +275,6 @@ static int __init call_prom_ret(const char *service, int nargs, int nret,
274} 275}
275 276
276 277
277static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
278 unsigned long align)
279{
280 return (unsigned int)call_prom("claim", 3, 1,
281 (prom_arg_t)virt, (prom_arg_t)size,
282 (prom_arg_t)align);
283}
284
285static void __init prom_print(const char *msg) 278static void __init prom_print(const char *msg)
286{ 279{
287 const char *p, *q; 280 const char *p, *q;
@@ -363,6 +356,21 @@ static void __init prom_printf(const char *format, ...)
363} 356}
364 357
365 358
359static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
360 unsigned long align)
361{
362 int ret;
363 struct prom_t *_prom = &RELOC(prom);
364
365 ret = call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
366 (prom_arg_t)align);
367 if (ret != -1 && _prom->mmumap != 0)
368 /* old pmacs need us to map as well */
369 call_prom("call-method", 6, 1,
370 ADDR("map"), _prom->mmumap, 0, size, virt, virt);
371 return ret;
372}
373
366static void __init __attribute__((noreturn)) prom_panic(const char *reason) 374static void __init __attribute__((noreturn)) prom_panic(const char *reason)
367{ 375{
368#ifdef CONFIG_PPC64 376#ifdef CONFIG_PPC64
@@ -1323,7 +1331,37 @@ static void __init prom_init_client_services(unsigned long pp)
1323 _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); 1331 _prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
1324 if (!PHANDLE_VALID(_prom->root)) 1332 if (!PHANDLE_VALID(_prom->root))
1325 prom_panic("cannot find device tree root"); /* msg won't be printed :( */ 1333 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
1334
1335 _prom->mmumap = 0;
1336}
1337
1338#ifdef CONFIG_PPC32
1339/*
1340 * For really old powermacs, we need to map things we claim.
1341 * For that, we need the ihandle of the mmu.
1342 */
1343static void __init prom_find_mmu(void)
1344{
1345 struct prom_t *_prom = &RELOC(prom);
1346 phandle oprom;
1347 char version[64];
1348
1349 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
1350 if (!PHANDLE_VALID(oprom))
1351 return;
1352 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
1353 return;
1354 version[sizeof(version) - 1] = 0;
1355 prom_printf("OF version is '%s'\n", version);
1356 /* XXX might need to add other versions here */
1357 if (strcmp(version, "Open Firmware, 1.0.5") != 0)
1358 return;
1359 prom_getprop(_prom->chosen, "mmu", &_prom->mmumap,
1360 sizeof(_prom->mmumap));
1326} 1361}
1362#else
1363#define prom_find_mmu()
1364#endif
1327 1365
1328static void __init prom_init_stdout(void) 1366static void __init prom_init_stdout(void)
1329{ 1367{
@@ -1379,7 +1417,7 @@ static int __init prom_find_machine_type(void)
1379 if (sl == 0) 1417 if (sl == 0)
1380 break; 1418 break;
1381 if (strstr(p, RELOC("Power Macintosh")) || 1419 if (strstr(p, RELOC("Power Macintosh")) ||
1382 strstr(p, RELOC("MacRISC4"))) 1420 strstr(p, RELOC("MacRISC")))
1383 return PLATFORM_POWERMAC; 1421 return PLATFORM_POWERMAC;
1384#ifdef CONFIG_PPC64 1422#ifdef CONFIG_PPC64
1385 if (strstr(p, RELOC("Momentum,Maple"))) 1423 if (strstr(p, RELOC("Momentum,Maple")))
@@ -1618,22 +1656,17 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1618 namep[l] = '\0'; 1656 namep[l] = '\0';
1619 1657
1620 /* Fixup an Apple bug where they have bogus \0 chars in the 1658 /* Fixup an Apple bug where they have bogus \0 chars in the
1621 * middle of the path in some properties 1659 * middle of the path in some properties, and extract
1660 * the unit name (everything after the last '/').
1622 */ 1661 */
1623 for (p = namep, ep = namep + l; p < ep; p++) 1662 for (lp = p = namep, ep = namep + l; p < ep; p++) {
1624 if (*p == '\0') {
1625 memmove(p, p+1, ep - p);
1626 ep--; l--; p--;
1627 }
1628
1629 /* now try to extract the unit name in that mess */
1630 for (p = namep, lp = NULL; *p; p++)
1631 if (*p == '/') 1663 if (*p == '/')
1632 lp = p + 1; 1664 lp = namep;
1633 if (lp != NULL) 1665 else if (*p != 0)
1634 memmove(namep, lp, strlen(lp) + 1); 1666 *lp++ = *p;
1635 *mem_start = _ALIGN(((unsigned long) namep) + 1667 }
1636 strlen(namep) + 1, 4); 1668 *lp = 0;
1669 *mem_start = _ALIGN((unsigned long)lp + 1, 4);
1637 } 1670 }
1638 1671
1639 /* get it again for debugging */ 1672 /* get it again for debugging */
@@ -1858,8 +1891,9 @@ static void __init prom_find_boot_cpu(void)
1858 ihandle prom_cpu; 1891 ihandle prom_cpu;
1859 phandle cpu_pkg; 1892 phandle cpu_pkg;
1860 1893
1894 _prom->cpu = 0;
1861 if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0) 1895 if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0)
1862 prom_panic("cannot find boot cpu"); 1896 return;
1863 1897
1864 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu); 1898 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
1865 1899
@@ -1934,6 +1968,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
1934 prom_init_stdout(); 1968 prom_init_stdout();
1935 1969
1936 /* 1970 /*
1971 * See if this OF is old enough that we need to do explicit maps
1972 */
1973 prom_find_mmu();
1974
1975 /*
1937 * Check for an initrd 1976 * Check for an initrd
1938 */ 1977 */
1939 prom_check_initrd(r3, r4); 1978 prom_check_initrd(r3, r4);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 50f5dd787900..908e4921bac4 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -225,7 +225,7 @@ int find_via_pmu(void)
225 return 0; 225 return 0;
226 printk("WARNING ! Your machine is PMU-based but your kernel\n"); 226 printk("WARNING ! Your machine is PMU-based but your kernel\n");
227 printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); 227 printk(" wasn't compiled with CONFIG_ADB_PMU option !\n");
228 return; 228 return 0;
229} 229}
230#endif 230#endif
231 231
@@ -293,7 +293,7 @@ static void __init l2cr_init(void)
293 293
294void __init pmac_setup_arch(void) 294void __init pmac_setup_arch(void)
295{ 295{
296 struct device_node *cpu; 296 struct device_node *cpu, *ic;
297 int *fp; 297 int *fp;
298 unsigned long pvr; 298 unsigned long pvr;
299 299
@@ -319,6 +319,12 @@ void __init pmac_setup_arch(void)
319 of_node_put(cpu); 319 of_node_put(cpu);
320 } 320 }
321 321
322 /* See if newworld or oldworld */
323 ic = of_find_node_by_name(NULL, "interrupt-controller");
324 pmac_newworld = (ic != NULL);
325 if (ic)
326 of_node_put(ic);
327
322 /* Lookup PCI hosts */ 328 /* Lookup PCI hosts */
323 pmac_pci_init(); 329 pmac_pci_init();
324 330