]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.c
cad3c13ba4c04fad54f8684445d63c0e41c7ddc2
[mirror_edk2.git] / ArmPkg / Library / ArmLib / ArmV7 / ArmV7Lib.c
1 /** @file
2
3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14 #include <Uefi.h>
15 #include <Chipset/ArmV7.h>
16 #include <Library/ArmLib.h>
17 #include <Library/BaseLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include "ArmV7Lib.h"
21 #include "ArmLibPrivate.h"
22
23 VOID
24 FillTranslationTable (
25 IN UINT32 *TranslationTable,
26 IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryRegion
27 )
28 {
29 UINT32 *Entry;
30 UINTN Sections;
31 UINTN Index;
32 UINT32 Attributes;
33 UINT32 PhysicalBase = MemoryRegion->PhysicalBase;
34
35 switch (MemoryRegion->Attributes) {
36 case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK:
37 Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK;
38 break;
39 case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH:
40 Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH;
41 break;
42 case ARM_MEMORY_REGION_ATTRIBUTE_DEVICE:
43 Attributes = TT_DESCRIPTOR_SECTION_DEVICE;
44 break;
45 case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED:
46 default:
47 Attributes = TT_DESCRIPTOR_SECTION_UNCACHED;
48 break;
49 }
50
51 Entry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase);
52 Sections = MemoryRegion->Length / TT_DESCRIPTOR_SECTION_SIZE;
53
54 for (Index = 0; Index < Sections; Index++) {
55 *Entry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes;
56 PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE;
57 }
58 }
59
60 VOID
61 EFIAPI
62 ArmConfigureMmu (
63 IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable,
64 OUT VOID **TranslationTableBase OPTIONAL,
65 OUT UINTN *TranslationTableSize OPTIONAL
66 )
67 {
68 VOID *TranslationTable;
69
70 // Allocate pages for translation table.
71 TranslationTable = AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_SIZE + TRANSLATION_TABLE_ALIGNMENT));
72 TranslationTable = (VOID *)(((UINTN)TranslationTable + TRANSLATION_TABLE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_ALIGNMENT_MASK);
73
74 if (TranslationTableBase != NULL) {
75 *TranslationTableBase = TranslationTable;
76 }
77
78 if (TranslationTableBase != NULL) {
79 *TranslationTableSize = TRANSLATION_TABLE_SIZE;
80 }
81
82 ZeroMem(TranslationTable, TRANSLATION_TABLE_SIZE);
83
84 ArmCleanInvalidateDataCache();
85 ArmInvalidateInstructionCache();
86 ArmInvalidateTlb();
87
88 ArmDisableDataCache();
89 ArmDisableInstructionCache();
90 ArmDisableMmu();
91
92 // Make sure nothing sneaked into the cache
93 ArmCleanInvalidateDataCache();
94 ArmInvalidateInstructionCache();
95
96 while (MemoryTable->Length != 0) {
97 FillTranslationTable(TranslationTable, MemoryTable);
98 MemoryTable++;
99 }
100
101 ArmSetTranslationTableBaseAddress(TranslationTable);
102
103 ArmSetDomainAccessControl(DOMAIN_ACCESS_CONTROL_NONE(15) |
104 DOMAIN_ACCESS_CONTROL_NONE(14) |
105 DOMAIN_ACCESS_CONTROL_NONE(13) |
106 DOMAIN_ACCESS_CONTROL_NONE(12) |
107 DOMAIN_ACCESS_CONTROL_NONE(11) |
108 DOMAIN_ACCESS_CONTROL_NONE(10) |
109 DOMAIN_ACCESS_CONTROL_NONE( 9) |
110 DOMAIN_ACCESS_CONTROL_NONE( 8) |
111 DOMAIN_ACCESS_CONTROL_NONE( 7) |
112 DOMAIN_ACCESS_CONTROL_NONE( 6) |
113 DOMAIN_ACCESS_CONTROL_NONE( 5) |
114 DOMAIN_ACCESS_CONTROL_NONE( 4) |
115 DOMAIN_ACCESS_CONTROL_NONE( 3) |
116 DOMAIN_ACCESS_CONTROL_NONE( 2) |
117 DOMAIN_ACCESS_CONTROL_NONE( 1) |
118 DOMAIN_ACCESS_CONTROL_MANAGER(0));
119
120 ArmEnableInstructionCache();
121 ArmEnableDataCache();
122 ArmEnableMmu();
123 }
124
125 ARM_CACHE_TYPE
126 EFIAPI
127 ArmCacheType (
128 VOID
129 )
130 {
131 return ARM_CACHE_TYPE_WRITE_BACK;
132 }
133
134 ARM_CACHE_ARCHITECTURE
135 EFIAPI
136 ArmCacheArchitecture (
137 VOID
138 )
139 {
140 UINT32 CLIDR = ReadCLIDR ();
141
142 return CLIDR; // BugBug Fix Me
143 }
144
145 BOOLEAN
146 EFIAPI
147 ArmDataCachePresent (
148 VOID
149 )
150 {
151 UINT32 CLIDR = ReadCLIDR ();
152
153 if ((CLIDR & 0x2) == 0x2) {
154 // Instruction cache exists
155 return TRUE;
156 }
157 if ((CLIDR & 0x7) == 0x4) {
158 // Unified cache
159 return TRUE;
160 }
161
162 return FALSE;
163 }
164
165 UINTN
166 EFIAPI
167 ArmDataCacheSize (
168 VOID
169 )
170 {
171 UINT32 NumSets;
172 UINT32 Associativity;
173 UINT32 LineSize;
174 UINT32 CCSIDR = ReadCCSIDR (0);
175
176 LineSize = (1 << (CCSIDR + 2));
177 Associativity = ((CCSIDR >> 3) & 0x3ff) + 1;
178 NumSets = ((CCSIDR >> 13) & 0x7fff) + 1;
179
180 // LineSize is in words (4 byte chunks)
181 return NumSets * Associativity * LineSize * 4;
182 }
183
184 UINTN
185 EFIAPI
186 ArmDataCacheAssociativity (
187 VOID
188 )
189 {
190 UINT32 CCSIDR = ReadCCSIDR (0);
191
192 return ((CCSIDR >> 3) & 0x3ff) + 1;
193 }
194
195 UINTN
196 ArmDataCacheSets (
197 VOID
198 )
199 {
200 UINT32 CCSIDR = ReadCCSIDR (0);
201
202 return ((CCSIDR >> 13) & 0x7fff) + 1;
203 }
204
205 UINTN
206 EFIAPI
207 ArmDataCacheLineLength (
208 VOID
209 )
210 {
211 UINT32 CCSIDR = ReadCCSIDR (0) & 7;
212
213 // * 4 converts to bytes
214 return (1 << (CCSIDR + 2)) * 4;
215 }
216
217 BOOLEAN
218 EFIAPI
219 ArmInstructionCachePresent (
220 VOID
221 )
222 {
223 UINT32 CLIDR = ReadCLIDR ();
224
225 if ((CLIDR & 1) == 1) {
226 // Instruction cache exists
227 return TRUE;
228 }
229 if ((CLIDR & 0x7) == 0x4) {
230 // Unified cache
231 return TRUE;
232 }
233
234 return FALSE;
235 }
236
237 UINTN
238 EFIAPI
239 ArmInstructionCacheSize (
240 VOID
241 )
242 {
243 UINT32 NumSets;
244 UINT32 Associativity;
245 UINT32 LineSize;
246 UINT32 CCSIDR = ReadCCSIDR (1);
247
248 LineSize = (1 << (CCSIDR + 2));
249 Associativity = ((CCSIDR >> 3) & 0x3ff) + 1;
250 NumSets = ((CCSIDR >> 13) & 0x7fff) + 1;
251
252 // LineSize is in words (4 byte chunks)
253 return NumSets * Associativity * LineSize * 4;
254 }
255
256 UINTN
257 EFIAPI
258 ArmInstructionCacheAssociativity (
259 VOID
260 )
261 {
262 UINT32 CCSIDR = ReadCCSIDR (1);
263
264 return ((CCSIDR >> 3) & 0x3ff) + 1;
265 // return 4;
266 }
267
268 UINTN
269 EFIAPI
270 ArmInstructionCacheSets (
271 VOID
272 )
273 {
274 UINT32 CCSIDR = ReadCCSIDR (1);
275
276 return ((CCSIDR >> 13) & 0x7fff) + 1;
277 }
278
279 UINTN
280 EFIAPI
281 ArmInstructionCacheLineLength (
282 VOID
283 )
284 {
285 UINT32 CCSIDR = ReadCCSIDR (1) & 7;
286
287 // * 4 converts to bytes
288 return (1 << (CCSIDR + 2)) * 4;
289
290 // return 64;
291 }
292
293
294 VOID
295 ArmV7DataCacheOperation (
296 IN ARM_V7_CACHE_OPERATION DataCacheOperation
297 )
298 {
299 UINTN SavedInterruptState;
300
301 SavedInterruptState = ArmGetInterruptState ();
302
303 ArmV7AllDataCachesOperation (DataCacheOperation);
304
305 ArmDrainWriteBuffer ();
306
307 if (SavedInterruptState) {
308 ArmEnableInterrupts ();
309 }
310 }
311
312 VOID
313 EFIAPI
314 ArmInvalidateDataCache (
315 VOID
316 )
317 {
318 ArmV7DataCacheOperation (ArmInvalidateDataCacheEntryBySetWay);
319 }
320
321 VOID
322 EFIAPI
323 ArmCleanInvalidateDataCache (
324 VOID
325 )
326 {
327 ArmV7DataCacheOperation (ArmCleanInvalidateDataCacheEntryBySetWay);
328 }
329
330 VOID
331 EFIAPI
332 ArmCleanDataCache (
333 VOID
334 )
335 {
336 ArmV7DataCacheOperation (ArmCleanDataCacheEntryBySetWay);
337 }