1 | /* |
2 | SPDX-FileCopyrightText: 2021 Alexey Minnekhanov <alexeymin@postmarketos.org> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
5 | */ |
6 | |
7 | #include "cpuinfo_arm.h" |
8 | |
9 | // don't even build the following code for non-ARM platforms |
10 | #ifdef BUILDING_FOR_ARM_TARGET |
11 | |
12 | namespace Solid |
13 | { |
14 | namespace Backends |
15 | { |
16 | namespace UDev |
17 | { |
18 | /** |
19 | * IDs list is based on code from lscpu-arm.c from util-linux project. |
20 | * You can also find them in Linux kernel source: |
21 | * https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/asm/cputype.h |
22 | * https://elixir.bootlin.com/linux/latest/source/arch/arm/include/asm/cputype.h |
23 | * There is also maintained list at https://github.com/bp0/armids |
24 | **/ |
25 | |
26 | // clang-format off |
27 | static const struct ArmIdPart armParts[] = { |
28 | {0x810, "ARM810" }, |
29 | {0x920, "ARM920" }, |
30 | {0x922, "ARM922" }, |
31 | {0x926, "ARM926" }, |
32 | {0x940, "ARM940" }, |
33 | {0x946, "ARM946" }, |
34 | {0x966, "ARM966" }, |
35 | {0xa20, "ARM1020" }, |
36 | {0xa22, "ARM1022" }, |
37 | {0xa26, "ARM1026" }, |
38 | {0xb02, "ARM11 MPCore" }, |
39 | {0xb36, "ARM1136" }, |
40 | {0xb56, "ARM1156" }, |
41 | {0xb76, "ARM1176" }, |
42 | {0xc05, "Cortex-A5" }, |
43 | {0xc07, "Cortex-A7" }, |
44 | {0xc08, "Cortex-A8" }, |
45 | {0xc09, "Cortex-A9" }, |
46 | {0xc0d, "Cortex-A17" }, |
47 | {0xc0e, "Cortex-A17" }, |
48 | {0xc0f, "Cortex-A15" }, |
49 | {0xc14, "Cortex-R4" }, |
50 | {0xc15, "Cortex-R5" }, |
51 | {0xc17, "Cortex-R7" }, |
52 | {0xc18, "Cortex-R8" }, |
53 | {0xc20, "Cortex-M0" }, |
54 | {0xc21, "Cortex-M1" }, |
55 | {0xc23, "Cortex-M3" }, |
56 | {0xc24, "Cortex-M4" }, |
57 | {0xc27, "Cortex-M7" }, |
58 | {0xc60, "Cortex-M0+" }, |
59 | {0xd01, "Cortex-A32" }, |
60 | {0xd03, "Cortex-A53" }, |
61 | {0xd04, "Cortex-A35" }, |
62 | {0xd05, "Cortex-A55" }, |
63 | {0xd06, "Cortex-A65" }, |
64 | {0xd07, "Cortex-A57" }, |
65 | {0xd08, "Cortex-A72" }, |
66 | {0xd09, "Cortex-A73" }, |
67 | {0xd0a, "Cortex-A75" }, |
68 | {0xd0b, "Cortex-A76" }, |
69 | {0xd0c, "Neoverse-N1" }, |
70 | {0xd0d, "Cortex-A77" }, |
71 | {0xd0e, "Cortex-A76AE" }, |
72 | {0xd13, "Cortex-R52" }, |
73 | {0xd20, "Cortex-M23" }, |
74 | {0xd21, "Cortex-M33" }, |
75 | {0xd40, "Neoverse-V1" }, |
76 | {0xd41, "Cortex-A78" }, |
77 | {0xd42, "Cortex-A78AE" }, |
78 | {0xd44, "Cortex-X1" }, |
79 | {0xd46, "Cortex-A510" }, |
80 | {0xd47, "Cortex-A710" }, |
81 | {0xd48, "Cortex-X2" }, |
82 | {0xd49, "Neoverse-N2" }, |
83 | {0xd4a, "Neoverse-E1" }, |
84 | {0xd4b, "Cortex-A78C" }, |
85 | {0xd4d, "Cortex-A715" }, |
86 | {-1, "unknown" }, |
87 | }; |
88 | // clang-format on |
89 | |
90 | static const struct ArmIdPart brcmParts[] = { |
91 | {0x0f, "Brahma B15" }, |
92 | {0x100, "Brahma B53" }, |
93 | {0x516, "ThunderX2 (Vulcan)" }, |
94 | {-1, "unknown" }, |
95 | }; |
96 | |
97 | static const struct ArmIdPart decParts[] = { |
98 | {0xa10, "SA110" }, |
99 | {0xa11, "SA1100" }, |
100 | {-1, "unknown" }, |
101 | }; |
102 | |
103 | static const struct ArmIdPart caviumParts[] = { |
104 | {0x0a0, "ThunderX" }, |
105 | {0x0a1, "ThunderX 88XX" }, |
106 | {0x0a2, "ThunderX 81XX" }, |
107 | {0x0a3, "ThunderX 83XX" }, |
108 | {0x0af, "ThunderX2 99xx" }, |
109 | {-1, "unknown" }, |
110 | }; |
111 | |
112 | static const struct ArmIdPart apmParts[] = { |
113 | {0x000, "X-Gene" }, |
114 | {-1, "unknown" }, |
115 | }; |
116 | |
117 | static const struct ArmIdPart qcomParts[] = { |
118 | {0x00f, "Scorpion" }, |
119 | {0x02d, "Scorpion" }, |
120 | {0x04d, "Krait" }, |
121 | {0x06f, "Krait 400" }, |
122 | {0x200, "Kryo" }, |
123 | {0x201, "Kryo Silver" }, |
124 | {0x205, "Kryo Gold" }, |
125 | {0x211, "Kryo" }, |
126 | {0x800, "Falkor V1/Kryo 2xx Gold" }, |
127 | {0x801, "Kryo 2xx Silver" }, |
128 | {0x802, "Kryo 3xx Gold" }, |
129 | {0x803, "Kryo 3xx Silver" }, |
130 | {0x804, "Kryo 4xx/5xx Gold" }, |
131 | {0x805, "Kryo 4xx/5xx Silver" }, |
132 | {0xc00, "Falkor" }, |
133 | {0xc01, "Saphira" }, |
134 | {-1, "unknown" }, |
135 | }; |
136 | |
137 | static const struct ArmIdPart samsungParts[] = { |
138 | {0x001, "exynos-m1" }, |
139 | {-1, "unknown" }, |
140 | }; |
141 | |
142 | static const struct ArmIdPart nvidiaParts[] = { |
143 | {0x000, "Denver" }, |
144 | {0x003, "Denver 2" }, |
145 | {0x004, "Carmel" }, |
146 | {-1, "unknown" }, |
147 | }; |
148 | |
149 | static const struct ArmIdPart marvellParts[] = { |
150 | {0x131, "Feroceon 88FR131" }, |
151 | {0x581, "PJ4/PJ4b" }, |
152 | {0x584, "PJ4B-MP" }, |
153 | {-1, "unknown" }, |
154 | }; |
155 | |
156 | static const struct ArmIdPart faradayParts[] = { |
157 | {0x526, "FA526" }, |
158 | {0x626, "FA626" }, |
159 | {-1, "unknown" }, |
160 | }; |
161 | |
162 | // clang-format off |
163 | static const struct ArmIdPart intelParts[] = { |
164 | {0x200, "i80200" }, |
165 | {0x210, "PXA250A" }, |
166 | {0x212, "PXA210A" }, |
167 | {0x242, "i80321-400" }, |
168 | {0x243, "i80321-600" }, |
169 | {0x290, "PXA250B/PXA26x" }, |
170 | {0x292, "PXA210B" }, |
171 | {0x2c2, "i80321-400-B0" }, |
172 | {0x2c3, "i80321-600-B0" }, |
173 | {0x2d0, "PXA250C/PXA255/PXA26x" }, |
174 | {0x2d2, "PXA210C" }, |
175 | {0x411, "PXA27x" }, |
176 | {0x41c, "IPX425-533" }, |
177 | {0x41d, "IPX425-400" }, |
178 | {0x41f, "IPX425-266" }, |
179 | {0x682, "PXA32x" }, |
180 | {0x683, "PXA930/PXA935" }, |
181 | {0x688, "PXA30x" }, |
182 | {0x689, "PXA31x" }, |
183 | {0xb11, "SA1110" }, |
184 | {0xc12, "IPX1200" }, |
185 | {-1, "unknown" }, |
186 | }; |
187 | // clang-format on |
188 | |
189 | static const struct ArmIdPart fujitsuParts[] = { |
190 | {0x001, "A64FX" }, |
191 | {-1, "unknown" }, |
192 | }; |
193 | |
194 | static const struct ArmIdPart hisiParts[] = { |
195 | {0xd01, "Kunpeng-920 (TSV110)" }, |
196 | {-1, "unknown" }, |
197 | }; |
198 | |
199 | static const struct ArmIdPart appleParts[] = { |
200 | {0x020, "Icestorm (A14)" }, |
201 | {0x021, "Firestorm (A14)" }, |
202 | {0x022, "Icestorm (M1)" }, |
203 | {0x023, "Firestorm (M1)" }, |
204 | {0x024, "Icestorm (M1 Pro)" }, |
205 | {0x025, "Firestorm (M1 Pro)" }, |
206 | {0x028, "Icestorm (M1 Max)" }, |
207 | {0x029, "Firestorm (M1 Max)" }, |
208 | {0x030, "Blizzard (A15)" }, |
209 | {0x031, "Avalanche (A15)" }, |
210 | {0x032, "Blizzard (M2)" }, |
211 | {0x033, "Avalanche (M2)" }, |
212 | {-1, "unknown" }, |
213 | }; |
214 | |
215 | static const struct ArmIdPart unknownPart[] = { |
216 | {-1, "unknown" }, |
217 | }; |
218 | |
219 | static const struct ArmCpuImplementer armHwImplementers[] = { |
220 | {0x41, armParts, "ARM" }, |
221 | {0x42, brcmParts, "Broadcom" }, |
222 | {0x43, caviumParts, "Cavium" }, |
223 | {0x44, decParts, "DEC" }, |
224 | {0x46, fujitsuParts, "FUJITSU" }, |
225 | {0x48, hisiParts, "HiSilicon" }, |
226 | {0x49, unknownPart, "Infineon" }, |
227 | {0x4d, unknownPart, "Motorola/Freescale" }, |
228 | {0x4e, nvidiaParts, "NVIDIA" }, |
229 | {0x50, apmParts, "APM" }, |
230 | {0x51, qcomParts, "Qualcomm" }, |
231 | {0x53, samsungParts, "Samsung" }, |
232 | {0x56, marvellParts, "Marvell" }, |
233 | {0x61, appleParts, "Apple" }, |
234 | {0x66, faradayParts, "Faraday" }, |
235 | {0x69, intelParts, "Intel" }, |
236 | {0xc0, unknownPart, "Ampere" }, |
237 | {-1, unknownPart, "unknown" }, |
238 | }; |
239 | |
240 | const ArmCpuImplementer *findArmCpuImplementer(int vendorId) |
241 | { |
242 | const ArmCpuImplementer *ret = nullptr; |
243 | for (int i = 0; armHwImplementers[i].id != -1; i++) { |
244 | if (armHwImplementers[i].id == vendorId) { |
245 | ret = &armHwImplementers[i]; |
246 | break; |
247 | } |
248 | } |
249 | return ret; |
250 | } |
251 | |
252 | /* |
253 | * The CPU part number is meaningless without referring to the CPU |
254 | * implementer: implementers are free to define their own part numbers |
255 | * which are permitted to clash with other implementer part numbers. |
256 | */ |
257 | QString findArmCpuModel(int vendorId, int modelId) |
258 | { |
259 | const ArmCpuImplementer *impl = findArmCpuImplementer(vendorId); |
260 | if (!impl) { |
261 | return QString(); |
262 | } |
263 | for (int i = 0; impl->parts[i].id != -1; i++) { |
264 | if (impl->parts[i].id == modelId) { |
265 | return QString::fromUtf8(impl->name) + QLatin1Char(' ') + QString::fromUtf8(impl->parts[i].name); |
266 | } |
267 | } |
268 | return QString(); |
269 | } |
270 | |
271 | } // namespace UDev |
272 | } // namespace Backends |
273 | } // namespace Solid |
274 | |
275 | #endif // BUILDING_FOR_ARM_TARGET |
276 | |