diff options
author | Paul Mackerras <paulus@samba.org> | 2005-10-23 03:23:21 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-10-23 03:23:21 -0400 |
commit | a575b807172ca7d8850e6e979c8e83d4258e8c43 (patch) | |
tree | 83c3a6be6f16e4e1d325ecb9b43d26bb4d3d1ab7 /arch | |
parent | 96c44507601d64f29b8ccc867637292e326c7019 (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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/prom.c | 36 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 87 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/setup.c | 10 |
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 | ||
137 | struct mem_map_entry { | 138 | struct 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 | ||
277 | static 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 | |||
285 | static void __init prom_print(const char *msg) | 278 | static 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 | ||
359 | static 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 | |||
366 | static void __init __attribute__((noreturn)) prom_panic(const char *reason) | 374 | static 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 | */ | ||
1343 | static 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 | ||
1328 | static void __init prom_init_stdout(void) | 1366 | static 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 | ||
294 | void __init pmac_setup_arch(void) | 294 | void __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 | ||