| 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 | {0x034, "Blizzard (M2 Pro)" }, |
| 213 | {0x035, "Avalanche (M2 Pro)" }, |
| 214 | {0x038, "Blizzard (M2 Max)" }, |
| 215 | {0x039, "Avalanche (M2 Max)" }, |
| 216 | {-1, "unknown" }, |
| 217 | }; |
| 218 | |
| 219 | static const struct ArmIdPart unknownPart[] = { |
| 220 | {-1, "unknown" }, |
| 221 | }; |
| 222 | |
| 223 | static const struct ArmCpuImplementer armHwImplementers[] = { |
| 224 | {0x41, armParts, "ARM" }, |
| 225 | {0x42, brcmParts, "Broadcom" }, |
| 226 | {0x43, caviumParts, "Cavium" }, |
| 227 | {0x44, decParts, "DEC" }, |
| 228 | {0x46, fujitsuParts, "FUJITSU" }, |
| 229 | {0x48, hisiParts, "HiSilicon" }, |
| 230 | {0x49, unknownPart, "Infineon" }, |
| 231 | {0x4d, unknownPart, "Motorola/Freescale" }, |
| 232 | {0x4e, nvidiaParts, "NVIDIA" }, |
| 233 | {0x50, apmParts, "APM" }, |
| 234 | {0x51, qcomParts, "Qualcomm" }, |
| 235 | {0x53, samsungParts, "Samsung" }, |
| 236 | {0x56, marvellParts, "Marvell" }, |
| 237 | {0x61, appleParts, "Apple" }, |
| 238 | {0x66, faradayParts, "Faraday" }, |
| 239 | {0x69, intelParts, "Intel" }, |
| 240 | {0xc0, unknownPart, "Ampere" }, |
| 241 | {-1, unknownPart, "unknown" }, |
| 242 | }; |
| 243 | |
| 244 | const ArmCpuImplementer *findArmCpuImplementer(int vendorId) |
| 245 | { |
| 246 | const ArmCpuImplementer *ret = nullptr; |
| 247 | for (int i = 0; armHwImplementers[i].id != -1; i++) { |
| 248 | if (armHwImplementers[i].id == vendorId) { |
| 249 | ret = &armHwImplementers[i]; |
| 250 | break; |
| 251 | } |
| 252 | } |
| 253 | return ret; |
| 254 | } |
| 255 | |
| 256 | /* |
| 257 | * The CPU part number is meaningless without referring to the CPU |
| 258 | * implementer: implementers are free to define their own part numbers |
| 259 | * which are permitted to clash with other implementer part numbers. |
| 260 | */ |
| 261 | QString findArmCpuModel(int vendorId, int modelId) |
| 262 | { |
| 263 | const ArmCpuImplementer *impl = findArmCpuImplementer(vendorId); |
| 264 | if (!impl) { |
| 265 | return QString(); |
| 266 | } |
| 267 | for (int i = 0; impl->parts[i].id != -1; i++) { |
| 268 | if (impl->parts[i].id == modelId) { |
| 269 | return QString::fromUtf8(impl->name) + QLatin1Char(' ') + QString::fromUtf8(impl->parts[i].name); |
| 270 | } |
| 271 | } |
| 272 | return QString(); |
| 273 | } |
| 274 | |
| 275 | } // namespace UDev |
| 276 | } // namespace Backends |
| 277 | } // namespace Solid |
| 278 | |
| 279 | #endif // BUILDING_FOR_ARM_TARGET |
| 280 | |