diff options
author | Sonic Zhang <sonic.zhang@analog.com> | 2010-08-05 03:49:26 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2011-03-18 04:01:04 -0400 |
commit | c6345ab1a3d17f4b6c80ac79d7fb0f006b32fdaa (patch) | |
tree | 8f3980f69cba2e3269aa9688426fca95be56d7a6 /arch/blackfin/mach-common | |
parent | 6f546bc3ac9eedbf770bf3bcbc45ce2ea32c94ad (diff) |
Blackfin: SMP: work around anomaly 05000491
In order to safely work around anomaly 05000491, we have to execute IFLUSH
from L1 instruction sram. The trouble with multi-core systems is that all
L1 sram is visible only to the active core. So we can't just place the
functions into L1 and call it directly. We need to setup a jump table and
place the entry point in external memory. This will call the right func
based on the active core.
In the process, convert from the manual relocation of a small bit of code
into Core B's L1 to the more general framework we already have in place
for loading arbitrary pieces of code into L1.
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r-- | arch/blackfin/mach-common/cache.S | 20 | ||||
-rw-r--r-- | arch/blackfin/mach-common/smp.c | 4 |
2 files changed, 24 insertions, 0 deletions
diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S index 85aadeb76658..9f4dd35bfd74 100644 --- a/arch/blackfin/mach-common/cache.S +++ b/arch/blackfin/mach-common/cache.S | |||
@@ -69,10 +69,30 @@ | |||
69 | #endif | 69 | #endif |
70 | 70 | ||
71 | /* Invalidate all instruction cache lines assocoiated with this memory area */ | 71 | /* Invalidate all instruction cache lines assocoiated with this memory area */ |
72 | #ifdef CONFIG_SMP | ||
73 | # define _blackfin_icache_flush_range _blackfin_icache_flush_range_l1 | ||
74 | #endif | ||
72 | ENTRY(_blackfin_icache_flush_range) | 75 | ENTRY(_blackfin_icache_flush_range) |
73 | do_flush IFLUSH | 76 | do_flush IFLUSH |
74 | ENDPROC(_blackfin_icache_flush_range) | 77 | ENDPROC(_blackfin_icache_flush_range) |
75 | 78 | ||
79 | #ifdef CONFIG_SMP | ||
80 | .text | ||
81 | # undef _blackfin_icache_flush_range | ||
82 | ENTRY(_blackfin_icache_flush_range) | ||
83 | p0.L = LO(DSPID); | ||
84 | p0.H = HI(DSPID); | ||
85 | r3 = [p0]; | ||
86 | r3 = r3.b (z); | ||
87 | p2 = r3; | ||
88 | p0.L = _blackfin_iflush_l1_entry; | ||
89 | p0.H = _blackfin_iflush_l1_entry; | ||
90 | p0 = p0 + (p2 << 2); | ||
91 | p1 = [p0]; | ||
92 | jump (p1); | ||
93 | ENDPROC(_blackfin_icache_flush_range) | ||
94 | #endif | ||
95 | |||
76 | #ifdef CONFIG_DCACHE_FLUSH_L1 | 96 | #ifdef CONFIG_DCACHE_FLUSH_L1 |
77 | .section .l1.text | 97 | .section .l1.text |
78 | #else | 98 | #else |
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 5f7617d66905..6e17a265c4d3 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c | |||
@@ -40,6 +40,10 @@ | |||
40 | */ | 40 | */ |
41 | struct corelock_slot corelock __attribute__ ((__section__(".l2.bss"))); | 41 | struct corelock_slot corelock __attribute__ ((__section__(".l2.bss"))); |
42 | 42 | ||
43 | #ifdef CONFIG_ICACHE_FLUSH_L1 | ||
44 | unsigned long blackfin_iflush_l1_entry[NR_CPUS]; | ||
45 | #endif | ||
46 | |||
43 | void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb, | 47 | void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb, |
44 | *init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb, | 48 | *init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb, |
45 | *init_saved_dcplb_fault_addr_coreb; | 49 | *init_saved_dcplb_fault_addr_coreb; |