@@ -29,5 +29,7 @@ void ibm440gx_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk,
unsigned int tmr_clk);
void ibm440spe_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk,
unsigned int tmr_clk);
+void ibm44x_le_kentry(unsigned long r3, unsigned long r4, void *r5,
+ kernel_entry_t kentry);
#endif /* _POWERPC_BOOT_4XX_H_ */
@@ -69,7 +69,7 @@ src-wlib := string.S crt0.S crtsavres.S stdio.c main.c \
gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
cpm-serial.c stdlib.c mpc52xx-psc.c planetcore.c uartlite.c \
- fsl-soc.c mpc8xx.c pq2.c ugecon.c
+ fsl-soc.c mpc8xx.c pq2.c ugecon.c le-44x.S
src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c \
cuboot-ebony.c cuboot-hotfoot.c treeboot-ebony.c prpmc2800.c \
ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
@@ -52,6 +52,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
CUBOOT_INIT();
platform_ops.fixups = taishan_fixups;
+ platform_ops.le_kentry = ibm44x_le_kentry;
fdt_init(_dtb_start);
serial_console_init();
}
new file mode 100644
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2010 Ian Munsie, IBM Corporation
+ *
+ * Assembly to begin executing a little endian kernel from a big endian boot
+ * wrapper. Uses a trampoline in address space 1 to update the E bit in each
+ * TLB entry of address space 0 before entering the kernel.
+ */
+
+#include "ppc_asm.h"
+
+#define __MASK(X) (1<<(X))
+
+#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
+#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
+
+#define MSR_IS __MASK(5) /* Instruction Space */
+#define MSR_DS __MASK(4) /* Data Space */
+
+#define PPC44x_TLB_PAGEID 0
+#define PPC44x_TLB_XLAT 1
+#define PPC44x_TLB_ATTRIB 2
+
+/* Page identification fields */
+#define PPC44x_TLB_VALID 0x00000200 /* Valid flag */
+#define PPC44x_TLB_TS 0x00000100 /* Translation address space */
+
+/* Storage attribute and access control fields */
+#define PPC44x_TLB_E 0x00000080 /* Memory is little endian */
+
+ .text
+ .global ibm44x_le_kentry
+ibm44x_le_kentry:
+ /* Find an invalid TLB entry we can use */
+ li r12,0 /* Start searching at TLB 0 */
+1: tlbre r10,r12,PPC44x_TLB_PAGEID /* Read TLB page ID word */
+ andi. r0,r10,PPC44x_TLB_VALID /* Test if TLB is valid */
+ beq 2f /* If not valid we are free to use it */
+ addi r12,r12,1 /* If valid, increment */
+ cmpwi r12,64 /* Have we reached the end of the TLBs? */
+ bne 1b /* If not, continue searching */
+ blr /* If so, no invalid TLB entries found :( Shouldn't happen AFAIK */
+
+ /* Locate TLB entry containing trampoline */
+2: lis r0,le_trampoline@h
+ ori r0,r0,le_trampoline@l
+ tlbsx r11,0,r0
+
+ /* Set free TLB to match our TLB, but with TS=1 */
+ tlbre r10,r11,PPC44x_TLB_XLAT
+ tlbwe r10,r12,PPC44x_TLB_XLAT
+ tlbre r10,r11,PPC44x_TLB_ATTRIB
+ tlbwe r10,r12,PPC44x_TLB_ATTRIB
+ tlbre r10,r11,PPC44x_TLB_PAGEID
+ ori r10,r10,PPC44x_TLB_TS
+ tlbwe r10,r12,PPC44x_TLB_PAGEID
+
+ /* Goto trampoline in address space 1 */
+ mtspr SPRN_SRR0,r0
+ mfmsr r0
+ ori r0,r0,MSR_IS | MSR_DS
+ mtspr SPRN_SRR1,r0
+ rfi
+
+le_trampoline:
+ /* Set E bit on all valid TLB entries with TS=0 */
+ li r12,0 /* Start searching at TLB 0 */
+1: tlbre r10,r12,PPC44x_TLB_PAGEID /* Read TLB page ID word */
+ andi. r0,r10,PPC44x_TLB_VALID /* Test if TLB is valid */
+ beq 2f /* If not valid, continue */
+ andi. r0,r10,PPC44x_TLB_TS /* If valid, test if TLB is TS=1 */
+ bne 2f /* If TS=1, continue */
+ tlbre r10,r12,PPC44x_TLB_ATTRIB /* If TS=0, read TLB attributes */
+ ori r10,r10,PPC44x_TLB_E /* Set little endian bit */
+ tlbwe r10,r12,PPC44x_TLB_ATTRIB /* Write attributes back */
+2: addi r12,r12,1 /* Increment */
+ cmpwi r12,64 /* Are we done? */
+ bne 1b /* If not, continue searching */
+
+ /* Goto kentry in address space 0 */
+ mtspr SPRN_SRR0,r6 /* arg 4 (kentry) */
+ mfmsr r11
+ li r12,MSR_IS | MSR_DS
+ andc r11,r11,r12
+ mtspr SPRN_SRR1,r11
+ rfi
@@ -49,6 +49,7 @@ config 44x
select 4xx_SOC
select PPC_PCI_CHOICE
select PHYS_64BIT
+ select ARCH_SUPPORTS_LITTLE_ENDIAN
config E200
bool "Freescale e200"