diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 13:58:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 13:58:34 -0400 |
commit | 5872c84027fdcc982e8109ca26d11e1117995745 (patch) | |
tree | f4b59f792a24526c0d2f1ffe3fa8d743b5693f1d /arch/microblaze | |
parent | 39eda2aba6be642b71f2e0ad623dcb09fd9d79cf (diff) | |
parent | 54ea21f0785fd01fb3279d42fe6670cef64cf648 (diff) |
Merge tag 'microblaze-3.12-rc1' of git://git.monstr.eu/linux-2.6-microblaze
Pull Microblaze patches from Michal Simek:
- PCI fixes
- Selfmod code removing
- Intc and timer fixes
- Adding new MB versions
- Minor fixes
* tag 'microblaze-3.12-rc1' of git://git.monstr.eu/linux-2.6-microblaze:
microblaze: Show message when reset gpio is not present
microblaze: Add linux.bin.ub target
microblaze: Add PVR version string for MB v9.0 and v9.1
microblaze: timer: Replace microblaze_ prefix by xilinx_
microblaze: timer: Update header
microblaze: timer: Remove unused header
microblaze: timer: Clear driver init function
microblaze: timer: Use CLKSRC_OF initialization
microblaze: intc: Remove unused header
microblaze: intc: Clean driver init function
microblaze: intc: Using irqchip
microblaze: intc: Update header
microblaze: intc: Remove unused headers
microblaze: Remove selfmodified feature
of/pci: Use of_pci_range_parser
Diffstat (limited to 'arch/microblaze')
-rw-r--r-- | arch/microblaze/Kconfig | 1 | ||||
-rw-r--r-- | arch/microblaze/Makefile | 3 | ||||
-rw-r--r-- | arch/microblaze/boot/Makefile | 7 | ||||
-rw-r--r-- | arch/microblaze/include/asm/selfmod.h | 24 | ||||
-rw-r--r-- | arch/microblaze/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/microblaze/kernel/cpu/cpuinfo.c | 2 | ||||
-rw-r--r-- | arch/microblaze/kernel/intc.c | 85 | ||||
-rw-r--r-- | arch/microblaze/kernel/irq.c | 10 | ||||
-rw-r--r-- | arch/microblaze/kernel/reset.c | 6 | ||||
-rw-r--r-- | arch/microblaze/kernel/selfmod.c | 81 | ||||
-rw-r--r-- | arch/microblaze/kernel/setup.c | 10 | ||||
-rw-r--r-- | arch/microblaze/kernel/timer.c | 186 | ||||
-rw-r--r-- | arch/microblaze/pci/pci-common.c | 106 | ||||
-rw-r--r-- | arch/microblaze/platform/Kconfig.platform | 22 |
14 files changed, 178 insertions, 367 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 4fab52294d98..3f6659cbc969 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig | |||
@@ -29,6 +29,7 @@ config MICROBLAZE | |||
29 | select GENERIC_IDLE_POLL_SETUP | 29 | select GENERIC_IDLE_POLL_SETUP |
30 | select MODULES_USE_ELF_RELA | 30 | select MODULES_USE_ELF_RELA |
31 | select CLONE_BACKWARDS3 | 31 | select CLONE_BACKWARDS3 |
32 | select CLKSRC_OF | ||
32 | 33 | ||
33 | config SWAP | 34 | config SWAP |
34 | def_bool n | 35 | def_bool n |
diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile index 0a603d3ecf24..40350a3c24e9 100644 --- a/arch/microblaze/Makefile +++ b/arch/microblaze/Makefile | |||
@@ -72,7 +72,7 @@ all: linux.bin | |||
72 | archclean: | 72 | archclean: |
73 | $(Q)$(MAKE) $(clean)=$(boot) | 73 | $(Q)$(MAKE) $(clean)=$(boot) |
74 | 74 | ||
75 | linux.bin linux.bin.gz: vmlinux | 75 | linux.bin linux.bin.gz linux.bin.ub: vmlinux |
76 | $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ | 76 | $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ |
77 | 77 | ||
78 | simpleImage.%: vmlinux | 78 | simpleImage.%: vmlinux |
@@ -81,6 +81,7 @@ simpleImage.%: vmlinux | |||
81 | define archhelp | 81 | define archhelp |
82 | echo '* linux.bin - Create raw binary' | 82 | echo '* linux.bin - Create raw binary' |
83 | echo ' linux.bin.gz - Create compressed raw binary' | 83 | echo ' linux.bin.gz - Create compressed raw binary' |
84 | echo ' linux.bin.ub - Create U-Boot wrapped raw binary' | ||
84 | echo ' simpleImage.<dt> - ELF image with $(arch)/boot/dts/<dt>.dts linked in' | 85 | echo ' simpleImage.<dt> - ELF image with $(arch)/boot/dts/<dt>.dts linked in' |
85 | echo ' - stripped elf with fdt blob' | 86 | echo ' - stripped elf with fdt blob' |
86 | echo ' simpleImage.<dt>.unstrip - full ELF image with fdt blob' | 87 | echo ' simpleImage.<dt>.unstrip - full ELF image with fdt blob' |
diff --git a/arch/microblaze/boot/Makefile b/arch/microblaze/boot/Makefile index 80fe54fb7ca3..8e211cc28dac 100644 --- a/arch/microblaze/boot/Makefile +++ b/arch/microblaze/boot/Makefile | |||
@@ -2,12 +2,15 @@ | |||
2 | # arch/microblaze/boot/Makefile | 2 | # arch/microblaze/boot/Makefile |
3 | # | 3 | # |
4 | 4 | ||
5 | targets := linux.bin linux.bin.gz simpleImage.% | 5 | targets := linux.bin linux.bin.gz linux.bin.ub simpleImage.% |
6 | 6 | ||
7 | OBJCOPYFLAGS := -R .note -R .comment -R .note.gnu.build-id -O binary | 7 | OBJCOPYFLAGS := -R .note -R .comment -R .note.gnu.build-id -O binary |
8 | 8 | ||
9 | $(obj)/linux.bin: vmlinux FORCE | 9 | $(obj)/linux.bin: vmlinux FORCE |
10 | $(call if_changed,objcopy) | 10 | $(call if_changed,objcopy) |
11 | @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' | ||
12 | |||
13 | $(obj)/linux.bin.ub: $(obj)/linux.bin FORCE | ||
11 | $(call if_changed,uimage) | 14 | $(call if_changed,uimage) |
12 | @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' | 15 | @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' |
13 | 16 | ||
@@ -22,8 +25,6 @@ quiet_cmd_strip = STRIP $@ | |||
22 | cmd_strip = $(STRIP) -K microblaze_start -K _end -K __log_buf \ | 25 | cmd_strip = $(STRIP) -K microblaze_start -K _end -K __log_buf \ |
23 | -K _fdt_start vmlinux -o $@ | 26 | -K _fdt_start vmlinux -o $@ |
24 | 27 | ||
25 | UIMAGE_IN = $@ | ||
26 | UIMAGE_OUT = $@.ub | ||
27 | UIMAGE_LOADADDR = $(CONFIG_KERNEL_BASE_ADDR) | 28 | UIMAGE_LOADADDR = $(CONFIG_KERNEL_BASE_ADDR) |
28 | 29 | ||
29 | $(obj)/simpleImage.%: vmlinux FORCE | 30 | $(obj)/simpleImage.%: vmlinux FORCE |
diff --git a/arch/microblaze/include/asm/selfmod.h b/arch/microblaze/include/asm/selfmod.h deleted file mode 100644 index c42aff2e6cd0..000000000000 --- a/arch/microblaze/include/asm/selfmod.h +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2008 Michal Simek <monstr@monstr.eu> | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | */ | ||
8 | |||
9 | #ifndef _ASM_MICROBLAZE_SELFMOD_H | ||
10 | #define _ASM_MICROBLAZE_SELFMOD_H | ||
11 | |||
12 | /* | ||
13 | * BARRIER_BASE_ADDR is constant address for selfmod function. | ||
14 | * do not change this value - selfmod function is in | ||
15 | * arch/microblaze/kernel/selfmod.c: selfmod_function() | ||
16 | * | ||
17 | * last 16 bits is used for storing register offset | ||
18 | */ | ||
19 | |||
20 | #define BARRIER_BASE_ADDR 0x1234ff00 | ||
21 | |||
22 | void selfmod_function(const int *arr_fce, const unsigned int base); | ||
23 | |||
24 | #endif /* _ASM_MICROBLAZE_SELFMOD_H */ | ||
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile index 928c950fc14c..5b0e512c78e5 100644 --- a/arch/microblaze/kernel/Makefile +++ b/arch/microblaze/kernel/Makefile | |||
@@ -7,7 +7,6 @@ ifdef CONFIG_FUNCTION_TRACER | |||
7 | CFLAGS_REMOVE_timer.o = -pg | 7 | CFLAGS_REMOVE_timer.o = -pg |
8 | CFLAGS_REMOVE_intc.o = -pg | 8 | CFLAGS_REMOVE_intc.o = -pg |
9 | CFLAGS_REMOVE_early_printk.o = -pg | 9 | CFLAGS_REMOVE_early_printk.o = -pg |
10 | CFLAGS_REMOVE_selfmod.o = -pg | ||
11 | CFLAGS_REMOVE_heartbeat.o = -pg | 10 | CFLAGS_REMOVE_heartbeat.o = -pg |
12 | CFLAGS_REMOVE_ftrace.o = -pg | 11 | CFLAGS_REMOVE_ftrace.o = -pg |
13 | CFLAGS_REMOVE_process.o = -pg | 12 | CFLAGS_REMOVE_process.o = -pg |
@@ -23,7 +22,6 @@ obj-y += dma.o exceptions.o \ | |||
23 | obj-y += cpu/ | 22 | obj-y += cpu/ |
24 | 23 | ||
25 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 24 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
26 | obj-$(CONFIG_SELFMOD) += selfmod.o | ||
27 | obj-$(CONFIG_HEART_BEAT) += heartbeat.o | 25 | obj-$(CONFIG_HEART_BEAT) += heartbeat.o |
28 | obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o | 26 | obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o |
29 | obj-$(CONFIG_MMU) += misc.o | 27 | obj-$(CONFIG_MMU) += misc.o |
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 410398f6db55..c9203b1007aa 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c | |||
@@ -39,6 +39,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = { | |||
39 | {"8.30.a", 0x17}, | 39 | {"8.30.a", 0x17}, |
40 | {"8.40.a", 0x18}, | 40 | {"8.40.a", 0x18}, |
41 | {"8.40.b", 0x19}, | 41 | {"8.40.b", 0x19}, |
42 | {"9.0", 0x1b}, | ||
43 | {"9.1", 0x1d}, | ||
42 | {NULL, 0}, | 44 | {NULL, 0}, |
43 | }; | 45 | }; |
44 | 46 | ||
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index d85fa3a2b0f8..581451ad4687 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> | 2 | * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu> |
3 | * Copyright (C) 2012-2013 Xilinx, Inc. | ||
3 | * Copyright (C) 2007-2009 PetaLogix | 4 | * Copyright (C) 2007-2009 PetaLogix |
4 | * Copyright (C) 2006 Atmark Techno, Inc. | 5 | * Copyright (C) 2006 Atmark Techno, Inc. |
5 | * | 6 | * |
@@ -8,23 +9,15 @@ | |||
8 | * for more details. | 9 | * for more details. |
9 | */ | 10 | */ |
10 | 11 | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/irqdomain.h> | 12 | #include <linux/irqdomain.h> |
13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
14 | #include <asm/page.h> | 14 | #include <linux/of_address.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/bug.h> | 16 | #include <linux/bug.h> |
17 | 17 | ||
18 | #include <asm/prom.h> | 18 | #include "../../drivers/irqchip/irqchip.h" |
19 | #include <asm/irq.h> | ||
20 | 19 | ||
21 | #ifdef CONFIG_SELFMOD_INTC | 20 | static void __iomem *intc_baseaddr; |
22 | #include <asm/selfmod.h> | ||
23 | #define INTC_BASE BARRIER_BASE_ADDR | ||
24 | #else | ||
25 | static unsigned int intc_baseaddr; | ||
26 | #define INTC_BASE intc_baseaddr | ||
27 | #endif | ||
28 | 21 | ||
29 | /* No one else should require these constants, so define them locally here. */ | 22 | /* No one else should require these constants, so define them locally here. */ |
30 | #define ISR 0x00 /* Interrupt Status Register */ | 23 | #define ISR 0x00 /* Interrupt Status Register */ |
@@ -50,21 +43,21 @@ static void intc_enable_or_unmask(struct irq_data *d) | |||
50 | * acks the irq before calling the interrupt handler | 43 | * acks the irq before calling the interrupt handler |
51 | */ | 44 | */ |
52 | if (irqd_is_level_type(d)) | 45 | if (irqd_is_level_type(d)) |
53 | out_be32(INTC_BASE + IAR, mask); | 46 | out_be32(intc_baseaddr + IAR, mask); |
54 | 47 | ||
55 | out_be32(INTC_BASE + SIE, mask); | 48 | out_be32(intc_baseaddr + SIE, mask); |
56 | } | 49 | } |
57 | 50 | ||
58 | static void intc_disable_or_mask(struct irq_data *d) | 51 | static void intc_disable_or_mask(struct irq_data *d) |
59 | { | 52 | { |
60 | pr_debug("disable: %ld\n", d->hwirq); | 53 | pr_debug("disable: %ld\n", d->hwirq); |
61 | out_be32(INTC_BASE + CIE, 1 << d->hwirq); | 54 | out_be32(intc_baseaddr + CIE, 1 << d->hwirq); |
62 | } | 55 | } |
63 | 56 | ||
64 | static void intc_ack(struct irq_data *d) | 57 | static void intc_ack(struct irq_data *d) |
65 | { | 58 | { |
66 | pr_debug("ack: %ld\n", d->hwirq); | 59 | pr_debug("ack: %ld\n", d->hwirq); |
67 | out_be32(INTC_BASE + IAR, 1 << d->hwirq); | 60 | out_be32(intc_baseaddr + IAR, 1 << d->hwirq); |
68 | } | 61 | } |
69 | 62 | ||
70 | static void intc_mask_ack(struct irq_data *d) | 63 | static void intc_mask_ack(struct irq_data *d) |
@@ -72,8 +65,8 @@ static void intc_mask_ack(struct irq_data *d) | |||
72 | unsigned long mask = 1 << d->hwirq; | 65 | unsigned long mask = 1 << d->hwirq; |
73 | 66 | ||
74 | pr_debug("disable_and_ack: %ld\n", d->hwirq); | 67 | pr_debug("disable_and_ack: %ld\n", d->hwirq); |
75 | out_be32(INTC_BASE + CIE, mask); | 68 | out_be32(intc_baseaddr + CIE, mask); |
76 | out_be32(INTC_BASE + IAR, mask); | 69 | out_be32(intc_baseaddr + IAR, mask); |
77 | } | 70 | } |
78 | 71 | ||
79 | static struct irq_chip intc_dev = { | 72 | static struct irq_chip intc_dev = { |
@@ -90,7 +83,7 @@ unsigned int get_irq(void) | |||
90 | { | 83 | { |
91 | unsigned int hwirq, irq = -1; | 84 | unsigned int hwirq, irq = -1; |
92 | 85 | ||
93 | hwirq = in_be32(INTC_BASE + IVR); | 86 | hwirq = in_be32(intc_baseaddr + IVR); |
94 | if (hwirq != -1U) | 87 | if (hwirq != -1U) |
95 | irq = irq_find_mapping(root_domain, hwirq); | 88 | irq = irq_find_mapping(root_domain, hwirq); |
96 | 89 | ||
@@ -120,40 +113,32 @@ static const struct irq_domain_ops xintc_irq_domain_ops = { | |||
120 | .map = xintc_map, | 113 | .map = xintc_map, |
121 | }; | 114 | }; |
122 | 115 | ||
123 | void __init init_IRQ(void) | 116 | static int __init xilinx_intc_of_init(struct device_node *intc, |
117 | struct device_node *parent) | ||
124 | { | 118 | { |
125 | u32 nr_irq, intr_mask; | 119 | u32 nr_irq, intr_mask; |
126 | struct device_node *intc = NULL; | 120 | int ret; |
127 | #ifdef CONFIG_SELFMOD_INTC | 121 | |
128 | unsigned int intc_baseaddr = 0; | 122 | intc_baseaddr = of_iomap(intc, 0); |
129 | static int arr_func[] = { | 123 | BUG_ON(!intc_baseaddr); |
130 | (int)&get_irq, | 124 | |
131 | (int)&intc_enable_or_unmask, | 125 | ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq); |
132 | (int)&intc_disable_or_mask, | 126 | if (ret < 0) { |
133 | (int)&intc_mask_ack, | 127 | pr_err("%s: unable to read xlnx,num-intr-inputs\n", __func__); |
134 | (int)&intc_ack, | 128 | return -EINVAL; |
135 | (int)&intc_end, | 129 | } |
136 | 0 | 130 | |
137 | }; | 131 | ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &intr_mask); |
138 | #endif | 132 | if (ret < 0) { |
139 | intc = of_find_compatible_node(NULL, NULL, "xlnx,xps-intc-1.00.a"); | 133 | pr_err("%s: unable to read xlnx,kind-of-intr\n", __func__); |
140 | BUG_ON(!intc); | 134 | return -EINVAL; |
141 | 135 | } | |
142 | intc_baseaddr = be32_to_cpup(of_get_property(intc, "reg", NULL)); | 136 | |
143 | intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE); | ||
144 | nr_irq = be32_to_cpup(of_get_property(intc, | ||
145 | "xlnx,num-intr-inputs", NULL)); | ||
146 | |||
147 | intr_mask = | ||
148 | be32_to_cpup(of_get_property(intc, "xlnx,kind-of-intr", NULL)); | ||
149 | if (intr_mask > (u32)((1ULL << nr_irq) - 1)) | 137 | if (intr_mask > (u32)((1ULL << nr_irq) - 1)) |
150 | pr_info(" ERROR: Mismatch in kind-of-intr param\n"); | 138 | pr_info(" ERROR: Mismatch in kind-of-intr param\n"); |
151 | 139 | ||
152 | #ifdef CONFIG_SELFMOD_INTC | 140 | pr_info("%s: num_irq=%d, edge=0x%x\n", |
153 | selfmod_function((int *) arr_func, intc_baseaddr); | 141 | intc->full_name, nr_irq, intr_mask); |
154 | #endif | ||
155 | pr_info("%s #0 at 0x%08x, num_irq=%d, edge=0x%x\n", | ||
156 | intc->name, intc_baseaddr, nr_irq, intr_mask); | ||
157 | 142 | ||
158 | /* | 143 | /* |
159 | * Disable all external interrupts until they are | 144 | * Disable all external interrupts until they are |
@@ -174,4 +159,8 @@ void __init init_IRQ(void) | |||
174 | (void *)intr_mask); | 159 | (void *)intr_mask); |
175 | 160 | ||
176 | irq_set_default_host(root_domain); | 161 | irq_set_default_host(root_domain); |
162 | |||
163 | return 0; | ||
177 | } | 164 | } |
165 | |||
166 | IRQCHIP_DECLARE(xilinx_intc, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init); | ||
diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c index ace700afbfdf..11e24de91aa4 100644 --- a/arch/microblaze/kernel/irq.c +++ b/arch/microblaze/kernel/irq.c | |||
@@ -17,10 +17,8 @@ | |||
17 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
18 | #include <linux/kernel_stat.h> | 18 | #include <linux/kernel_stat.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | #include <linux/irqchip.h> | ||
20 | #include <linux/of_irq.h> | 21 | #include <linux/of_irq.h> |
21 | #include <linux/export.h> | ||
22 | |||
23 | #include <asm/prom.h> | ||
24 | 22 | ||
25 | static u32 concurrent_irq; | 23 | static u32 concurrent_irq; |
26 | 24 | ||
@@ -47,3 +45,9 @@ next_irq: | |||
47 | set_irq_regs(old_regs); | 45 | set_irq_regs(old_regs); |
48 | trace_hardirqs_on(); | 46 | trace_hardirqs_on(); |
49 | } | 47 | } |
48 | |||
49 | void __init init_IRQ(void) | ||
50 | { | ||
51 | /* process the entire interrupt tree in one go */ | ||
52 | irqchip_init(); | ||
53 | } | ||
diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c index 2e5079ab53d2..fbe58c6554a8 100644 --- a/arch/microblaze/kernel/reset.c +++ b/arch/microblaze/kernel/reset.c | |||
@@ -67,7 +67,11 @@ static void gpio_system_reset(void) | |||
67 | pr_notice("Reset GPIO unavailable - halting!\n"); | 67 | pr_notice("Reset GPIO unavailable - halting!\n"); |
68 | } | 68 | } |
69 | #else | 69 | #else |
70 | #define gpio_system_reset() do {} while (0) | 70 | static void gpio_system_reset(void) |
71 | { | ||
72 | pr_notice("No reset GPIO present - halting!\n"); | ||
73 | } | ||
74 | |||
71 | void of_platform_reset_gpio_probe(void) | 75 | void of_platform_reset_gpio_probe(void) |
72 | { | 76 | { |
73 | return; | 77 | return; |
diff --git a/arch/microblaze/kernel/selfmod.c b/arch/microblaze/kernel/selfmod.c deleted file mode 100644 index 89508bdc9f3c..000000000000 --- a/arch/microblaze/kernel/selfmod.c +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-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/interrupt.h> | ||
11 | #include <asm/selfmod.h> | ||
12 | |||
13 | #undef DEBUG | ||
14 | |||
15 | #if __GNUC__ > 3 | ||
16 | #error GCC 4 unsupported SELFMOD. Please disable SELFMOD from menuconfig. | ||
17 | #endif | ||
18 | |||
19 | #define OPCODE_IMM 0xB0000000 | ||
20 | #define OPCODE_LWI 0xE8000000 | ||
21 | #define OPCODE_LWI_MASK 0xEC000000 | ||
22 | #define OPCODE_RTSD 0xB60F0008 /* return from func: rtsd r15, 8 */ | ||
23 | #define OPCODE_ADDIK 0x30000000 | ||
24 | #define OPCODE_ADDIK_MASK 0xFC000000 | ||
25 | |||
26 | #define IMM_BASE (OPCODE_IMM | (BARRIER_BASE_ADDR >> 16)) | ||
27 | #define LWI_BASE (OPCODE_LWI | (BARRIER_BASE_ADDR & 0x0000ff00)) | ||
28 | #define LWI_BASE_MASK (OPCODE_LWI_MASK | (BARRIER_BASE_ADDR & 0x0000ff00)) | ||
29 | #define ADDIK_BASE (OPCODE_ADDIK | (BARRIER_BASE_ADDR & 0x0000ff00)) | ||
30 | #define ADDIK_BASE_MASK (OPCODE_ADDIK_MASK | (BARRIER_BASE_ADDR & 0x0000ff00)) | ||
31 | |||
32 | #define MODIFY_INSTR { \ | ||
33 | pr_debug("%s: curr instr, (%d):0x%x, next(%d):0x%x\n", \ | ||
34 | __func__, i, addr[i], i + 1, addr[i + 1]); \ | ||
35 | addr[i] = OPCODE_IMM + (base >> 16); \ | ||
36 | /* keep instruction opcode and add only last 16bits */ \ | ||
37 | addr[i + 1] = (addr[i + 1] & 0xffff00ff) + (base & 0xffff); \ | ||
38 | __invalidate_icache(addr[i]); \ | ||
39 | __invalidate_icache(addr[i + 1]); \ | ||
40 | pr_debug("%s: hack instr, (%d):0x%x, next(%d):0x%x\n", \ | ||
41 | __func__, i, addr[i], i + 1, addr[i + 1]); } | ||
42 | |||
43 | /* NOTE | ||
44 | * self-modified part of code for improvement of interrupt controller | ||
45 | * save instruction in interrupt rutine | ||
46 | */ | ||
47 | void selfmod_function(const int *arr_fce, const unsigned int base) | ||
48 | { | ||
49 | unsigned int flags, i, j, *addr = NULL; | ||
50 | |||
51 | local_irq_save(flags); | ||
52 | __disable_icache(); | ||
53 | |||
54 | /* zero terminated array */ | ||
55 | for (j = 0; arr_fce[j] != 0; j++) { | ||
56 | /* get start address of function */ | ||
57 | addr = (unsigned int *) arr_fce[j]; | ||
58 | pr_debug("%s: func(%d) at 0x%x\n", | ||
59 | __func__, j, (unsigned int) addr); | ||
60 | for (i = 0; ; i++) { | ||
61 | pr_debug("%s: instruction code at %d: 0x%x\n", | ||
62 | __func__, i, addr[i]); | ||
63 | if (addr[i] == IMM_BASE) { | ||
64 | /* detecting of lwi (0xE8) or swi (0xF8) instr | ||
65 | * I can detect both opcode with one mask */ | ||
66 | if ((addr[i + 1] & LWI_BASE_MASK) == LWI_BASE) { | ||
67 | MODIFY_INSTR; | ||
68 | } else /* detection addik for ack */ | ||
69 | if ((addr[i + 1] & ADDIK_BASE_MASK) == | ||
70 | ADDIK_BASE) { | ||
71 | MODIFY_INSTR; | ||
72 | } | ||
73 | } else if (addr[i] == OPCODE_RTSD) { | ||
74 | /* return from function means end of function */ | ||
75 | pr_debug("%s: end of array %d\n", __func__, i); | ||
76 | break; | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | local_irq_restore(flags); | ||
81 | } /* end of self-modified code */ | ||
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index 0263da7b83dd..0775e036c526 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c | |||
@@ -9,6 +9,7 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/clocksource.h> | ||
12 | #include <linux/string.h> | 13 | #include <linux/string.h> |
13 | #include <linux/seq_file.h> | 14 | #include <linux/seq_file.h> |
14 | #include <linux/cpu.h> | 15 | #include <linux/cpu.h> |
@@ -68,10 +69,6 @@ void __init setup_arch(char **cmdline_p) | |||
68 | 69 | ||
69 | xilinx_pci_init(); | 70 | xilinx_pci_init(); |
70 | 71 | ||
71 | #if defined(CONFIG_SELFMOD_INTC) || defined(CONFIG_SELFMOD_TIMER) | ||
72 | pr_notice("Self modified code enable\n"); | ||
73 | #endif | ||
74 | |||
75 | #ifdef CONFIG_VT | 72 | #ifdef CONFIG_VT |
76 | #if defined(CONFIG_XILINX_CONSOLE) | 73 | #if defined(CONFIG_XILINX_CONSOLE) |
77 | conswitchp = &xil_con; | 74 | conswitchp = &xil_con; |
@@ -196,6 +193,11 @@ void __init machine_early_init(const char *cmdline, unsigned int ram, | |||
196 | per_cpu(CURRENT_SAVE, 0) = (unsigned long)current; | 193 | per_cpu(CURRENT_SAVE, 0) = (unsigned long)current; |
197 | } | 194 | } |
198 | 195 | ||
196 | void __init time_init(void) | ||
197 | { | ||
198 | clocksource_of_init(); | ||
199 | } | ||
200 | |||
199 | #ifdef CONFIG_DEBUG_FS | 201 | #ifdef CONFIG_DEBUG_FS |
200 | struct dentry *of_debugfs_root; | 202 | struct dentry *of_debugfs_root; |
201 | 203 | ||
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index aec5020a6e31..e4b3f33ef34c 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> | 2 | * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu> |
3 | * Copyright (C) 2012-2013 Xilinx, Inc. | ||
3 | * Copyright (C) 2007-2009 PetaLogix | 4 | * Copyright (C) 2007-2009 PetaLogix |
4 | * Copyright (C) 2006 Atmark Techno, Inc. | 5 | * Copyright (C) 2006 Atmark Techno, Inc. |
5 | * | 6 | * |
@@ -8,34 +9,16 @@ | |||
8 | * for more details. | 9 | * for more details. |
9 | */ | 10 | */ |
10 | 11 | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/param.h> | ||
14 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
15 | #include <linux/profile.h> | ||
16 | #include <linux/irq.h> | ||
17 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
18 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
19 | #include <linux/spinlock.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
22 | #include <linux/clocksource.h> | ||
23 | #include <linux/clockchips.h> | 16 | #include <linux/clockchips.h> |
24 | #include <linux/io.h> | 17 | #include <linux/of_address.h> |
25 | #include <linux/bug.h> | ||
26 | #include <asm/cpuinfo.h> | 18 | #include <asm/cpuinfo.h> |
27 | #include <asm/setup.h> | ||
28 | #include <asm/prom.h> | ||
29 | #include <asm/irq.h> | ||
30 | #include <linux/cnt32_to_63.h> | 19 | #include <linux/cnt32_to_63.h> |
31 | 20 | ||
32 | #ifdef CONFIG_SELFMOD_TIMER | 21 | static void __iomem *timer_baseaddr; |
33 | #include <asm/selfmod.h> | ||
34 | #define TIMER_BASE BARRIER_BASE_ADDR | ||
35 | #else | ||
36 | static unsigned int timer_baseaddr; | ||
37 | #define TIMER_BASE timer_baseaddr | ||
38 | #endif | ||
39 | 22 | ||
40 | static unsigned int freq_div_hz; | 23 | static unsigned int freq_div_hz; |
41 | static unsigned int timer_clock_freq; | 24 | static unsigned int timer_clock_freq; |
@@ -59,19 +42,21 @@ static unsigned int timer_clock_freq; | |||
59 | #define TCSR_PWMA (1<<9) | 42 | #define TCSR_PWMA (1<<9) |
60 | #define TCSR_ENALL (1<<10) | 43 | #define TCSR_ENALL (1<<10) |
61 | 44 | ||
62 | static inline void microblaze_timer0_stop(void) | 45 | static inline void xilinx_timer0_stop(void) |
63 | { | 46 | { |
64 | out_be32(TIMER_BASE + TCSR0, in_be32(TIMER_BASE + TCSR0) & ~TCSR_ENT); | 47 | out_be32(timer_baseaddr + TCSR0, |
48 | in_be32(timer_baseaddr + TCSR0) & ~TCSR_ENT); | ||
65 | } | 49 | } |
66 | 50 | ||
67 | static inline void microblaze_timer0_start_periodic(unsigned long load_val) | 51 | static inline void xilinx_timer0_start_periodic(unsigned long load_val) |
68 | { | 52 | { |
69 | if (!load_val) | 53 | if (!load_val) |
70 | load_val = 1; | 54 | load_val = 1; |
71 | out_be32(TIMER_BASE + TLR0, load_val); /* loading value to timer reg */ | 55 | /* loading value to timer reg */ |
56 | out_be32(timer_baseaddr + TLR0, load_val); | ||
72 | 57 | ||
73 | /* load the initial value */ | 58 | /* load the initial value */ |
74 | out_be32(TIMER_BASE + TCSR0, TCSR_LOAD); | 59 | out_be32(timer_baseaddr + TCSR0, TCSR_LOAD); |
75 | 60 | ||
76 | /* see timer data sheet for detail | 61 | /* see timer data sheet for detail |
77 | * !ENALL - don't enable 'em all | 62 | * !ENALL - don't enable 'em all |
@@ -86,38 +71,39 @@ static inline void microblaze_timer0_start_periodic(unsigned long load_val) | |||
86 | * UDT - set the timer as down counter | 71 | * UDT - set the timer as down counter |
87 | * !MDT0 - generate mode | 72 | * !MDT0 - generate mode |
88 | */ | 73 | */ |
89 | out_be32(TIMER_BASE + TCSR0, | 74 | out_be32(timer_baseaddr + TCSR0, |
90 | TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT); | 75 | TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT); |
91 | } | 76 | } |
92 | 77 | ||
93 | static inline void microblaze_timer0_start_oneshot(unsigned long load_val) | 78 | static inline void xilinx_timer0_start_oneshot(unsigned long load_val) |
94 | { | 79 | { |
95 | if (!load_val) | 80 | if (!load_val) |
96 | load_val = 1; | 81 | load_val = 1; |
97 | out_be32(TIMER_BASE + TLR0, load_val); /* loading value to timer reg */ | 82 | /* loading value to timer reg */ |
83 | out_be32(timer_baseaddr + TLR0, load_val); | ||
98 | 84 | ||
99 | /* load the initial value */ | 85 | /* load the initial value */ |
100 | out_be32(TIMER_BASE + TCSR0, TCSR_LOAD); | 86 | out_be32(timer_baseaddr + TCSR0, TCSR_LOAD); |
101 | 87 | ||
102 | out_be32(TIMER_BASE + TCSR0, | 88 | out_be32(timer_baseaddr + TCSR0, |
103 | TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT); | 89 | TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT); |
104 | } | 90 | } |
105 | 91 | ||
106 | static int microblaze_timer_set_next_event(unsigned long delta, | 92 | static int xilinx_timer_set_next_event(unsigned long delta, |
107 | struct clock_event_device *dev) | 93 | struct clock_event_device *dev) |
108 | { | 94 | { |
109 | pr_debug("%s: next event, delta %x\n", __func__, (u32)delta); | 95 | pr_debug("%s: next event, delta %x\n", __func__, (u32)delta); |
110 | microblaze_timer0_start_oneshot(delta); | 96 | xilinx_timer0_start_oneshot(delta); |
111 | return 0; | 97 | return 0; |
112 | } | 98 | } |
113 | 99 | ||
114 | static void microblaze_timer_set_mode(enum clock_event_mode mode, | 100 | static void xilinx_timer_set_mode(enum clock_event_mode mode, |
115 | struct clock_event_device *evt) | 101 | struct clock_event_device *evt) |
116 | { | 102 | { |
117 | switch (mode) { | 103 | switch (mode) { |
118 | case CLOCK_EVT_MODE_PERIODIC: | 104 | case CLOCK_EVT_MODE_PERIODIC: |
119 | pr_info("%s: periodic\n", __func__); | 105 | pr_info("%s: periodic\n", __func__); |
120 | microblaze_timer0_start_periodic(freq_div_hz); | 106 | xilinx_timer0_start_periodic(freq_div_hz); |
121 | break; | 107 | break; |
122 | case CLOCK_EVT_MODE_ONESHOT: | 108 | case CLOCK_EVT_MODE_ONESHOT: |
123 | pr_info("%s: oneshot\n", __func__); | 109 | pr_info("%s: oneshot\n", __func__); |
@@ -127,7 +113,7 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode, | |||
127 | break; | 113 | break; |
128 | case CLOCK_EVT_MODE_SHUTDOWN: | 114 | case CLOCK_EVT_MODE_SHUTDOWN: |
129 | pr_info("%s: shutdown\n", __func__); | 115 | pr_info("%s: shutdown\n", __func__); |
130 | microblaze_timer0_stop(); | 116 | xilinx_timer0_stop(); |
131 | break; | 117 | break; |
132 | case CLOCK_EVT_MODE_RESUME: | 118 | case CLOCK_EVT_MODE_RESUME: |
133 | pr_info("%s: resume\n", __func__); | 119 | pr_info("%s: resume\n", __func__); |
@@ -135,23 +121,23 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode, | |||
135 | } | 121 | } |
136 | } | 122 | } |
137 | 123 | ||
138 | static struct clock_event_device clockevent_microblaze_timer = { | 124 | static struct clock_event_device clockevent_xilinx_timer = { |
139 | .name = "microblaze_clockevent", | 125 | .name = "xilinx_clockevent", |
140 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, | 126 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, |
141 | .shift = 8, | 127 | .shift = 8, |
142 | .rating = 300, | 128 | .rating = 300, |
143 | .set_next_event = microblaze_timer_set_next_event, | 129 | .set_next_event = xilinx_timer_set_next_event, |
144 | .set_mode = microblaze_timer_set_mode, | 130 | .set_mode = xilinx_timer_set_mode, |
145 | }; | 131 | }; |
146 | 132 | ||
147 | static inline void timer_ack(void) | 133 | static inline void timer_ack(void) |
148 | { | 134 | { |
149 | out_be32(TIMER_BASE + TCSR0, in_be32(TIMER_BASE + TCSR0)); | 135 | out_be32(timer_baseaddr + TCSR0, in_be32(timer_baseaddr + TCSR0)); |
150 | } | 136 | } |
151 | 137 | ||
152 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | 138 | static irqreturn_t timer_interrupt(int irq, void *dev_id) |
153 | { | 139 | { |
154 | struct clock_event_device *evt = &clockevent_microblaze_timer; | 140 | struct clock_event_device *evt = &clockevent_xilinx_timer; |
155 | #ifdef CONFIG_HEART_BEAT | 141 | #ifdef CONFIG_HEART_BEAT |
156 | heartbeat(); | 142 | heartbeat(); |
157 | #endif | 143 | #endif |
@@ -164,73 +150,74 @@ static struct irqaction timer_irqaction = { | |||
164 | .handler = timer_interrupt, | 150 | .handler = timer_interrupt, |
165 | .flags = IRQF_DISABLED | IRQF_TIMER, | 151 | .flags = IRQF_DISABLED | IRQF_TIMER, |
166 | .name = "timer", | 152 | .name = "timer", |
167 | .dev_id = &clockevent_microblaze_timer, | 153 | .dev_id = &clockevent_xilinx_timer, |
168 | }; | 154 | }; |
169 | 155 | ||
170 | static __init void microblaze_clockevent_init(void) | 156 | static __init void xilinx_clockevent_init(void) |
171 | { | 157 | { |
172 | clockevent_microblaze_timer.mult = | 158 | clockevent_xilinx_timer.mult = |
173 | div_sc(timer_clock_freq, NSEC_PER_SEC, | 159 | div_sc(timer_clock_freq, NSEC_PER_SEC, |
174 | clockevent_microblaze_timer.shift); | 160 | clockevent_xilinx_timer.shift); |
175 | clockevent_microblaze_timer.max_delta_ns = | 161 | clockevent_xilinx_timer.max_delta_ns = |
176 | clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer); | 162 | clockevent_delta2ns((u32)~0, &clockevent_xilinx_timer); |
177 | clockevent_microblaze_timer.min_delta_ns = | 163 | clockevent_xilinx_timer.min_delta_ns = |
178 | clockevent_delta2ns(1, &clockevent_microblaze_timer); | 164 | clockevent_delta2ns(1, &clockevent_xilinx_timer); |
179 | clockevent_microblaze_timer.cpumask = cpumask_of(0); | 165 | clockevent_xilinx_timer.cpumask = cpumask_of(0); |
180 | clockevents_register_device(&clockevent_microblaze_timer); | 166 | clockevents_register_device(&clockevent_xilinx_timer); |
181 | } | 167 | } |
182 | 168 | ||
183 | static cycle_t microblaze_read(struct clocksource *cs) | 169 | static cycle_t xilinx_read(struct clocksource *cs) |
184 | { | 170 | { |
185 | /* reading actual value of timer 1 */ | 171 | /* reading actual value of timer 1 */ |
186 | return (cycle_t) (in_be32(TIMER_BASE + TCR1)); | 172 | return (cycle_t) (in_be32(timer_baseaddr + TCR1)); |
187 | } | 173 | } |
188 | 174 | ||
189 | static struct timecounter microblaze_tc = { | 175 | static struct timecounter xilinx_tc = { |
190 | .cc = NULL, | 176 | .cc = NULL, |
191 | }; | 177 | }; |
192 | 178 | ||
193 | static cycle_t microblaze_cc_read(const struct cyclecounter *cc) | 179 | static cycle_t xilinx_cc_read(const struct cyclecounter *cc) |
194 | { | 180 | { |
195 | return microblaze_read(NULL); | 181 | return xilinx_read(NULL); |
196 | } | 182 | } |
197 | 183 | ||
198 | static struct cyclecounter microblaze_cc = { | 184 | static struct cyclecounter xilinx_cc = { |
199 | .read = microblaze_cc_read, | 185 | .read = xilinx_cc_read, |
200 | .mask = CLOCKSOURCE_MASK(32), | 186 | .mask = CLOCKSOURCE_MASK(32), |
201 | .shift = 8, | 187 | .shift = 8, |
202 | }; | 188 | }; |
203 | 189 | ||
204 | static int __init init_microblaze_timecounter(void) | 190 | static int __init init_xilinx_timecounter(void) |
205 | { | 191 | { |
206 | microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC, | 192 | xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC, |
207 | microblaze_cc.shift); | 193 | xilinx_cc.shift); |
208 | 194 | ||
209 | timecounter_init(µblaze_tc, µblaze_cc, sched_clock()); | 195 | timecounter_init(&xilinx_tc, &xilinx_cc, sched_clock()); |
210 | 196 | ||
211 | return 0; | 197 | return 0; |
212 | } | 198 | } |
213 | 199 | ||
214 | static struct clocksource clocksource_microblaze = { | 200 | static struct clocksource clocksource_microblaze = { |
215 | .name = "microblaze_clocksource", | 201 | .name = "xilinx_clocksource", |
216 | .rating = 300, | 202 | .rating = 300, |
217 | .read = microblaze_read, | 203 | .read = xilinx_read, |
218 | .mask = CLOCKSOURCE_MASK(32), | 204 | .mask = CLOCKSOURCE_MASK(32), |
219 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 205 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
220 | }; | 206 | }; |
221 | 207 | ||
222 | static int __init microblaze_clocksource_init(void) | 208 | static int __init xilinx_clocksource_init(void) |
223 | { | 209 | { |
224 | if (clocksource_register_hz(&clocksource_microblaze, timer_clock_freq)) | 210 | if (clocksource_register_hz(&clocksource_microblaze, timer_clock_freq)) |
225 | panic("failed to register clocksource"); | 211 | panic("failed to register clocksource"); |
226 | 212 | ||
227 | /* stop timer1 */ | 213 | /* stop timer1 */ |
228 | out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT); | 214 | out_be32(timer_baseaddr + TCSR1, |
215 | in_be32(timer_baseaddr + TCSR1) & ~TCSR_ENT); | ||
229 | /* start timer1 - up counting without interrupt */ | 216 | /* start timer1 - up counting without interrupt */ |
230 | out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT); | 217 | out_be32(timer_baseaddr + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT); |
231 | 218 | ||
232 | /* register timecounter - for ftrace support */ | 219 | /* register timecounter - for ftrace support */ |
233 | init_microblaze_timecounter(); | 220 | init_xilinx_timecounter(); |
234 | return 0; | 221 | return 0; |
235 | } | 222 | } |
236 | 223 | ||
@@ -240,55 +227,31 @@ static int __init microblaze_clocksource_init(void) | |||
240 | */ | 227 | */ |
241 | static int timer_initialized; | 228 | static int timer_initialized; |
242 | 229 | ||
243 | void __init time_init(void) | 230 | static void __init xilinx_timer_init(struct device_node *timer) |
244 | { | 231 | { |
245 | u32 irq; | 232 | u32 irq; |
246 | u32 timer_num = 1; | 233 | u32 timer_num = 1; |
247 | struct device_node *timer = NULL; | 234 | int ret; |
248 | const void *prop; | 235 | |
249 | #ifdef CONFIG_SELFMOD_TIMER | 236 | timer_baseaddr = of_iomap(timer, 0); |
250 | unsigned int timer_baseaddr = 0; | 237 | if (!timer_baseaddr) { |
251 | int arr_func[] = { | 238 | pr_err("ERROR: invalid timer base address\n"); |
252 | (int)µblaze_read, | 239 | BUG(); |
253 | (int)&timer_interrupt, | 240 | } |
254 | (int)µblaze_clocksource_init, | 241 | |
255 | (int)µblaze_timer_set_mode, | ||
256 | (int)µblaze_timer_set_next_event, | ||
257 | 0 | ||
258 | }; | ||
259 | #endif | ||
260 | prop = of_get_property(of_chosen, "system-timer", NULL); | ||
261 | if (prop) | ||
262 | timer = of_find_node_by_phandle(be32_to_cpup(prop)); | ||
263 | else | ||
264 | pr_info("No chosen timer found, using default\n"); | ||
265 | |||
266 | if (!timer) | ||
267 | timer = of_find_compatible_node(NULL, NULL, | ||
268 | "xlnx,xps-timer-1.00.a"); | ||
269 | BUG_ON(!timer); | ||
270 | |||
271 | timer_baseaddr = be32_to_cpup(of_get_property(timer, "reg", NULL)); | ||
272 | timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE); | ||
273 | irq = irq_of_parse_and_map(timer, 0); | 242 | irq = irq_of_parse_and_map(timer, 0); |
274 | timer_num = be32_to_cpup(of_get_property(timer, | 243 | |
275 | "xlnx,one-timer-only", NULL)); | 244 | of_property_read_u32(timer, "xlnx,one-timer-only", &timer_num); |
276 | if (timer_num) { | 245 | if (timer_num) { |
277 | pr_emerg("Please enable two timers in HW\n"); | 246 | pr_emerg("Please enable two timers in HW\n"); |
278 | BUG(); | 247 | BUG(); |
279 | } | 248 | } |
280 | 249 | ||
281 | #ifdef CONFIG_SELFMOD_TIMER | 250 | pr_info("%s: irq=%d\n", timer->full_name, irq); |
282 | selfmod_function((int *) arr_func, timer_baseaddr); | ||
283 | #endif | ||
284 | pr_info("%s #0 at 0x%08x, irq=%d\n", | ||
285 | timer->name, timer_baseaddr, irq); | ||
286 | 251 | ||
287 | /* If there is clock-frequency property than use it */ | 252 | /* If there is clock-frequency property than use it */ |
288 | prop = of_get_property(timer, "clock-frequency", NULL); | 253 | ret = of_property_read_u32(timer, "clock-frequency", &timer_clock_freq); |
289 | if (prop) | 254 | if (ret < 0) |
290 | timer_clock_freq = be32_to_cpup(prop); | ||
291 | else | ||
292 | timer_clock_freq = cpuinfo.cpu_clock_freq; | 255 | timer_clock_freq = cpuinfo.cpu_clock_freq; |
293 | 256 | ||
294 | freq_div_hz = timer_clock_freq / HZ; | 257 | freq_div_hz = timer_clock_freq / HZ; |
@@ -297,8 +260,8 @@ void __init time_init(void) | |||
297 | #ifdef CONFIG_HEART_BEAT | 260 | #ifdef CONFIG_HEART_BEAT |
298 | setup_heartbeat(); | 261 | setup_heartbeat(); |
299 | #endif | 262 | #endif |
300 | microblaze_clocksource_init(); | 263 | xilinx_clocksource_init(); |
301 | microblaze_clockevent_init(); | 264 | xilinx_clockevent_init(); |
302 | timer_initialized = 1; | 265 | timer_initialized = 1; |
303 | } | 266 | } |
304 | 267 | ||
@@ -312,3 +275,6 @@ unsigned long long notrace sched_clock(void) | |||
312 | } | 275 | } |
313 | return 0; | 276 | return 0; |
314 | } | 277 | } |
278 | |||
279 | CLOCKSOURCE_OF_DECLARE(xilinx_timer, "xlnx,xps-timer-1.00.a", | ||
280 | xilinx_timer_init); | ||
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index bdb8ea100e73..1b93bf0892a0 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c | |||
@@ -657,67 +657,42 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar, | |||
657 | void pci_process_bridge_OF_ranges(struct pci_controller *hose, | 657 | void pci_process_bridge_OF_ranges(struct pci_controller *hose, |
658 | struct device_node *dev, int primary) | 658 | struct device_node *dev, int primary) |
659 | { | 659 | { |
660 | const u32 *ranges; | ||
661 | int rlen; | ||
662 | int pna = of_n_addr_cells(dev); | ||
663 | int np = pna + 5; | ||
664 | int memno = 0, isa_hole = -1; | 660 | int memno = 0, isa_hole = -1; |
665 | u32 pci_space; | ||
666 | unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size; | ||
667 | unsigned long long isa_mb = 0; | 661 | unsigned long long isa_mb = 0; |
668 | struct resource *res; | 662 | struct resource *res; |
663 | struct of_pci_range range; | ||
664 | struct of_pci_range_parser parser; | ||
669 | 665 | ||
670 | pr_info("PCI host bridge %s %s ranges:\n", | 666 | pr_info("PCI host bridge %s %s ranges:\n", |
671 | dev->full_name, primary ? "(primary)" : ""); | 667 | dev->full_name, primary ? "(primary)" : ""); |
672 | 668 | ||
673 | /* Get ranges property */ | 669 | /* Check for ranges property */ |
674 | ranges = of_get_property(dev, "ranges", &rlen); | 670 | if (of_pci_range_parser_init(&parser, dev)) |
675 | if (ranges == NULL) | ||
676 | return; | 671 | return; |
677 | 672 | ||
678 | /* Parse it */ | ||
679 | pr_debug("Parsing ranges property...\n"); | 673 | pr_debug("Parsing ranges property...\n"); |
680 | while ((rlen -= np * 4) >= 0) { | 674 | for_each_of_pci_range(&parser, &range) { |
681 | /* Read next ranges element */ | 675 | /* Read next ranges element */ |
682 | pci_space = ranges[0]; | ||
683 | pci_addr = of_read_number(ranges + 1, 2); | ||
684 | cpu_addr = of_translate_address(dev, ranges + 3); | ||
685 | size = of_read_number(ranges + pna + 3, 2); | ||
686 | |||
687 | pr_debug("pci_space: 0x%08x pci_addr:0x%016llx ", | 676 | pr_debug("pci_space: 0x%08x pci_addr:0x%016llx ", |
688 | pci_space, pci_addr); | 677 | range.pci_space, range.pci_addr); |
689 | pr_debug("cpu_addr:0x%016llx size:0x%016llx\n", | 678 | pr_debug("cpu_addr:0x%016llx size:0x%016llx\n", |
690 | cpu_addr, size); | 679 | range.cpu_addr, range.size); |
691 | |||
692 | ranges += np; | ||
693 | 680 | ||
694 | /* If we failed translation or got a zero-sized region | 681 | /* If we failed translation or got a zero-sized region |
695 | * (some FW try to feed us with non sensical zero sized regions | 682 | * (some FW try to feed us with non sensical zero sized regions |
696 | * such as power3 which look like some kind of attempt | 683 | * such as power3 which look like some kind of attempt |
697 | * at exposing the VGA memory hole) | 684 | * at exposing the VGA memory hole) |
698 | */ | 685 | */ |
699 | if (cpu_addr == OF_BAD_ADDR || size == 0) | 686 | if (range.cpu_addr == OF_BAD_ADDR || range.size == 0) |
700 | continue; | 687 | continue; |
701 | 688 | ||
702 | /* Now consume following elements while they are contiguous */ | ||
703 | for (; rlen >= np * sizeof(u32); | ||
704 | ranges += np, rlen -= np * 4) { | ||
705 | if (ranges[0] != pci_space) | ||
706 | break; | ||
707 | pci_next = of_read_number(ranges + 1, 2); | ||
708 | cpu_next = of_translate_address(dev, ranges + 3); | ||
709 | if (pci_next != pci_addr + size || | ||
710 | cpu_next != cpu_addr + size) | ||
711 | break; | ||
712 | size += of_read_number(ranges + pna + 3, 2); | ||
713 | } | ||
714 | |||
715 | /* Act based on address space type */ | 689 | /* Act based on address space type */ |
716 | res = NULL; | 690 | res = NULL; |
717 | switch ((pci_space >> 24) & 0x3) { | 691 | switch (range.flags & IORESOURCE_TYPE_BITS) { |
718 | case 1: /* PCI IO space */ | 692 | case IORESOURCE_IO: |
719 | pr_info(" IO 0x%016llx..0x%016llx -> 0x%016llx\n", | 693 | pr_info(" IO 0x%016llx..0x%016llx -> 0x%016llx\n", |
720 | cpu_addr, cpu_addr + size - 1, pci_addr); | 694 | range.cpu_addr, range.cpu_addr + range.size - 1, |
695 | range.pci_addr); | ||
721 | 696 | ||
722 | /* We support only one IO range */ | 697 | /* We support only one IO range */ |
723 | if (hose->pci_io_size) { | 698 | if (hose->pci_io_size) { |
@@ -725,11 +700,12 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
725 | continue; | 700 | continue; |
726 | } | 701 | } |
727 | /* On 32 bits, limit I/O space to 16MB */ | 702 | /* On 32 bits, limit I/O space to 16MB */ |
728 | if (size > 0x01000000) | 703 | if (range.size > 0x01000000) |
729 | size = 0x01000000; | 704 | range.size = 0x01000000; |
730 | 705 | ||
731 | /* 32 bits needs to map IOs here */ | 706 | /* 32 bits needs to map IOs here */ |
732 | hose->io_base_virt = ioremap(cpu_addr, size); | 707 | hose->io_base_virt = ioremap(range.cpu_addr, |
708 | range.size); | ||
733 | 709 | ||
734 | /* Expect trouble if pci_addr is not 0 */ | 710 | /* Expect trouble if pci_addr is not 0 */ |
735 | if (primary) | 711 | if (primary) |
@@ -738,19 +714,20 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
738 | /* pci_io_size and io_base_phys always represent IO | 714 | /* pci_io_size and io_base_phys always represent IO |
739 | * space starting at 0 so we factor in pci_addr | 715 | * space starting at 0 so we factor in pci_addr |
740 | */ | 716 | */ |
741 | hose->pci_io_size = pci_addr + size; | 717 | hose->pci_io_size = range.pci_addr + range.size; |
742 | hose->io_base_phys = cpu_addr - pci_addr; | 718 | hose->io_base_phys = range.cpu_addr - range.pci_addr; |
743 | 719 | ||
744 | /* Build resource */ | 720 | /* Build resource */ |
745 | res = &hose->io_resource; | 721 | res = &hose->io_resource; |
746 | res->flags = IORESOURCE_IO; | 722 | range.cpu_addr = range.pci_addr; |
747 | res->start = pci_addr; | 723 | |
748 | break; | 724 | break; |
749 | case 2: /* PCI Memory space */ | 725 | case IORESOURCE_MEM: |
750 | case 3: /* PCI 64 bits Memory space */ | ||
751 | pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n", | 726 | pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n", |
752 | cpu_addr, cpu_addr + size - 1, pci_addr, | 727 | range.cpu_addr, range.cpu_addr + range.size - 1, |
753 | (pci_space & 0x40000000) ? "Prefetch" : ""); | 728 | range.pci_addr, |
729 | (range.pci_space & 0x40000000) ? | ||
730 | "Prefetch" : ""); | ||
754 | 731 | ||
755 | /* We support only 3 memory ranges */ | 732 | /* We support only 3 memory ranges */ |
756 | if (memno >= 3) { | 733 | if (memno >= 3) { |
@@ -758,13 +735,13 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
758 | continue; | 735 | continue; |
759 | } | 736 | } |
760 | /* Handles ISA memory hole space here */ | 737 | /* Handles ISA memory hole space here */ |
761 | if (pci_addr == 0) { | 738 | if (range.pci_addr == 0) { |
762 | isa_mb = cpu_addr; | 739 | isa_mb = range.cpu_addr; |
763 | isa_hole = memno; | 740 | isa_hole = memno; |
764 | if (primary || isa_mem_base == 0) | 741 | if (primary || isa_mem_base == 0) |
765 | isa_mem_base = cpu_addr; | 742 | isa_mem_base = range.cpu_addr; |
766 | hose->isa_mem_phys = cpu_addr; | 743 | hose->isa_mem_phys = range.cpu_addr; |
767 | hose->isa_mem_size = size; | 744 | hose->isa_mem_size = range.size; |
768 | } | 745 | } |
769 | 746 | ||
770 | /* We get the PCI/Mem offset from the first range or | 747 | /* We get the PCI/Mem offset from the first range or |
@@ -772,30 +749,23 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
772 | * hole. If they don't match, bugger. | 749 | * hole. If they don't match, bugger. |
773 | */ | 750 | */ |
774 | if (memno == 0 || | 751 | if (memno == 0 || |
775 | (isa_hole >= 0 && pci_addr != 0 && | 752 | (isa_hole >= 0 && range.pci_addr != 0 && |
776 | hose->pci_mem_offset == isa_mb)) | 753 | hose->pci_mem_offset == isa_mb)) |
777 | hose->pci_mem_offset = cpu_addr - pci_addr; | 754 | hose->pci_mem_offset = range.cpu_addr - |
778 | else if (pci_addr != 0 && | 755 | range.pci_addr; |
779 | hose->pci_mem_offset != cpu_addr - pci_addr) { | 756 | else if (range.pci_addr != 0 && |
757 | hose->pci_mem_offset != range.cpu_addr - | ||
758 | range.pci_addr) { | ||
780 | pr_info(" \\--> Skipped (offset mismatch) !\n"); | 759 | pr_info(" \\--> Skipped (offset mismatch) !\n"); |
781 | continue; | 760 | continue; |
782 | } | 761 | } |
783 | 762 | ||
784 | /* Build resource */ | 763 | /* Build resource */ |
785 | res = &hose->mem_resources[memno++]; | 764 | res = &hose->mem_resources[memno++]; |
786 | res->flags = IORESOURCE_MEM; | ||
787 | if (pci_space & 0x40000000) | ||
788 | res->flags |= IORESOURCE_PREFETCH; | ||
789 | res->start = cpu_addr; | ||
790 | break; | 765 | break; |
791 | } | 766 | } |
792 | if (res != NULL) { | 767 | if (res != NULL) |
793 | res->name = dev->full_name; | 768 | of_pci_range_to_resource(&range, dev, res); |
794 | res->end = res->start + size - 1; | ||
795 | res->parent = NULL; | ||
796 | res->sibling = NULL; | ||
797 | res->child = NULL; | ||
798 | } | ||
799 | } | 769 | } |
800 | 770 | ||
801 | /* If there's an ISA hole and the pci_mem_offset is -not- matching | 771 | /* If there's an ISA hole and the pci_mem_offset is -not- matching |
diff --git a/arch/microblaze/platform/Kconfig.platform b/arch/microblaze/platform/Kconfig.platform index b1747211b8b1..db1aa5c22cea 100644 --- a/arch/microblaze/platform/Kconfig.platform +++ b/arch/microblaze/platform/Kconfig.platform | |||
@@ -18,28 +18,6 @@ config PLATFORM_GENERIC | |||
18 | 18 | ||
19 | endchoice | 19 | endchoice |
20 | 20 | ||
21 | config SELFMOD | ||
22 | bool "Use self modified code for intc/timer" | ||
23 | depends on NO_MMU | ||
24 | default n | ||
25 | help | ||
26 | This choice enables self-modified code for interrupt controller | ||
27 | and timer. | ||
28 | |||
29 | config SELFMOD_INTC | ||
30 | bool "Use self modified code for intc" | ||
31 | depends on SELFMOD | ||
32 | default y | ||
33 | help | ||
34 | This choice enables self-modified code for interrupt controller. | ||
35 | |||
36 | config SELFMOD_TIMER | ||
37 | bool "Use self modified code for timer" | ||
38 | depends on SELFMOD | ||
39 | default y | ||
40 | help | ||
41 | This choice enables self-modified code for timer. | ||
42 | |||
43 | config OPT_LIB_FUNCTION | 21 | config OPT_LIB_FUNCTION |
44 | bool "Optimalized lib function" | 22 | bool "Optimalized lib function" |
45 | default y | 23 | default y |