diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/prom.c | 9 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 170 | ||||
-rw-r--r-- | arch/powerpc/platforms/chrp/setup.c | 4 | ||||
-rw-r--r-- | arch/ppc/boot/include/of1275.h | 3 | ||||
-rw-r--r-- | arch/ppc/boot/of1275/Makefile | 2 | ||||
-rw-r--r-- | arch/ppc/boot/of1275/call_prom.c | 74 | ||||
-rw-r--r-- | arch/ppc/boot/of1275/claim.c | 97 | ||||
-rw-r--r-- | arch/ppc/boot/of1275/finddevice.c | 19 |
8 files changed, 295 insertions, 83 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index f645adb57534..5af39f866735 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -1264,7 +1264,14 @@ static int __init early_init_dt_scan_memory(unsigned long node, | |||
1264 | unsigned long l; | 1264 | unsigned long l; |
1265 | 1265 | ||
1266 | /* We are scanning "memory" nodes only */ | 1266 | /* We are scanning "memory" nodes only */ |
1267 | if (type == NULL || strcmp(type, "memory") != 0) | 1267 | if (type == NULL) { |
1268 | /* | ||
1269 | * The longtrail doesn't have a device_type on the | ||
1270 | * /memory node, so look for the node called /memory@0. | ||
1271 | */ | ||
1272 | if (depth != 1 || strcmp(uname, "memory@0") != 0) | ||
1273 | return 0; | ||
1274 | } else if (strcmp(type, "memory") != 0) | ||
1268 | return 0; | 1275 | return 0; |
1269 | 1276 | ||
1270 | reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); | 1277 | reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 58f0917bd6b6..09db1bb9ec91 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -94,11 +94,17 @@ extern const struct linux_logo logo_linux_clut224; | |||
94 | #ifdef CONFIG_PPC64 | 94 | #ifdef CONFIG_PPC64 |
95 | #define RELOC(x) (*PTRRELOC(&(x))) | 95 | #define RELOC(x) (*PTRRELOC(&(x))) |
96 | #define ADDR(x) (u32) add_reloc_offset((unsigned long)(x)) | 96 | #define ADDR(x) (u32) add_reloc_offset((unsigned long)(x)) |
97 | #define OF_WORKAROUNDS 0 | ||
97 | #else | 98 | #else |
98 | #define RELOC(x) (x) | 99 | #define RELOC(x) (x) |
99 | #define ADDR(x) (u32) (x) | 100 | #define ADDR(x) (u32) (x) |
101 | #define OF_WORKAROUNDS of_workarounds | ||
102 | int of_workarounds; | ||
100 | #endif | 103 | #endif |
101 | 104 | ||
105 | #define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */ | ||
106 | #define OF_WA_LONGTRAIL 2 /* work around longtrail bugs */ | ||
107 | |||
102 | #define PROM_BUG() do { \ | 108 | #define PROM_BUG() do { \ |
103 | prom_printf("kernel BUG at %s line 0x%x!\n", \ | 109 | prom_printf("kernel BUG at %s line 0x%x!\n", \ |
104 | RELOC(__FILE__), __LINE__); \ | 110 | RELOC(__FILE__), __LINE__); \ |
@@ -128,10 +134,11 @@ struct prom_args { | |||
128 | 134 | ||
129 | struct prom_t { | 135 | struct prom_t { |
130 | ihandle root; | 136 | ihandle root; |
131 | ihandle chosen; | 137 | phandle chosen; |
132 | int cpu; | 138 | int cpu; |
133 | ihandle stdout; | 139 | ihandle stdout; |
134 | ihandle mmumap; | 140 | ihandle mmumap; |
141 | ihandle memory; | ||
135 | }; | 142 | }; |
136 | 143 | ||
137 | struct mem_map_entry { | 144 | struct mem_map_entry { |
@@ -360,16 +367,36 @@ static void __init prom_printf(const char *format, ...) | |||
360 | static unsigned int __init prom_claim(unsigned long virt, unsigned long size, | 367 | static unsigned int __init prom_claim(unsigned long virt, unsigned long size, |
361 | unsigned long align) | 368 | unsigned long align) |
362 | { | 369 | { |
363 | int ret; | ||
364 | struct prom_t *_prom = &RELOC(prom); | 370 | struct prom_t *_prom = &RELOC(prom); |
365 | 371 | ||
366 | ret = call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size, | 372 | if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) { |
367 | (prom_arg_t)align); | 373 | /* |
368 | if (ret != -1 && _prom->mmumap != 0) | 374 | * Old OF requires we claim physical and virtual separately |
369 | /* old pmacs need us to map as well */ | 375 | * and then map explicitly (assuming virtual mode) |
376 | */ | ||
377 | int ret; | ||
378 | prom_arg_t result; | ||
379 | |||
380 | ret = call_prom_ret("call-method", 5, 2, &result, | ||
381 | ADDR("claim"), _prom->memory, | ||
382 | align, size, virt); | ||
383 | if (ret != 0 || result == -1) | ||
384 | return -1; | ||
385 | ret = call_prom_ret("call-method", 5, 2, &result, | ||
386 | ADDR("claim"), _prom->mmumap, | ||
387 | align, size, virt); | ||
388 | if (ret != 0) { | ||
389 | call_prom("call-method", 4, 1, ADDR("release"), | ||
390 | _prom->memory, size, virt); | ||
391 | return -1; | ||
392 | } | ||
393 | /* the 0x12 is M (coherence) + PP == read/write */ | ||
370 | call_prom("call-method", 6, 1, | 394 | call_prom("call-method", 6, 1, |
371 | ADDR("map"), _prom->mmumap, 0, size, virt, virt); | 395 | ADDR("map"), _prom->mmumap, 0x12, size, virt, virt); |
372 | return ret; | 396 | return virt; |
397 | } | ||
398 | return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size, | ||
399 | (prom_arg_t)align); | ||
373 | } | 400 | } |
374 | 401 | ||
375 | static void __init __attribute__((noreturn)) prom_panic(const char *reason) | 402 | static void __init __attribute__((noreturn)) prom_panic(const char *reason) |
@@ -415,11 +442,52 @@ static int inline prom_getproplen(phandle node, const char *pname) | |||
415 | return call_prom("getproplen", 2, 1, node, ADDR(pname)); | 442 | return call_prom("getproplen", 2, 1, node, ADDR(pname)); |
416 | } | 443 | } |
417 | 444 | ||
418 | static int inline prom_setprop(phandle node, const char *pname, | 445 | static void add_string(char **str, const char *q) |
419 | void *value, size_t valuelen) | ||
420 | { | 446 | { |
421 | return call_prom("setprop", 4, 1, node, ADDR(pname), | 447 | char *p = *str; |
422 | (u32)(unsigned long) value, (u32) valuelen); | 448 | |
449 | while (*q) | ||
450 | *p++ = *q++; | ||
451 | *p++ = ' '; | ||
452 | *str = p; | ||
453 | } | ||
454 | |||
455 | static char *tohex(unsigned int x) | ||
456 | { | ||
457 | static char digits[] = "0123456789abcdef"; | ||
458 | static char result[9]; | ||
459 | int i; | ||
460 | |||
461 | result[8] = 0; | ||
462 | i = 8; | ||
463 | do { | ||
464 | --i; | ||
465 | result[i] = digits[x & 0xf]; | ||
466 | x >>= 4; | ||
467 | } while (x != 0 && i > 0); | ||
468 | return &result[i]; | ||
469 | } | ||
470 | |||
471 | static int __init prom_setprop(phandle node, const char *nodename, | ||
472 | const char *pname, void *value, size_t valuelen) | ||
473 | { | ||
474 | char cmd[256], *p; | ||
475 | |||
476 | if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL)) | ||
477 | return call_prom("setprop", 4, 1, node, ADDR(pname), | ||
478 | (u32)(unsigned long) value, (u32) valuelen); | ||
479 | |||
480 | /* gah... setprop doesn't work on longtrail, have to use interpret */ | ||
481 | p = cmd; | ||
482 | add_string(&p, "dev"); | ||
483 | add_string(&p, nodename); | ||
484 | add_string(&p, tohex((u32)(unsigned long) value)); | ||
485 | add_string(&p, tohex(valuelen)); | ||
486 | add_string(&p, tohex(ADDR(pname))); | ||
487 | add_string(&p, tohex(strlen(RELOC(pname)))); | ||
488 | add_string(&p, "property"); | ||
489 | *p = 0; | ||
490 | return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd); | ||
423 | } | 491 | } |
424 | 492 | ||
425 | /* We can't use the standard versions because of RELOC headaches. */ | 493 | /* We can't use the standard versions because of RELOC headaches. */ |
@@ -980,7 +1048,7 @@ static void __init prom_instantiate_rtas(void) | |||
980 | 1048 | ||
981 | rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); | 1049 | rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); |
982 | if (!IHANDLE_VALID(rtas_inst)) { | 1050 | if (!IHANDLE_VALID(rtas_inst)) { |
983 | prom_printf("opening rtas package failed"); | 1051 | prom_printf("opening rtas package failed (%x)\n", rtas_inst); |
984 | return; | 1052 | return; |
985 | } | 1053 | } |
986 | 1054 | ||
@@ -988,7 +1056,7 @@ static void __init prom_instantiate_rtas(void) | |||
988 | 1056 | ||
989 | if (call_prom_ret("call-method", 3, 2, &entry, | 1057 | if (call_prom_ret("call-method", 3, 2, &entry, |
990 | ADDR("instantiate-rtas"), | 1058 | ADDR("instantiate-rtas"), |
991 | rtas_inst, base) == PROM_ERROR | 1059 | rtas_inst, base) != 0 |
992 | || entry == 0) { | 1060 | || entry == 0) { |
993 | prom_printf(" failed\n"); | 1061 | prom_printf(" failed\n"); |
994 | return; | 1062 | return; |
@@ -997,8 +1065,10 @@ static void __init prom_instantiate_rtas(void) | |||
997 | 1065 | ||
998 | reserve_mem(base, size); | 1066 | reserve_mem(base, size); |
999 | 1067 | ||
1000 | prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); | 1068 | prom_setprop(rtas_node, "/rtas", "linux,rtas-base", |
1001 | prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); | 1069 | &base, sizeof(base)); |
1070 | prom_setprop(rtas_node, "/rtas", "linux,rtas-entry", | ||
1071 | &entry, sizeof(entry)); | ||
1002 | 1072 | ||
1003 | prom_debug("rtas base = 0x%x\n", base); | 1073 | prom_debug("rtas base = 0x%x\n", base); |
1004 | prom_debug("rtas entry = 0x%x\n", entry); | 1074 | prom_debug("rtas entry = 0x%x\n", entry); |
@@ -1089,10 +1159,6 @@ static void __init prom_initialize_tce_table(void) | |||
1089 | if (base < local_alloc_bottom) | 1159 | if (base < local_alloc_bottom) |
1090 | local_alloc_bottom = base; | 1160 | local_alloc_bottom = base; |
1091 | 1161 | ||
1092 | /* Save away the TCE table attributes for later use. */ | ||
1093 | prom_setprop(node, "linux,tce-base", &base, sizeof(base)); | ||
1094 | prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize)); | ||
1095 | |||
1096 | /* It seems OF doesn't null-terminate the path :-( */ | 1162 | /* It seems OF doesn't null-terminate the path :-( */ |
1097 | memset(path, 0, sizeof(path)); | 1163 | memset(path, 0, sizeof(path)); |
1098 | /* Call OF to setup the TCE hardware */ | 1164 | /* Call OF to setup the TCE hardware */ |
@@ -1101,6 +1167,10 @@ static void __init prom_initialize_tce_table(void) | |||
1101 | prom_printf("package-to-path failed\n"); | 1167 | prom_printf("package-to-path failed\n"); |
1102 | } | 1168 | } |
1103 | 1169 | ||
1170 | /* Save away the TCE table attributes for later use. */ | ||
1171 | prom_setprop(node, path, "linux,tce-base", &base, sizeof(base)); | ||
1172 | prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize)); | ||
1173 | |||
1104 | prom_debug("TCE table: %s\n", path); | 1174 | prom_debug("TCE table: %s\n", path); |
1105 | prom_debug("\tnode = 0x%x\n", node); | 1175 | prom_debug("\tnode = 0x%x\n", node); |
1106 | prom_debug("\tbase = 0x%x\n", base); | 1176 | prom_debug("\tbase = 0x%x\n", base); |
@@ -1342,6 +1412,7 @@ static void __init prom_init_client_services(unsigned long pp) | |||
1342 | /* | 1412 | /* |
1343 | * For really old powermacs, we need to map things we claim. | 1413 | * For really old powermacs, we need to map things we claim. |
1344 | * For that, we need the ihandle of the mmu. | 1414 | * For that, we need the ihandle of the mmu. |
1415 | * Also, on the longtrail, we need to work around other bugs. | ||
1345 | */ | 1416 | */ |
1346 | static void __init prom_find_mmu(void) | 1417 | static void __init prom_find_mmu(void) |
1347 | { | 1418 | { |
@@ -1355,12 +1426,19 @@ static void __init prom_find_mmu(void) | |||
1355 | if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0) | 1426 | if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0) |
1356 | return; | 1427 | return; |
1357 | version[sizeof(version) - 1] = 0; | 1428 | version[sizeof(version) - 1] = 0; |
1358 | prom_printf("OF version is '%s'\n", version); | ||
1359 | /* XXX might need to add other versions here */ | 1429 | /* XXX might need to add other versions here */ |
1360 | if (strcmp(version, "Open Firmware, 1.0.5") != 0) | 1430 | if (strcmp(version, "Open Firmware, 1.0.5") == 0) |
1431 | of_workarounds = OF_WA_CLAIM; | ||
1432 | else if (strncmp(version, "FirmWorks,3.", 12) == 0) { | ||
1433 | of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL; | ||
1434 | call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim"); | ||
1435 | } else | ||
1361 | return; | 1436 | return; |
1437 | _prom->memory = call_prom("open", 1, 1, ADDR("/memory")); | ||
1362 | prom_getprop(_prom->chosen, "mmu", &_prom->mmumap, | 1438 | prom_getprop(_prom->chosen, "mmu", &_prom->mmumap, |
1363 | sizeof(_prom->mmumap)); | 1439 | sizeof(_prom->mmumap)); |
1440 | if (!IHANDLE_VALID(_prom->memory) || !IHANDLE_VALID(_prom->mmumap)) | ||
1441 | of_workarounds &= ~OF_WA_CLAIM; /* hmmm */ | ||
1364 | } | 1442 | } |
1365 | #else | 1443 | #else |
1366 | #define prom_find_mmu() | 1444 | #define prom_find_mmu() |
@@ -1382,16 +1460,17 @@ static void __init prom_init_stdout(void) | |||
1382 | memset(path, 0, 256); | 1460 | memset(path, 0, 256); |
1383 | call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255); | 1461 | call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255); |
1384 | val = call_prom("instance-to-package", 1, 1, _prom->stdout); | 1462 | val = call_prom("instance-to-package", 1, 1, _prom->stdout); |
1385 | prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val)); | 1463 | prom_setprop(_prom->chosen, "/chosen", "linux,stdout-package", |
1464 | &val, sizeof(val)); | ||
1386 | prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device)); | 1465 | prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device)); |
1387 | prom_setprop(_prom->chosen, "linux,stdout-path", | 1466 | prom_setprop(_prom->chosen, "/chosen", "linux,stdout-path", |
1388 | RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1); | 1467 | path, strlen(path) + 1); |
1389 | 1468 | ||
1390 | /* If it's a display, note it */ | 1469 | /* If it's a display, note it */ |
1391 | memset(type, 0, sizeof(type)); | 1470 | memset(type, 0, sizeof(type)); |
1392 | prom_getprop(val, "device_type", type, sizeof(type)); | 1471 | prom_getprop(val, "device_type", type, sizeof(type)); |
1393 | if (strcmp(type, RELOC("display")) == 0) | 1472 | if (strcmp(type, RELOC("display")) == 0) |
1394 | prom_setprop(val, "linux,boot-display", NULL, 0); | 1473 | prom_setprop(val, path, "linux,boot-display", NULL, 0); |
1395 | } | 1474 | } |
1396 | 1475 | ||
1397 | static void __init prom_close_stdin(void) | 1476 | static void __init prom_close_stdin(void) |
@@ -1514,7 +1593,7 @@ static void __init prom_check_displays(void) | |||
1514 | 1593 | ||
1515 | /* Success */ | 1594 | /* Success */ |
1516 | prom_printf("done\n"); | 1595 | prom_printf("done\n"); |
1517 | prom_setprop(node, "linux,opened", NULL, 0); | 1596 | prom_setprop(node, path, "linux,opened", NULL, 0); |
1518 | 1597 | ||
1519 | /* Setup a usable color table when the appropriate | 1598 | /* Setup a usable color table when the appropriate |
1520 | * method is available. Should update this to set-colors */ | 1599 | * method is available. Should update this to set-colors */ |
@@ -1884,9 +1963,11 @@ static void __init fixup_device_tree(void) | |||
1884 | /* interrupt on this revision of u3 is number 0 and level */ | 1963 | /* interrupt on this revision of u3 is number 0 and level */ |
1885 | interrupts[0] = 0; | 1964 | interrupts[0] = 0; |
1886 | interrupts[1] = 1; | 1965 | interrupts[1] = 1; |
1887 | prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); | 1966 | prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts", |
1967 | &interrupts, sizeof(interrupts)); | ||
1888 | parent = (u32)mpic; | 1968 | parent = (u32)mpic; |
1889 | prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); | 1969 | prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent", |
1970 | &parent, sizeof(parent)); | ||
1890 | #endif | 1971 | #endif |
1891 | } | 1972 | } |
1892 | 1973 | ||
@@ -1922,11 +2003,11 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4) | |||
1922 | RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4; | 2003 | RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4; |
1923 | 2004 | ||
1924 | val = RELOC(prom_initrd_start); | 2005 | val = RELOC(prom_initrd_start); |
1925 | prom_setprop(_prom->chosen, "linux,initrd-start", &val, | 2006 | prom_setprop(_prom->chosen, "/chosen", "linux,initrd-start", |
1926 | sizeof(val)); | 2007 | &val, sizeof(val)); |
1927 | val = RELOC(prom_initrd_end); | 2008 | val = RELOC(prom_initrd_end); |
1928 | prom_setprop(_prom->chosen, "linux,initrd-end", &val, | 2009 | prom_setprop(_prom->chosen, "/chosen", "linux,initrd-end", |
1929 | sizeof(val)); | 2010 | &val, sizeof(val)); |
1930 | 2011 | ||
1931 | reserve_mem(RELOC(prom_initrd_start), | 2012 | reserve_mem(RELOC(prom_initrd_start), |
1932 | RELOC(prom_initrd_end) - RELOC(prom_initrd_start)); | 2013 | RELOC(prom_initrd_end) - RELOC(prom_initrd_start)); |
@@ -1969,14 +2050,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
1969 | prom_init_client_services(pp); | 2050 | prom_init_client_services(pp); |
1970 | 2051 | ||
1971 | /* | 2052 | /* |
1972 | * Init prom stdout device | 2053 | * See if this OF is old enough that we need to do explicit maps |
2054 | * and other workarounds | ||
1973 | */ | 2055 | */ |
1974 | prom_init_stdout(); | 2056 | prom_find_mmu(); |
1975 | 2057 | ||
1976 | /* | 2058 | /* |
1977 | * See if this OF is old enough that we need to do explicit maps | 2059 | * Init prom stdout device |
1978 | */ | 2060 | */ |
1979 | prom_find_mmu(); | 2061 | prom_init_stdout(); |
1980 | 2062 | ||
1981 | /* | 2063 | /* |
1982 | * Check for an initrd | 2064 | * Check for an initrd |
@@ -1989,7 +2071,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
1989 | */ | 2071 | */ |
1990 | RELOC(of_platform) = prom_find_machine_type(); | 2072 | RELOC(of_platform) = prom_find_machine_type(); |
1991 | getprop_rval = RELOC(of_platform); | 2073 | getprop_rval = RELOC(of_platform); |
1992 | prom_setprop(_prom->chosen, "linux,platform", | 2074 | prom_setprop(_prom->chosen, "/chosen", "linux,platform", |
1993 | &getprop_rval, sizeof(getprop_rval)); | 2075 | &getprop_rval, sizeof(getprop_rval)); |
1994 | 2076 | ||
1995 | #ifdef CONFIG_PPC_PSERIES | 2077 | #ifdef CONFIG_PPC_PSERIES |
@@ -2050,21 +2132,23 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2050 | * Fill in some infos for use by the kernel later on | 2132 | * Fill in some infos for use by the kernel later on |
2051 | */ | 2133 | */ |
2052 | if (RELOC(prom_memory_limit)) | 2134 | if (RELOC(prom_memory_limit)) |
2053 | prom_setprop(_prom->chosen, "linux,memory-limit", | 2135 | prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit", |
2054 | &RELOC(prom_memory_limit), | 2136 | &RELOC(prom_memory_limit), |
2055 | sizeof(prom_memory_limit)); | 2137 | sizeof(prom_memory_limit)); |
2056 | #ifdef CONFIG_PPC64 | 2138 | #ifdef CONFIG_PPC64 |
2057 | if (RELOC(ppc64_iommu_off)) | 2139 | if (RELOC(ppc64_iommu_off)) |
2058 | prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0); | 2140 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", |
2141 | NULL, 0); | ||
2059 | 2142 | ||
2060 | if (RELOC(iommu_force_on)) | 2143 | if (RELOC(iommu_force_on)) |
2061 | prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0); | 2144 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on", |
2145 | NULL, 0); | ||
2062 | 2146 | ||
2063 | if (RELOC(prom_tce_alloc_start)) { | 2147 | if (RELOC(prom_tce_alloc_start)) { |
2064 | prom_setprop(_prom->chosen, "linux,tce-alloc-start", | 2148 | prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-start", |
2065 | &RELOC(prom_tce_alloc_start), | 2149 | &RELOC(prom_tce_alloc_start), |
2066 | sizeof(prom_tce_alloc_start)); | 2150 | sizeof(prom_tce_alloc_start)); |
2067 | prom_setprop(_prom->chosen, "linux,tce-alloc-end", | 2151 | prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-end", |
2068 | &RELOC(prom_tce_alloc_end), | 2152 | &RELOC(prom_tce_alloc_end), |
2069 | sizeof(prom_tce_alloc_end)); | 2153 | sizeof(prom_tce_alloc_end)); |
2070 | } | 2154 | } |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index ecd32d5d85f4..4099ddab9205 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -361,7 +361,9 @@ static void __init chrp_find_openpic(void) | |||
361 | printk(KERN_INFO "OpenPIC at %lx\n", opaddr); | 361 | printk(KERN_INFO "OpenPIC at %lx\n", opaddr); |
362 | 362 | ||
363 | irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ | 363 | irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ |
364 | prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS - 4); | 364 | prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4); |
365 | /* i8259 cascade is always positive level */ | ||
366 | init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE; | ||
365 | 367 | ||
366 | iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); | 368 | iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); |
367 | if (iranges == NULL) | 369 | if (iranges == NULL) |
diff --git a/arch/ppc/boot/include/of1275.h b/arch/ppc/boot/include/of1275.h index 69173df76db0..4ed88acfa73a 100644 --- a/arch/ppc/boot/include/of1275.h +++ b/arch/ppc/boot/include/of1275.h | |||
@@ -19,6 +19,9 @@ extern prom_entry of_prom_entry; | |||
19 | 19 | ||
20 | /* function declarations */ | 20 | /* function declarations */ |
21 | 21 | ||
22 | int call_prom(const char *service, int nargs, int nret, ...); | ||
23 | int call_prom_ret(const char *service, int nargs, int nret, | ||
24 | unsigned int *rets, ...); | ||
22 | void * claim(unsigned int virt, unsigned int size, unsigned int align); | 25 | void * claim(unsigned int virt, unsigned int size, unsigned int align); |
23 | int map(unsigned int phys, unsigned int virt, unsigned int size); | 26 | int map(unsigned int phys, unsigned int virt, unsigned int size); |
24 | void enter(void); | 27 | void enter(void); |
diff --git a/arch/ppc/boot/of1275/Makefile b/arch/ppc/boot/of1275/Makefile index 02e6f235d7cb..0b979c004972 100644 --- a/arch/ppc/boot/of1275/Makefile +++ b/arch/ppc/boot/of1275/Makefile | |||
@@ -3,4 +3,4 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \ | 5 | lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \ |
6 | ofstdio.o read.o release.o write.o map.o | 6 | ofstdio.o read.o release.o write.o map.o call_prom.o |
diff --git a/arch/ppc/boot/of1275/call_prom.c b/arch/ppc/boot/of1275/call_prom.c new file mode 100644 index 000000000000..9479a3a2b8c7 --- /dev/null +++ b/arch/ppc/boot/of1275/call_prom.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996-2005 Paul Mackerras. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include "of1275.h" | ||
11 | #include <stdarg.h> | ||
12 | |||
13 | int call_prom(const char *service, int nargs, int nret, ...) | ||
14 | { | ||
15 | int i; | ||
16 | struct prom_args { | ||
17 | const char *service; | ||
18 | int nargs; | ||
19 | int nret; | ||
20 | unsigned int args[12]; | ||
21 | } args; | ||
22 | va_list list; | ||
23 | |||
24 | args.service = service; | ||
25 | args.nargs = nargs; | ||
26 | args.nret = nret; | ||
27 | |||
28 | va_start(list, nret); | ||
29 | for (i = 0; i < nargs; i++) | ||
30 | args.args[i] = va_arg(list, unsigned int); | ||
31 | va_end(list); | ||
32 | |||
33 | for (i = 0; i < nret; i++) | ||
34 | args.args[nargs+i] = 0; | ||
35 | |||
36 | if (of_prom_entry(&args) < 0) | ||
37 | return -1; | ||
38 | |||
39 | return (nret > 0)? args.args[nargs]: 0; | ||
40 | } | ||
41 | |||
42 | int call_prom_ret(const char *service, int nargs, int nret, | ||
43 | unsigned int *rets, ...) | ||
44 | { | ||
45 | int i; | ||
46 | struct prom_args { | ||
47 | const char *service; | ||
48 | int nargs; | ||
49 | int nret; | ||
50 | unsigned int args[12]; | ||
51 | } args; | ||
52 | va_list list; | ||
53 | |||
54 | args.service = service; | ||
55 | args.nargs = nargs; | ||
56 | args.nret = nret; | ||
57 | |||
58 | va_start(list, rets); | ||
59 | for (i = 0; i < nargs; i++) | ||
60 | args.args[i] = va_arg(list, unsigned int); | ||
61 | va_end(list); | ||
62 | |||
63 | for (i = 0; i < nret; i++) | ||
64 | args.args[nargs+i] = 0; | ||
65 | |||
66 | if (of_prom_entry(&args) < 0) | ||
67 | return -1; | ||
68 | |||
69 | if (rets != (void *) 0) | ||
70 | for (i = 1; i < nret; ++i) | ||
71 | rets[i-1] = args.args[nargs+i]; | ||
72 | |||
73 | return (nret > 0)? args.args[nargs]: 0; | ||
74 | } | ||
diff --git a/arch/ppc/boot/of1275/claim.c b/arch/ppc/boot/of1275/claim.c index 13169a5c4339..1ed3aeeff8ae 100644 --- a/arch/ppc/boot/of1275/claim.c +++ b/arch/ppc/boot/of1275/claim.c | |||
@@ -9,27 +9,84 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include "of1275.h" | 11 | #include "of1275.h" |
12 | #include "nonstdio.h" | ||
12 | 13 | ||
13 | void * | 14 | /* |
14 | claim(unsigned int virt, unsigned int size, unsigned int align) | 15 | * Older OF's require that when claiming a specific range of addresses, |
16 | * we claim the physical space in the /memory node and the virtual | ||
17 | * space in the chosen mmu node, and then do a map operation to | ||
18 | * map virtual to physical. | ||
19 | */ | ||
20 | static int need_map = -1; | ||
21 | static ihandle chosen_mmu; | ||
22 | static phandle memory; | ||
23 | |||
24 | /* returns true if s2 is a prefix of s1 */ | ||
25 | static int string_match(const char *s1, const char *s2) | ||
26 | { | ||
27 | for (; *s2; ++s2) | ||
28 | if (*s1++ != *s2) | ||
29 | return 0; | ||
30 | return 1; | ||
31 | } | ||
32 | |||
33 | static int check_of_version(void) | ||
34 | { | ||
35 | phandle oprom, chosen; | ||
36 | char version[64]; | ||
37 | |||
38 | oprom = finddevice("/openprom"); | ||
39 | if (oprom == OF_INVALID_HANDLE) | ||
40 | return 0; | ||
41 | if (getprop(oprom, "model", version, sizeof(version)) <= 0) | ||
42 | return 0; | ||
43 | version[sizeof(version)-1] = 0; | ||
44 | printf("OF version = '%s'\n", version); | ||
45 | if (!string_match(version, "Open Firmware, 1.") | ||
46 | && !string_match(version, "FirmWorks,3.")) | ||
47 | return 0; | ||
48 | chosen = finddevice("/chosen"); | ||
49 | if (chosen == OF_INVALID_HANDLE) { | ||
50 | chosen = finddevice("/chosen@0"); | ||
51 | if (chosen == OF_INVALID_HANDLE) { | ||
52 | printf("no chosen\n"); | ||
53 | return 0; | ||
54 | } | ||
55 | } | ||
56 | if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { | ||
57 | printf("no mmu\n"); | ||
58 | return 0; | ||
59 | } | ||
60 | memory = (ihandle) call_prom("open", 1, 1, "/memory"); | ||
61 | if (memory == OF_INVALID_HANDLE) { | ||
62 | memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); | ||
63 | if (memory == OF_INVALID_HANDLE) { | ||
64 | printf("no memory node\n"); | ||
65 | return 0; | ||
66 | } | ||
67 | } | ||
68 | printf("old OF detected\n"); | ||
69 | return 1; | ||
70 | } | ||
71 | |||
72 | void *claim(unsigned int virt, unsigned int size, unsigned int align) | ||
15 | { | 73 | { |
16 | struct prom_args { | 74 | int ret; |
17 | char *service; | 75 | unsigned int result; |
18 | int nargs; | ||
19 | int nret; | ||
20 | unsigned int virt; | ||
21 | unsigned int size; | ||
22 | unsigned int align; | ||
23 | void *ret; | ||
24 | } args; | ||
25 | 76 | ||
26 | args.service = "claim"; | 77 | if (need_map < 0) |
27 | args.nargs = 3; | 78 | need_map = check_of_version(); |
28 | args.nret = 1; | 79 | if (align || !need_map) |
29 | args.virt = virt; | 80 | return (void *) call_prom("claim", 3, 1, virt, size, align); |
30 | args.size = size; | 81 | |
31 | args.align = align; | 82 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, |
32 | args.ret = (void *) 0; | 83 | align, size, virt); |
33 | (*of_prom_entry)(&args); | 84 | if (ret != 0 || result == -1) |
34 | return args.ret; | 85 | return (void *) -1; |
86 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, | ||
87 | align, size, virt); | ||
88 | /* 0x12 == coherent + read/write */ | ||
89 | ret = call_prom("call-method", 6, 1, "map", chosen_mmu, | ||
90 | 0x12, size, virt, virt); | ||
91 | return virt; | ||
35 | } | 92 | } |
diff --git a/arch/ppc/boot/of1275/finddevice.c b/arch/ppc/boot/of1275/finddevice.c index 2c0f7cbb793e..0dcb1201b772 100644 --- a/arch/ppc/boot/of1275/finddevice.c +++ b/arch/ppc/boot/of1275/finddevice.c | |||
@@ -10,22 +10,7 @@ | |||
10 | 10 | ||
11 | #include "of1275.h" | 11 | #include "of1275.h" |
12 | 12 | ||
13 | phandle | 13 | phandle finddevice(const char *name) |
14 | finddevice(const char *name) | ||
15 | { | 14 | { |
16 | struct prom_args { | 15 | return (phandle) call_prom("finddevice", 1, 1, name); |
17 | char *service; | ||
18 | int nargs; | ||
19 | int nret; | ||
20 | const char *devspec; | ||
21 | phandle device; | ||
22 | } args; | ||
23 | |||
24 | args.service = "finddevice"; | ||
25 | args.nargs = 1; | ||
26 | args.nret = 1; | ||
27 | args.devspec = name; | ||
28 | args.device = OF_INVALID_HANDLE; | ||
29 | (*of_prom_entry)(&args); | ||
30 | return args.device; | ||
31 | } | 16 | } |