diff options
Diffstat (limited to 'arch/microblaze')
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" | |||
6 | config MICROBLAZE | 6 | config 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 | ||
12 | config SWAP | 19 | config SWAP |
13 | def_bool n | 20 | def_bool n |
@@ -57,12 +64,24 @@ config GENERIC_GPIO | |||
57 | config GENERIC_CSUM | 64 | config GENERIC_CSUM |
58 | def_bool y | 65 | def_bool y |
59 | 66 | ||
67 | config STACKTRACE_SUPPORT | ||
68 | def_bool y | ||
69 | |||
70 | config LOCKDEP_SUPPORT | ||
71 | def_bool y | ||
72 | |||
73 | config HAVE_LATENCYTOP_SUPPORT | ||
74 | def_bool y | ||
75 | |||
60 | config PCI | 76 | config PCI |
61 | def_bool n | 77 | def_bool n |
62 | 78 | ||
63 | config NO_DMA | 79 | config NO_DMA |
64 | def_bool y | 80 | def_bool y |
65 | 81 | ||
82 | config DTC | ||
83 | def_bool y | ||
84 | |||
66 | source "init/Kconfig" | 85 | source "init/Kconfig" |
67 | 86 | ||
68 | source "kernel/Kconfig.freezer" | 87 | source "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 | ||
4 | menu "Kernel hacking" | 4 | menu "Kernel hacking" |
5 | 5 | ||
6 | config TRACE_IRQFLAGS_SUPPORT | ||
7 | def_bool y | ||
8 | |||
6 | source "lib/Kconfig.debug" | 9 | source "lib/Kconfig.debug" |
7 | 10 | ||
8 | config EARLY_PRINTK | 11 | config 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/ | |||
51 | core-y += arch/microblaze/mm/ | 51 | core-y += arch/microblaze/mm/ |
52 | core-y += arch/microblaze/platform/ | 52 | core-y += arch/microblaze/platform/ |
53 | 53 | ||
54 | drivers-$(CONFIG_OPROFILE) += arch/microblaze/oprofile/ | ||
55 | |||
54 | boot := arch/microblaze/boot | 56 | boot := 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 | ||
5 | MKIMAGE := $(srctree)/scripts/mkuboot.sh | ||
6 | |||
5 | obj-y += linked_dtb.o | 7 | obj-y += linked_dtb.o |
6 | 8 | ||
7 | targets := linux.bin linux.bin.gz simpleImage.% | 9 | targets := linux.bin linux.bin.gz simpleImage.% |
8 | 10 | ||
9 | OBJCOPYFLAGS_linux.bin := -O binary | 11 | OBJCOPYFLAGS := -O binary |
10 | 12 | ||
11 | # Where the DTS files live | 13 | # Where the DTS files live |
12 | dtstree := $(srctree)/$(src)/dts | 14 | dtstree := $(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 | |||
36 | quiet_cmd_strip = STRIP $@ | 39 | quiet_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 | ||
42 | quiet_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 | ||
54 | clean-kernel += linux.bin linux.bin.gz simpleImage.* | 65 | clean-kernel += linux.bin linux.bin.gz simpleImage.* |
55 | 66 | ||
56 | clean-files += *.dtb | 67 | clean-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 | ||
24 | void _enable_icache(void); | ||
25 | void _disable_icache(void); | ||
26 | void _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 | |||
32 | void _enable_dcache(void); | ||
33 | void _disable_dcache(void); | ||
34 | void _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 */ | ||
34 | struct 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 */ | ||
52 | extern struct scache *mbc; | ||
53 | |||
54 | void 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 | |||
68 | struct page; | ||
69 | struct mm_struct; | ||
70 | struct vm_area_struct; | ||
71 | |||
72 | /* see arch/microblaze/kernel/cache.c */ | ||
73 | extern void __invalidate_icache_all(void); | ||
74 | extern void __invalidate_icache_range(unsigned long start, unsigned long end); | ||
75 | extern void __invalidate_icache_page(struct vm_area_struct *vma, | ||
76 | struct page *page); | ||
77 | extern void __invalidate_icache_user_range(struct vm_area_struct *vma, | ||
78 | struct page *page, | ||
79 | unsigned long adr, int len); | ||
80 | extern void __invalidate_cache_sigtramp(unsigned long addr); | ||
81 | |||
82 | extern void __invalidate_dcache_all(void); | ||
83 | extern void __invalidate_dcache_range(unsigned long start, unsigned long end); | ||
84 | extern void __invalidate_dcache_page(struct vm_area_struct *vma, | ||
85 | struct page *page); | ||
86 | extern void __invalidate_dcache_user_range(struct vm_area_struct *vma, | ||
87 | struct page *page, | ||
88 | unsigned long adr, int len); | ||
89 | |||
90 | extern 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) \ |
97 | do { memcpy((dst), (src), (len)); \ | 99 | do { \ |
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)) | 105 | do { \ |
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 { | |||
19 | struct pdev_archdata { | 19 | struct pdev_archdata { |
20 | }; | 20 | }; |
21 | 21 | ||
22 | static inline void dev_archdata_set_node(struct dev_archdata *ad, | ||
23 | struct device_node *np) | ||
24 | { | ||
25 | ad->of_node = np; | ||
26 | } | ||
27 | |||
28 | static inline struct device_node * | ||
29 | dev_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__ | ||
10 | extern void _mcount(void); | ||
11 | extern 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 */ | ||
16 | static inline unsigned long ftrace_call_adjust(unsigned long addr) | ||
17 | { | ||
18 | return addr; | ||
19 | } | ||
20 | |||
21 | struct 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 | |||
31 | static inline int | ||
32 | futex_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 | |||
96 | static inline int | ||
97 | futex_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) \ | 96 | static 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 | |||
112 | static 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 | ||
113 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | 110 | static 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 | ||
199 | extern int do_check_pgt_cache(int, int); | 196 | extern 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); | |||
35 | extern void early_console_reg_tlb_alloc(unsigned int addr); | 35 | extern void early_console_reg_tlb_alloc(unsigned int addr); |
36 | # endif /* CONFIG_MMU */ | 36 | # endif /* CONFIG_MMU */ |
37 | 37 | ||
38 | extern void of_platform_reset_gpio_probe(void); | ||
39 | |||
38 | void time_init(void); | 40 | void time_init(void); |
39 | void init_IRQ(void); | 41 | void init_IRQ(void); |
40 | void machine_early_init(const char *cmdline, unsigned int ram, | 42 | void 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 | |||
19 | struct task_struct; | 21 | struct task_struct; |
20 | struct thread_info; | 22 | struct 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 | ||
275 | extern 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 | |||
297 | extern int __strncpy_user(char *to, const char __user *from, int len); | 294 | extern int __strncpy_user(char *to, const char __user *from, int len); |
298 | extern int __strnlen_user(const char __user *sstr, int len); | 295 | extern 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 | ||
305 | extern 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 | ||
5 | ifdef CONFIG_FUNCTION_TRACER | ||
6 | # Do not trace early boot code and low level code | ||
7 | CFLAGS_REMOVE_timer.o = -pg | ||
8 | CFLAGS_REMOVE_intc.o = -pg | ||
9 | CFLAGS_REMOVE_early_printk.o = -pg | ||
10 | CFLAGS_REMOVE_selfmod.o = -pg | ||
11 | CFLAGS_REMOVE_heartbeat.o = -pg | ||
12 | CFLAGS_REMOVE_ftrace.o = -pg | ||
13 | endif | ||
14 | |||
5 | extra-y := head.o vmlinux.lds | 15 | extra-y := head.o vmlinux.lds |
6 | 16 | ||
7 | obj-y += exceptions.o \ | 17 | obj-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 | ||
12 | obj-y += cpu/ | 22 | obj-y += cpu/ |
13 | 23 | ||
@@ -16,5 +26,7 @@ obj-$(CONFIG_SELFMOD) += selfmod.o | |||
16 | obj-$(CONFIG_HEART_BEAT) += heartbeat.o | 26 | obj-$(CONFIG_HEART_BEAT) += heartbeat.o |
17 | obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o | 27 | obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o |
18 | obj-$(CONFIG_MMU) += misc.o | 28 | obj-$(CONFIG_MMU) += misc.o |
29 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | ||
30 | obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount.o | ||
19 | 31 | ||
20 | obj-y += entry$(MMU).o | 32 | obj-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 | ||
5 | ifdef CONFIG_FUNCTION_TRACER | ||
6 | CFLAGS_REMOVE_cache.o = -pg | ||
7 | endif | ||
8 | |||
5 | EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \ | 9 | EXTRA_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 */ | 18 | static inline void __invalidate_flush_icache(unsigned int addr) |
19 | { | ||
20 | __asm__ __volatile__ ("wic %0, r0;" \ | ||
21 | : : "r" (addr)); | ||
22 | } | ||
23 | |||
24 | static inline void __flush_dcache(unsigned int addr) | ||
25 | { | ||
26 | __asm__ __volatile__ ("wdc.flush %0, r0;" \ | ||
27 | : : "r" (addr)); | ||
28 | } | ||
29 | |||
30 | static 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 | ||
19 | void _enable_icache(void) | 37 | static 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 | : \ | 44 | static 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 | |||
51 | static 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 | ||
43 | void _disable_icache(void) | 60 | static 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; \ | 69 | static 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 | ||
67 | void _invalidate_icache(unsigned int addr) | 81 | static 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 | ||
77 | void _enable_dcache(void) | 93 | static 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 | ||
101 | void _disable_dcache(void) | 105 | static 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 | ||
123 | void _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) \ | ||
120 | do { \ | ||
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) \ | ||
132 | do { \ | ||
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) \ | ||
146 | do { \ | ||
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) \ | ||
160 | do { \ | ||
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) \ | ||
174 | do { \ | ||
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 | |||
187 | static 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 | ||
131 | void __invalidate_icache_all(void) | 206 | static 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 | ||
151 | void __invalidate_icache_range(unsigned long start, unsigned long end) | 226 | static 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 | */ | 237 | static 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 | } | 252 | static 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 | ||
179 | void __invalidate_icache_page(struct vm_area_struct *vma, struct page *page) | 267 | static 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 | ||
184 | void __invalidate_icache_user_range(struct vm_area_struct *vma, | 273 | static 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 | ||
191 | void __invalidate_cache_sigtramp(unsigned long addr) | 288 | static 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 | ||
196 | void __invalidate_dcache_all(void) | 303 | static 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 | ||
218 | void __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 */ | ||
311 | static 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); | 328 | static 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); | 339 | static 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 | ||
245 | void __invalidate_dcache_page(struct vm_area_struct *vma, struct page *page) | 350 | static 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 | |||
369 | static 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 | |||
389 | static 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 | ||
250 | void __invalidate_dcache_user_range(struct vm_area_struct *vma, | 396 | static 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 */ | ||
407 | struct scache *mbc; | ||
408 | |||
409 | /* new wb cache model */ | ||
410 | const 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 */ | ||
426 | const 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 */ | ||
442 | const 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 | |||
457 | const 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 */ | ||
473 | const 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 | |||
488 | const 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 | |||
509 | void 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 | ||
27 | void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) | 33 | void 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 | ||
46 | int cpu_has_pvr(void) | 46 | int 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 */ | ||
213 | 2: | 211 | 2: |
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 | ||
499 | C_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 | |||
510 | C_ENTRY(sys_rt_sigreturn_wrapper): | 503 | C_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. */ |
725 | 1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ | 714 | 1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ |
diff --git a/arch/microblaze/kernel/ftrace.c b/arch/microblaze/kernel/ftrace.c new file mode 100644 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 | */ | ||
22 | void 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(¤t->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 */ | ||
77 | static 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 | |||
104 | static unsigned int recorded; /* if save was or not */ | ||
105 | static 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 | ||
111 | static unsigned int bralid; /* saving whole bralid instruction */ | ||
112 | #endif | ||
113 | |||
114 | int 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 | |||
154 | static int ret_addr; /* initialized as 0 by default */ | ||
155 | |||
156 | /* I believe that first is called ftrace_make_nop before this function */ | ||
157 | int 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 | |||
171 | int __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 | |||
179 | int 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 | ||
210 | unsigned int old_jump; /* saving place for jump instruction */ | ||
211 | |||
212 | int 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 | |||
225 | int 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) | |||
45 | void setup_heartbeat(void) | 45 | void 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 | ||
43 | static void intc_enable_or_unmask(unsigned int irq) | 43 | static 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 | ||
49 | static void intc_disable_or_mask(unsigned int irq) | 57 | static 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'); |
91 | skip: | 91 | skip: |
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 | |||
81 | ENTRY(ftrace_stub) | ||
82 | rtsd r15, 8; | ||
83 | nop; | ||
84 | |||
85 | ENTRY(_mcount) | ||
86 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
87 | ENTRY(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 */ | ||
113 | NOALIGN_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; | ||
124 | end_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 */ | ||
134 | NOALIGN_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; | ||
145 | end: | ||
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 | ||
153 | ENTRY(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); | |||
47 | EXPORT_SYMBOL(__umodsi3); | 48 | EXPORT_SYMBOL(__umodsi3); |
48 | extern char *_ebss; | 49 | extern char *_ebss; |
49 | EXPORT_SYMBOL_GPL(_ebss); | 50 | EXPORT_SYMBOL_GPL(_ebss); |
51 | #ifdef CONFIG_FUNCTION_TRACER | ||
52 | extern void _mcount(void); | ||
53 | EXPORT_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 | ||
19 | void show_regs(struct pt_regs *regs) | 20 | void 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 | |||
19 | static int handle; /* reset pin handle */ | ||
20 | static unsigned int reset_val; | ||
21 | |||
22 | static 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; | ||
55 | err1: | ||
56 | of_node_put(gpio); | ||
57 | err0: | ||
58 | pr_debug("%s exited with status %d\n", __func__, ret); | ||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | void 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; | ||
94 | err: | ||
95 | gpio_free(handle); | ||
96 | return; | ||
97 | } | ||
98 | |||
99 | |||
100 | static 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) | ||
106 | void of_platform_reset_gpio_probe(void) | ||
107 | { | ||
108 | return; | ||
109 | } | ||
110 | #endif | ||
111 | |||
112 | void 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 | |||
121 | void machine_shutdown(void) | ||
122 | { | ||
123 | printk(KERN_NOTICE "Machine shutdown...\n"); | ||
124 | while (1) | ||
125 | ; | ||
126 | } | ||
127 | |||
128 | void machine_halt(void) | ||
129 | { | ||
130 | printk(KERN_NOTICE "Machine halt...\n"); | ||
131 | while (1) | ||
132 | ; | ||
133 | } | ||
134 | |||
135 | void 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 | } |
187 | arch_initcall(microblaze_debugfs_init); | 188 | arch_initcall(microblaze_debugfs_init); |
188 | #endif | 189 | #endif |
189 | |||
190 | void machine_restart(char *cmd) | ||
191 | { | ||
192 | printk(KERN_NOTICE "Machine restart...\n"); | ||
193 | dump_stack(); | ||
194 | while (1) | ||
195 | ; | ||
196 | } | ||
197 | |||
198 | void machine_shutdown(void) | ||
199 | { | ||
200 | printk(KERN_NOTICE "Machine shutdown...\n"); | ||
201 | while (1) | ||
202 | ; | ||
203 | } | ||
204 | |||
205 | void machine_halt(void) | ||
206 | { | ||
207 | printk(KERN_NOTICE "Machine halt...\n"); | ||
208 | while (1) | ||
209 | ; | ||
210 | } | ||
211 | |||
212 | void 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 | ||
45 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); | 45 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); |
46 | 46 | ||
47 | |||
48 | asmlinkage long | 47 | asmlinkage long |
49 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 48 | sys_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 */ | ||
19 | void 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 | } | ||
38 | EXPORT_SYMBOL_GPL(save_stack_trace); | ||
39 | |||
40 | void 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 | } | ||
65 | EXPORT_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 | ||
186 | static struct timecounter microblaze_tc = { | ||
187 | .cc = NULL, | ||
188 | }; | ||
189 | |||
190 | static cycle_t microblaze_cc_read(const struct cyclecounter *cc) | ||
191 | { | ||
192 | return microblaze_read(NULL); | ||
193 | } | ||
194 | |||
195 | static struct cyclecounter microblaze_cc = { | ||
196 | .read = microblaze_cc_read, | ||
197 | .mask = CLOCKSOURCE_MASK(32), | ||
198 | .shift = 24, | ||
199 | }; | ||
200 | |||
201 | int __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(µblaze_tc, µblaze_cc, sched_clock()); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
186 | static struct clocksource clocksource_microblaze = { | 211 | static 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 | |||
43 | unsigned 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 | */ |
43 | unsigned long memory_start; | 43 | unsigned long memory_start; |
44 | EXPORT_SYMBOL(memory_start); | ||
44 | unsigned long memory_end; /* due to mm/nommu.c */ | 45 | unsigned long memory_end; /* due to mm/nommu.c */ |
45 | unsigned long memory_size; | 46 | unsigned 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 | ||
185 | static 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 | |||
5 | obj-$(CONFIG_OPROFILE) += oprofile.o | ||
6 | |||
7 | DRIVER_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 | |||
13 | oprofile-y := $(DRIVER_OBJS) microblaze_oprofile.o | ||
diff --git a/arch/microblaze/oprofile/microblaze_oprofile.c b/arch/microblaze/oprofile/microblaze_oprofile.c new file mode 100644 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 | |||
15 | int __init oprofile_arch_init(struct oprofile_operations *ops) | ||
16 | { | ||
17 | return -1; | ||
18 | } | ||
19 | |||
20 | void 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 | ||
54 | config OPT_LIB_ASM | 54 | config 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 | ||
63 | config 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 | |||
78 | comment "Automatic platform settings from Kconfig.auto" | ||
79 | depends on ALLOW_EDIT_AUTO | ||
80 | |||
81 | if PLATFORM_GENERIC=y | 62 | if PLATFORM_GENERIC=y |
82 | source "arch/microblaze/platform/generic/Kconfig.auto" | 63 | source "arch/microblaze/platform/generic/Kconfig.auto" |
83 | endif | 64 | endif |
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 |
23 | comment "Definitions for MICROBLAZE0" | 23 | comment "Definitions for MICROBLAZE0" |
24 | depends on ALLOW_EDIT_AUTO | ||
25 | 24 | ||
26 | config KERNEL_BASE_ADDR | 25 | config 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 | ||
32 | config XILINX_MICROBLAZE0_FAMILY | 31 | config 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 | ||
36 | config XILINX_MICROBLAZE0_USE_MSR_INSTR | 35 | config 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 | ||
40 | config XILINX_MICROBLAZE0_USE_PCMP_INSTR | 39 | config 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 | ||
44 | config XILINX_MICROBLAZE0_USE_BARREL | 43 | config 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 | ||
48 | config XILINX_MICROBLAZE0_USE_DIV | 47 | config 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 | ||
52 | config XILINX_MICROBLAZE0_USE_HW_MUL | 51 | config 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 | ||
56 | config XILINX_MICROBLAZE0_USE_FPU | 55 | config 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 | ||
60 | config XILINX_MICROBLAZE0_HW_VER | 59 | config 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 | ||
17 | static struct of_device_id xilinx_of_bus_ids[] __initdata = { | 18 | static 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 = { | |||
26 | static int __init microblaze_device_probe(void) | 27 | static 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 | } |
31 | device_initcall(microblaze_device_probe); | 33 | device_initcall(microblaze_device_probe); |