Skip to content

Commit 6e35d5d

Browse files
committed
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 <[email protected]>
1 parent 14a43e6 commit 6e35d5d

File tree

1 file changed

+117
-19
lines changed

1 file changed

+117
-19
lines changed

arch/powerpc/kernel/prom_init.c

Lines changed: 117 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ struct mem_map_entry {
140140

141141
typedef u32 cell_t;
142142

143-
extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
143+
extern 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);
144146

145147
#ifdef CONFIG_PPC64
146148
extern int enter_prom(struct prom_args *args, unsigned long entry);
@@ -1293,6 +1295,11 @@ static int __initdata prom_rtas_start_cpu;
12931295
static u64 __initdata prom_rtas_data;
12941296
static u64 __initdata prom_rtas_entry;
12951297

1298+
#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
1299+
static u64 __initdata prom_opal_base;
1300+
static u64 __initdata prom_opal_entry;
1301+
#endif
1302+
12961303
/* XXX Don't change this structure without updating opal-takeover.S */
12971304
static struct opal_secondary_data {
12981305
s64 ack; /* 0 */
@@ -1468,6 +1475,76 @@ static void prom_opal_takeover(void)
14681475
for (;;)
14691476
opal_do_takeover(args);
14701477
}
1478+
1479+
/*
1480+
* Allocate room for and instantiate OPAL
1481+
*/
1482+
static 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+
14711548
#endif /* CONFIG_PPC_POWERNV */
14721549

14731550
/*
@@ -1863,7 +1940,7 @@ static int __init prom_find_machine_type(void)
18631940
int x;
18641941
#endif
18651942

1866-
/* Look for a PowerMac */
1943+
/* Look for a PowerMac or a Cell */
18671944
len = prom_getprop(_prom->root, "compatible",
18681945
compat, sizeof(compat)-1);
18691946
if (len > 0) {
@@ -1889,7 +1966,11 @@ static int __init prom_find_machine_type(void)
18891966
}
18901967
}
18911968
#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
18931974
* PAPR compliant platform. We assume it is if :
18941975
* - /device_type is "chrp" (please, do NOT use that for future
18951976
* non-IBM designs !
@@ -2116,7 +2197,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
21162197
unsigned long soff;
21172198
unsigned char *valp;
21182199
static char pname[MAX_PROPERTY_NAME];
2119-
int l, room;
2200+
int l, room, has_phandle = 0;
21202201

21212202
dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
21222203

@@ -2200,19 +2281,26 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
22002281
valp = make_room(mem_start, mem_end, l, 4);
22012282
call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
22022283
*mem_start = _ALIGN(*mem_start, 4);
2284+
2285+
if (!strcmp(RELOC(pname), RELOC("phandle")))
2286+
has_phandle = 1;
22032287
}
22042288

2205-
/* Add a "linux,phandle" property. */
2206-
soff = dt_find_string(RELOC("linux,phandle"));
2207-
if (soff == 0)
2208-
prom_printf("WARNING: Can't find string index for"
2209-
" <linux-phandle> node %s\n", path);
2210-
else {
2211-
dt_push_token(OF_DT_PROP, mem_start, mem_end);
2212-
dt_push_token(4, mem_start, mem_end);
2213-
dt_push_token(soff, mem_start, mem_end);
2214-
valp = make_room(mem_start, mem_end, 4, 4);
2215-
*(u32 *)valp = node;
2289+
/* Add a "linux,phandle" property if no "phandle" property already
2290+
* existed (can happen with OPAL)
2291+
*/
2292+
if (!has_phandle) {
2293+
soff = dt_find_string(RELOC("linux,phandle"));
2294+
if (soff == 0)
2295+
prom_printf("WARNING: Can't find string index for"
2296+
" <linux-phandle> node %s\n", path);
2297+
else {
2298+
dt_push_token(OF_DT_PROP, mem_start, mem_end);
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+
}
22162304
}
22172305

22182306
/* do all our children */
@@ -2746,6 +2834,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
27462834
* between pSeries SMP and pSeries LPAR
27472835
*/
27482836
RELOC(of_platform) = prom_find_machine_type();
2837+
prom_printf("Detected machine type: %x\n", RELOC(of_platform));
27492838

27502839
#ifndef CONFIG_RELOCATABLE
27512840
/* Bail if this is a kdump kernel. */
@@ -2807,7 +2896,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
28072896
* On non-powermacs, try to instantiate RTAS. PowerMacs don't
28082897
* have a usable RTAS implementation.
28092898
*/
2810-
if (RELOC(of_platform) != PLATFORM_POWERMAC)
2899+
if (RELOC(of_platform) != PLATFORM_POWERMAC &&
2900+
RELOC(of_platform) != PLATFORM_OPAL)
28112901
prom_instantiate_rtas();
28122902

28132903
#ifdef CONFIG_PPC_POWERNV
@@ -2818,15 +2908,17 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
28182908
prom_opal_hold_cpus();
28192909
prom_opal_takeover();
28202910
}
2821-
}
2911+
} else if (RELOC(of_platform) == PLATFORM_OPAL)
2912+
prom_instantiate_opal();
28222913
#endif
28232914

28242915
/*
28252916
* On non-powermacs, put all CPUs in spin-loops.
28262917
*
28272918
* PowerMacs use a different mechanism to spin CPUs
28282919
*/
2829-
if (RELOC(of_platform) != PLATFORM_POWERMAC)
2920+
if (RELOC(of_platform) != PLATFORM_POWERMAC &&
2921+
RELOC(of_platform) != PLATFORM_OPAL)
28302922
prom_hold_cpus();
28312923

28322924
/*
@@ -2894,7 +2986,13 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
28942986
reloc_got2(-offset);
28952987
#endif
28962988

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
28982996

28992997
return 0;
29002998
}

0 commit comments

Comments
 (0)