]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArmCommon.c
d644cd33d2491d067868b44e19dcf276dad8a438
[mirror_edk2.git] / ArmPkg / Universal / Smbios / ProcessorSubClassDxe / SmbiosProcessorArmCommon.c
1 /** @file
2 Functions for processor information common to ARM and AARCH64.
3
4 Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
5 Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include <Uefi.h>
12 #include <IndustryStandard/ArmCache.h>
13 #include <IndustryStandard/ArmStdSmc.h>
14 #include <IndustryStandard/SmBios.h>
15 #include <Library/ArmLib.h>
16 #include <Library/ArmSmcLib.h>
17 #include <Library/BaseMemoryLib.h>
18
19 #include "SmbiosProcessor.h"
20
21 /** Returns the maximum cache level implemented by the current CPU.
22
23 @return The maximum cache level implemented.
24 **/
25 UINT8
26 SmbiosProcessorGetMaxCacheLevel (
27 VOID
28 )
29 {
30 CLIDR_DATA Clidr;
31 UINT8 CacheLevel;
32 UINT8 MaxCacheLevel;
33
34 MaxCacheLevel = 0;
35
36 // Read the CLIDR register to find out what caches are present.
37 Clidr.Data = ReadCLIDR ();
38
39 // Get the cache type for the L1 cache. If it's 0, there are no caches.
40 if (CLIDR_GET_CACHE_TYPE (Clidr.Data, 1) == ClidrCacheTypeNone) {
41 return 0;
42 }
43
44 for (CacheLevel = 1; CacheLevel <= MAX_ARM_CACHE_LEVEL; CacheLevel++) {
45 if (CLIDR_GET_CACHE_TYPE (Clidr.Data, CacheLevel) == ClidrCacheTypeNone) {
46 MaxCacheLevel = CacheLevel;
47 break;
48 }
49 }
50
51 return MaxCacheLevel;
52 }
53
54 /** Returns whether or not the specified cache level has separate I/D caches.
55
56 @param CacheLevel The cache level (L1, L2 etc.).
57
58 @return TRUE if the cache level has separate I/D caches, FALSE otherwise.
59 **/
60 BOOLEAN
61 SmbiosProcessorHasSeparateCaches (
62 UINT8 CacheLevel
63 )
64 {
65 CLIDR_CACHE_TYPE CacheType;
66 CLIDR_DATA Clidr;
67 BOOLEAN SeparateCaches;
68
69 SeparateCaches = FALSE;
70
71 Clidr.Data = ReadCLIDR ();
72
73 CacheType = CLIDR_GET_CACHE_TYPE (Clidr.Data, CacheLevel - 1);
74
75 if (CacheType == ClidrCacheTypeSeparate) {
76 SeparateCaches = TRUE;
77 }
78
79 return SeparateCaches;
80 }
81
82 /** Checks if ther ARM64 SoC ID SMC call is supported
83
84 @return Whether the ARM64 SoC ID call is supported.
85 **/
86 BOOLEAN
87 HasSmcArm64SocId (
88 VOID
89 )
90 {
91 ARM_SMC_ARGS Args;
92 INT32 SmcCallStatus;
93 BOOLEAN Arm64SocIdSupported;
94
95 Arm64SocIdSupported = FALSE;
96
97 Args.Arg0 = SMCCC_VERSION;
98 ArmCallSmc (&Args);
99 SmcCallStatus = (INT32)Args.Arg0;
100
101 if (SmcCallStatus < 0 || (SmcCallStatus >> 16) >= 1) {
102 Args.Arg0 = SMCCC_ARCH_FEATURES;
103 Args.Arg1 = SMCCC_ARCH_SOC_ID;
104 ArmCallSmc (&Args);
105
106 if (Args.Arg0 >= 0) {
107 Arm64SocIdSupported = TRUE;
108 }
109 }
110
111 return Arm64SocIdSupported;
112 }
113
114 /** Fetches the JEP106 code and SoC Revision.
115
116 @param Jep106Code JEP 106 code.
117 @param SocRevision SoC revision.
118
119 @retval EFI_SUCCESS Succeeded.
120 @retval EFI_UNSUPPORTED Failed.
121 **/
122 EFI_STATUS
123 SmbiosGetSmcArm64SocId (
124 OUT INT32 *Jep106Code,
125 OUT INT32 *SocRevision
126 )
127 {
128 ARM_SMC_ARGS Args;
129 INT32 SmcCallStatus;
130 EFI_STATUS Status;
131
132 Status = EFI_SUCCESS;
133
134 Args.Arg0 = SMCCC_ARCH_SOC_ID;
135 Args.Arg1 = 0;
136 ArmCallSmc (&Args);
137 SmcCallStatus = (INT32)Args.Arg0;
138
139 if (SmcCallStatus >= 0) {
140 *Jep106Code = (INT32)Args.Arg0;
141 } else {
142 Status = EFI_UNSUPPORTED;
143 }
144
145 Args.Arg0 = SMCCC_ARCH_SOC_ID;
146 Args.Arg1 = 1;
147 ArmCallSmc (&Args);
148 SmcCallStatus = (INT32)Args.Arg0;
149
150 if (SmcCallStatus >= 0) {
151 *SocRevision = (INT32)Args.Arg0;
152 } else {
153 Status = EFI_UNSUPPORTED;
154 }
155
156 return Status;
157 }
158
159 /** Returns a value for the Processor ID field that conforms to SMBIOS
160 requirements.
161
162 @return Processor ID.
163 **/
164 UINT64
165 SmbiosGetProcessorId (
166 VOID
167 )
168 {
169 INT32 Jep106Code;
170 INT32 SocRevision;
171 UINT64 ProcessorId;
172
173 if (HasSmcArm64SocId ()) {
174 SmbiosGetSmcArm64SocId (&Jep106Code, &SocRevision);
175 ProcessorId = ((UINT64)SocRevision << 32) | Jep106Code;
176 } else {
177 ProcessorId = ArmReadMidr ();
178 }
179
180 return ProcessorId;
181 }
182
183 /** Returns the external clock frequency.
184
185 @return The external clock frequency.
186 **/
187 UINTN
188 SmbiosGetExternalClockFrequency (
189 VOID
190 )
191 {
192 return ArmReadCntFrq ();
193 }
194
195 /** Returns the SMBIOS ProcessorFamily field value.
196
197 @return The value for the ProcessorFamily field.
198 **/
199 UINT8
200 SmbiosGetProcessorFamily (
201 VOID
202 )
203 {
204 return ProcessorFamilyIndicatorFamily2;
205 }
206
207 /** Returns the ProcessorFamily2 field value.
208
209 @return The value for the ProcessorFamily2 field.
210 **/
211 UINT16
212 SmbiosGetProcessorFamily2 (
213 VOID
214 )
215 {
216 UINTN MainIdRegister;
217 UINT16 ProcessorFamily2;
218
219 MainIdRegister = ArmReadMidr ();
220
221 if (((MainIdRegister >> 16) & 0xF) < 8) {
222 ProcessorFamily2 = ProcessorFamilyARM;
223 } else {
224 if (sizeof (VOID*) == 4) {
225 ProcessorFamily2 = ProcessorFamilyARMv7;
226 } else {
227 ProcessorFamily2 = ProcessorFamilyARMv8;
228 }
229 }
230
231 return ProcessorFamily2;
232 }
233
234 /** Returns the SMBIOS Processor Characteristics.
235
236 @return Processor Characteristics bitfield.
237 **/
238 PROCESSOR_CHARACTERISTIC_FLAGS
239 SmbiosGetProcessorCharacteristics (
240 VOID
241 )
242 {
243 PROCESSOR_CHARACTERISTIC_FLAGS Characteristics;
244
245 ZeroMem (&Characteristics, sizeof (Characteristics));
246
247 Characteristics.ProcessorArm64SocId = HasSmcArm64SocId ();
248
249 return Characteristics;
250 }