[PATCH v2 12/15] powerpc/boot: define a routine to enter prom

2014-04-24 Thread Cédric Le Goater
This patch defines a 'prom' routine similar to 'enter_prom' in the
kernel.

The difference is in the MSR which is built before entering prom. Big
endian order is enforced as in the kernel but 32bit mode is not. It
prepares ground for the next patches which will introduce Little endian
order.

Signed-off-by: Cédric Le Goater c...@fr.ibm.com
---
 arch/powerpc/boot/crt0.S  |   71 +
 arch/powerpc/boot/oflib.c |6 
 2 files changed, 77 insertions(+)

diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
index 0f7428a37efb..dbd99d064828 100644
--- a/arch/powerpc/boot/crt0.S
+++ b/arch/powerpc/boot/crt0.S
@@ -126,3 +126,74 @@ RELACOUNT = 0x6ff9
 
/* Call start */
b   start
+
+#ifdef __powerpc64__
+
+#define PROM_FRAME_SIZE 512
+#define SAVE_GPR(n, base)   std n,8*(n)(base)
+#define REST_GPR(n, base)   ld  n,8*(n)(base)
+#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
+#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
+#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
+#define SAVE_10GPRS(n, base)SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
+#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
+#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
+#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
+#define REST_10GPRS(n, base)REST_8GPRS(n, base); REST_2GPRS(n+8, base)
+
+/* prom handles the jump into and return from firmware.  The prom args pointer
+   is loaded in r3. */
+.globl prom
+prom:
+   mflrr0
+   std r0,16(r1)
+   stdur1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
+
+   SAVE_GPR(2, r1)
+   SAVE_GPR(13, r1)
+   SAVE_8GPRS(14, r1)
+   SAVE_10GPRS(22, r1)
+   mfcrr10
+   std r10,8*32(r1)
+   mfmsr   r10
+   std r10,8*33(r1)
+
+   /* remove MSR_LE from msr but keep MSR_SF */
+   mfmsr   r10
+   rldicr  r10,r10,0,62
+   mtsrr1  r10
+
+   /* Load FW address, set LR to label 1, and jump to FW */
+   bl  0f
+0: mflrr10
+   addir11,r10,(1f-0b)
+   mtlrr11
+
+   ld  r10,(p_prom-0b)(r10)
+   mtsrr0  r10
+
+   rfid
+
+1: /* Return from OF */
+
+   /* Restore registers and return. */
+   rldicl  r1,r1,0,32
+
+   /* Restore the MSR (back to 64 bits) */
+   ld  r10,8*(33)(r1)
+   mtmsr   r10
+   isync
+
+   /* Restore other registers */
+   REST_GPR(2, r1)
+   REST_GPR(13, r1)
+   REST_8GPRS(14, r1)
+   REST_10GPRS(22, r1)
+   ld  r10,8*32(r1)
+   mtcrr10
+
+   addir1,r1,PROM_FRAME_SIZE
+   ld  r0,16(r1)
+   mtlrr0
+   blr
+#endif
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index cdfe762d2b2b..46c98a47d949 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -27,11 +27,17 @@ struct prom_args {
__be32 args[10];/* Input/output arguments. */
 };
 
+#ifdef __powerpc64__
+extern int prom(void *);
+#else
 static int (*prom) (void *);
+#endif
 
 void of_init(void *promptr)
 {
+#ifndef __powerpc64__
prom = (int (*)(void *))promptr;
+#endif
 }
 
 #define ADDR(x)(u32)(unsigned long)(x)
-- 
1.7.10.4

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH v2 12/15] powerpc/boot: define a routine to enter prom

2014-04-14 Thread Cédric Le Goater
This patch defines a 'prom' routine similar to 'enter_prom' in the
kernel.

The difference is in the MSR which is built before entering prom. Big
endian order is enforced as in the kernel but 32bit mode is not. It
prepares ground for the next patches which will introduce Little endian
order.

Signed-off-by: Cédric Le Goater c...@fr.ibm.com
---
 arch/powerpc/boot/crt0.S  |   71 +
 arch/powerpc/boot/oflib.c |6 
 2 files changed, 77 insertions(+)

diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
index 0f7428a37efb..dbd99d064828 100644
--- a/arch/powerpc/boot/crt0.S
+++ b/arch/powerpc/boot/crt0.S
@@ -126,3 +126,74 @@ RELACOUNT = 0x6ff9
 
/* Call start */
b   start
+
+#ifdef __powerpc64__
+
+#define PROM_FRAME_SIZE 512
+#define SAVE_GPR(n, base)   std n,8*(n)(base)
+#define REST_GPR(n, base)   ld  n,8*(n)(base)
+#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
+#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
+#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
+#define SAVE_10GPRS(n, base)SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
+#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
+#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
+#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
+#define REST_10GPRS(n, base)REST_8GPRS(n, base); REST_2GPRS(n+8, base)
+
+/* prom handles the jump into and return from firmware.  The prom args pointer
+   is loaded in r3. */
+.globl prom
+prom:
+   mflrr0
+   std r0,16(r1)
+   stdur1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
+
+   SAVE_GPR(2, r1)
+   SAVE_GPR(13, r1)
+   SAVE_8GPRS(14, r1)
+   SAVE_10GPRS(22, r1)
+   mfcrr10
+   std r10,8*32(r1)
+   mfmsr   r10
+   std r10,8*33(r1)
+
+   /* remove MSR_LE from msr but keep MSR_SF */
+   mfmsr   r10
+   rldicr  r10,r10,0,62
+   mtsrr1  r10
+
+   /* Load FW address, set LR to label 1, and jump to FW */
+   bl  0f
+0: mflrr10
+   addir11,r10,(1f-0b)
+   mtlrr11
+
+   ld  r10,(p_prom-0b)(r10)
+   mtsrr0  r10
+
+   rfid
+
+1: /* Return from OF */
+
+   /* Restore registers and return. */
+   rldicl  r1,r1,0,32
+
+   /* Restore the MSR (back to 64 bits) */
+   ld  r10,8*(33)(r1)
+   mtmsr   r10
+   isync
+
+   /* Restore other registers */
+   REST_GPR(2, r1)
+   REST_GPR(13, r1)
+   REST_8GPRS(14, r1)
+   REST_10GPRS(22, r1)
+   ld  r10,8*32(r1)
+   mtcrr10
+
+   addir1,r1,PROM_FRAME_SIZE
+   ld  r0,16(r1)
+   mtlrr0
+   blr
+#endif
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index cdfe762d2b2b..46c98a47d949 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -27,11 +27,17 @@ struct prom_args {
__be32 args[10];/* Input/output arguments. */
 };
 
+#ifdef __powerpc64__
+extern int prom(void *);
+#else
 static int (*prom) (void *);
+#endif
 
 void of_init(void *promptr)
 {
+#ifndef __powerpc64__
prom = (int (*)(void *))promptr;
+#endif
 }
 
 #define ADDR(x)(u32)(unsigned long)(x)
-- 
1.7.10.4

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev