diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-25 23:53:11 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-25 23:53:11 (GMT) |
commit | e0e170bd7ded2ec16e2813d63c0faff43193fde8 (patch) | |
tree | 2f06008b61ef2eedf8f77d1326e286a64e426ef6 | |
parent | b20f9e5bddddb5ef0d743d6e0d409ffc8cf9fc56 (diff) | |
parent | b843e4ec01991a386a9e0e9030703524446e03da (diff) | |
download | linux-fsl-qoriq-e0e170bd7ded2ec16e2813d63c0faff43193fde8.tar.xz |
Merge branch 'next' of git://git.monstr.eu/linux-2.6-microblaze
* 'next' of git://git.monstr.eu/linux-2.6-microblaze: (42 commits)
microblaze: Fix build with make 3.82
fbdev/xilinxfb: Microblaze driver support
microblaze: Support C optimized lib functions for little-endian
microblaze: Separate library optimized functions
microblaze: Support timer on AXI lite
microblaze: Add support for little-endian Microblaze
microblaze: KGDB little endian support
microblaze: Add PVR for endians plus detection
net: emaclite: Add support for little-endian platforms
microblaze: trivial: Add comment for AXI pvr
microblaze: pci-common cleanup
microblaze: Support early console on uart16550
microblaze: Do not compile early console support for uartlite if is disabled
microblaze: Setup early console dynamically
microblaze: Rename all uartlite early printk functions
microblaze: remove early printk uarlite console dependency from header
microblaze: Remove additional compatible properties
microblaze: Remove hardcoded asm instraction for PVR loading
microblaze: Use static const char * const where possible
microblaze: Define VMALLOC_START/END
...
56 files changed, 1038 insertions, 201 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 692fdfc..dad40fc 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -121,6 +121,23 @@ config CMDLINE_FORCE Set this to have arguments from the default kernel command string override those passed by the boot loader. +config SECCOMP + bool "Enable seccomp to safely compute untrusted bytecode" + depends on PROC_FS + default y + help + This kernel feature is useful for number crunching applications + that may need to compute untrusted bytecode during their + execution. By using pipes or other transports made available to + the process as file descriptors supporting the read/write + syscalls, it's possible to isolate those applications in + their own address space using seccomp. Once seccomp is + enabled via /proc/<pid>/seccomp, it cannot be disabled + and the task is only allowed to execute a few safe syscalls + defined by each seccomp mode. + + If unsure, say Y. Only embedded should say N here. + endmenu menu "Advanced setup" diff --git a/arch/microblaze/Kconfig.debug b/arch/microblaze/Kconfig.debug index e6e5e0d..e66e25c 100644 --- a/arch/microblaze/Kconfig.debug +++ b/arch/microblaze/Kconfig.debug @@ -10,7 +10,7 @@ source "lib/Kconfig.debug" config EARLY_PRINTK bool "Early printk function for kernel" - depends on SERIAL_UARTLITE_CONSOLE + depends on SERIAL_UARTLITE_CONSOLE || SERIAL_8250_CONSOLE default n help This option turns on/off early printk messages to console. diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile index 592c707..15f1f1d 100644 --- a/arch/microblaze/Makefile +++ b/arch/microblaze/Makefile @@ -42,11 +42,8 @@ KBUILD_CFLAGS += -ffixed-r31 $(CPUFLAGS-1) $(CPUFLAGS-2) LDFLAGS := LDFLAGS_vmlinux := -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) - head-y := arch/microblaze/kernel/head.o libs-y += arch/microblaze/lib/ -libs-y += $(LIBGCC) core-y += arch/microblaze/kernel/ core-y += arch/microblaze/mm/ core-y += arch/microblaze/platform/ @@ -72,12 +69,16 @@ export MMU DTB all: linux.bin -BOOT_TARGETS = linux.bin linux.bin.gz simpleImage.% +# With make 3.82 we cannot mix normal and wildcard targets +BOOT_TARGETS1 = linux.bin linux.bin.gz +BOOT_TARGETS2 = simpleImage.% archclean: $(Q)$(MAKE) $(clean)=$(boot) -$(BOOT_TARGETS): vmlinux +$(BOOT_TARGETS1): vmlinux + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ +$(BOOT_TARGETS2): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ define archhelp diff --git a/arch/microblaze/include/asm/byteorder.h b/arch/microblaze/include/asm/byteorder.h index ce9c587..3190276 100644 --- a/arch/microblaze/include/asm/byteorder.h +++ b/arch/microblaze/include/asm/byteorder.h @@ -1,6 +1,10 @@ #ifndef _ASM_MICROBLAZE_BYTEORDER_H #define _ASM_MICROBLAZE_BYTEORDER_H +#ifdef __MICROBLAZEEL__ +#include <linux/byteorder/little_endian.h> +#else #include <linux/byteorder/big_endian.h> +#endif #endif /* _ASM_MICROBLAZE_BYTEORDER_H */ diff --git a/arch/microblaze/include/asm/checksum.h b/arch/microblaze/include/asm/checksum.h index 128bf03..0185cbe 100644 --- a/arch/microblaze/include/asm/checksum.h +++ b/arch/microblaze/include/asm/checksum.h @@ -24,8 +24,13 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, "addc %0, %0, %3\n\t" "addc %0, %0, r0\n\t" : "+&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; } diff --git a/arch/microblaze/include/asm/cpuinfo.h b/arch/microblaze/include/asm/cpuinfo.h index b4f5ca3..cd25753 100644 --- a/arch/microblaze/include/asm/cpuinfo.h +++ b/arch/microblaze/include/asm/cpuinfo.h @@ -38,6 +38,7 @@ struct cpuinfo { u32 use_exc; u32 ver_code; u32 mmu; + u32 endian; /* CPU caches */ u32 use_icache; @@ -76,7 +77,6 @@ struct cpuinfo { u32 num_rd_brk; u32 num_wr_brk; u32 cpu_clock_freq; /* store real freq of cpu */ - u32 freq_div_hz; /* store freq/HZ */ /* FPGA family */ u32 fpga_family_code; @@ -97,7 +97,8 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu); static inline unsigned int fcpu(struct device_node *cpu, char *n) { 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 */ diff --git a/arch/microblaze/include/asm/elf.h b/arch/microblaze/include/asm/elf.h index 732caf1..098dfdd 100644 --- a/arch/microblaze/include/asm/elf.h +++ b/arch/microblaze/include/asm/elf.h @@ -71,7 +71,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #define ELF_ET_DYN_BASE (0x08000000) -#ifdef __LITTLE_ENDIAN__ +#ifdef __MICROBLAZEEL__ #define ELF_DATA ELFDATA2LSB #else #define ELF_DATA ELFDATA2MSB diff --git a/arch/microblaze/include/asm/gpio.h b/arch/microblaze/include/asm/gpio.h index 2345ac3..2b2c18b 100644 --- a/arch/microblaze/include/asm/gpio.h +++ b/arch/microblaze/include/asm/gpio.h @@ -38,12 +38,9 @@ static inline int gpio_cansleep(unsigned int gpio) return __gpio_cansleep(gpio); } -/* - * Not implemented, yet. - */ static inline int gpio_to_irq(unsigned int gpio) { - return -ENOSYS; + return __gpio_to_irq(gpio); } static inline int irq_to_gpio(unsigned int irq) diff --git a/arch/microblaze/include/asm/io.h b/arch/microblaze/include/asm/io.h index 00b5398..eae3222 100644 --- a/arch/microblaze/include/asm/io.h +++ b/arch/microblaze/include/asm/io.h @@ -243,6 +243,8 @@ static inline void __iomem *__ioremap(phys_addr_t address, unsigned long size, #define out_8(a, v) __raw_writeb((v), (a)) #define in_8(a) __raw_readb(a) +#define mmiowb() + #define ioport_map(port, nr) ((void __iomem *)(port)) #define ioport_unmap(addr) diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h index cf377d9..ed9d0f6 100644 --- a/arch/microblaze/include/asm/page.h +++ b/arch/microblaze/include/asm/page.h @@ -205,9 +205,6 @@ extern int page_is_ram(unsigned long pfn); #define TOPHYS(addr) __virt_to_phys(addr) #ifdef CONFIG_MMU -#ifdef CONFIG_CONTIGUOUS_PAGE_ALLOC -#define WANT_PAGE_VIRTUAL 1 /* page alloc 2 relies on this */ -#endif #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h index 5a388ee..2232ff94 100644 --- a/arch/microblaze/include/asm/pci.h +++ b/arch/microblaze/include/asm/pci.h @@ -165,5 +165,7 @@ extern void __init xilinx_pci_init(void); static inline void __init xilinx_pci_init(void) { return; } #endif +#include <asm-generic/pci-dma-compat.h> + #endif /* __KERNEL__ */ #endif /* __ASM_MICROBLAZE_PCI_H */ diff --git a/arch/microblaze/include/asm/pgalloc.h b/arch/microblaze/include/asm/pgalloc.h index c614a89..ebd3579 100644 --- a/arch/microblaze/include/asm/pgalloc.h +++ b/arch/microblaze/include/asm/pgalloc.h @@ -165,7 +165,8 @@ extern inline void pte_free(struct mm_struct *mm, struct page *ptepage) #define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, (pte)) -#define pmd_populate(mm, pmd, pte) (pmd_val(*(pmd)) = page_address(pte)) +#define pmd_populate(mm, pmd, pte) \ + (pmd_val(*(pmd)) = (unsigned long)page_address(pte)) #define pmd_populate_kernel(mm, pmd, pte) \ (pmd_val(*(pmd)) = (unsigned long) (pte)) diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h index ca2d928..d4f4216 100644 --- a/arch/microblaze/include/asm/pgtable.h +++ b/arch/microblaze/include/asm/pgtable.h @@ -57,6 +57,13 @@ static inline int pte_file(pte_t pte) { return 0; } #define pgprot_noncached_wc(prot) prot +/* + * All 32bit addresses are effectively valid for vmalloc... + * Sort of meaningless for non-VM targets. + */ +#define VMALLOC_START 0 +#define VMALLOC_END 0xffffffff + #else /* CONFIG_MMU */ #include <asm-generic/4level-fixup.h> diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h index 101fa09..bdc3831 100644 --- a/arch/microblaze/include/asm/prom.h +++ b/arch/microblaze/include/asm/prom.h @@ -27,6 +27,7 @@ /* Other Prototypes */ extern int early_uartlite_console(void); +extern int early_uart16550_console(void); #ifdef CONFIG_PCI /* diff --git a/arch/microblaze/include/asm/pvr.h b/arch/microblaze/include/asm/pvr.h index 9578666..37db96a 100644 --- a/arch/microblaze/include/asm/pvr.h +++ b/arch/microblaze/include/asm/pvr.h @@ -30,7 +30,9 @@ struct pvr_s { #define PVR0_USE_EXC_MASK 0x04000000 #define PVR0_USE_ICACHE_MASK 0x02000000 #define PVR0_USE_DCACHE_MASK 0x01000000 -#define PVR0_USE_MMU 0x00800000 /* new */ +#define PVR0_USE_MMU 0x00800000 +#define PVR0_USE_BTC 0x00400000 +#define PVR0_ENDI 0x00200000 #define PVR0_VERSION_MASK 0x0000FF00 #define PVR0_USER1_MASK 0x000000FF @@ -38,9 +40,9 @@ struct pvr_s { #define PVR1_USER2_MASK 0xFFFFFFFF /* Configuration PVR masks */ -#define PVR2_D_OPB_MASK 0x80000000 +#define PVR2_D_OPB_MASK 0x80000000 /* or AXI */ #define PVR2_D_LMB_MASK 0x40000000 -#define PVR2_I_OPB_MASK 0x20000000 +#define PVR2_I_OPB_MASK 0x20000000 /* or AXI */ #define PVR2_I_LMB_MASK 0x10000000 #define PVR2_INTERRUPT_IS_EDGE_MASK 0x08000000 #define PVR2_EDGE_IS_POSITIVE_MASK 0x04000000 @@ -63,8 +65,8 @@ struct pvr_s { #define PVR2_OPCODE_0x0_ILL_MASK 0x00000040 #define PVR2_UNALIGNED_EXC_MASK 0x00000020 #define PVR2_ILL_OPCODE_EXC_MASK 0x00000010 -#define PVR2_IOPB_BUS_EXC_MASK 0x00000008 -#define PVR2_DOPB_BUS_EXC_MASK 0x00000004 +#define PVR2_IOPB_BUS_EXC_MASK 0x00000008 /* or AXI */ +#define PVR2_DOPB_BUS_EXC_MASK 0x00000004 /* or AXI */ #define PVR2_DIV_ZERO_EXC_MASK 0x00000002 #define PVR2_FPU_EXC_MASK 0x00000001 @@ -208,6 +210,8 @@ struct pvr_s { #define PVR_MMU_TLB_ACCESS(pvr) (pvr.pvr[11] & PVR11_MMU_TLB_ACCESS) #define PVR_MMU_ZONES(pvr) (pvr.pvr[11] & PVR11_MMU_ZONES) +/* endian */ +#define PVR_ENDIAN(pvr) (pvr.pvr[0] & PVR0_ENDI) int cpu_has_pvr(void); void get_pvr(struct pvr_s *pvr); diff --git a/arch/microblaze/include/asm/seccomp.h b/arch/microblaze/include/asm/seccomp.h new file mode 100644 index 0000000..0d91275 --- /dev/null +++ b/arch/microblaze/include/asm/seccomp.h @@ -0,0 +1,16 @@ +#ifndef _ASM_MICROBLAZE_SECCOMP_H +#define _ASM_MICROBLAZE_SECCOMP_H + +#include <linux/unistd.h> + +#define __NR_seccomp_read __NR_read +#define __NR_seccomp_write __NR_write +#define __NR_seccomp_exit __NR_exit +#define __NR_seccomp_sigreturn __NR_sigreturn + +#define __NR_seccomp_read_32 __NR_read +#define __NR_seccomp_write_32 __NR_write +#define __NR_seccomp_exit_32 __NR_exit +#define __NR_seccomp_sigreturn_32 __NR_sigreturn + +#endif /* _ASM_MICROBLAZE_SECCOMP_H */ diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h index 782b5c8..8f39689 100644 --- a/arch/microblaze/include/asm/setup.h +++ b/arch/microblaze/include/asm/setup.h @@ -25,6 +25,12 @@ void early_printk(const char *fmt, ...); int setup_early_printk(char *opt); void disable_early_printk(void); +#if defined(CONFIG_EARLY_PRINTK) +#define eprintk early_printk +#else +#define eprintk printk +#endif + void heartbeat(void); void setup_heartbeat(void); diff --git a/arch/microblaze/include/asm/thread_info.h b/arch/microblaze/include/asm/thread_info.h index 8a8e9fc..b73da2a 100644 --- a/arch/microblaze/include/asm/thread_info.h +++ b/arch/microblaze/include/asm/thread_info.h @@ -127,23 +127,19 @@ static inline struct thread_info *current_thread_info(void) #define TIF_SECCOMP 10 /* secure computing */ #define TIF_FREEZE 14 /* Freezing for suspend */ -/* FIXME change in entry.S */ -#define TIF_KERNEL_TRACE 8 /* kernel trace active */ - /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_POLLING_NRFLAG 16 -#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) -#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) -#define _TIF_SIGPENDING (1<<TIF_SIGPENDING) -#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) -#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) -#define _TIF_IRET (1<<TIF_IRET) -#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) -#define _TIF_FREEZE (1<<TIF_FREEZE) +#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) +#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) +#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) +#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) +#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) +#define _TIF_IRET (1 << TIF_IRET) +#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) +#define _TIF_FREEZE (1 << TIF_FREEZE) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) #define _TIF_SECCOMP (1 << TIF_SECCOMP) -#define _TIF_KERNEL_TRACE (1 << TIF_KERNEL_TRACE) /* work to do in syscall trace */ #define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \ diff --git a/arch/microblaze/include/asm/unaligned.h b/arch/microblaze/include/asm/unaligned.h index 3658d91..2b97cbe 100644 --- a/arch/microblaze/include/asm/unaligned.h +++ b/arch/microblaze/include/asm/unaligned.h @@ -12,12 +12,18 @@ # ifdef __KERNEL__ -# include <linux/unaligned/be_struct.h> +# include <linux/unaligned/be_byteshift.h> # include <linux/unaligned/le_byteshift.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 /* _ASM_MICROBLAZE_UNALIGNED_H */ diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index 2b67e92..d770b00 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -383,8 +383,11 @@ #define __NR_rt_tgsigqueueinfo 365 /* new */ #define __NR_perf_event_open 366 /* new */ #define __NR_recvmmsg 367 /* new */ +#define __NR_fanotify_init 368 +#define __NR_fanotify_mark 369 +#define __NR_prlimit64 370 -#define __NR_syscalls 368 +#define __NR_syscalls 371 #ifdef __KERNEL__ #ifndef __ASSEMBLY__ diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c index f72dbd6..f70a604 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c @@ -72,6 +72,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) CI(pvr_user2, USER2); CI(mmu, USE_MMU); + CI(endian, ENDIAN); CI(use_icache, USE_ICACHE); CI(icache_tagbits, ICACHE_ADDR_TAG_BITS); diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c index 6095aa6..b16b994 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-static.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c @@ -119,6 +119,7 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) ci->pvr_user2 = fcpu(cpu, "xlnx,pvr-user2"); ci->mmu = fcpu(cpu, "xlnx,use-mmu"); + ci->endian = fcpu(cpu, "xlnx,endianness"); ci->ver_code = 0; ci->fpga_family_code = 0; diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 255ef88..87c79fa 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -30,6 +30,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = { {"7.20.c", 0x0e}, {"7.20.d", 0x0f}, {"7.30.a", 0x10}, + {"7.30.b", 0x11}, + {"8.00.a", 0x12}, {NULL, 0}, }; diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c index 7086e35..b4048af 100644 --- a/arch/microblaze/kernel/cpu/mb.c +++ b/arch/microblaze/kernel/cpu/mb.c @@ -51,11 +51,12 @@ static int show_cpuinfo(struct seq_file *m, void *v) count = seq_printf(m, "CPU-Family: MicroBlaze\n" "FPGA-Arch: %s\n" - "CPU-Ver: %s\n" + "CPU-Ver: %s, %s endian\n" "CPU-MHz: %d.%02d\n" "BogoMips: %lu.%02lu\n", fpga_family, cpu_ver, + cpuinfo.endian ? "little" : "big", cpuinfo.cpu_clock_freq / 1000000, cpuinfo.cpu_clock_freq % diff --git a/arch/microblaze/kernel/cpu/pvr.c b/arch/microblaze/kernel/cpu/pvr.c index 9bee938..e01afa6 100644 --- a/arch/microblaze/kernel/cpu/pvr.c +++ b/arch/microblaze/kernel/cpu/pvr.c @@ -27,7 +27,7 @@ register unsigned tmp __asm__("r3"); \ tmp = 0x0; /* Prevent warning about unused */ \ __asm__ __volatile__ ( \ - ".byte 0x94,0x60,0xa0, " #pvrid "\n\t" \ + "mfs %0, rpvr" #pvrid ";" \ : "=r" (tmp) : : "memory"); \ val = tmp; \ } diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c index 7de8492..c3616a0 100644 --- a/arch/microblaze/kernel/early_printk.c +++ b/arch/microblaze/kernel/early_printk.c @@ -24,7 +24,8 @@ static u32 early_console_initialized; static u32 base_addr; -static void early_printk_putc(char c) +#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE +static void early_printk_uartlite_putc(char c) { /* * Limit how many times we'll spin waiting for TX FIFO status. @@ -45,25 +46,70 @@ static void early_printk_putc(char c) out_be32(base_addr + 4, c & 0xff); } -static void early_printk_write(struct console *unused, +static void early_printk_uartlite_write(struct console *unused, const char *s, unsigned n) { while (*s && n-- > 0) { - early_printk_putc(*s); + early_printk_uartlite_putc(*s); if (*s == '\n') - early_printk_putc('\r'); + early_printk_uartlite_putc('\r'); s++; } } -static struct console early_serial_console = { +static struct console early_serial_uartlite_console = { .name = "earlyser", - .write = early_printk_write, + .write = early_printk_uartlite_write, .flags = CON_PRINTBUFFER, .index = -1, }; +#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */ -static struct console *early_console = &early_serial_console; +#ifdef CONFIG_SERIAL_8250_CONSOLE +static void early_printk_uart16550_putc(char c) +{ + /* + * Limit how many times we'll spin waiting for TX FIFO status. + * This will prevent lockups if the base address is incorrectly + * set, or any other issue on the UARTLITE. + * This limit is pretty arbitrary, unless we are at about 10 baud + * we'll never timeout on a working UART. + */ + + #define UART_LSR_TEMT 0x40 /* Transmitter empty */ + #define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ + #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + + unsigned retries = 10000; + + while (--retries && + !((in_be32(base_addr + 0x14) & BOTH_EMPTY) == BOTH_EMPTY)) + ; + + if (retries) + out_be32(base_addr, c & 0xff); +} + +static void early_printk_uart16550_write(struct console *unused, + const char *s, unsigned n) +{ + while (*s && n-- > 0) { + early_printk_uart16550_putc(*s); + if (*s == '\n') + early_printk_uart16550_putc('\r'); + s++; + } +} + +static struct console early_serial_uart16550_console = { + .name = "earlyser", + .write = early_printk_uart16550_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; +#endif /* CONFIG_SERIAL_8250_CONSOLE */ + +static struct console *early_console; void early_printk(const char *fmt, ...) { @@ -84,20 +130,43 @@ int __init setup_early_printk(char *opt) if (early_console_initialized) return 1; +#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE base_addr = early_uartlite_console(); if (base_addr) { early_console_initialized = 1; #ifdef CONFIG_MMU early_console_reg_tlb_alloc(base_addr); #endif + early_console = &early_serial_uartlite_console; early_printk("early_printk_console is enabled at 0x%08x\n", base_addr); /* register_console(early_console); */ return 0; - } else - return 1; + } +#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */ + +#ifdef CONFIG_SERIAL_8250_CONSOLE + base_addr = early_uart16550_console(); + base_addr &= ~3; /* clear register offset */ + if (base_addr) { + early_console_initialized = 1; +#ifdef CONFIG_MMU + early_console_reg_tlb_alloc(base_addr); +#endif + early_console = &early_serial_uart16550_console; + + early_printk("early_printk_console is enabled at 0x%08x\n", + base_addr); + + /* register_console(early_console); */ + + return 0; + } +#endif /* CONFIG_SERIAL_8250_CONSOLE */ + + return 1; } void __init disable_early_printk(void) diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 304882e..819238b 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -186,6 +186,8 @@ swi r13, r1, PTO+PT_R13; /* Save SDA2 */ \ swi r14, r1, PTO+PT_PC; /* PC, before IRQ/trap */ \ swi r15, r1, PTO+PT_R15; /* Save LP */ \ + swi r16, r1, PTO+PT_R16; \ + swi r17, r1, PTO+PT_R17; \ swi r18, r1, PTO+PT_R18; /* Save asm scratch reg */ \ swi r19, r1, PTO+PT_R19; \ swi r20, r1, PTO+PT_R20; \ @@ -220,6 +222,8 @@ lwi r13, r1, PTO+PT_R13; /* restore SDA2 */ \ lwi r14, r1, PTO+PT_PC; /* RESTORE_LINK PC, before IRQ/trap */\ lwi r15, r1, PTO+PT_R15; /* restore LP */ \ + lwi r16, r1, PTO+PT_R16; \ + lwi r17, r1, PTO+PT_R17; \ lwi r18, r1, PTO+PT_R18; /* restore asm scratch reg */ \ lwi r19, r1, PTO+PT_R19; \ lwi r20, r1, PTO+PT_R20; \ @@ -295,6 +299,8 @@ C_ENTRY(_user_exception): /* addik r1, r1, -STATE_SAVE_SIZE; */ addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; SAVE_REGS + swi r0, r1, PTO + PT_R3 + swi r0, r1, PTO + PT_R4 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); swi r11, r1, PTO+PT_R1; /* Store user SP. */ @@ -458,14 +464,8 @@ C_ENTRY(sys_execve): addik r8, r1, PTO; /* add user context as 4th arg */ C_ENTRY(sys_rt_sigreturn_wrapper): - swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - swi r4, r1, PTO+PT_R4; - brlid r15, sys_rt_sigreturn /* Do real work */ + brid sys_rt_sigreturn /* Do real work */ addik r5, r1, PTO; /* add user context as 1st arg */ - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; - bri ret_from_trap /* fall through will not work here due to align */ - nop; /* * HW EXCEPTION rutine start @@ -765,9 +765,7 @@ C_ENTRY(_debug_exception): /* save all regs to pt_reg structure */ swi r0, r1, PTO+PT_R0; /* R0 must be saved too */ swi r14, r1, PTO+PT_R14 /* rewrite saved R14 value */ - swi r16, r1, PTO+PT_R16 swi r16, r1, PTO+PT_PC; /* PC and r16 are the same */ - swi r17, r1, PTO+PT_R17 /* save special purpose registers to pt_regs */ mfs r11, rear; swi r11, r1, PTO+PT_EAR; @@ -801,8 +799,6 @@ C_ENTRY(_debug_exception): addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ SAVE_REGS; - swi r17, r1, PTO+PT_R17; - swi r16, r1, PTO+PT_R16; swi r16, r1, PTO+PT_PC; /* Save LP */ swi r0, r1, PTO + PT_MODE; /* Was in user-mode. */ lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); @@ -848,8 +844,6 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */ tophys(r1,r1); /* MS: Restore all regs */ RESTORE_REGS - lwi r17, r1, PTO+PT_R17; - lwi r16, r1, PTO+PT_R16; addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space */ lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */ DBTRAP_return_user: /* MS: Make global symbol for debugging */ @@ -863,7 +857,6 @@ DBTRAP_return_user: /* MS: Make global symbol for debugging */ RESTORE_REGS lwi r14, r1, PTO+PT_R14; lwi r16, r1, PTO+PT_PC; - lwi r17, r1, PTO+PT_R17; addik r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */ tovirt(r1,r1); DBTRAP_return_kernel: /* MS: Make global symbol for debugging */ diff --git a/arch/microblaze/kernel/exceptions.c b/arch/microblaze/kernel/exceptions.c index b98ee8d..478f294 100644 --- a/arch/microblaze/kernel/exceptions.c +++ b/arch/microblaze/kernel/exceptions.c @@ -72,7 +72,6 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, int fsr, int addr) { #ifdef CONFIG_MMU - int code; addr = regs->pc; #endif @@ -86,8 +85,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, switch (type & 0x1F) { case MICROBLAZE_ILL_OPCODE_EXCEPTION: if (user_mode(regs)) { - pr_debug(KERN_WARNING "Illegal opcode exception " \ - "in user mode.\n"); + pr_debug("Illegal opcode exception in user mode\n"); _exception(SIGILL, regs, ILL_ILLOPC, addr); return; } @@ -97,8 +95,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, break; case MICROBLAZE_IBUS_EXCEPTION: if (user_mode(regs)) { - pr_debug(KERN_WARNING "Instruction bus error " \ - "exception in user mode.\n"); + pr_debug("Instruction bus error exception in user mode\n"); _exception(SIGBUS, regs, BUS_ADRERR, addr); return; } @@ -108,8 +105,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, break; case MICROBLAZE_DBUS_EXCEPTION: if (user_mode(regs)) { - pr_debug(KERN_WARNING "Data bus error exception " \ - "in user mode.\n"); + pr_debug("Data bus error exception in user mode\n"); _exception(SIGBUS, regs, BUS_ADRERR, addr); return; } @@ -119,8 +115,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, break; case MICROBLAZE_DIV_ZERO_EXCEPTION: if (user_mode(regs)) { - pr_debug(KERN_WARNING "Divide by zero exception " \ - "in user mode\n"); + pr_debug("Divide by zero exception in user mode\n"); _exception(SIGILL, regs, FPE_INTDIV, addr); return; } @@ -129,7 +124,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, die("Divide by zero exception", regs, SIGBUS); break; case MICROBLAZE_FPU_EXCEPTION: - pr_debug(KERN_WARNING "FPU exception\n"); + pr_debug("FPU exception\n"); /* IEEE FP exception */ /* I removed fsr variable and use code var for storing fsr */ if (fsr & FSR_IO) @@ -147,14 +142,8 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, #ifdef CONFIG_MMU case MICROBLAZE_PRIVILEGED_EXCEPTION: - pr_debug(KERN_WARNING "Privileged exception\n"); - /* "brk r0,r0" - used as debug breakpoint - old toolchain */ - if (get_user(code, (unsigned long *)regs->pc) == 0 - && code == 0x980c0000) { - _exception(SIGTRAP, regs, TRAP_BRKPT, addr); - } else { - _exception(SIGILL, regs, ILL_PRVOPC, addr); - } + pr_debug("Privileged exception\n"); + _exception(SIGILL, regs, ILL_PRVOPC, addr); break; #endif default: diff --git a/arch/microblaze/kernel/heartbeat.c b/arch/microblaze/kernel/heartbeat.c index 5227517..154756f 100644 --- a/arch/microblaze/kernel/heartbeat.c +++ b/arch/microblaze/kernel/heartbeat.c @@ -47,11 +47,10 @@ void setup_heartbeat(void) struct device_node *gpio = NULL; int *prop; int j; - char *gpio_list[] = { - "xlnx,xps-gpio-1.00.a", - "xlnx,opb-gpio-1.00.a", - NULL - }; + const char * const gpio_list[] = { + "xlnx,xps-gpio-1.00.a", + NULL + }; for (j = 0; gpio_list[j] != NULL; j++) { gpio = of_find_compatible_node(NULL, NULL, gpio_list[j]); @@ -60,7 +59,7 @@ void setup_heartbeat(void) } 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); printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr); diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index 03172c1..d61ea33 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c @@ -126,11 +126,8 @@ void __init init_IRQ(void) 0 }; #endif - static char *intc_list[] = { + const char * const intc_list[] = { "xlnx,xps-intc-1.00.a", - "xlnx,opb-intc-1.00.c", - "xlnx,opb-intc-1.00.b", - "xlnx,opb-intc-1.00.a", NULL }; @@ -141,12 +138,15 @@ void __init init_IRQ(void) } 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); - 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 = - *(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))) printk(KERN_INFO " ERROR: Mismatch in kind-of-intr param\n"); diff --git a/arch/microblaze/kernel/kgdb.c b/arch/microblaze/kernel/kgdb.c index bfc006b..09a5e82 100644 --- a/arch/microblaze/kernel/kgdb.c +++ b/arch/microblaze/kernel/kgdb.c @@ -80,7 +80,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) void microblaze_kgdb_break(struct pt_regs *regs) { if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0) - return 0; + return; /* Jump over the first arch_kgdb_breakpoint which is barrier to * get kgdb work. The same solution is used for powerpc */ @@ -114,7 +114,6 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, { char *ptr; unsigned long address; - int cpu = smp_processor_id(); switch (remcom_in_buffer[0]) { case 'c': @@ -143,5 +142,9 @@ void kgdb_arch_exit(void) * Global data */ struct kgdb_arch arch_kgdb_ops = { +#ifdef __MICROBLAZEEL__ + .gdb_bpt_instr = {0x18, 0x00, 0x0c, 0xba}, /* brki r16, 0x18 */ +#else .gdb_bpt_instr = {0xba, 0x0c, 0x00, 0x18}, /* brki r16, 0x18 */ +#endif }; diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c index ff85f77..5cb0341 100644 --- a/arch/microblaze/kernel/microblaze_ksyms.c +++ b/arch/microblaze/kernel/microblaze_ksyms.c @@ -15,37 +15,13 @@ #include <linux/syscalls.h> #include <asm/checksum.h> +#include <asm/cacheflush.h> #include <linux/io.h> #include <asm/page.h> #include <asm/system.h> #include <linux/ftrace.h> #include <linux/uaccess.h> -/* - * libgcc functions - functions that are used internally by the - * compiler... (prototypes are not correct though, but that - * doesn't really matter since they're not versioned). - */ -extern void __ashldi3(void); -EXPORT_SYMBOL(__ashldi3); -extern void __ashrdi3(void); -EXPORT_SYMBOL(__ashrdi3); -extern void __divsi3(void); -EXPORT_SYMBOL(__divsi3); -extern void __lshrdi3(void); -EXPORT_SYMBOL(__lshrdi3); -extern void __modsi3(void); -EXPORT_SYMBOL(__modsi3); -extern void __mulsi3(void); -EXPORT_SYMBOL(__mulsi3); -extern void __muldi3(void); -EXPORT_SYMBOL(__muldi3); -extern void __ucmpdi2(void); -EXPORT_SYMBOL(__ucmpdi2); -extern void __udivsi3(void); -EXPORT_SYMBOL(__udivsi3); -extern void __umodsi3(void); -EXPORT_SYMBOL(__umodsi3); extern char *_ebss; EXPORT_SYMBOL_GPL(_ebss); #ifdef CONFIG_FUNCTION_TRACER @@ -63,3 +39,9 @@ EXPORT_SYMBOL(__strncpy_user); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memmove); #endif + +#ifdef CONFIG_MMU +EXPORT_SYMBOL(empty_zero_page); +#endif + +EXPORT_SYMBOL(mbc); diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c index bacbd3d..a105301 100644 --- a/arch/microblaze/kernel/prom.c +++ b/arch/microblaze/kernel/prom.c @@ -72,11 +72,12 @@ static int __init early_init_dt_scan_serial(unsigned long node, /* find compatible node with uartlite */ p = of_get_flat_dt_prop(node, "compatible", &l); 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; 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 */ @@ -84,6 +85,40 @@ int __init early_uartlite_console(void) { return of_scan_flat_dt(early_init_dt_scan_serial, NULL); } + +/* MS this is Microblaze specifig function */ +static int __init early_init_dt_scan_serial_full(unsigned long node, + const char *uname, int depth, void *data) +{ + unsigned long l; + char *p; + unsigned int addr; + + pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); + +/* find all serial nodes */ + if (strncmp(uname, "serial", 6) != 0) + return 0; + + early_init_dt_check_for_initrd(node); + +/* find compatible node with uartlite */ + p = of_get_flat_dt_prop(node, "compatible", &l); + + if ((strncmp(p, "xlnx,xps-uart16550", 18) != 0) && + (strncmp(p, "xlnx,axi-uart16550", 18) != 0)) + return 0; + + addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l); + addr += *(u32 *)of_get_flat_dt_prop(node, "reg-offset", &l); + return be32_to_cpu(addr); /* return address */ +} + +/* this function is looking for early uartlite console - Microblaze specific */ +int __init early_uart16550_console(void) +{ + return of_scan_flat_dt(early_init_dt_scan_serial_full, NULL); +} #endif void __init early_init_devtree(void *params) diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index f5f7688..bb1558e 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -92,12 +92,6 @@ inline unsigned get_romfs_len(unsigned *addr) } #endif /* CONFIG_MTD_UCLINUX_EBSS */ -#if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE) -#define eprintk early_printk -#else -#define eprintk printk -#endif - void __init machine_early_init(const char *cmdline, unsigned int ram, unsigned int fdt, unsigned int msr) { diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index 03376dc..e88a930 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -372,3 +372,6 @@ ENTRY(sys_call_table) .long sys_rt_tgsigqueueinfo /* 365 */ .long sys_perf_event_open .long sys_recvmmsg + .long sys_fanotify_init + .long sys_fanotify_mark + .long sys_prlimit64 /* 370 */ diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index b1380ae..a5aa33d 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -38,6 +38,9 @@ static unsigned int timer_baseaddr; #define TIMER_BASE timer_baseaddr #endif +unsigned int freq_div_hz; +unsigned int timer_clock_freq; + #define TCSR0 (0x00) #define TLR0 (0x04) #define TCR0 (0x08) @@ -115,7 +118,7 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: printk(KERN_INFO "%s: periodic\n", __func__); - microblaze_timer0_start_periodic(cpuinfo.freq_div_hz); + microblaze_timer0_start_periodic(freq_div_hz); break; case CLOCK_EVT_MODE_ONESHOT: printk(KERN_INFO "%s: oneshot\n", __func__); @@ -168,7 +171,7 @@ static struct irqaction timer_irqaction = { static __init void microblaze_clockevent_init(void) { clockevent_microblaze_timer.mult = - div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC, + div_sc(timer_clock_freq, NSEC_PER_SEC, clockevent_microblaze_timer.shift); clockevent_microblaze_timer.max_delta_ns = clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer); @@ -201,7 +204,7 @@ static struct cyclecounter microblaze_cc = { int __init init_microblaze_timecounter(void) { - microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC, + microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC, microblaze_cc.shift); timecounter_init(µblaze_tc, µblaze_cc, sched_clock()); @@ -221,7 +224,7 @@ static struct clocksource clocksource_microblaze = { static int __init microblaze_clocksource_init(void) { clocksource_microblaze.mult = - clocksource_hz2mult(cpuinfo.cpu_clock_freq, + clocksource_hz2mult(timer_clock_freq, clocksource_microblaze.shift); if (clocksource_register(&clocksource_microblaze)) panic("failed to register clocksource"); @@ -247,6 +250,7 @@ void __init time_init(void) u32 irq, i = 0; u32 timer_num = 1; struct device_node *timer = NULL; + const void *prop; #ifdef CONFIG_SELFMOD_TIMER unsigned int timer_baseaddr = 0; int arr_func[] = { @@ -258,12 +262,10 @@ void __init time_init(void) 0 }; #endif - char *timer_list[] = { - "xlnx,xps-timer-1.00.a", - "xlnx,opb-timer-1.00.b", - "xlnx,opb-timer-1.00.a", - NULL - }; + const char * const timer_list[] = { + "xlnx,xps-timer-1.00.a", + NULL + }; for (i = 0; timer_list[i] != NULL; i++) { timer = of_find_compatible_node(NULL, NULL, timer_list[i]); @@ -272,13 +274,13 @@ void __init time_init(void) } 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); - irq = *(int *) of_get_property(timer, "interrupts", NULL); - timer_num = - *(int *) of_get_property(timer, "xlnx,one-timer-only", NULL); + irq = be32_to_cpup(of_get_property(timer, "interrupts", NULL)); + timer_num = be32_to_cpup(of_get_property(timer, + "xlnx,one-timer-only", NULL)); if (timer_num) { - printk(KERN_EMERG "Please enable two timers in HW\n"); + eprintk(KERN_EMERG "Please enable two timers in HW\n"); BUG(); } @@ -288,7 +290,14 @@ void __init time_init(void) printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n", timer_list[i], timer_baseaddr, irq); - cpuinfo.freq_div_hz = cpuinfo.cpu_clock_freq / HZ; + /* If there is clock-frequency property than use it */ + prop = of_get_property(timer, "clock-frequency", NULL); + if (prop) + timer_clock_freq = be32_to_cpup(prop); + else + timer_clock_freq = cpuinfo.cpu_clock_freq; + + freq_div_hz = timer_clock_freq / HZ; setup_irq(irq, &timer_irqaction); #ifdef CONFIG_HEART_BEAT diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S index a09f296..96a88c3 100644 --- a/arch/microblaze/kernel/vmlinux.lds.S +++ b/arch/microblaze/kernel/vmlinux.lds.S @@ -8,7 +8,6 @@ * for more details. */ -OUTPUT_FORMAT("elf32-microblaze", "elf32-microblaze", "elf32-microblaze") OUTPUT_ARCH(microblaze) ENTRY(microblaze_start) @@ -16,7 +15,11 @@ ENTRY(microblaze_start) #include <asm-generic/vmlinux.lds.h> #include <asm/thread_info.h> +#ifdef __MICROBLAZEEL__ +jiffies = jiffies_64; +#else jiffies = jiffies_64 + 4; +#endif SECTIONS { . = CONFIG_KERNEL_START; diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile index 4dfe47d..f1fcbff 100644 --- a/arch/microblaze/lib/Makefile +++ b/arch/microblaze/lib/Makefile @@ -11,3 +11,13 @@ lib-y += memcpy.o memmove.o endif lib-y += uaccess_old.o + +lib-y += ashldi3.o +lib-y += ashrdi3.o +lib-y += divsi3.o +lib-y += lshrdi3.o +lib-y += modsi3.o +lib-y += muldi3.o +lib-y += mulsi3.o +lib-y += udivsi3.o +lib-y += umodsi3.o diff --git a/arch/microblaze/lib/ashldi3.c b/arch/microblaze/lib/ashldi3.c new file mode 100644 index 0000000..beb80f31 --- /dev/null +++ b/arch/microblaze/lib/ashldi3.c @@ -0,0 +1,29 @@ +#include <linux/module.h> + +#include "libgcc.h" + +long long __ashldi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.low = 0; + w.s.high = (unsigned int) uu.s.low << -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.low >> bm; + + w.s.low = (unsigned int) uu.s.low << b; + w.s.high = ((unsigned int) uu.s.high << b) | carries; + } + + return w.ll; +} + +EXPORT_SYMBOL(__ashldi3); diff --git a/arch/microblaze/lib/ashrdi3.c b/arch/microblaze/lib/ashrdi3.c new file mode 100644 index 0000000..c884a91 --- /dev/null +++ b/arch/microblaze/lib/ashrdi3.c @@ -0,0 +1,31 @@ +#include <linux/module.h> + +#include "libgcc.h" + +long long __ashrdi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = + uu.s.high >> 31; + w.s.low = uu.s.high >> -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.high << bm; + + w.s.high = uu.s.high >> b; + w.s.low = ((unsigned int) uu.s.low >> b) | carries; + } + + return w.ll; +} + +EXPORT_SYMBOL(__ashrdi3); diff --git a/arch/microblaze/lib/divsi3.S b/arch/microblaze/lib/divsi3.S new file mode 100644 index 0000000..595b02d --- /dev/null +++ b/arch/microblaze/lib/divsi3.S @@ -0,0 +1,73 @@ +#include <linux/linkage.h> + +/* +* Divide operation for 32 bit integers. +* Input : Dividend in Reg r5 +* Divisor in Reg r6 +* Output: Result in Reg r3 +*/ + .text + .globl __divsi3 + .type __divsi3, @function + .ent __divsi3 +__divsi3: + .frame r1, 0, r15 + + addik r1, r1, -16 + swi r28, r1, 0 + swi r29, r1, 4 + swi r30, r1, 8 + swi r31, r1, 12 + + beqi r6, div_by_zero /* div_by_zero - division error */ + beqi r5, result_is_zero /* result is zero */ + bgeid r5, r5_pos + xor r28, r5, r6 /* get the sign of the result */ + rsubi r5, r5, 0 /* make r5 positive */ +r5_pos: + bgei r6, r6_pos + rsubi r6, r6, 0 /* make r6 positive */ +r6_pos: + addik r30, r0, 0 /* clear mod */ + addik r3, r0, 0 /* clear div */ + addik r29, r0, 32 /* initialize the loop count */ + + /* first part try to find the first '1' in the r5 */ +div0: + blti r5, div2 /* this traps r5 == 0x80000000 */ +div1: + add r5, r5, r5 /* left shift logical r5 */ + bgtid r5, div1 + addik r29, r29, -1 +div2: + /* left shift logical r5 get the '1' into the carry */ + add r5, r5, r5 + addc r30, r30, r30 /* move that bit into the mod register */ + rsub r31, r6, r30 /* try to subtract (r30 a r6) */ + blti r31, mod_too_small + /* move the r31 to mod since the result was positive */ + or r30, r0, r31 + addik r3, r3, 1 +mod_too_small: + addik r29, r29, -1 + beqi r29, loop_end + add r3, r3, r3 /* shift in the '1' into div */ + bri div2 /* div2 */ +loop_end: + bgei r28, return_here + brid return_here + rsubi r3, r3, 0 /* negate the result */ +div_by_zero: +result_is_zero: + or r3, r0, r0 /* set result to 0 */ +return_here: +/* restore values of csrs and that of r3 and the divisor and the dividend */ + lwi r28, r1, 0 + lwi r29, r1, 4 + lwi r30, r1, 8 + lwi r31, r1, 12 + rtsd r15, 8 + addik r1, r1, 16 + +.size __divsi3, . - __divsi3 +.end __divsi3 diff --git a/arch/microblaze/lib/libgcc.h b/arch/microblaze/lib/libgcc.h new file mode 100644 index 0000000..05909d58 --- /dev/null +++ b/arch/microblaze/lib/libgcc.h @@ -0,0 +1,25 @@ +#ifndef __ASM_LIBGCC_H +#define __ASM_LIBGCC_H + +#include <asm/byteorder.h> + +typedef int word_type __attribute__ ((mode (__word__))); + +#ifdef __BIG_ENDIAN +struct DWstruct { + int high, low; +}; +#elif defined(__LITTLE_ENDIAN) +struct DWstruct { + int low, high; +}; +#else +#error I feel sick. +#endif + +typedef union { + struct DWstruct s; + long long ll; +} DWunion; + +#endif /* __ASM_LIBGCC_H */ diff --git a/arch/microblaze/lib/lshrdi3.c b/arch/microblaze/lib/lshrdi3.c new file mode 100644 index 0000000..dcf8d68 --- /dev/null +++ b/arch/microblaze/lib/lshrdi3.c @@ -0,0 +1,29 @@ +#include <linux/module.h> + +#include "libgcc.h" + +long long __lshrdi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.high = 0; + w.s.low = (unsigned int) uu.s.high >> -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.high << bm; + + w.s.high = (unsigned int) uu.s.high >> b; + w.s.low = ((unsigned int) uu.s.low >> b) | carries; + } + + return w.ll; +} + +EXPORT_SYMBOL(__lshrdi3); diff --git a/arch/microblaze/lib/memcpy.c b/arch/microblaze/lib/memcpy.c index 014bac9..cc495d7 100644 --- a/arch/microblaze/lib/memcpy.c +++ b/arch/microblaze/lib/memcpy.c @@ -33,17 +33,24 @@ #include <asm/system.h> #ifdef __HAVE_ARCH_MEMCPY +#ifndef CONFIG_OPT_LIB_FUNCTION void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) { const char *src = v_src; char *dst = v_dst; -#ifndef CONFIG_OPT_LIB_FUNCTION + /* Simple, byte oriented memcpy. */ while (c--) *dst++ = *src++; return v_dst; -#else +} +#else /* CONFIG_OPT_LIB_FUNCTION */ +void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) +{ + const char *src = v_src; + char *dst = v_dst; + /* The following code tries to optimize the copy by using unsigned * alignment. This will work fine if both source and destination are * aligned on the same boundary. However, if they are aligned on @@ -86,7 +93,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) case 0x1: /* Unaligned - Off by 1 */ /* Word align the source */ i_src = (const void *) ((unsigned)src & ~3); - +#ifndef __MICROBLAZEEL__ /* Load the holding buffer */ buf_hold = *i_src++ << 8; @@ -95,7 +102,16 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) *i_dst++ = buf_hold | value >> 24; buf_hold = value << 8; } +#else + /* Load the holding buffer */ + buf_hold = (*i_src++ & 0xFFFFFF00) >>8; + for (; c >= 4; c -= 4) { + value = *i_src++; + *i_dst++ = buf_hold | ((value & 0xFF) << 24); + buf_hold = (value & 0xFFFFFF00) >>8; + } +#endif /* Realign the source */ src = (const void *)i_src; src -= 3; @@ -103,7 +119,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) case 0x2: /* Unaligned - Off by 2 */ /* Word align the source */ i_src = (const void *) ((unsigned)src & ~3); - +#ifndef __MICROBLAZEEL__ /* Load the holding buffer */ buf_hold = *i_src++ << 16; @@ -112,7 +128,16 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) *i_dst++ = buf_hold | value >> 16; buf_hold = value << 16; } +#else + /* Load the holding buffer */ + buf_hold = (*i_src++ & 0xFFFF0000 )>>16; + for (; c >= 4; c -= 4) { + value = *i_src++; + *i_dst++ = buf_hold | ((value & 0xFFFF)<<16); + buf_hold = (value & 0xFFFF0000) >>16; + } +#endif /* Realign the source */ src = (const void *)i_src; src -= 2; @@ -120,7 +145,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) case 0x3: /* Unaligned - Off by 3 */ /* Word align the source */ i_src = (const void *) ((unsigned)src & ~3); - +#ifndef __MICROBLAZEEL__ /* Load the holding buffer */ buf_hold = *i_src++ << 24; @@ -129,7 +154,16 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) *i_dst++ = buf_hold | value >> 8; buf_hold = value << 24; } +#else + /* Load the holding buffer */ + buf_hold = (*i_src++ & 0xFF000000) >> 24; + for (; c >= 4; c -= 4) { + value = *i_src++; + *i_dst++ = buf_hold | ((value & 0xFFFFFF) << 8); + buf_hold = (value & 0xFF000000) >> 24; + } +#endif /* Realign the source */ src = (const void *)i_src; src -= 1; @@ -150,7 +184,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) } return v_dst; -#endif } +#endif /* CONFIG_OPT_LIB_FUNCTION */ EXPORT_SYMBOL(memcpy); #endif /* __HAVE_ARCH_MEMCPY */ diff --git a/arch/microblaze/lib/memmove.c b/arch/microblaze/lib/memmove.c index 0929198..123e361 100644 --- a/arch/microblaze/lib/memmove.c +++ b/arch/microblaze/lib/memmove.c @@ -31,16 +31,12 @@ #include <linux/string.h> #ifdef __HAVE_ARCH_MEMMOVE +#ifndef CONFIG_OPT_LIB_FUNCTION void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) { const char *src = v_src; char *dst = v_dst; -#ifdef CONFIG_OPT_LIB_FUNCTION - const uint32_t *i_src; - uint32_t *i_dst; -#endif - if (!c) return v_dst; @@ -48,7 +44,6 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) if (v_dst <= v_src) return memcpy(v_dst, v_src, c); -#ifndef CONFIG_OPT_LIB_FUNCTION /* copy backwards, from end to beginning */ src += c; dst += c; @@ -58,7 +53,22 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) *--dst = *--src; return v_dst; -#else +} +#else /* CONFIG_OPT_LIB_FUNCTION */ +void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) +{ + const char *src = v_src; + char *dst = v_dst; + const uint32_t *i_src; + uint32_t *i_dst; + + if (!c) + return v_dst; + + /* Use memcpy when source is higher than dest */ + if (v_dst <= v_src) + return memcpy(v_dst, v_src, c); + /* The following code tries to optimize the copy by using unsigned * alignment. This will work fine if both source and destination are * aligned on the same boundary. However, if they are aligned on @@ -104,7 +114,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) case 0x1: /* Unaligned - Off by 1 */ /* Word align the source */ i_src = (const void *) (((unsigned)src + 4) & ~3); - +#ifndef __MICROBLAZEEL__ /* Load the holding buffer */ buf_hold = *--i_src >> 24; @@ -113,7 +123,16 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) *--i_dst = buf_hold << 8 | value; buf_hold = value >> 24; } +#else + /* Load the holding buffer */ + buf_hold = (*--i_src & 0xFF) << 24; + for (; c >= 4; c -= 4) { + value = *--i_src; + *--i_dst = buf_hold | ((value & 0xFFFFFF00)>>8); + buf_hold = (value & 0xFF) << 24; + } +#endif /* Realign the source */ src = (const void *)i_src; src += 1; @@ -121,7 +140,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) case 0x2: /* Unaligned - Off by 2 */ /* Word align the source */ i_src = (const void *) (((unsigned)src + 4) & ~3); - +#ifndef __MICROBLAZEEL__ /* Load the holding buffer */ buf_hold = *--i_src >> 16; @@ -130,7 +149,16 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) *--i_dst = buf_hold << 16 | value; buf_hold = value >> 16; } +#else + /* Load the holding buffer */ + buf_hold = (*--i_src & 0xFFFF) << 16; + for (; c >= 4; c -= 4) { + value = *--i_src; + *--i_dst = buf_hold | ((value & 0xFFFF0000)>>16); + buf_hold = (value & 0xFFFF) << 16; + } +#endif /* Realign the source */ src = (const void *)i_src; src += 2; @@ -138,7 +166,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) case 0x3: /* Unaligned - Off by 3 */ /* Word align the source */ i_src = (const void *) (((unsigned)src + 4) & ~3); - +#ifndef __MICROBLAZEEL__ /* Load the holding buffer */ buf_hold = *--i_src >> 8; @@ -147,7 +175,16 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) *--i_dst = buf_hold << 24 | value; buf_hold = value >> 8; } +#else + /* Load the holding buffer */ + buf_hold = (*--i_src & 0xFFFFFF) << 8; + for (; c >= 4; c -= 4) { + value = *--i_src; + *--i_dst = buf_hold | ((value & 0xFF000000)>> 24); + buf_hold = (value & 0xFFFFFF) << 8;; + } +#endif /* Realign the source */ src = (const void *)i_src; src += 3; @@ -169,7 +206,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) *--dst = *--src; } return v_dst; -#endif } +#endif /* CONFIG_OPT_LIB_FUNCTION */ EXPORT_SYMBOL(memmove); #endif /* __HAVE_ARCH_MEMMOVE */ diff --git a/arch/microblaze/lib/memset.c b/arch/microblaze/lib/memset.c index ecfb663..834565d 100644 --- a/arch/microblaze/lib/memset.c +++ b/arch/microblaze/lib/memset.c @@ -31,17 +31,30 @@ #include <linux/string.h> #ifdef __HAVE_ARCH_MEMSET +#ifndef CONFIG_OPT_LIB_FUNCTION +void *memset(void *v_src, int c, __kernel_size_t n) +{ + char *src = v_src; + + /* Truncate c to 8 bits */ + c = (c & 0xFF); + + /* Simple, byte oriented memset or the rest of count. */ + while (n--) + *src++ = c; + + return v_src; +} +#else /* CONFIG_OPT_LIB_FUNCTION */ void *memset(void *v_src, int c, __kernel_size_t n) { char *src = v_src; -#ifdef CONFIG_OPT_LIB_FUNCTION uint32_t *i_src; uint32_t w32 = 0; -#endif + /* Truncate c to 8 bits */ c = (c & 0xFF); -#ifdef CONFIG_OPT_LIB_FUNCTION if (unlikely(c)) { /* Make a repeating word out of it */ w32 = c; @@ -72,12 +85,13 @@ void *memset(void *v_src, int c, __kernel_size_t n) src = (void *)i_src; } -#endif + /* Simple, byte oriented memset or the rest of count. */ while (n--) *src++ = c; return v_src; } +#endif /* CONFIG_OPT_LIB_FUNCTION */ EXPORT_SYMBOL(memset); #endif /* __HAVE_ARCH_MEMSET */ diff --git a/arch/microblaze/lib/modsi3.S b/arch/microblaze/lib/modsi3.S new file mode 100644 index 0000000..84e0bee --- /dev/null +++ b/arch/microblaze/lib/modsi3.S @@ -0,0 +1,73 @@ +#include <linux/linkage.h> + +/* +* modulo operation for 32 bit integers. +* Input : op1 in Reg r5 +* op2 in Reg r6 +* Output: op1 mod op2 in Reg r3 +*/ + + .text + .globl __modsi3 + .type __modsi3, @function + .ent __modsi3 + +__modsi3: + .frame r1, 0, r15 + + addik r1, r1, -16 + swi r28, r1, 0 + swi r29, r1, 4 + swi r30, r1, 8 + swi r31, r1, 12 + + beqi r6, div_by_zero /* div_by_zero division error */ + beqi r5, result_is_zero /* result is zero */ + bgeid r5, r5_pos + /* get the sign of the result [ depends only on the first arg] */ + add r28, r5, r0 + rsubi r5, r5, 0 /* make r5 positive */ +r5_pos: + bgei r6, r6_pos + rsubi r6, r6, 0 /* make r6 positive */ +r6_pos: + addik r3, r0, 0 /* clear mod */ + addik r30, r0, 0 /* clear div */ + addik r29, r0, 32 /* initialize the loop count */ +/* first part try to find the first '1' in the r5 */ +div1: + add r5, r5, r5 /* left shift logical r5 */ + bgeid r5, div1 + addik r29, r29, -1 +div2: + /* left shift logical r5 get the '1' into the carry */ + add r5, r5, r5 + addc r3, r3, r3 /* move that bit into the mod register */ + rsub r31, r6, r3 /* try to subtract (r30 a r6) */ + blti r31, mod_too_small + /* move the r31 to mod since the result was positive */ + or r3, r0, r31 + addik r30, r30, 1 +mod_too_small: + addik r29, r29, -1 + beqi r29, loop_end + add r30, r30, r30 /* shift in the '1' into div */ + bri div2 /* div2 */ +loop_end: + bgei r28, return_here + brid return_here + rsubi r3, r3, 0 /* negate the result */ +div_by_zero: +result_is_zero: + or r3, r0, r0 /* set result to 0 [both mod as well as div are 0] */ +return_here: +/* restore values of csrs and that of r3 and the divisor and the dividend */ + lwi r28, r1, 0 + lwi r29, r1, 4 + lwi r30, r1, 8 + lwi r31, r1, 12 + rtsd r15, 8 + addik r1, r1, 16 + +.size __modsi3, . - __modsi3 +.end __modsi3 diff --git a/arch/microblaze/lib/muldi3.S b/arch/microblaze/lib/muldi3.S new file mode 100644 index 0000000..ceeaa8c --- /dev/null +++ b/arch/microblaze/lib/muldi3.S @@ -0,0 +1,121 @@ +#include <linux/linkage.h> + +/* + * Multiply operation for 64 bit integers, for devices with hard multiply + * Input : Operand1[H] in Reg r5 + * Operand1[L] in Reg r6 + * Operand2[H] in Reg r7 + * Operand2[L] in Reg r8 + * Output: Result[H] in Reg r3 + * Result[L] in Reg r4 + * + * Explaination: + * + * Both the input numbers are divided into 16 bit number as follows + * op1 = A B C D + * op2 = E F G H + * result = D * H + * + (C * H + D * G) << 16 + * + (B * H + C * G + D * F) << 32 + * + (A * H + B * G + C * F + D * E) << 48 + * + * Only 64 bits of the output are considered + */ + + .text + .globl __muldi3 + .type __muldi3, @function + .ent __muldi3 + +__muldi3: + addi r1, r1, -40 + +/* Save the input operands on the caller's stack */ + swi r5, r1, 44 + swi r6, r1, 48 + swi r7, r1, 52 + swi r8, r1, 56 + +/* Store all the callee saved registers */ + sw r20, r1, r0 + swi r21, r1, 4 + swi r22, r1, 8 + swi r23, r1, 12 + swi r24, r1, 16 + swi r25, r1, 20 + swi r26, r1, 24 + swi r27, r1, 28 + +/* Load all the 16 bit values for A thru H */ + lhui r20, r1, 44 /* A */ + lhui r21, r1, 46 /* B */ + lhui r22, r1, 48 /* C */ + lhui r23, r1, 50 /* D */ + lhui r24, r1, 52 /* E */ + lhui r25, r1, 54 /* F */ + lhui r26, r1, 56 /* G */ + lhui r27, r1, 58 /* H */ + +/* D * H ==> LSB of the result on stack ==> Store1 */ + mul r9, r23, r27 + swi r9, r1, 36 /* Pos2 and Pos3 */ + +/* Hi (Store1) + C * H + D * G ==> Store2 ==> Pos1 and Pos2 */ +/* Store the carry generated in position 2 for Pos 3 */ + lhui r11, r1, 36 /* Pos2 */ + mul r9, r22, r27 /* C * H */ + mul r10, r23, r26 /* D * G */ + add r9, r9, r10 + addc r12, r0, r0 + add r9, r9, r11 + addc r12, r12, r0 /* Store the Carry */ + shi r9, r1, 36 /* Store Pos2 */ + swi r9, r1, 32 + lhui r11, r1, 32 + shi r11, r1, 34 /* Store Pos1 */ + +/* Hi (Store2) + B * H + C * G + D * F ==> Store3 ==> Pos0 and Pos1 */ + mul r9, r21, r27 /* B * H */ + mul r10, r22, r26 /* C * G */ + mul r7, r23, r25 /* D * F */ + add r9, r9, r11 + add r9, r9, r10 + add r9, r9, r7 + swi r9, r1, 32 /* Pos0 and Pos1 */ + +/* Hi (Store3) + A * H + B * G + C * F + D * E ==> Store3 ==> Pos0 */ + lhui r11, r1, 32 /* Pos0 */ + mul r9, r20, r27 /* A * H */ + mul r10, r21, r26 /* B * G */ + mul r7, r22, r25 /* C * F */ + mul r8, r23, r24 /* D * E */ + add r9, r9, r11 + add r9, r9, r10 + add r9, r9, r7 + add r9, r9, r8 + sext16 r9, r9 /* Sign extend the MSB */ + shi r9, r1, 32 + +/* Move results to r3 and r4 */ + lhui r3, r1, 32 + add r3, r3, r12 + shi r3, r1, 32 + lwi r3, r1, 32 /* Hi Part */ + lwi r4, r1, 36 /* Lo Part */ + +/* Restore Callee saved registers */ + lw r20, r1, r0 + lwi r21, r1, 4 + lwi r22, r1, 8 + lwi r23, r1, 12 + lwi r24, r1, 16 + lwi r25, r1, 20 + lwi r26, r1, 24 + lwi r27, r1, 28 + +/* Restore Frame and return */ + rtsd r15, 8 + addi r1, r1, 40 + +.size __muldi3, . - __muldi3 +.end __muldi3 diff --git a/arch/microblaze/lib/mulsi3.S b/arch/microblaze/lib/mulsi3.S new file mode 100644 index 0000000..90bd7b9 --- /dev/null +++ b/arch/microblaze/lib/mulsi3.S @@ -0,0 +1,46 @@ +#include <linux/linkage.h> + +/* + * Multiply operation for 32 bit integers. + * Input : Operand1 in Reg r5 + * Operand2 in Reg r6 + * Output: Result [op1 * op2] in Reg r3 + */ + .text + .globl __mulsi3 + .type __mulsi3, @function + .ent __mulsi3 + +__mulsi3: + .frame r1, 0, r15 + add r3, r0, r0 + beqi r5, result_is_zero /* multiply by zero */ + beqi r6, result_is_zero /* multiply by zero */ + bgeid r5, r5_pos + xor r4, r5, r6 /* get the sign of the result */ + rsubi r5, r5, 0 /* make r5 positive */ +r5_pos: + bgei r6, r6_pos + rsubi r6, r6, 0 /* make r6 positive */ +r6_pos: + bri l1 +l2: + add r5, r5, r5 +l1: + srl r6, r6 + addc r7, r0, r0 + beqi r7, l2 + bneid r6, l2 + add r3, r3, r5 + blti r4, negateresult + rtsd r15, 8 + nop +negateresult: + rtsd r15, 8 + rsub r3, r3, r0 +result_is_zero: + rtsd r15, 8 + addi r3, r0, 0 + +.size __mulsi3, . - __mulsi3 +.end __mulsi3 diff --git a/arch/microblaze/lib/udivsi3.S b/arch/microblaze/lib/udivsi3.S new file mode 100644 index 0000000..64cf57e --- /dev/null +++ b/arch/microblaze/lib/udivsi3.S @@ -0,0 +1,84 @@ +#include <linux/linkage.h> + +/* +* Unsigned divide operation. +* Input : Divisor in Reg r5 +* Dividend in Reg r6 +* Output: Result in Reg r3 +*/ + + .text + .globl __udivsi3 + .type __udivsi3, @function + .ent __udivsi3 + +__udivsi3: + + .frame r1, 0, r15 + + addik r1, r1, -12 + swi r29, r1, 0 + swi r30, r1, 4 + swi r31, r1, 8 + + beqi r6, div_by_zero /* div_by_zero /* division error */ + beqid r5, result_is_zero /* result is zero */ + addik r30, r0, 0 /* clear mod */ + addik r29, r0, 32 /* initialize the loop count */ + +/* check if r6 and r5 are equal - if yes, return 1 */ + rsub r18, r5, r6 + beqid r18, return_here + addik r3, r0, 1 + +/* check if (uns)r6 is greater than (uns)r5. in that case, just return 0 */ + xor r18, r5, r6 + bgeid r18, 16 + add r3, r0, r0 /* we would anyways clear r3 */ + blti r6, return_here /* r6[bit 31 = 1] hence is greater */ + bri checkr6 + rsub r18, r6, r5 /* microblazecmp */ + blti r18, return_here + +/* if r6 [bit 31] is set, then return result as 1 */ +checkr6: + bgti r6, div0 + brid return_here + addik r3, r0, 1 + +/* first part try to find the first '1' in the r5 */ +div0: + blti r5, div2 +div1: + add r5, r5, r5 /* left shift logical r5 */ + bgtid r5, div1 + addik r29, r29, -1 +div2: +/* left shift logical r5 get the '1' into the carry */ + add r5, r5, r5 + addc r30, r30, r30 /* move that bit into the mod register */ + rsub r31, r6, r30 /* try to subtract (r30 a r6) */ + blti r31, mod_too_small +/* move the r31 to mod since the result was positive */ + or r30, r0, r31 + addik r3, r3, 1 +mod_too_small: + addik r29, r29, -1 + beqi r29, loop_end + add r3, r3, r3 /* shift in the '1' into div */ + bri div2 /* div2 */ +loop_end: + bri return_here +div_by_zero: +result_is_zero: + or r3, r0, r0 /* set result to 0 */ +return_here: +/* restore values of csrs and that of r3 and the divisor and the dividend */ + lwi r29, r1, 0 + lwi r30, r1, 4 + lwi r31, r1, 8 + rtsd r15, 8 + addik r1, r1, 12 + +.size __udivsi3, . - __udivsi3 +.end __udivsi3 diff --git a/arch/microblaze/lib/umodsi3.S b/arch/microblaze/lib/umodsi3.S new file mode 100644 index 0000000..17d16ba --- /dev/null +++ b/arch/microblaze/lib/umodsi3.S @@ -0,0 +1,86 @@ +#include <linux/linkage.h> + +/* + * Unsigned modulo operation for 32 bit integers. + * Input : op1 in Reg r5 + * op2 in Reg r6 + * Output: op1 mod op2 in Reg r3 + */ + + .text + .globl __umodsi3 + .type __umodsi3, @function + .ent __umodsi3 + +__umodsi3: + .frame r1, 0, r15 + + addik r1, r1, -12 + swi r29, r1, 0 + swi r30, r1, 4 + swi r31, r1, 8 + + beqi r6, div_by_zero /* div_by_zero - division error */ + beqid r5, result_is_zero /* result is zero */ + addik r3, r0, 0 /* clear div */ + addik r30, r0, 0 /* clear mod */ + addik r29, r0, 32 /* initialize the loop count */ + +/* check if r6 and r5 are equal /* if yes, return 0 */ + rsub r18, r5, r6 + beqi r18, return_here + +/* check if (uns)r6 is greater than (uns)r5. in that case, just return r5 */ + xor r18, r5, r6 + bgeid r18, 16 + addik r3, r5, 0 + blti r6, return_here + bri $lcheckr6 + rsub r18, r5, r6 /* microblazecmp */ + bgti r18, return_here + +/* if r6 [bit 31] is set, then return result as r5-r6 */ +$lcheckr6: + bgtid r6, div0 + addik r3, r0, 0 + addik r18, r0, 0x7fffffff + and r5, r5, r18 + and r6, r6, r18 + brid return_here + rsub r3, r6, r5 +/* first part: try to find the first '1' in the r5 */ +div0: + blti r5, div2 +div1: + add r5, r5, r5 /* left shift logical r5 */ + bgeid r5, div1 + addik r29, r29, -1 +div2: + /* left shift logical r5 get the '1' into the carry */ + add r5, r5, r5 + addc r3, r3, r3 /* move that bit into the mod register */ + rsub r31, r6, r3 /* try to subtract (r3 a r6) */ + blti r31, mod_too_small + /* move the r31 to mod since the result was positive */ + or r3, r0, r31 + addik r30, r30, 1 +mod_too_small: + addik r29, r29, -1 + beqi r29, loop_end + add r30, r30, r30 /* shift in the '1' into div */ + bri div2 /* div2 */ +loop_end: + bri return_here +div_by_zero: +result_is_zero: + or r3, r0, r0 /* set result to 0 */ +return_here: +/* restore values of csrs and that of r3 and the divisor and the dividend */ + lwi r29, r1, 0 + lwi r30, r1, 4 + lwi r31, r1, 8 + rtsd r15, 8 + addik r1, r1, 12 + +.size __umodsi3, . - __umodsi3 +.end __umodsi3 diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index 55ef532..e363615 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -60,21 +60,6 @@ struct dma_map_ops *get_pci_dma_ops(void) } EXPORT_SYMBOL(get_pci_dma_ops); -int pci_set_dma_mask(struct pci_dev *dev, u64 mask) -{ - return dma_set_mask(&dev->dev, mask); -} - -int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) -{ - int rc; - - rc = dma_set_mask(&dev->dev, mask); - dev->dev.coherent_dma_mask = dev->dma_mask; - - return rc; -} - struct pci_controller *pcibios_alloc_controller(struct device_node *dev) { struct pci_controller *phb; @@ -1075,8 +1060,6 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) bus->number, bus->self ? pci_name(bus->self) : "PHB"); list_for_each_entry(dev, &bus->devices, bus_list) { - struct dev_archdata *sd = &dev->dev.archdata; - /* Setup OF node pointer in archdata */ dev->dev.of_node = pci_device_to_OF_node(dev); @@ -1086,8 +1069,8 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) set_dev_node(&dev->dev, pcibus_to_node(dev->bus)); /* Hook up default DMA ops */ - sd->dma_ops = pci_dma_ops; - sd->dma_data = (void *)PCI_DRAM_OFFSET; + set_dma_ops(&dev->dev, pci_dma_ops); + dev->dev.archdata.dma_data = (void *)PCI_DRAM_OFFSET; /* Read default IRQs and fixup if necessary */ pci_read_irq_line(dev); diff --git a/arch/microblaze/platform/generic/system.dts b/arch/microblaze/platform/generic/system.dts index 2d5c417..3f85df2 100644 --- a/arch/microblaze/platform/generic/system.dts +++ b/arch/microblaze/platform/generic/system.dts @@ -85,6 +85,7 @@ xlnx,dynamic-bus-sizing = <0x1>; xlnx,edge-is-positive = <0x1>; xlnx,family = "virtex5"; + xlnx,endianness = <0x1>; xlnx,fpu-exception = <0x1>; xlnx,fsl-data-size = <0x20>; xlnx,fsl-exception = <0x0>; @@ -218,6 +219,7 @@ #address-cells = <1>; #size-cells = <1>; compatible = "xlnx,compound"; + ranges ; ethernet@81c00000 { compatible = "xlnx,xps-ll-temac-1.01.b", "xlnx,xps-ll-temac-1.00.a"; device_type = "network"; @@ -332,6 +334,7 @@ #address-cells = <1>; #size-cells = <1>; compatible = "xlnx,mpmc-4.02.a"; + ranges ; PIM3: sdma@84600180 { compatible = "xlnx,ll-dma-1.00.a"; interrupt-parent = <&xps_intc_0>; diff --git a/arch/microblaze/platform/platform.c b/arch/microblaze/platform/platform.c index 5b89b58..b9529ca 100644 --- a/arch/microblaze/platform/platform.c +++ b/arch/microblaze/platform/platform.c @@ -17,9 +17,6 @@ static struct of_device_id xilinx_of_bus_ids[] __initdata = { { .compatible = "simple-bus", }, - { .compatible = "xlnx,plb-v46-1.00.a", }, - { .compatible = "xlnx,opb-v20-1.10.c", }, - { .compatible = "xlnx,opb-v20-1.10.b", }, { .compatible = "xlnx,compound", }, {} }; diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index f3f8be5..14f0955 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c @@ -430,8 +430,8 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) } /* Get the protocol type of the ethernet frame that arrived */ - proto_type = ((in_be32(addr + XEL_HEADER_OFFSET + - XEL_RXBUFF_OFFSET) >> XEL_HEADER_SHIFT) & + proto_type = ((ntohl(in_be32(addr + XEL_HEADER_OFFSET + + XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) & XEL_RPLR_LENGTH_MASK); /* Check if received ethernet frame is a raw ethernet frame @@ -439,9 +439,9 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) { if (proto_type == ETH_P_IP) { - length = ((in_be32(addr + + length = ((ntohl(in_be32(addr + XEL_HEADER_IP_LENGTH_OFFSET + - XEL_RXBUFF_OFFSET) >> + XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) & XEL_RPLR_LENGTH_MASK); length += ETH_HLEN + ETH_FCS_LEN; diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 0c9ce88..68bd234 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c @@ -32,10 +32,14 @@ #include <linux/dma-mapping.h> #include <linux/of_device.h> #include <linux/of_platform.h> +#include <linux/of_address.h> #include <linux/io.h> #include <linux/xilinxfb.h> #include <linux/slab.h> + +#ifdef CONFIG_PPC_DCR #include <asm/dcr.h> +#endif #define DRIVER_NAME "xilinxfb" @@ -123,10 +127,10 @@ struct xilinxfb_drvdata { registers */ void __iomem *regs; /* virt. address of the control registers */ - +#ifdef CONFIG_PPC_DCR dcr_host_t dcr_host; unsigned int dcr_len; - +#endif void *fb_virt; /* virt. address of the frame buffer */ dma_addr_t fb_phys; /* phys. address of the frame buffer */ int fb_alloced; /* Flag, was the fb memory alloced? */ @@ -152,9 +156,10 @@ static void xilinx_fb_out_be32(struct xilinxfb_drvdata *drvdata, u32 offset, { if (drvdata->flags & PLB_ACCESS_FLAG) out_be32(drvdata->regs + (offset << 2), val); +#ifdef CONFIG_PPC_DCR else dcr_write(drvdata->dcr_host, offset, val); - +#endif } static int @@ -383,8 +388,11 @@ static int xilinxfb_release(struct device *dev) if (drvdata->flags & PLB_ACCESS_FLAG) { iounmap(drvdata->regs); release_mem_region(drvdata->regs_phys, 8); - } else + } +#ifdef CONFIG_PPC_DCR + else dcr_unmap(drvdata->dcr_host, drvdata->dcr_len); +#endif kfree(drvdata); dev_set_drvdata(dev, NULL); @@ -404,7 +412,7 @@ xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match) u32 tft_access; struct xilinxfb_platform_data pdata; struct resource res; - int size, rc, start; + int size, rc; struct xilinxfb_drvdata *drvdata; /* Copy with the default pdata (not a ptr reference!) */ @@ -437,7 +445,10 @@ xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match) dev_err(&op->dev, "invalid address\n"); goto err; } - } else { + } +#ifdef CONFIG_PPC_DCR + else { + int start; res.start = 0; start = dcr_resource_start(op->dev.of_node, 0); drvdata->dcr_len = dcr_resource_len(op->dev.of_node, 0); @@ -447,6 +458,7 @@ xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match) goto err; } } +#endif prop = of_get_property(op->dev.of_node, "phys-size", &size); if ((prop) && (size >= sizeof(u32)*2)) { |