xref: /haiku/src/system/boot/arch/arm/arch_cpu.cpp (revision e5d65858f2361fe0552495b61620c84dcee6bc00)
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 /*! Detect ARM core version and features.
30     Please note the fact that ARM7 and ARMv7 are two different things ;)
31     ARMx is a specific ARM CPU core instance, while ARMvX refers to the
32     ARM architecture specification version....
33 
34     Most of the architecture versions we're detecting here we will probably
35     never run on, just included for completeness sake... ARMv5 and up are
36     the likely ones for us to support (as they all have some kind of MMU).
37 */
38 static status_t
39 check_cpu_features()
40 {
41 	uint32 result = 0;
42 	int arch;
43 	int variant = 0;
44 	int part = 0;
45 	int revision = 0;
46 	int implementor = 0;
47 
48 	asm volatile("MRC p15, 0, %[c1out], c0, c0, 0":[c1out] "=r" (result));
49 
50 	implementor = (result >> 24) & 0xff;
51 
52 	if (!(result & (1 << 19))) {
53 		switch ((result >> 12) & 0xf) {
54 			case 0:	/* early ARMv3 or even older */
55 				arch = ARCH_ARM_PRE_ARM7;
56 				break;
57 
58 			case 7:	/* ARM7 processor */
59 				arch = (result & (1 << 23)) ? ARCH_ARM_v4T : ARCH_ARM_v3;
60 				variant = (result >> 16) & 0x7f;
61 				part = (result >> 4) & 0xfff;
62 				revision = result & 0xf;
63 				break;
64 
65 			default:
66 				revision = result & 0xf;
67 				part = (result >> 4) & 0xfff;
68 				switch((result >> 16) & 0xf) {
69 					case 1: arch = ARCH_ARM_v4; break;
70 					case 2: arch = ARCH_ARM_v4T; break;
71 					case 3: arch = ARCH_ARM_v5; break;
72 					case 4: arch = ARCH_ARM_v5T; break;
73 					case 5: arch = ARCH_ARM_v5TE; break;
74 					case 6: arch = ARCH_ARM_v5TEJ; break;
75 					case 7: arch = ARCH_ARM_v6; break;
76 					case 0xf: /* XXX TODO ARMv7 */; break;
77 				}
78 				variant = (result >> 20) & 0xf;
79 				break;
80 		}
81 	}
82 
83 	TRACE(("%s: implementor=0x%x('%c'), arch=%d, variant=0x%x, part=0x%x, revision=0x%x\n",
84 		__func__, implementor, implementor, arch, variant, part, revision));
85 
86 	return B_OK;
87 }
88 
89 
90 void
91 arch_cpu_memory_read_barrier(void)
92 {
93 	asm volatile ("" : : : "memory");
94 }
95 
96 
97 void
98 arch_cpu_memory_write_barrier(void)
99 {
100 	asm volatile ("" : : : "memory");
101 }
102 
103 
104 extern "C" void
105 arch_spin(bigtime_t microseconds)
106 {
107 	panic("No timing support in bootloader yet!");
108 }
109 
110 
111 extern "C" status_t
112 boot_arch_cpu_init(void)
113 {
114 	status_t err = check_cpu_features();
115 	if (err != B_OK) {
116 		panic("Retire your old Acorn and get something modern to boot!\n");
117 		return err;
118 	}
119 
120 	gKernelArgs.num_cpus = 1;
121 		// this will eventually be corrected later on
122 
123 	return B_OK;
124 }
125