microblaze: Add support for little-endian Microblaze

Microblaze little-endian toolchain exports __MICROBLAZEEL__
which is used in the kernel to identify little/big endian.

The most of the changes are in loading values from DTB which
is always big endian.

Little endian platforms are based on new AXI bus which has
impact to early uartlite initialization.

Signed-off-by: Michal Simek <monstr@monstr.eu>
This commit is contained in:
Michal Simek 2010-09-28 16:04:14 +10:00
Родитель e4f2909227
Коммит 02b08045a0
10 изменённых файлов: 42 добавлений и 18 удалений

Просмотреть файл

@ -1,6 +1,10 @@
#ifndef _ASM_MICROBLAZE_BYTEORDER_H #ifndef _ASM_MICROBLAZE_BYTEORDER_H
#define _ASM_MICROBLAZE_BYTEORDER_H #define _ASM_MICROBLAZE_BYTEORDER_H
#ifdef __MICROBLAZEEL__
#include <linux/byteorder/little_endian.h>
#else
#include <linux/byteorder/big_endian.h> #include <linux/byteorder/big_endian.h>
#endif
#endif /* _ASM_MICROBLAZE_BYTEORDER_H */ #endif /* _ASM_MICROBLAZE_BYTEORDER_H */

Просмотреть файл

@ -24,8 +24,13 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
"addc %0, %0, %3\n\t" "addc %0, %0, %3\n\t"
"addc %0, %0, r0\n\t" "addc %0, %0, r0\n\t"
: "+&d" (sum) : "+&d" (sum)
: "d" (saddr), "d" (daddr), "d" (len + proto)); : "d" (saddr), "d" (daddr),
#ifdef __MICROBLAZEEL__
"d" ((len + proto) << 8)
#else
"d" (len + proto)
#endif
);
return sum; return sum;
} }

Просмотреть файл

@ -98,7 +98,8 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu);
static inline unsigned int fcpu(struct device_node *cpu, char *n) static inline unsigned int fcpu(struct device_node *cpu, char *n)
{ {
int *val; int *val;
return (val = (int *) of_get_property(cpu, n, NULL)) ? *val : 0; return (val = (int *) of_get_property(cpu, n, NULL)) ?
be32_to_cpup(val) : 0;
} }
#endif /* _ASM_MICROBLAZE_CPUINFO_H */ #endif /* _ASM_MICROBLAZE_CPUINFO_H */

Просмотреть файл

@ -71,7 +71,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
#define ELF_ET_DYN_BASE (0x08000000) #define ELF_ET_DYN_BASE (0x08000000)
#ifdef __LITTLE_ENDIAN__ #ifdef __MICROBLAZEEL__
#define ELF_DATA ELFDATA2LSB #define ELF_DATA ELFDATA2LSB
#else #else
#define ELF_DATA ELFDATA2MSB #define ELF_DATA ELFDATA2MSB

Просмотреть файл

@ -12,12 +12,18 @@
# ifdef __KERNEL__ # ifdef __KERNEL__
# include <linux/unaligned/be_struct.h> # include <linux/unaligned/be_byteshift.h>
# include <linux/unaligned/le_byteshift.h> # include <linux/unaligned/le_byteshift.h>
# include <linux/unaligned/generic.h> # include <linux/unaligned/generic.h>
# define get_unaligned __get_unaligned_be
# define put_unaligned __put_unaligned_be # ifdef __MICROBLAZEEL__
# define get_unaligned __get_unaligned_le
# define put_unaligned __put_unaligned_le
# else
# define get_unaligned __get_unaligned_be
# define put_unaligned __put_unaligned_be
# endif
# endif /* __KERNEL__ */ # endif /* __KERNEL__ */
#endif /* _ASM_MICROBLAZE_UNALIGNED_H */ #endif /* _ASM_MICROBLAZE_UNALIGNED_H */

Просмотреть файл

@ -59,7 +59,7 @@ void setup_heartbeat(void)
} }
if (gpio) { if (gpio) {
base_addr = *(int *) of_get_property(gpio, "reg", NULL); base_addr = be32_to_cpup(of_get_property(gpio, "reg", NULL));
base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE); base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE);
printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr); printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr);

Просмотреть файл

@ -138,12 +138,15 @@ void __init init_IRQ(void)
} }
BUG_ON(!intc); BUG_ON(!intc);
intc_baseaddr = *(int *) of_get_property(intc, "reg", NULL); intc_baseaddr = be32_to_cpup(of_get_property(intc,
"reg", NULL));
intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE); intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE);
nr_irq = *(int *) of_get_property(intc, "xlnx,num-intr-inputs", NULL); nr_irq = be32_to_cpup(of_get_property(intc,
"xlnx,num-intr-inputs", NULL));
intr_type = intr_type =
*(int *) of_get_property(intc, "xlnx,kind-of-intr", NULL); be32_to_cpup(of_get_property(intc,
"xlnx,kind-of-intr", NULL));
if (intr_type >= (1 << (nr_irq + 1))) if (intr_type >= (1 << (nr_irq + 1)))
printk(KERN_INFO " ERROR: Mismatch in kind-of-intr param\n"); printk(KERN_INFO " ERROR: Mismatch in kind-of-intr param\n");

Просмотреть файл

@ -77,11 +77,12 @@ static int __init early_init_dt_scan_serial(unsigned long node,
/* find compatible node with uartlite */ /* find compatible node with uartlite */
p = of_get_flat_dt_prop(node, "compatible", &l); p = of_get_flat_dt_prop(node, "compatible", &l);
if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) && if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) &&
(strncmp(p, "xlnx,opb-uartlite", 17) != 0)) (strncmp(p, "xlnx,opb-uartlite", 17) != 0) &&
(strncmp(p, "xlnx,axi-uartlite", 17) != 0))
return 0; return 0;
addr = of_get_flat_dt_prop(node, "reg", &l); addr = of_get_flat_dt_prop(node, "reg", &l);
return *addr; /* return address */ return be32_to_cpup(addr); /* return address */
} }
/* this function is looking for early uartlite console - Microblaze specific */ /* this function is looking for early uartlite console - Microblaze specific */
@ -115,7 +116,7 @@ static int __init early_init_dt_scan_serial_full(unsigned long node,
addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l); addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
addr += *(u32 *)of_get_flat_dt_prop(node, "reg-offset", &l); addr += *(u32 *)of_get_flat_dt_prop(node, "reg-offset", &l);
return addr; /* return address */ return be32_to_cpu(addr); /* return address */
} }
/* this function is looking for early uartlite console - Microblaze specific */ /* this function is looking for early uartlite console - Microblaze specific */

Просмотреть файл

@ -270,11 +270,11 @@ void __init time_init(void)
} }
BUG_ON(!timer); BUG_ON(!timer);
timer_baseaddr = *(int *) of_get_property(timer, "reg", NULL); timer_baseaddr = be32_to_cpup(of_get_property(timer, "reg", NULL));
timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE); timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE);
irq = *(int *) of_get_property(timer, "interrupts", NULL); irq = be32_to_cpup(of_get_property(timer, "interrupts", NULL));
timer_num = timer_num = be32_to_cpup(of_get_property(timer,
*(int *) of_get_property(timer, "xlnx,one-timer-only", NULL); "xlnx,one-timer-only", NULL));
if (timer_num) { if (timer_num) {
eprintk(KERN_EMERG "Please enable two timers in HW\n"); eprintk(KERN_EMERG "Please enable two timers in HW\n");
BUG(); BUG();

Просмотреть файл

@ -15,7 +15,11 @@ ENTRY(microblaze_start)
#include <asm-generic/vmlinux.lds.h> #include <asm-generic/vmlinux.lds.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
#ifdef __MICROBLAZEEL__
jiffies = jiffies_64;
#else
jiffies = jiffies_64 + 4; jiffies = jiffies_64 + 4;
#endif
SECTIONS { SECTIONS {
. = CONFIG_KERNEL_START; . = CONFIG_KERNEL_START;