aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-09-19 14:28:01 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-09-20 02:09:52 -0400
commit6e35d5dac0c83ebb616ff3b9c2d6155c9a9ccb86 (patch)
treebbd8641fa69eaa3f62d644e5acb03a657cd1c6b9
parent14a43e69ed257a1fadadf9fea2c05adb1686419f (diff)
powerpc/powernv: Add support for instanciating OPAL v2 from Open Firmware
OPAL v2 is instantiated in a way similar to RTAS using Open Firmware client interface calls, and the resulting address and entry point are put in the device-tree Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/kernel/prom_init.c136
1 files changed, 117 insertions, 19 deletions
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index e3f390427216..e96f5d0d2c78 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -140,7 +140,9 @@ struct mem_map_entry {
140 140
141typedef u32 cell_t; 141typedef u32 cell_t;
142 142
143extern void __start(unsigned long r3, unsigned long r4, unsigned long r5); 143extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
144 unsigned long r6, unsigned long r7, unsigned long r8,
145 unsigned long r9);
144 146
145#ifdef CONFIG_PPC64 147#ifdef CONFIG_PPC64
146extern int enter_prom(struct prom_args *args, unsigned long entry); 148extern int enter_prom(struct prom_args *args, unsigned long entry);
@@ -1293,6 +1295,11 @@ static int __initdata prom_rtas_start_cpu;
1293static u64 __initdata prom_rtas_data; 1295static u64 __initdata prom_rtas_data;
1294static u64 __initdata prom_rtas_entry; 1296static u64 __initdata prom_rtas_entry;
1295 1297
1298#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
1299static u64 __initdata prom_opal_base;
1300static u64 __initdata prom_opal_entry;
1301#endif
1302
1296/* XXX Don't change this structure without updating opal-takeover.S */ 1303/* XXX Don't change this structure without updating opal-takeover.S */
1297static struct opal_secondary_data { 1304static struct opal_secondary_data {
1298 s64 ack; /* 0 */ 1305 s64 ack; /* 0 */
@@ -1468,6 +1475,76 @@ static void prom_opal_takeover(void)
1468 for (;;) 1475 for (;;)
1469 opal_do_takeover(args); 1476 opal_do_takeover(args);
1470} 1477}
1478
1479/*
1480 * Allocate room for and instantiate OPAL
1481 */
1482static void __init prom_instantiate_opal(void)
1483{
1484 phandle opal_node;
1485 ihandle opal_inst;
1486 u64 base, entry;
1487 u64 size = 0, align = 0x10000;
1488 u32 rets[2];
1489
1490 prom_debug("prom_instantiate_opal: start...\n");
1491
1492 opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal"));
1493 prom_debug("opal_node: %x\n", opal_node);
1494 if (!PHANDLE_VALID(opal_node))
1495 return;
1496
1497 prom_getprop(opal_node, "opal-runtime-size", &size, sizeof(size));
1498 if (size == 0)
1499 return;
1500 prom_getprop(opal_node, "opal-runtime-alignment", &align,
1501 sizeof(align));
1502
1503 base = alloc_down(size, align, 0);
1504 if (base == 0) {
1505 prom_printf("OPAL allocation failed !\n");
1506 return;
1507 }
1508
1509 opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal"));
1510 if (!IHANDLE_VALID(opal_inst)) {
1511 prom_printf("opening opal package failed (%x)\n", opal_inst);
1512 return;
1513 }
1514
1515 prom_printf("instantiating opal at 0x%x...", base);
1516
1517 if (call_prom_ret("call-method", 4, 3, rets,
1518 ADDR("load-opal-runtime"),
1519 opal_inst,
1520 base >> 32, base & 0xffffffff) != 0
1521 || (rets[0] == 0 && rets[1] == 0)) {
1522 prom_printf(" failed\n");
1523 return;
1524 }
1525 entry = (((u64)rets[0]) << 32) | rets[1];
1526
1527 prom_printf(" done\n");
1528
1529 reserve_mem(base, size);
1530
1531 prom_debug("opal base = 0x%x\n", base);
1532 prom_debug("opal align = 0x%x\n", align);
1533 prom_debug("opal entry = 0x%x\n", entry);
1534 prom_debug("opal size = 0x%x\n", (long)size);
1535
1536 prom_setprop(opal_node, "/ibm,opal", "opal-base-address",
1537 &base, sizeof(base));
1538 prom_setprop(opal_node, "/ibm,opal", "opal-entry-address",
1539 &entry, sizeof(entry));
1540
1541#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
1542 RELOC(prom_opal_base) = base;
1543 RELOC(prom_opal_entry) = entry;
1544#endif
1545 prom_debug("prom_instantiate_opal: end...\n");
1546}
1547
1471#endif /* CONFIG_PPC_POWERNV */ 1548#endif /* CONFIG_PPC_POWERNV */
1472 1549
1473/* 1550/*
@@ -1863,7 +1940,7 @@ static int __init prom_find_machine_type(void)
1863 int x; 1940 int x;
1864#endif 1941#endif
1865 1942
1866 /* Look for a PowerMac */ 1943 /* Look for a PowerMac or a Cell */
1867 len = prom_getprop(_prom->root, "compatible", 1944 len = prom_getprop(_prom->root, "compatible",
1868 compat, sizeof(compat)-1); 1945 compat, sizeof(compat)-1);
1869 if (len > 0) { 1946 if (len > 0) {
@@ -1889,7 +1966,11 @@ static int __init prom_find_machine_type(void)
1889 } 1966 }
1890 } 1967 }
1891#ifdef CONFIG_PPC64 1968#ifdef CONFIG_PPC64
1892 /* If not a mac, try to figure out if it's an IBM pSeries or any other 1969 /* Try to detect OPAL */
1970 if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal"))))
1971 return PLATFORM_OPAL;
1972
1973 /* Try to figure out if it's an IBM pSeries or any other
1893 * PAPR compliant platform. We assume it is if : 1974 * PAPR compliant platform. We assume it is if :
1894 * - /device_type is "chrp" (please, do NOT use that for future 1975 * - /device_type is "chrp" (please, do NOT use that for future
1895 * non-IBM designs ! 1976 * non-IBM designs !
@@ -2116,7 +2197,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2116 unsigned long soff; 2197 unsigned long soff;
2117 unsigned char *valp; 2198 unsigned char *valp;
2118 static char pname[MAX_PROPERTY_NAME]; 2199 static char pname[MAX_PROPERTY_NAME];
2119 int l, room; 2200 int l, room, has_phandle = 0;
2120 2201
2121 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); 2202 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2122 2203
@@ -2200,19 +2281,26 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2200 valp = make_room(mem_start, mem_end, l, 4); 2281 valp = make_room(mem_start, mem_end, l, 4);
2201 call_prom("getprop", 4, 1, node, RELOC(pname), valp, l); 2282 call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
2202 *mem_start = _ALIGN(*mem_start, 4); 2283 *mem_start = _ALIGN(*mem_start, 4);
2284
2285 if (!strcmp(RELOC(pname), RELOC("phandle")))
2286 has_phandle = 1;
2203 } 2287 }
2204 2288
2205 /* Add a "linux,phandle" property. */ 2289 /* Add a "linux,phandle" property if no "phandle" property already
2206 soff = dt_find_string(RELOC("linux,phandle")); 2290 * existed (can happen with OPAL)
2207 if (soff == 0) 2291 */
2208 prom_printf("WARNING: Can't find string index for" 2292 if (!has_phandle) {
2209 " <linux-phandle> node %s\n", path); 2293 soff = dt_find_string(RELOC("linux,phandle"));
2210 else { 2294 if (soff == 0)
2211 dt_push_token(OF_DT_PROP, mem_start, mem_end); 2295 prom_printf("WARNING: Can't find string index for"
2212 dt_push_token(4, mem_start, mem_end); 2296 " <linux-phandle> node %s\n", path);
2213 dt_push_token(soff, mem_start, mem_end); 2297 else {
2214 valp = make_room(mem_start, mem_end, 4, 4); 2298 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2215 *(u32 *)valp = node; 2299 dt_push_token(4, mem_start, mem_end);
2300 dt_push_token(soff, mem_start, mem_end);
2301 valp = make_room(mem_start, mem_end, 4, 4);
2302 *(u32 *)valp = node;
2303 }
2216 } 2304 }
2217 2305
2218 /* do all our children */ 2306 /* do all our children */
@@ -2746,6 +2834,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2746 * between pSeries SMP and pSeries LPAR 2834 * between pSeries SMP and pSeries LPAR
2747 */ 2835 */
2748 RELOC(of_platform) = prom_find_machine_type(); 2836 RELOC(of_platform) = prom_find_machine_type();
2837 prom_printf("Detected machine type: %x\n", RELOC(of_platform));
2749 2838
2750#ifndef CONFIG_RELOCATABLE 2839#ifndef CONFIG_RELOCATABLE
2751 /* Bail if this is a kdump kernel. */ 2840 /* Bail if this is a kdump kernel. */
@@ -2807,7 +2896,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2807 * On non-powermacs, try to instantiate RTAS. PowerMacs don't 2896 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
2808 * have a usable RTAS implementation. 2897 * have a usable RTAS implementation.
2809 */ 2898 */
2810 if (RELOC(of_platform) != PLATFORM_POWERMAC) 2899 if (RELOC(of_platform) != PLATFORM_POWERMAC &&
2900 RELOC(of_platform) != PLATFORM_OPAL)
2811 prom_instantiate_rtas(); 2901 prom_instantiate_rtas();
2812 2902
2813#ifdef CONFIG_PPC_POWERNV 2903#ifdef CONFIG_PPC_POWERNV
@@ -2818,7 +2908,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2818 prom_opal_hold_cpus(); 2908 prom_opal_hold_cpus();
2819 prom_opal_takeover(); 2909 prom_opal_takeover();
2820 } 2910 }
2821 } 2911 } else if (RELOC(of_platform) == PLATFORM_OPAL)
2912 prom_instantiate_opal();
2822#endif 2913#endif
2823 2914
2824 /* 2915 /*
@@ -2826,7 +2917,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2826 * 2917 *
2827 * PowerMacs use a different mechanism to spin CPUs 2918 * PowerMacs use a different mechanism to spin CPUs
2828 */ 2919 */
2829 if (RELOC(of_platform) != PLATFORM_POWERMAC) 2920 if (RELOC(of_platform) != PLATFORM_POWERMAC &&
2921 RELOC(of_platform) != PLATFORM_OPAL)
2830 prom_hold_cpus(); 2922 prom_hold_cpus();
2831 2923
2832 /* 2924 /*
@@ -2894,7 +2986,13 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2894 reloc_got2(-offset); 2986 reloc_got2(-offset);
2895#endif 2987#endif
2896 2988
2897 __start(hdr, kbase, 0); 2989#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
2990 /* OPAL early debug gets the OPAL base & entry in r8 and r9 */
2991 __start(hdr, kbase, 0, 0, 0,
2992 RELOC(prom_opal_base), RELOC(prom_opal_entry));
2993#else
2994 __start(hdr, kbase, 0, 0, 0, 0, 0);
2995#endif
2898 2996
2899 return 0; 2997 return 0;
2900} 2998}