aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/microblaze/include/asm/selfmod.h24
-rw-r--r--arch/microblaze/kernel/Makefile2
-rw-r--r--arch/microblaze/kernel/intc.c36
-rw-r--r--arch/microblaze/kernel/selfmod.c81
-rw-r--r--arch/microblaze/kernel/setup.c4
-rw-r--r--arch/microblaze/kernel/timer.c47
-rw-r--r--arch/microblaze/platform/Kconfig.platform22
7 files changed, 24 insertions, 192 deletions
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
22void 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
7CFLAGS_REMOVE_timer.o = -pg 7CFLAGS_REMOVE_timer.o = -pg
8CFLAGS_REMOVE_intc.o = -pg 8CFLAGS_REMOVE_intc.o = -pg
9CFLAGS_REMOVE_early_printk.o = -pg 9CFLAGS_REMOVE_early_printk.o = -pg
10CFLAGS_REMOVE_selfmod.o = -pg
11CFLAGS_REMOVE_heartbeat.o = -pg 10CFLAGS_REMOVE_heartbeat.o = -pg
12CFLAGS_REMOVE_ftrace.o = -pg 11CFLAGS_REMOVE_ftrace.o = -pg
13CFLAGS_REMOVE_process.o = -pg 12CFLAGS_REMOVE_process.o = -pg
@@ -23,7 +22,6 @@ obj-y += dma.o exceptions.o \
23obj-y += cpu/ 22obj-y += cpu/
24 23
25obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 24obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
26obj-$(CONFIG_SELFMOD) += selfmod.o
27obj-$(CONFIG_HEART_BEAT) += heartbeat.o 25obj-$(CONFIG_HEART_BEAT) += heartbeat.o
28obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o 26obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o
29obj-$(CONFIG_MMU) += misc.o 27obj-$(CONFIG_MMU) += misc.o
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
index d85fa3a2b0f8..f618b5351f59 100644
--- a/arch/microblaze/kernel/intc.c
+++ b/arch/microblaze/kernel/intc.c
@@ -18,13 +18,7 @@
18#include <asm/prom.h> 18#include <asm/prom.h>
19#include <asm/irq.h> 19#include <asm/irq.h>
20 20
21#ifdef CONFIG_SELFMOD_INTC
22#include <asm/selfmod.h>
23#define INTC_BASE BARRIER_BASE_ADDR
24#else
25static unsigned int intc_baseaddr; 21static unsigned int intc_baseaddr;
26#define INTC_BASE intc_baseaddr
27#endif
28 22
29/* No one else should require these constants, so define them locally here. */ 23/* No one else should require these constants, so define them locally here. */
30#define ISR 0x00 /* Interrupt Status Register */ 24#define ISR 0x00 /* Interrupt Status Register */
@@ -50,21 +44,21 @@ static void intc_enable_or_unmask(struct irq_data *d)
50 * acks the irq before calling the interrupt handler 44 * acks the irq before calling the interrupt handler
51 */ 45 */
52 if (irqd_is_level_type(d)) 46 if (irqd_is_level_type(d))
53 out_be32(INTC_BASE + IAR, mask); 47 out_be32(intc_baseaddr + IAR, mask);
54 48
55 out_be32(INTC_BASE + SIE, mask); 49 out_be32(intc_baseaddr + SIE, mask);
56} 50}
57 51
58static void intc_disable_or_mask(struct irq_data *d) 52static void intc_disable_or_mask(struct irq_data *d)
59{ 53{
60 pr_debug("disable: %ld\n", d->hwirq); 54 pr_debug("disable: %ld\n", d->hwirq);
61 out_be32(INTC_BASE + CIE, 1 << d->hwirq); 55 out_be32(intc_baseaddr + CIE, 1 << d->hwirq);
62} 56}
63 57
64static void intc_ack(struct irq_data *d) 58static void intc_ack(struct irq_data *d)
65{ 59{
66 pr_debug("ack: %ld\n", d->hwirq); 60 pr_debug("ack: %ld\n", d->hwirq);
67 out_be32(INTC_BASE + IAR, 1 << d->hwirq); 61 out_be32(intc_baseaddr + IAR, 1 << d->hwirq);
68} 62}
69 63
70static void intc_mask_ack(struct irq_data *d) 64static void intc_mask_ack(struct irq_data *d)
@@ -72,8 +66,8 @@ static void intc_mask_ack(struct irq_data *d)
72 unsigned long mask = 1 << d->hwirq; 66 unsigned long mask = 1 << d->hwirq;
73 67
74 pr_debug("disable_and_ack: %ld\n", d->hwirq); 68 pr_debug("disable_and_ack: %ld\n", d->hwirq);
75 out_be32(INTC_BASE + CIE, mask); 69 out_be32(intc_baseaddr + CIE, mask);
76 out_be32(INTC_BASE + IAR, mask); 70 out_be32(intc_baseaddr + IAR, mask);
77} 71}
78 72
79static struct irq_chip intc_dev = { 73static struct irq_chip intc_dev = {
@@ -90,7 +84,7 @@ unsigned int get_irq(void)
90{ 84{
91 unsigned int hwirq, irq = -1; 85 unsigned int hwirq, irq = -1;
92 86
93 hwirq = in_be32(INTC_BASE + IVR); 87 hwirq = in_be32(intc_baseaddr + IVR);
94 if (hwirq != -1U) 88 if (hwirq != -1U)
95 irq = irq_find_mapping(root_domain, hwirq); 89 irq = irq_find_mapping(root_domain, hwirq);
96 90
@@ -124,18 +118,7 @@ void __init init_IRQ(void)
124{ 118{
125 u32 nr_irq, intr_mask; 119 u32 nr_irq, intr_mask;
126 struct device_node *intc = NULL; 120 struct device_node *intc = NULL;
127#ifdef CONFIG_SELFMOD_INTC 121
128 unsigned int intc_baseaddr = 0;
129 static int arr_func[] = {
130 (int)&get_irq,
131 (int)&intc_enable_or_unmask,
132 (int)&intc_disable_or_mask,
133 (int)&intc_mask_ack,
134 (int)&intc_ack,
135 (int)&intc_end,
136 0
137 };
138#endif
139 intc = of_find_compatible_node(NULL, NULL, "xlnx,xps-intc-1.00.a"); 122 intc = of_find_compatible_node(NULL, NULL, "xlnx,xps-intc-1.00.a");
140 BUG_ON(!intc); 123 BUG_ON(!intc);
141 124
@@ -149,9 +132,6 @@ void __init init_IRQ(void)
149 if (intr_mask > (u32)((1ULL << nr_irq) - 1)) 132 if (intr_mask > (u32)((1ULL << nr_irq) - 1))
150 pr_info(" ERROR: Mismatch in kind-of-intr param\n"); 133 pr_info(" ERROR: Mismatch in kind-of-intr param\n");
151 134
152#ifdef CONFIG_SELFMOD_INTC
153 selfmod_function((int *) arr_func, intc_baseaddr);
154#endif
155 pr_info("%s #0 at 0x%08x, num_irq=%d, edge=0x%x\n", 135 pr_info("%s #0 at 0x%08x, num_irq=%d, edge=0x%x\n",
156 intc->name, intc_baseaddr, nr_irq, intr_mask); 136 intc->name, intc_baseaddr, nr_irq, intr_mask);
157 137
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 */
47void 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..4259f8b0f113 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -68,10 +68,6 @@ void __init setup_arch(char **cmdline_p)
68 68
69 xilinx_pci_init(); 69 xilinx_pci_init();
70 70
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 71#ifdef CONFIG_VT
76#if defined(CONFIG_XILINX_CONSOLE) 72#if defined(CONFIG_XILINX_CONSOLE)
77 conswitchp = &xil_con; 73 conswitchp = &xil_con;
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index aec5020a6e31..d00a60e62e05 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -29,13 +29,7 @@
29#include <asm/irq.h> 29#include <asm/irq.h>
30#include <linux/cnt32_to_63.h> 30#include <linux/cnt32_to_63.h>
31 31
32#ifdef CONFIG_SELFMOD_TIMER
33#include <asm/selfmod.h>
34#define TIMER_BASE BARRIER_BASE_ADDR
35#else
36static unsigned int timer_baseaddr; 32static unsigned int timer_baseaddr;
37#define TIMER_BASE timer_baseaddr
38#endif
39 33
40static unsigned int freq_div_hz; 34static unsigned int freq_div_hz;
41static unsigned int timer_clock_freq; 35static unsigned int timer_clock_freq;
@@ -61,17 +55,19 @@ static unsigned int timer_clock_freq;
61 55
62static inline void microblaze_timer0_stop(void) 56static inline void microblaze_timer0_stop(void)
63{ 57{
64 out_be32(TIMER_BASE + TCSR0, in_be32(TIMER_BASE + TCSR0) & ~TCSR_ENT); 58 out_be32(timer_baseaddr + TCSR0,
59 in_be32(timer_baseaddr + TCSR0) & ~TCSR_ENT);
65} 60}
66 61
67static inline void microblaze_timer0_start_periodic(unsigned long load_val) 62static inline void microblaze_timer0_start_periodic(unsigned long load_val)
68{ 63{
69 if (!load_val) 64 if (!load_val)
70 load_val = 1; 65 load_val = 1;
71 out_be32(TIMER_BASE + TLR0, load_val); /* loading value to timer reg */ 66 /* loading value to timer reg */
67 out_be32(timer_baseaddr + TLR0, load_val);
72 68
73 /* load the initial value */ 69 /* load the initial value */
74 out_be32(TIMER_BASE + TCSR0, TCSR_LOAD); 70 out_be32(timer_baseaddr + TCSR0, TCSR_LOAD);
75 71
76 /* see timer data sheet for detail 72 /* see timer data sheet for detail
77 * !ENALL - don't enable 'em all 73 * !ENALL - don't enable 'em all
@@ -86,7 +82,7 @@ static inline void microblaze_timer0_start_periodic(unsigned long load_val)
86 * UDT - set the timer as down counter 82 * UDT - set the timer as down counter
87 * !MDT0 - generate mode 83 * !MDT0 - generate mode
88 */ 84 */
89 out_be32(TIMER_BASE + TCSR0, 85 out_be32(timer_baseaddr + TCSR0,
90 TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT); 86 TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT);
91} 87}
92 88
@@ -94,12 +90,13 @@ static inline void microblaze_timer0_start_oneshot(unsigned long load_val)
94{ 90{
95 if (!load_val) 91 if (!load_val)
96 load_val = 1; 92 load_val = 1;
97 out_be32(TIMER_BASE + TLR0, load_val); /* loading value to timer reg */ 93 /* loading value to timer reg */
94 out_be32(timer_baseaddr + TLR0, load_val);
98 95
99 /* load the initial value */ 96 /* load the initial value */
100 out_be32(TIMER_BASE + TCSR0, TCSR_LOAD); 97 out_be32(timer_baseaddr + TCSR0, TCSR_LOAD);
101 98
102 out_be32(TIMER_BASE + TCSR0, 99 out_be32(timer_baseaddr + TCSR0,
103 TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT); 100 TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT);
104} 101}
105 102
@@ -146,7 +143,7 @@ static struct clock_event_device clockevent_microblaze_timer = {
146 143
147static inline void timer_ack(void) 144static inline void timer_ack(void)
148{ 145{
149 out_be32(TIMER_BASE + TCSR0, in_be32(TIMER_BASE + TCSR0)); 146 out_be32(timer_baseaddr + TCSR0, in_be32(timer_baseaddr + TCSR0));
150} 147}
151 148
152static irqreturn_t timer_interrupt(int irq, void *dev_id) 149static irqreturn_t timer_interrupt(int irq, void *dev_id)
@@ -183,7 +180,7 @@ static __init void microblaze_clockevent_init(void)
183static cycle_t microblaze_read(struct clocksource *cs) 180static cycle_t microblaze_read(struct clocksource *cs)
184{ 181{
185 /* reading actual value of timer 1 */ 182 /* reading actual value of timer 1 */
186 return (cycle_t) (in_be32(TIMER_BASE + TCR1)); 183 return (cycle_t) (in_be32(timer_baseaddr + TCR1));
187} 184}
188 185
189static struct timecounter microblaze_tc = { 186static struct timecounter microblaze_tc = {
@@ -225,9 +222,10 @@ static int __init microblaze_clocksource_init(void)
225 panic("failed to register clocksource"); 222 panic("failed to register clocksource");
226 223
227 /* stop timer1 */ 224 /* stop timer1 */
228 out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT); 225 out_be32(timer_baseaddr + TCSR1,
226 in_be32(timer_baseaddr + TCSR1) & ~TCSR_ENT);
229 /* start timer1 - up counting without interrupt */ 227 /* start timer1 - up counting without interrupt */
230 out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT); 228 out_be32(timer_baseaddr + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT);
231 229
232 /* register timecounter - for ftrace support */ 230 /* register timecounter - for ftrace support */
233 init_microblaze_timecounter(); 231 init_microblaze_timecounter();
@@ -246,17 +244,7 @@ void __init time_init(void)
246 u32 timer_num = 1; 244 u32 timer_num = 1;
247 struct device_node *timer = NULL; 245 struct device_node *timer = NULL;
248 const void *prop; 246 const void *prop;
249#ifdef CONFIG_SELFMOD_TIMER 247
250 unsigned int timer_baseaddr = 0;
251 int arr_func[] = {
252 (int)&microblaze_read,
253 (int)&timer_interrupt,
254 (int)&microblaze_clocksource_init,
255 (int)&microblaze_timer_set_mode,
256 (int)&microblaze_timer_set_next_event,
257 0
258 };
259#endif
260 prop = of_get_property(of_chosen, "system-timer", NULL); 248 prop = of_get_property(of_chosen, "system-timer", NULL);
261 if (prop) 249 if (prop)
262 timer = of_find_node_by_phandle(be32_to_cpup(prop)); 250 timer = of_find_node_by_phandle(be32_to_cpup(prop));
@@ -278,9 +266,6 @@ void __init time_init(void)
278 BUG(); 266 BUG();
279 } 267 }
280 268
281#ifdef CONFIG_SELFMOD_TIMER
282 selfmod_function((int *) arr_func, timer_baseaddr);
283#endif
284 pr_info("%s #0 at 0x%08x, irq=%d\n", 269 pr_info("%s #0 at 0x%08x, irq=%d\n",
285 timer->name, timer_baseaddr, irq); 270 timer->name, timer_baseaddr, irq);
286 271
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
19endchoice 19endchoice
20 20
21config 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
29config 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
36config 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
43config OPT_LIB_FUNCTION 21config OPT_LIB_FUNCTION
44 bool "Optimalized lib function" 22 bool "Optimalized lib function"
45 default y 23 default y