Merge branch 'for-linus' of git://git.monstr.eu/linux-2.6-microblaze
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 14 Dec 2009 18:04:04 +0000 (10:04 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 14 Dec 2009 18:04:04 +0000 (10:04 -0800)
* 'for-linus' of git://git.monstr.eu/linux-2.6-microblaze: (46 commits)
  microblaze: Remove rt_sigsuspend wrapper
  microblaze: nommu: Don't clobber R11 on syscalls
  microblaze: Remove show_tmem function
  microblaze: Support for WB cache
  microblaze: Add PVR for Microblaze v7.30.a
  microblaze: Remove ancient and fake microblaze version from cpu_ver table
  microblaze: Remove panic_timeout init value
  microblaze: Do not count system calls in default
  microblaze: Enable DTC compilation
  microblaze: Core oprofile configs and hooks
  microblaze: Fix level interrupt ACKing
  microblaze: Enable futimesat syscall
  microblaze: Checking DTS against PVR for write-back cache
  microblaze: Remove duplicity from pgalloc.h
  microblaze: Futex support
  microblaze: Adding dev_arch_data functions
  microblaze: Fix the heartbeat gpio to be more robust
  microblaze: Simple __copy_tofrom_user for noMMU
  microblaze: Export memory_start for modules
  microblaze: Use lowest-common-denominator default CPU settings
  ...

50 files changed:
arch/microblaze/Kconfig
arch/microblaze/Kconfig.debug
arch/microblaze/Makefile
arch/microblaze/boot/Makefile
arch/microblaze/include/asm/cache.h
arch/microblaze/include/asm/cacheflush.h
arch/microblaze/include/asm/cpuinfo.h
arch/microblaze/include/asm/device.h
arch/microblaze/include/asm/ftrace.h
arch/microblaze/include/asm/futex.h
arch/microblaze/include/asm/irqflags.h
arch/microblaze/include/asm/page.h
arch/microblaze/include/asm/pgalloc.h
arch/microblaze/include/asm/pvr.h
arch/microblaze/include/asm/setup.h
arch/microblaze/include/asm/system.h
arch/microblaze/include/asm/uaccess.h
arch/microblaze/kernel/Makefile
arch/microblaze/kernel/cpu/Makefile
arch/microblaze/kernel/cpu/cache.c
arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
arch/microblaze/kernel/cpu/cpuinfo-static.c
arch/microblaze/kernel/cpu/cpuinfo.c
arch/microblaze/kernel/cpu/mb.c
arch/microblaze/kernel/cpu/pvr.c
arch/microblaze/kernel/entry-nommu.S
arch/microblaze/kernel/entry.S
arch/microblaze/kernel/ftrace.c [new file with mode: 0644]
arch/microblaze/kernel/heartbeat.c
arch/microblaze/kernel/intc.c
arch/microblaze/kernel/mcount.S [new file with mode: 0644]
arch/microblaze/kernel/microblaze_ksyms.c
arch/microblaze/kernel/process.c
arch/microblaze/kernel/reset.c [new file with mode: 0644]
arch/microblaze/kernel/setup.c
arch/microblaze/kernel/signal.c
arch/microblaze/kernel/stacktrace.c [new file with mode: 0644]
arch/microblaze/kernel/syscall_table.S
arch/microblaze/kernel/timer.c
arch/microblaze/kernel/vmlinux.lds.S
arch/microblaze/lib/uaccess.c
arch/microblaze/mm/init.c
arch/microblaze/mm/pgtable.c
arch/microblaze/oprofile/Makefile [new file with mode: 0644]
arch/microblaze/oprofile/microblaze_oprofile.c [new file with mode: 0644]
arch/microblaze/platform/Kconfig.platform
arch/microblaze/platform/generic/Kconfig.auto
arch/microblaze/platform/generic/system.dts
arch/microblaze/platform/platform.c
scripts/recordmcount.pl

index bbd8327f18901d80d5eefe3e27015f65993a099f..fd53e500be67b21e5d48c96f9e745d8dfa0e158a 100644 (file)
@@ -6,8 +6,15 @@ mainmenu "Linux/Microblaze Kernel Configuration"
 config MICROBLAZE
        def_bool y
        select HAVE_LMB
+       select HAVE_FUNCTION_TRACER
+       select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+       select HAVE_FUNCTION_GRAPH_TRACER
+       select HAVE_DYNAMIC_FTRACE
+       select HAVE_FTRACE_MCOUNT_RECORD
        select USB_ARCH_HAS_EHCI
        select ARCH_WANT_OPTIONAL_GPIOLIB
+       select HAVE_OPROFILE
+       select TRACING_SUPPORT
 
 config SWAP
        def_bool n
@@ -57,12 +64,24 @@ config GENERIC_GPIO
 config GENERIC_CSUM
        def_bool y
 
+config STACKTRACE_SUPPORT
+       def_bool y
+
+config LOCKDEP_SUPPORT
+       def_bool y
+
+config HAVE_LATENCYTOP_SUPPORT
+       def_bool y
+
 config PCI
        def_bool n
 
 config NO_DMA
        def_bool y
 
+config DTC
+       def_bool y
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
index 242cd35bdb4bfe22970a0110be801e98a410d616..9dc708a7f7005a5bf35f55c6b80654743a9b4e54 100644 (file)
@@ -3,6 +3,9 @@
 
 menu "Kernel hacking"
 
+config TRACE_IRQFLAGS_SUPPORT
+       def_bool y
+
 source "lib/Kconfig.debug"
 
 config EARLY_PRINTK
index 34187354304a6217d16ff3dab5315e605409ab05..d2d6cfcb1a3028bde39bad803094746713518d5d 100644 (file)
@@ -51,6 +51,8 @@ core-y += arch/microblaze/kernel/
 core-y += arch/microblaze/mm/
 core-y += arch/microblaze/platform/
 
+drivers-$(CONFIG_OPROFILE) += arch/microblaze/oprofile/
+
 boot := arch/microblaze/boot
 
 # Are we making a simpleImage.<boardname> target? If so, crack out the boardname
index 21f13322a4cad74da687055e50eb840804dda78b..902cf9846c3cb9b89f0940a8a635554cb265fd0b 100644 (file)
@@ -2,11 +2,13 @@
 # arch/microblaze/boot/Makefile
 #
 
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+
 obj-y += linked_dtb.o
 
 targets := linux.bin linux.bin.gz simpleImage.%
 
-OBJCOPYFLAGS_linux.bin  := -O binary
+OBJCOPYFLAGS := -O binary
 
 # Where the DTS files live
 dtstree         := $(srctree)/$(src)/dts
@@ -24,6 +26,7 @@ $(obj)/linux.bin: vmlinux FORCE
        [ -n $(CONFIG_INITRAMFS_SOURCE) ] && [ ! -e $(CONFIG_INITRAMFS_SOURCE) ] && \
        touch $(CONFIG_INITRAMFS_SOURCE) || echo "No CPIO image"
        $(call if_changed,objcopy)
+       $(call if_changed,uimage)
        @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
 
 $(obj)/linux.bin.gz: $(obj)/linux.bin FORCE
@@ -36,8 +39,16 @@ quiet_cmd_cp = CP      $< $@$2
 quiet_cmd_strip = STRIP   $@
       cmd_strip = $(STRIP) -K _start -K _end -K __log_buf -K _fdt_start vmlinux -o $@
 
+quiet_cmd_uimage = UIMAGE  $@.ub
+      cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A microblaze -O linux -T kernel \
+                   -C none -n 'Linux-$(KERNELRELEASE)' \
+                   -a $(CONFIG_KERNEL_BASE_ADDR) -e $(CONFIG_KERNEL_BASE_ADDR) \
+                   -d $@ $@.ub
+
 $(obj)/simpleImage.%: vmlinux FORCE
        $(call if_changed,cp,.unstrip)
+       $(call if_changed,objcopy)
+       $(call if_changed,uimage)
        $(call if_changed,strip)
        @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
 
@@ -53,4 +64,4 @@ $(obj)/%.dtb: $(dtstree)/%.dts FORCE
 
 clean-kernel += linux.bin linux.bin.gz simpleImage.*
 
-clean-files += *.dtb
+clean-files += *.dtb simpleImage.*.unstrip
index c209c47509d52435303c8b09008405fb14837afc..e52210891d78ed167a71e24ca35c1cd9abee6bf4 100644 (file)
 
 #define SMP_CACHE_BYTES        L1_CACHE_BYTES
 
-void _enable_icache(void);
-void _disable_icache(void);
-void _invalidate_icache(unsigned int addr);
-
-#define __enable_icache()              _enable_icache()
-#define __disable_icache()             _disable_icache()
-#define __invalidate_icache(addr)      _invalidate_icache(addr)
-
-void _enable_dcache(void);
-void _disable_dcache(void);
-void _invalidate_dcache(unsigned int addr);
-
-#define __enable_dcache()              _enable_dcache()
-#define __disable_dcache()             _disable_dcache()
-#define __invalidate_dcache(addr)      _invalidate_dcache(addr)
-
 #endif /* _ASM_MICROBLAZE_CACHE_H */
index 088076e657b32189ac16e6b9a9e3d0959740633a..a6edd356cd08c583807fb278913f943172f7ae20 100644 (file)
@@ -18,6 +18,8 @@
 /* Somebody depends on this; sigh... */
 #include <linux/mm.h>
 
+/* Look at Documentation/cachetlb.txt */
+
 /*
  * Cache handling functions.
  * Microblaze has a write-through data cache, meaning that the data cache
  * instruction cache to make sure we don't fetch old, bad code.
  */
 
+/* struct cache, d=dcache, i=icache, fl = flush, iv = invalidate,
+ * suffix r = range */
+struct scache {
+       /* icache */
+       void (*ie)(void); /* enable */
+       void (*id)(void); /* disable */
+       void (*ifl)(void); /* flush */
+       void (*iflr)(unsigned long a, unsigned long b);
+       void (*iin)(void); /* invalidate */
+       void (*iinr)(unsigned long a, unsigned long b);
+       /* dcache */
+       void (*de)(void); /* enable */
+       void (*dd)(void); /* disable */
+       void (*dfl)(void); /* flush */
+       void (*dflr)(unsigned long a, unsigned long b);
+       void (*din)(void); /* invalidate */
+       void (*dinr)(unsigned long a, unsigned long b);
+};
+
+/* microblaze cache */
+extern struct scache *mbc;
+
+void microblaze_cache_init(void);
+
+#define enable_icache()                                        mbc->ie();
+#define disable_icache()                               mbc->id();
+#define flush_icache()                                 mbc->ifl();
+#define flush_icache_range(start, end)                 mbc->iflr(start, end);
+#define invalidate_icache()                            mbc->iin();
+#define invalidate_icache_range(start, end)            mbc->iinr(start, end);
+
+
+#define flush_icache_user_range(vma, pg, adr, len)     flush_icache();
+#define flush_icache_page(vma, pg)                     do { } while (0)
+
+#define enable_dcache()                                        mbc->de();
+#define disable_dcache()                               mbc->dd();
 /* FIXME for LL-temac driver */
-#define invalidate_dcache_range(start, end) \
-                       __invalidate_dcache_range(start, end)
-
-#define flush_cache_all()                      __invalidate_cache_all()
-#define flush_cache_mm(mm)                     do { } while (0)
-#define flush_cache_range(vma, start, end)     __invalidate_cache_all()
-#define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
+#define invalidate_dcache()                            mbc->din();
+#define invalidate_dcache_range(start, end)            mbc->dinr(start, end);
+#define flush_dcache()                                 mbc->dfl();
+#define flush_dcache_range(start, end)                 mbc->dflr(start, end);
 
-#define flush_dcache_range(start, end) __invalidate_dcache_range(start, end)
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
+/* D-cache aliasing problem can't happen - cache is between MMU and ram */
 #define flush_dcache_page(page)                        do { } while (0)
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 
-#define flush_icache_range(start, len) __invalidate_icache_range(start, len)
-#define flush_icache_page(vma, pg)             do { } while (0)
-
-#ifndef CONFIG_MMU
-# define flush_icache_user_range(start, len)   do { } while (0)
-#else
-# define flush_icache_user_range(vma, pg, adr, len) __invalidate_icache_all()
-
-# define flush_page_to_ram(page)               do { } while (0)
 
-# define flush_icache()                        __invalidate_icache_all()
-# define flush_cache_sigtramp(vaddr) \
-                       __invalidate_icache_range(vaddr, vaddr + 8)
-
-# define flush_dcache_mmap_lock(mapping)       do { } while (0)
-# define flush_dcache_mmap_unlock(mapping)     do { } while (0)
+#define flush_cache_dup_mm(mm)                         do { } while (0)
+#define flush_cache_vmap(start, end)                   do { } while (0)
+#define flush_cache_vunmap(start, end)                 do { } while (0)
+#define flush_cache_mm(mm)                     do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 
-# define flush_cache_dup_mm(mm)                        do { } while (0)
+/* MS: kgdb code use this macro, wrong len with FLASH */
+#if 0
+#define flush_cache_range(vma, start, len)     {       \
+       flush_icache_range((unsigned) (start), (unsigned) (start) + (len)); \
+       flush_dcache_range((unsigned) (start), (unsigned) (start) + (len)); \
+}
 #endif
 
-#define flush_cache_vmap(start, end)           do { } while (0)
-#define flush_cache_vunmap(start, end)         do { } while (0)
-
-struct page;
-struct mm_struct;
-struct vm_area_struct;
-
-/* see arch/microblaze/kernel/cache.c */
-extern void __invalidate_icache_all(void);
-extern void __invalidate_icache_range(unsigned long start, unsigned long end);
-extern void __invalidate_icache_page(struct vm_area_struct *vma,
-                               struct page *page);
-extern void __invalidate_icache_user_range(struct vm_area_struct *vma,
-                               struct page *page,
-                               unsigned long adr, int len);
-extern void __invalidate_cache_sigtramp(unsigned long addr);
-
-extern void __invalidate_dcache_all(void);
-extern void __invalidate_dcache_range(unsigned long start, unsigned long end);
-extern void __invalidate_dcache_page(struct vm_area_struct *vma,
-                               struct page *page);
-extern void __invalidate_dcache_user_range(struct vm_area_struct *vma,
-                               struct page *page,
-                               unsigned long adr, int len);
-
-extern inline void __invalidate_cache_all(void)
-{
-       __invalidate_icache_all();
-       __invalidate_dcache_all();
-}
+#define flush_cache_range(vma, start, len) do { } while (0)
 
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy((dst), (src), (len)); \
-       flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \
+#define copy_to_user_page(vma, page, vaddr, dst, src, len)             \
+do {                                                                   \
+       memcpy((dst), (src), (len));                                    \
+       flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \
 } while (0)
 
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-       memcpy((dst), (src), (len))
+#define copy_from_user_page(vma, page, vaddr, dst, src, len)           \
+do {                                                                   \
+       memcpy((dst), (src), (len));                                    \
+} while (0)
 
 #endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */
index 52f28f6dc4eb1b0985965d03f8fe9401a986c3f6..b4f5ca33aebf09a831226022ae0b9513c8344322 100644 (file)
@@ -43,7 +43,7 @@ struct cpuinfo {
        u32 use_icache;
        u32 icache_tagbits;
        u32 icache_write;
-       u32 icache_line;
+       u32 icache_line_length;
        u32 icache_size;
        unsigned long icache_base;
        unsigned long icache_high;
@@ -51,8 +51,9 @@ struct cpuinfo {
        u32 use_dcache;
        u32 dcache_tagbits;
        u32 dcache_write;
-       u32 dcache_line;
+       u32 dcache_line_length;
        u32 dcache_size;
+       u32 dcache_wb;
        unsigned long dcache_base;
        unsigned long dcache_high;
 
index 30286db27c1c2a08e94c513991deb2a4904d23c1..78a038452c0faa0106f3a0f7bb48e50e811c91da 100644 (file)
@@ -19,6 +19,18 @@ struct dev_archdata {
 struct pdev_archdata {
 };
 
+static inline void dev_archdata_set_node(struct dev_archdata *ad,
+                                        struct device_node *np)
+{
+       ad->of_node = np;
+}
+
+static inline struct device_node *
+dev_archdata_get_node(const struct dev_archdata *ad)
+{
+       return ad->of_node;
+}
+
 #endif /* _ASM_MICROBLAZE_DEVICE_H */
 
 
index 8b137891791fe96927ad78e64b0aad7bded08bdc..fd2fa2eca62f18fe2541300a8ffc5453632760d7 100644 (file)
@@ -1 +1,26 @@
+#ifndef _ASM_MICROBLAZE_FTRACE
+#define _ASM_MICROBLAZE_FTRACE
 
+#ifdef CONFIG_FUNCTION_TRACER
+
+#define MCOUNT_ADDR            ((long)(_mcount))
+#define MCOUNT_INSN_SIZE       8 /* sizeof mcount call */
+
+#ifndef __ASSEMBLY__
+extern void _mcount(void);
+extern void ftrace_call_graph(void);
+#endif
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/* reloction of mcount call site is the same as the address */
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+       return addr;
+}
+
+struct dyn_arch_ftrace {
+};
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+#endif /* CONFIG_FUNCTION_TRACER */
+#endif /* _ASM_MICROBLAZE_FTRACE */
index 0b745828f42bc9be46ded49786b887c9ad35df2d..8dbb6e7a03a2183c135656ca4fee82e302223885 100644 (file)
@@ -1 +1,126 @@
-#include <asm-generic/futex.h>
+#ifndef _ASM_MICROBLAZE_FUTEX_H
+#define _ASM_MICROBLAZE_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
+({                                                                     \
+       __asm__ __volatile__ (                                          \
+                       "1:     lwx     %0, %2, r0; "                   \
+                               insn                                    \
+                       "2:     swx     %1, %2, r0;                     \
+                               addic   %1, r0, 0;                      \
+                               bnei    %1, 1b;                         \
+                       3:                                              \
+                       .section .fixup,\"ax\";                         \
+                       4:      brid    3b;                             \
+                               addik   %1, r0, %3;                     \
+                       .previous;                                      \
+                       .section __ex_table,\"a\";                      \
+                       .word   1b,4b,2b,4b;                            \
+                       .previous;"                                     \
+       : "=&r" (oldval), "=&r" (ret)                                   \
+       : "b" (uaddr), "i" (-EFAULT), "r" (oparg)                       \
+       );                                                              \
+})
+
+static inline int
+futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       pagefault_disable();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+               __futex_atomic_op("or %1,%4,%4;", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_ADD:
+               __futex_atomic_op("add %1,%0,%4;", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_OR:
+               __futex_atomic_op("or %1,%0,%4;", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_ANDN:
+               __futex_atomic_op("and %1,%0,%4;", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_XOR:
+               __futex_atomic_op("xor %1,%0,%4;", ret, oldval, uaddr, oparg);
+               break;
+       default:
+               ret = -ENOSYS;
+       }
+
+       pagefault_enable();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ:
+                       ret = (oldval == cmparg);
+                       break;
+               case FUTEX_OP_CMP_NE:
+                       ret = (oldval != cmparg);
+                       break;
+               case FUTEX_OP_CMP_LT:
+                       ret = (oldval < cmparg);
+                       break;
+               case FUTEX_OP_CMP_GE:
+                       ret = (oldval >= cmparg);
+                       break;
+               case FUTEX_OP_CMP_LE:
+                       ret = (oldval <= cmparg);
+                       break;
+               case FUTEX_OP_CMP_GT:
+                       ret = (oldval > cmparg);
+                       break;
+               default:
+                       ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+       int prev, cmp;
+
+       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       __asm__ __volatile__ ("1:       lwx     %0, %2, r0;             \
+                                       cmp     %1, %0, %3;             \
+                                       beqi    %1, 3f;                 \
+                               2:      swx     %4, %2, r0;             \
+                                       addic   %1, r0, 0;              \
+                                       bnei    %1, 1b;                 \
+                               3:                                      \
+                               .section .fixup,\"ax\";                 \
+                               4:      brid    3b;                     \
+                                       addik   %0, r0, %5;             \
+                               .previous;                              \
+                               .section __ex_table,\"a\";              \
+                               .word   1b,4b,2b,4b;                    \
+                               .previous;"                             \
+               : "=&r" (prev), "=&r"(cmp)                              \
+               : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
+
+       return prev;
+}
+
+#endif /* __KERNEL__ */
+
+#endif
index dea65645a4f8d5d8cc591c534c6eec8adeb16b67..2c38c6d801769be469348fa80f4ef3283aab44e2 100644 (file)
 #define _ASM_MICROBLAZE_IRQFLAGS_H
 
 #include <linux/irqflags.h>
+#include <asm/registers.h>
 
 # if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
 
-# define local_irq_save(flags)                         \
+# define raw_local_irq_save(flags)                     \
        do {                                            \
-               asm volatile ("# local_irq_save \n\t"   \
-                               "msrclr %0, %1  \n\t"   \
-                               "nop    \n\t"           \
+               asm volatile (" msrclr %0, %1;          \
+                               nop;"                   \
                                : "=r"(flags)           \
                                : "i"(MSR_IE)           \
                                : "memory");            \
        } while (0)
 
-# define local_irq_disable()                                   \
-       do {                                                    \
-               asm volatile ("# local_irq_disable \n\t"        \
-                               "msrclr r0, %0 \n\t"            \
-                               "nop    \n\t"                   \
-                               :                               \
-                               : "i"(MSR_IE)                   \
-                               : "memory");                    \
+# define raw_local_irq_disable()                       \
+       do {                                            \
+               asm volatile (" msrclr r0, %0;          \
+                               nop;"                   \
+                               :                       \
+                               : "i"(MSR_IE)           \
+                               : "memory");            \
        } while (0)
 
-# define local_irq_enable()                                    \
-       do {                                                    \
-               asm volatile ("# local_irq_enable \n\t"         \
-                               "msrset r0, %0 \n\t"            \
-                               "nop    \n\t"                   \
-                               :                               \
-                               : "i"(MSR_IE)                   \
-                               : "memory");                    \
+# define raw_local_irq_enable()                                \
+       do {                                            \
+               asm volatile (" msrset  r0, %0;         \
+                               nop;"                   \
+                               :                       \
+                               : "i"(MSR_IE)           \
+                               : "memory");            \
        } while (0)
 
 # else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */
 
-# define local_irq_save(flags)                                 \
+# define raw_local_irq_save(flags)                             \
        do {                                                    \
                register unsigned tmp;                          \
-               asm volatile ("# local_irq_save \n\t"           \
-                               "mfs    %0, rmsr \n\t"          \
-                               "nop \n\t"                      \
-                               "andi   %1, %0, %2 \n\t"        \
-                               "mts    rmsr, %1 \n\t"          \
-                               "nop \n\t"                      \
+               asm volatile (" mfs     %0, rmsr;               \
+                               nop;                            \
+                               andi    %1, %0, %2;             \
+                               mts     rmsr, %1;               \
+                               nop;"                           \
                                : "=r"(flags), "=r" (tmp)       \
                                : "i"(~MSR_IE)                  \
                                : "memory");                    \
        } while (0)
 
-# define local_irq_disable()                                   \
+# define raw_local_irq_disable()                               \
        do {                                                    \
                register unsigned tmp;                          \
-               asm volatile ("# local_irq_disable \n\t"        \
-                               "mfs    %0, rmsr \n\t"          \
-                               "nop \n\t"                      \
-                               "andi   %0, %0, %1 \n\t"        \
-                               "mts    rmsr, %0 \n\t"          \
-                               "nop \n\t"                      \
+               asm volatile (" mfs     %0, rmsr;               \
+                               nop;                            \
+                               andi    %0, %0, %1;             \
+                               mts     rmsr, %0;               \
+                               nop;"                   \
                                : "=r"(tmp)                     \
                                : "i"(~MSR_IE)                  \
                                : "memory");                    \
        } while (0)
 
-# define local_irq_enable()                                    \
+# define raw_local_irq_enable()                                        \
        do {                                                    \
                register unsigned tmp;                          \
-               asm volatile ("# local_irq_enable \n\t"         \
-                               "mfs    %0, rmsr \n\t"          \
-                               "nop \n\t"                      \
-                               "ori    %0, %0, %1 \n\t"        \
-                               "mts    rmsr, %0 \n\t"          \
-                               "nop \n\t"                      \
+               asm volatile (" mfs     %0, rmsr;               \
+                               nop;                            \
+                               ori     %0, %0, %1;             \
+                               mts     rmsr, %0;               \
+                               nop;"                           \
                                : "=r"(tmp)                     \
                                : "i"(MSR_IE)                   \
                                : "memory");                    \
 
 # endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
 
-#define local_save_flags(flags)                                        \
+#define raw_local_irq_restore(flags)                           \
        do {                                                    \
-               asm volatile ("# local_save_flags \n\t"         \
-                               "mfs    %0, rmsr \n\t"          \
-                               "nop    \n\t"                   \
-                               : "=r"(flags)                   \
+               asm volatile (" mts     rmsr, %0;               \
+                               nop;"                           \
                                :                               \
+                               : "r"(flags)                    \
                                : "memory");                    \
        } while (0)
 
-#define local_irq_restore(flags)                       \
-       do {                                            \
-               asm volatile ("# local_irq_restore \n\t"\
-                               "mts    rmsr, %0 \n\t"  \
-                               "nop    \n\t"           \
-                               :                       \
-                               : "r"(flags)            \
-                               : "memory");            \
-       } while (0)
-
-static inline int irqs_disabled(void)
+static inline unsigned long get_msr(void)
 {
        unsigned long flags;
-
-       local_save_flags(flags);
-       return ((flags & MSR_IE) == 0);
+       asm volatile (" mfs     %0, rmsr;       \
+                       nop;"                   \
+                       : "=r"(flags)           \
+                       :                       \
+                       : "memory");            \
+       return flags;
 }
 
-#define raw_irqs_disabled irqs_disabled
-#define raw_irqs_disabled_flags(flags) ((flags) == 0)
+#define raw_local_save_flags(flags)    ((flags) = get_msr())
+#define raw_irqs_disabled()            ((get_msr() & MSR_IE) == 0)
+#define raw_irqs_disabled_flags(flags) ((flags & MSR_IE) == 0)
 
 #endif /* _ASM_MICROBLAZE_IRQFLAGS_H */
index 880c988c2237e2a333bbb7cc51c939a385ea9d07..9b66c0fa9a32caf5ba14e7f0c9478119808a0759 100644 (file)
@@ -164,7 +164,8 @@ extern int page_is_ram(unsigned long pfn);
 #  endif /* CONFIG_MMU */
 
 #  ifndef CONFIG_MMU
-#  define pfn_valid(pfn)       ((pfn) >= min_low_pfn && (pfn) <= max_mapnr)
+#  define pfn_valid(pfn)       (((pfn) >= min_low_pfn) && \
+                               ((pfn) <= (min_low_pfn + max_mapnr)))
 #  define ARCH_PFN_OFFSET      (PAGE_OFFSET >> PAGE_SHIFT)
 #  else /* CONFIG_MMU */
 #  define ARCH_PFN_OFFSET      (memory_start >> PAGE_SHIFT)
index b0131da1387bb131cd9e7666519eedb9591302e3..7547f50645608c9c34170e9680d3072b9e636a8d 100644 (file)
@@ -106,9 +106,6 @@ extern inline void free_pgd_slow(pgd_t *pgd)
  */
 #define pmd_alloc_one_fast(mm, address)        ({ BUG(); ((pmd_t *)1); })
 #define pmd_alloc_one(mm, address)     ({ BUG(); ((pmd_t *)2); })
-/* FIXME two definition - look below */
-#define pmd_free(mm, x)                        do { } while (0)
-#define pgd_populate(mm, pmd, pte)     BUG()
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                unsigned long address)
@@ -192,14 +189,14 @@ extern inline void pte_free(struct mm_struct *mm, struct page *ptepage)
  * the pgd will always be present..
  */
 #define pmd_alloc_one(mm, address)     ({ BUG(); ((pmd_t *)2); })
-/*#define pmd_free(mm, x)                      do { } while (0)*/
-#define __pmd_free_tlb(tlb, x, addr)   do { } while (0)
+#define pmd_free(mm, x)                        do { } while (0)
+#define __pmd_free_tlb(tlb, x, addr)   pmd_free((tlb)->mm, x)
 #define pgd_populate(mm, pmd, pte)     BUG()
 
 extern int do_check_pgt_cache(int, int);
 
 #endif /* CONFIG_MMU */
 
-#define check_pgt_cache()      do {} while (0)
+#define check_pgt_cache()              do { } while (0)
 
 #endif /* _ASM_MICROBLAZE_PGALLOC_H */
index 66f1b30dd097db0fabde6ca1ddb475b71107b96a..e38abc7714b60bff43f11b2c52e5401cfd3e8db5 100644 (file)
@@ -76,20 +76,23 @@ struct pvr_s {
 #define PVR3_FSL_LINKS_MASK            0x00000380
 
 /* ICache config PVR masks */
-#define PVR4_USE_ICACHE_MASK           0x80000000
-#define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000
-#define PVR4_ICACHE_USE_FSL_MASK       0x02000000
-#define PVR4_ICACHE_ALLOW_WR_MASK      0x01000000
-#define PVR4_ICACHE_LINE_LEN_MASK      0x00E00000
-#define PVR4_ICACHE_BYTE_SIZE_MASK     0x001F0000
+#define PVR4_USE_ICACHE_MASK           0x80000000 /* ICU */
+#define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000 /* ICTS */
+#define PVR4_ICACHE_ALLOW_WR_MASK      0x01000000 /* ICW */
+#define PVR4_ICACHE_LINE_LEN_MASK      0x00E00000 /* ICLL */
+#define PVR4_ICACHE_BYTE_SIZE_MASK     0x001F0000 /* ICBS */
+#define PVR4_ICACHE_ALWAYS_USED                0x00008000 /* IAU */
+#define PVR4_ICACHE_INTERFACE          0x00002000 /* ICI */
 
 /* DCache config PVR masks */
-#define PVR5_USE_DCACHE_MASK           0x80000000
-#define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000
-#define PVR5_DCACHE_USE_FSL_MASK       0x02000000
-#define PVR5_DCACHE_ALLOW_WR_MASK      0x01000000
-#define PVR5_DCACHE_LINE_LEN_MASK      0x00E00000
-#define PVR5_DCACHE_BYTE_SIZE_MASK     0x001F0000
+#define PVR5_USE_DCACHE_MASK           0x80000000 /* DCU */
+#define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000 /* DCTS */
+#define PVR5_DCACHE_ALLOW_WR_MASK      0x01000000 /* DCW */
+#define PVR5_DCACHE_LINE_LEN_MASK      0x00E00000 /* DCLL */
+#define PVR5_DCACHE_BYTE_SIZE_MASK     0x001F0000 /* DCBS */
+#define PVR5_DCACHE_ALWAYS_USED                0x00008000 /* DAU */
+#define PVR5_DCACHE_USE_WRITEBACK      0x00004000 /* DWB */
+#define PVR5_DCACHE_INTERFACE          0x00002000 /* DCI */
 
 /* ICache base address PVR mask */
 #define PVR6_ICACHE_BASEADDR_MASK      0xFFFFFFFF
@@ -178,11 +181,14 @@ struct pvr_s {
                        ((pvr.pvr[5] & PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26)
 #define PVR_DCACHE_USE_FSL(pvr)                (pvr.pvr[5] & PVR5_DCACHE_USE_FSL_MASK)
 #define PVR_DCACHE_ALLOW_WR(pvr)       (pvr.pvr[5] & PVR5_DCACHE_ALLOW_WR_MASK)
+/* FIXME two shifts on one line needs any comment */
 #define PVR_DCACHE_LINE_LEN(pvr) \
                        (1 << ((pvr.pvr[5] & PVR5_DCACHE_LINE_LEN_MASK) >> 21))
 #define PVR_DCACHE_BYTE_SIZE(pvr) \
                        (1 << ((pvr.pvr[5] & PVR5_DCACHE_BYTE_SIZE_MASK) >> 16))
 
+#define PVR_DCACHE_USE_WRITEBACK(pvr) \
+                       ((pvr.pvr[5] & PVR5_DCACHE_USE_WRITEBACK) >> 14)
 
 #define PVR_ICACHE_BASEADDR(pvr)       (pvr.pvr[6] & PVR6_ICACHE_BASEADDR_MASK)
 #define PVR_ICACHE_HIGHADDR(pvr)       (pvr.pvr[7] & PVR7_ICACHE_HIGHADDR_MASK)
index ed67c9ed15b8346f8752ff506b59ffe6e43afe17..7f31394985e05f5884d6848ab902de53f8c45ac4 100644 (file)
@@ -35,6 +35,8 @@ extern void mmu_reset(void);
 extern void early_console_reg_tlb_alloc(unsigned int addr);
 #   endif /* CONFIG_MMU */
 
+extern void of_platform_reset_gpio_probe(void);
+
 void time_init(void);
 void init_IRQ(void);
 void machine_early_init(const char *cmdline, unsigned int ram,
index b1ed6159066006bd3d635f57126316a12f25962a..157970688b2aba72037e94b4e08a96fc831184ac 100644 (file)
@@ -16,6 +16,8 @@
 #include <asm-generic/cmpxchg.h>
 #include <asm-generic/cmpxchg-local.h>
 
+#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
+
 struct task_struct;
 struct thread_info;
 
index 5431b4631a7ad479bc23baf72de4563c68b8efb8..371bd6e56d9a20e60624147a050366f9fd06d2ea 100644 (file)
@@ -272,8 +272,9 @@ static inline int clear_user(char *to, int size)
        return size;
 }
 
-extern unsigned long __copy_tofrom_user(void __user *to,
-               const void __user *from, unsigned long size);
+#define __copy_from_user(to, from, n)  copy_from_user((to), (from), (n))
+#define __copy_from_user_inatomic(to, from, n) \
+               copy_from_user((to), (from), (n))
 
 #define copy_to_user(to, from, n)                                      \
        (access_ok(VERIFY_WRITE, (to), (n)) ?                           \
@@ -290,10 +291,6 @@ extern unsigned long __copy_tofrom_user(void __user *to,
                        (void __user *)(from), (n))                     \
                : -EFAULT)
 
-#define __copy_from_user(to, from, n)  copy_from_user((to), (from), (n))
-#define __copy_from_user_inatomic(to, from, n) \
-               copy_from_user((to), (from), (n))
-
 extern int __strncpy_user(char *to, const char __user *from, int len);
 extern int __strnlen_user(const char __user *sstr, int len);
 
@@ -305,6 +302,9 @@ extern int __strnlen_user(const char __user *sstr, int len);
 
 #endif /* CONFIG_MMU */
 
+extern unsigned long __copy_tofrom_user(void __user *to,
+               const void __user *from, unsigned long size);
+
 /*
  * The exception table consists of pairs of addresses: the first is the
  * address of an instruction that is allowed to fault, and the second is
index d487729683de8a0b66c6d082a8cefb096621687d..b07594eccf9b0d71c47e996bc33d22f61ffd39e4 100644 (file)
@@ -2,12 +2,22 @@
 # Makefile
 #
 
+ifdef CONFIG_FUNCTION_TRACER
+# Do not trace early boot code and low level code
+CFLAGS_REMOVE_timer.o = -pg
+CFLAGS_REMOVE_intc.o = -pg
+CFLAGS_REMOVE_early_printk.o = -pg
+CFLAGS_REMOVE_selfmod.o = -pg
+CFLAGS_REMOVE_heartbeat.o = -pg
+CFLAGS_REMOVE_ftrace.o = -pg
+endif
+
 extra-y := head.o vmlinux.lds
 
 obj-y += exceptions.o \
        hw_exception_handler.o init_task.o intc.o irq.o of_device.o \
        of_platform.o process.o prom.o prom_parse.o ptrace.o \
-       setup.o signal.o sys_microblaze.o timer.o traps.o
+       setup.o signal.o sys_microblaze.o timer.o traps.o reset.o
 
 obj-y += cpu/
 
@@ -16,5 +26,7 @@ obj-$(CONFIG_SELFMOD)         += selfmod.o
 obj-$(CONFIG_HEART_BEAT)       += heartbeat.o
 obj-$(CONFIG_MODULES)          += microblaze_ksyms.o module.o
 obj-$(CONFIG_MMU)              += misc.o
+obj-$(CONFIG_STACKTRACE)       += stacktrace.o
+obj-$(CONFIG_FUNCTION_TRACER)  += ftrace.o mcount.o
 
 obj-y  += entry$(MMU).o
index 20646e5492710bd51893e07e8452a0c481c32b07..59cc7bceaf8c493d35ef426e9bafaad914dbf3ab 100644 (file)
@@ -2,6 +2,10 @@
 # Build the appropriate CPU version support
 #
 
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_cache.o = -pg
+endif
+
 EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
                -DCPU_REV=$(CPU_REV)
 
index af866a4501256a4028b0daa99c92ff40a8b40e69..d9d63831cc2f9d6318257fa358ac41d41553c789 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2007-2009 PetaLogix
- * Copyright (C) 2007 John Williams <john.williams@petalogix.com>
+ * Copyright (C) 2007-2009 John Williams <john.williams@petalogix.com>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License. See the file COPYING in the main directory of this
 #include <asm/cacheflush.h>
 #include <linux/cache.h>
 #include <asm/cpuinfo.h>
+#include <asm/pvr.h>
 
-/* Exported functions */
+static inline void __invalidate_flush_icache(unsigned int addr)
+{
+       __asm__ __volatile__ ("wic      %0, r0;"        \
+                                       : : "r" (addr));
+}
+
+static inline void __flush_dcache(unsigned int addr)
+{
+       __asm__ __volatile__ ("wdc.flush        %0, r0;"        \
+                                       : : "r" (addr));
+}
+
+static inline void __invalidate_dcache(unsigned int baseaddr,
+                                               unsigned int offset)
+{
+       __asm__ __volatile__ ("wdc.clear        %0, %1;"        \
+                                       : : "r" (baseaddr), "r" (offset));
+}
 
-void _enable_icache(void)
+static inline void __enable_icache_msr(void)
 {
-       if (cpuinfo.use_icache) {
-#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
-               __asm__ __volatile__ ("                                 \
-                               msrset  r0, %0;                         \
-                               nop; "                                  \
-                               :                                       \
-                               : "i" (MSR_ICE)                         \
+       __asm__ __volatile__ (" msrset  r0, %0;         \
+                               nop; "                  \
+                       : : "i" (MSR_ICE) : "memory");
+}
+
+static inline void __disable_icache_msr(void)
+{
+       __asm__ __volatile__ (" msrclr  r0, %0;         \
+                               nop; "                  \
+                       : : "i" (MSR_ICE) : "memory");
+}
+
+static inline void __enable_dcache_msr(void)
+{
+       __asm__ __volatile__ (" msrset  r0, %0;         \
+                               nop; "                  \
+                               :                       \
+                               : "i" (MSR_DCE)         \
                                : "memory");
-#else
-               __asm__ __volatile__ ("                                 \
-                               mfs     r12, rmsr;                      \
-                               nop;                                    \
-                               ori     r12, r12, %0;                   \
-                               mts     rmsr, r12;                      \
-                               nop; "                                  \
-                               :                                       \
-                               : "i" (MSR_ICE)                         \
-                               : "memory", "r12");
-#endif
-       }
 }
 
-void _disable_icache(void)
+static inline void __disable_dcache_msr(void)
 {
-       if (cpuinfo.use_icache) {
-#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
-               __asm__ __volatile__ ("                                 \
-                               msrclr r0, %0;                          \
-                               nop; "                                  \
-                               :                                       \
-                               : "i" (MSR_ICE)                         \
+       __asm__ __volatile__ (" msrclr  r0, %0;         \
+                               nop; "                  \
+                               :                       \
+                               : "i" (MSR_DCE)         \
                                : "memory");
-#else
-               __asm__ __volatile__ ("                                 \
-                               mfs     r12, rmsr;                      \
-                               nop;                                    \
-                               andi    r12, r12, ~%0;                  \
-                               mts     rmsr, r12;                      \
-                               nop; "                                  \
-                               :                                       \
-                               : "i" (MSR_ICE)                         \
+}
+
+static inline void __enable_icache_nomsr(void)
+{
+       __asm__ __volatile__ (" mfs     r12, rmsr;      \
+                               nop;                    \
+                               ori     r12, r12, %0;   \
+                               mts     rmsr, r12;      \
+                               nop; "                  \
+                               :                       \
+                               : "i" (MSR_ICE)         \
                                : "memory", "r12");
-#endif
-       }
 }
 
-void _invalidate_icache(unsigned int addr)
+static inline void __disable_icache_nomsr(void)
 {
-       if (cpuinfo.use_icache) {
-               __asm__ __volatile__ ("                                 \
-                               wic     %0, r0"                         \
-                               :                                       \
-                               : "r" (addr));
-       }
+       __asm__ __volatile__ (" mfs     r12, rmsr;      \
+                               nop;                    \
+                               andi    r12, r12, ~%0;  \
+                               mts     rmsr, r12;      \
+                               nop; "                  \
+                               :                       \
+                               : "i" (MSR_ICE)         \
+                               : "memory", "r12");
 }
 
-void _enable_dcache(void)
+static inline void __enable_dcache_nomsr(void)
 {
-       if (cpuinfo.use_dcache) {
-#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
-               __asm__ __volatile__ ("                                 \
-                               msrset  r0, %0;                         \
-                               nop; "                                  \
-                               :                                       \
-                               : "i" (MSR_DCE)                         \
-                               : "memory");
-#else
-               __asm__ __volatile__ ("                                 \
-                               mfs     r12, rmsr;                      \
-                               nop;                                    \
-                               ori     r12, r12, %0;                   \
-                               mts     rmsr, r12;                      \
-                               nop; "                                  \
-                               :                                       \
-                               : "i" (MSR_DCE)                 \
+       __asm__ __volatile__ (" mfs     r12, rmsr;      \
+                               nop;                    \
+                               ori     r12, r12, %0;   \
+                               mts     rmsr, r12;      \
+                               nop; "                  \
+                               :                       \
+                               : "i" (MSR_DCE)         \
                                : "memory", "r12");
-#endif
-       }
 }
 
-void _disable_dcache(void)
+static inline void __disable_dcache_nomsr(void)
 {
-#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
-               __asm__ __volatile__ ("                                 \
-                               msrclr  r0, %0;                         \
-                               nop; "                                  \
-                               :                                       \
-                               : "i" (MSR_DCE)                 \
-                               : "memory");
-#else
-               __asm__ __volatile__ ("                                 \
-                               mfs     r12, rmsr;                      \
-                               nop;                                    \
-                               andi    r12, r12, ~%0;                  \
-                               mts     rmsr, r12;                      \
-                               nop; "                                  \
-                               :                                       \
-                               : "i" (MSR_DCE)                 \
+       __asm__ __volatile__ (" mfs     r12, rmsr;      \
+                               nop;                    \
+                               andi    r12, r12, ~%0;  \
+                               mts     rmsr, r12;      \
+                               nop; "                  \
+                               :                       \
+                               : "i" (MSR_DCE)         \
                                : "memory", "r12");
-#endif
 }
 
-void _invalidate_dcache(unsigned int addr)
+
+/* Helper macro for computing the limits of cache range loops */
+#define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size)   \
+do {                                                                   \
+       int align = ~(cache_line_length - 1);                           \
+       end = min(start + cache_size, end);                             \
+       start &= align;                                                 \
+       end = ((end & align) + cache_line_length);                      \
+} while (0);
+
+/*
+ * Helper macro to loop over the specified cache_size/line_length and
+ * execute 'op' on that cacheline
+ */
+#define CACHE_ALL_LOOP(cache_size, line_length, op)                    \
+do {                                                                   \
+       unsigned int len = cache_size;                                  \
+       int step = -line_length;                                        \
+       BUG_ON(step >= 0);                                              \
+                                                                       \
+       __asm__ __volatile__ (" 1:      " #op " %0, r0;                 \
+                                       bgtid   %0, 1b;                 \
+                                       addk    %0, %0, %1;             \
+                                       " : : "r" (len), "r" (step)     \
+                                       : "memory");                    \
+} while (0);
+
+
+#define CACHE_ALL_LOOP2(cache_size, line_length, op)                   \
+do {                                                                   \
+       unsigned int len = cache_size;                                  \
+       int step = -line_length;                                        \
+       BUG_ON(step >= 0);                                              \
+                                                                       \
+       __asm__ __volatile__ (" 1:      " #op " r0, %0;                 \
+                                       bgtid   %0, 1b;                 \
+                                       addk    %0, %0, %1;             \
+                                       " : : "r" (len), "r" (step)     \
+                                       : "memory");                    \
+} while (0);
+
+/* for wdc.flush/clear */
+#define CACHE_RANGE_LOOP_2(start, end, line_length, op)                        \
+do {                                                                   \
+       int step = -line_length;                                        \
+       int count = end - start;                                        \
+       BUG_ON(count <= 0);                                             \
+                                                                       \
+       __asm__ __volatile__ (" 1:      " #op " %0, %1;                 \
+                                       bgtid   %1, 1b;                 \
+                                       addk    %1, %1, %2;             \
+                                       " : : "r" (start), "r" (count), \
+                                       "r" (step) : "memory");         \
+} while (0);
+
+/* It is used only first parameter for OP - for wic, wdc */
+#define CACHE_RANGE_LOOP_1(start, end, line_length, op)                        \
+do {                                                                   \
+       int step = -line_length;                                        \
+       int count = end - start;                                        \
+       BUG_ON(count <= 0);                                             \
+                                                                       \
+       __asm__ __volatile__ (" 1:      addk    %0, %0, %1;             \
+                                       " #op " %0, r0;                 \
+                                       bgtid   %1, 1b;                 \
+                                       addk    %1, %1, %2;             \
+                                       " : : "r" (start), "r" (count), \
+                                       "r" (step) : "memory");         \
+} while (0);
+
+static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end)
 {
-               __asm__ __volatile__ ("                                 \
-                               wdc     %0, r0"                         \
-                               :                                       \
-                               : "r" (addr));
+       unsigned long flags;
+
+       pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
+                               (unsigned int)start, (unsigned int) end);
+
+       CACHE_LOOP_LIMITS(start, end,
+                       cpuinfo.icache_line_length, cpuinfo.icache_size);
+
+       local_irq_save(flags);
+       __disable_icache_msr();
+
+       CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
+
+       __enable_icache_msr();
+       local_irq_restore(flags);
 }
 
-void __invalidate_icache_all(void)
+static void __flush_icache_range_nomsr_irq(unsigned long start,
+                               unsigned long end)
 {
-       unsigned int i;
-       unsigned flags;
+       unsigned long flags;
 
-       if (cpuinfo.use_icache) {
-               local_irq_save(flags);
-               __disable_icache();
+       pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
+                               (unsigned int)start, (unsigned int) end);
 
-               /* Just loop through cache size and invalidate, no need to add
-                       CACHE_BASE address */
-               for (i = 0; i < cpuinfo.icache_size;
-                       i += cpuinfo.icache_line)
-                               __invalidate_icache(i);
+       CACHE_LOOP_LIMITS(start, end,
+                       cpuinfo.icache_line_length, cpuinfo.icache_size);
 
-               __enable_icache();
-               local_irq_restore(flags);
-       }
+       local_irq_save(flags);
+       __disable_icache_nomsr();
+
+       CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
+
+       __enable_icache_nomsr();
+       local_irq_restore(flags);
 }
 
-void __invalidate_icache_range(unsigned long start, unsigned long end)
+static void __flush_icache_range_noirq(unsigned long start,
+                               unsigned long end)
 {
-       unsigned int i;
-       unsigned flags;
-       unsigned int align;
-
-       if (cpuinfo.use_icache) {
-               /*
-                * No need to cover entire cache range,
-                * just cover cache footprint
-                */
-               end = min(start + cpuinfo.icache_size, end);
-               align = ~(cpuinfo.icache_line - 1);
-               start &= align; /* Make sure we are aligned */
-               /* Push end up to the next cache line */
-               end = ((end & align) + cpuinfo.icache_line);
-
-               local_irq_save(flags);
-               __disable_icache();
-
-               for (i = start; i < end; i += cpuinfo.icache_line)
-                       __invalidate_icache(i);
-
-               __enable_icache();
-               local_irq_restore(flags);
-       }
+       pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
+                               (unsigned int)start, (unsigned int) end);
+
+       CACHE_LOOP_LIMITS(start, end,
+                       cpuinfo.icache_line_length, cpuinfo.icache_size);
+       CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
+}
+
+static void __flush_icache_all_msr_irq(void)
+{
+       unsigned long flags;
+
+       pr_debug("%s\n", __func__);
+
+       local_irq_save(flags);
+       __disable_icache_msr();
+
+       CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
+
+       __enable_icache_msr();
+       local_irq_restore(flags);
+}
+
+static void __flush_icache_all_nomsr_irq(void)
+{
+       unsigned long flags;
+
+       pr_debug("%s\n", __func__);
+
+       local_irq_save(flags);
+       __disable_icache_nomsr();
+
+       CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
+
+       __enable_icache_nomsr();
+       local_irq_restore(flags);
 }
 
-void __invalidate_icache_page(struct vm_area_struct *vma, struct page *page)
+static void __flush_icache_all_noirq(void)
 {
-       __invalidate_icache_all();
+       pr_debug("%s\n", __func__);
+       CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
 }
 
-void __invalidate_icache_user_range(struct vm_area_struct *vma,
-                               struct page *page, unsigned long adr,
-                               int len)
+static void __invalidate_dcache_all_msr_irq(void)
 {
-       __invalidate_icache_all();
+       unsigned long flags;
+
+       pr_debug("%s\n", __func__);
+
+       local_irq_save(flags);
+       __disable_dcache_msr();
+
+       CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
+
+       __enable_dcache_msr();
+       local_irq_restore(flags);
 }
 
-void __invalidate_cache_sigtramp(unsigned long addr)
+static void __invalidate_dcache_all_nomsr_irq(void)
 {
-       __invalidate_icache_range(addr, addr + 8);
+       unsigned long flags;
+
+       pr_debug("%s\n", __func__);
+
+       local_irq_save(flags);
+       __disable_dcache_nomsr();
+
+       CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
+
+       __enable_dcache_nomsr();
+       local_irq_restore(flags);
 }
 
-void __invalidate_dcache_all(void)
+static void __invalidate_dcache_all_noirq_wt(void)
 {
-       unsigned int i;
-       unsigned flags;
-
-       if (cpuinfo.use_dcache) {
-               local_irq_save(flags);
-               __disable_dcache();
-
-               /*
-                * Just loop through cache size and invalidate,
-                * no need to add CACHE_BASE address
-                */
-               for (i = 0; i < cpuinfo.dcache_size;
-                       i += cpuinfo.dcache_line)
-                               __invalidate_dcache(i);
-
-               __enable_dcache();
-               local_irq_restore(flags);
-       }
+       pr_debug("%s\n", __func__);
+       CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc)
 }
 
-void __invalidate_dcache_range(unsigned long start, unsigned long end)
+/* FIXME this is weird - should be only wdc but not work
+ * MS: I am getting bus errors and other weird things */
+static void __invalidate_dcache_all_wb(void)
 {
+       pr_debug("%s\n", __func__);
+       CACHE_ALL_LOOP2(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
+                                       wdc.clear)
+
+#if 0
        unsigned int i;
-       unsigned flags;
-       unsigned int align;
-
-       if (cpuinfo.use_dcache) {
-               /*
-                * No need to cover entire cache range,
-                * just cover cache footprint
-                */
-               end = min(start + cpuinfo.dcache_size, end);
-               align = ~(cpuinfo.dcache_line - 1);
-               start &= align; /* Make sure we are aligned */
-               /* Push end up to the next cache line */
-               end = ((end & align) + cpuinfo.dcache_line);
-               local_irq_save(flags);
-               __disable_dcache();
-
-               for (i = start; i < end; i += cpuinfo.dcache_line)
-                       __invalidate_dcache(i);
-
-               __enable_dcache();
-               local_irq_restore(flags);
-       }
+
+       pr_debug("%s\n", __func__);
+
+       /* Just loop through cache size and invalidate it */
+       for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length)
+                       __invalidate_dcache(0, i);
+#endif
+}
+
+static void __invalidate_dcache_range_wb(unsigned long start,
+                                               unsigned long end)
+{
+       pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
+                               (unsigned int)start, (unsigned int) end);
+
+       CACHE_LOOP_LIMITS(start, end,
+                       cpuinfo.dcache_line_length, cpuinfo.dcache_size);
+       CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear);
+}
+
+static void __invalidate_dcache_range_nomsr_wt(unsigned long start,
+                                                       unsigned long end)
+{
+       pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
+                               (unsigned int)start, (unsigned int) end);
+       CACHE_LOOP_LIMITS(start, end,
+                       cpuinfo.dcache_line_length, cpuinfo.dcache_size);
+
+       CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
 }
 
-void __invalidate_dcache_page(struct vm_area_struct *vma, struct page *page)
+static void __invalidate_dcache_range_msr_irq_wt(unsigned long start,
+                                                       unsigned long end)
 {
-       __invalidate_dcache_all();
+       unsigned long flags;
+
+       pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
+                               (unsigned int)start, (unsigned int) end);
+       CACHE_LOOP_LIMITS(start, end,
+                       cpuinfo.dcache_line_length, cpuinfo.dcache_size);
+
+       local_irq_save(flags);
+       __disable_dcache_msr();
+
+       CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
+
+       __enable_dcache_msr();
+       local_irq_restore(flags);
+}
+
+static void __invalidate_dcache_range_nomsr_irq(unsigned long start,
+                                                       unsigned long end)
+{
+       unsigned long flags;
+
+       pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
+                               (unsigned int)start, (unsigned int) end);
+
+       CACHE_LOOP_LIMITS(start, end,
+                       cpuinfo.dcache_line_length, cpuinfo.dcache_size);
+
+       local_irq_save(flags);
+       __disable_dcache_nomsr();
+
+       CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
+
+       __enable_dcache_nomsr();
+       local_irq_restore(flags);
+}
+
+static void __flush_dcache_all_wb(void)
+{
+       pr_debug("%s\n", __func__);
+       CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
+                               wdc.flush);
 }
 
-void __invalidate_dcache_user_range(struct vm_area_struct *vma,
-                               struct page *page, unsigned long adr,
-                               int len)
+static void __flush_dcache_range_wb(unsigned long start, unsigned long end)
 {
-       __invalidate_dcache_all();
+       pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
+                               (unsigned int)start, (unsigned int) end);
+
+       CACHE_LOOP_LIMITS(start, end,
+                       cpuinfo.dcache_line_length, cpuinfo.dcache_size);
+       CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush);
+}
+
+/* struct for wb caches and for wt caches */
+struct scache *mbc;
+
+/* new wb cache model */
+const struct scache wb_msr = {
+       .ie = __enable_icache_msr,
+       .id = __disable_icache_msr,
+       .ifl = __flush_icache_all_noirq,
+       .iflr = __flush_icache_range_noirq,
+       .iin = __flush_icache_all_noirq,
+       .iinr = __flush_icache_range_noirq,
+       .de = __enable_dcache_msr,
+       .dd = __disable_dcache_msr,
+       .dfl = __flush_dcache_all_wb,
+       .dflr = __flush_dcache_range_wb,
+       .din = __invalidate_dcache_all_wb,
+       .dinr = __invalidate_dcache_range_wb,
+};
+
+/* There is only difference in ie, id, de, dd functions */
+const struct scache wb_nomsr = {
+       .ie = __enable_icache_nomsr,
+       .id = __disable_icache_nomsr,
+       .ifl = __flush_icache_all_noirq,
+       .iflr = __flush_icache_range_noirq,
+       .iin = __flush_icache_all_noirq,
+       .iinr = __flush_icache_range_noirq,
+       .de = __enable_dcache_nomsr,
+       .dd = __disable_dcache_nomsr,
+       .dfl = __flush_dcache_all_wb,
+       .dflr = __flush_dcache_range_wb,
+       .din = __invalidate_dcache_all_wb,
+       .dinr = __invalidate_dcache_range_wb,
+};
+
+/* Old wt cache model with disabling irq and turn off cache */
+const struct scache wt_msr = {
+       .ie = __enable_icache_msr,
+       .id = __disable_icache_msr,
+       .ifl = __flush_icache_all_msr_irq,
+       .iflr = __flush_icache_range_msr_irq,
+       .iin = __flush_icache_all_msr_irq,
+       .iinr = __flush_icache_range_msr_irq,
+       .de = __enable_dcache_msr,
+       .dd = __disable_dcache_msr,
+       .dfl = __invalidate_dcache_all_msr_irq,
+       .dflr = __invalidate_dcache_range_msr_irq_wt,
+       .din = __invalidate_dcache_all_msr_irq,
+       .dinr = __invalidate_dcache_range_msr_irq_wt,
+};
+
+const struct scache wt_nomsr = {
+       .ie = __enable_icache_nomsr,
+       .id = __disable_icache_nomsr,
+       .ifl = __flush_icache_all_nomsr_irq,
+       .iflr = __flush_icache_range_nomsr_irq,
+       .iin = __flush_icache_all_nomsr_irq,
+       .iinr = __flush_icache_range_nomsr_irq,
+       .de = __enable_dcache_nomsr,
+       .dd = __disable_dcache_nomsr,
+       .dfl = __invalidate_dcache_all_nomsr_irq,
+       .dflr = __invalidate_dcache_range_nomsr_irq,
+       .din = __invalidate_dcache_all_nomsr_irq,
+       .dinr = __invalidate_dcache_range_nomsr_irq,
+};
+
+/* New wt cache model for newer Microblaze versions */
+const struct scache wt_msr_noirq = {
+       .ie = __enable_icache_msr,
+       .id = __disable_icache_msr,
+       .ifl = __flush_icache_all_noirq,
+       .iflr = __flush_icache_range_noirq,
+       .iin = __flush_icache_all_noirq,
+       .iinr = __flush_icache_range_noirq,
+       .de = __enable_dcache_msr,
+       .dd = __disable_dcache_msr,
+       .dfl = __invalidate_dcache_all_noirq_wt,
+       .dflr = __invalidate_dcache_range_nomsr_wt,
+       .din = __invalidate_dcache_all_noirq_wt,
+       .dinr = __invalidate_dcache_range_nomsr_wt,
+};
+
+const struct scache wt_nomsr_noirq = {
+       .ie = __enable_icache_nomsr,
+       .id = __disable_icache_nomsr,
+       .ifl = __flush_icache_all_noirq,
+       .iflr = __flush_icache_range_noirq,
+       .iin = __flush_icache_all_noirq,
+       .iinr = __flush_icache_range_noirq,
+       .de = __enable_dcache_nomsr,
+       .dd = __disable_dcache_nomsr,
+       .dfl = __invalidate_dcache_all_noirq_wt,
+       .dflr = __invalidate_dcache_range_nomsr_wt,
+       .din = __invalidate_dcache_all_noirq_wt,
+       .dinr = __invalidate_dcache_range_nomsr_wt,
+};
+
+/* CPU version code for 7.20.c - see arch/microblaze/kernel/cpu/cpuinfo.c */
+#define CPUVER_7_20_A  0x0c
+#define CPUVER_7_20_D  0x0f
+
+#define INFO(s)        printk(KERN_INFO "cache: " s " \n");
+
+void microblaze_cache_init(void)
+{
+       if (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) {
+               if (cpuinfo.dcache_wb) {
+                       INFO("wb_msr");
+                       mbc = (struct scache *)&wb_msr;
+                       if (cpuinfo.ver_code < CPUVER_7_20_D) {
+                               /* MS: problem with signal handling - hw bug */
+                               INFO("WB won't work properly");
+                       }
+               } else {
+                       if (cpuinfo.ver_code >= CPUVER_7_20_A) {
+                               INFO("wt_msr_noirq");
+                               mbc = (struct scache *)&wt_msr_noirq;
+                       } else {
+                               INFO("wt_msr");
+                               mbc = (struct scache *)&wt_msr;
+                       }
+               }
+       } else {
+               if (cpuinfo.dcache_wb) {
+                       INFO("wb_nomsr");
+                       mbc = (struct scache *)&wb_nomsr;
+                       if (cpuinfo.ver_code < CPUVER_7_20_D) {
+                               /* MS: problem with signal handling - hw bug */
+                               INFO("WB won't work properly");
+                       }
+               } else {
+                       if (cpuinfo.ver_code >= CPUVER_7_20_A) {
+                               INFO("wt_nomsr_noirq");
+                               mbc = (struct scache *)&wt_nomsr_noirq;
+                       } else {
+                               INFO("wt_nomsr");
+                               mbc = (struct scache *)&wt_nomsr;
+                       }
+               }
+       }
 }
index c259786e7faa1c51853d3a0e31621ea1ddd154c7..f72dbd66c84411041c59705f72d253ee896af574 100644 (file)
  */
 
 #define CI(c, p) { ci->c = PVR_##p(pvr); }
+
+#if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
 #define err_printk(x) \
        early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n");
+#else
+#define err_printk(x) \
+       printk(KERN_INFO "ERROR: Microblaze " x "-different for PVR and DTS\n");
+#endif
 
 void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
 {
@@ -70,7 +76,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
        CI(use_icache, USE_ICACHE);
        CI(icache_tagbits, ICACHE_ADDR_TAG_BITS);
        CI(icache_write, ICACHE_ALLOW_WR);
-       CI(icache_line, ICACHE_LINE_LEN);
+       ci->icache_line_length = PVR_ICACHE_LINE_LEN(pvr) << 2;
        CI(icache_size, ICACHE_BYTE_SIZE);
        CI(icache_base, ICACHE_BASEADDR);
        CI(icache_high, ICACHE_HIGHADDR);
@@ -78,11 +84,16 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
        CI(use_dcache, USE_DCACHE);
        CI(dcache_tagbits, DCACHE_ADDR_TAG_BITS);
        CI(dcache_write, DCACHE_ALLOW_WR);
-       CI(dcache_line, DCACHE_LINE_LEN);
+       ci->dcache_line_length = PVR_DCACHE_LINE_LEN(pvr) << 2;
        CI(dcache_size, DCACHE_BYTE_SIZE);
        CI(dcache_base, DCACHE_BASEADDR);
        CI(dcache_high, DCACHE_HIGHADDR);
 
+       temp = PVR_DCACHE_USE_WRITEBACK(pvr);
+       if (ci->dcache_wb != temp)
+               err_printk("DCACHE WB");
+       ci->dcache_wb = temp;
+
        CI(use_dopb, D_OPB);
        CI(use_iopb, I_OPB);
        CI(use_dlmb, D_LMB);
index adb448f93d5fd3157c89b2336ca52488da6ecb42..6095aa6b5c88ef17d6cdab7d7393d49dfd0ee286 100644 (file)
@@ -72,12 +72,12 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
        ci->use_icache = fcpu(cpu, "xlnx,use-icache");
        ci->icache_tagbits = fcpu(cpu, "xlnx,addr-tag-bits");
        ci->icache_write = fcpu(cpu, "xlnx,allow-icache-wr");
-       ci->icache_line = fcpu(cpu, "xlnx,icache-line-len") << 2;
-       if (!ci->icache_line) {
+       ci->icache_line_length = fcpu(cpu, "xlnx,icache-line-len") << 2;
+       if (!ci->icache_line_length) {
                if (fcpu(cpu, "xlnx,icache-use-fsl"))
-                       ci->icache_line = 4 << 2;
+                       ci->icache_line_length = 4 << 2;
                else
-                       ci->icache_line = 1 << 2;
+                       ci->icache_line_length = 1 << 2;
        }
        ci->icache_size = fcpu(cpu, "i-cache-size");
        ci->icache_base = fcpu(cpu, "i-cache-baseaddr");
@@ -86,16 +86,17 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
        ci->use_dcache = fcpu(cpu, "xlnx,use-dcache");
        ci->dcache_tagbits = fcpu(cpu, "xlnx,dcache-addr-tag");
        ci->dcache_write = fcpu(cpu, "xlnx,allow-dcache-wr");
-       ci->dcache_line = fcpu(cpu, "xlnx,dcache-line-len") << 2;
-       if (!ci->dcache_line) {
+       ci->dcache_line_length = fcpu(cpu, "xlnx,dcache-line-len") << 2;
+       if (!ci->dcache_line_length) {
                if (fcpu(cpu, "xlnx,dcache-use-fsl"))
-                       ci->dcache_line = 4 << 2;
+                       ci->dcache_line_length = 4 << 2;
                else
-                       ci->dcache_line = 1 << 2;
+                       ci->dcache_line_length = 1 << 2;
        }
        ci->dcache_size = fcpu(cpu, "d-cache-size");
        ci->dcache_base = fcpu(cpu, "d-cache-baseaddr");
        ci->dcache_high = fcpu(cpu, "d-cache-highaddr");
+       ci->dcache_wb = fcpu(cpu, "xlnx,dcache-use-writeback");
 
        ci->use_dopb = fcpu(cpu, "xlnx,d-opb");
        ci->use_iopb = fcpu(cpu, "xlnx,i-opb");
index 3539babc1c18ddb2ef59c3ae3e4c5ee2b571ca12..991d71311b0ebaad156a03e03f9f4f2cce277d30 100644 (file)
@@ -29,11 +29,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
        {"7.20.a", 0x0c},
        {"7.20.b", 0x0d},
        {"7.20.c", 0x0e},
-       /* FIXME There is no keycode defined in MBV for these versions */
-       {"2.10.a", 0x10},
-       {"3.00.a", 0x20},
-       {"4.00.a", 0x30},
-       {"4.00.b", 0x40},
+       {"7.20.d", 0x0f},
+       {"7.30.a", 0x10},
        {NULL, 0},
 };
 
index 4dcfccdbc36480beec86d4fd24c31ccf0d8cdc6d..0c912b2a8e03ae72c1073ff94185595f18a3ab68 100644 (file)
@@ -103,11 +103,15 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        else
                count += seq_printf(m, "Icache:\t\tno\n");
 
-       if (cpuinfo.use_dcache)
+       if (cpuinfo.use_dcache) {
                count += seq_printf(m,
                                "Dcache:\t\t%ukB\n",
                                cpuinfo.dcache_size >> 10);
-       else
+               if (cpuinfo.dcache_wb)
+                       count += seq_printf(m, "\t\twrite-back\n");
+               else
+                       count += seq_printf(m, "\t\twrite-through\n");
+       } else
                count += seq_printf(m, "Dcache:\t\tno\n");
 
        count += seq_printf(m,
index c9a4340ddd53d65a4cd171ea2d5622154208a72f..9bee9382bf74587031e01fde8e828f243683d147 100644 (file)
@@ -45,7 +45,7 @@
 
 int cpu_has_pvr(void)
 {
-       unsigned flags;
+       unsigned long flags;
        unsigned pvr0;
 
        local_save_flags(flags);
index 9083d85376a4dc57b6e7c535869eb4b3f11570f5..95b0855802dff0b342d77cfe279f1eaa23bf6828 100644 (file)
@@ -208,8 +208,6 @@ ENTRY(_user_exception)
        lwi     r1, r1, TS_THREAD_INFO          /* get the thread info */
        /* calculate kernel stack pointer */
        addik   r1, r1, THREAD_SIZE - PT_SIZE
-       swi     r11, r0, PER_CPU(R11_SAVE)      /* temporarily save r11 */
-       lwi     r11, r0, PER_CPU(KM)            /* load mode indicator */
 2:
        swi     r11, r1, PT_MODE                /* store the mode */
        lwi     r11, r0, PER_CPU(R11_SAVE)      /* reload r11 */
index e3ecb36dd554ebc3504e08ac369a29359e8c304f..3bad4ff494711c205b3536a686e4aa36d9913b94 100644 (file)
@@ -31,6 +31,8 @@
 #include <linux/errno.h>
 #include <asm/signal.h>
 
+#undef DEBUG
+
 /* The size of a state save frame. */
 #define STATE_SAVE_SIZE                (PT_SIZE + STATE_SAVE_ARG_SPACE)
 
@@ -352,10 +354,12 @@ C_ENTRY(_user_exception):
        add     r12, r12, r12;                  /* convert num -> ptr */
        add     r12, r12, r12;
 
+#ifdef DEBUG
        /* Trac syscalls and stored them to r0_ram */
        lwi     r3, r12, 0x400 + r0_ram
        addi    r3, r3, 1
        swi     r3, r12, 0x400 + r0_ram
+#endif
 
        # Find and jump into the syscall handler.
        lwi     r12, r12, sys_call_table
@@ -496,17 +500,6 @@ C_ENTRY(sys_execve):
        brid    microblaze_execve;      /* Do real work (tail-call).*/
        nop;
 
-C_ENTRY(sys_rt_sigsuspend_wrapper):
-       swi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
-       swi     r4, r1, PTO+PT_R4;
-       la      r7, r1, PTO;            /* add user context as 3rd arg */
-       brlid   r15, sys_rt_sigsuspend; /* Do real work.*/
-       nop;
-       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;
-
 C_ENTRY(sys_rt_sigreturn_wrapper):
        swi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
        swi     r4, r1, PTO+PT_R4;
@@ -711,15 +704,11 @@ C_ENTRY(ret_from_exc):
         * (in a possibly modified form) after do_signal returns.
         * store return registers separately because this macros is use
         * for others exceptions */
-       swi     r3, r1, PTO + PT_R3;
-       swi     r4, r1, PTO + PT_R4;
        la      r5, r1, PTO;            /* Arg 1: struct pt_regs *regs */
        add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
        addi    r7, r0, 0;              /* Arg 3: int in_syscall */
        bralid  r15, do_signal; /* Handle any signals */
        nop;
-       lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
-       lwi     r4, r1, PTO+PT_R4;
 
 /* Finally, return to user state.  */
 1:     swi     r0, r0, PER_CPU(KM);    /* Now officially in user state. */
diff --git a/arch/microblaze/kernel/ftrace.c b/arch/microblaze/kernel/ftrace.c
new file mode 100644 (file)
index 0000000..388b31c
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Ftrace support for Microblaze.
+ *
+ * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2009 PetaLogix
+ *
+ * Based on MIPS and PowerPC ftrace code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <asm/cacheflush.h>
+#include <linux/ftrace.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * Hook the return address and push it in the stack of return addrs
+ * in current thread info.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
+{
+       unsigned long old;
+       int faulted, err;
+       struct ftrace_graph_ent trace;
+       unsigned long return_hooker = (unsigned long)
+                               &return_to_handler;
+
+       if (unlikely(atomic_read(&current->tracing_graph_pause)))
+               return;
+
+       /*
+        * Protect against fault, even if it shouldn't
+        * happen. This tool is too much intrusive to
+        * ignore such a protection.
+        */
+       asm volatile("  1:      lwi     %0, %2, 0;              \
+                       2:      swi     %3, %2, 0;              \
+                               addik   %1, r0, 0;              \
+                       3:                                      \
+                               .section .fixup, \"ax\";        \
+                       4:      brid    3b;                     \
+                               addik   %1, r0, 1;              \
+                               .previous;                      \
+                               .section __ex_table,\"a\";      \
+                               .word   1b,4b;                  \
+                               .word   2b,4b;                  \
+                               .previous;"                     \
+                       : "=&r" (old), "=r" (faulted)
+                       : "r" (parent), "r" (return_hooker)
+       );
+
+       if (unlikely(faulted)) {
+               ftrace_graph_stop();
+               WARN_ON(1);
+               return;
+       }
+
+       err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0);
+       if (err == -EBUSY) {
+               *parent = old;
+               return;
+       }
+
+       trace.func = self_addr;
+       /* Only trace if the calling function expects to */
+       if (!ftrace_graph_entry(&trace)) {
+               current->curr_ret_stack--;
+               *parent = old;
+       }
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/* save value to addr - it is save to do it in asm */
+static int ftrace_modify_code(unsigned long addr, unsigned int value)
+{
+       int faulted = 0;
+
+       __asm__ __volatile__("  1:      swi     %2, %1, 0;              \
+                                       addik   %0, r0, 0;              \
+                               2:                                      \
+                                       .section .fixup, \"ax\";        \
+                               3:      brid    2b;                     \
+                                       addik   %0, r0, 1;              \
+                                       .previous;                      \
+                                       .section __ex_table,\"a\";      \
+                                       .word   1b,3b;                  \
+                                       .previous;"                     \
+                               : "=r" (faulted)
+                               : "r" (addr), "r" (value)
+       );
+
+       if (unlikely(faulted))
+               return -EFAULT;
+
+       return 0;
+}
+
+#define MICROBLAZE_NOP 0x80000000
+#define MICROBLAZE_BRI 0xb800000C
+
+static unsigned int recorded; /* if save was or not */
+static unsigned int imm; /* saving whole imm instruction */
+
+/* There are two approaches howto solve ftrace_make nop function - look below */
+#undef USE_FTRACE_NOP
+
+#ifdef USE_FTRACE_NOP
+static unsigned int bralid; /* saving whole bralid instruction */
+#endif
+
+int ftrace_make_nop(struct module *mod,
+                       struct dyn_ftrace *rec, unsigned long addr)
+{
+       /* we have this part of code which we are working with
+        * b000c000        imm     -16384
+        * b9fc8e30        bralid  r15, -29136     // c0008e30 <_mcount>
+        * 80000000        or      r0, r0, r0
+        *
+        * The first solution (!USE_FTRACE_NOP-could be called branch solution)
+        * b000c000        bri  12 (0xC - jump to any other instruction)
+        * b9fc8e30        bralid  r15, -29136     // c0008e30 <_mcount>
+        * 80000000        or      r0, r0, r0
+        * any other instruction
+        *
+        * The second solution (USE_FTRACE_NOP) - no jump just nops
+        * 80000000        or      r0, r0, r0
+        * 80000000        or      r0, r0, r0
+        * 80000000        or      r0, r0, r0
+        */
+       int ret = 0;
+
+       if (recorded == 0) {
+               recorded = 1;
+               imm = *(unsigned int *)rec->ip;
+               pr_debug("%s: imm:0x%x\n", __func__, imm);
+#ifdef USE_FTRACE_NOP
+               bralid = *(unsigned int *)(rec->ip + 4);
+               pr_debug("%s: bralid 0x%x\n", __func__, bralid);
+#endif /* USE_FTRACE_NOP */
+       }
+
+#ifdef USE_FTRACE_NOP
+       ret = ftrace_modify_code(rec->ip, MICROBLAZE_NOP);
+       ret += ftrace_modify_code(rec->ip + 4, MICROBLAZE_NOP);
+#else /* USE_FTRACE_NOP */
+       ret = ftrace_modify_code(rec->ip, MICROBLAZE_BRI);
+#endif /* USE_FTRACE_NOP */
+       return ret;
+}
+
+static int ret_addr; /* initialized as 0 by default */
+
+/* I believe that first is called ftrace_make_nop before this function */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+       int ret;
+       ret_addr = addr; /* saving where the barrier jump is */
+       pr_debug("%s: addr:0x%x, rec->ip: 0x%x, imm:0x%x\n",
+               __func__, (unsigned int)addr, (unsigned int)rec->ip, imm);
+       ret = ftrace_modify_code(rec->ip, imm);
+#ifdef USE_FTRACE_NOP
+       pr_debug("%s: bralid:0x%x\n", __func__, bralid);
+       ret += ftrace_modify_code(rec->ip + 4, bralid);
+#endif /* USE_FTRACE_NOP */
+       return ret;
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+       /* The return code is retured via data */
+       *(unsigned long *)data = 0;
+
+       return 0;
+}
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+       unsigned long ip = (unsigned long)(&ftrace_call);
+       unsigned int upper = (unsigned int)func;
+       unsigned int lower = (unsigned int)func;
+       int ret = 0;
+
+       /* create proper saving to ftrace_call poll */
+       upper = 0xb0000000 + (upper >> 16); /* imm func_upper */
+       lower = 0x32800000 + (lower & 0xFFFF); /* addik r20, r0, func_lower */
+
+       pr_debug("%s: func=0x%x, ip=0x%x, upper=0x%x, lower=0x%x\n",
+               __func__, (unsigned int)func, (unsigned int)ip, upper, lower);
+
+       /* save upper and lower code */
+       ret = ftrace_modify_code(ip, upper);
+       ret += ftrace_modify_code(ip + 4, lower);
+
+       /* We just need to remove the rtsd r15, 8 by NOP */
+       BUG_ON(!ret_addr);
+       if (ret_addr)
+               ret += ftrace_modify_code(ret_addr, MICROBLAZE_NOP);
+       else
+               ret = 1; /* fault */
+
+       /* All changes are done - lets do caches consistent */
+       flush_icache();
+       return ret;
+}
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+unsigned int old_jump; /* saving place for jump instruction */
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+       unsigned int ret;
+       unsigned long ip = (unsigned long)(&ftrace_call_graph);
+
+       old_jump = *(unsigned int *)ip; /* save jump over instruction */
+       ret = ftrace_modify_code(ip, MICROBLAZE_NOP);
+       flush_icache();
+
+       pr_debug("%s: Replace instruction: 0x%x\n", __func__, old_jump);
+       return ret;
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+       unsigned int ret;
+       unsigned long ip = (unsigned long)(&ftrace_call_graph);
+
+       ret = ftrace_modify_code(ip, old_jump);
+       flush_icache();
+
+       pr_debug("%s\n", __func__);
+       return ret;
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#endif /* CONFIG_DYNAMIC_FTRACE */
index 1bdf20222b92ba0ecdb0fe8b35488f7653ab6909..522751737cfad936fe5193a93fd0105c874c04cc 100644 (file)
@@ -45,6 +45,7 @@ void heartbeat(void)
 void setup_heartbeat(void)
 {
        struct device_node *gpio = NULL;
+       int *prop;
        int j;
        char *gpio_list[] = {
                                "xlnx,xps-gpio-1.00.a",
@@ -58,10 +59,14 @@ void setup_heartbeat(void)
                        break;
        }
 
-       base_addr = *(int *) 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);
+       if (gpio) {
+               base_addr = *(int *) 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);
 
-       if (*(int *) of_get_property(gpio, "xlnx,is-bidir", NULL))
-               out_be32(base_addr + 4, 0); /* GPIO is configured as output */
+               /* GPIO is configured as output */
+               prop = (int *) of_get_property(gpio, "xlnx,is-bidir", NULL);
+               if (prop)
+                       out_be32(base_addr + 4, 0);
+       }
 }
index 6eea6f92b84e19780b781bdad3da277fed57a4bb..03172c1da770c69eda75e8c72aca7a648c7ada53 100644 (file)
@@ -42,8 +42,16 @@ unsigned int nr_irq;
 
 static void intc_enable_or_unmask(unsigned int irq)
 {
+       unsigned long mask = 1 << irq;
        pr_debug("enable_or_unmask: %d\n", irq);
-       out_be32(INTC_BASE + SIE, 1 << irq);
+       out_be32(INTC_BASE + SIE, mask);
+
+       /* ack level irqs because they can't be acked during
+        * ack function since the handle_level_irq function
+        * acks the irq before calling the interrupt handler
+        */
+       if (irq_desc[irq].status & IRQ_LEVEL)
+               out_be32(INTC_BASE + IAR, mask);
 }
 
 static void intc_disable_or_mask(unsigned int irq)
diff --git a/arch/microblaze/kernel/mcount.S b/arch/microblaze/kernel/mcount.S
new file mode 100644 (file)
index 0000000..e7eaa7a
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Low-level ftrace handling
+ *
+ * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2009 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#include <linux/linkage.h>
+
+#define NOALIGN_ENTRY(name)    .globl name; name:
+
+/* FIXME MS: I think that I don't need to save all regs */
+#define SAVE_REGS              \
+       addik   r1, r1, -120;   \
+       swi     r2, r1, 4;      \
+       swi     r3, r1, 8;      \
+       swi     r4, r1, 12;     \
+       swi     r5, r1, 116;    \
+       swi     r6, r1, 16;     \
+       swi     r7, r1, 20;     \
+       swi     r8, r1, 24;     \
+       swi     r9, r1, 28;     \
+       swi     r10, r1, 32;    \
+       swi     r11, r1, 36;    \
+       swi     r12, r1, 40;    \
+       swi     r13, r1, 44;    \
+       swi     r14, r1, 48;    \
+       swi     r16, r1, 52;    \
+       swi     r17, r1, 56;    \
+       swi     r18, r1, 60;    \
+       swi     r19, r1, 64;    \
+       swi     r20, r1, 68;    \
+       swi     r21, r1, 72;    \
+       swi     r22, r1, 76;    \
+       swi     r23, r1, 80;    \
+       swi     r24, r1, 84;    \
+       swi     r25, r1, 88;    \
+       swi     r26, r1, 92;    \
+       swi     r27, r1, 96;    \
+       swi     r28, r1, 100;   \
+       swi     r29, r1, 104;   \
+       swi     r30, r1, 108;   \
+       swi     r31, r1, 112;
+
+#define RESTORE_REGS           \
+       lwi     r2, r1, 4;      \
+       lwi     r3, r1, 8;      \
+       lwi     r4, r1, 12;     \
+       lwi     r5, r1, 116;    \
+       lwi     r6, r1, 16;     \
+       lwi     r7, r1, 20;     \
+       lwi     r8, r1, 24;     \
+       lwi     r9, r1, 28;     \
+       lwi     r10, r1, 32;    \
+       lwi     r11, r1, 36;    \
+       lwi     r12, r1, 40;    \
+       lwi     r13, r1, 44;    \
+       lwi     r14, r1, 48;    \
+       lwi     r16, r1, 52;    \
+       lwi     r17, r1, 56;    \
+       lwi     r18, r1, 60;    \
+       lwi     r19, r1, 64;    \
+       lwi     r20, r1, 68;    \
+       lwi     r21, r1, 72;    \
+       lwi     r22, r1, 76;    \
+       lwi     r23, r1, 80;    \
+       lwi     r24, r1, 84;    \
+       lwi     r25, r1, 88;    \
+       lwi     r26, r1, 92;    \
+       lwi     r27, r1, 96;    \
+       lwi     r28, r1, 100;   \
+       lwi     r29, r1, 104;   \
+       lwi     r30, r1, 108;   \
+       lwi     r31, r1, 112;   \
+       addik   r1, r1, 120;
+
+ENTRY(ftrace_stub)
+       rtsd    r15, 8;
+       nop;
+
+ENTRY(_mcount)
+#ifdef CONFIG_DYNAMIC_FTRACE
+ENTRY(ftrace_caller)
+       /* MS: It is just barrier which is removed from C code */
+       rtsd    r15, 8
+       nop
+#endif /* CONFIG_DYNAMIC_FTRACE */
+       SAVE_REGS
+       swi     r15, r1, 0;
+       /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST begin of checking */
+       lwi     r5, r0, function_trace_stop;
+       bneid   r5, end;
+       nop;
+       /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#ifndef CONFIG_DYNAMIC_FTRACE
+       lwi     r5, r0, ftrace_graph_return;
+       addik   r6, r0, ftrace_stub; /* asm implementation */
+       cmpu    r5, r5, r6; /* ftrace_graph_return != ftrace_stub */
+       beqid   r5, end_graph_tracer;
+       nop;
+
+       lwi     r6, r0, ftrace_graph_entry;
+       addik   r5, r0, ftrace_graph_entry_stub; /* implemented in C */
+       cmpu    r5, r5, r6; /* ftrace_graph_entry != ftrace_graph_entry_stub */
+       beqid   r5, end_graph_tracer;
+       nop;
+#else /* CONFIG_DYNAMIC_FTRACE */
+NOALIGN_ENTRY(ftrace_call_graph)
+       /* MS: jump over graph function - replaced from C code */
+       bri     end_graph_tracer
+#endif /* CONFIG_DYNAMIC_FTRACE */
+       addik   r5, r1, 120; /* MS: load parent addr */
+       addik   r6, r15, 0; /* MS: load current function addr */
+       bralid  r15, prepare_ftrace_return;
+       nop;
+       /* MS: graph was taken that's why - can jump over function trace */
+       brid    end;
+       nop;
+end_graph_tracer:
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#ifndef CONFIG_DYNAMIC_FTRACE
+       /* MS: test function trace if is taken or not */
+       lwi     r20, r0, ftrace_trace_function;
+       addik   r6, r0, ftrace_stub;
+       cmpu    r5, r20, r6; /* ftrace_trace_function != ftrace_stub */
+       beqid   r5, end; /* MS: not taken -> jump over */
+       nop;
+#else /* CONFIG_DYNAMIC_FTRACE */
+NOALIGN_ENTRY(ftrace_call)
+/* instruction for setup imm FUNC_part1, addik r20, r0, FUNC_part2 */
+       nop
+       nop
+#endif /* CONFIG_DYNAMIC_FTRACE */
+/* static normal trace */
+       lwi     r6, r1, 120; /* MS: load parent addr */
+       addik   r5, r15, 0; /* MS: load current function addr */
+       /* MS: here is dependency on previous code */
+       brald   r15, r20; /* MS: jump to ftrace handler */
+       nop;
+end:
+       lwi     r15, r1, 0;
+       RESTORE_REGS
+
+       rtsd    r15, 8; /* MS: jump back */
+       nop;
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ENTRY(return_to_handler)
+       nop; /* MS: just barrier for rtsd r15, 8 */
+       nop;
+       SAVE_REGS
+       swi     r15, r1, 0;
+
+       /* MS: find out returning address */
+       bralid  r15, ftrace_return_to_handler;
+       nop;
+
+       /* MS: return value from ftrace_return_to_handler is my returning addr
+        * must be before restore regs because I have to restore r3 content */
+       addik   r15, r3, 0;
+       RESTORE_REGS
+
+       rtsd    r15, 8; /* MS: jump back */
+       nop;
+#endif /* CONFIG_FUNCTION_TRACER */
index 59ff20e33e0cde5b22b7f95fb0517323066c4440..bc4dcb7d3861c50aff24b152f37655c80c937d95 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <asm/page.h>
 #include <asm/system.h>
+#include <linux/ftrace.h>
 #include <linux/uaccess.h>
 
 /*
@@ -47,3 +48,7 @@ extern void __umodsi3(void);
 EXPORT_SYMBOL(__umodsi3);
 extern char *_ebss;
 EXPORT_SYMBOL_GPL(_ebss);
+#ifdef CONFIG_FUNCTION_TRACER
+extern void _mcount(void);
+EXPORT_SYMBOL(_mcount);
+#endif
index c592d475b3d890a50061f8f3b265c4516457d749..812f1bf06c9e5cbfb2a88222974e2931d20f9a24 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/bitops.h>
 #include <asm/system.h>
 #include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
 
 void show_regs(struct pt_regs *regs)
 {
diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c
new file mode 100644 (file)
index 0000000..a1721a3
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2009 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/of_platform.h>
+#include <asm/prom.h>
+
+/* Trigger specific functions */
+#ifdef CONFIG_GPIOLIB
+
+#include <linux/of_gpio.h>
+
+static int handle; /* reset pin handle */
+static unsigned int reset_val;
+
+static int of_reset_gpio_handle(void)
+{
+       int ret; /* variable which stored handle reset gpio pin */
+       struct device_node *root; /* root node */
+       struct device_node *gpio; /* gpio node */
+       struct of_gpio_chip *of_gc = NULL;
+       enum of_gpio_flags flags ;
+       const void *gpio_spec;
+
+       /* find out root node */
+       root = of_find_node_by_path("/");
+
+       /* give me handle for gpio node to be possible allocate pin */
+       ret = of_parse_phandles_with_args(root, "hard-reset-gpios",
+                               "#gpio-cells", 0, &gpio, &gpio_spec);
+       if (ret) {
+               pr_debug("%s: can't parse gpios property\n", __func__);
+               goto err0;
+       }
+
+       of_gc = gpio->data;
+       if (!of_gc) {
+               pr_debug("%s: gpio controller %s isn't registered\n",
+                        root->full_name, gpio->full_name);
+               ret = -ENODEV;
+               goto err1;
+       }
+
+       ret = of_gc->xlate(of_gc, root, gpio_spec, &flags);
+       if (ret < 0)
+               goto err1;
+
+       ret += of_gc->gc.base;
+err1:
+       of_node_put(gpio);
+err0:
+       pr_debug("%s exited with status %d\n", __func__, ret);
+       return ret;
+}
+
+void of_platform_reset_gpio_probe(void)
+{
+       int ret;
+       handle = of_reset_gpio_handle();
+
+       if (!gpio_is_valid(handle)) {
+               printk(KERN_INFO "Skipping unavailable RESET gpio %d (%s)\n",
+                               handle, "reset");
+       }
+
+       ret = gpio_request(handle, "reset");
+       if (ret < 0) {
+               printk(KERN_INFO "GPIO pin is already allocated\n");
+               return;
+       }
+
+       /* get current setup value */
+       reset_val = gpio_get_value(handle);
+       /* FIXME maybe worth to perform any action */
+       pr_debug("Reset: Gpio output state: 0x%x\n", reset_val);
+
+       /* Setup GPIO as output */
+       ret = gpio_direction_output(handle, 0);
+       if (ret < 0)
+               goto err;
+
+       /* Setup output direction */
+       gpio_set_value(handle, 0);
+
+       printk(KERN_INFO "RESET: Registered gpio device: %d, current val: %d\n",
+                                                       handle, reset_val);
+       return;
+err:
+       gpio_free(handle);
+       return;
+}
+
+
+static void gpio_system_reset(void)
+{
+       gpio_set_value(handle, 1 - reset_val);
+}
+#else
+#define gpio_system_reset() do {} while (0)
+void of_platform_reset_gpio_probe(void)
+{
+       return;
+}
+#endif
+
+void machine_restart(char *cmd)
+{
+       printk(KERN_NOTICE "Machine restart...\n");
+       gpio_system_reset();
+       dump_stack();
+       while (1)
+               ;
+}
+
+void machine_shutdown(void)
+{
+       printk(KERN_NOTICE "Machine shutdown...\n");
+       while (1)
+               ;
+}
+
+void machine_halt(void)
+{
+       printk(KERN_NOTICE "Machine halt...\n");
+       while (1)
+               ;
+}
+
+void machine_power_off(void)
+{
+       printk(KERN_NOTICE "Machine power off...\n");
+       while (1)
+               ;
+}
index 8c1e0f4dcf18b63c6323a3b8042c68c3774621e0..5372b24ad049cf92cfd881927c21f5e559a54089 100644 (file)
@@ -52,13 +52,12 @@ void __init setup_arch(char **cmdline_p)
        /* irq_early_init(); */
        setup_cpuinfo();
 
-       __invalidate_icache_all();
-       __enable_icache();
+       microblaze_cache_init();
 
-       __invalidate_dcache_all();
-       __enable_dcache();
+       enable_dcache();
 
-       panic_timeout = 120;
+       invalidate_icache();
+       enable_icache();
 
        setup_memory();
 
@@ -131,6 +130,8 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
                strlcpy(cmd_line, cmdline, COMMAND_LINE_SIZE);
 #endif
 
+       lockdep_init();
+
 /* initialize device tree for usage in early_printk */
        early_init_devtree((void *)_fdt_start);
 
@@ -186,32 +187,3 @@ static int microblaze_debugfs_init(void)
 }
 arch_initcall(microblaze_debugfs_init);
 #endif
-
-void machine_restart(char *cmd)
-{
-       printk(KERN_NOTICE "Machine restart...\n");
-       dump_stack();
-       while (1)
-               ;
-}
-
-void machine_shutdown(void)
-{
-       printk(KERN_NOTICE "Machine shutdown...\n");
-       while (1)
-               ;
-}
-
-void machine_halt(void)
-{
-       printk(KERN_NOTICE "Machine halt...\n");
-       while (1)
-               ;
-}
-
-void machine_power_off(void)
-{
-       printk(KERN_NOTICE "Machine power off...\n");
-       while (1)
-               ;
-}
index 1c80e4fc40cef1fc0513951c449452ff23139c96..d8d3bb396cd6d7e4b0d82d52fa62960222662ab3 100644 (file)
@@ -44,7 +44,6 @@
 
 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
 
-
 asmlinkage long
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
                struct pt_regs *regs)
@@ -176,6 +175,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        struct rt_sigframe __user *frame;
        int err = 0;
        int signal;
+       unsigned long address = 0;
+#ifdef CONFIG_MMU
+       pmd_t *pmdp;
+       pte_t *ptep;
+#endif
 
        frame = get_sigframe(ka, regs, sizeof(*frame));
 
@@ -216,8 +220,29 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
         Negative 8 offset because return is rtsd r15, 8 */
        regs->r15 = ((unsigned long)frame->tramp)-8;
 
-       __invalidate_cache_sigtramp((unsigned long)frame->tramp);
-
+       address = ((unsigned long)frame->tramp);
+#ifdef CONFIG_MMU
+       pmdp = pmd_offset(pud_offset(
+                       pgd_offset(current->mm, address),
+                                       address), address);
+
+       preempt_disable();
+       ptep = pte_offset_map(pmdp, address);
+       if (pte_present(*ptep)) {
+               address = (unsigned long) page_address(pte_page(*ptep));
+               /* MS: I need add offset in page */
+               address += ((unsigned long)frame->tramp) & ~PAGE_MASK;
+               /* MS address is virtual */
+               address = virt_to_phys(address);
+               invalidate_icache_range(address, address + 8);
+               flush_dcache_range(address, address + 8);
+       }
+       pte_unmap(ptep);
+       preempt_enable();
+#else
+       flush_icache_range(address, address + 8);
+       flush_dcache_range(address, address + 8);
+#endif
        if (err)
                goto give_sigsegv;
 
@@ -233,6 +258,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        set_fs(USER_DS);
 
+       /* the tracer may want to single-step inside the handler */
+       if (test_thread_flag(TIF_SINGLESTEP))
+               ptrace_notify(SIGTRAP);
+
 #ifdef DEBUG_SIG
        printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
                current->comm, current->pid, frame, regs->pc);
diff --git a/arch/microblaze/kernel/stacktrace.c b/arch/microblaze/kernel/stacktrace.c
new file mode 100644 (file)
index 0000000..123692f
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Stack trace support for Microblaze.
+ *
+ * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2009 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <linux/ptrace.h>
+#include <linux/module.h>
+
+/* FIXME initial support */
+void save_stack_trace(struct stack_trace *trace)
+{
+       unsigned long *sp;
+       unsigned long addr;
+       asm("addik %0, r1, 0" : "=r" (sp));
+
+       while (!kstack_end(sp)) {
+               addr = *sp++;
+               if (__kernel_text_address(addr)) {
+                       if (trace->skip > 0)
+                               trace->skip--;
+                       else
+                               trace->entries[trace->nr_entries++] = addr;
+
+                       if (trace->nr_entries >= trace->max_entries)
+                               break;
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(save_stack_trace);
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+       unsigned int *sp;
+       unsigned long addr;
+
+       struct thread_info *ti = task_thread_info(tsk);
+
+       if (tsk == current)
+               asm("addik %0, r1, 0" : "=r" (sp));
+       else
+               sp = (unsigned int *)ti->cpu_context.r1;
+
+       while (!kstack_end(sp)) {
+               addr = *sp++;
+               if (__kernel_text_address(addr)) {
+                       if (trace->skip > 0)
+                               trace->skip--;
+                       else
+                               trace->entries[trace->nr_entries++] = addr;
+
+                       if (trace->nr_entries >= trace->max_entries)
+                               break;
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
index b96f365ea6b1aaf46d5d9c1026f8ae9fbac7afa1..4088be7d4e292ed307cdf4539df4f2b5adfc06be 100644 (file)
@@ -183,7 +183,7 @@ ENTRY(sys_call_table)
        .long sys_rt_sigpending
        .long sys_rt_sigtimedwait
        .long sys_rt_sigqueueinfo
-       .long sys_rt_sigsuspend_wrapper
+       .long sys_rt_sigsuspend
        .long sys_pread64               /* 180 */
        .long sys_pwrite64
        .long sys_chown
@@ -303,7 +303,7 @@ ENTRY(sys_call_table)
        .long sys_mkdirat
        .long sys_mknodat
        .long sys_fchownat
-       .long sys_ni_syscall
+       .long sys_futimesat
        .long sys_fstatat64             /* 300 */
        .long sys_unlinkat
        .long sys_renameat
index 5499deae7fa68cb155e4e6aefe9b53c0da8c7298..ed61b2f177192e79921fae4e95092374309a3c0f 100644 (file)
@@ -183,6 +183,31 @@ static cycle_t microblaze_read(struct clocksource *cs)
        return (cycle_t) (in_be32(TIMER_BASE + TCR1));
 }
 
+static struct timecounter microblaze_tc = {
+       .cc = NULL,
+};
+
+static cycle_t microblaze_cc_read(const struct cyclecounter *cc)
+{
+       return microblaze_read(NULL);
+}
+
+static struct cyclecounter microblaze_cc = {
+       .read = microblaze_cc_read,
+       .mask = CLOCKSOURCE_MASK(32),
+       .shift = 24,
+};
+
+int __init init_microblaze_timecounter(void)
+{
+       microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
+                               microblaze_cc.shift);
+
+       timecounter_init(&microblaze_tc, &microblaze_cc, sched_clock());
+
+       return 0;
+}
+
 static struct clocksource clocksource_microblaze = {
        .name           = "microblaze_clocksource",
        .rating         = 300,
@@ -204,6 +229,9 @@ static int __init microblaze_clocksource_init(void)
        out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT);
        /* start timer1 - up counting without interrupt */
        out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT);
+
+       /* register timecounter - for ftrace support */
+       init_microblaze_timecounter();
        return 0;
 }
 
index e704188d7855ec6115ddef659505ffba6b6d5578..5ef619aad6341b8ecd6ca021c03dd4b74d418653 100644 (file)
@@ -26,11 +26,12 @@ SECTIONS {
                _stext = . ;
                *(.text .text.*)
                *(.fixup)
-               EXIT_TEXT
-               EXIT_CALL
+               EXIT_TEXT
+               EXIT_CALL
                SCHED_TEXT
                LOCK_TEXT
                KPROBES_TEXT
+               IRQENTRY_TEXT
                . = ALIGN (4) ;
                _etext = . ;
        }
@@ -86,6 +87,7 @@ SECTIONS {
                _KERNEL_SDA_BASE_ = _ssro + (_ssro_size / 2) ;
        }
 
+       . = ALIGN(PAGE_SIZE);
        __init_begin = .;
 
        INIT_TEXT_SECTION(PAGE_SIZE)
index 8eb9df5a26c9f53ad53a298330039e1e88898295..a853fe089c44a402c4e53e41b65792ebca5c2f09 100644 (file)
@@ -39,3 +39,10 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
                __do_strncpy_from_user(dst, src, count, res);
        return res;
 }
+
+unsigned long __copy_tofrom_user(void __user *to,
+               const void __user *from, unsigned long size)
+{
+       memcpy(to, from, size);
+       return 0;
+}
index a44892e7cd5b7e2839976585e69bc8c274c21509..a57cedf36715f7511395b3066878731b107edb1e 100644 (file)
@@ -41,6 +41,7 @@ char *klimit = _end;
  * have available.
  */
 unsigned long memory_start;
+EXPORT_SYMBOL(memory_start);
 unsigned long memory_end; /* due to mm/nommu.c */
 unsigned long memory_size;
 
index 46c4ca5d15c55f4d573ad9248c2eec1a9ab65478..2820081b21ab8bc4a9b87c5147f3516cfb674c4a 100644 (file)
@@ -144,7 +144,6 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
        pmd_t *pd;
        pte_t *pg;
        int err = -ENOMEM;
-       /* spin_lock(&init_mm.page_table_lock); */
        /* Use upper 10 bits of VA to index the first level map */
        pd = pmd_offset(pgd_offset_k(va), va);
        /* Use middle 10 bits of VA to index the second-level map */
@@ -158,9 +157,7 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
                if (mem_init_done)
                        flush_HPTE(0, va, pmd_val(*pd));
                        /* flush_HPTE(0, va, pg); */
-
        }
-       /* spin_unlock(&init_mm.page_table_lock); */
        return err;
 }
 
@@ -182,12 +179,6 @@ void __init adjust_total_lowmem(void)
 #endif
 }
 
-static void show_tmem(unsigned long tmem)
-{
-       volatile unsigned long a;
-       a = a + tmem;
-}
-
 /*
  * Map in all of physical memory starting at CONFIG_KERNEL_START.
  */
@@ -197,7 +188,6 @@ void __init mapin_ram(void)
 
        v = CONFIG_KERNEL_START;
        p = memory_start;
-       show_tmem(memory_size);
        for (s = 0; s < memory_size; s += PAGE_SIZE) {
                f = _PAGE_PRESENT | _PAGE_ACCESSED |
                                _PAGE_SHARED | _PAGE_HWEXEC;
diff --git a/arch/microblaze/oprofile/Makefile b/arch/microblaze/oprofile/Makefile
new file mode 100644 (file)
index 0000000..0d0348c
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# arch/microblaze/oprofile/Makefile
+#
+
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
+               oprof.o cpu_buffer.o buffer_sync.o \
+               event_buffer.o oprofile_files.o \
+               oprofilefs.o oprofile_stats.o \
+               timer_int.o )
+
+oprofile-y := $(DRIVER_OBJS) microblaze_oprofile.o
diff --git a/arch/microblaze/oprofile/microblaze_oprofile.c b/arch/microblaze/oprofile/microblaze_oprofile.c
new file mode 100644 (file)
index 0000000..def17e5
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Microblaze oprofile code
+ *
+ * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2009 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/oprofile.h>
+#include <linux/init.h>
+
+int __init oprofile_arch_init(struct oprofile_operations *ops)
+{
+       return -1;
+}
+
+void oprofile_arch_exit(void)
+{
+}
index 8e9b4752d3ff1def57e29b91a587f404e077928f..669c7eec293eb921689ba618a11d9e701ee626a3 100644 (file)
@@ -53,31 +53,12 @@ config OPT_LIB_FUNCTION
 
 config OPT_LIB_ASM
        bool "Optimalized lib function ASM"
-       depends on OPT_LIB_FUNCTION
+       depends on OPT_LIB_FUNCTION && (XILINX_MICROBLAZE0_USE_BARREL = 1)
        default n
        help
          Allows turn on optimalized library function (memcpy and memmove).
          Function are written in asm code.
 
-# This is still a bit broken - disabling for now JW 20070504
-config ALLOW_EDIT_AUTO
-       bool "Permit Display/edit of Kconfig.auto platform settings"
-       default n
-       help
-         Allows the editing of auto-generated platform settings from
-         the Kconfig.auto file. Obviously this does not change the
-         underlying hardware, so be very careful if you go editing
-         these settings.
-
-         Also, if you enable this, and edit various Kconfig.auto
-         settings, YOUR CHANGES WILL BE LOST if you then disable it
-         again. You have been warned!
-
-         If unsure, say no.
-
-comment "Automatic platform settings from Kconfig.auto"
-       depends on ALLOW_EDIT_AUTO
-
 if PLATFORM_GENERIC=y
        source "arch/microblaze/platform/generic/Kconfig.auto"
 endif
index fbca22d9c8b9bac47767f1b2f0e5fd1c48d1f8f1..5d86fc19029d412ed068ecff73c4010dde9841d0 100644 (file)
@@ -21,7 +21,6 @@
 
 # Definitions for MICROBLAZE0
 comment "Definitions for MICROBLAZE0"
-       depends on ALLOW_EDIT_AUTO
 
 config KERNEL_BASE_ADDR
        hex "Physical address where Linux Kernel is"
@@ -30,33 +29,33 @@ config KERNEL_BASE_ADDR
          BASE Address for kernel
 
 config XILINX_MICROBLAZE0_FAMILY
-       string "Targetted FPGA family" if ALLOW_EDIT_AUTO
+       string "Targetted FPGA family"
        default "virtex5"
 
 config XILINX_MICROBLAZE0_USE_MSR_INSTR
-       int "USE_MSR_INSTR range (0:1)" if ALLOW_EDIT_AUTO
-       default 1
+       int "USE_MSR_INSTR range (0:1)"
+       default 0
 
 config XILINX_MICROBLAZE0_USE_PCMP_INSTR
-       int "USE_PCMP_INSTR range (0:1)" if ALLOW_EDIT_AUTO
-       default 1
+       int "USE_PCMP_INSTR range (0:1)"
+       default 0
 
 config XILINX_MICROBLAZE0_USE_BARREL
-       int "USE_BARREL range (0:1)" if ALLOW_EDIT_AUTO
-       default 1
+       int "USE_BARREL range (0:1)"
+       default 0
 
 config XILINX_MICROBLAZE0_USE_DIV
-       int "USE_DIV range (0:1)" if ALLOW_EDIT_AUTO
-       default 1
+       int "USE_DIV range (0:1)"
+       default 0
 
 config XILINX_MICROBLAZE0_USE_HW_MUL
-       int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)" if ALLOW_EDIT_AUTO
-       default 2
+       int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)"
+       default 0
 
 config XILINX_MICROBLAZE0_USE_FPU
-       int "USE_FPU values (0=NONE, 1=BASIC, 2=EXTENDED)" if ALLOW_EDIT_AUTO
-       default 2
+       int "USE_FPU values (0=NONE, 1=BASIC, 2=EXTENDED)"
+       default 0
 
 config XILINX_MICROBLAZE0_HW_VER
-       string "Core version number" if ALLOW_EDIT_AUTO
+       string "Core version number"
        default 7.10.d
index 29993f62b30a2c47abfb7c24a3ab5677c9142dc5..2d5c41767cd06ca146e0192df79e9fd9f06ef441 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
        compatible = "xlnx,microblaze";
+       hard-reset-gpios = <&LEDs_8Bit 2 1>;
        model = "testing";
        DDR2_SDRAM: memory@90000000 {
                device_type = "memory";
                reg = < 0x90000000 0x10000000 >;
        } ;
+       aliases {
+               ethernet0 = &Hard_Ethernet_MAC;
+               serial0 = &RS232_Uart_1;
+       } ;
        chosen {
                bootargs = "console=ttyUL0,115200 highres=on";
                linux,stdout-path = "/plb@0/serial@84000000";
        mb_plb: plb@0 {
                #address-cells = <1>;
                #size-cells = <1>;
-               compatible = "xlnx,plb-v46-1.03.a", "simple-bus";
+               compatible = "xlnx,plb-v46-1.03.a", "xlnx,plb-v46-1.00.a", "simple-bus";
                ranges ;
                FLASH: flash@a0000000 {
                        bank-width = <2>;
                        #size-cells = <1>;
                        compatible = "xlnx,compound";
                        ethernet@81c00000 {
-                               compatible = "xlnx,xps-ll-temac-1.01.b";
+                               compatible = "xlnx,xps-ll-temac-1.01.b", "xlnx,xps-ll-temac-1.00.a";
                                device_type = "network";
                                interrupt-parent = <&xps_intc_0>;
                                interrupts = < 5 2 >;
                                llink-connected = <&PIM3>;
-                               local-mac-address = [ 02 00 00 00 00 00 ];
+                               local-mac-address = [ 00 0a 35 00 00 00 ];
                                reg = < 0x81c00000 0x40 >;
                                xlnx,bus2core-clk-ratio = <0x1>;
                                xlnx,phy-type = <0x1>;
                        xlnx,is-dual = <0x0>;
                        xlnx,tri-default = <0xffffffff>;
                        xlnx,tri-default-2 = <0xffffffff>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+               } ;
+
+               gpio-leds {
+                       compatible = "gpio-leds";
+
+                       heartbeat {
+                               label = "Heartbeat";
+                               gpios = <&LEDs_8Bit 4 1>;
+                               linux,default-trigger = "heartbeat";
+                       };
+
+                       yellow {
+                               label = "Yellow";
+                               gpios = <&LEDs_8Bit 5 1>;
+                       };
+
+                       red {
+                               label = "Red";
+                               gpios = <&LEDs_8Bit 6 1>;
+                       };
+
+                       green {
+                               label = "Green";
+                               gpios = <&LEDs_8Bit 7 1>;
+                       };
                } ;
                RS232_Uart_1: serial@84000000 {
                        clock-frequency = <125000000>;
index 56e0234fa34b444a235bd4b812861f3c9c3e96ad..5b89b58c5aedbc9d9f12aa5d6b2e541134101f6f 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/of_platform.h>
 #include <asm/prom.h>
+#include <asm/setup.h>
 
 static struct of_device_id xilinx_of_bus_ids[] __initdata = {
        { .compatible = "simple-bus", },
@@ -26,6 +27,7 @@ static struct of_device_id xilinx_of_bus_ids[] __initdata = {
 static int __init microblaze_device_probe(void)
 {
        of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL);
+       of_platform_reset_gpio_probe();
        return 0;
 }
 device_initcall(microblaze_device_probe);
index f0d14452632b554fa3d85681d075a729b54ebb2f..9cf0a6fad6ba8bc03a11dca5e658fde8ed8f6af4 100755 (executable)
@@ -295,6 +295,9 @@ if ($arch eq "x86_64") {
     $ld .= " -m elf64_sparc";
     $cc .= " -m64";
     $objcopy .= " -O elf64-sparc";
+} elsif ($arch eq "microblaze") {
+    # Microblaze calls '_mcount' instead of plain 'mcount'.
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
 } else {
     die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
 }