aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze
diff options
context:
space:
mode:
Diffstat (limited to 'arch/microblaze')
-rw-r--r--arch/microblaze/Kconfig19
-rw-r--r--arch/microblaze/Kconfig.debug3
-rw-r--r--arch/microblaze/Makefile2
-rw-r--r--arch/microblaze/boot/Makefile15
-rw-r--r--arch/microblaze/include/asm/cache.h16
-rw-r--r--arch/microblaze/include/asm/cacheflush.h123
-rw-r--r--arch/microblaze/include/asm/cpuinfo.h5
-rw-r--r--arch/microblaze/include/asm/device.h12
-rw-r--r--arch/microblaze/include/asm/ftrace.h25
-rw-r--r--arch/microblaze/include/asm/futex.h127
-rw-r--r--arch/microblaze/include/asm/irqflags.h112
-rw-r--r--arch/microblaze/include/asm/page.h3
-rw-r--r--arch/microblaze/include/asm/pgalloc.h9
-rw-r--r--arch/microblaze/include/asm/pvr.h30
-rw-r--r--arch/microblaze/include/asm/setup.h2
-rw-r--r--arch/microblaze/include/asm/system.h2
-rw-r--r--arch/microblaze/include/asm/uaccess.h12
-rw-r--r--arch/microblaze/kernel/Makefile14
-rw-r--r--arch/microblaze/kernel/cpu/Makefile4
-rw-r--r--arch/microblaze/kernel/cpu/cache.c663
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c15
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo-static.c17
-rw-r--r--arch/microblaze/kernel/cpu/cpuinfo.c7
-rw-r--r--arch/microblaze/kernel/cpu/mb.c8
-rw-r--r--arch/microblaze/kernel/cpu/pvr.c2
-rw-r--r--arch/microblaze/kernel/entry-nommu.S2
-rw-r--r--arch/microblaze/kernel/entry.S19
-rw-r--r--arch/microblaze/kernel/ftrace.c237
-rw-r--r--arch/microblaze/kernel/heartbeat.c15
-rw-r--r--arch/microblaze/kernel/intc.c10
-rw-r--r--arch/microblaze/kernel/irq.c4
-rw-r--r--arch/microblaze/kernel/mcount.S170
-rw-r--r--arch/microblaze/kernel/microblaze_ksyms.c5
-rw-r--r--arch/microblaze/kernel/process.c1
-rw-r--r--arch/microblaze/kernel/reset.c140
-rw-r--r--arch/microblaze/kernel/setup.c40
-rw-r--r--arch/microblaze/kernel/signal.c35
-rw-r--r--arch/microblaze/kernel/stacktrace.c65
-rw-r--r--arch/microblaze/kernel/syscall_table.S4
-rw-r--r--arch/microblaze/kernel/timer.c28
-rw-r--r--arch/microblaze/kernel/vmlinux.lds.S6
-rw-r--r--arch/microblaze/lib/uaccess.c7
-rw-r--r--arch/microblaze/mm/init.c1
-rw-r--r--arch/microblaze/mm/pgtable.c10
-rw-r--r--arch/microblaze/oprofile/Makefile13
-rw-r--r--arch/microblaze/oprofile/microblaze_oprofile.c22
-rw-r--r--arch/microblaze/platform/Kconfig.platform21
-rw-r--r--arch/microblaze/platform/generic/Kconfig.auto29
-rw-r--r--arch/microblaze/platform/generic/system.dts38
-rw-r--r--arch/microblaze/platform/platform.c2
50 files changed, 1685 insertions, 486 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index bbd8327f1890..fd53e500be67 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -6,8 +6,15 @@ mainmenu "Linux/Microblaze Kernel Configuration"
6config MICROBLAZE 6config MICROBLAZE
7 def_bool y 7 def_bool y
8 select HAVE_LMB 8 select HAVE_LMB
9 select HAVE_FUNCTION_TRACER
10 select HAVE_FUNCTION_TRACE_MCOUNT_TEST
11 select HAVE_FUNCTION_GRAPH_TRACER
12 select HAVE_DYNAMIC_FTRACE
13 select HAVE_FTRACE_MCOUNT_RECORD
9 select USB_ARCH_HAS_EHCI 14 select USB_ARCH_HAS_EHCI
10 select ARCH_WANT_OPTIONAL_GPIOLIB 15 select ARCH_WANT_OPTIONAL_GPIOLIB
16 select HAVE_OPROFILE
17 select TRACING_SUPPORT
11 18
12config SWAP 19config SWAP
13 def_bool n 20 def_bool n
@@ -57,12 +64,24 @@ config GENERIC_GPIO
57config GENERIC_CSUM 64config GENERIC_CSUM
58 def_bool y 65 def_bool y
59 66
67config STACKTRACE_SUPPORT
68 def_bool y
69
70config LOCKDEP_SUPPORT
71 def_bool y
72
73config HAVE_LATENCYTOP_SUPPORT
74 def_bool y
75
60config PCI 76config PCI
61 def_bool n 77 def_bool n
62 78
63config NO_DMA 79config NO_DMA
64 def_bool y 80 def_bool y
65 81
82config DTC
83 def_bool y
84
66source "init/Kconfig" 85source "init/Kconfig"
67 86
68source "kernel/Kconfig.freezer" 87source "kernel/Kconfig.freezer"
diff --git a/arch/microblaze/Kconfig.debug b/arch/microblaze/Kconfig.debug
index 242cd35bdb4b..9dc708a7f700 100644
--- a/arch/microblaze/Kconfig.debug
+++ b/arch/microblaze/Kconfig.debug
@@ -3,6 +3,9 @@
3 3
4menu "Kernel hacking" 4menu "Kernel hacking"
5 5
6config TRACE_IRQFLAGS_SUPPORT
7 def_bool y
8
6source "lib/Kconfig.debug" 9source "lib/Kconfig.debug"
7 10
8config EARLY_PRINTK 11config EARLY_PRINTK
diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile
index 34187354304a..d2d6cfcb1a30 100644
--- a/arch/microblaze/Makefile
+++ b/arch/microblaze/Makefile
@@ -51,6 +51,8 @@ core-y += arch/microblaze/kernel/
51core-y += arch/microblaze/mm/ 51core-y += arch/microblaze/mm/
52core-y += arch/microblaze/platform/ 52core-y += arch/microblaze/platform/
53 53
54drivers-$(CONFIG_OPROFILE) += arch/microblaze/oprofile/
55
54boot := arch/microblaze/boot 56boot := arch/microblaze/boot
55 57
56# Are we making a simpleImage.<boardname> target? If so, crack out the boardname 58# Are we making a simpleImage.<boardname> target? If so, crack out the boardname
diff --git a/arch/microblaze/boot/Makefile b/arch/microblaze/boot/Makefile
index 21f13322a4ca..902cf9846c3c 100644
--- a/arch/microblaze/boot/Makefile
+++ b/arch/microblaze/boot/Makefile
@@ -2,11 +2,13 @@
2# arch/microblaze/boot/Makefile 2# arch/microblaze/boot/Makefile
3# 3#
4 4
5MKIMAGE := $(srctree)/scripts/mkuboot.sh
6
5obj-y += linked_dtb.o 7obj-y += linked_dtb.o
6 8
7targets := linux.bin linux.bin.gz simpleImage.% 9targets := linux.bin linux.bin.gz simpleImage.%
8 10
9OBJCOPYFLAGS_linux.bin := -O binary 11OBJCOPYFLAGS := -O binary
10 12
11# Where the DTS files live 13# Where the DTS files live
12dtstree := $(srctree)/$(src)/dts 14dtstree := $(srctree)/$(src)/dts
@@ -24,6 +26,7 @@ $(obj)/linux.bin: vmlinux FORCE
24 [ -n $(CONFIG_INITRAMFS_SOURCE) ] && [ ! -e $(CONFIG_INITRAMFS_SOURCE) ] && \ 26 [ -n $(CONFIG_INITRAMFS_SOURCE) ] && [ ! -e $(CONFIG_INITRAMFS_SOURCE) ] && \
25 touch $(CONFIG_INITRAMFS_SOURCE) || echo "No CPIO image" 27 touch $(CONFIG_INITRAMFS_SOURCE) || echo "No CPIO image"
26 $(call if_changed,objcopy) 28 $(call if_changed,objcopy)
29 $(call if_changed,uimage)
27 @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' 30 @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
28 31
29$(obj)/linux.bin.gz: $(obj)/linux.bin FORCE 32$(obj)/linux.bin.gz: $(obj)/linux.bin FORCE
@@ -36,8 +39,16 @@ quiet_cmd_cp = CP $< $@$2
36quiet_cmd_strip = STRIP $@ 39quiet_cmd_strip = STRIP $@
37 cmd_strip = $(STRIP) -K _start -K _end -K __log_buf -K _fdt_start vmlinux -o $@ 40 cmd_strip = $(STRIP) -K _start -K _end -K __log_buf -K _fdt_start vmlinux -o $@
38 41
42quiet_cmd_uimage = UIMAGE $@.ub
43 cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A microblaze -O linux -T kernel \
44 -C none -n 'Linux-$(KERNELRELEASE)' \
45 -a $(CONFIG_KERNEL_BASE_ADDR) -e $(CONFIG_KERNEL_BASE_ADDR) \
46 -d $@ $@.ub
47
39$(obj)/simpleImage.%: vmlinux FORCE 48$(obj)/simpleImage.%: vmlinux FORCE
40 $(call if_changed,cp,.unstrip) 49 $(call if_changed,cp,.unstrip)
50 $(call if_changed,objcopy)
51 $(call if_changed,uimage)
41 $(call if_changed,strip) 52 $(call if_changed,strip)
42 @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' 53 @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
43 54
@@ -53,4 +64,4 @@ $(obj)/%.dtb: $(dtstree)/%.dts FORCE
53 64
54clean-kernel += linux.bin linux.bin.gz simpleImage.* 65clean-kernel += linux.bin linux.bin.gz simpleImage.*
55 66
56clean-files += *.dtb 67clean-files += *.dtb simpleImage.*.unstrip
diff --git a/arch/microblaze/include/asm/cache.h b/arch/microblaze/include/asm/cache.h
index c209c47509d5..e52210891d78 100644
--- a/arch/microblaze/include/asm/cache.h
+++ b/arch/microblaze/include/asm/cache.h
@@ -21,20 +21,4 @@
21 21
22#define SMP_CACHE_BYTES L1_CACHE_BYTES 22#define SMP_CACHE_BYTES L1_CACHE_BYTES
23 23
24void _enable_icache(void);
25void _disable_icache(void);
26void _invalidate_icache(unsigned int addr);
27
28#define __enable_icache() _enable_icache()
29#define __disable_icache() _disable_icache()
30#define __invalidate_icache(addr) _invalidate_icache(addr)
31
32void _enable_dcache(void);
33void _disable_dcache(void);
34void _invalidate_dcache(unsigned int addr);
35
36#define __enable_dcache() _enable_dcache()
37#define __disable_dcache() _disable_dcache()
38#define __invalidate_dcache(addr) _invalidate_dcache(addr)
39
40#endif /* _ASM_MICROBLAZE_CACHE_H */ 24#endif /* _ASM_MICROBLAZE_CACHE_H */
diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h
index 088076e657b3..a6edd356cd08 100644
--- a/arch/microblaze/include/asm/cacheflush.h
+++ b/arch/microblaze/include/asm/cacheflush.h
@@ -18,6 +18,8 @@
18/* Somebody depends on this; sigh... */ 18/* Somebody depends on this; sigh... */
19#include <linux/mm.h> 19#include <linux/mm.h>
20 20
21/* Look at Documentation/cachetlb.txt */
22
21/* 23/*
22 * Cache handling functions. 24 * Cache handling functions.
23 * Microblaze has a write-through data cache, meaning that the data cache 25 * Microblaze has a write-through data cache, meaning that the data cache
@@ -27,78 +29,81 @@
27 * instruction cache to make sure we don't fetch old, bad code. 29 * instruction cache to make sure we don't fetch old, bad code.
28 */ 30 */
29 31
32/* struct cache, d=dcache, i=icache, fl = flush, iv = invalidate,
33 * suffix r = range */
34struct scache {
35 /* icache */
36 void (*ie)(void); /* enable */
37 void (*id)(void); /* disable */
38 void (*ifl)(void); /* flush */
39 void (*iflr)(unsigned long a, unsigned long b);
40 void (*iin)(void); /* invalidate */
41 void (*iinr)(unsigned long a, unsigned long b);
42 /* dcache */
43 void (*de)(void); /* enable */
44 void (*dd)(void); /* disable */
45 void (*dfl)(void); /* flush */
46 void (*dflr)(unsigned long a, unsigned long b);
47 void (*din)(void); /* invalidate */
48 void (*dinr)(unsigned long a, unsigned long b);
49};
50
51/* microblaze cache */
52extern struct scache *mbc;
53
54void microblaze_cache_init(void);
55
56#define enable_icache() mbc->ie();
57#define disable_icache() mbc->id();
58#define flush_icache() mbc->ifl();
59#define flush_icache_range(start, end) mbc->iflr(start, end);
60#define invalidate_icache() mbc->iin();
61#define invalidate_icache_range(start, end) mbc->iinr(start, end);
62
63
64#define flush_icache_user_range(vma, pg, adr, len) flush_icache();
65#define flush_icache_page(vma, pg) do { } while (0)
66
67#define enable_dcache() mbc->de();
68#define disable_dcache() mbc->dd();
30/* FIXME for LL-temac driver */ 69/* FIXME for LL-temac driver */
31#define invalidate_dcache_range(start, end) \ 70#define invalidate_dcache() mbc->din();
32 __invalidate_dcache_range(start, end) 71#define invalidate_dcache_range(start, end) mbc->dinr(start, end);
33 72#define flush_dcache() mbc->dfl();
34#define flush_cache_all() __invalidate_cache_all() 73#define flush_dcache_range(start, end) mbc->dflr(start, end);
35#define flush_cache_mm(mm) do { } while (0)
36#define flush_cache_range(vma, start, end) __invalidate_cache_all()
37#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
38 74
39#define flush_dcache_range(start, end) __invalidate_dcache_range(start, end)
40#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 75#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
76/* D-cache aliasing problem can't happen - cache is between MMU and ram */
41#define flush_dcache_page(page) do { } while (0) 77#define flush_dcache_page(page) do { } while (0)
42#define flush_dcache_mmap_lock(mapping) do { } while (0) 78#define flush_dcache_mmap_lock(mapping) do { } while (0)
43#define flush_dcache_mmap_unlock(mapping) do { } while (0) 79#define flush_dcache_mmap_unlock(mapping) do { } while (0)
44 80
45#define flush_icache_range(start, len) __invalidate_icache_range(start, len)
46#define flush_icache_page(vma, pg) do { } while (0)
47
48#ifndef CONFIG_MMU
49# define flush_icache_user_range(start, len) do { } while (0)
50#else
51# define flush_icache_user_range(vma, pg, adr, len) __invalidate_icache_all()
52
53# define flush_page_to_ram(page) do { } while (0)
54 81
55# define flush_icache() __invalidate_icache_all() 82#define flush_cache_dup_mm(mm) do { } while (0)
56# define flush_cache_sigtramp(vaddr) \ 83#define flush_cache_vmap(start, end) do { } while (0)
57 __invalidate_icache_range(vaddr, vaddr + 8) 84#define flush_cache_vunmap(start, end) do { } while (0)
58 85#define flush_cache_mm(mm) do { } while (0)
59# define flush_dcache_mmap_lock(mapping) do { } while (0) 86#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
60# define flush_dcache_mmap_unlock(mapping) do { } while (0)
61 87
62# define flush_cache_dup_mm(mm) do { } while (0) 88/* MS: kgdb code use this macro, wrong len with FLASH */
89#if 0
90#define flush_cache_range(vma, start, len) { \
91 flush_icache_range((unsigned) (start), (unsigned) (start) + (len)); \
92 flush_dcache_range((unsigned) (start), (unsigned) (start) + (len)); \
93}
63#endif 94#endif
64 95
65#define flush_cache_vmap(start, end) do { } while (0) 96#define flush_cache_range(vma, start, len) do { } while (0)
66#define flush_cache_vunmap(start, end) do { } while (0)
67
68struct page;
69struct mm_struct;
70struct vm_area_struct;
71
72/* see arch/microblaze/kernel/cache.c */
73extern void __invalidate_icache_all(void);
74extern void __invalidate_icache_range(unsigned long start, unsigned long end);
75extern void __invalidate_icache_page(struct vm_area_struct *vma,
76 struct page *page);
77extern void __invalidate_icache_user_range(struct vm_area_struct *vma,
78 struct page *page,
79 unsigned long adr, int len);
80extern void __invalidate_cache_sigtramp(unsigned long addr);
81
82extern void __invalidate_dcache_all(void);
83extern void __invalidate_dcache_range(unsigned long start, unsigned long end);
84extern void __invalidate_dcache_page(struct vm_area_struct *vma,
85 struct page *page);
86extern void __invalidate_dcache_user_range(struct vm_area_struct *vma,
87 struct page *page,
88 unsigned long adr, int len);
89
90extern inline void __invalidate_cache_all(void)
91{
92 __invalidate_icache_all();
93 __invalidate_dcache_all();
94}
95 97
96#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ 98#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
97do { memcpy((dst), (src), (len)); \ 99do { \
98 flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ 100 memcpy((dst), (src), (len)); \
101 flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \
99} while (0) 102} while (0)
100 103
101#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ 104#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
102 memcpy((dst), (src), (len)) 105do { \
106 memcpy((dst), (src), (len)); \
107} while (0)
103 108
104#endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */ 109#endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */
diff --git a/arch/microblaze/include/asm/cpuinfo.h b/arch/microblaze/include/asm/cpuinfo.h
index 52f28f6dc4eb..b4f5ca33aebf 100644
--- a/arch/microblaze/include/asm/cpuinfo.h
+++ b/arch/microblaze/include/asm/cpuinfo.h
@@ -43,7 +43,7 @@ struct cpuinfo {
43 u32 use_icache; 43 u32 use_icache;
44 u32 icache_tagbits; 44 u32 icache_tagbits;
45 u32 icache_write; 45 u32 icache_write;
46 u32 icache_line; 46 u32 icache_line_length;
47 u32 icache_size; 47 u32 icache_size;
48 unsigned long icache_base; 48 unsigned long icache_base;
49 unsigned long icache_high; 49 unsigned long icache_high;
@@ -51,8 +51,9 @@ struct cpuinfo {
51 u32 use_dcache; 51 u32 use_dcache;
52 u32 dcache_tagbits; 52 u32 dcache_tagbits;
53 u32 dcache_write; 53 u32 dcache_write;
54 u32 dcache_line; 54 u32 dcache_line_length;
55 u32 dcache_size; 55 u32 dcache_size;
56 u32 dcache_wb;
56 unsigned long dcache_base; 57 unsigned long dcache_base;
57 unsigned long dcache_high; 58 unsigned long dcache_high;
58 59
diff --git a/arch/microblaze/include/asm/device.h b/arch/microblaze/include/asm/device.h
index 30286db27c1c..78a038452c0f 100644
--- a/arch/microblaze/include/asm/device.h
+++ b/arch/microblaze/include/asm/device.h
@@ -19,6 +19,18 @@ struct dev_archdata {
19struct pdev_archdata { 19struct pdev_archdata {
20}; 20};
21 21
22static inline void dev_archdata_set_node(struct dev_archdata *ad,
23 struct device_node *np)
24{
25 ad->of_node = np;
26}
27
28static inline struct device_node *
29dev_archdata_get_node(const struct dev_archdata *ad)
30{
31 return ad->of_node;
32}
33
22#endif /* _ASM_MICROBLAZE_DEVICE_H */ 34#endif /* _ASM_MICROBLAZE_DEVICE_H */
23 35
24 36
diff --git a/arch/microblaze/include/asm/ftrace.h b/arch/microblaze/include/asm/ftrace.h
index 8b137891791f..fd2fa2eca62f 100644
--- a/arch/microblaze/include/asm/ftrace.h
+++ b/arch/microblaze/include/asm/ftrace.h
@@ -1 +1,26 @@
1#ifndef _ASM_MICROBLAZE_FTRACE
2#define _ASM_MICROBLAZE_FTRACE
1 3
4#ifdef CONFIG_FUNCTION_TRACER
5
6#define MCOUNT_ADDR ((long)(_mcount))
7#define MCOUNT_INSN_SIZE 8 /* sizeof mcount call */
8
9#ifndef __ASSEMBLY__
10extern void _mcount(void);
11extern void ftrace_call_graph(void);
12#endif
13
14#ifdef CONFIG_DYNAMIC_FTRACE
15/* reloction of mcount call site is the same as the address */
16static inline unsigned long ftrace_call_adjust(unsigned long addr)
17{
18 return addr;
19}
20
21struct dyn_arch_ftrace {
22};
23#endif /* CONFIG_DYNAMIC_FTRACE */
24
25#endif /* CONFIG_FUNCTION_TRACER */
26#endif /* _ASM_MICROBLAZE_FTRACE */
diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h
index 0b745828f42b..8dbb6e7a03a2 100644
--- a/arch/microblaze/include/asm/futex.h
+++ b/arch/microblaze/include/asm/futex.h
@@ -1 +1,126 @@
1#include <asm-generic/futex.h> 1#ifndef _ASM_MICROBLAZE_FUTEX_H
2#define _ASM_MICROBLAZE_FUTEX_H
3
4#ifdef __KERNEL__
5
6#include <linux/futex.h>
7#include <linux/uaccess.h>
8#include <asm/errno.h>
9
10#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
11({ \
12 __asm__ __volatile__ ( \
13 "1: lwx %0, %2, r0; " \
14 insn \
15 "2: swx %1, %2, r0; \
16 addic %1, r0, 0; \
17 bnei %1, 1b; \
18 3: \
19 .section .fixup,\"ax\"; \
20 4: brid 3b; \
21 addik %1, r0, %3; \
22 .previous; \
23 .section __ex_table,\"a\"; \
24 .word 1b,4b,2b,4b; \
25 .previous;" \
26 : "=&r" (oldval), "=&r" (ret) \
27 : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
28 ); \
29})
30
31static inline int
32futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
33{
34 int op = (encoded_op >> 28) & 7;
35 int cmp = (encoded_op >> 24) & 15;
36 int oparg = (encoded_op << 8) >> 20;
37 int cmparg = (encoded_op << 20) >> 20;
38 int oldval = 0, ret;
39 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
40 oparg = 1 << oparg;
41
42 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
43 return -EFAULT;
44
45 pagefault_disable();
46
47 switch (op) {
48 case FUTEX_OP_SET:
49 __futex_atomic_op("or %1,%4,%4;", ret, oldval, uaddr, oparg);
50 break;
51 case FUTEX_OP_ADD:
52 __futex_atomic_op("add %1,%0,%4;", ret, oldval, uaddr, oparg);
53 break;
54 case FUTEX_OP_OR:
55 __futex_atomic_op("or %1,%0,%4;", ret, oldval, uaddr, oparg);
56 break;
57 case FUTEX_OP_ANDN:
58 __futex_atomic_op("and %1,%0,%4;", ret, oldval, uaddr, oparg);
59 break;
60 case FUTEX_OP_XOR:
61 __futex_atomic_op("xor %1,%0,%4;", ret, oldval, uaddr, oparg);
62 break;
63 default:
64 ret = -ENOSYS;
65 }
66
67 pagefault_enable();
68
69 if (!ret) {
70 switch (cmp) {
71 case FUTEX_OP_CMP_EQ:
72 ret = (oldval == cmparg);
73 break;
74 case FUTEX_OP_CMP_NE:
75 ret = (oldval != cmparg);
76 break;
77 case FUTEX_OP_CMP_LT:
78 ret = (oldval < cmparg);
79 break;
80 case FUTEX_OP_CMP_GE:
81 ret = (oldval >= cmparg);
82 break;
83 case FUTEX_OP_CMP_LE:
84 ret = (oldval <= cmparg);
85 break;
86 case FUTEX_OP_CMP_GT:
87 ret = (oldval > cmparg);
88 break;
89 default:
90 ret = -ENOSYS;
91 }
92 }
93 return ret;
94}
95
96static inline int
97futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
98{
99 int prev, cmp;
100
101 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
102 return -EFAULT;
103
104 __asm__ __volatile__ ("1: lwx %0, %2, r0; \
105 cmp %1, %0, %3; \
106 beqi %1, 3f; \
107 2: swx %4, %2, r0; \
108 addic %1, r0, 0; \
109 bnei %1, 1b; \
110 3: \
111 .section .fixup,\"ax\"; \
112 4: brid 3b; \
113 addik %0, r0, %5; \
114 .previous; \
115 .section __ex_table,\"a\"; \
116 .word 1b,4b,2b,4b; \
117 .previous;" \
118 : "=&r" (prev), "=&r"(cmp) \
119 : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
120
121 return prev;
122}
123
124#endif /* __KERNEL__ */
125
126#endif
diff --git a/arch/microblaze/include/asm/irqflags.h b/arch/microblaze/include/asm/irqflags.h
index dea65645a4f8..2c38c6d80176 100644
--- a/arch/microblaze/include/asm/irqflags.h
+++ b/arch/microblaze/include/asm/irqflags.h
@@ -10,78 +10,73 @@
10#define _ASM_MICROBLAZE_IRQFLAGS_H 10#define _ASM_MICROBLAZE_IRQFLAGS_H
11 11
12#include <linux/irqflags.h> 12#include <linux/irqflags.h>
13#include <asm/registers.h>
13 14
14# if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 15# if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
15 16
16# define local_irq_save(flags) \ 17# define raw_local_irq_save(flags) \
17 do { \ 18 do { \
18 asm volatile ("# local_irq_save \n\t" \ 19 asm volatile (" msrclr %0, %1; \
19 "msrclr %0, %1 \n\t" \ 20 nop;" \
20 "nop \n\t" \
21 : "=r"(flags) \ 21 : "=r"(flags) \
22 : "i"(MSR_IE) \ 22 : "i"(MSR_IE) \
23 : "memory"); \ 23 : "memory"); \
24 } while (0) 24 } while (0)
25 25
26# define local_irq_disable() \ 26# define raw_local_irq_disable() \
27 do { \ 27 do { \
28 asm volatile ("# local_irq_disable \n\t" \ 28 asm volatile (" msrclr r0, %0; \
29 "msrclr r0, %0 \n\t" \ 29 nop;" \
30 "nop \n\t" \ 30 : \
31 : \ 31 : "i"(MSR_IE) \
32 : "i"(MSR_IE) \ 32 : "memory"); \
33 : "memory"); \
34 } while (0) 33 } while (0)
35 34
36# define local_irq_enable() \ 35# define raw_local_irq_enable() \
37 do { \ 36 do { \
38 asm volatile ("# local_irq_enable \n\t" \ 37 asm volatile (" msrset r0, %0; \
39 "msrset r0, %0 \n\t" \ 38 nop;" \
40 "nop \n\t" \ 39 : \
41 : \ 40 : "i"(MSR_IE) \
42 : "i"(MSR_IE) \ 41 : "memory"); \
43 : "memory"); \
44 } while (0) 42 } while (0)
45 43
46# else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */ 44# else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */
47 45
48# define local_irq_save(flags) \ 46# define raw_local_irq_save(flags) \
49 do { \ 47 do { \
50 register unsigned tmp; \ 48 register unsigned tmp; \
51 asm volatile ("# local_irq_save \n\t" \ 49 asm volatile (" mfs %0, rmsr; \
52 "mfs %0, rmsr \n\t" \ 50 nop; \
53 "nop \n\t" \ 51 andi %1, %0, %2; \
54 "andi %1, %0, %2 \n\t" \ 52 mts rmsr, %1; \
55 "mts rmsr, %1 \n\t" \ 53 nop;" \
56 "nop \n\t" \
57 : "=r"(flags), "=r" (tmp) \ 54 : "=r"(flags), "=r" (tmp) \
58 : "i"(~MSR_IE) \ 55 : "i"(~MSR_IE) \
59 : "memory"); \ 56 : "memory"); \
60 } while (0) 57 } while (0)
61 58
62# define local_irq_disable() \ 59# define raw_local_irq_disable() \
63 do { \ 60 do { \
64 register unsigned tmp; \ 61 register unsigned tmp; \
65 asm volatile ("# local_irq_disable \n\t" \ 62 asm volatile (" mfs %0, rmsr; \
66 "mfs %0, rmsr \n\t" \ 63 nop; \
67 "nop \n\t" \ 64 andi %0, %0, %1; \
68 "andi %0, %0, %1 \n\t" \ 65 mts rmsr, %0; \
69 "mts rmsr, %0 \n\t" \ 66 nop;" \
70 "nop \n\t" \
71 : "=r"(tmp) \ 67 : "=r"(tmp) \
72 : "i"(~MSR_IE) \ 68 : "i"(~MSR_IE) \
73 : "memory"); \ 69 : "memory"); \
74 } while (0) 70 } while (0)
75 71
76# define local_irq_enable() \ 72# define raw_local_irq_enable() \
77 do { \ 73 do { \
78 register unsigned tmp; \ 74 register unsigned tmp; \
79 asm volatile ("# local_irq_enable \n\t" \ 75 asm volatile (" mfs %0, rmsr; \
80 "mfs %0, rmsr \n\t" \ 76 nop; \
81 "nop \n\t" \ 77 ori %0, %0, %1; \
82 "ori %0, %0, %1 \n\t" \ 78 mts rmsr, %0; \
83 "mts rmsr, %0 \n\t" \ 79 nop;" \
84 "nop \n\t" \
85 : "=r"(tmp) \ 80 : "=r"(tmp) \
86 : "i"(MSR_IE) \ 81 : "i"(MSR_IE) \
87 : "memory"); \ 82 : "memory"); \
@@ -89,35 +84,28 @@
89 84
90# endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */ 85# endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
91 86
92#define local_save_flags(flags) \ 87#define raw_local_irq_restore(flags) \
93 do { \ 88 do { \
94 asm volatile ("# local_save_flags \n\t" \ 89 asm volatile (" mts rmsr, %0; \
95 "mfs %0, rmsr \n\t" \ 90 nop;" \
96 "nop \n\t" \
97 : "=r"(flags) \
98 : \ 91 : \
92 : "r"(flags) \
99 : "memory"); \ 93 : "memory"); \
100 } while (0) 94 } while (0)
101 95
102#define local_irq_restore(flags) \ 96static inline unsigned long get_msr(void)
103 do { \
104 asm volatile ("# local_irq_restore \n\t"\
105 "mts rmsr, %0 \n\t" \
106 "nop \n\t" \
107 : \
108 : "r"(flags) \
109 : "memory"); \
110 } while (0)
111
112static inline int irqs_disabled(void)
113{ 97{
114 unsigned long flags; 98 unsigned long flags;
115 99 asm volatile (" mfs %0, rmsr; \
116 local_save_flags(flags); 100 nop;" \
117 return ((flags & MSR_IE) == 0); 101 : "=r"(flags) \
102 : \
103 : "memory"); \
104 return flags;
118} 105}
119 106
120#define raw_irqs_disabled irqs_disabled 107#define raw_local_save_flags(flags) ((flags) = get_msr())
121#define raw_irqs_disabled_flags(flags) ((flags) == 0) 108#define raw_irqs_disabled() ((get_msr() & MSR_IE) == 0)
109#define raw_irqs_disabled_flags(flags) ((flags & MSR_IE) == 0)
122 110
123#endif /* _ASM_MICROBLAZE_IRQFLAGS_H */ 111#endif /* _ASM_MICROBLAZE_IRQFLAGS_H */
diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h
index 880c988c2237..9b66c0fa9a32 100644
--- a/arch/microblaze/include/asm/page.h
+++ b/arch/microblaze/include/asm/page.h
@@ -164,7 +164,8 @@ extern int page_is_ram(unsigned long pfn);
164# endif /* CONFIG_MMU */ 164# endif /* CONFIG_MMU */
165 165
166# ifndef CONFIG_MMU 166# ifndef CONFIG_MMU
167# define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) <= max_mapnr) 167# define pfn_valid(pfn) (((pfn) >= min_low_pfn) && \
168 ((pfn) <= (min_low_pfn + max_mapnr)))
168# define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) 169# define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
169# else /* CONFIG_MMU */ 170# else /* CONFIG_MMU */
170# define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT) 171# define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT)
diff --git a/arch/microblaze/include/asm/pgalloc.h b/arch/microblaze/include/asm/pgalloc.h
index b0131da1387b..7547f5064560 100644
--- a/arch/microblaze/include/asm/pgalloc.h
+++ b/arch/microblaze/include/asm/pgalloc.h
@@ -106,9 +106,6 @@ extern inline void free_pgd_slow(pgd_t *pgd)
106 */ 106 */
107#define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); }) 107#define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); })
108#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) 108#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); })
109/* FIXME two definition - look below */
110#define pmd_free(mm, x) do { } while (0)
111#define pgd_populate(mm, pmd, pte) BUG()
112 109
113static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, 110static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
114 unsigned long address) 111 unsigned long address)
@@ -192,14 +189,14 @@ extern inline void pte_free(struct mm_struct *mm, struct page *ptepage)
192 * the pgd will always be present.. 189 * the pgd will always be present..
193 */ 190 */
194#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) 191#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); })
195/*#define pmd_free(mm, x) do { } while (0)*/ 192#define pmd_free(mm, x) do { } while (0)
196#define __pmd_free_tlb(tlb, x, addr) do { } while (0) 193#define __pmd_free_tlb(tlb, x, addr) pmd_free((tlb)->mm, x)
197#define pgd_populate(mm, pmd, pte) BUG() 194#define pgd_populate(mm, pmd, pte) BUG()
198 195
199extern int do_check_pgt_cache(int, int); 196extern int do_check_pgt_cache(int, int);
200 197
201#endif /* CONFIG_MMU */ 198#endif /* CONFIG_MMU */
202 199
203#define check_pgt_cache() do {} while (0) 200#define check_pgt_cache() do { } while (0)
204 201
205#endif /* _ASM_MICROBLAZE_PGALLOC_H */ 202#endif /* _ASM_MICROBLAZE_PGALLOC_H */
diff --git a/arch/microblaze/include/asm/pvr.h b/arch/microblaze/include/asm/pvr.h
index 66f1b30dd097..e38abc7714b6 100644
--- a/arch/microblaze/include/asm/pvr.h
+++ b/arch/microblaze/include/asm/pvr.h
@@ -76,20 +76,23 @@ struct pvr_s {
76#define PVR3_FSL_LINKS_MASK 0x00000380 76#define PVR3_FSL_LINKS_MASK 0x00000380
77 77
78/* ICache config PVR masks */ 78/* ICache config PVR masks */
79#define PVR4_USE_ICACHE_MASK 0x80000000 79#define PVR4_USE_ICACHE_MASK 0x80000000 /* ICU */
80#define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000 80#define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000 /* ICTS */
81#define PVR4_ICACHE_USE_FSL_MASK 0x02000000 81#define PVR4_ICACHE_ALLOW_WR_MASK 0x01000000 /* ICW */
82#define PVR4_ICACHE_ALLOW_WR_MASK 0x01000000 82#define PVR4_ICACHE_LINE_LEN_MASK 0x00E00000 /* ICLL */
83#define PVR4_ICACHE_LINE_LEN_MASK 0x00E00000 83#define PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000 /* ICBS */
84#define PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000 84#define PVR4_ICACHE_ALWAYS_USED 0x00008000 /* IAU */
85#define PVR4_ICACHE_INTERFACE 0x00002000 /* ICI */
85 86
86/* DCache config PVR masks */ 87/* DCache config PVR masks */
87#define PVR5_USE_DCACHE_MASK 0x80000000 88#define PVR5_USE_DCACHE_MASK 0x80000000 /* DCU */
88#define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000 89#define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000 /* DCTS */
89#define PVR5_DCACHE_USE_FSL_MASK 0x02000000 90#define PVR5_DCACHE_ALLOW_WR_MASK 0x01000000 /* DCW */
90#define PVR5_DCACHE_ALLOW_WR_MASK 0x01000000 91#define PVR5_DCACHE_LINE_LEN_MASK 0x00E00000 /* DCLL */
91#define PVR5_DCACHE_LINE_LEN_MASK 0x00E00000 92#define PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000 /* DCBS */
92#define PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000 93#define PVR5_DCACHE_ALWAYS_USED 0x00008000 /* DAU */
94#define PVR5_DCACHE_USE_WRITEBACK 0x00004000 /* DWB */
95#define PVR5_DCACHE_INTERFACE 0x00002000 /* DCI */
93 96
94/* ICache base address PVR mask */ 97/* ICache base address PVR mask */
95#define PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFF 98#define PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFF
@@ -178,11 +181,14 @@ struct pvr_s {
178 ((pvr.pvr[5] & PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26) 181 ((pvr.pvr[5] & PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26)
179#define PVR_DCACHE_USE_FSL(pvr) (pvr.pvr[5] & PVR5_DCACHE_USE_FSL_MASK) 182#define PVR_DCACHE_USE_FSL(pvr) (pvr.pvr[5] & PVR5_DCACHE_USE_FSL_MASK)
180#define PVR_DCACHE_ALLOW_WR(pvr) (pvr.pvr[5] & PVR5_DCACHE_ALLOW_WR_MASK) 183#define PVR_DCACHE_ALLOW_WR(pvr) (pvr.pvr[5] & PVR5_DCACHE_ALLOW_WR_MASK)
184/* FIXME two shifts on one line needs any comment */
181#define PVR_DCACHE_LINE_LEN(pvr) \ 185#define PVR_DCACHE_LINE_LEN(pvr) \
182 (1 << ((pvr.pvr[5] & PVR5_DCACHE_LINE_LEN_MASK) >> 21)) 186 (1 << ((pvr.pvr[5] & PVR5_DCACHE_LINE_LEN_MASK) >> 21))
183#define PVR_DCACHE_BYTE_SIZE(pvr) \ 187#define PVR_DCACHE_BYTE_SIZE(pvr) \
184 (1 << ((pvr.pvr[5] & PVR5_DCACHE_BYTE_SIZE_MASK) >> 16)) 188 (1 << ((pvr.pvr[5] & PVR5_DCACHE_BYTE_SIZE_MASK) >> 16))
185 189
190#define PVR_DCACHE_USE_WRITEBACK(pvr) \
191 ((pvr.pvr[5] & PVR5_DCACHE_USE_WRITEBACK) >> 14)
186 192
187#define PVR_ICACHE_BASEADDR(pvr) (pvr.pvr[6] & PVR6_ICACHE_BASEADDR_MASK) 193#define PVR_ICACHE_BASEADDR(pvr) (pvr.pvr[6] & PVR6_ICACHE_BASEADDR_MASK)
188#define PVR_ICACHE_HIGHADDR(pvr) (pvr.pvr[7] & PVR7_ICACHE_HIGHADDR_MASK) 194#define PVR_ICACHE_HIGHADDR(pvr) (pvr.pvr[7] & PVR7_ICACHE_HIGHADDR_MASK)
diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h
index ed67c9ed15b8..7f31394985e0 100644
--- a/arch/microblaze/include/asm/setup.h
+++ b/arch/microblaze/include/asm/setup.h
@@ -35,6 +35,8 @@ extern void mmu_reset(void);
35extern void early_console_reg_tlb_alloc(unsigned int addr); 35extern void early_console_reg_tlb_alloc(unsigned int addr);
36# endif /* CONFIG_MMU */ 36# endif /* CONFIG_MMU */
37 37
38extern void of_platform_reset_gpio_probe(void);
39
38void time_init(void); 40void time_init(void);
39void init_IRQ(void); 41void init_IRQ(void);
40void machine_early_init(const char *cmdline, unsigned int ram, 42void machine_early_init(const char *cmdline, unsigned int ram,
diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h
index b1ed61590660..157970688b2a 100644
--- a/arch/microblaze/include/asm/system.h
+++ b/arch/microblaze/include/asm/system.h
@@ -16,6 +16,8 @@
16#include <asm-generic/cmpxchg.h> 16#include <asm-generic/cmpxchg.h>
17#include <asm-generic/cmpxchg-local.h> 17#include <asm-generic/cmpxchg-local.h>
18 18
19#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
20
19struct task_struct; 21struct task_struct;
20struct thread_info; 22struct thread_info;
21 23
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
index 5431b4631a7a..371bd6e56d9a 100644
--- a/arch/microblaze/include/asm/uaccess.h
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -272,8 +272,9 @@ static inline int clear_user(char *to, int size)
272 return size; 272 return size;
273} 273}
274 274
275extern unsigned long __copy_tofrom_user(void __user *to, 275#define __copy_from_user(to, from, n) copy_from_user((to), (from), (n))
276 const void __user *from, unsigned long size); 276#define __copy_from_user_inatomic(to, from, n) \
277 copy_from_user((to), (from), (n))
277 278
278#define copy_to_user(to, from, n) \ 279#define copy_to_user(to, from, n) \
279 (access_ok(VERIFY_WRITE, (to), (n)) ? \ 280 (access_ok(VERIFY_WRITE, (to), (n)) ? \
@@ -290,10 +291,6 @@ extern unsigned long __copy_tofrom_user(void __user *to,
290 (void __user *)(from), (n)) \ 291 (void __user *)(from), (n)) \
291 : -EFAULT) 292 : -EFAULT)
292 293
293#define __copy_from_user(to, from, n) copy_from_user((to), (from), (n))
294#define __copy_from_user_inatomic(to, from, n) \
295 copy_from_user((to), (from), (n))
296
297extern int __strncpy_user(char *to, const char __user *from, int len); 294extern int __strncpy_user(char *to, const char __user *from, int len);
298extern int __strnlen_user(const char __user *sstr, int len); 295extern int __strnlen_user(const char __user *sstr, int len);
299 296
@@ -305,6 +302,9 @@ extern int __strnlen_user(const char __user *sstr, int len);
305 302
306#endif /* CONFIG_MMU */ 303#endif /* CONFIG_MMU */
307 304
305extern unsigned long __copy_tofrom_user(void __user *to,
306 const void __user *from, unsigned long size);
307
308/* 308/*
309 * The exception table consists of pairs of addresses: the first is the 309 * The exception table consists of pairs of addresses: the first is the
310 * address of an instruction that is allowed to fault, and the second is 310 * address of an instruction that is allowed to fault, and the second is
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile
index d487729683de..b07594eccf9b 100644
--- a/arch/microblaze/kernel/Makefile
+++ b/arch/microblaze/kernel/Makefile
@@ -2,12 +2,22 @@
2# Makefile 2# Makefile
3# 3#
4 4
5ifdef CONFIG_FUNCTION_TRACER
6# Do not trace early boot code and low level code
7CFLAGS_REMOVE_timer.o = -pg
8CFLAGS_REMOVE_intc.o = -pg
9CFLAGS_REMOVE_early_printk.o = -pg
10CFLAGS_REMOVE_selfmod.o = -pg
11CFLAGS_REMOVE_heartbeat.o = -pg
12CFLAGS_REMOVE_ftrace.o = -pg
13endif
14
5extra-y := head.o vmlinux.lds 15extra-y := head.o vmlinux.lds
6 16
7obj-y += exceptions.o \ 17obj-y += exceptions.o \
8 hw_exception_handler.o init_task.o intc.o irq.o of_device.o \ 18 hw_exception_handler.o init_task.o intc.o irq.o of_device.o \
9 of_platform.o process.o prom.o prom_parse.o ptrace.o \ 19 of_platform.o process.o prom.o prom_parse.o ptrace.o \
10 setup.o signal.o sys_microblaze.o timer.o traps.o 20 setup.o signal.o sys_microblaze.o timer.o traps.o reset.o
11 21
12obj-y += cpu/ 22obj-y += cpu/
13 23
@@ -16,5 +26,7 @@ obj-$(CONFIG_SELFMOD) += selfmod.o
16obj-$(CONFIG_HEART_BEAT) += heartbeat.o 26obj-$(CONFIG_HEART_BEAT) += heartbeat.o
17obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o 27obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o
18obj-$(CONFIG_MMU) += misc.o 28obj-$(CONFIG_MMU) += misc.o
29obj-$(CONFIG_STACKTRACE) += stacktrace.o
30obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount.o
19 31
20obj-y += entry$(MMU).o 32obj-y += entry$(MMU).o
diff --git a/arch/microblaze/kernel/cpu/Makefile b/arch/microblaze/kernel/cpu/Makefile
index 20646e549271..59cc7bceaf8c 100644
--- a/arch/microblaze/kernel/cpu/Makefile
+++ b/arch/microblaze/kernel/cpu/Makefile
@@ -2,6 +2,10 @@
2# Build the appropriate CPU version support 2# Build the appropriate CPU version support
3# 3#
4 4
5ifdef CONFIG_FUNCTION_TRACER
6CFLAGS_REMOVE_cache.o = -pg
7endif
8
5EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \ 9EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
6 -DCPU_REV=$(CPU_REV) 10 -DCPU_REV=$(CPU_REV)
7 11
diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c
index af866a450125..d9d63831cc2f 100644
--- a/arch/microblaze/kernel/cpu/cache.c
+++ b/arch/microblaze/kernel/cpu/cache.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> 4 * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
5 * Copyright (C) 2007-2009 PetaLogix 5 * Copyright (C) 2007-2009 PetaLogix
6 * Copyright (C) 2007 John Williams <john.williams@petalogix.com> 6 * Copyright (C) 2007-2009 John Williams <john.williams@petalogix.com>
7 * 7 *
8 * This file is subject to the terms and conditions of the GNU General 8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this 9 * Public License. See the file COPYING in the main directory of this
@@ -13,243 +13,534 @@
13#include <asm/cacheflush.h> 13#include <asm/cacheflush.h>
14#include <linux/cache.h> 14#include <linux/cache.h>
15#include <asm/cpuinfo.h> 15#include <asm/cpuinfo.h>
16#include <asm/pvr.h>
16 17
17/* Exported functions */ 18static inline void __invalidate_flush_icache(unsigned int addr)
19{
20 __asm__ __volatile__ ("wic %0, r0;" \
21 : : "r" (addr));
22}
23
24static inline void __flush_dcache(unsigned int addr)
25{
26 __asm__ __volatile__ ("wdc.flush %0, r0;" \
27 : : "r" (addr));
28}
29
30static inline void __invalidate_dcache(unsigned int baseaddr,
31 unsigned int offset)
32{
33 __asm__ __volatile__ ("wdc.clear %0, %1;" \
34 : : "r" (baseaddr), "r" (offset));
35}
18 36
19void _enable_icache(void) 37static inline void __enable_icache_msr(void)
20{ 38{
21 if (cpuinfo.use_icache) { 39 __asm__ __volatile__ (" msrset r0, %0; \
22#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 40 nop; " \
23 __asm__ __volatile__ (" \ 41 : : "i" (MSR_ICE) : "memory");
24 msrset r0, %0; \ 42}
25 nop; " \ 43
26 : \ 44static inline void __disable_icache_msr(void)
27 : "i" (MSR_ICE) \ 45{
46 __asm__ __volatile__ (" msrclr r0, %0; \
47 nop; " \
48 : : "i" (MSR_ICE) : "memory");
49}
50
51static inline void __enable_dcache_msr(void)
52{
53 __asm__ __volatile__ (" msrset r0, %0; \
54 nop; " \
55 : \
56 : "i" (MSR_DCE) \
28 : "memory"); 57 : "memory");
29#else
30 __asm__ __volatile__ (" \
31 mfs r12, rmsr; \
32 nop; \
33 ori r12, r12, %0; \
34 mts rmsr, r12; \
35 nop; " \
36 : \
37 : "i" (MSR_ICE) \
38 : "memory", "r12");
39#endif
40 }
41} 58}
42 59
43void _disable_icache(void) 60static inline void __disable_dcache_msr(void)
44{ 61{
45 if (cpuinfo.use_icache) { 62 __asm__ __volatile__ (" msrclr r0, %0; \
46#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 63 nop; " \
47 __asm__ __volatile__ (" \ 64 : \
48 msrclr r0, %0; \ 65 : "i" (MSR_DCE) \
49 nop; " \
50 : \
51 : "i" (MSR_ICE) \
52 : "memory"); 66 : "memory");
53#else 67}
54 __asm__ __volatile__ (" \ 68
55 mfs r12, rmsr; \ 69static inline void __enable_icache_nomsr(void)
56 nop; \ 70{
57 andi r12, r12, ~%0; \ 71 __asm__ __volatile__ (" mfs r12, rmsr; \
58 mts rmsr, r12; \ 72 nop; \
59 nop; " \ 73 ori r12, r12, %0; \
60 : \ 74 mts rmsr, r12; \
61 : "i" (MSR_ICE) \ 75 nop; " \
76 : \
77 : "i" (MSR_ICE) \
62 : "memory", "r12"); 78 : "memory", "r12");
63#endif
64 }
65} 79}
66 80
67void _invalidate_icache(unsigned int addr) 81static inline void __disable_icache_nomsr(void)
68{ 82{
69 if (cpuinfo.use_icache) { 83 __asm__ __volatile__ (" mfs r12, rmsr; \
70 __asm__ __volatile__ (" \ 84 nop; \
71 wic %0, r0" \ 85 andi r12, r12, ~%0; \
72 : \ 86 mts rmsr, r12; \
73 : "r" (addr)); 87 nop; " \
74 } 88 : \
89 : "i" (MSR_ICE) \
90 : "memory", "r12");
75} 91}
76 92
77void _enable_dcache(void) 93static inline void __enable_dcache_nomsr(void)
78{ 94{
79 if (cpuinfo.use_dcache) { 95 __asm__ __volatile__ (" mfs r12, rmsr; \
80#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 96 nop; \
81 __asm__ __volatile__ (" \ 97 ori r12, r12, %0; \
82 msrset r0, %0; \ 98 mts rmsr, r12; \
83 nop; " \ 99 nop; " \
84 : \ 100 : \
85 : "i" (MSR_DCE) \ 101 : "i" (MSR_DCE) \
86 : "memory");
87#else
88 __asm__ __volatile__ (" \
89 mfs r12, rmsr; \
90 nop; \
91 ori r12, r12, %0; \
92 mts rmsr, r12; \
93 nop; " \
94 : \
95 : "i" (MSR_DCE) \
96 : "memory", "r12"); 102 : "memory", "r12");
97#endif
98 }
99} 103}
100 104
101void _disable_dcache(void) 105static inline void __disable_dcache_nomsr(void)
102{ 106{
103#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 107 __asm__ __volatile__ (" mfs r12, rmsr; \
104 __asm__ __volatile__ (" \ 108 nop; \
105 msrclr r0, %0; \ 109 andi r12, r12, ~%0; \
106 nop; " \ 110 mts rmsr, r12; \
107 : \ 111 nop; " \
108 : "i" (MSR_DCE) \ 112 : \
109 : "memory"); 113 : "i" (MSR_DCE) \
110#else
111 __asm__ __volatile__ (" \
112 mfs r12, rmsr; \
113 nop; \
114 andi r12, r12, ~%0; \
115 mts rmsr, r12; \
116 nop; " \
117 : \
118 : "i" (MSR_DCE) \
119 : "memory", "r12"); 114 : "memory", "r12");
120#endif
121} 115}
122 116
123void _invalidate_dcache(unsigned int addr) 117
118/* Helper macro for computing the limits of cache range loops */
119#define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size) \
120do { \
121 int align = ~(cache_line_length - 1); \
122 end = min(start + cache_size, end); \
123 start &= align; \
124 end = ((end & align) + cache_line_length); \
125} while (0);
126
127/*
128 * Helper macro to loop over the specified cache_size/line_length and
129 * execute 'op' on that cacheline
130 */
131#define CACHE_ALL_LOOP(cache_size, line_length, op) \
132do { \
133 unsigned int len = cache_size; \
134 int step = -line_length; \
135 BUG_ON(step >= 0); \
136 \
137 __asm__ __volatile__ (" 1: " #op " %0, r0; \
138 bgtid %0, 1b; \
139 addk %0, %0, %1; \
140 " : : "r" (len), "r" (step) \
141 : "memory"); \
142} while (0);
143
144
145#define CACHE_ALL_LOOP2(cache_size, line_length, op) \
146do { \
147 unsigned int len = cache_size; \
148 int step = -line_length; \
149 BUG_ON(step >= 0); \
150 \
151 __asm__ __volatile__ (" 1: " #op " r0, %0; \
152 bgtid %0, 1b; \
153 addk %0, %0, %1; \
154 " : : "r" (len), "r" (step) \
155 : "memory"); \
156} while (0);
157
158/* for wdc.flush/clear */
159#define CACHE_RANGE_LOOP_2(start, end, line_length, op) \
160do { \
161 int step = -line_length; \
162 int count = end - start; \
163 BUG_ON(count <= 0); \
164 \
165 __asm__ __volatile__ (" 1: " #op " %0, %1; \
166 bgtid %1, 1b; \
167 addk %1, %1, %2; \
168 " : : "r" (start), "r" (count), \
169 "r" (step) : "memory"); \
170} while (0);
171
172/* It is used only first parameter for OP - for wic, wdc */
173#define CACHE_RANGE_LOOP_1(start, end, line_length, op) \
174do { \
175 int step = -line_length; \
176 int count = end - start; \
177 BUG_ON(count <= 0); \
178 \
179 __asm__ __volatile__ (" 1: addk %0, %0, %1; \
180 " #op " %0, r0; \
181 bgtid %1, 1b; \
182 addk %1, %1, %2; \
183 " : : "r" (start), "r" (count), \
184 "r" (step) : "memory"); \
185} while (0);
186
187static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end)
124{ 188{
125 __asm__ __volatile__ (" \ 189 unsigned long flags;
126 wdc %0, r0" \ 190
127 : \ 191 pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
128 : "r" (addr)); 192 (unsigned int)start, (unsigned int) end);
193
194 CACHE_LOOP_LIMITS(start, end,
195 cpuinfo.icache_line_length, cpuinfo.icache_size);
196
197 local_irq_save(flags);
198 __disable_icache_msr();
199
200 CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
201
202 __enable_icache_msr();
203 local_irq_restore(flags);
129} 204}
130 205
131void __invalidate_icache_all(void) 206static void __flush_icache_range_nomsr_irq(unsigned long start,
207 unsigned long end)
132{ 208{
133 unsigned int i; 209 unsigned long flags;
134 unsigned flags;
135 210
136 if (cpuinfo.use_icache) { 211 pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
137 local_irq_save(flags); 212 (unsigned int)start, (unsigned int) end);
138 __disable_icache();
139 213
140 /* Just loop through cache size and invalidate, no need to add 214 CACHE_LOOP_LIMITS(start, end,
141 CACHE_BASE address */ 215 cpuinfo.icache_line_length, cpuinfo.icache_size);
142 for (i = 0; i < cpuinfo.icache_size;
143 i += cpuinfo.icache_line)
144 __invalidate_icache(i);
145 216
146 __enable_icache(); 217 local_irq_save(flags);
147 local_irq_restore(flags); 218 __disable_icache_nomsr();
148 } 219
220 CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
221
222 __enable_icache_nomsr();
223 local_irq_restore(flags);
149} 224}
150 225
151void __invalidate_icache_range(unsigned long start, unsigned long end) 226static void __flush_icache_range_noirq(unsigned long start,
227 unsigned long end)
152{ 228{
153 unsigned int i; 229 pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
154 unsigned flags; 230 (unsigned int)start, (unsigned int) end);
155 unsigned int align; 231
156 232 CACHE_LOOP_LIMITS(start, end,
157 if (cpuinfo.use_icache) { 233 cpuinfo.icache_line_length, cpuinfo.icache_size);
158 /* 234 CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
159 * No need to cover entire cache range, 235}
160 * just cover cache footprint 236
161 */ 237static void __flush_icache_all_msr_irq(void)
162 end = min(start + cpuinfo.icache_size, end); 238{
163 align = ~(cpuinfo.icache_line - 1); 239 unsigned long flags;
164 start &= align; /* Make sure we are aligned */ 240
165 /* Push end up to the next cache line */ 241 pr_debug("%s\n", __func__);
166 end = ((end & align) + cpuinfo.icache_line); 242
167 243 local_irq_save(flags);
168 local_irq_save(flags); 244 __disable_icache_msr();
169 __disable_icache(); 245
170 246 CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
171 for (i = start; i < end; i += cpuinfo.icache_line) 247
172 __invalidate_icache(i); 248 __enable_icache_msr();
173 249 local_irq_restore(flags);
174 __enable_icache(); 250}
175 local_irq_restore(flags); 251
176 } 252static void __flush_icache_all_nomsr_irq(void)
253{
254 unsigned long flags;
255
256 pr_debug("%s\n", __func__);
257
258 local_irq_save(flags);
259 __disable_icache_nomsr();
260
261 CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
262
263 __enable_icache_nomsr();
264 local_irq_restore(flags);
177} 265}
178 266
179void __invalidate_icache_page(struct vm_area_struct *vma, struct page *page) 267static void __flush_icache_all_noirq(void)
180{ 268{
181 __invalidate_icache_all(); 269 pr_debug("%s\n", __func__);
270 CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
182} 271}
183 272
184void __invalidate_icache_user_range(struct vm_area_struct *vma, 273static void __invalidate_dcache_all_msr_irq(void)
185 struct page *page, unsigned long adr,
186 int len)
187{ 274{
188 __invalidate_icache_all(); 275 unsigned long flags;
276
277 pr_debug("%s\n", __func__);
278
279 local_irq_save(flags);
280 __disable_dcache_msr();
281
282 CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
283
284 __enable_dcache_msr();
285 local_irq_restore(flags);
189} 286}
190 287
191void __invalidate_cache_sigtramp(unsigned long addr) 288static void __invalidate_dcache_all_nomsr_irq(void)
192{ 289{
193 __invalidate_icache_range(addr, addr + 8); 290 unsigned long flags;
291
292 pr_debug("%s\n", __func__);
293
294 local_irq_save(flags);
295 __disable_dcache_nomsr();
296
297 CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
298
299 __enable_dcache_nomsr();
300 local_irq_restore(flags);
194} 301}
195 302
196void __invalidate_dcache_all(void) 303static void __invalidate_dcache_all_noirq_wt(void)
197{ 304{
198 unsigned int i; 305 pr_debug("%s\n", __func__);
199 unsigned flags; 306 CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc)
200
201 if (cpuinfo.use_dcache) {
202 local_irq_save(flags);
203 __disable_dcache();
204
205 /*
206 * Just loop through cache size and invalidate,
207 * no need to add CACHE_BASE address
208 */
209 for (i = 0; i < cpuinfo.dcache_size;
210 i += cpuinfo.dcache_line)
211 __invalidate_dcache(i);
212
213 __enable_dcache();
214 local_irq_restore(flags);
215 }
216} 307}
217 308
218void __invalidate_dcache_range(unsigned long start, unsigned long end) 309/* FIXME this is weird - should be only wdc but not work
310 * MS: I am getting bus errors and other weird things */
311static void __invalidate_dcache_all_wb(void)
219{ 312{
313 pr_debug("%s\n", __func__);
314 CACHE_ALL_LOOP2(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
315 wdc.clear)
316
317#if 0
220 unsigned int i; 318 unsigned int i;
221 unsigned flags; 319
222 unsigned int align; 320 pr_debug("%s\n", __func__);
223 321
224 if (cpuinfo.use_dcache) { 322 /* Just loop through cache size and invalidate it */
225 /* 323 for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length)
226 * No need to cover entire cache range, 324 __invalidate_dcache(0, i);
227 * just cover cache footprint 325#endif
228 */ 326}
229 end = min(start + cpuinfo.dcache_size, end); 327
230 align = ~(cpuinfo.dcache_line - 1); 328static void __invalidate_dcache_range_wb(unsigned long start,
231 start &= align; /* Make sure we are aligned */ 329 unsigned long end)
232 /* Push end up to the next cache line */ 330{
233 end = ((end & align) + cpuinfo.dcache_line); 331 pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
234 local_irq_save(flags); 332 (unsigned int)start, (unsigned int) end);
235 __disable_dcache(); 333
236 334 CACHE_LOOP_LIMITS(start, end,
237 for (i = start; i < end; i += cpuinfo.dcache_line) 335 cpuinfo.dcache_line_length, cpuinfo.dcache_size);
238 __invalidate_dcache(i); 336 CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear);
239 337}
240 __enable_dcache(); 338
241 local_irq_restore(flags); 339static void __invalidate_dcache_range_nomsr_wt(unsigned long start,
242 } 340 unsigned long end)
341{
342 pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
343 (unsigned int)start, (unsigned int) end);
344 CACHE_LOOP_LIMITS(start, end,
345 cpuinfo.dcache_line_length, cpuinfo.dcache_size);
346
347 CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
243} 348}
244 349
245void __invalidate_dcache_page(struct vm_area_struct *vma, struct page *page) 350static void __invalidate_dcache_range_msr_irq_wt(unsigned long start,
351 unsigned long end)
246{ 352{
247 __invalidate_dcache_all(); 353 unsigned long flags;
354
355 pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
356 (unsigned int)start, (unsigned int) end);
357 CACHE_LOOP_LIMITS(start, end,
358 cpuinfo.dcache_line_length, cpuinfo.dcache_size);
359
360 local_irq_save(flags);
361 __disable_dcache_msr();
362
363 CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
364
365 __enable_dcache_msr();
366 local_irq_restore(flags);
367}
368
369static void __invalidate_dcache_range_nomsr_irq(unsigned long start,
370 unsigned long end)
371{
372 unsigned long flags;
373
374 pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
375 (unsigned int)start, (unsigned int) end);
376
377 CACHE_LOOP_LIMITS(start, end,
378 cpuinfo.dcache_line_length, cpuinfo.dcache_size);
379
380 local_irq_save(flags);
381 __disable_dcache_nomsr();
382
383 CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
384
385 __enable_dcache_nomsr();
386 local_irq_restore(flags);
387}
388
389static void __flush_dcache_all_wb(void)
390{
391 pr_debug("%s\n", __func__);
392 CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
393 wdc.flush);
248} 394}
249 395
250void __invalidate_dcache_user_range(struct vm_area_struct *vma, 396static void __flush_dcache_range_wb(unsigned long start, unsigned long end)
251 struct page *page, unsigned long adr,
252 int len)
253{ 397{
254 __invalidate_dcache_all(); 398 pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
399 (unsigned int)start, (unsigned int) end);
400
401 CACHE_LOOP_LIMITS(start, end,
402 cpuinfo.dcache_line_length, cpuinfo.dcache_size);
403 CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush);
404}
405
406/* struct for wb caches and for wt caches */
407struct scache *mbc;
408
409/* new wb cache model */
410const struct scache wb_msr = {
411 .ie = __enable_icache_msr,
412 .id = __disable_icache_msr,
413 .ifl = __flush_icache_all_noirq,
414 .iflr = __flush_icache_range_noirq,
415 .iin = __flush_icache_all_noirq,
416 .iinr = __flush_icache_range_noirq,
417 .de = __enable_dcache_msr,
418 .dd = __disable_dcache_msr,
419 .dfl = __flush_dcache_all_wb,
420 .dflr = __flush_dcache_range_wb,
421 .din = __invalidate_dcache_all_wb,
422 .dinr = __invalidate_dcache_range_wb,
423};
424
425/* There is only difference in ie, id, de, dd functions */
426const struct scache wb_nomsr = {
427 .ie = __enable_icache_nomsr,
428 .id = __disable_icache_nomsr,
429 .ifl = __flush_icache_all_noirq,
430 .iflr = __flush_icache_range_noirq,
431 .iin = __flush_icache_all_noirq,
432 .iinr = __flush_icache_range_noirq,
433 .de = __enable_dcache_nomsr,
434 .dd = __disable_dcache_nomsr,
435 .dfl = __flush_dcache_all_wb,
436 .dflr = __flush_dcache_range_wb,
437 .din = __invalidate_dcache_all_wb,
438 .dinr = __invalidate_dcache_range_wb,
439};
440
441/* Old wt cache model with disabling irq and turn off cache */
442const struct scache wt_msr = {
443 .ie = __enable_icache_msr,
444 .id = __disable_icache_msr,
445 .ifl = __flush_icache_all_msr_irq,
446 .iflr = __flush_icache_range_msr_irq,
447 .iin = __flush_icache_all_msr_irq,
448 .iinr = __flush_icache_range_msr_irq,
449 .de = __enable_dcache_msr,
450 .dd = __disable_dcache_msr,
451 .dfl = __invalidate_dcache_all_msr_irq,
452 .dflr = __invalidate_dcache_range_msr_irq_wt,
453 .din = __invalidate_dcache_all_msr_irq,
454 .dinr = __invalidate_dcache_range_msr_irq_wt,
455};
456
457const struct scache wt_nomsr = {
458 .ie = __enable_icache_nomsr,
459 .id = __disable_icache_nomsr,
460 .ifl = __flush_icache_all_nomsr_irq,
461 .iflr = __flush_icache_range_nomsr_irq,
462 .iin = __flush_icache_all_nomsr_irq,
463 .iinr = __flush_icache_range_nomsr_irq,
464 .de = __enable_dcache_nomsr,
465 .dd = __disable_dcache_nomsr,
466 .dfl = __invalidate_dcache_all_nomsr_irq,
467 .dflr = __invalidate_dcache_range_nomsr_irq,
468 .din = __invalidate_dcache_all_nomsr_irq,
469 .dinr = __invalidate_dcache_range_nomsr_irq,
470};
471
472/* New wt cache model for newer Microblaze versions */
473const struct scache wt_msr_noirq = {
474 .ie = __enable_icache_msr,
475 .id = __disable_icache_msr,
476 .ifl = __flush_icache_all_noirq,
477 .iflr = __flush_icache_range_noirq,
478 .iin = __flush_icache_all_noirq,
479 .iinr = __flush_icache_range_noirq,
480 .de = __enable_dcache_msr,
481 .dd = __disable_dcache_msr,
482 .dfl = __invalidate_dcache_all_noirq_wt,
483 .dflr = __invalidate_dcache_range_nomsr_wt,
484 .din = __invalidate_dcache_all_noirq_wt,
485 .dinr = __invalidate_dcache_range_nomsr_wt,
486};
487
488const struct scache wt_nomsr_noirq = {
489 .ie = __enable_icache_nomsr,
490 .id = __disable_icache_nomsr,
491 .ifl = __flush_icache_all_noirq,
492 .iflr = __flush_icache_range_noirq,
493 .iin = __flush_icache_all_noirq,
494 .iinr = __flush_icache_range_noirq,
495 .de = __enable_dcache_nomsr,
496 .dd = __disable_dcache_nomsr,
497 .dfl = __invalidate_dcache_all_noirq_wt,
498 .dflr = __invalidate_dcache_range_nomsr_wt,
499 .din = __invalidate_dcache_all_noirq_wt,
500 .dinr = __invalidate_dcache_range_nomsr_wt,
501};
502
503/* CPU version code for 7.20.c - see arch/microblaze/kernel/cpu/cpuinfo.c */
504#define CPUVER_7_20_A 0x0c
505#define CPUVER_7_20_D 0x0f
506
507#define INFO(s) printk(KERN_INFO "cache: " s " \n");
508
509void microblaze_cache_init(void)
510{
511 if (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) {
512 if (cpuinfo.dcache_wb) {
513 INFO("wb_msr");
514 mbc = (struct scache *)&wb_msr;
515 if (cpuinfo.ver_code < CPUVER_7_20_D) {
516 /* MS: problem with signal handling - hw bug */
517 INFO("WB won't work properly");
518 }
519 } else {
520 if (cpuinfo.ver_code >= CPUVER_7_20_A) {
521 INFO("wt_msr_noirq");
522 mbc = (struct scache *)&wt_msr_noirq;
523 } else {
524 INFO("wt_msr");
525 mbc = (struct scache *)&wt_msr;
526 }
527 }
528 } else {
529 if (cpuinfo.dcache_wb) {
530 INFO("wb_nomsr");
531 mbc = (struct scache *)&wb_nomsr;
532 if (cpuinfo.ver_code < CPUVER_7_20_D) {
533 /* MS: problem with signal handling - hw bug */
534 INFO("WB won't work properly");
535 }
536 } else {
537 if (cpuinfo.ver_code >= CPUVER_7_20_A) {
538 INFO("wt_nomsr_noirq");
539 mbc = (struct scache *)&wt_nomsr_noirq;
540 } else {
541 INFO("wt_nomsr");
542 mbc = (struct scache *)&wt_nomsr;
543 }
544 }
545 }
255} 546}
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
index c259786e7faa..f72dbd66c844 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
@@ -21,8 +21,14 @@
21 */ 21 */
22 22
23#define CI(c, p) { ci->c = PVR_##p(pvr); } 23#define CI(c, p) { ci->c = PVR_##p(pvr); }
24
25#if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
24#define err_printk(x) \ 26#define err_printk(x) \
25 early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n"); 27 early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n");
28#else
29#define err_printk(x) \
30 printk(KERN_INFO "ERROR: Microblaze " x "-different for PVR and DTS\n");
31#endif
26 32
27void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) 33void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
28{ 34{
@@ -70,7 +76,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
70 CI(use_icache, USE_ICACHE); 76 CI(use_icache, USE_ICACHE);
71 CI(icache_tagbits, ICACHE_ADDR_TAG_BITS); 77 CI(icache_tagbits, ICACHE_ADDR_TAG_BITS);
72 CI(icache_write, ICACHE_ALLOW_WR); 78 CI(icache_write, ICACHE_ALLOW_WR);
73 CI(icache_line, ICACHE_LINE_LEN); 79 ci->icache_line_length = PVR_ICACHE_LINE_LEN(pvr) << 2;
74 CI(icache_size, ICACHE_BYTE_SIZE); 80 CI(icache_size, ICACHE_BYTE_SIZE);
75 CI(icache_base, ICACHE_BASEADDR); 81 CI(icache_base, ICACHE_BASEADDR);
76 CI(icache_high, ICACHE_HIGHADDR); 82 CI(icache_high, ICACHE_HIGHADDR);
@@ -78,11 +84,16 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
78 CI(use_dcache, USE_DCACHE); 84 CI(use_dcache, USE_DCACHE);
79 CI(dcache_tagbits, DCACHE_ADDR_TAG_BITS); 85 CI(dcache_tagbits, DCACHE_ADDR_TAG_BITS);
80 CI(dcache_write, DCACHE_ALLOW_WR); 86 CI(dcache_write, DCACHE_ALLOW_WR);
81 CI(dcache_line, DCACHE_LINE_LEN); 87 ci->dcache_line_length = PVR_DCACHE_LINE_LEN(pvr) << 2;
82 CI(dcache_size, DCACHE_BYTE_SIZE); 88 CI(dcache_size, DCACHE_BYTE_SIZE);
83 CI(dcache_base, DCACHE_BASEADDR); 89 CI(dcache_base, DCACHE_BASEADDR);
84 CI(dcache_high, DCACHE_HIGHADDR); 90 CI(dcache_high, DCACHE_HIGHADDR);
85 91
92 temp = PVR_DCACHE_USE_WRITEBACK(pvr);
93 if (ci->dcache_wb != temp)
94 err_printk("DCACHE WB");
95 ci->dcache_wb = temp;
96
86 CI(use_dopb, D_OPB); 97 CI(use_dopb, D_OPB);
87 CI(use_iopb, I_OPB); 98 CI(use_iopb, I_OPB);
88 CI(use_dlmb, D_LMB); 99 CI(use_dlmb, D_LMB);
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c
index adb448f93d5f..6095aa6b5c88 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo-static.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c
@@ -72,12 +72,12 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
72 ci->use_icache = fcpu(cpu, "xlnx,use-icache"); 72 ci->use_icache = fcpu(cpu, "xlnx,use-icache");
73 ci->icache_tagbits = fcpu(cpu, "xlnx,addr-tag-bits"); 73 ci->icache_tagbits = fcpu(cpu, "xlnx,addr-tag-bits");
74 ci->icache_write = fcpu(cpu, "xlnx,allow-icache-wr"); 74 ci->icache_write = fcpu(cpu, "xlnx,allow-icache-wr");
75 ci->icache_line = fcpu(cpu, "xlnx,icache-line-len") << 2; 75 ci->icache_line_length = fcpu(cpu, "xlnx,icache-line-len") << 2;
76 if (!ci->icache_line) { 76 if (!ci->icache_line_length) {
77 if (fcpu(cpu, "xlnx,icache-use-fsl")) 77 if (fcpu(cpu, "xlnx,icache-use-fsl"))
78 ci->icache_line = 4 << 2; 78 ci->icache_line_length = 4 << 2;
79 else 79 else
80 ci->icache_line = 1 << 2; 80 ci->icache_line_length = 1 << 2;
81 } 81 }
82 ci->icache_size = fcpu(cpu, "i-cache-size"); 82 ci->icache_size = fcpu(cpu, "i-cache-size");
83 ci->icache_base = fcpu(cpu, "i-cache-baseaddr"); 83 ci->icache_base = fcpu(cpu, "i-cache-baseaddr");
@@ -86,16 +86,17 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
86 ci->use_dcache = fcpu(cpu, "xlnx,use-dcache"); 86 ci->use_dcache = fcpu(cpu, "xlnx,use-dcache");
87 ci->dcache_tagbits = fcpu(cpu, "xlnx,dcache-addr-tag"); 87 ci->dcache_tagbits = fcpu(cpu, "xlnx,dcache-addr-tag");
88 ci->dcache_write = fcpu(cpu, "xlnx,allow-dcache-wr"); 88 ci->dcache_write = fcpu(cpu, "xlnx,allow-dcache-wr");
89 ci->dcache_line = fcpu(cpu, "xlnx,dcache-line-len") << 2; 89 ci->dcache_line_length = fcpu(cpu, "xlnx,dcache-line-len") << 2;
90 if (!ci->dcache_line) { 90 if (!ci->dcache_line_length) {
91 if (fcpu(cpu, "xlnx,dcache-use-fsl")) 91 if (fcpu(cpu, "xlnx,dcache-use-fsl"))
92 ci->dcache_line = 4 << 2; 92 ci->dcache_line_length = 4 << 2;
93 else 93 else
94 ci->dcache_line = 1 << 2; 94 ci->dcache_line_length = 1 << 2;
95 } 95 }
96 ci->dcache_size = fcpu(cpu, "d-cache-size"); 96 ci->dcache_size = fcpu(cpu, "d-cache-size");
97 ci->dcache_base = fcpu(cpu, "d-cache-baseaddr"); 97 ci->dcache_base = fcpu(cpu, "d-cache-baseaddr");
98 ci->dcache_high = fcpu(cpu, "d-cache-highaddr"); 98 ci->dcache_high = fcpu(cpu, "d-cache-highaddr");
99 ci->dcache_wb = fcpu(cpu, "xlnx,dcache-use-writeback");
99 100
100 ci->use_dopb = fcpu(cpu, "xlnx,d-opb"); 101 ci->use_dopb = fcpu(cpu, "xlnx,d-opb");
101 ci->use_iopb = fcpu(cpu, "xlnx,i-opb"); 102 ci->use_iopb = fcpu(cpu, "xlnx,i-opb");
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c
index 3539babc1c18..991d71311b0e 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo.c
@@ -29,11 +29,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
29 {"7.20.a", 0x0c}, 29 {"7.20.a", 0x0c},
30 {"7.20.b", 0x0d}, 30 {"7.20.b", 0x0d},
31 {"7.20.c", 0x0e}, 31 {"7.20.c", 0x0e},
32 /* FIXME There is no keycode defined in MBV for these versions */ 32 {"7.20.d", 0x0f},
33 {"2.10.a", 0x10}, 33 {"7.30.a", 0x10},
34 {"3.00.a", 0x20},
35 {"4.00.a", 0x30},
36 {"4.00.b", 0x40},
37 {NULL, 0}, 34 {NULL, 0},
38}; 35};
39 36
diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c
index 4dcfccdbc364..0c912b2a8e03 100644
--- a/arch/microblaze/kernel/cpu/mb.c
+++ b/arch/microblaze/kernel/cpu/mb.c
@@ -103,11 +103,15 @@ static int show_cpuinfo(struct seq_file *m, void *v)
103 else 103 else
104 count += seq_printf(m, "Icache:\t\tno\n"); 104 count += seq_printf(m, "Icache:\t\tno\n");
105 105
106 if (cpuinfo.use_dcache) 106 if (cpuinfo.use_dcache) {
107 count += seq_printf(m, 107 count += seq_printf(m,
108 "Dcache:\t\t%ukB\n", 108 "Dcache:\t\t%ukB\n",
109 cpuinfo.dcache_size >> 10); 109 cpuinfo.dcache_size >> 10);
110 else 110 if (cpuinfo.dcache_wb)
111 count += seq_printf(m, "\t\twrite-back\n");
112 else
113 count += seq_printf(m, "\t\twrite-through\n");
114 } else
111 count += seq_printf(m, "Dcache:\t\tno\n"); 115 count += seq_printf(m, "Dcache:\t\tno\n");
112 116
113 count += seq_printf(m, 117 count += seq_printf(m,
diff --git a/arch/microblaze/kernel/cpu/pvr.c b/arch/microblaze/kernel/cpu/pvr.c
index c9a4340ddd53..9bee9382bf74 100644
--- a/arch/microblaze/kernel/cpu/pvr.c
+++ b/arch/microblaze/kernel/cpu/pvr.c
@@ -45,7 +45,7 @@
45 45
46int cpu_has_pvr(void) 46int cpu_has_pvr(void)
47{ 47{
48 unsigned flags; 48 unsigned long flags;
49 unsigned pvr0; 49 unsigned pvr0;
50 50
51 local_save_flags(flags); 51 local_save_flags(flags);
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S
index 9083d85376a4..95b0855802df 100644
--- a/arch/microblaze/kernel/entry-nommu.S
+++ b/arch/microblaze/kernel/entry-nommu.S
@@ -208,8 +208,6 @@ ENTRY(_user_exception)
208 lwi r1, r1, TS_THREAD_INFO /* get the thread info */ 208 lwi r1, r1, TS_THREAD_INFO /* get the thread info */
209 /* calculate kernel stack pointer */ 209 /* calculate kernel stack pointer */
210 addik r1, r1, THREAD_SIZE - PT_SIZE 210 addik r1, r1, THREAD_SIZE - PT_SIZE
211 swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */
212 lwi r11, r0, PER_CPU(KM) /* load mode indicator */
2132: 2112:
214 swi r11, r1, PT_MODE /* store the mode */ 212 swi r11, r1, PT_MODE /* store the mode */
215 lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */ 213 lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S
index e3ecb36dd554..3bad4ff49471 100644
--- a/arch/microblaze/kernel/entry.S
+++ b/arch/microblaze/kernel/entry.S
@@ -31,6 +31,8 @@
31#include <linux/errno.h> 31#include <linux/errno.h>
32#include <asm/signal.h> 32#include <asm/signal.h>
33 33
34#undef DEBUG
35
34/* The size of a state save frame. */ 36/* The size of a state save frame. */
35#define STATE_SAVE_SIZE (PT_SIZE + STATE_SAVE_ARG_SPACE) 37#define STATE_SAVE_SIZE (PT_SIZE + STATE_SAVE_ARG_SPACE)
36 38
@@ -352,10 +354,12 @@ C_ENTRY(_user_exception):
352 add r12, r12, r12; /* convert num -> ptr */ 354 add r12, r12, r12; /* convert num -> ptr */
353 add r12, r12, r12; 355 add r12, r12, r12;
354 356
357#ifdef DEBUG
355 /* Trac syscalls and stored them to r0_ram */ 358 /* Trac syscalls and stored them to r0_ram */
356 lwi r3, r12, 0x400 + r0_ram 359 lwi r3, r12, 0x400 + r0_ram
357 addi r3, r3, 1 360 addi r3, r3, 1
358 swi r3, r12, 0x400 + r0_ram 361 swi r3, r12, 0x400 + r0_ram
362#endif
359 363
360 # Find and jump into the syscall handler. 364 # Find and jump into the syscall handler.
361 lwi r12, r12, sys_call_table 365 lwi r12, r12, sys_call_table
@@ -496,17 +500,6 @@ C_ENTRY(sys_execve):
496 brid microblaze_execve; /* Do real work (tail-call).*/ 500 brid microblaze_execve; /* Do real work (tail-call).*/
497 nop; 501 nop;
498 502
499C_ENTRY(sys_rt_sigsuspend_wrapper):
500 swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
501 swi r4, r1, PTO+PT_R4;
502 la r7, r1, PTO; /* add user context as 3rd arg */
503 brlid r15, sys_rt_sigsuspend; /* Do real work.*/
504 nop;
505 lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
506 lwi r4, r1, PTO+PT_R4;
507 bri ret_from_trap /* fall through will not work here due to align */
508 nop;
509
510C_ENTRY(sys_rt_sigreturn_wrapper): 503C_ENTRY(sys_rt_sigreturn_wrapper):
511 swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ 504 swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
512 swi r4, r1, PTO+PT_R4; 505 swi r4, r1, PTO+PT_R4;
@@ -711,15 +704,11 @@ C_ENTRY(ret_from_exc):
711 * (in a possibly modified form) after do_signal returns. 704 * (in a possibly modified form) after do_signal returns.
712 * store return registers separately because this macros is use 705 * store return registers separately because this macros is use
713 * for others exceptions */ 706 * for others exceptions */
714 swi r3, r1, PTO + PT_R3;
715 swi r4, r1, PTO + PT_R4;
716 la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ 707 la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
717 add r6, r0, r0; /* Arg 2: sigset_t *oldset */ 708 add r6, r0, r0; /* Arg 2: sigset_t *oldset */
718 addi r7, r0, 0; /* Arg 3: int in_syscall */ 709 addi r7, r0, 0; /* Arg 3: int in_syscall */
719 bralid r15, do_signal; /* Handle any signals */ 710 bralid r15, do_signal; /* Handle any signals */
720 nop; 711 nop;
721 lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
722 lwi r4, r1, PTO+PT_R4;
723 712
724/* Finally, return to user state. */ 713/* Finally, return to user state. */
7251: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ 7141: 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
index 000000000000..388b31ca65a1
--- /dev/null
+++ b/arch/microblaze/kernel/ftrace.c
@@ -0,0 +1,237 @@
1/*
2 * Ftrace support for Microblaze.
3 *
4 * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
5 * Copyright (C) 2009 PetaLogix
6 *
7 * Based on MIPS and PowerPC ftrace code
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 */
13
14#include <asm/cacheflush.h>
15#include <linux/ftrace.h>
16
17#ifdef CONFIG_FUNCTION_GRAPH_TRACER
18/*
19 * Hook the return address and push it in the stack of return addrs
20 * in current thread info.
21 */
22void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
23{
24 unsigned long old;
25 int faulted, err;
26 struct ftrace_graph_ent trace;
27 unsigned long return_hooker = (unsigned long)
28 &return_to_handler;
29
30 if (unlikely(atomic_read(&current->tracing_graph_pause)))
31 return;
32
33 /*
34 * Protect against fault, even if it shouldn't
35 * happen. This tool is too much intrusive to
36 * ignore such a protection.
37 */
38 asm volatile(" 1: lwi %0, %2, 0; \
39 2: swi %3, %2, 0; \
40 addik %1, r0, 0; \
41 3: \
42 .section .fixup, \"ax\"; \
43 4: brid 3b; \
44 addik %1, r0, 1; \
45 .previous; \
46 .section __ex_table,\"a\"; \
47 .word 1b,4b; \
48 .word 2b,4b; \
49 .previous;" \
50 : "=&r" (old), "=r" (faulted)
51 : "r" (parent), "r" (return_hooker)
52 );
53
54 if (unlikely(faulted)) {
55 ftrace_graph_stop();
56 WARN_ON(1);
57 return;
58 }
59
60 err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0);
61 if (err == -EBUSY) {
62 *parent = old;
63 return;
64 }
65
66 trace.func = self_addr;
67 /* Only trace if the calling function expects to */
68 if (!ftrace_graph_entry(&trace)) {
69 current->curr_ret_stack--;
70 *parent = old;
71 }
72}
73#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
74
75#ifdef CONFIG_DYNAMIC_FTRACE
76/* save value to addr - it is save to do it in asm */
77static int ftrace_modify_code(unsigned long addr, unsigned int value)
78{
79 int faulted = 0;
80
81 __asm__ __volatile__(" 1: swi %2, %1, 0; \
82 addik %0, r0, 0; \
83 2: \
84 .section .fixup, \"ax\"; \
85 3: brid 2b; \
86 addik %0, r0, 1; \
87 .previous; \
88 .section __ex_table,\"a\"; \
89 .word 1b,3b; \
90 .previous;" \
91 : "=r" (faulted)
92 : "r" (addr), "r" (value)
93 );
94
95 if (unlikely(faulted))
96 return -EFAULT;
97
98 return 0;
99}
100
101#define MICROBLAZE_NOP 0x80000000
102#define MICROBLAZE_BRI 0xb800000C
103
104static unsigned int recorded; /* if save was or not */
105static unsigned int imm; /* saving whole imm instruction */
106
107/* There are two approaches howto solve ftrace_make nop function - look below */
108#undef USE_FTRACE_NOP
109
110#ifdef USE_FTRACE_NOP
111static unsigned int bralid; /* saving whole bralid instruction */
112#endif
113
114int ftrace_make_nop(struct module *mod,
115 struct dyn_ftrace *rec, unsigned long addr)
116{
117 /* we have this part of code which we are working with
118 * b000c000 imm -16384
119 * b9fc8e30 bralid r15, -29136 // c0008e30 <_mcount>
120 * 80000000 or r0, r0, r0
121 *
122 * The first solution (!USE_FTRACE_NOP-could be called branch solution)
123 * b000c000 bri 12 (0xC - jump to any other instruction)
124 * b9fc8e30 bralid r15, -29136 // c0008e30 <_mcount>
125 * 80000000 or r0, r0, r0
126 * any other instruction
127 *
128 * The second solution (USE_FTRACE_NOP) - no jump just nops
129 * 80000000 or r0, r0, r0
130 * 80000000 or r0, r0, r0
131 * 80000000 or r0, r0, r0
132 */
133 int ret = 0;
134
135 if (recorded == 0) {
136 recorded = 1;
137 imm = *(unsigned int *)rec->ip;
138 pr_debug("%s: imm:0x%x\n", __func__, imm);
139#ifdef USE_FTRACE_NOP
140 bralid = *(unsigned int *)(rec->ip + 4);
141 pr_debug("%s: bralid 0x%x\n", __func__, bralid);
142#endif /* USE_FTRACE_NOP */
143 }
144
145#ifdef USE_FTRACE_NOP
146 ret = ftrace_modify_code(rec->ip, MICROBLAZE_NOP);
147 ret += ftrace_modify_code(rec->ip + 4, MICROBLAZE_NOP);
148#else /* USE_FTRACE_NOP */
149 ret = ftrace_modify_code(rec->ip, MICROBLAZE_BRI);
150#endif /* USE_FTRACE_NOP */
151 return ret;
152}
153
154static int ret_addr; /* initialized as 0 by default */
155
156/* I believe that first is called ftrace_make_nop before this function */
157int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
158{
159 int ret;
160 ret_addr = addr; /* saving where the barrier jump is */
161 pr_debug("%s: addr:0x%x, rec->ip: 0x%x, imm:0x%x\n",
162 __func__, (unsigned int)addr, (unsigned int)rec->ip, imm);
163 ret = ftrace_modify_code(rec->ip, imm);
164#ifdef USE_FTRACE_NOP
165 pr_debug("%s: bralid:0x%x\n", __func__, bralid);
166 ret += ftrace_modify_code(rec->ip + 4, bralid);
167#endif /* USE_FTRACE_NOP */
168 return ret;
169}
170
171int __init ftrace_dyn_arch_init(void *data)
172{
173 /* The return code is retured via data */
174 *(unsigned long *)data = 0;
175
176 return 0;
177}
178
179int ftrace_update_ftrace_func(ftrace_func_t func)
180{
181 unsigned long ip = (unsigned long)(&ftrace_call);
182 unsigned int upper = (unsigned int)func;
183 unsigned int lower = (unsigned int)func;
184 int ret = 0;
185
186 /* create proper saving to ftrace_call poll */
187 upper = 0xb0000000 + (upper >> 16); /* imm func_upper */
188 lower = 0x32800000 + (lower & 0xFFFF); /* addik r20, r0, func_lower */
189
190 pr_debug("%s: func=0x%x, ip=0x%x, upper=0x%x, lower=0x%x\n",
191 __func__, (unsigned int)func, (unsigned int)ip, upper, lower);
192
193 /* save upper and lower code */
194 ret = ftrace_modify_code(ip, upper);
195 ret += ftrace_modify_code(ip + 4, lower);
196
197 /* We just need to remove the rtsd r15, 8 by NOP */
198 BUG_ON(!ret_addr);
199 if (ret_addr)
200 ret += ftrace_modify_code(ret_addr, MICROBLAZE_NOP);
201 else
202 ret = 1; /* fault */
203
204 /* All changes are done - lets do caches consistent */
205 flush_icache();
206 return ret;
207}
208
209#ifdef CONFIG_FUNCTION_GRAPH_TRACER
210unsigned int old_jump; /* saving place for jump instruction */
211
212int ftrace_enable_ftrace_graph_caller(void)
213{
214 unsigned int ret;
215 unsigned long ip = (unsigned long)(&ftrace_call_graph);
216
217 old_jump = *(unsigned int *)ip; /* save jump over instruction */
218 ret = ftrace_modify_code(ip, MICROBLAZE_NOP);
219 flush_icache();
220
221 pr_debug("%s: Replace instruction: 0x%x\n", __func__, old_jump);
222 return ret;
223}
224
225int ftrace_disable_ftrace_graph_caller(void)
226{
227 unsigned int ret;
228 unsigned long ip = (unsigned long)(&ftrace_call_graph);
229
230 ret = ftrace_modify_code(ip, old_jump);
231 flush_icache();
232
233 pr_debug("%s\n", __func__);
234 return ret;
235}
236#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
237#endif /* CONFIG_DYNAMIC_FTRACE */
diff --git a/arch/microblaze/kernel/heartbeat.c b/arch/microblaze/kernel/heartbeat.c
index 1bdf20222b92..522751737cfa 100644
--- a/arch/microblaze/kernel/heartbeat.c
+++ b/arch/microblaze/kernel/heartbeat.c
@@ -45,6 +45,7 @@ void heartbeat(void)
45void setup_heartbeat(void) 45void setup_heartbeat(void)
46{ 46{
47 struct device_node *gpio = NULL; 47 struct device_node *gpio = NULL;
48 int *prop;
48 int j; 49 int j;
49 char *gpio_list[] = { 50 char *gpio_list[] = {
50 "xlnx,xps-gpio-1.00.a", 51 "xlnx,xps-gpio-1.00.a",
@@ -58,10 +59,14 @@ void setup_heartbeat(void)
58 break; 59 break;
59 } 60 }
60 61
61 base_addr = *(int *) of_get_property(gpio, "reg", NULL); 62 if (gpio) {
62 base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE); 63 base_addr = *(int *) of_get_property(gpio, "reg", NULL);
63 printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr); 64 base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE);
65 printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr);
64 66
65 if (*(int *) of_get_property(gpio, "xlnx,is-bidir", NULL)) 67 /* GPIO is configured as output */
66 out_be32(base_addr + 4, 0); /* GPIO is configured as output */ 68 prop = (int *) of_get_property(gpio, "xlnx,is-bidir", NULL);
69 if (prop)
70 out_be32(base_addr + 4, 0);
71 }
67} 72}
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
index 6eea6f92b84e..03172c1da770 100644
--- a/arch/microblaze/kernel/intc.c
+++ b/arch/microblaze/kernel/intc.c
@@ -42,8 +42,16 @@ unsigned int nr_irq;
42 42
43static void intc_enable_or_unmask(unsigned int irq) 43static void intc_enable_or_unmask(unsigned int irq)
44{ 44{
45 unsigned long mask = 1 << irq;
45 pr_debug("enable_or_unmask: %d\n", irq); 46 pr_debug("enable_or_unmask: %d\n", irq);
46 out_be32(INTC_BASE + SIE, 1 << irq); 47 out_be32(INTC_BASE + SIE, mask);
48
49 /* ack level irqs because they can't be acked during
50 * ack function since the handle_level_irq function
51 * acks the irq before calling the interrupt handler
52 */
53 if (irq_desc[irq].status & IRQ_LEVEL)
54 out_be32(INTC_BASE + IAR, mask);
47} 55}
48 56
49static void intc_disable_or_mask(unsigned int irq) 57static void intc_disable_or_mask(unsigned int irq)
diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
index 7d5ddd62d4d2..0f06034d1fe0 100644
--- a/arch/microblaze/kernel/irq.c
+++ b/arch/microblaze/kernel/irq.c
@@ -68,7 +68,7 @@ int show_interrupts(struct seq_file *p, void *v)
68 } 68 }
69 69
70 if (i < nr_irq) { 70 if (i < nr_irq) {
71 spin_lock_irqsave(&irq_desc[i].lock, flags); 71 raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
72 action = irq_desc[i].action; 72 action = irq_desc[i].action;
73 if (!action) 73 if (!action)
74 goto skip; 74 goto skip;
@@ -89,7 +89,7 @@ int show_interrupts(struct seq_file *p, void *v)
89 89
90 seq_putc(p, '\n'); 90 seq_putc(p, '\n');
91skip: 91skip:
92 spin_unlock_irqrestore(&irq_desc[i].lock, flags); 92 raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
93 } 93 }
94 return 0; 94 return 0;
95} 95}
diff --git a/arch/microblaze/kernel/mcount.S b/arch/microblaze/kernel/mcount.S
new file mode 100644
index 000000000000..e7eaa7a8cbd3
--- /dev/null
+++ b/arch/microblaze/kernel/mcount.S
@@ -0,0 +1,170 @@
1/*
2 * Low-level ftrace handling
3 *
4 * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
5 * Copyright (C) 2009 PetaLogix
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 */
11
12#include <linux/linkage.h>
13
14#define NOALIGN_ENTRY(name) .globl name; name:
15
16/* FIXME MS: I think that I don't need to save all regs */
17#define SAVE_REGS \
18 addik r1, r1, -120; \
19 swi r2, r1, 4; \
20 swi r3, r1, 8; \
21 swi r4, r1, 12; \
22 swi r5, r1, 116; \
23 swi r6, r1, 16; \
24 swi r7, r1, 20; \
25 swi r8, r1, 24; \
26 swi r9, r1, 28; \
27 swi r10, r1, 32; \
28 swi r11, r1, 36; \
29 swi r12, r1, 40; \
30 swi r13, r1, 44; \
31 swi r14, r1, 48; \
32 swi r16, r1, 52; \
33 swi r17, r1, 56; \
34 swi r18, r1, 60; \
35 swi r19, r1, 64; \
36 swi r20, r1, 68; \
37 swi r21, r1, 72; \
38 swi r22, r1, 76; \
39 swi r23, r1, 80; \
40 swi r24, r1, 84; \
41 swi r25, r1, 88; \
42 swi r26, r1, 92; \
43 swi r27, r1, 96; \
44 swi r28, r1, 100; \
45 swi r29, r1, 104; \
46 swi r30, r1, 108; \
47 swi r31, r1, 112;
48
49#define RESTORE_REGS \
50 lwi r2, r1, 4; \
51 lwi r3, r1, 8; \
52 lwi r4, r1, 12; \
53 lwi r5, r1, 116; \
54 lwi r6, r1, 16; \
55 lwi r7, r1, 20; \
56 lwi r8, r1, 24; \
57 lwi r9, r1, 28; \
58 lwi r10, r1, 32; \
59 lwi r11, r1, 36; \
60 lwi r12, r1, 40; \
61 lwi r13, r1, 44; \
62 lwi r14, r1, 48; \
63 lwi r16, r1, 52; \
64 lwi r17, r1, 56; \
65 lwi r18, r1, 60; \
66 lwi r19, r1, 64; \
67 lwi r20, r1, 68; \
68 lwi r21, r1, 72; \
69 lwi r22, r1, 76; \
70 lwi r23, r1, 80; \
71 lwi r24, r1, 84; \
72 lwi r25, r1, 88; \
73 lwi r26, r1, 92; \
74 lwi r27, r1, 96; \
75 lwi r28, r1, 100; \
76 lwi r29, r1, 104; \
77 lwi r30, r1, 108; \
78 lwi r31, r1, 112; \
79 addik r1, r1, 120;
80
81ENTRY(ftrace_stub)
82 rtsd r15, 8;
83 nop;
84
85ENTRY(_mcount)
86#ifdef CONFIG_DYNAMIC_FTRACE
87ENTRY(ftrace_caller)
88 /* MS: It is just barrier which is removed from C code */
89 rtsd r15, 8
90 nop
91#endif /* CONFIG_DYNAMIC_FTRACE */
92 SAVE_REGS
93 swi r15, r1, 0;
94 /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST begin of checking */
95 lwi r5, r0, function_trace_stop;
96 bneid r5, end;
97 nop;
98 /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */
99#ifdef CONFIG_FUNCTION_GRAPH_TRACER
100#ifndef CONFIG_DYNAMIC_FTRACE
101 lwi r5, r0, ftrace_graph_return;
102 addik r6, r0, ftrace_stub; /* asm implementation */
103 cmpu r5, r5, r6; /* ftrace_graph_return != ftrace_stub */
104 beqid r5, end_graph_tracer;
105 nop;
106
107 lwi r6, r0, ftrace_graph_entry;
108 addik r5, r0, ftrace_graph_entry_stub; /* implemented in C */
109 cmpu r5, r5, r6; /* ftrace_graph_entry != ftrace_graph_entry_stub */
110 beqid r5, end_graph_tracer;
111 nop;
112#else /* CONFIG_DYNAMIC_FTRACE */
113NOALIGN_ENTRY(ftrace_call_graph)
114 /* MS: jump over graph function - replaced from C code */
115 bri end_graph_tracer
116#endif /* CONFIG_DYNAMIC_FTRACE */
117 addik r5, r1, 120; /* MS: load parent addr */
118 addik r6, r15, 0; /* MS: load current function addr */
119 bralid r15, prepare_ftrace_return;
120 nop;
121 /* MS: graph was taken that's why - can jump over function trace */
122 brid end;
123 nop;
124end_graph_tracer:
125#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
126#ifndef CONFIG_DYNAMIC_FTRACE
127 /* MS: test function trace if is taken or not */
128 lwi r20, r0, ftrace_trace_function;
129 addik r6, r0, ftrace_stub;
130 cmpu r5, r20, r6; /* ftrace_trace_function != ftrace_stub */
131 beqid r5, end; /* MS: not taken -> jump over */
132 nop;
133#else /* CONFIG_DYNAMIC_FTRACE */
134NOALIGN_ENTRY(ftrace_call)
135/* instruction for setup imm FUNC_part1, addik r20, r0, FUNC_part2 */
136 nop
137 nop
138#endif /* CONFIG_DYNAMIC_FTRACE */
139/* static normal trace */
140 lwi r6, r1, 120; /* MS: load parent addr */
141 addik r5, r15, 0; /* MS: load current function addr */
142 /* MS: here is dependency on previous code */
143 brald r15, r20; /* MS: jump to ftrace handler */
144 nop;
145end:
146 lwi r15, r1, 0;
147 RESTORE_REGS
148
149 rtsd r15, 8; /* MS: jump back */
150 nop;
151
152#ifdef CONFIG_FUNCTION_GRAPH_TRACER
153ENTRY(return_to_handler)
154 nop; /* MS: just barrier for rtsd r15, 8 */
155 nop;
156 SAVE_REGS
157 swi r15, r1, 0;
158
159 /* MS: find out returning address */
160 bralid r15, ftrace_return_to_handler;
161 nop;
162
163 /* MS: return value from ftrace_return_to_handler is my returning addr
164 * must be before restore regs because I have to restore r3 content */
165 addik r15, r3, 0;
166 RESTORE_REGS
167
168 rtsd r15, 8; /* MS: jump back */
169 nop;
170#endif /* CONFIG_FUNCTION_TRACER */
diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c
index 59ff20e33e0c..bc4dcb7d3861 100644
--- a/arch/microblaze/kernel/microblaze_ksyms.c
+++ b/arch/microblaze/kernel/microblaze_ksyms.c
@@ -18,6 +18,7 @@
18#include <linux/io.h> 18#include <linux/io.h>
19#include <asm/page.h> 19#include <asm/page.h>
20#include <asm/system.h> 20#include <asm/system.h>
21#include <linux/ftrace.h>
21#include <linux/uaccess.h> 22#include <linux/uaccess.h>
22 23
23/* 24/*
@@ -47,3 +48,7 @@ extern void __umodsi3(void);
47EXPORT_SYMBOL(__umodsi3); 48EXPORT_SYMBOL(__umodsi3);
48extern char *_ebss; 49extern char *_ebss;
49EXPORT_SYMBOL_GPL(_ebss); 50EXPORT_SYMBOL_GPL(_ebss);
51#ifdef CONFIG_FUNCTION_TRACER
52extern void _mcount(void);
53EXPORT_SYMBOL(_mcount);
54#endif
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c
index c592d475b3d8..812f1bf06c9e 100644
--- a/arch/microblaze/kernel/process.c
+++ b/arch/microblaze/kernel/process.c
@@ -15,6 +15,7 @@
15#include <linux/bitops.h> 15#include <linux/bitops.h>
16#include <asm/system.h> 16#include <asm/system.h>
17#include <asm/pgalloc.h> 17#include <asm/pgalloc.h>
18#include <asm/cacheflush.h>
18 19
19void show_regs(struct pt_regs *regs) 20void show_regs(struct pt_regs *regs)
20{ 21{
diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c
new file mode 100644
index 000000000000..a1721a33042e
--- /dev/null
+++ b/arch/microblaze/kernel/reset.c
@@ -0,0 +1,140 @@
1/*
2 * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
3 * Copyright (C) 2009 PetaLogix
4 *
5 * This file is subject to the terms and conditions of the GNU General Public
6 * License. See the file "COPYING" in the main directory of this archive
7 * for more details.
8 */
9
10#include <linux/init.h>
11#include <linux/of_platform.h>
12#include <asm/prom.h>
13
14/* Trigger specific functions */
15#ifdef CONFIG_GPIOLIB
16
17#include <linux/of_gpio.h>
18
19static int handle; /* reset pin handle */
20static unsigned int reset_val;
21
22static int of_reset_gpio_handle(void)
23{
24 int ret; /* variable which stored handle reset gpio pin */
25 struct device_node *root; /* root node */
26 struct device_node *gpio; /* gpio node */
27 struct of_gpio_chip *of_gc = NULL;
28 enum of_gpio_flags flags ;
29 const void *gpio_spec;
30
31 /* find out root node */
32 root = of_find_node_by_path("/");
33
34 /* give me handle for gpio node to be possible allocate pin */
35 ret = of_parse_phandles_with_args(root, "hard-reset-gpios",
36 "#gpio-cells", 0, &gpio, &gpio_spec);
37 if (ret) {
38 pr_debug("%s: can't parse gpios property\n", __func__);
39 goto err0;
40 }
41
42 of_gc = gpio->data;
43 if (!of_gc) {
44 pr_debug("%s: gpio controller %s isn't registered\n",
45 root->full_name, gpio->full_name);
46 ret = -ENODEV;
47 goto err1;
48 }
49
50 ret = of_gc->xlate(of_gc, root, gpio_spec, &flags);
51 if (ret < 0)
52 goto err1;
53
54 ret += of_gc->gc.base;
55err1:
56 of_node_put(gpio);
57err0:
58 pr_debug("%s exited with status %d\n", __func__, ret);
59 return ret;
60}
61
62void of_platform_reset_gpio_probe(void)
63{
64 int ret;
65 handle = of_reset_gpio_handle();
66
67 if (!gpio_is_valid(handle)) {
68 printk(KERN_INFO "Skipping unavailable RESET gpio %d (%s)\n",
69 handle, "reset");
70 }
71
72 ret = gpio_request(handle, "reset");
73 if (ret < 0) {
74 printk(KERN_INFO "GPIO pin is already allocated\n");
75 return;
76 }
77
78 /* get current setup value */
79 reset_val = gpio_get_value(handle);
80 /* FIXME maybe worth to perform any action */
81 pr_debug("Reset: Gpio output state: 0x%x\n", reset_val);
82
83 /* Setup GPIO as output */
84 ret = gpio_direction_output(handle, 0);
85 if (ret < 0)
86 goto err;
87
88 /* Setup output direction */
89 gpio_set_value(handle, 0);
90
91 printk(KERN_INFO "RESET: Registered gpio device: %d, current val: %d\n",
92 handle, reset_val);
93 return;
94err:
95 gpio_free(handle);
96 return;
97}
98
99
100static void gpio_system_reset(void)
101{
102 gpio_set_value(handle, 1 - reset_val);
103}
104#else
105#define gpio_system_reset() do {} while (0)
106void of_platform_reset_gpio_probe(void)
107{
108 return;
109}
110#endif
111
112void machine_restart(char *cmd)
113{
114 printk(KERN_NOTICE "Machine restart...\n");
115 gpio_system_reset();
116 dump_stack();
117 while (1)
118 ;
119}
120
121void machine_shutdown(void)
122{
123 printk(KERN_NOTICE "Machine shutdown...\n");
124 while (1)
125 ;
126}
127
128void machine_halt(void)
129{
130 printk(KERN_NOTICE "Machine halt...\n");
131 while (1)
132 ;
133}
134
135void machine_power_off(void)
136{
137 printk(KERN_NOTICE "Machine power off...\n");
138 while (1)
139 ;
140}
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index 8c1e0f4dcf18..5372b24ad049 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -52,13 +52,12 @@ void __init setup_arch(char **cmdline_p)
52 /* irq_early_init(); */ 52 /* irq_early_init(); */
53 setup_cpuinfo(); 53 setup_cpuinfo();
54 54
55 __invalidate_icache_all(); 55 microblaze_cache_init();
56 __enable_icache();
57 56
58 __invalidate_dcache_all(); 57 enable_dcache();
59 __enable_dcache();
60 58
61 panic_timeout = 120; 59 invalidate_icache();
60 enable_icache();
62 61
63 setup_memory(); 62 setup_memory();
64 63
@@ -131,6 +130,8 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
131 strlcpy(cmd_line, cmdline, COMMAND_LINE_SIZE); 130 strlcpy(cmd_line, cmdline, COMMAND_LINE_SIZE);
132#endif 131#endif
133 132
133 lockdep_init();
134
134/* initialize device tree for usage in early_printk */ 135/* initialize device tree for usage in early_printk */
135 early_init_devtree((void *)_fdt_start); 136 early_init_devtree((void *)_fdt_start);
136 137
@@ -186,32 +187,3 @@ static int microblaze_debugfs_init(void)
186} 187}
187arch_initcall(microblaze_debugfs_init); 188arch_initcall(microblaze_debugfs_init);
188#endif 189#endif
189
190void machine_restart(char *cmd)
191{
192 printk(KERN_NOTICE "Machine restart...\n");
193 dump_stack();
194 while (1)
195 ;
196}
197
198void machine_shutdown(void)
199{
200 printk(KERN_NOTICE "Machine shutdown...\n");
201 while (1)
202 ;
203}
204
205void machine_halt(void)
206{
207 printk(KERN_NOTICE "Machine halt...\n");
208 while (1)
209 ;
210}
211
212void machine_power_off(void)
213{
214 printk(KERN_NOTICE "Machine power off...\n");
215 while (1)
216 ;
217}
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index 1c80e4fc40ce..d8d3bb396cd6 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -44,7 +44,6 @@
44 44
45asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); 45asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
46 46
47
48asmlinkage long 47asmlinkage long
49sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 48sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
50 struct pt_regs *regs) 49 struct pt_regs *regs)
@@ -176,6 +175,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
176 struct rt_sigframe __user *frame; 175 struct rt_sigframe __user *frame;
177 int err = 0; 176 int err = 0;
178 int signal; 177 int signal;
178 unsigned long address = 0;
179#ifdef CONFIG_MMU
180 pmd_t *pmdp;
181 pte_t *ptep;
182#endif
179 183
180 frame = get_sigframe(ka, regs, sizeof(*frame)); 184 frame = get_sigframe(ka, regs, sizeof(*frame));
181 185
@@ -216,8 +220,29 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
216 Negative 8 offset because return is rtsd r15, 8 */ 220 Negative 8 offset because return is rtsd r15, 8 */
217 regs->r15 = ((unsigned long)frame->tramp)-8; 221 regs->r15 = ((unsigned long)frame->tramp)-8;
218 222
219 __invalidate_cache_sigtramp((unsigned long)frame->tramp); 223 address = ((unsigned long)frame->tramp);
220 224#ifdef CONFIG_MMU
225 pmdp = pmd_offset(pud_offset(
226 pgd_offset(current->mm, address),
227 address), address);
228
229 preempt_disable();
230 ptep = pte_offset_map(pmdp, address);
231 if (pte_present(*ptep)) {
232 address = (unsigned long) page_address(pte_page(*ptep));
233 /* MS: I need add offset in page */
234 address += ((unsigned long)frame->tramp) & ~PAGE_MASK;
235 /* MS address is virtual */
236 address = virt_to_phys(address);
237 invalidate_icache_range(address, address + 8);
238 flush_dcache_range(address, address + 8);
239 }
240 pte_unmap(ptep);
241 preempt_enable();
242#else
243 flush_icache_range(address, address + 8);
244 flush_dcache_range(address, address + 8);
245#endif
221 if (err) 246 if (err)
222 goto give_sigsegv; 247 goto give_sigsegv;
223 248
@@ -233,6 +258,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
233 258
234 set_fs(USER_DS); 259 set_fs(USER_DS);
235 260
261 /* the tracer may want to single-step inside the handler */
262 if (test_thread_flag(TIF_SINGLESTEP))
263 ptrace_notify(SIGTRAP);
264
236#ifdef DEBUG_SIG 265#ifdef DEBUG_SIG
237 printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n", 266 printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
238 current->comm, current->pid, frame, regs->pc); 267 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
index 000000000000..123692f22647
--- /dev/null
+++ b/arch/microblaze/kernel/stacktrace.c
@@ -0,0 +1,65 @@
1/*
2 * Stack trace support for Microblaze.
3 *
4 * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
5 * Copyright (C) 2009 PetaLogix
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11
12#include <linux/sched.h>
13#include <linux/stacktrace.h>
14#include <linux/thread_info.h>
15#include <linux/ptrace.h>
16#include <linux/module.h>
17
18/* FIXME initial support */
19void save_stack_trace(struct stack_trace *trace)
20{
21 unsigned long *sp;
22 unsigned long addr;
23 asm("addik %0, r1, 0" : "=r" (sp));
24
25 while (!kstack_end(sp)) {
26 addr = *sp++;
27 if (__kernel_text_address(addr)) {
28 if (trace->skip > 0)
29 trace->skip--;
30 else
31 trace->entries[trace->nr_entries++] = addr;
32
33 if (trace->nr_entries >= trace->max_entries)
34 break;
35 }
36 }
37}
38EXPORT_SYMBOL_GPL(save_stack_trace);
39
40void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
41{
42 unsigned int *sp;
43 unsigned long addr;
44
45 struct thread_info *ti = task_thread_info(tsk);
46
47 if (tsk == current)
48 asm("addik %0, r1, 0" : "=r" (sp));
49 else
50 sp = (unsigned int *)ti->cpu_context.r1;
51
52 while (!kstack_end(sp)) {
53 addr = *sp++;
54 if (__kernel_text_address(addr)) {
55 if (trace->skip > 0)
56 trace->skip--;
57 else
58 trace->entries[trace->nr_entries++] = addr;
59
60 if (trace->nr_entries >= trace->max_entries)
61 break;
62 }
63 }
64}
65EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S
index b96f365ea6b1..4088be7d4e29 100644
--- a/arch/microblaze/kernel/syscall_table.S
+++ b/arch/microblaze/kernel/syscall_table.S
@@ -183,7 +183,7 @@ ENTRY(sys_call_table)
183 .long sys_rt_sigpending 183 .long sys_rt_sigpending
184 .long sys_rt_sigtimedwait 184 .long sys_rt_sigtimedwait
185 .long sys_rt_sigqueueinfo 185 .long sys_rt_sigqueueinfo
186 .long sys_rt_sigsuspend_wrapper 186 .long sys_rt_sigsuspend
187 .long sys_pread64 /* 180 */ 187 .long sys_pread64 /* 180 */
188 .long sys_pwrite64 188 .long sys_pwrite64
189 .long sys_chown 189 .long sys_chown
@@ -303,7 +303,7 @@ ENTRY(sys_call_table)
303 .long sys_mkdirat 303 .long sys_mkdirat
304 .long sys_mknodat 304 .long sys_mknodat
305 .long sys_fchownat 305 .long sys_fchownat
306 .long sys_ni_syscall 306 .long sys_futimesat
307 .long sys_fstatat64 /* 300 */ 307 .long sys_fstatat64 /* 300 */
308 .long sys_unlinkat 308 .long sys_unlinkat
309 .long sys_renameat 309 .long sys_renameat
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index 5499deae7fa6..ed61b2f17719 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -183,6 +183,31 @@ static cycle_t microblaze_read(struct clocksource *cs)
183 return (cycle_t) (in_be32(TIMER_BASE + TCR1)); 183 return (cycle_t) (in_be32(TIMER_BASE + TCR1));
184} 184}
185 185
186static struct timecounter microblaze_tc = {
187 .cc = NULL,
188};
189
190static cycle_t microblaze_cc_read(const struct cyclecounter *cc)
191{
192 return microblaze_read(NULL);
193}
194
195static struct cyclecounter microblaze_cc = {
196 .read = microblaze_cc_read,
197 .mask = CLOCKSOURCE_MASK(32),
198 .shift = 24,
199};
200
201int __init init_microblaze_timecounter(void)
202{
203 microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
204 microblaze_cc.shift);
205
206 timecounter_init(&microblaze_tc, &microblaze_cc, sched_clock());
207
208 return 0;
209}
210
186static struct clocksource clocksource_microblaze = { 211static struct clocksource clocksource_microblaze = {
187 .name = "microblaze_clocksource", 212 .name = "microblaze_clocksource",
188 .rating = 300, 213 .rating = 300,
@@ -204,6 +229,9 @@ static int __init microblaze_clocksource_init(void)
204 out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT); 229 out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT);
205 /* start timer1 - up counting without interrupt */ 230 /* start timer1 - up counting without interrupt */
206 out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT); 231 out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT);
232
233 /* register timecounter - for ftrace support */
234 init_microblaze_timecounter();
207 return 0; 235 return 0;
208} 236}
209 237
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index e704188d7855..5ef619aad634 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -26,11 +26,12 @@ SECTIONS {
26 _stext = . ; 26 _stext = . ;
27 *(.text .text.*) 27 *(.text .text.*)
28 *(.fixup) 28 *(.fixup)
29 EXIT_TEXT 29 EXIT_TEXT
30 EXIT_CALL 30 EXIT_CALL
31 SCHED_TEXT 31 SCHED_TEXT
32 LOCK_TEXT 32 LOCK_TEXT
33 KPROBES_TEXT 33 KPROBES_TEXT
34 IRQENTRY_TEXT
34 . = ALIGN (4) ; 35 . = ALIGN (4) ;
35 _etext = . ; 36 _etext = . ;
36 } 37 }
@@ -86,6 +87,7 @@ SECTIONS {
86 _KERNEL_SDA_BASE_ = _ssro + (_ssro_size / 2) ; 87 _KERNEL_SDA_BASE_ = _ssro + (_ssro_size / 2) ;
87 } 88 }
88 89
90 . = ALIGN(PAGE_SIZE);
89 __init_begin = .; 91 __init_begin = .;
90 92
91 INIT_TEXT_SECTION(PAGE_SIZE) 93 INIT_TEXT_SECTION(PAGE_SIZE)
diff --git a/arch/microblaze/lib/uaccess.c b/arch/microblaze/lib/uaccess.c
index 8eb9df5a26c9..a853fe089c44 100644
--- a/arch/microblaze/lib/uaccess.c
+++ b/arch/microblaze/lib/uaccess.c
@@ -39,3 +39,10 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
39 __do_strncpy_from_user(dst, src, count, res); 39 __do_strncpy_from_user(dst, src, count, res);
40 return res; 40 return res;
41} 41}
42
43unsigned long __copy_tofrom_user(void __user *to,
44 const void __user *from, unsigned long size)
45{
46 memcpy(to, from, size);
47 return 0;
48}
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c
index a44892e7cd5b..a57cedf36715 100644
--- a/arch/microblaze/mm/init.c
+++ b/arch/microblaze/mm/init.c
@@ -41,6 +41,7 @@ char *klimit = _end;
41 * have available. 41 * have available.
42 */ 42 */
43unsigned long memory_start; 43unsigned long memory_start;
44EXPORT_SYMBOL(memory_start);
44unsigned long memory_end; /* due to mm/nommu.c */ 45unsigned long memory_end; /* due to mm/nommu.c */
45unsigned long memory_size; 46unsigned long memory_size;
46 47
diff --git a/arch/microblaze/mm/pgtable.c b/arch/microblaze/mm/pgtable.c
index 46c4ca5d15c5..2820081b21ab 100644
--- a/arch/microblaze/mm/pgtable.c
+++ b/arch/microblaze/mm/pgtable.c
@@ -144,7 +144,6 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
144 pmd_t *pd; 144 pmd_t *pd;
145 pte_t *pg; 145 pte_t *pg;
146 int err = -ENOMEM; 146 int err = -ENOMEM;
147 /* spin_lock(&init_mm.page_table_lock); */
148 /* Use upper 10 bits of VA to index the first level map */ 147 /* Use upper 10 bits of VA to index the first level map */
149 pd = pmd_offset(pgd_offset_k(va), va); 148 pd = pmd_offset(pgd_offset_k(va), va);
150 /* Use middle 10 bits of VA to index the second-level map */ 149 /* 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)
158 if (mem_init_done) 157 if (mem_init_done)
159 flush_HPTE(0, va, pmd_val(*pd)); 158 flush_HPTE(0, va, pmd_val(*pd));
160 /* flush_HPTE(0, va, pg); */ 159 /* flush_HPTE(0, va, pg); */
161
162 } 160 }
163 /* spin_unlock(&init_mm.page_table_lock); */
164 return err; 161 return err;
165} 162}
166 163
@@ -182,12 +179,6 @@ void __init adjust_total_lowmem(void)
182#endif 179#endif
183} 180}
184 181
185static void show_tmem(unsigned long tmem)
186{
187 volatile unsigned long a;
188 a = a + tmem;
189}
190
191/* 182/*
192 * Map in all of physical memory starting at CONFIG_KERNEL_START. 183 * Map in all of physical memory starting at CONFIG_KERNEL_START.
193 */ 184 */
@@ -197,7 +188,6 @@ void __init mapin_ram(void)
197 188
198 v = CONFIG_KERNEL_START; 189 v = CONFIG_KERNEL_START;
199 p = memory_start; 190 p = memory_start;
200 show_tmem(memory_size);
201 for (s = 0; s < memory_size; s += PAGE_SIZE) { 191 for (s = 0; s < memory_size; s += PAGE_SIZE) {
202 f = _PAGE_PRESENT | _PAGE_ACCESSED | 192 f = _PAGE_PRESENT | _PAGE_ACCESSED |
203 _PAGE_SHARED | _PAGE_HWEXEC; 193 _PAGE_SHARED | _PAGE_HWEXEC;
diff --git a/arch/microblaze/oprofile/Makefile b/arch/microblaze/oprofile/Makefile
new file mode 100644
index 000000000000..0d0348c8af97
--- /dev/null
+++ b/arch/microblaze/oprofile/Makefile
@@ -0,0 +1,13 @@
1#
2# arch/microblaze/oprofile/Makefile
3#
4
5obj-$(CONFIG_OPROFILE) += oprofile.o
6
7DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
8 oprof.o cpu_buffer.o buffer_sync.o \
9 event_buffer.o oprofile_files.o \
10 oprofilefs.o oprofile_stats.o \
11 timer_int.o )
12
13oprofile-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
index 000000000000..def17e59888e
--- /dev/null
+++ b/arch/microblaze/oprofile/microblaze_oprofile.c
@@ -0,0 +1,22 @@
1/*
2 * Microblaze oprofile code
3 *
4 * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
5 * Copyright (C) 2009 PetaLogix
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11
12#include <linux/oprofile.h>
13#include <linux/init.h>
14
15int __init oprofile_arch_init(struct oprofile_operations *ops)
16{
17 return -1;
18}
19
20void oprofile_arch_exit(void)
21{
22}
diff --git a/arch/microblaze/platform/Kconfig.platform b/arch/microblaze/platform/Kconfig.platform
index 8e9b4752d3ff..669c7eec293e 100644
--- a/arch/microblaze/platform/Kconfig.platform
+++ b/arch/microblaze/platform/Kconfig.platform
@@ -53,31 +53,12 @@ config OPT_LIB_FUNCTION
53 53
54config OPT_LIB_ASM 54config OPT_LIB_ASM
55 bool "Optimalized lib function ASM" 55 bool "Optimalized lib function ASM"
56 depends on OPT_LIB_FUNCTION 56 depends on OPT_LIB_FUNCTION && (XILINX_MICROBLAZE0_USE_BARREL = 1)
57 default n 57 default n
58 help 58 help
59 Allows turn on optimalized library function (memcpy and memmove). 59 Allows turn on optimalized library function (memcpy and memmove).
60 Function are written in asm code. 60 Function are written in asm code.
61 61
62# This is still a bit broken - disabling for now JW 20070504
63config ALLOW_EDIT_AUTO
64 bool "Permit Display/edit of Kconfig.auto platform settings"
65 default n
66 help
67 Allows the editing of auto-generated platform settings from
68 the Kconfig.auto file. Obviously this does not change the
69 underlying hardware, so be very careful if you go editing
70 these settings.
71
72 Also, if you enable this, and edit various Kconfig.auto
73 settings, YOUR CHANGES WILL BE LOST if you then disable it
74 again. You have been warned!
75
76 If unsure, say no.
77
78comment "Automatic platform settings from Kconfig.auto"
79 depends on ALLOW_EDIT_AUTO
80
81if PLATFORM_GENERIC=y 62if PLATFORM_GENERIC=y
82 source "arch/microblaze/platform/generic/Kconfig.auto" 63 source "arch/microblaze/platform/generic/Kconfig.auto"
83endif 64endif
diff --git a/arch/microblaze/platform/generic/Kconfig.auto b/arch/microblaze/platform/generic/Kconfig.auto
index fbca22d9c8b9..5d86fc19029d 100644
--- a/arch/microblaze/platform/generic/Kconfig.auto
+++ b/arch/microblaze/platform/generic/Kconfig.auto
@@ -21,7 +21,6 @@
21 21
22# Definitions for MICROBLAZE0 22# Definitions for MICROBLAZE0
23comment "Definitions for MICROBLAZE0" 23comment "Definitions for MICROBLAZE0"
24 depends on ALLOW_EDIT_AUTO
25 24
26config KERNEL_BASE_ADDR 25config KERNEL_BASE_ADDR
27 hex "Physical address where Linux Kernel is" 26 hex "Physical address where Linux Kernel is"
@@ -30,33 +29,33 @@ config KERNEL_BASE_ADDR
30 BASE Address for kernel 29 BASE Address for kernel
31 30
32config XILINX_MICROBLAZE0_FAMILY 31config XILINX_MICROBLAZE0_FAMILY
33 string "Targetted FPGA family" if ALLOW_EDIT_AUTO 32 string "Targetted FPGA family"
34 default "virtex5" 33 default "virtex5"
35 34
36config XILINX_MICROBLAZE0_USE_MSR_INSTR 35config XILINX_MICROBLAZE0_USE_MSR_INSTR
37 int "USE_MSR_INSTR range (0:1)" if ALLOW_EDIT_AUTO 36 int "USE_MSR_INSTR range (0:1)"
38 default 1 37 default 0
39 38
40config XILINX_MICROBLAZE0_USE_PCMP_INSTR 39config XILINX_MICROBLAZE0_USE_PCMP_INSTR
41 int "USE_PCMP_INSTR range (0:1)" if ALLOW_EDIT_AUTO 40 int "USE_PCMP_INSTR range (0:1)"
42 default 1 41 default 0
43 42
44config XILINX_MICROBLAZE0_USE_BARREL 43config XILINX_MICROBLAZE0_USE_BARREL
45 int "USE_BARREL range (0:1)" if ALLOW_EDIT_AUTO 44 int "USE_BARREL range (0:1)"
46 default 1 45 default 0
47 46
48config XILINX_MICROBLAZE0_USE_DIV 47config XILINX_MICROBLAZE0_USE_DIV
49 int "USE_DIV range (0:1)" if ALLOW_EDIT_AUTO 48 int "USE_DIV range (0:1)"
50 default 1 49 default 0
51 50
52config XILINX_MICROBLAZE0_USE_HW_MUL 51config XILINX_MICROBLAZE0_USE_HW_MUL
53 int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)" if ALLOW_EDIT_AUTO 52 int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)"
54 default 2 53 default 0
55 54
56config XILINX_MICROBLAZE0_USE_FPU 55config XILINX_MICROBLAZE0_USE_FPU
57 int "USE_FPU values (0=NONE, 1=BASIC, 2=EXTENDED)" if ALLOW_EDIT_AUTO 56 int "USE_FPU values (0=NONE, 1=BASIC, 2=EXTENDED)"
58 default 2 57 default 0
59 58
60config XILINX_MICROBLAZE0_HW_VER 59config XILINX_MICROBLAZE0_HW_VER
61 string "Core version number" if ALLOW_EDIT_AUTO 60 string "Core version number"
62 default 7.10.d 61 default 7.10.d
diff --git a/arch/microblaze/platform/generic/system.dts b/arch/microblaze/platform/generic/system.dts
index 29993f62b30a..2d5c41767cd0 100644
--- a/arch/microblaze/platform/generic/system.dts
+++ b/arch/microblaze/platform/generic/system.dts
@@ -32,11 +32,16 @@
32 #address-cells = <1>; 32 #address-cells = <1>;
33 #size-cells = <1>; 33 #size-cells = <1>;
34 compatible = "xlnx,microblaze"; 34 compatible = "xlnx,microblaze";
35 hard-reset-gpios = <&LEDs_8Bit 2 1>;
35 model = "testing"; 36 model = "testing";
36 DDR2_SDRAM: memory@90000000 { 37 DDR2_SDRAM: memory@90000000 {
37 device_type = "memory"; 38 device_type = "memory";
38 reg = < 0x90000000 0x10000000 >; 39 reg = < 0x90000000 0x10000000 >;
39 } ; 40 } ;
41 aliases {
42 ethernet0 = &Hard_Ethernet_MAC;
43 serial0 = &RS232_Uart_1;
44 } ;
40 chosen { 45 chosen {
41 bootargs = "console=ttyUL0,115200 highres=on"; 46 bootargs = "console=ttyUL0,115200 highres=on";
42 linux,stdout-path = "/plb@0/serial@84000000"; 47 linux,stdout-path = "/plb@0/serial@84000000";
@@ -127,7 +132,7 @@
127 mb_plb: plb@0 { 132 mb_plb: plb@0 {
128 #address-cells = <1>; 133 #address-cells = <1>;
129 #size-cells = <1>; 134 #size-cells = <1>;
130 compatible = "xlnx,plb-v46-1.03.a", "simple-bus"; 135 compatible = "xlnx,plb-v46-1.03.a", "xlnx,plb-v46-1.00.a", "simple-bus";
131 ranges ; 136 ranges ;
132 FLASH: flash@a0000000 { 137 FLASH: flash@a0000000 {
133 bank-width = <2>; 138 bank-width = <2>;
@@ -214,12 +219,12 @@
214 #size-cells = <1>; 219 #size-cells = <1>;
215 compatible = "xlnx,compound"; 220 compatible = "xlnx,compound";
216 ethernet@81c00000 { 221 ethernet@81c00000 {
217 compatible = "xlnx,xps-ll-temac-1.01.b"; 222 compatible = "xlnx,xps-ll-temac-1.01.b", "xlnx,xps-ll-temac-1.00.a";
218 device_type = "network"; 223 device_type = "network";
219 interrupt-parent = <&xps_intc_0>; 224 interrupt-parent = <&xps_intc_0>;
220 interrupts = < 5 2 >; 225 interrupts = < 5 2 >;
221 llink-connected = <&PIM3>; 226 llink-connected = <&PIM3>;
222 local-mac-address = [ 02 00 00 00 00 00 ]; 227 local-mac-address = [ 00 0a 35 00 00 00 ];
223 reg = < 0x81c00000 0x40 >; 228 reg = < 0x81c00000 0x40 >;
224 xlnx,bus2core-clk-ratio = <0x1>; 229 xlnx,bus2core-clk-ratio = <0x1>;
225 xlnx,phy-type = <0x1>; 230 xlnx,phy-type = <0x1>;
@@ -261,6 +266,33 @@
261 xlnx,is-dual = <0x0>; 266 xlnx,is-dual = <0x0>;
262 xlnx,tri-default = <0xffffffff>; 267 xlnx,tri-default = <0xffffffff>;
263 xlnx,tri-default-2 = <0xffffffff>; 268 xlnx,tri-default-2 = <0xffffffff>;
269 #gpio-cells = <2>;
270 gpio-controller;
271 } ;
272
273 gpio-leds {
274 compatible = "gpio-leds";
275
276 heartbeat {
277 label = "Heartbeat";
278 gpios = <&LEDs_8Bit 4 1>;
279 linux,default-trigger = "heartbeat";
280 };
281
282 yellow {
283 label = "Yellow";
284 gpios = <&LEDs_8Bit 5 1>;
285 };
286
287 red {
288 label = "Red";
289 gpios = <&LEDs_8Bit 6 1>;
290 };
291
292 green {
293 label = "Green";
294 gpios = <&LEDs_8Bit 7 1>;
295 };
264 } ; 296 } ;
265 RS232_Uart_1: serial@84000000 { 297 RS232_Uart_1: serial@84000000 {
266 clock-frequency = <125000000>; 298 clock-frequency = <125000000>;
diff --git a/arch/microblaze/platform/platform.c b/arch/microblaze/platform/platform.c
index 56e0234fa34b..5b89b58c5aed 100644
--- a/arch/microblaze/platform/platform.c
+++ b/arch/microblaze/platform/platform.c
@@ -13,6 +13,7 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/of_platform.h> 14#include <linux/of_platform.h>
15#include <asm/prom.h> 15#include <asm/prom.h>
16#include <asm/setup.h>
16 17
17static struct of_device_id xilinx_of_bus_ids[] __initdata = { 18static struct of_device_id xilinx_of_bus_ids[] __initdata = {
18 { .compatible = "simple-bus", }, 19 { .compatible = "simple-bus", },
@@ -26,6 +27,7 @@ static struct of_device_id xilinx_of_bus_ids[] __initdata = {
26static int __init microblaze_device_probe(void) 27static int __init microblaze_device_probe(void)
27{ 28{
28 of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL); 29 of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL);
30 of_platform_reset_gpio_probe();
29 return 0; 31 return 0;
30} 32}
31device_initcall(microblaze_device_probe); 33device_initcall(microblaze_device_probe);