summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powernv/opal.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt2014-05-20 03:01:28 +0200
committerBenjamin Herrenschmidt2014-06-05 05:19:59 +0200
commit4926616c77435e735c59288f838e7761baec4a6c (patch)
treea9dd2f673b9bdc1de9530b49232d7beb85ebd0f8 /arch/powerpc/platforms/powernv/opal.c
parentpowerpc: Document sysfs DSCR interface (diff)
downloadkernel-qcow2-linux-4926616c77435e735c59288f838e7761baec4a6c.tar.gz
kernel-qcow2-linux-4926616c77435e735c59288f838e7761baec4a6c.tar.xz
kernel-qcow2-linux-4926616c77435e735c59288f838e7761baec4a6c.zip
powerpc/powernv: Add calls to support little endian host
When running as a powernv "host" system on P8, we need to switch the endianness of interrupt handlers. This does it via the appropriate call to the OPAL firmware which may result in just switching HID0:HILE but depending on the processor version might need to do a few more things. This call must be done early before any other processor has been brought out of firmware. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andy Whitcroft <apw@canonical.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms/powernv/opal.c')
-rw-r--r--arch/powerpc/platforms/powernv/opal.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 360ad80c754c..539243e9dc23 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -57,6 +57,21 @@ static DEFINE_SPINLOCK(opal_notifier_lock);
static uint64_t last_notified_mask = 0x0ul;
static atomic_t opal_notifier_hold = ATOMIC_INIT(0);
+static void opal_reinit_cores(void)
+{
+ /* Do the actual re-init, This will clobber all FPRs, VRs, etc...
+ *
+ * It will preserve non volatile GPRs and HSPRG0/1. It will
+ * also restore HIDs and other SPRs to their original value
+ * but it might clobber a bunch.
+ */
+#ifdef __BIG_ENDIAN__
+ opal_reinit_cpus(OPAL_REINIT_CPUS_HILE_BE);
+#else
+ opal_reinit_cpus(OPAL_REINIT_CPUS_HILE_LE);
+#endif
+}
+
int __init early_init_dt_scan_opal(unsigned long node,
const char *uname, int depth, void *data)
{
@@ -96,6 +111,13 @@ int __init early_init_dt_scan_opal(unsigned long node,
printk("OPAL V1 detected !\n");
}
+ /* Reinit all cores with the right endian */
+ opal_reinit_cores();
+
+ /* Restore some bits */
+ if (cur_cpu_spec->cpu_restore)
+ cur_cpu_spec->cpu_restore();
+
return 1;
}