prism2.device: Compiler delint
[AROS.git] / arch / arm-linux / processor / arch_init.c
blob135d3bd6366df13ae7931175ffba08a362945b52
1 #include <aros/symbolsets.h>
2 #include <resources/processor.h>
3 #include <proto/alib.h>
4 #include <proto/exec.h>
5 #include <proto/hostlib.h>
7 #include <ctype.h>
8 #include <stdlib.h>
9 #include <string.h>
11 #include "arch_intern.h"
12 #include "processor_intern.h"
14 static char *getval(const char *key, char *s)
16 while (*key)
18 if (*key++ != *s++)
19 return NULL;
22 /* Skip whitespaces and colon */
23 while (*s && (isspace(*s) || (*s == ':')))
24 s++;
26 return s;
29 static ULONG ParseFlags(char *opts, const char * const *FlagNames)
31 ULONG ret = 0;
32 unsigned int i;
34 while (*opts)
36 /* Remember beginning of the word */
37 char *p = opts;
39 /* Find end of the word */
40 while (*opts && (!isspace(*opts)))
41 opts++;
43 if (*opts)
46 * If this is not the end of line, split the string and advance to the next char.
47 * Feature names are separated with one whitespace.
49 *opts++ = 0;
52 /* Decode flag name */
53 for (i = 0; FlagNames[i]; i++)
55 if (!strcmp(p, FlagNames[i]))
57 /* Set bit corresponding to number of flag name in the list */
58 ret |= (1UL << i);
59 break;
64 return ret;
68 * This is what can be reported by Linux kernel (see their arch/arm/kernel/setup.c).
69 * Order of these must be the same as order of family IDs.
71 static const char *arch_ids[] =
73 "3",
74 "4",
75 "4T",
76 "5",
77 "5T",
78 "5TE",
79 "5TEJ",
80 "6TEJ",
81 "7",
82 NULL
86 * Feature flags as reported by kernel (quote not everything is supported).
87 * Again, order of these repeats order of feature ID tags.
89 static const char *feature_ids[] =
91 "vfp",
92 "vfpv3",
93 "neon",
94 "thumb",
95 "thumbee",
96 NULL
99 #ifdef HOST_OS_android
100 #define LIBC_NAME "libc.so"
101 #else
102 #define LIBC_NAME "libc.so.6"
103 #endif
105 static const char *libc_symbols[] =
107 "fopen",
108 "fclose",
109 "fgets",
110 NULL
114 * Unfortunately CPU identification instructions on ARM requires supervisor privileges,
115 * so we can't use them on hosted. We can only ask host OS about our CPU.
116 * On Linux (and Android) we can do this only by parsing human-readable text in /proc/cpuinfo.
117 * We don't use unixio.hidd here because we want to start up as early as possible.
119 static ULONG arch_Init(struct ProcessorBase *ProcessorBase)
121 APTR HostLibBase, libc;
122 struct LibCInterface *iface;
123 ULONG i;
124 struct LinuxArmProcessor *data = NULL;
126 HostLibBase = OpenResource("hostlib.resource");
127 if (!HostLibBase)
128 return FALSE;
130 libc = HostLib_Open(LIBC_NAME, NULL);
131 if (!libc)
132 return FALSE;
134 iface = (struct LibCInterface *)HostLib_GetInterface(libc, libc_symbols, &i);
135 if (iface)
137 if (!i)
139 char *buf = AllocMem(BUFFER_SIZE, MEMF_ANY);
141 if (buf)
143 data = AllocMem(sizeof(struct LinuxArmProcessor), MEMF_CLEAR);
144 if (data)
146 UWORD variant = 0;
147 UWORD revision = 0;
148 void *file;
150 HostLib_Lock();
151 file = iface->fopen("/proc/cpuinfo", "r");
152 HostLib_Unlock();
154 if (file)
156 char *res;
160 HostLib_Lock();
161 res = iface->fgets(buf, BUFFER_SIZE - 1, file);
162 HostLib_Unlock();
164 if (res)
166 char *val;
168 i = strlen(buf);
169 if (i)
171 /* Strip the newline */
172 i--;
173 if (buf[i] == 0x0A)
174 buf[i] = 0;
176 if ((val = getval("Processor", buf)))
178 data->Model = StrDup(val);
180 else if ((val = getval("Features", buf)))
182 data->Features = ParseFlags(val, feature_ids);
184 else if ((val = getval("CPU implementer", buf)))
186 data->Implementer = strtoul(val, NULL, 0);
188 else if ((val = getval("CPU architecture", buf)))
190 ULONG family;
192 for (family = 0; arch_ids[family]; family++)
194 if (!strcmp(arch_ids[family], val))
196 data->Arch = family + CPUFAMILY_ARM_3;
197 break;
201 else if ((val = getval("CPU variant", buf)))
203 variant = strtoul(val, NULL, 0);
205 else if ((val = getval("CPU part", buf)))
207 data->Part = strtoul(val, NULL, 0);
209 else if ((val = getval("CPU revision", buf)))
211 revision = strtoul(val, NULL, 0);
215 } while (res);
217 HostLib_Lock();
218 iface->fclose(file);
219 HostLib_Unlock();
221 data->Version = (revision << 16) | variant;
223 /* Hack for qemu-arm support */
224 if (data->Arch == 0) {
225 data->Arch = CPUFAMILY_ARM_6;
226 data->Features |= FF_VFP;
230 FreeMem(buf, BUFFER_SIZE);
233 HostLib_DropInterface((void **)iface);
236 HostLib_Close(libc, NULL);
238 ProcessorBase->Private1 = data;
239 if (data)
241 if (data->Features & (FF_VFP | FF_VFPv3))
244 * Perhaps rather late, but i really would not like to duplicate this
245 * code in kernel.resource.
246 * Actually this definition can be used only by math code, i hope no
247 * floating-point operations are performed at early startup.
249 SysBase->AttnFlags |= AFF_FPU;
251 return TRUE;
253 else
254 return FALSE;
257 ADD2INITLIB(arch_Init, 1);