diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-07-17 13:49:48 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-07-20 13:57:39 -0400 |
commit | 5a81299928f3d9abfaced60bedd85214cf9921a4 (patch) | |
tree | 19cd4059c98338749a918392a91ca42533658577 /arch/mips/kernel | |
parent | 17099b1142f6c0359fca60a3464dea8fb30badea (diff) |
[MIPS] Workaround for RM7000 WAIT instruction aka erratum 38
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 26 |
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 | */ | ||
82 | static 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. */ |
80 | int allow_au1k_wait; | 101 | int 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; |