aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-07-17 13:49:48 -0400
committerRalf Baechle <ralf@linux-mips.org>2007-07-20 13:57:39 -0400
commit5a81299928f3d9abfaced60bedd85214cf9921a4 (patch)
tree19cd4059c98338749a918392a91ca42533658577 /arch
parent17099b1142f6c0359fca60a3464dea8fb30badea (diff)
[MIPS] Workaround for RM7000 WAIT instruction aka erratum 38
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/kernel/cpu-probe.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index c6b8b074a81a..06448a9656dc 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -75,6 +75,27 @@ static void r4k_wait_irqoff(void)
75 local_irq_enable(); 75 local_irq_enable();
76} 76}
77 77
78/*
79 * The RM7000 variant has to handle erratum 38. The workaround is to not
80 * have any pending stores when the WAIT instruction is executed.
81 */
82static void rm7k_wait_irqoff(void)
83{
84 local_irq_disable();
85 if (!need_resched())
86 __asm__(
87 " .set push \n"
88 " .set mips3 \n"
89 " .set noat \n"
90 " mfc0 $1, $12 \n"
91 " sync \n"
92 " mtc0 $1, $12 # stalls until W stage \n"
93 " wait \n"
94 " mtc0 $1, $12 # stalls until W stage \n"
95 " .set pop \n");
96 local_irq_enable();
97}
98
78/* The Au1xxx wait is available only if using 32khz counter or 99/* The Au1xxx wait is available only if using 32khz counter or
79 * external timer source, but specifically not CP0 Counter. */ 100 * external timer source, but specifically not CP0 Counter. */
80int allow_au1k_wait; 101int allow_au1k_wait;
@@ -132,7 +153,6 @@ static inline void check_wait(void)
132 case CPU_R4700: 153 case CPU_R4700:
133 case CPU_R5000: 154 case CPU_R5000:
134 case CPU_NEVADA: 155 case CPU_NEVADA:
135 case CPU_RM7000:
136 case CPU_4KC: 156 case CPU_4KC:
137 case CPU_4KEC: 157 case CPU_4KEC:
138 case CPU_4KSC: 158 case CPU_4KSC:
@@ -142,6 +162,10 @@ static inline void check_wait(void)
142 cpu_wait = r4k_wait; 162 cpu_wait = r4k_wait;
143 break; 163 break;
144 164
165 case CPU_RM7000:
166 cpu_wait = rm7k_wait_irqoff;
167 break;
168
145 case CPU_24K: 169 case CPU_24K:
146 case CPU_34K: 170 case CPU_34K:
147 cpu_wait = r4k_wait; 171 cpu_wait = r4k_wait;