* [PATCH 03/18] powerpc: Support parsing a little endian kernel from zImage wrapper
From: Ian Munsie @ 2010-10-01 7:05 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, benh; +Cc: paulus, Ian Munsie
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
From: Ian Munsie <imunsie@au1.ibm.com>
This patch adds support to the PowerPC zImage wrapper (which always runs
in big endian mode) to detect if the zImage is little endian and parse
it's ELF header to enable it's successful extraction.
It also provides some infrastructure for executing a little endian
kernel - PowerPC platforms that support little endian should fill
platform_ops.le_kentry with a function pointer to the routine
responsible for switching the CPU to little endian and executing the
kernel. This routing takes the same arguments in the same positions as
kentry to allow them to easily be passed onto the kernel, with the
kentry pointer itself tacked on as argument 4.
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
arch/powerpc/boot/elf.h | 2 +-
arch/powerpc/boot/elf_util.c | 48 +++++++++++++++++++++++++++++++++++++---
arch/powerpc/boot/main.c | 26 +++++++++++++++++-----
arch/powerpc/boot/ops.h | 3 ++
arch/powerpc/boot/prpmc2800.c | 5 +++-
arch/powerpc/boot/swab.h | 26 ++++++++++++++++++++++
6 files changed, 98 insertions(+), 12 deletions(-)
create mode 100644 arch/powerpc/boot/swab.h
diff --git a/arch/powerpc/boot/elf.h b/arch/powerpc/boot/elf.h
index 1941bc5..9de8105 100644
--- a/arch/powerpc/boot/elf.h
+++ b/arch/powerpc/boot/elf.h
@@ -152,6 +152,6 @@ struct elf_info {
unsigned long elfoffset;
};
int parse_elf64(void *hdr, struct elf_info *info);
-int parse_elf32(void *hdr, struct elf_info *info);
+int parse_elf32(void *hdr, struct elf_info *info, int *little_endian);
#endif /* _PPC_BOOT_ELF_H_ */
diff --git a/arch/powerpc/boot/elf_util.c b/arch/powerpc/boot/elf_util.c
index 1567a0c..67bba80 100644
--- a/arch/powerpc/boot/elf_util.c
+++ b/arch/powerpc/boot/elf_util.c
@@ -14,6 +14,7 @@
#include "page.h"
#include "string.h"
#include "stdio.h"
+#include "swab.h"
int parse_elf64(void *hdr, struct elf_info *info)
{
@@ -47,7 +48,35 @@ int parse_elf64(void *hdr, struct elf_info *info)
return 1;
}
-int parse_elf32(void *hdr, struct elf_info *info)
+void byteswap_elf32(Elf32_Ehdr *elf32) {
+ Elf32_Phdr *elf32ph;
+
+ swab16s(&elf32->e_type);
+ swab16s(&elf32->e_machine);
+ swab32s(&elf32->e_version);
+ swab32s(&elf32->e_entry);
+ swab32s(&elf32->e_phoff);
+ swab32s(&elf32->e_shoff);
+ swab32s(&elf32->e_flags);
+ swab16s(&elf32->e_ehsize);
+ swab16s(&elf32->e_phentsize);
+ swab16s(&elf32->e_phnum);
+ swab16s(&elf32->e_shentsize);
+ swab16s(&elf32->e_shnum);
+ swab16s(&elf32->e_shstrndx);
+
+ elf32ph = (Elf32_Phdr *) ((unsigned long)elf32 + elf32->e_phoff);
+ swab32s(&elf32ph->p_type);
+ swab32s(&elf32ph->p_offset);
+ swab32s(&elf32ph->p_vaddr);
+ swab32s(&elf32ph->p_paddr);
+ swab32s(&elf32ph->p_filesz);
+ swab32s(&elf32ph->p_memsz);
+ swab32s(&elf32ph->p_flags);
+ swab32s(&elf32ph->p_align);
+}
+
+int parse_elf32(void *hdr, struct elf_info *info, int *little_endian)
{
Elf32_Ehdr *elf32 = hdr;
Elf32_Phdr *elf32ph;
@@ -57,9 +86,20 @@ int parse_elf32(void *hdr, struct elf_info *info)
elf32->e_ident[EI_MAG1] == ELFMAG1 &&
elf32->e_ident[EI_MAG2] == ELFMAG2 &&
elf32->e_ident[EI_MAG3] == ELFMAG3 &&
- elf32->e_ident[EI_CLASS] == ELFCLASS32 &&
- elf32->e_ident[EI_DATA] == ELFDATA2MSB &&
- (elf32->e_type == ET_EXEC ||
+ elf32->e_ident[EI_CLASS] == ELFCLASS32))
+ return 0;
+ switch(elf32->e_ident[EI_DATA]) {
+ case ELFDATA2MSB:
+ *little_endian = 0;
+ break;
+ case ELFDATA2LSB:
+ *little_endian = 1;
+ byteswap_elf32(elf32);
+ break;
+ default:
+ return 0;
+ }
+ if (!((elf32->e_type == ET_EXEC ||
elf32->e_type == ET_DYN) &&
elf32->e_machine == EM_PPC))
return 0;
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index a28f021..36dd2b6 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -27,7 +27,7 @@ struct addr_range {
#undef DEBUG
-static struct addr_range prep_kernel(void)
+static struct addr_range prep_kernel(int *little_endian)
{
char elfheader[256];
void *vmlinuz_addr = _vmlinux_start;
@@ -40,8 +40,10 @@ static struct addr_range prep_kernel(void)
gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size);
gunzip_exactly(&gzstate, elfheader, sizeof(elfheader));
- if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei))
+ if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei, little_endian))
fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
+ if (*little_endian && !platform_ops.le_kentry)
+ fatal("Little Endian kernel unsupported on this platform!");
if (platform_ops.image_hdr)
platform_ops.image_hdr(elfheader);
@@ -166,8 +168,10 @@ void start(void)
{
struct addr_range vmlinux, initrd;
kernel_entry_t kentry;
+ le_kernel_entry_t le_kentry;
unsigned long ft_addr = 0;
void *chosen;
+ int little_endian = 0;
/* Do this first, because malloc() could clobber the loader's
* command line. Only use the loader command line if a
@@ -189,7 +193,7 @@ void start(void)
if (!chosen)
chosen = create_node(NULL, "chosen");
- vmlinux = prep_kernel();
+ vmlinux = prep_kernel(&little_endian);
initrd = prep_initrd(vmlinux, chosen,
loader_info.initrd_addr, loader_info.initrd_size);
prep_cmdline(chosen);
@@ -206,11 +210,21 @@ void start(void)
console_ops.close();
kentry = (kernel_entry_t) vmlinux.addr;
+ le_kentry = (le_kernel_entry_t)platform_ops.le_kentry;
if (ft_addr)
- kentry(ft_addr, 0, NULL);
+ if (little_endian)
+ le_kentry(ft_addr, 0, NULL, kentry);
+ else
+ kentry(ft_addr, 0, NULL);
else
- kentry((unsigned long)initrd.addr, initrd.size,
- loader_info.promptr);
+ if (little_endian)
+ le_kentry((unsigned long)initrd.addr, initrd.size,
+ loader_info.promptr, kentry);
+ else
+ kentry((unsigned long)initrd.addr, initrd.size,
+ loader_info.promptr);
+
+ kentry(ft_addr, 0, NULL);
/* console closed so printf in fatal below may not work */
fatal("Error: Linux kernel returned to zImage boot wrapper!\n\r");
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index b3218ce..cd6c7bf 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -20,6 +20,8 @@
#define MAX_PROP_LEN 256 /* What should this be? */
typedef void (*kernel_entry_t)(unsigned long r3, unsigned long r4, void *r5);
+typedef void (*le_kernel_entry_t)(unsigned long r3, unsigned long r4, void *r5,
+ kernel_entry_t kentry);
/* Platform specific operations */
struct platform_ops {
@@ -30,6 +32,7 @@ struct platform_ops {
void * (*realloc)(void *ptr, unsigned long size);
void (*exit)(void);
void * (*vmlinux_alloc)(unsigned long size);
+ le_kernel_entry_t le_kentry;
};
extern struct platform_ops platform_ops;
diff --git a/arch/powerpc/boot/prpmc2800.c b/arch/powerpc/boot/prpmc2800.c
index da31d60..6bad899 100644
--- a/arch/powerpc/boot/prpmc2800.c
+++ b/arch/powerpc/boot/prpmc2800.c
@@ -519,6 +519,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
void *vmlinuz_addr = _vmlinux_start;
unsigned long vmlinuz_size = _vmlinux_end - _vmlinux_start;
char elfheader[256];
+ int little_endian;
if (dt_size <= 0) /* No fdt */
exit();
@@ -533,7 +534,9 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size);
gunzip_exactly(&gzstate, elfheader, sizeof(elfheader));
- if (!parse_elf32(elfheader, &ei))
+ if (!parse_elf32(elfheader, &ei, &little_endian))
+ exit();
+ if (little_endian)
exit();
heap_start = (char *)(ei.memsize + ei.elfoffset); /* end of kernel*/
diff --git a/arch/powerpc/boot/swab.h b/arch/powerpc/boot/swab.h
new file mode 100644
index 0000000..b122c2d
--- /dev/null
+++ b/arch/powerpc/boot/swab.h
@@ -0,0 +1,26 @@
+#ifndef _SWAB_H_
+#define _SWAB_H_
+
+#include "types.h"
+
+static __inline__ void st_le16(volatile u16 *addr, const u16 val)
+{
+ __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+static inline void swab16s(u16 *addr)
+{
+ st_le16(addr, *addr);
+}
+
+static __inline__ void st_le32(volatile u32 *addr, const u32 val)
+{
+ __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+static inline void swab32s(u32 *addr)
+{
+ st_le32(addr, *addr);
+}
+
+#endif
--
1.7.1
^ permalink raw reply related
* [PATCH 04/18] powerpc: Allow taishan platform to boot a little endian kernel
From: Ian Munsie @ 2010-10-01 7:05 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, benh
Cc: Albert Herranz, paulus, Ian Munsie, Torez Smith
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 6195 bytes --]
From: Ian Munsie <imunsie@au1.ibm.com>
This adds code to the boot wrapper to allow 44x CPUs to boot little
endian kernels. Presumably all 44x PowerPC platforms should also be able
to use this code unmodified, but this patch only wires up the taishan
platform as that has been tested.
The boot wrapper is still run in 32bit big endian mode and must set the
E bit in the TLB entries that the kernel may use initially. Naturally
the code setting this up can't afford to change the E bit on it's own
TLB entry while it is executing so it sets up a trampoline in address
space 1 to affect the change on all address space 0 TLB entries.
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
arch/powerpc/boot/4xx.h | 2 +
arch/powerpc/boot/Makefile | 2 +-
arch/powerpc/boot/cuboot-taishan.c | 1 +
arch/powerpc/boot/le-44x.S | 85 ++++++++++++++++++++++++++++++++
arch/powerpc/platforms/Kconfig.cputype | 1 +
5 files changed, 90 insertions(+), 1 deletions(-)
create mode 100644 arch/powerpc/boot/le-44x.S
diff --git a/arch/powerpc/boot/4xx.h b/arch/powerpc/boot/4xx.h
index 7dc5d45..05bc068 100644
--- a/arch/powerpc/boot/4xx.h
+++ b/arch/powerpc/boot/4xx.h
@@ -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_ */
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 79d7e69..c4b8616 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -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 \
diff --git a/arch/powerpc/boot/cuboot-taishan.c b/arch/powerpc/boot/cuboot-taishan.c
index 9bc906a..7fdd614 100644
--- a/arch/powerpc/boot/cuboot-taishan.c
+++ b/arch/powerpc/boot/cuboot-taishan.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();
}
diff --git a/arch/powerpc/boot/le-44x.S b/arch/powerpc/boot/le-44x.S
new file mode 100644
index 0000000..c8d2ee4
--- /dev/null
+++ b/arch/powerpc/boot/le-44x.S
@@ -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
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 074ff12..8ba962e 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -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"
--
1.7.1
^ permalink raw reply related
* [PATCH 05/18] powerpc: Wire up 44x little endian boot for remaining 44x targets
From: Ian Munsie @ 2010-10-01 7:05 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, benh; +Cc: paulus, Ian Munsie
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
From: Ian Munsie <imunsie@au1.ibm.com>
I haven't tested booting a little endian kernel on any of these targets,
but they all claim to be 44x so my little endian trampoline should work
on all of them, so wire it up on:
bamboo
katmai
kilauea
rainer
sam440ep
sequoia
warp
yosemite
ebony
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
arch/powerpc/boot/bamboo.c | 1 +
arch/powerpc/boot/cuboot-katmai.c | 1 +
arch/powerpc/boot/cuboot-kilauea.c | 1 +
arch/powerpc/boot/cuboot-rainier.c | 1 +
arch/powerpc/boot/cuboot-sam440ep.c | 1 +
arch/powerpc/boot/cuboot-sequoia.c | 1 +
arch/powerpc/boot/cuboot-warp.c | 1 +
arch/powerpc/boot/cuboot-yosemite.c | 1 +
arch/powerpc/boot/ebony.c | 1 +
9 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/boot/bamboo.c b/arch/powerpc/boot/bamboo.c
index b82cacb..547494b 100644
--- a/arch/powerpc/boot/bamboo.c
+++ b/arch/powerpc/boot/bamboo.c
@@ -41,6 +41,7 @@ void bamboo_init(void *mac0, void *mac1)
{
platform_ops.fixups = bamboo_fixups;
platform_ops.exit = ibm44x_dbcr_reset;
+ platform_ops.le_kentry = ibm44x_le_kentry;
bamboo_mac0 = mac0;
bamboo_mac1 = mac1;
fdt_init(_dtb_start);
diff --git a/arch/powerpc/boot/cuboot-katmai.c b/arch/powerpc/boot/cuboot-katmai.c
index 5434d70..c72bdbf 100644
--- a/arch/powerpc/boot/cuboot-katmai.c
+++ b/arch/powerpc/boot/cuboot-katmai.c
@@ -52,6 +52,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
CUBOOT_INIT();
platform_ops.fixups = katmai_fixups;
+ platform_ops.le_kentry = ibm44x_le_kentry;
fdt_init(_dtb_start);
serial_console_init();
}
diff --git a/arch/powerpc/boot/cuboot-kilauea.c b/arch/powerpc/boot/cuboot-kilauea.c
index 80cdad6..115048a 100644
--- a/arch/powerpc/boot/cuboot-kilauea.c
+++ b/arch/powerpc/boot/cuboot-kilauea.c
@@ -44,6 +44,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
CUBOOT_INIT();
platform_ops.fixups = kilauea_fixups;
platform_ops.exit = ibm40x_dbcr_reset;
+ platform_ops.le_kentry = ibm44x_le_kentry;
fdt_init(_dtb_start);
serial_console_init();
}
diff --git a/arch/powerpc/boot/cuboot-rainier.c b/arch/powerpc/boot/cuboot-rainier.c
index 0a3fdde..7c1ad02 100644
--- a/arch/powerpc/boot/cuboot-rainier.c
+++ b/arch/powerpc/boot/cuboot-rainier.c
@@ -52,6 +52,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
CUBOOT_INIT();
platform_ops.fixups = rainier_fixups;
platform_ops.exit = ibm44x_dbcr_reset;
+ platform_ops.le_kentry = ibm44x_le_kentry;
fdt_init(_dtb_start);
serial_console_init();
}
diff --git a/arch/powerpc/boot/cuboot-sam440ep.c b/arch/powerpc/boot/cuboot-sam440ep.c
index ec10a47..60761fd 100644
--- a/arch/powerpc/boot/cuboot-sam440ep.c
+++ b/arch/powerpc/boot/cuboot-sam440ep.c
@@ -44,6 +44,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
CUBOOT_INIT();
platform_ops.fixups = sam440ep_fixups;
platform_ops.exit = ibm44x_dbcr_reset;
+ platform_ops.le_kentry = ibm44x_le_kentry;
fdt_init(_dtb_start);
serial_console_init();
}
diff --git a/arch/powerpc/boot/cuboot-sequoia.c b/arch/powerpc/boot/cuboot-sequoia.c
index caf8f2e..3e93748 100644
--- a/arch/powerpc/boot/cuboot-sequoia.c
+++ b/arch/powerpc/boot/cuboot-sequoia.c
@@ -52,6 +52,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
CUBOOT_INIT();
platform_ops.fixups = sequoia_fixups;
platform_ops.exit = ibm44x_dbcr_reset;
+ platform_ops.le_kentry = ibm44x_le_kentry;
fdt_init(_dtb_start);
serial_console_init();
}
diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
index 806df69..8bdc383 100644
--- a/arch/powerpc/boot/cuboot-warp.c
+++ b/arch/powerpc/boot/cuboot-warp.c
@@ -33,6 +33,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
platform_ops.fixups = warp_fixups;
platform_ops.exit = ibm44x_dbcr_reset;
+ platform_ops.le_kentry = ibm44x_le_kentry;
fdt_init(_dtb_start);
serial_console_init();
}
diff --git a/arch/powerpc/boot/cuboot-yosemite.c b/arch/powerpc/boot/cuboot-yosemite.c
index cc6e338..7fe0e05 100644
--- a/arch/powerpc/boot/cuboot-yosemite.c
+++ b/arch/powerpc/boot/cuboot-yosemite.c
@@ -39,6 +39,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
CUBOOT_INIT();
platform_ops.fixups = yosemite_fixups;
platform_ops.exit = ibm44x_dbcr_reset;
+ platform_ops.le_kentry = ibm44x_le_kentry;
fdt_init(_dtb_start);
serial_console_init();
}
diff --git a/arch/powerpc/boot/ebony.c b/arch/powerpc/boot/ebony.c
index 5532ab3..6f302aa 100644
--- a/arch/powerpc/boot/ebony.c
+++ b/arch/powerpc/boot/ebony.c
@@ -85,6 +85,7 @@ void ebony_init(void *mac0, void *mac1)
{
platform_ops.fixups = ebony_fixups;
platform_ops.exit = ibm44x_dbcr_reset;
+ platform_ops.le_kentry = ibm44x_le_kentry;
ebony_mac0 = mac0;
ebony_mac1 = mac1;
fdt_init(_dtb_start);
--
1.7.1
^ permalink raw reply related
* [PATCH 07/18] powerpc: Use generic bitops for little endian bitmap operations
From: Ian Munsie @ 2010-10-01 7:06 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, benh; +Cc: paulus, Ian Munsie, Anton Blanchard
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
From: Ian Munsie <imunsie@au1.ibm.com>
With the little endian PowerPC Linux port, the CPU could be in either
mode. Rather than byte swapping and mapping the little endian bitmap
operations ourselves on the assumption that we are big endian, map them
to the generic macros that will automatically byte swap the bit number
only if we actually are big endian.
The generic bitops le.h already defines the macros/prototypes for the
generic_find_next_[zero_]le_bit appropriately for the current endian so
we can drop those prototypes altogether.
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
arch/powerpc/include/asm/bitops.h | 30 ++++++++++++------------------
1 files changed, 12 insertions(+), 18 deletions(-)
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
index 30964ae..066b2df 100644
--- a/arch/powerpc/include/asm/bitops.h
+++ b/arch/powerpc/include/asm/bitops.h
@@ -54,7 +54,6 @@
#define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
-#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7)
/* Macro for generating the ***_bits() functions */
#define DEFINE_BITOP(fn, op, prefix, postfix) \
@@ -272,34 +271,29 @@ static __inline__ int fls64(__u64 x)
/* Little-endian versions */
-static __inline__ int test_le_bit(unsigned long nr,
- __const__ unsigned long *addr)
-{
- __const__ unsigned char *tmp = (__const__ unsigned char *) addr;
- return (tmp[nr >> 3] >> (nr & 7)) & 1;
-}
+#include <asm-generic/bitops/le.h>
+
+#define test_le_bit(nr, addr) \
+ generic_test_le_bit(nr, addr)
#define __set_le_bit(nr, addr) \
- __set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+ generic__set_le_bit(nr, addr)
#define __clear_le_bit(nr, addr) \
- __clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+ generic__clear_le_bit(nr, addr)
#define test_and_set_le_bit(nr, addr) \
- test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+ generic_test_and_set_le_bit(nr, addr)
#define test_and_clear_le_bit(nr, addr) \
- test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+ generic_test_and_clear_le_bit(nr, addr)
#define __test_and_set_le_bit(nr, addr) \
- __test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+ generic__test_and_set_le_bit(nr, addr)
#define __test_and_clear_le_bit(nr, addr) \
- __test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+ generic__test_and_clear_le_bit(nr, addr)
-#define find_first_zero_le_bit(addr, size) generic_find_next_zero_le_bit((addr), (size), 0)
-unsigned long generic_find_next_zero_le_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset);
+#define find_first_zero_le_bit(addr, size) \
+ generic_find_first_zero_le_bit(addr, size)
-unsigned long generic_find_next_le_bit(const unsigned long *addr,
- unsigned long size, unsigned long offset);
/* Bitmap functions for the ext2 filesystem */
#define ext2_set_bit(nr,addr) \
--
1.7.1
^ permalink raw reply related
* [PATCH 06/18] powerpc 44x: Set E bit in TLBs and PTEs when CPU is in little endian mode
From: Ian Munsie @ 2010-10-01 7:05 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, benh
Cc: Stephen Rothwell, Dave Kleikamp, Ian Munsie, paulus, Torez Smith
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
From: Ian Munsie <imunsie@au1.ibm.com>
The endianness on the 44x CPUs is controlled by the E bit in the TLB
entries. If the kernel has been compiled for little endian this patch
sets this E bit wherever they are set - in the PTE base flags, the early
debugging, and TLB pinning.
It defines some _PAGE_CPUENDIAN and ..._TLB_CPUE macros which are set
if the CPU is little endian or 0 if the CPU is big endian so these can
be used to easily set the E bit only if the CPU is little endian.
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
arch/powerpc/include/asm/mmu-44x.h | 12 ++++++++++++
arch/powerpc/include/asm/pte-44x.h | 4 ++++
arch/powerpc/include/asm/pte-common.h | 9 ++++++---
arch/powerpc/kernel/head_44x.S | 6 +++---
arch/powerpc/mm/44x_mmu.c | 4 ++--
5 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/include/asm/mmu-44x.h b/arch/powerpc/include/asm/mmu-44x.h
index bf52d70..e96f5c3 100644
--- a/arch/powerpc/include/asm/mmu-44x.h
+++ b/arch/powerpc/include/asm/mmu-44x.h
@@ -42,6 +42,12 @@
#define PPC44x_TLB_G 0x00000100 /* Memory is guarded */
#define PPC44x_TLB_E 0x00000080 /* Memory is little endian */
+#ifdef __LITTLE_ENDIAN__
+#define PPC44x_TLB_CPUE PPC44x_TLB_E
+#else
+#define PPC44x_TLB_CPUE 0
+#endif
+
#define PPC44x_TLB_PERM_MASK 0x0000003f
#define PPC44x_TLB_UX 0x00000020 /* User execution */
#define PPC44x_TLB_UW 0x00000010 /* User write */
@@ -99,6 +105,12 @@
#define PPC47x_TLB2_S_RW (PPC47x_TLB2_SW | PPC47x_TLB2_SR)
#define PPC47x_TLB2_IMG (PPC47x_TLB2_I | PPC47x_TLB2_M | PPC47x_TLB2_G)
+#ifdef __LITTLE_ENDIAN__
+#define PPC47x_TLB2_CPUE PPC47x_TLB2_E
+#else
+#define PPC47x_TLB2_CPUE 0
+#endif
+
#ifndef __ASSEMBLY__
extern unsigned int tlb_44x_hwater;
diff --git a/arch/powerpc/include/asm/pte-44x.h b/arch/powerpc/include/asm/pte-44x.h
index 4192b9b..9c79a85 100644
--- a/arch/powerpc/include/asm/pte-44x.h
+++ b/arch/powerpc/include/asm/pte-44x.h
@@ -89,6 +89,10 @@
#define _PAGE_NO_CACHE 0x00000400 /* H: I bit */
#define _PAGE_WRITETHRU 0x00000800 /* H: W bit */
+#ifdef __LITTLE_ENDIAN__
+#define _PAGE_CPUENDIAN _PAGE_ENDIAN
+#endif
+
/* TODO: Add large page lowmem mapping support */
#define _PMD_PRESENT 0
#define _PMD_PRESENT_MASK (PAGE_MASK)
diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h
index f2b3701..b69609c 100644
--- a/arch/powerpc/include/asm/pte-common.h
+++ b/arch/powerpc/include/asm/pte-common.h
@@ -19,6 +19,9 @@
#ifndef _PAGE_ENDIAN
#define _PAGE_ENDIAN 0
#endif
+#ifndef _PAGE_CPUENDIAN
+#define _PAGE_CPUENDIAN 0
+#endif
#ifndef _PAGE_COHERENT
#define _PAGE_COHERENT 0
#endif
@@ -104,11 +107,11 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
* pages. We always set _PAGE_COHERENT when SMP is enabled or
* the processor might need it for DMA coherency.
*/
-#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE)
+#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE | _PAGE_CPUENDIAN)
#if defined(CONFIG_SMP) || defined(CONFIG_PPC_STD_MMU)
-#define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT)
+#define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT | _PAGE_CPUENDIAN)
#else
-#define _PAGE_BASE (_PAGE_BASE_NC)
+#define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_CPUENDIAN)
#endif
/* Permission masks used to generate the __P and __S table,
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index 562305b..6198733 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -813,7 +813,7 @@ skpinv: addi r4,r4,1 /* Increment */
/* attrib fields */
/* Added guarded bit to protect against speculative loads/stores */
li r5,0
- ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
+ ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G | PPC44x_TLB_CPUE)
li r0,63 /* TLB slot 63 */
@@ -850,7 +850,7 @@ skpinv: addi r4,r4,1 /* Increment */
ori r4,r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH
/* attrib fields */
- li r5,(PPC44x_TLB_SW|PPC44x_TLB_SR|PPC44x_TLB_I|PPC44x_TLB_G)
+ li r5,(PPC44x_TLB_SW|PPC44x_TLB_SR|PPC44x_TLB_I|PPC44x_TLB_G|PPC44x_TLB_CPUE)
li r0,62 /* TLB slot 0 */
tlbwe r3,r0,PPC44x_TLB_PAGEID
@@ -1068,7 +1068,7 @@ clear_utlb_entry:
ori r4,r4,CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH
/* Word 2 */
- li r5,(PPC47x_TLB2_S_RW | PPC47x_TLB2_IMG)
+ li r5,(PPC47x_TLB2_S_RW | PPC47x_TLB2_IMG | PPC47x_TLB2_CPUE)
/* Bolted in way 0, bolt slot 5, we -hope- we don't hit the same
* congruence class as the kernel, we need to make sure of it at
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index d8c6efb..70760e7 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -79,7 +79,7 @@ static void __init ppc44x_pin_tlb(unsigned int virt, unsigned int phys)
#ifdef CONFIG_PPC47x
: "r" (PPC47x_TLB2_S_RWX),
#else
- : "r" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G),
+ : "r" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G | PPC44x_TLB_CPUE),
#endif
"r" (phys),
"r" (virt | PPC44x_TLB_VALID | PPC44x_TLB_256M),
@@ -163,7 +163,7 @@ static void __cpuinit ppc47x_pin_tlb(unsigned int virt, unsigned int phys)
"tlbwe %0,%3,2\n"
:
: "r" (PPC47x_TLB2_SW | PPC47x_TLB2_SR |
- PPC47x_TLB2_SX
+ PPC47x_TLB2_SX | PPC47x_TLB2_CPUE
#ifdef CONFIG_SMP
| PPC47x_TLB2_M
#endif
--
1.7.1
^ permalink raw reply related
* [PATCH 08/18] powerpc: Include the appropriate endianness header
From: Ian Munsie @ 2010-10-01 7:06 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, benh; +Cc: paulus, Ian Munsie
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
From: Ian Munsie <imunsie@au1.ibm.com>
This patch will have powerpc include the appropriate generic endianness
header depending on what the compiler reports.
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
arch/powerpc/include/asm/byteorder.h | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/include/asm/byteorder.h b/arch/powerpc/include/asm/byteorder.h
index aa6cc4f..ca931d0 100644
--- a/arch/powerpc/include/asm/byteorder.h
+++ b/arch/powerpc/include/asm/byteorder.h
@@ -7,6 +7,10 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+#ifdef __LITTLE_ENDIAN__
+#include <linux/byteorder/little_endian.h>
+#else
#include <linux/byteorder/big_endian.h>
+#endif
#endif /* _ASM_POWERPC_BYTEORDER_H */
--
1.7.1
^ permalink raw reply related
* [PATCH 10/18] powerpc: Support endian agnostic MMIO
From: Ian Munsie @ 2010-10-01 7:06 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, benh; +Cc: paulus, Ian Munsie
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
From: Ian Munsie <imunsie@au1.ibm.com>
This patch maps the MMIO functions for 32bit PowerPC to their
appropriate instructions depending on CPU endianness.
The macros used to create the corresponding inline functions are also
renamed by this patch. Previously they had BE or LE in their names which
was misleading - they had nothing to do with endianness, but actually
created different instruction forms so their new names reflect the
instruction form they are creating (D-Form and X-Form).
Little endian 64bit PowerPC is not supported, so the lack of mappings
(and corresponding breakage) for that case is intentional to bring the
attention of anyone doing a 64bit little endian port. 64bit big endian
is unaffected.
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
arch/powerpc/include/asm/io.h | 51 ++++++++++++++++++++++++++--------------
1 files changed, 33 insertions(+), 18 deletions(-)
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index 001f2f1..fd8e922 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -97,7 +97,7 @@ extern resource_size_t isa_mem_base;
/* gcc 4.0 and older doesn't have 'Z' constraint */
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
-#define DEF_MMIO_IN_LE(name, size, insn) \
+#define DEF_MMIO_IN_X(name, size, insn) \
static inline u##size name(const volatile u##size __iomem *addr) \
{ \
u##size ret; \
@@ -106,7 +106,7 @@ static inline u##size name(const volatile u##size __iomem *addr) \
return ret; \
}
-#define DEF_MMIO_OUT_LE(name, size, insn) \
+#define DEF_MMIO_OUT_X(name, size, insn) \
static inline void name(volatile u##size __iomem *addr, u##size val) \
{ \
__asm__ __volatile__("sync;"#insn" %1,0,%2" \
@@ -114,7 +114,7 @@ static inline void name(volatile u##size __iomem *addr, u##size val) \
IO_SET_SYNC_FLAG(); \
}
#else /* newer gcc */
-#define DEF_MMIO_IN_LE(name, size, insn) \
+#define DEF_MMIO_IN_X(name, size, insn) \
static inline u##size name(const volatile u##size __iomem *addr) \
{ \
u##size ret; \
@@ -123,7 +123,7 @@ static inline u##size name(const volatile u##size __iomem *addr) \
return ret; \
}
-#define DEF_MMIO_OUT_LE(name, size, insn) \
+#define DEF_MMIO_OUT_X(name, size, insn) \
static inline void name(volatile u##size __iomem *addr, u##size val) \
{ \
__asm__ __volatile__("sync;"#insn" %1,%y0" \
@@ -132,7 +132,7 @@ static inline void name(volatile u##size __iomem *addr, u##size val) \
}
#endif
-#define DEF_MMIO_IN_BE(name, size, insn) \
+#define DEF_MMIO_IN_D(name, size, insn) \
static inline u##size name(const volatile u##size __iomem *addr) \
{ \
u##size ret; \
@@ -141,7 +141,7 @@ static inline u##size name(const volatile u##size __iomem *addr) \
return ret; \
}
-#define DEF_MMIO_OUT_BE(name, size, insn) \
+#define DEF_MMIO_OUT_D(name, size, insn) \
static inline void name(volatile u##size __iomem *addr, u##size val) \
{ \
__asm__ __volatile__("sync;"#insn"%U0%X0 %1,%0" \
@@ -149,22 +149,37 @@ static inline void name(volatile u##size __iomem *addr, u##size val) \
IO_SET_SYNC_FLAG(); \
}
+DEF_MMIO_IN_D(in_8, 8, lbz);
+DEF_MMIO_OUT_D(out_8, 8, stb);
-DEF_MMIO_IN_BE(in_8, 8, lbz);
-DEF_MMIO_IN_BE(in_be16, 16, lhz);
-DEF_MMIO_IN_BE(in_be32, 32, lwz);
-DEF_MMIO_IN_LE(in_le16, 16, lhbrx);
-DEF_MMIO_IN_LE(in_le32, 32, lwbrx);
+#ifdef __BIG_ENDIAN__
+DEF_MMIO_IN_D(in_be16, 16, lhz);
+DEF_MMIO_IN_D(in_be32, 32, lwz);
+DEF_MMIO_IN_X(in_le16, 16, lhbrx);
+DEF_MMIO_IN_X(in_le32, 32, lwbrx);
-DEF_MMIO_OUT_BE(out_8, 8, stb);
-DEF_MMIO_OUT_BE(out_be16, 16, sth);
-DEF_MMIO_OUT_BE(out_be32, 32, stw);
-DEF_MMIO_OUT_LE(out_le16, 16, sthbrx);
-DEF_MMIO_OUT_LE(out_le32, 32, stwbrx);
+DEF_MMIO_OUT_D(out_be16, 16, sth);
+DEF_MMIO_OUT_D(out_be32, 32, stw);
+DEF_MMIO_OUT_X(out_le16, 16, sthbrx);
+DEF_MMIO_OUT_X(out_le32, 32, stwbrx);
+#else
+DEF_MMIO_IN_X(in_be16, 16, lhbrx);
+DEF_MMIO_IN_X(in_be32, 32, lwbrx);
+DEF_MMIO_IN_D(in_le16, 16, lhz);
+DEF_MMIO_IN_D(in_le32, 32, lwz);
+
+DEF_MMIO_OUT_X(out_be16, 16, sthbrx);
+DEF_MMIO_OUT_X(out_be32, 32, stwbrx);
+DEF_MMIO_OUT_D(out_le16, 16, sth);
+DEF_MMIO_OUT_D(out_le32, 32, stw);
+#endif /* __BIG_ENDIAN */
#ifdef __powerpc64__
-DEF_MMIO_OUT_BE(out_be64, 64, std);
-DEF_MMIO_IN_BE(in_be64, 64, ld);
+
+#ifndef __LITTLE_ENDIAN__
+DEF_MMIO_OUT_D(out_be64, 64, std);
+DEF_MMIO_IN_D(in_be64, 64, ld);
+#endif
/* There is no asm instructions for 64 bits reverse loads and stores */
static inline u64 in_le64(const volatile u64 __iomem *addr)
--
1.7.1
^ permalink raw reply related
* [PATCH 11/18] powerpc: Make assembly endian agnostic when accessing 64bit values
From: Ian Munsie @ 2010-10-01 7:06 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, benh
Cc: paulus, Ian Munsie, Matthew McClintock, Torez Smith
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
From: Ian Munsie <imunsie@au1.ibm.com>
The 32bit PowerPC ABI states that when passing arguments and return
values via registers a value of type long long is stored in pairs of
registers as follows:
The lower addressed word is stored in the next available odd numbered
register and the higher addressed value is stored in register+1.
i.e. the values will either be stored in the next available of:
r3/r4, r5/r6, r7/r8 or r9/r10
Since the lower addressed value must be in the lower register number we
have an endianness issue and need to treat this specially in any
assembly that is passed or returns a 64bit value.
This patch introduces some aliases in ppc_asm.h which will select the
appropriate register from the pair depending on the CPU endianness.
There are in the form of r34l for the low word from the r3/r4 pair and
r34h for the high word and so on for the remaining register pairs.
It also introduces p64l and p64h which can be used to select the
appropriate offset whenever loading a 32bit word while referring to the
address of a 64bit value. For instance if r3 contains the address of a
64bit value the following assembly would load the high word into r5 and
the low word into r6 regardless of endianness:
lwz r5,p64h(r3)
lwz r6,p64l(r3)
Finally, the patch also alters the functions in misc_32.S that take
64bit arguments to use these new accessors to work on the little endian
PowerPC architecture:
mulhdu, __div64_32, __ashrdi3, __ashldi3, __lshrdi3 and __ucmpdi2
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
arch/powerpc/include/asm/ppc_asm.h | 24 ++++++++++++
arch/powerpc/kernel/misc_32.S | 72 ++++++++++++++++++------------------
arch/powerpc/lib/div64.S | 8 ++--
3 files changed, 64 insertions(+), 40 deletions(-)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 9821006..6929483 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -510,6 +510,30 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
#define r30 30
#define r31 31
+/* Endian agnostic accessors for 64 bit values passed and returned in GPRs */
+#ifdef __BIG_ENDIAN__
+#define r34l r4
+#define r34h r3
+#define r56l r6
+#define r56h r5
+#define r78l r8
+#define r78h r7
+
+/* Endian agnostic accessors for pointer offsets to 64 bit values */
+#define p64l 4
+#define p64h 0
+#else
+#define r34l r3
+#define r34h r4
+#define r56l r5
+#define r56h r6
+#define r78l r7
+#define r78h r8
+
+#define p64l 0
+#define p64h 4
+#endif
+
/* Floating Point Registers (FPRs) */
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index a7a570d..6c40079 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -60,27 +60,27 @@ _GLOBAL(call_handle_irq)
* This returns the high 64 bits of the product of two 64-bit numbers.
*/
_GLOBAL(mulhdu)
- cmpwi r6,0
- cmpwi cr1,r3,0
- mr r10,r4
- mulhwu r4,r4,r5
+ cmpwi r56l,0
+ cmpwi cr1,r34h,0
+ mr r10,r34l
+ mulhwu r34l,r34l,r56h
beq 1f
- mulhwu r0,r10,r6
- mullw r7,r10,r5
+ mulhwu r0,r10,r56l
+ mullw r7,r10,r56h
addc r7,r0,r7
- addze r4,r4
+ addze r34l,r34l
1: beqlr cr1 /* all done if high part of A is 0 */
- mr r10,r3
- mullw r9,r3,r5
- mulhwu r3,r3,r5
+ mr r10,r34h
+ mullw r9,r34h,r56h
+ mulhwu r34h,r34h,r56h
beq 2f
- mullw r0,r10,r6
- mulhwu r8,r10,r6
+ mullw r0,r10,r56l
+ mulhwu r8,r10,r56l
addc r7,r0,r7
- adde r4,r4,r8
- addze r3,r3
-2: addc r4,r4,r9
- addze r3,r3
+ adde r34l,r34l,r8
+ addze r34h,r34h
+2: addc r34l,r34l,r9
+ addze r34h,r34h
blr
/*
@@ -606,37 +606,37 @@ _GLOBAL(atomic_set_mask)
*/
_GLOBAL(__ashrdi3)
subfic r6,r5,32
- srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ srw r34l,r34l,r5 # LSW = count > 31 ? 0 : LSW >> count
addi r7,r5,32 # could be xori, or addi with -32
- slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ slw r6,r34h,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
- sraw r7,r3,r7 # t2 = MSW >> (count-32)
- or r4,r4,r6 # LSW |= t1
+ sraw r7,r34h,r7 # t2 = MSW >> (count-32)
+ or r34l,r34l,r6 # LSW |= t1
slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
- sraw r3,r3,r5 # MSW = MSW >> count
- or r4,r4,r7 # LSW |= t2
+ sraw r34h,r34h,r5 # MSW = MSW >> count
+ or r34l,r34l,r7 # LSW |= t2
blr
_GLOBAL(__ashldi3)
subfic r6,r5,32
- slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
+ slw r34h,r34h,r5 # MSW = count > 31 ? 0 : MSW << count
addi r7,r5,32 # could be xori, or addi with -32
- srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
- slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
- or r3,r3,r6 # MSW |= t1
- slw r4,r4,r5 # LSW = LSW << count
- or r3,r3,r7 # MSW |= t2
+ srw r6,r34l,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
+ slw r7,r34l,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
+ or r34h,r34h,r6 # MSW |= t1
+ slw r34l,r34l,r5 # LSW = LSW << count
+ or r34h,r34h,r7 # MSW |= t2
blr
_GLOBAL(__lshrdi3)
subfic r6,r5,32
- srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ srw r34l,r34l,r5 # LSW = count > 31 ? 0 : LSW >> count
addi r7,r5,32 # could be xori, or addi with -32
- slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
- srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
- or r4,r4,r6 # LSW |= t1
- srw r3,r3,r5 # MSW = MSW >> count
- or r4,r4,r7 # LSW |= t2
+ slw r6,r34h,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ srw r7,r34h,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
+ or r34l,r34l,r6 # LSW |= t1
+ srw r34h,r34h,r5 # MSW = MSW >> count
+ or r34l,r34l,r7 # LSW |= t2
blr
/*
@@ -644,10 +644,10 @@ _GLOBAL(__lshrdi3)
* Returns 0 if a < b, 1 if a == b, 2 if a > b.
*/
_GLOBAL(__ucmpdi2)
- cmplw r3,r5
+ cmplw r34h,r56h
li r3,1
bne 1f
- cmplw r4,r6
+ cmplw r34l,r56l
beqlr
1: li r3,0
bltlr
diff --git a/arch/powerpc/lib/div64.S b/arch/powerpc/lib/div64.S
index 83d9832..12f2da4 100644
--- a/arch/powerpc/lib/div64.S
+++ b/arch/powerpc/lib/div64.S
@@ -17,8 +17,8 @@
#include <asm/processor.h>
_GLOBAL(__div64_32)
- lwz r5,0(r3) # get the dividend into r5/r6
- lwz r6,4(r3)
+ lwz r5,p64h(r3) # get the dividend into r5/r6
+ lwz r6,p64l(r3)
cmplw r5,r4
li r7,0
li r8,0
@@ -53,7 +53,7 @@ _GLOBAL(__div64_32)
mullw r10,r0,r4 # and get the remainder
add r8,r8,r0
subf r6,r10,r6
-4: stw r7,0(r3) # return the quotient in *r3
- stw r8,4(r3)
+4: stw r7,p64h(r3) # return the quotient in *r3
+ stw r8,p64l(r3)
mr r3,r6 # return the remainder in r3
blr
--
1.7.1
^ permalink raw reply related
* [PATCH 12/18] powerpc 44x: Handle TLB miss regardless of endianness
From: Ian Munsie @ 2010-10-01 7:06 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, benh
Cc: Dave Kleikamp, paulus, Ian Munsie, Torez Smith
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
From: Ian Munsie <imunsie@au1.ibm.com>
On the 44x we use 64bit page table entries, but the CPU is only 32bit.
When a PTE is loaded during a TLB miss each half is loaded into
different registers, so we need to reverse the offsets if the CPU is
running in little endian mode.
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
arch/powerpc/kernel/head_44x.S | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index 6198733..d4c144f 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -258,8 +258,8 @@ interrupt_base:
/* Compute pte address */
rlwimi r12, r10, PPC44x_PTE_ADD_SHIFT, PPC44x_PTE_ADD_MASK_BIT, 28
- lwz r11, 0(r12) /* Get high word of pte entry */
- lwz r12, 4(r12) /* Get low word of pte entry */
+ lwz r11, p64h(r12) /* Get high word of pte entry */
+ lwz r12, p64l(r12) /* Get low word of pte entry */
lis r10,tlb_44x_index@ha
@@ -354,8 +354,8 @@ tlb_44x_patch_hwater_D:
/* Compute pte address */
rlwimi r12, r10, PPC44x_PTE_ADD_SHIFT, PPC44x_PTE_ADD_MASK_BIT, 28
- lwz r11, 0(r12) /* Get high word of pte entry */
- lwz r12, 4(r12) /* Get low word of pte entry */
+ lwz r11, p64h(r12) /* Get high word of pte entry */
+ lwz r12, p64l(r12) /* Get low word of pte entry */
lis r10,tlb_44x_index@ha
--
1.7.1
^ permalink raw reply related
* [PATCH 16/18] powerpc: Fix endianness issues in alignment handler
From: Ian Munsie @ 2010-10-01 7:06 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, benh
Cc: Andreas Schwab, Michael Neuling, paulus, Ian Munsie,
Anton Blanchard
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
From: Ian Munsie <imunsie@au1.ibm.com>
This patch reverses the order of the high and low bits in the alignment
handler on little endian, which should be enough to fix any alignment
exceptions.
Please note that this patch is largely untested.
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
arch/powerpc/kernel/align.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 8184ee9..fc357c6 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -712,12 +712,22 @@ int fix_alignment(struct pt_regs *regs)
double dd;
unsigned char v[8];
struct {
+#ifdef __LITTLE_ENDIAN__
+ int low32;
+ unsigned hi32;
+#else
unsigned hi32;
int low32;
+#endif
} x32;
struct {
+#ifdef __LITTLE_ENDIAN__
+ short low16;
+ unsigned char hi48[6];
+#else
unsigned char hi48[6];
short low16;
+#endif
} x16;
} data;
--
1.7.1
^ permalink raw reply related
* [PATCH 15/18] mtd: Fix endianness issues from device tree
From: Ian Munsie @ 2010-10-01 7:06 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, benh
Cc: Jason Gunthorpe, Artem Bityutskiy, H Hartley Sweeten,
Julia Lawall, Ian Munsie, linux-mtd, Sean MacLennan, Tejun Heo,
paulus, Steve Deiters, Anatolij Gustschin, David Woodhouse,
David S. Miller
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
From: Ian Munsie <imunsie@au1.ibm.com>
This patch adds the appropriate conversions to correct the endianness
issues in the MTD driver whenever it accesses the device tree (which is
always big endian).
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
drivers/mtd/maps/physmap_of.c | 14 +++++++-------
drivers/mtd/nand/fsl_upm.c | 8 ++++----
drivers/mtd/nand/mpc5121_nfc.c | 4 ++--
drivers/mtd/nand/ndfc.c | 8 ++++----
drivers/mtd/ofpart.c | 6 +++---
5 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index fe63f6b..ec4011c 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -50,7 +50,7 @@ static int parse_obsolete_partitions(struct platform_device *dev,
{
int i, plen, nr_parts;
const struct {
- u32 offset, len;
+ __be32 offset, len;
} *part;
const char *names;
@@ -69,9 +69,9 @@ static int parse_obsolete_partitions(struct platform_device *dev,
names = of_get_property(dp, "partition-names", &plen);
for (i = 0; i < nr_parts; i++) {
- info->parts[i].offset = part->offset;
- info->parts[i].size = part->len & ~1;
- if (part->len & 1) /* bit 0 set signifies read only partition */
+ info->parts[i].offset = be32_to_cpu(part->offset);
+ info->parts[i].size = be32_to_cpu(part->len) & ~1;
+ if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */
info->parts[i].mask_flags = MTD_WRITEABLE;
if (names && (plen > 0)) {
@@ -226,11 +226,11 @@ static int __devinit of_flash_probe(struct platform_device *dev,
struct resource res;
struct of_flash *info;
const char *probe_type = match->data;
- const u32 *width;
+ const __be32 *width;
int err;
int i;
int count;
- const u32 *p;
+ const __be32 *p;
int reg_tuple_size;
struct mtd_info **mtd_list = NULL;
resource_size_t res_size;
@@ -294,7 +294,7 @@ static int __devinit of_flash_probe(struct platform_device *dev,
info->list[i].map.name = dev_name(&dev->dev);
info->list[i].map.phys = res.start;
info->list[i].map.size = res_size;
- info->list[i].map.bankwidth = *width;
+ info->list[i].map.bankwidth = be32_to_cpup(width);
err = -ENOMEM;
info->list[i].map.virt = ioremap(info->list[i].map.phys,
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 4eff8b2..8da9014 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -222,7 +222,7 @@ static int __devinit fun_probe(struct platform_device *ofdev,
{
struct fsl_upm_nand *fun;
struct resource io_res;
- const uint32_t *prop;
+ const __be32 *prop;
int rnb_gpio;
int ret;
int size;
@@ -270,7 +270,7 @@ static int __devinit fun_probe(struct platform_device *ofdev,
goto err1;
}
for (i = 0; i < fun->mchip_count; i++)
- fun->mchip_offsets[i] = prop[i];
+ fun->mchip_offsets[i] = be32_to_cpu(prop[i]);
} else {
fun->mchip_count = 1;
}
@@ -295,13 +295,13 @@ static int __devinit fun_probe(struct platform_device *ofdev,
prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL);
if (prop)
- fun->chip_delay = *prop;
+ fun->chip_delay = be32_to_cpup(prop);
else
fun->chip_delay = 50;
prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size);
if (prop && size == sizeof(uint32_t))
- fun->wait_flags = *prop;
+ fun->wait_flags = be32_to_cpup(prop);
else
fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN |
FSL_UPM_WAIT_WRITE_BYTE;
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index df0c1da..aeb27a1 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -660,7 +660,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op,
#endif
struct nand_chip *chip;
unsigned long regs_paddr, regs_size;
- const uint *chips_no;
+ const __be32 *chips_no;
int resettime = 0;
int retval = 0;
int rev, len;
@@ -803,7 +803,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op,
}
/* Detect NAND chips */
- if (nand_scan(mtd, *chips_no)) {
+ if (nand_scan(mtd, be32_to_cpup(chips_no))) {
dev_err(dev, "NAND Flash not found !\n");
devm_free_irq(dev, prv->irq, mtd);
retval = -ENXIO;
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 510554e..c9ae0a5 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -229,7 +229,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev,
const struct of_device_id *match)
{
struct ndfc_controller *ndfc = &ndfc_ctrl;
- const u32 *reg;
+ const __be32 *reg;
u32 ccr;
int err, len;
@@ -244,7 +244,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev,
dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
return -ENOENT;
}
- ndfc->chip_select = reg[0];
+ ndfc->chip_select = be32_to_cpu(reg[0]);
ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0);
if (!ndfc->ndfcbase) {
@@ -257,7 +257,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev,
/* It is ok if ccr does not exist - just default to 0 */
reg = of_get_property(ofdev->dev.of_node, "ccr", NULL);
if (reg)
- ccr |= *reg;
+ ccr |= be32_to_cpup(reg);
out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
@@ -265,7 +265,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev,
reg = of_get_property(ofdev->dev.of_node, "bank-settings", NULL);
if (reg) {
int offset = NDFC_BCFG0 + (ndfc->chip_select << 2);
- out_be32(ndfc->ndfcbase + offset, *reg);
+ out_be32(ndfc->ndfcbase + offset, be32_to_cpup(reg));
}
err = ndfc_chip_init(ndfc, ofdev->dev.of_node);
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 8bf7dc6..a996718 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -44,7 +44,7 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
pp = NULL;
i = 0;
while ((pp = of_get_next_child(node, pp))) {
- const u32 *reg;
+ const __be32 *reg;
int len;
reg = of_get_property(pp, "reg", &len);
@@ -53,8 +53,8 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
continue;
}
- (*pparts)[i].offset = reg[0];
- (*pparts)[i].size = reg[1];
+ (*pparts)[i].offset = be32_to_cpu(reg[0]);
+ (*pparts)[i].size = be32_to_cpu(reg[1]);
partname = of_get_property(pp, "label", &len);
if (!partname)
--
1.7.1
^ permalink raw reply related
* [PATCH 18/18] powerpc: Fix jiffies variable on little endian
From: Ian Munsie @ 2010-10-01 7:06 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev, benh
Cc: Michal Marek, Denys Vlasenko, Rusty Russell, Tim Abbott, paulus,
Ian Munsie, Sean MacLennan
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
From: Ian Munsie <imunsie@au1.ibm.com>
The vmlinux linker script sets the jiffies variable to the low word of
the jiffies_64 variable. This patch corrects which word is used on
little endian.
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
---
arch/powerpc/kernel/vmlinux.lds.S | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 8a0deef..7a9010f 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -34,8 +34,12 @@ OUTPUT_ARCH(powerpc:common64)
jiffies = jiffies_64;
#else
OUTPUT_ARCH(powerpc:common)
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+jiffies = jiffies_64;
+#else
jiffies = jiffies_64 + 4;
#endif
+#endif
SECTIONS
{
. = 0;
--
1.7.1
^ permalink raw reply related
* Re: [PATCH 02/18] powerpc: Add CROSSBE_COMPILE to build big endian boot wrapper
From: Geert Uytterhoeven @ 2010-10-01 7:13 UTC (permalink / raw)
To: Ian Munsie
Cc: Michal Marek, Sam Ravnborg, Albert Herranz, linux-kernel, paulus,
Andrew Morton, linuxppc-dev
In-Reply-To: <1285916771-18033-3-git-send-email-imunsie@au1.ibm.com>
On Fri, Oct 1, 2010 at 09:05, Ian Munsie <imunsie@au1.ibm.com> wrote:
> From: Ian Munsie <imunsie@au1.ibm.com>
>
> Since the boot wrapper must be built by a big endian 32bit toolchain
> regardless of what the rest of the kernel is using introduce a new
> parameter to specify that toolchain - CROSSBE_COMPILE.
>
> We already have CROSS32_COMPILE which is already used for the boot
> wrapper, but it is also used to build the 32bit vdso which should be
> build in the same endianness as the rest of the kernel, so it is
> necessary to be able to specify the toolchain to build the boot wrapper
> separately from that used to build the vdso and again separately from
> that used to build the main kernel.
>
> CROSSBE_COMPILE should be pointed to a toolchain capable of targeting
> 32bit big endian powerpc, either specifically targetted at 32bit or
> bi-arch 64 and 32bit. If CROSSBE_COMPILE is not specified it will fall
> back to CROSS32_COMPILE to maintain compatibility with big endian
> targets.
Shouldn't the help text added by [PATCH 01/18]:
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -329,3 +329,19 @@ config CHECK_CACHE_COHERENCY
bool
endmenu
+
+config ARCH_SUPPORTS_LITTLE_ENDIAN
+ bool
+
+config CPU_LITTLE_ENDIAN
+ bool "Build little endian kernel"
+ depends on ARCH_SUPPORTS_LITTLE_ENDIAN && EXPERIMENTAL
+ default n
+ help
+ This option selects whether a big endian or little endian kernel =
will
+ be built.
+
+ Note that if building a little endian kernel, CROSS_COMPILE must
+ point to a toolchain capable of targetting little endian powerpc,
+ while the toolchain specified by CROSS32_COMPILE must be capable =
of
+ targetting *BIG* endian PowerPC.
be updated here as well?
Gr{oetje,eeting}s,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org
In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 -- Linus Torvalds
^ permalink raw reply
* Re: [PATCH 02/18] powerpc: Add CROSSBE_COMPILE to build big endian boot wrapper
From: Ian Munsie @ 2010-10-01 7:19 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Michal Marek, Sam Ravnborg, Albert Herranz, linux-kernel, paulus,
Andrew Morton, linuxppc-dev
In-Reply-To: <AANLkTi=VmSXN6XeD__nkQLJAYXzxOh6WEtW6-jjJcC4Q@mail.gmail.com>
Excerpts from Geert Uytterhoeven's message of Fri Oct 01 17:13:19 +1000 2010:
> Shouldn't the help text added by [PATCH 01/18]:
....
> be updated here as well?
Yep, you're right. Thanks for pointing that out, I'll fix it for the next
revision.
Cheers,
-Ian
^ permalink raw reply
* Re: Introduce support for little endian PowerPC
From: Kumar Gala @ 2010-10-01 9:02 UTC (permalink / raw)
To: Ian Munsie; +Cc: linuxppc-dev, linux-kernel, paulus
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
On Oct 1, 2010, at 2:05 AM, Ian Munsie wrote:
> Some PowerPC processors can be run in either big or little endian =
modes, some
> others can map selected pages of memory as little endian, which allows =
the same
> thing. Until now we have only supported the default big endian mode in =
Linux.
> This patch set introduces little endian support for the 44x family of =
PowerPC
> processors.
=46rom a community aspect is anyone actually going to use this? Is this =
going to be the equivalent of voyager on x86? I've got nothing against =
some of the endian clean ups this introduces. However the changes to =
misc_32.S are a bit ugly from a readability point of view. Just seems =
like this is likely to bit-rot pretty quickly.
- k
^ permalink raw reply
* Re: [PATCH 01/18] powerpc: Add ability to build little endian kernels
From: Kumar Gala @ 2010-10-01 9:18 UTC (permalink / raw)
To: Ian Munsie
Cc: Michal Marek, Albert Herranz, linuxppc-dev, linux-kernel, paulus,
Andreas Schwab, Andrew Morton, Sam Ravnborg, Torez Smith
In-Reply-To: <1285916771-18033-2-git-send-email-imunsie@au1.ibm.com>
On Oct 1, 2010, at 2:05 AM, Ian Munsie wrote:
>=20
> diff --git a/arch/powerpc/platforms/Kconfig.cputype =
b/arch/powerpc/platforms/Kconfig.cputype
> index d361f81..074ff12 100644
> --- a/arch/powerpc/platforms/Kconfig.cputype
> +++ b/arch/powerpc/platforms/Kconfig.cputype
> @@ -329,3 +329,19 @@ config CHECK_CACHE_COHERENCY
> bool
>=20
> endmenu
> +
> +config ARCH_SUPPORTS_LITTLE_ENDIAN
> + bool
> +
> +config CPU_LITTLE_ENDIAN
> + bool "Build little endian kernel"
> + depends on ARCH_SUPPORTS_LITTLE_ENDIAN && EXPERIMENTAL
> + default n
> + help
> + This option selects whether a big endian or little endian =
kernel will
> + be built.
> +
> + Note that if building a little endian kernel, CROSS_COMPILE =
must
> + point to a toolchain capable of targetting little endian =
powerpc,
> + while the toolchain specified by CROSS32_COMPILE must be =
capable of
> + targetting *BIG* endian PowerPC.
> --=20
> 1.7.1
Shouldn't we have something that limits to the sub-arch'es that actually =
support it? I doubt I'm ever going to make FSL-Book-e support LE.
- k=
^ permalink raw reply
* Re: [PATCH v3 3/7] eSPI: add eSPI controller support
From: Anton Vorontsov @ 2010-10-01 11:22 UTC (permalink / raw)
To: Mingkai Hu; +Cc: linuxppc-dev, kumar.gala, linux-mtd, spi-devel-general
In-Reply-To: <1285833646-12006-4-git-send-email-Mingkai.hu@freescale.com>
Hello Mingkai,
There are mostly cosmetic comments down below.
On Thu, Sep 30, 2010 at 04:00:42PM +0800, Mingkai Hu wrote:
[...]
> +/*
> + * Freescale eSPI controller driver.
> + *
> + * Copyright 2010 Freescale Semiconductor, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +#include <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/irq.h>
> +#include <linux/spi/spi.h>
> +#include <linux/platform_device.h>
> +#include <linux/fsl_devices.h>
> +#include <linux/mm.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_spi.h>
> +#include <sysdev/fsl_soc.h>
Please move the sysdev/ include after linux/.
Will make it a bit prettier. :-)
> +#include <linux/interrupt.h>
> +#include <linux/err.h>
> +
> +#include "spi_fsl_lib.h"
[...]
> +static void fsl_espi_change_mode(struct spi_device *spi)
> +{
> + struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
> + struct spi_mpc8xxx_cs *cs = spi->controller_state;
> + struct fsl_espi_reg *reg_base = (struct fsl_espi_reg *)mspi->reg_base;
No need for the type cast. The same for the rest of the code.
> + __be32 __iomem *mode;
> + __be32 __iomem *espi_mode = NULL;
> + u32 tmp;
> + unsigned long flags;
> +
> + espi_mode = ®_base->mode;
> + mode = ®_base->csmode[spi->chip_select];
Could save a few lines by turning this into initializers.
> +
> + /* Turn off IRQs locally to minimize time that SPI is disabled. */
> + local_irq_save(flags);
> +
> + /* Turn off SPI unit prior changing mode */
> + tmp = mpc8xxx_spi_read_reg(espi_mode);
> + mpc8xxx_spi_write_reg(espi_mode, tmp & ~SPMODE_ENABLE);
> + mpc8xxx_spi_write_reg(mode, cs->hw_mode);
> + mpc8xxx_spi_write_reg(espi_mode, tmp);
> +
> + local_irq_restore(flags);
> +}
> +
> +static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi)
> +{
> + u32 data;
> + u16 data_h, data_l;
u16 data_h;
u16 data_l;
> +
No need for this empty line.
> + const u32 *tx = mpc8xxx_spi->tx;
<- Instead, add an empty line here.
> + if (!tx)
> + return 0;
> +
> + data = *tx++ << mpc8xxx_spi->tx_shift;
> + data_l = data & 0xffff;
> + data_h = (data >> 16) & 0xffff;
> + swab16s(&data_l);
> + swab16s(&data_h);
> + data = data_h | data_l;
> +
> + mpc8xxx_spi->tx = tx;
> + return data;
> +}
> +
> +static int fsl_espi_setup_transfer(struct spi_device *spi,
> + struct spi_transfer *t)
> +{
> + struct mpc8xxx_spi *mpc8xxx_spi;
> + int bits_per_word = 0;
> + u8 pm;
> + u32 hz = 0;
> + struct spi_mpc8xxx_cs *cs = spi->controller_state;
Stray tab.
> +
> + mpc8xxx_spi = spi_master_get_devdata(spi->master);
Could move this to the initializer.
> +
> + if (t) {
> + bits_per_word = t->bits_per_word;
> + hz = t->speed_hz;
> + }
> +
> + /* spi_transfer level calls that work per-word */
> + if (!bits_per_word)
> + bits_per_word = spi->bits_per_word;
> +
> + /* Make sure its a bit width we support [4..16] */
> + if ((bits_per_word < 4) || (bits_per_word > 16))
> + return -EINVAL;
> +
> + if (!hz)
> + hz = spi->max_speed_hz;
> +
> + cs->rx_shift = 0;
> + cs->tx_shift = 0;
> + cs->get_rx = mpc8xxx_spi_rx_buf_u32;
> + cs->get_tx = mpc8xxx_spi_tx_buf_u32;
> + if (bits_per_word <= 8) {
> + cs->rx_shift = 8 - bits_per_word;
> + } else if (bits_per_word <= 16) {
> + cs->rx_shift = 16 - bits_per_word;
> + if (spi->mode & SPI_LSB_FIRST)
> + cs->get_tx = fsl_espi_tx_buf_lsb;
> + } else
> + return -EINVAL;
} else {
}
> +
> + mpc8xxx_spi->rx_shift = cs->rx_shift;
> + mpc8xxx_spi->tx_shift = cs->tx_shift;
> + mpc8xxx_spi->get_rx = cs->get_rx;
> + mpc8xxx_spi->get_tx = cs->get_tx;
> +
> + bits_per_word = bits_per_word - 1;
> +
> + /* mask out bits we are going to set */
> + cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16
> + | CSMODE_PM(0xF));
No need to break this statement.
> +
> + cs->hw_mode |= CSMODE_LEN(bits_per_word);
> +
> + if ((mpc8xxx_spi->spibrg / hz) > 64) {
> + cs->hw_mode |= CSMODE_DIV16;
> + pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
> +
> + WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
> + "Will use %d Hz instead.\n", dev_name(&spi->dev),
> + hz, mpc8xxx_spi->spibrg / 1024);
> + if (pm > 16)
> + pm = 16;
> + } else {
> + pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
> + }
> + if (pm)
> + pm--;
> +
> + cs->hw_mode |= CSMODE_PM(pm);
> +
> + fsl_espi_change_mode(spi);
> + return 0;
> +}
> +
> +int fsl_espi_cpu_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t,
> + unsigned int len)
Does this need to be global?
> +{
> + u32 word;
> + struct fsl_espi_reg *reg_base = (struct fsl_espi_reg *)mspi->reg_base;
> +
> + mspi->count = len;
> +
> + /* enable rx ints */
> + mpc8xxx_spi_write_reg(®_base->mask, SPIM_NE);
> +
> + /* transmit word */
> + word = mspi->get_tx(mspi);
> + mpc8xxx_spi_write_reg(®_base->transmit, word);
> +
> + return 0;
> +}
> +
> +static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t,
> + bool is_dma_mapped)
No need for the is_dma_mapped argument.
> +{
> + struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> + struct fsl_espi_reg *reg_base;
> + unsigned int len = t->len;
> + u8 bits_per_word;
> + int ret;
> +
> + reg_base = (struct fsl_espi_reg *)mpc8xxx_spi->reg_base;
Better write this as an initializer, no need for the cast.
> +
> + bits_per_word = spi->bits_per_word;
> + if (t->bits_per_word)
> + bits_per_word = t->bits_per_word;
[...]
> +static int fsl_espi_setup(struct spi_device *spi)
> +{
> + struct mpc8xxx_spi *mpc8xxx_spi;
> + struct fsl_espi_reg *reg_base;
> + int retval;
> + u32 hw_mode;
> + u32 loop_mode;
> + struct spi_mpc8xxx_cs *cs = spi->controller_state;
Stray tab.
> +
> + if (!spi->max_speed_hz)
> + return -EINVAL;
> +
> + if (!cs) {
> + cs = kzalloc(sizeof *cs, GFP_KERNEL);
> + if (!cs)
> + return -ENOMEM;
> + spi->controller_state = cs;
> + }
[...]
> + rx_data = mpc8xxx_spi_read_reg(®_base->receive);
> +
> + if (mspi->rx)
> + mspi->get_rx(rx_data, mspi);
> + }
> +
> + if ((events & SPIE_NF) == 0)
if (!(events & bit)) is a bit more more natural. Also, the if
statement here needs braces.
> + /* spin until TX is done */
> + while (((events = mpc8xxx_spi_read_reg(®_base->event))
> + & SPIE_NF) == 0)
> + cpu_relax();
This is dangerous. There's a handy spin_event_timeout()
in asm/delay.h.
> +
> + /* Clear the events */
> + mpc8xxx_spi_write_reg(®_base->event, events);
> +
> + mspi->count -= 1;
> + if (mspi->count) {
> + u32 word = mspi->get_tx(mspi);
> +
> + mpc8xxx_spi_write_reg(®_base->transmit, word);
> + } else {
> + complete(&mspi->done);
> + }
> +}
> +
> +static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
> +{
> + struct mpc8xxx_spi *mspi = context_data;
> + struct fsl_espi_reg *reg_base = (struct fsl_espi_reg *)mspi->reg_base;
> + irqreturn_t ret = IRQ_NONE;
> + u32 events;
> +
> + /* Get interrupt events(tx/rx) */
> + events = mpc8xxx_spi_read_reg(®_base->event);
> + if (events)
> + ret = IRQ_HANDLED;
> +
> + dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
dev_vdbg()
> +
> + fsl_espi_cpu_irq(mspi, events);
> +
> + return ret;
> +}
> +
> +static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
> +{
> + iounmap(mspi->reg_base);
> +}
> +
> +static struct spi_master * __devinit fsl_espi_probe(struct device *dev,
> + struct resource *mem, unsigned int irq)
> +{
> + struct fsl_spi_platform_data *pdata = dev->platform_data;
> + struct spi_master *master;
> + struct mpc8xxx_spi *mpc8xxx_spi;
> + struct fsl_espi_reg *reg_base;
> + u32 regval;
> + int i, ret = 0;
> +
> + master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
> + if (master == NULL) {
Sometimes you check for !allocated, and sometimes allocated == NULL.
Be consistent. (And !allocated is more natural.)
> + ret = -ENOMEM;
> + goto err;
> + }
> +
> + dev_set_drvdata(dev, master);
> +
> + ret = mpc8xxx_spi_probe(dev, mem, irq);
> + if (ret)
> + goto err_probe;
> +
> + master->setup = fsl_espi_setup;
> +
> + mpc8xxx_spi = spi_master_get_devdata(master);
> + mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
> + mpc8xxx_spi->spi_remove = fsl_espi_remove;
> +
> + mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
> + if (mpc8xxx_spi->reg_base == NULL) {
Ditto.
> + ret = -ENOMEM;
> + goto err_probe;
> + }
> +
> + reg_base = (struct fsl_espi_reg *)mpc8xxx_spi->reg_base;
> +
> + /* Register for SPI Interrupt */
> + ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
> + 0, "fsl_espi", mpc8xxx_spi);
> +
> + if (ret != 0)
Every time someone writes 'if (rc != 0)', a kitty dies.
Simple 'if (rc)' saves kittens.
> + goto free_irq;
> +
> + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
> + mpc8xxx_spi->rx_shift = 16;
> + mpc8xxx_spi->tx_shift = 24;
> + }
[...]
> +
> +static int __devexit of_fsl_espi_remove(struct platform_device *dev)
> +{
> + int ret;
> +
> + ret = mpc8xxx_spi_remove(&dev->dev);
> + if (ret)
> + return ret;
> +
> + return 0;
Just 'return mpc8xxx_spi_remove(&dev->dev);' is sufficient.
Also, I think there's no need for this wrapper nowadays (but
splitting OF and real probe() stuff is still appropriate).
> +}
> +
> +static const struct of_device_id of_fsl_espi_match[] = {
> + { .compatible = "fsl,mpc8536-espi" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
> +
> +static struct of_platform_driver fsl_espi_driver = {
> + .driver = {
> + .name = "fsl_espi",
> + .owner = THIS_MODULE,
> + .of_match_table = of_fsl_espi_match,
> + },
> + .probe = of_fsl_espi_probe,
> + .remove = __devexit_p(of_fsl_espi_remove),
> +};
> +
> +static int __init fsl_espi_init(void)
> +{
> + return of_register_platform_driver(&fsl_espi_driver);
> +}
> +module_init(fsl_espi_init);
> +
> +static void __exit fsl_espi_exit(void)
> +{
> + of_unregister_platform_driver(&fsl_espi_driver);
> +}
> +module_exit(fsl_espi_exit);
> +
> +MODULE_AUTHOR("Mingkai Hu");
> +MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");
This sounds like that this is an enhanced version of the
Freescale SPI driver, which it is not. ;-)
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi_fsl_lib.h
> index 6ae8949..9c81498 100644
> --- a/drivers/spi/spi_fsl_lib.h
> +++ b/drivers/spi/spi_fsl_lib.h
> @@ -26,6 +26,7 @@ struct mpc8xxx_spi {
> /* rx & tx bufs from the spi_transfer */
> const void *tx;
> void *rx;
> + int len;
I'd place the #ifdef CONFIG_SPI_ESPI, for documentation purposes.
Thanks,
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: [PATCH v3 2/7] spi/mpc8xxx: refactor the common code for SPI/eSPI controller
From: Anton Vorontsov @ 2010-10-01 11:22 UTC (permalink / raw)
To: Mingkai Hu; +Cc: linuxppc-dev, kumar.gala, linux-mtd, spi-devel-general
In-Reply-To: <1285833646-12006-3-git-send-email-Mingkai.hu@freescale.com>
On Thu, Sep 30, 2010 at 04:00:41PM +0800, Mingkai Hu wrote:
[...]
> -static void mpc8xxx_spi_change_mode(struct spi_device *spi)
> +static void fsl_spi_change_mode(struct spi_device *spi)
> {
> struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
> struct spi_mpc8xxx_cs *cs = spi->controller_state;
> - __be32 __iomem *mode = &mspi->base->mode;
> + struct fsl_spi_reg *reg_base = (struct fsl_spi_reg *)mspi->reg_base;
No need for these type casts (the same is for the whole patch).
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: [PATCH 05/18] powerpc: Wire up 44x little endian boot for remaining 44x targets
From: Josh Boyer @ 2010-10-01 11:27 UTC (permalink / raw)
To: Ian Munsie; +Cc: linuxppc-dev, linux-kernel, paulus
In-Reply-To: <1285916771-18033-6-git-send-email-imunsie@au1.ibm.com>
On Fri, Oct 1, 2010 at 3:05 AM, Ian Munsie <imunsie@au1.ibm.com> wrote:
> From: Ian Munsie <imunsie@au1.ibm.com>
>
> I haven't tested booting a little endian kernel on any of these targets,
> but they all claim to be 44x so my little endian trampoline should work
> on all of them, so wire it up on:
>
> bamboo
> katmai
> kilauea
> rainer
> sam440ep
> sequoia
> warp
> yosemite
> ebony
>
> Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
I see no reason to do this at all. If you haven't tested them and
there is no demand, there's no reason to wire them up. Some might
actively want to disallow LE mode anyway, like the Warp or Sam440EP.
josh
^ permalink raw reply
* Re: [PATCH 01/18] powerpc: Add ability to build little endian kernels
From: Josh Boyer @ 2010-10-01 11:28 UTC (permalink / raw)
To: Kumar Gala
Cc: Michal Marek, Sam Ravnborg, Albert Herranz, linux-kernel, paulus,
Ian Munsie, Andreas Schwab, Andrew Morton, linuxppc-dev,
Torez Smith
In-Reply-To: <F7E7DAE6-A132-458D-ABC3-4CC92A4C7263@kernel.crashing.org>
On Fri, Oct 1, 2010 at 5:18 AM, Kumar Gala <galak@kernel.crashing.org> wrot=
e:
>
> On Oct 1, 2010, at 2:05 AM, Ian Munsie wrote:
>
>>
>> diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platf=
orms/Kconfig.cputype
>> index d361f81..074ff12 100644
>> --- a/arch/powerpc/platforms/Kconfig.cputype
>> +++ b/arch/powerpc/platforms/Kconfig.cputype
>> @@ -329,3 +329,19 @@ config CHECK_CACHE_COHERENCY
>> =A0 =A0 =A0 bool
>>
>> endmenu
>> +
>> +config ARCH_SUPPORTS_LITTLE_ENDIAN
>> + =A0 =A0 bool
>> +
>> +config CPU_LITTLE_ENDIAN
>> + =A0 =A0 bool "Build little endian kernel"
>> + =A0 =A0 depends on ARCH_SUPPORTS_LITTLE_ENDIAN && EXPERIMENTAL
>> + =A0 =A0 default n
>> + =A0 =A0 help
>> + =A0 =A0 =A0 This option selects whether a big endian or little endian =
kernel will
>> + =A0 =A0 =A0 be built.
>> +
>> + =A0 =A0 =A0 Note that if building a little endian kernel, CROSS_COMPIL=
E must
>> + =A0 =A0 =A0 point to a toolchain capable of targetting little endian p=
owerpc,
>> + =A0 =A0 =A0 while the toolchain specified by CROSS32_COMPILE must be c=
apable of
>> + =A0 =A0 =A0 targetting *BIG* endian PowerPC.
>> --
>> 1.7.1
>
> Shouldn't we have something that limits to the sub-arch'es that actually =
support it? =A0I doubt I'm ever going to make FSL-Book-e support LE.
Yes, it should.
josh
^ permalink raw reply
* Re: Introduce support for little endian PowerPC
From: Josh Boyer @ 2010-10-01 11:30 UTC (permalink / raw)
To: Kumar Gala; +Cc: paulus, linuxppc-dev, Ian Munsie, linux-kernel
In-Reply-To: <2C5357FA-F87F-457E-B5C1-0DCC5A842DE7@kernel.crashing.org>
On Fri, Oct 1, 2010 at 5:02 AM, Kumar Gala <galak@kernel.crashing.org> wrot=
e:
>
> On Oct 1, 2010, at 2:05 AM, Ian Munsie wrote:
>
>> Some PowerPC processors can be run in either big or little endian modes,=
some
>> others can map selected pages of memory as little endian, which allows t=
he same
>> thing. Until now we have only supported the default big endian mode in L=
inux.
>> This patch set introduces little endian support for the 44x family of Po=
werPC
>> processors.
>
> From a community aspect is anyone actually going to use this? =A0Is this =
going to be the equivalent of voyager on x86? =A0I've got nothing against s=
ome of the endian clean ups this introduces. =A0However the changes to misc=
_32.S are a bit ugly from a readability point of view. =A0Just seems like t=
his is likely to bit-rot pretty quickly.
I'm with Kumar on this one. Why would we want to support this? I
can't say I would be very willing to help anyone run in LE mode, let
alone have it randomly selectable.
josh
^ permalink raw reply
* Re: Introduce support for little endian PowerPC
From: Josh Boyer @ 2010-10-01 11:36 UTC (permalink / raw)
To: Ian Munsie; +Cc: linuxppc-dev, linux-kernel, paulus
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
On Fri, Oct 1, 2010 at 3:05 AM, Ian Munsie <imunsie@au1.ibm.com> wrote:
> This patch set in combination with a patched GCC, binutils, uClibc and
> buildroot has allowed for a full proof of concept little endian environme=
nt on
> a 440 Taishan board, which was able to successfully run busybox, OpenSSH =
and a
> handful of other userspace programs without problems.
Aside from my general "uh, why?" stance, I'm very very hesitant to
integrate anything in the kernel that doesn'.t have released patches
on the toolchain side.
Also, which uClibc? The old and crusty uClibc that uses the horrible
linuxthreads, or the somewhat less crusty that just switched to NPTL
(which hasn't been verified on normal PowerPC that I recall). Why not
use glibc...
> This is not yet complete support for little endian PowerPC, some outstand=
ing
> issues that I am aware of are:
> =A0* We only support 32bit PowerPC for now (and indeed, only 44x)
> =A0* The vdso has not been fixed to be endian agnostic - any userspace pr=
ogram
> =A0 accessing it will get an unexpected result.
> =A0* I have not touched PCI at all
> =A0* Remaining device tree accesses still need to be examined to ensure t=
hey are
> =A0 correctly handling the endianess of the device tree.
> =A0* Any other driver that uses the device tree is likely be broken for t=
he same reason.
> =A0* I've included a patch for the alignment handler, however it is as ye=
t
> =A0 completely untested due to a property of the hardware I've been using=
for
> =A0 testing.
I'm not meeting to detract here, but the Kconfig should be dependent
on && BROKEN until the above is fixed.
josh
^ permalink raw reply
* Re: [PATCH 01/18] powerpc: Add ability to build little endian kernels
From: Josh Boyer @ 2010-10-01 11:40 UTC (permalink / raw)
To: Ian Munsie
Cc: Michal Marek, Sam Ravnborg, Albert Herranz, linux-kernel, paulus,
Andreas Schwab, Andrew Morton, linuxppc-dev, Torez Smith
In-Reply-To: <1285916771-18033-2-git-send-email-imunsie@au1.ibm.com>
On Fri, Oct 1, 2010 at 3:05 AM, Ian Munsie <imunsie@au1.ibm.com> wrote:
> diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platfo=
rms/Kconfig.cputype
> index d361f81..074ff12 100644
> --- a/arch/powerpc/platforms/Kconfig.cputype
> +++ b/arch/powerpc/platforms/Kconfig.cputype
> @@ -329,3 +329,19 @@ config CHECK_CACHE_COHERENCY
> =A0 =A0 =A0 =A0bool
>
> =A0endmenu
> +
> +config ARCH_SUPPORTS_LITTLE_ENDIAN
> + =A0 =A0 =A0 bool
> +
> +config CPU_LITTLE_ENDIAN
> + =A0 =A0 =A0 bool "Build little endian kernel"
> + =A0 =A0 =A0 depends on ARCH_SUPPORTS_LITTLE_ENDIAN && EXPERIMENTAL
> + =A0 =A0 =A0 default n
> + =A0 =A0 =A0 help
> + =A0 =A0 =A0 =A0 This option selects whether a big endian or little endi=
an kernel will
> + =A0 =A0 =A0 =A0 be built.
> +
> + =A0 =A0 =A0 =A0 Note that if building a little endian kernel, CROSS_COM=
PILE must
> + =A0 =A0 =A0 =A0 point to a toolchain capable of targetting little endia=
n powerpc,
> + =A0 =A0 =A0 =A0 while the toolchain specified by CROSS32_COMPILE must b=
e capable of
> + =A0 =A0 =A0 =A0 targetting *BIG* endian PowerPC.
Have you tested this support with a userspace containing floating
point instructions? I wonder if CONFIG_MATH_EMULATION is going to
need work at all, and if the boards with an actual FPU (440EP, 440EPx,
460EX, etc) would have issues.
josh
^ permalink raw reply
* Re: Introduce support for little endian PowerPC
From: Gary Thomas @ 2010-10-01 11:55 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev, paulus, linux-kernel, Ian Munsie
In-Reply-To: <AANLkTinSDMvBb7rnnfwYMkEVOgDUqRetZg86rh-UmSAg@mail.gmail.com>
On 10/01/2010 05:30 AM, Josh Boyer wrote:
> On Fri, Oct 1, 2010 at 5:02 AM, Kumar Gala<galak@kernel.crashing.org> wrote:
>>
>> On Oct 1, 2010, at 2:05 AM, Ian Munsie wrote:
>>
>>> Some PowerPC processors can be run in either big or little endian modes, some
>>> others can map selected pages of memory as little endian, which allows the same
>>> thing. Until now we have only supported the default big endian mode in Linux.
>>> This patch set introduces little endian support for the 44x family of PowerPC
>>> processors.
>>
>> From a community aspect is anyone actually going to use this? Is this going to be the equivalent of voyager on x86? I've got nothing against some of the endian clean ups this introduces. However the changes to misc_32.S are a bit ugly from a readability point of view. Just seems like this is likely to bit-rot pretty quickly.
>
> I'm with Kumar on this one. Why would we want to support this? I
> can't say I would be very willing to help anyone run in LE mode, let
> alone have it randomly selectable.
Indeed, I thought we had killed that Windows-NT dog ~15 years ago :-)
--
------------------------------------------------------------
Gary Thomas | Consulting for the
MLB Associates | Embedded world
------------------------------------------------------------
^ permalink raw reply
* Re: [PATCH 01/18] powerpc: Add ability to build little endian kernels
From: Benjamin Herrenschmidt @ 2010-10-01 12:09 UTC (permalink / raw)
To: Josh Boyer
Cc: Michal Marek, linuxppc-dev, Albert Herranz, linux-kernel, paulus,
Ian Munsie, Andreas Schwab, Andrew Morton, Sam Ravnborg,
Torez Smith
In-Reply-To: <AANLkTimGtB_KoOgwk3Ujn2UcNzs9qHxzeZcb1ShLgcXh@mail.gmail.com>
On Fri, 2010-10-01 at 07:28 -0400, Josh Boyer wrote:
> > Shouldn't we have something that limits to the sub-arch'es that
> actually support it? I doubt I'm ever going to make FSL-Book-e
> support LE.
>
> Yes, it should.
Sure, that's only WIP patches :-)
Tho FSL BookE would be relatively easy...
Cheers,
Ben.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox