diff options
author | Paul Mackerras <paulus@samba.org> | 2006-12-03 23:59:07 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-12-03 23:59:07 -0500 |
commit | 79acbb3ff2d8095b692e1502b9eb2ccec348de26 (patch) | |
tree | 6ab773e5a8f9de2cd6443362b21d0d6fffe3b35e /arch/powerpc/kernel/cputable.c | |
parent | 19a79859e168640f8e16d7b216d211c1c52b687a (diff) | |
parent | 2b5f6dcce5bf94b9b119e9ed8d537098ec61c3d2 (diff) |
Merge branch 'linux-2.6' into for-linus
Diffstat (limited to 'arch/powerpc/kernel/cputable.c')
-rw-r--r-- | arch/powerpc/kernel/cputable.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index f02b402c66d9..1e4ed0731d15 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <asm/oprofile_impl.h> | 19 | #include <asm/oprofile_impl.h> |
20 | #include <asm/cputable.h> | 20 | #include <asm/cputable.h> |
21 | #include <asm/prom.h> /* for PTRRELOC on ARCH=ppc */ | ||
21 | 22 | ||
22 | struct cpu_spec* cur_cpu_spec = NULL; | 23 | struct cpu_spec* cur_cpu_spec = NULL; |
23 | EXPORT_SYMBOL(cur_cpu_spec); | 24 | EXPORT_SYMBOL(cur_cpu_spec); |
@@ -74,7 +75,7 @@ extern void __restore_cpu_ppc970(void); | |||
74 | #define PPC_FEATURE_SPE_COMP 0 | 75 | #define PPC_FEATURE_SPE_COMP 0 |
75 | #endif | 76 | #endif |
76 | 77 | ||
77 | struct cpu_spec cpu_specs[] = { | 78 | static struct cpu_spec cpu_specs[] = { |
78 | #ifdef CONFIG_PPC64 | 79 | #ifdef CONFIG_PPC64 |
79 | { /* Power3 */ | 80 | { /* Power3 */ |
80 | .pvr_mask = 0xffff0000, | 81 | .pvr_mask = 0xffff0000, |
@@ -228,6 +229,21 @@ struct cpu_spec cpu_specs[] = { | |||
228 | .oprofile_type = PPC_OPROFILE_POWER4, | 229 | .oprofile_type = PPC_OPROFILE_POWER4, |
229 | .platform = "ppc970", | 230 | .platform = "ppc970", |
230 | }, | 231 | }, |
232 | { /* PPC970GX */ | ||
233 | .pvr_mask = 0xffff0000, | ||
234 | .pvr_value = 0x00450000, | ||
235 | .cpu_name = "PPC970GX", | ||
236 | .cpu_features = CPU_FTRS_PPC970, | ||
237 | .cpu_user_features = COMMON_USER_POWER4 | | ||
238 | PPC_FEATURE_HAS_ALTIVEC_COMP, | ||
239 | .icache_bsize = 128, | ||
240 | .dcache_bsize = 128, | ||
241 | .num_pmcs = 8, | ||
242 | .cpu_setup = __setup_cpu_ppc970, | ||
243 | .oprofile_cpu_type = "ppc64/970", | ||
244 | .oprofile_type = PPC_OPROFILE_POWER4, | ||
245 | .platform = "ppc970", | ||
246 | }, | ||
231 | { /* Power5 GR */ | 247 | { /* Power5 GR */ |
232 | .pvr_mask = 0xffff0000, | 248 | .pvr_mask = 0xffff0000, |
233 | .pvr_value = 0x003a0000, | 249 | .pvr_value = 0x003a0000, |
@@ -1153,3 +1169,71 @@ struct cpu_spec cpu_specs[] = { | |||
1153 | #endif /* !CLASSIC_PPC */ | 1169 | #endif /* !CLASSIC_PPC */ |
1154 | #endif /* CONFIG_PPC32 */ | 1170 | #endif /* CONFIG_PPC32 */ |
1155 | }; | 1171 | }; |
1172 | |||
1173 | struct cpu_spec *identify_cpu(unsigned long offset) | ||
1174 | { | ||
1175 | struct cpu_spec *s = cpu_specs; | ||
1176 | struct cpu_spec **cur = &cur_cpu_spec; | ||
1177 | unsigned int pvr = mfspr(SPRN_PVR); | ||
1178 | int i; | ||
1179 | |||
1180 | s = PTRRELOC(s); | ||
1181 | cur = PTRRELOC(cur); | ||
1182 | |||
1183 | if (*cur != NULL) | ||
1184 | return PTRRELOC(*cur); | ||
1185 | |||
1186 | for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) | ||
1187 | if ((pvr & s->pvr_mask) == s->pvr_value) { | ||
1188 | *cur = cpu_specs + i; | ||
1189 | #ifdef CONFIG_PPC64 | ||
1190 | /* ppc64 expects identify_cpu to also call setup_cpu | ||
1191 | * for that processor. I will consolidate that at a | ||
1192 | * later time, for now, just use our friend #ifdef. | ||
1193 | * we also don't need to PTRRELOC the function pointer | ||
1194 | * on ppc64 as we are running at 0 in real mode. | ||
1195 | */ | ||
1196 | if (s->cpu_setup) { | ||
1197 | s->cpu_setup(offset, s); | ||
1198 | } | ||
1199 | #endif /* CONFIG_PPC64 */ | ||
1200 | return s; | ||
1201 | } | ||
1202 | BUG(); | ||
1203 | return NULL; | ||
1204 | } | ||
1205 | |||
1206 | void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end) | ||
1207 | { | ||
1208 | struct fixup_entry { | ||
1209 | unsigned long mask; | ||
1210 | unsigned long value; | ||
1211 | long start_off; | ||
1212 | long end_off; | ||
1213 | } *fcur, *fend; | ||
1214 | |||
1215 | fcur = fixup_start; | ||
1216 | fend = fixup_end; | ||
1217 | |||
1218 | for (; fcur < fend; fcur++) { | ||
1219 | unsigned int *pstart, *pend, *p; | ||
1220 | |||
1221 | if ((value & fcur->mask) == fcur->value) | ||
1222 | continue; | ||
1223 | |||
1224 | /* These PTRRELOCs will disappear once the new scheme for | ||
1225 | * modules and vdso is implemented | ||
1226 | */ | ||
1227 | pstart = ((unsigned int *)fcur) + (fcur->start_off / 4); | ||
1228 | pend = ((unsigned int *)fcur) + (fcur->end_off / 4); | ||
1229 | |||
1230 | for (p = pstart; p < pend; p++) { | ||
1231 | *p = 0x60000000u; | ||
1232 | asm volatile ("dcbst 0, %0" : : "r" (p)); | ||
1233 | } | ||
1234 | asm volatile ("sync" : : : "memory"); | ||
1235 | for (p = pstart; p < pend; p++) | ||
1236 | asm volatile ("icbi 0,%0" : : "r" (p)); | ||
1237 | asm volatile ("sync; isync" : : : "memory"); | ||
1238 | } | ||
1239 | } | ||