diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2006-12-08 10:22:20 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-12-08 11:05:26 -0500 |
commit | efe90d273b6f365d37c0f82fbbd68a40982c3265 (patch) | |
tree | a065719ebabfd6fa8b41e5a01fc5ff0c7ad3e80c | |
parent | c99767974ebd2a719d849fdeaaa1674456f5283f (diff) |
[ARM] Handle HWCAP_VFP in VFP support code
Don't set HWCAP_VFP in the processor support file; not only does it
depend on the processor features, but it also depends on the support
code being present. Therefore, only set it if the support code
detects that we have a VFP coprocessor attached.
Also, move the VFP handling of the coprocessor access register into
the VFP support code.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/kernel/setup.c | 3 | ||||
-rw-r--r-- | arch/arm/mm/proc-arm926.S | 2 | ||||
-rw-r--r-- | arch/arm/mm/proc-v6.S | 7 | ||||
-rw-r--r-- | arch/arm/vfp/vfpmodule.c | 26 | ||||
-rw-r--r-- | include/asm-arm/system.h | 43 |
5 files changed, 57 insertions, 24 deletions
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 238dd9b6db84..cf2bd4242803 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -354,9 +354,6 @@ static void __init setup_processor(void) | |||
354 | #ifndef CONFIG_ARM_THUMB | 354 | #ifndef CONFIG_ARM_THUMB |
355 | elf_hwcap &= ~HWCAP_THUMB; | 355 | elf_hwcap &= ~HWCAP_THUMB; |
356 | #endif | 356 | #endif |
357 | #ifndef CONFIG_VFP | ||
358 | elf_hwcap &= ~HWCAP_VFP; | ||
359 | #endif | ||
360 | 357 | ||
361 | cpu_proc_init(); | 358 | cpu_proc_init(); |
362 | } | 359 | } |
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 8628ed29a955..080efac9d9ff 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S | |||
@@ -480,7 +480,7 @@ __arm926_proc_info: | |||
480 | b __arm926_setup | 480 | b __arm926_setup |
481 | .long cpu_arch_name | 481 | .long cpu_arch_name |
482 | .long cpu_elf_name | 482 | .long cpu_elf_name |
483 | .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA | 483 | .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA |
484 | .long cpu_arm926_name | 484 | .long cpu_arm926_name |
485 | .long arm926_processor_functions | 485 | .long arm926_processor_functions |
486 | .long v4wbi_tlb_fns | 486 | .long v4wbi_tlb_fns |
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index b440c8a1d345..c40baf8a47f0 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S | |||
@@ -207,11 +207,6 @@ __v6_setup: | |||
207 | #endif | 207 | #endif |
208 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 | 208 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 |
209 | #endif /* CONFIG_MMU */ | 209 | #endif /* CONFIG_MMU */ |
210 | #ifdef CONFIG_VFP | ||
211 | mrc p15, 0, r0, c1, c0, 2 | ||
212 | orr r0, r0, #(0xf << 20) | ||
213 | mcr p15, 0, r0, c1, c0, 2 @ Enable full access to VFP | ||
214 | #endif | ||
215 | adr r5, v6_crval | 210 | adr r5, v6_crval |
216 | ldmia r5, {r5, r6} | 211 | ldmia r5, {r5, r6} |
217 | mrc p15, 0, r0, c1, c0, 0 @ read control register | 212 | mrc p15, 0, r0, c1, c0, 0 @ read control register |
@@ -273,7 +268,7 @@ __v6_proc_info: | |||
273 | b __v6_setup | 268 | b __v6_setup |
274 | .long cpu_arch_name | 269 | .long cpu_arch_name |
275 | .long cpu_elf_name | 270 | .long cpu_elf_name |
276 | .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA | 271 | .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA |
277 | .long cpu_v6_name | 272 | .long cpu_v6_name |
278 | .long v6_processor_functions | 273 | .long v6_processor_functions |
279 | .long v6wbi_tlb_fns | 274 | .long v6wbi_tlb_fns |
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index f08eafbddcc1..e26cc1f59948 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c | |||
@@ -263,13 +263,24 @@ void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) | |||
263 | if (exceptions) | 263 | if (exceptions) |
264 | vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs); | 264 | vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs); |
265 | } | 265 | } |
266 | 266 | ||
267 | /* | 267 | /* |
268 | * VFP support code initialisation. | 268 | * VFP support code initialisation. |
269 | */ | 269 | */ |
270 | static int __init vfp_init(void) | 270 | static int __init vfp_init(void) |
271 | { | 271 | { |
272 | unsigned int vfpsid; | 272 | unsigned int vfpsid; |
273 | unsigned int cpu_arch = cpu_architecture(); | ||
274 | u32 access = 0; | ||
275 | |||
276 | if (cpu_arch >= CPU_ARCH_ARMv6) { | ||
277 | access = get_copro_access(); | ||
278 | |||
279 | /* | ||
280 | * Enable full access to VFP (cp10 and cp11) | ||
281 | */ | ||
282 | set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11)); | ||
283 | } | ||
273 | 284 | ||
274 | /* | 285 | /* |
275 | * First check that there is a VFP that we can use. | 286 | * First check that there is a VFP that we can use. |
@@ -281,6 +292,12 @@ static int __init vfp_init(void) | |||
281 | printk(KERN_INFO "VFP support v0.3: "); | 292 | printk(KERN_INFO "VFP support v0.3: "); |
282 | if (VFP_arch) { | 293 | if (VFP_arch) { |
283 | printk("not present\n"); | 294 | printk("not present\n"); |
295 | |||
296 | /* | ||
297 | * Restore the copro access register. | ||
298 | */ | ||
299 | if (cpu_arch >= CPU_ARCH_ARMv6) | ||
300 | set_copro_access(access); | ||
284 | } else if (vfpsid & FPSID_NODOUBLE) { | 301 | } else if (vfpsid & FPSID_NODOUBLE) { |
285 | printk("no double precision support\n"); | 302 | printk("no double precision support\n"); |
286 | } else { | 303 | } else { |
@@ -291,9 +308,16 @@ static int __init vfp_init(void) | |||
291 | (vfpsid & FPSID_PART_MASK) >> FPSID_PART_BIT, | 308 | (vfpsid & FPSID_PART_MASK) >> FPSID_PART_BIT, |
292 | (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, | 309 | (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, |
293 | (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); | 310 | (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); |
311 | |||
294 | vfp_vector = vfp_support_entry; | 312 | vfp_vector = vfp_support_entry; |
295 | 313 | ||
296 | thread_register_notifier(&vfp_notifier_block); | 314 | thread_register_notifier(&vfp_notifier_block); |
315 | |||
316 | /* | ||
317 | * We detected VFP, and the support code is | ||
318 | * in place; report VFP support to userspace. | ||
319 | */ | ||
320 | elf_hwcap |= HWCAP_VFP; | ||
297 | } | 321 | } |
298 | return 0; | 322 | return 0; |
299 | } | 323 | } |
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h index f05fbe31576c..f60faccf01fa 100644 --- a/include/asm-arm/system.h +++ b/include/asm-arm/system.h | |||
@@ -139,19 +139,36 @@ static inline int cpu_is_xsc3(void) | |||
139 | #define cpu_is_xscale() 1 | 139 | #define cpu_is_xscale() 1 |
140 | #endif | 140 | #endif |
141 | 141 | ||
142 | #define set_cr(x) \ | 142 | static inline unsigned int get_cr(void) |
143 | __asm__ __volatile__( \ | 143 | { |
144 | "mcr p15, 0, %0, c1, c0, 0 @ set CR" \ | 144 | unsigned int val; |
145 | : : "r" (x) : "cc") | 145 | asm("mrc p15, 0, %0, c1, c0, 0 @ get CR" : "=r" (val) : : "cc"); |
146 | 146 | return val; | |
147 | #define get_cr() \ | 147 | } |
148 | ({ \ | 148 | |
149 | unsigned int __val; \ | 149 | static inline void set_cr(unsigned int val) |
150 | __asm__ __volatile__( \ | 150 | { |
151 | "mrc p15, 0, %0, c1, c0, 0 @ get CR" \ | 151 | asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR" |
152 | : "=r" (__val) : : "cc"); \ | 152 | : : "r" (val) : "cc"); |
153 | __val; \ | 153 | } |
154 | }) | 154 | |
155 | #define CPACC_FULL(n) (3 << (n * 2)) | ||
156 | #define CPACC_SVC(n) (1 << (n * 2)) | ||
157 | #define CPACC_DISABLE(n) (0 << (n * 2)) | ||
158 | |||
159 | static inline unsigned int get_copro_access(void) | ||
160 | { | ||
161 | unsigned int val; | ||
162 | asm("mrc p15, 0, %0, c1, c0, 2 @ get copro access" | ||
163 | : "=r" (val) : : "cc"); | ||
164 | return val; | ||
165 | } | ||
166 | |||
167 | static inline void set_copro_access(unsigned int val) | ||
168 | { | ||
169 | asm volatile("mcr p15, 0, %0, c1, c0, 2 @ set copro access" | ||
170 | : : "r" (val) : "cc"); | ||
171 | } | ||
155 | 172 | ||
156 | extern unsigned long cr_no_alignment; /* defined in entry-armv.S */ | 173 | extern unsigned long cr_no_alignment; /* defined in entry-armv.S */ |
157 | extern unsigned long cr_alignment; /* defined in entry-armv.S */ | 174 | extern unsigned long cr_alignment; /* defined in entry-armv.S */ |