]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Drivers/ArmGic/ArmGicLib.c
ArmPkg/ArmMmuLib: avoid type promotion in TCR_EL1 assignment
[mirror_edk2.git] / ArmPkg / Drivers / ArmGic / ArmGicLib.c
CommitLineData
397bdc99
OM
1/** @file\r
2*\r
8705cb38 3* Copyright (c) 2011-2015, ARM Limited. All rights reserved.\r
397bdc99
OM
4*\r
5* This program and the accompanying materials\r
6* are licensed and made available under the terms and conditions of the BSD License\r
7* which accompanies this distribution. The full text of the license may be found at\r
8* http://opensource.org/licenses/bsd-license.php\r
9*\r
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12*\r
13**/\r
14\r
60775c51 15#include <Base.h>\r
397bdc99 16#include <Library/ArmGicLib.h>\r
8705cb38 17#include <Library/ArmLib.h>\r
1b0ac0de 18#include <Library/DebugLib.h>\r
60775c51 19#include <Library/IoLib.h>\r
8705cb38 20#include <Library/PcdLib.h>\r
397bdc99 21\r
8705cb38
OM
22/**\r
23 * Return the base address of the GIC redistributor for the current CPU\r
24 *\r
25 * @param Revision GIC Revision. The GIC redistributor might have a different\r
26 * granularity following the GIC revision.\r
27 *\r
28 * @retval Base address of the associated GIC Redistributor\r
29 */\r
30STATIC\r
31UINTN\r
32GicGetCpuRedistributorBase (\r
33 IN UINTN GicRedistributorBase,\r
34 IN ARM_GIC_ARCH_REVISION Revision\r
35 )\r
36{\r
37 UINTN Index;\r
38 UINTN MpId;\r
39 UINTN CpuAffinity;\r
40 UINTN Affinity;\r
41 UINTN GicRedistributorGranularity;\r
42 UINTN GicCpuRedistributorBase;\r
43\r
44 MpId = ArmReadMpidr ();\r
45 // Define CPU affinity as Affinity0[0:8], Affinity1[9:15], Affinity2[16:23], Affinity3[24:32]\r
46 // whereas Affinity3 is defined at [32:39] in MPIDR\r
47 CpuAffinity = (MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2)) | ((MpId & ARM_CORE_AFF3) >> 8);\r
48\r
49 if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
50 // 2 x 64KB frame: Redistributor control frame + SGI Control & Generation frame\r
51 GicRedistributorGranularity = ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_SGI_PPI_FRAME_SIZE;\r
52 } else {\r
53 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
54 return 0;\r
55 }\r
56\r
57 GicCpuRedistributorBase = GicRedistributorBase;\r
58\r
59 for (Index = 0; Index < PcdGet32 (PcdCoreCount); Index++) {\r
60 Affinity = MmioRead64 (GicCpuRedistributorBase + ARM_GICR_TYPER) >> 32;\r
61 if (Affinity == CpuAffinity) {\r
62 return GicCpuRedistributorBase;\r
63 }\r
64\r
65 // Move to the next GIC Redistributor frame\r
66 GicRedistributorBase += GicRedistributorGranularity;\r
67 }\r
68\r
69 // The Redistributor has not been found for the current CPU\r
70 ASSERT_EFI_ERROR (EFI_NOT_FOUND);\r
71 return 0;\r
72}\r
73\r
397bdc99
OM
74UINTN\r
75EFIAPI\r
76ArmGicGetInterfaceIdentification (\r
77 IN INTN GicInterruptInterfaceBase\r
78 )\r
79{\r
80 // Read the GIC Identification Register\r
81 return MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIIDR);\r
82}\r
83\r
84UINTN\r
85EFIAPI\r
86ArmGicGetMaxNumInterrupts (\r
87 IN INTN GicDistributorBase\r
88 )\r
89{\r
90 return 32 * ((MmioRead32 (GicDistributorBase + ARM_GIC_ICDICTR) & 0x1F) + 1);\r
91}\r
92\r
93VOID\r
94EFIAPI\r
95ArmGicSendSgiTo (\r
96 IN INTN GicDistributorBase,\r
97 IN INTN TargetListFilter,\r
98 IN INTN CPUTargetList,\r
99 IN INTN SgiId\r
100 )\r
101{\r
102 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDSGIR, ((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16) | SgiId);\r
103}\r
104\r
1b0ac0de
OM
105/*\r
106 * Acknowledge and return the value of the Interrupt Acknowledge Register\r
107 *\r
108 * InterruptId is returned separately from the register value because in\r
109 * the GICv2 the register value contains the CpuId and InterruptId while\r
110 * in the GICv3 the register value is only the InterruptId.\r
111 *\r
112 * @param GicInterruptInterfaceBase Base Address of the GIC CPU Interface\r
113 * @param InterruptId InterruptId read from the Interrupt Acknowledge Register\r
114 *\r
115 * @retval value returned by the Interrupt Acknowledge Register\r
116 *\r
117 */\r
397bdc99
OM
118UINTN\r
119EFIAPI\r
120ArmGicAcknowledgeInterrupt (\r
1b0ac0de
OM
121 IN UINTN GicInterruptInterfaceBase,\r
122 OUT UINTN *InterruptId\r
397bdc99
OM
123 )\r
124{\r
1b0ac0de 125 UINTN Value;\r
d5c6b7fc
OM
126 ARM_GIC_ARCH_REVISION Revision;\r
127\r
128 Revision = ArmGicGetSupportedArchRevision ();\r
129 if (Revision == ARM_GIC_ARCH_REVISION_2) {\r
130 Value = ArmGicV2AcknowledgeInterrupt (GicInterruptInterfaceBase);\r
131 // InterruptId is required for the caller to know if a valid or spurious\r
132 // interrupt has been read\r
133 ASSERT (InterruptId != NULL);\r
134 if (InterruptId != NULL) {\r
135 *InterruptId = Value & ARM_GIC_ICCIAR_ACKINTID;\r
136 }\r
d7133859
OM
137 } else if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
138 Value = ArmGicV3AcknowledgeInterrupt ();\r
d5c6b7fc
OM
139 } else {\r
140 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
141 // Report Spurious interrupt which is what the above controllers would\r
142 // return if no interrupt was available\r
143 Value = 1023;\r
1b0ac0de
OM
144 }\r
145\r
146 return Value;\r
397bdc99
OM
147}\r
148\r
149VOID\r
150EFIAPI\r
151ArmGicEndOfInterrupt (\r
152 IN UINTN GicInterruptInterfaceBase,\r
153 IN UINTN Source\r
154 )\r
155{\r
d5c6b7fc
OM
156 ARM_GIC_ARCH_REVISION Revision;\r
157\r
158 Revision = ArmGicGetSupportedArchRevision ();\r
159 if (Revision == ARM_GIC_ARCH_REVISION_2) {\r
160 ArmGicV2EndOfInterrupt (GicInterruptInterfaceBase, Source);\r
d7133859
OM
161 } else if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
162 ArmGicV3EndOfInterrupt (Source);\r
d5c6b7fc
OM
163 } else {\r
164 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
165 }\r
397bdc99
OM
166}\r
167\r
168VOID\r
169EFIAPI\r
170ArmGicEnableInterrupt (\r
171 IN UINTN GicDistributorBase,\r
41fb5d46 172 IN UINTN GicRedistributorBase,\r
397bdc99
OM
173 IN UINTN Source\r
174 )\r
175{\r
41fb5d46
OM
176 UINT32 RegOffset;\r
177 UINTN RegShift;\r
178 ARM_GIC_ARCH_REVISION Revision;\r
179 UINTN GicCpuRedistributorBase;\r
397bdc99
OM
180\r
181 // Calculate enable register offset and bit position\r
182 RegOffset = Source / 32;\r
183 RegShift = Source % 32;\r
184\r
41fb5d46 185 Revision = ArmGicGetSupportedArchRevision ();\r
f6d46e29 186 if ((Revision == ARM_GIC_ARCH_REVISION_2) || FeaturePcdGet (PcdArmGicV3WithV2Legacy)) {\r
41fb5d46
OM
187 // Write set-enable register\r
188 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset), 1 << RegShift);\r
189 } else {\r
190 GicCpuRedistributorBase = GicGetCpuRedistributorBase (GicRedistributorBase, Revision);\r
191 if (GicCpuRedistributorBase == 0) {\r
192 ASSERT_EFI_ERROR (EFI_NOT_FOUND);\r
193 return;\r
194 }\r
195\r
196 // Write set-enable register\r
197 MmioWrite32 (GicCpuRedistributorBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ISENABLER + (4 * RegOffset), 1 << RegShift);\r
198 }\r
397bdc99
OM
199}\r
200\r
201VOID\r
202EFIAPI\r
203ArmGicDisableInterrupt (\r
204 IN UINTN GicDistributorBase,\r
41fb5d46 205 IN UINTN GicRedistributorBase,\r
397bdc99
OM
206 IN UINTN Source\r
207 )\r
208{\r
41fb5d46
OM
209 UINT32 RegOffset;\r
210 UINTN RegShift;\r
211 ARM_GIC_ARCH_REVISION Revision;\r
212 UINTN GicCpuRedistributorBase;\r
397bdc99
OM
213\r
214 // Calculate enable register offset and bit position\r
215 RegOffset = Source / 32;\r
216 RegShift = Source % 32;\r
217\r
41fb5d46 218 Revision = ArmGicGetSupportedArchRevision ();\r
f6d46e29 219 if ((Revision == ARM_GIC_ARCH_REVISION_2) || FeaturePcdGet (PcdArmGicV3WithV2Legacy)) {\r
41fb5d46
OM
220 // Write clear-enable register\r
221 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDICER + (4 * RegOffset), 1 << RegShift);\r
222 } else {\r
223 GicCpuRedistributorBase = GicGetCpuRedistributorBase (GicRedistributorBase, Revision);\r
224 if (GicCpuRedistributorBase == 0) {\r
225 return;\r
226 }\r
227\r
228 // Write clear-enable register\r
229 MmioWrite32 (GicCpuRedistributorBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ICENABLER + (4 * RegOffset), 1 << RegShift);\r
230 }\r
397bdc99
OM
231}\r
232\r
233BOOLEAN\r
234EFIAPI\r
235ArmGicIsInterruptEnabled (\r
236 IN UINTN GicDistributorBase,\r
41fb5d46 237 IN UINTN GicRedistributorBase,\r
397bdc99
OM
238 IN UINTN Source\r
239 )\r
240{\r
41fb5d46
OM
241 UINT32 RegOffset;\r
242 UINTN RegShift;\r
243 ARM_GIC_ARCH_REVISION Revision;\r
244 UINTN GicCpuRedistributorBase;\r
245 UINT32 Interrupts;\r
397bdc99
OM
246\r
247 // Calculate enable register offset and bit position\r
248 RegOffset = Source / 32;\r
249 RegShift = Source % 32;\r
250\r
41fb5d46 251 Revision = ArmGicGetSupportedArchRevision ();\r
f6d46e29 252 if ((Revision == ARM_GIC_ARCH_REVISION_2) || FeaturePcdGet (PcdArmGicV3WithV2Legacy)) {\r
41fb5d46
OM
253 Interrupts = ((MmioRead32 (GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset)) & (1 << RegShift)) != 0);\r
254 } else {\r
255 GicCpuRedistributorBase = GicGetCpuRedistributorBase (GicRedistributorBase, Revision);\r
256 if (GicCpuRedistributorBase == 0) {\r
257 return 0;\r
258 }\r
259\r
260 // Read set-enable register\r
261 Interrupts = MmioRead32 (GicCpuRedistributorBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ISENABLER + (4 * RegOffset));\r
262 }\r
263\r
264 return ((Interrupts & (1 << RegShift)) != 0);\r
397bdc99 265}\r
60775c51
OM
266\r
267VOID\r
268EFIAPI\r
269ArmGicDisableDistributor (\r
270 IN INTN GicDistributorBase\r
271 )\r
272{\r
273 // Disable Gic Distributor\r
274 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x0);\r
275}\r
62d441fb 276\r
793ca69f
OM
277VOID\r
278EFIAPI\r
279ArmGicEnableInterruptInterface (\r
280 IN INTN GicInterruptInterfaceBase\r
281 )\r
282{\r
d5c6b7fc
OM
283 ARM_GIC_ARCH_REVISION Revision;\r
284\r
285 Revision = ArmGicGetSupportedArchRevision ();\r
286 if (Revision == ARM_GIC_ARCH_REVISION_2) {\r
287 ArmGicV2EnableInterruptInterface (GicInterruptInterfaceBase);\r
d7133859
OM
288 } else if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
289 ArmGicV3EnableInterruptInterface ();\r
d5c6b7fc
OM
290 } else {\r
291 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
292 }\r
793ca69f
OM
293}\r
294\r
295VOID\r
296EFIAPI\r
297ArmGicDisableInterruptInterface (\r
298 IN INTN GicInterruptInterfaceBase\r
299 )\r
300{\r
d5c6b7fc
OM
301 ARM_GIC_ARCH_REVISION Revision;\r
302\r
303 Revision = ArmGicGetSupportedArchRevision ();\r
304 if (Revision == ARM_GIC_ARCH_REVISION_2) {\r
305 ArmGicV2DisableInterruptInterface (GicInterruptInterfaceBase);\r
d7133859
OM
306 } else if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
307 ArmGicV3DisableInterruptInterface ();\r
d5c6b7fc
OM
308 } else {\r
309 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
310 }\r
793ca69f 311}\r