xref: /haiku/src/system/boot/arch/arm/arch_cpu.cpp (revision 49d7857e32a5c34fe63a11e46a41a774aa1b2728)
1 /*
2  * Copyright 2012, Haiku, Inc.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Ithamar R. Adema <ithamar@upgrade-android.com>
7  */
8 
9 #include "cpu.h"
10 
11 #include <OS.h>
12 #include <boot/platform.h>
13 #include <boot/stdio.h>
14 #include <boot/kernel_args.h>
15 #include <boot/stage2.h>
16 #include <arch/cpu.h>
17 #include <arch_kernel.h>
18 #include <arch_system_info.h>
19 #include <arch_cpu.h>
20 #include <string.h>
21 
22 #define TRACE_CPU
23 #ifdef TRACE_CPU
24 #	define TRACE(x) dprintf x
25 #else
26 #	define TRACE(x) ;
27 #endif
28 
29 /*! check_cpu_features
30  *
31  * Please note the fact that ARM7 and ARMv7 are two different things ;)
32  * ARMx is a specific ARM CPU core instance, while ARMvX refers to the
33  * ARM architecture specification version....
34  *
35  * Most of the architecture versions we're detecting here we will probably
36  * never run on, just included for completeness sake... ARMv5 and up are
37  * the likely ones for us to support (as they all have some kind of MMU).
38  */
39 
40 static status_t
41 check_cpu_features()
42 {
43 	uint32 result = 0;
44 	int arch, variant = 0, part = 0, revision = 0, implementor = 0;
45 
46 	asm volatile("MRC p15, 0, %[c1out], c0, c0, 0":[c1out] "=r" (result));
47 
48 	implementor = (result >> 24) & 0xff;
49 
50 	if (!(result & (1 << 19))) {
51 		switch((result >> 12) & 0xf) {
52 			case 0:	/* early ARMv3 or even older */
53 				arch = ARCH_ARM_PRE_ARM7;
54 				break;
55 
56 			case 7:	/* ARM7 processor */
57 				arch = (result & (1 << 23)) ? ARCH_ARM_v4T : ARCH_ARM_v3;
58 				variant = (result >> 16) & 0x7f;
59 				part = (result >> 4) & 0xfff;
60 				revision = result & 0xf;
61 				break;
62 
63 			default:
64 				revision = result & 0xf;
65 				part = (result >> 4) & 0xfff;
66 				switch((result >> 16) & 0xf) {
67 					case 1: arch = ARCH_ARM_v4; break;
68 					case 2: arch = ARCH_ARM_v4T; break;
69 					case 3: arch = ARCH_ARM_v5; break;
70 					case 4: arch = ARCH_ARM_v5T; break;
71 					case 5: arch = ARCH_ARM_v5TE; break;
72 					case 6: arch = ARCH_ARM_v5TEJ; break;
73 					case 7: arch = ARCH_ARM_v6; break;
74 					case 0xf: /* XXX TODO ARMv7 */; break;
75 				}
76 				variant = (result >> 20) & 0xf;
77 				break;
78 		}
79 	}
80 
81 	TRACE(("%s: implementor=0x%x('%c'), arch=%d, variant=0x%x, part=0x%x, revision=0x%x\n",
82 		__func__, implementor, implementor, arch, variant, part, revision));
83 
84 	return B_OK;
85 }
86 
87 //	#pragma mark -
88 
89 extern "C" void
90 arch_spin(bigtime_t microseconds)
91 {
92 	panic("No timing support in bootloader yet!");
93 }
94 
95 
96 extern "C" status_t
97 boot_arch_cpu_init(void)
98 {
99 	status_t err = check_cpu_features();
100 	if (err != B_OK) {
101 		panic("Retire your old Acorn and get something modern to boot!\n");
102 		return err;
103 	}
104 
105 	gKernelArgs.num_cpus = 1;
106 		// this will eventually be corrected later on
107 
108 	return B_OK;
109 }
110