diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2005-05-01 11:58:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-05-01 11:58:40 -0400 |
commit | f1c55dea0bb2df94aa2b01b0871cb02f2e206676 (patch) | |
tree | 0bac72de98485c578bd0590daf4c7d9090660c6d /arch | |
parent | b207a290ea7dc83dba02e40b81cc8a29415a9c60 (diff) |
[PATCH] ppc32: Fix errata for some G3 CPUs
Some G3 CPUs can crash in funny way if a store from an FPU register
instruction is executed on a register that has never been initialized since
power on. This patch fixes it by making sure all FP registers have been
properly initialized at kernel boot and when waking from sleep. It also makes
the code that decides wether HID0_BTIC and HID0_DPM are allowed on a given CPU
smarter (it can actually _clear_ them now if they are not allowed instead of
just setting them when they are allowed in case the firmware got them wrong)
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ppc/kernel/cpu_setup_6xx.S | 42 | ||||
-rw-r--r-- | arch/ppc/platforms/pmac_sleep.S | 4 |
2 files changed, 40 insertions, 6 deletions
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S index 74f781b486a3..468721d9ebd2 100644 --- a/arch/ppc/kernel/cpu_setup_6xx.S +++ b/arch/ppc/kernel/cpu_setup_6xx.S | |||
@@ -30,12 +30,14 @@ _GLOBAL(__setup_cpu_604) | |||
30 | blr | 30 | blr |
31 | _GLOBAL(__setup_cpu_750) | 31 | _GLOBAL(__setup_cpu_750) |
32 | mflr r4 | 32 | mflr r4 |
33 | bl __init_fpu_registers | ||
33 | bl setup_common_caches | 34 | bl setup_common_caches |
34 | bl setup_750_7400_hid0 | 35 | bl setup_750_7400_hid0 |
35 | mtlr r4 | 36 | mtlr r4 |
36 | blr | 37 | blr |
37 | _GLOBAL(__setup_cpu_750cx) | 38 | _GLOBAL(__setup_cpu_750cx) |
38 | mflr r4 | 39 | mflr r4 |
40 | bl __init_fpu_registers | ||
39 | bl setup_common_caches | 41 | bl setup_common_caches |
40 | bl setup_750_7400_hid0 | 42 | bl setup_750_7400_hid0 |
41 | bl setup_750cx | 43 | bl setup_750cx |
@@ -43,6 +45,7 @@ _GLOBAL(__setup_cpu_750cx) | |||
43 | blr | 45 | blr |
44 | _GLOBAL(__setup_cpu_750fx) | 46 | _GLOBAL(__setup_cpu_750fx) |
45 | mflr r4 | 47 | mflr r4 |
48 | bl __init_fpu_registers | ||
46 | bl setup_common_caches | 49 | bl setup_common_caches |
47 | bl setup_750_7400_hid0 | 50 | bl setup_750_7400_hid0 |
48 | bl setup_750fx | 51 | bl setup_750fx |
@@ -50,6 +53,7 @@ _GLOBAL(__setup_cpu_750fx) | |||
50 | blr | 53 | blr |
51 | _GLOBAL(__setup_cpu_7400) | 54 | _GLOBAL(__setup_cpu_7400) |
52 | mflr r4 | 55 | mflr r4 |
56 | bl __init_fpu_registers | ||
53 | bl setup_7400_workarounds | 57 | bl setup_7400_workarounds |
54 | bl setup_common_caches | 58 | bl setup_common_caches |
55 | bl setup_750_7400_hid0 | 59 | bl setup_750_7400_hid0 |
@@ -57,6 +61,7 @@ _GLOBAL(__setup_cpu_7400) | |||
57 | blr | 61 | blr |
58 | _GLOBAL(__setup_cpu_7410) | 62 | _GLOBAL(__setup_cpu_7410) |
59 | mflr r4 | 63 | mflr r4 |
64 | bl __init_fpu_registers | ||
60 | bl setup_7410_workarounds | 65 | bl setup_7410_workarounds |
61 | bl setup_common_caches | 66 | bl setup_common_caches |
62 | bl setup_750_7400_hid0 | 67 | bl setup_750_7400_hid0 |
@@ -80,7 +85,7 @@ setup_common_caches: | |||
80 | bne 1f /* don't invalidate the D-cache */ | 85 | bne 1f /* don't invalidate the D-cache */ |
81 | ori r8,r8,HID0_DCI /* unless it wasn't enabled */ | 86 | ori r8,r8,HID0_DCI /* unless it wasn't enabled */ |
82 | 1: sync | 87 | 1: sync |
83 | mtspr SPRN_HID0,r8 /* enable and invalidate caches */ | 88 | mtspr SPRN_HID0,r8 /* enable and invalidate caches */ |
84 | sync | 89 | sync |
85 | mtspr SPRN_HID0,r11 /* enable caches */ | 90 | mtspr SPRN_HID0,r11 /* enable caches */ |
86 | sync | 91 | sync |
@@ -152,9 +157,13 @@ setup_7410_workarounds: | |||
152 | setup_750_7400_hid0: | 157 | setup_750_7400_hid0: |
153 | mfspr r11,SPRN_HID0 | 158 | mfspr r11,SPRN_HID0 |
154 | ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC | 159 | ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC |
160 | oris r11,r11,HID0_DPM@h | ||
155 | BEGIN_FTR_SECTION | 161 | BEGIN_FTR_SECTION |
156 | oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ | 162 | xori r11,r11,HID0_BTIC |
157 | END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) | 163 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) |
164 | BEGIN_FTR_SECTION | ||
165 | xoris r11,r11,HID0_DPM@h /* disable dynamic power mgmt */ | ||
166 | END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM) | ||
158 | li r3,HID0_SPD | 167 | li r3,HID0_SPD |
159 | andc r11,r11,r3 /* clear SPD: enable speculative */ | 168 | andc r11,r11,r3 /* clear SPD: enable speculative */ |
160 | li r3,0 | 169 | li r3,0 |
@@ -218,13 +227,15 @@ setup_745x_specifics: | |||
218 | 227 | ||
219 | /* All of the bits we have to set..... | 228 | /* All of the bits we have to set..... |
220 | */ | 229 | */ |
221 | ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK | HID0_BTIC | 230 | ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE |
231 | ori r11,r11,HID0_LRSTK | HID0_BTIC | ||
232 | oris r11,r11,HID0_DPM@h | ||
222 | BEGIN_FTR_SECTION | 233 | BEGIN_FTR_SECTION |
223 | xori r11,r11,HID0_BTIC | 234 | xori r11,r11,HID0_BTIC |
224 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) | 235 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) |
225 | BEGIN_FTR_SECTION | 236 | BEGIN_FTR_SECTION |
226 | oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */ | 237 | xoris r11,r11,HID0_DPM@h /* disable dynamic power mgmt */ |
227 | END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) | 238 | END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM) |
228 | 239 | ||
229 | /* All of the bits we have to clear.... | 240 | /* All of the bits we have to clear.... |
230 | */ | 241 | */ |
@@ -248,6 +259,25 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM) | |||
248 | isync | 259 | isync |
249 | blr | 260 | blr |
250 | 261 | ||
262 | /* | ||
263 | * Initialize the FPU registers. This is needed to work around an errata | ||
264 | * in some 750 cpus where using a not yet initialized FPU register after | ||
265 | * power on reset may hang the CPU | ||
266 | */ | ||
267 | _GLOBAL(__init_fpu_registers) | ||
268 | mfmsr r10 | ||
269 | ori r11,r10,MSR_FP | ||
270 | mtmsr r11 | ||
271 | isync | ||
272 | addis r9,r3,empty_zero_page@ha | ||
273 | addi r9,r9,empty_zero_page@l | ||
274 | REST_32FPRS(0,r9) | ||
275 | sync | ||
276 | mtmsr r10 | ||
277 | isync | ||
278 | blr | ||
279 | |||
280 | |||
251 | /* Definitions for the table use to save CPU states */ | 281 | /* Definitions for the table use to save CPU states */ |
252 | #define CS_HID0 0 | 282 | #define CS_HID0 0 |
253 | #define CS_HID1 4 | 283 | #define CS_HID1 4 |
diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S index 3139b6766ad3..f459ade1bd63 100644 --- a/arch/ppc/platforms/pmac_sleep.S +++ b/arch/ppc/platforms/pmac_sleep.S | |||
@@ -267,6 +267,10 @@ grackle_wake_up: | |||
267 | /* Restore various CPU config stuffs */ | 267 | /* Restore various CPU config stuffs */ |
268 | bl __restore_cpu_setup | 268 | bl __restore_cpu_setup |
269 | 269 | ||
270 | /* Make sure all FPRs have been initialized */ | ||
271 | bl reloc_offset | ||
272 | bl __init_fpu_registers | ||
273 | |||
270 | /* Invalidate & enable L1 cache, we don't care about | 274 | /* Invalidate & enable L1 cache, we don't care about |
271 | * whatever the ROM may have tried to write to memory | 275 | * whatever the ROM may have tried to write to memory |
272 | */ | 276 | */ |