]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Drivers/ArmGic/ArmGicLib.c
ArmPkg/ArmGic: Function to locate the current CPU GIC redistributor
[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
793ca69f 22#include "GicV2/ArmGicV2Lib.h"\r
d7133859 23#include "GicV3/ArmGicV3Lib.h"\r
793ca69f 24\r
8705cb38
OM
25/**\r
26 * Return the base address of the GIC redistributor for the current CPU\r
27 *\r
28 * @param Revision GIC Revision. The GIC redistributor might have a different\r
29 * granularity following the GIC revision.\r
30 *\r
31 * @retval Base address of the associated GIC Redistributor\r
32 */\r
33STATIC\r
34UINTN\r
35GicGetCpuRedistributorBase (\r
36 IN UINTN GicRedistributorBase,\r
37 IN ARM_GIC_ARCH_REVISION Revision\r
38 )\r
39{\r
40 UINTN Index;\r
41 UINTN MpId;\r
42 UINTN CpuAffinity;\r
43 UINTN Affinity;\r
44 UINTN GicRedistributorGranularity;\r
45 UINTN GicCpuRedistributorBase;\r
46\r
47 MpId = ArmReadMpidr ();\r
48 // Define CPU affinity as Affinity0[0:8], Affinity1[9:15], Affinity2[16:23], Affinity3[24:32]\r
49 // whereas Affinity3 is defined at [32:39] in MPIDR\r
50 CpuAffinity = (MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2)) | ((MpId & ARM_CORE_AFF3) >> 8);\r
51\r
52 if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
53 // 2 x 64KB frame: Redistributor control frame + SGI Control & Generation frame\r
54 GicRedistributorGranularity = ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_SGI_PPI_FRAME_SIZE;\r
55 } else {\r
56 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
57 return 0;\r
58 }\r
59\r
60 GicCpuRedistributorBase = GicRedistributorBase;\r
61\r
62 for (Index = 0; Index < PcdGet32 (PcdCoreCount); Index++) {\r
63 Affinity = MmioRead64 (GicCpuRedistributorBase + ARM_GICR_TYPER) >> 32;\r
64 if (Affinity == CpuAffinity) {\r
65 return GicCpuRedistributorBase;\r
66 }\r
67\r
68 // Move to the next GIC Redistributor frame\r
69 GicRedistributorBase += GicRedistributorGranularity;\r
70 }\r
71\r
72 // The Redistributor has not been found for the current CPU\r
73 ASSERT_EFI_ERROR (EFI_NOT_FOUND);\r
74 return 0;\r
75}\r
76\r
397bdc99
OM
77UINTN\r
78EFIAPI\r
79ArmGicGetInterfaceIdentification (\r
80 IN INTN GicInterruptInterfaceBase\r
81 )\r
82{\r
83 // Read the GIC Identification Register\r
84 return MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIIDR);\r
85}\r
86\r
87UINTN\r
88EFIAPI\r
89ArmGicGetMaxNumInterrupts (\r
90 IN INTN GicDistributorBase\r
91 )\r
92{\r
93 return 32 * ((MmioRead32 (GicDistributorBase + ARM_GIC_ICDICTR) & 0x1F) + 1);\r
94}\r
95\r
96VOID\r
97EFIAPI\r
98ArmGicSendSgiTo (\r
99 IN INTN GicDistributorBase,\r
100 IN INTN TargetListFilter,\r
101 IN INTN CPUTargetList,\r
102 IN INTN SgiId\r
103 )\r
104{\r
105 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDSGIR, ((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16) | SgiId);\r
106}\r
107\r
1b0ac0de
OM
108/*\r
109 * Acknowledge and return the value of the Interrupt Acknowledge Register\r
110 *\r
111 * InterruptId is returned separately from the register value because in\r
112 * the GICv2 the register value contains the CpuId and InterruptId while\r
113 * in the GICv3 the register value is only the InterruptId.\r
114 *\r
115 * @param GicInterruptInterfaceBase Base Address of the GIC CPU Interface\r
116 * @param InterruptId InterruptId read from the Interrupt Acknowledge Register\r
117 *\r
118 * @retval value returned by the Interrupt Acknowledge Register\r
119 *\r
120 */\r
397bdc99
OM
121UINTN\r
122EFIAPI\r
123ArmGicAcknowledgeInterrupt (\r
1b0ac0de
OM
124 IN UINTN GicInterruptInterfaceBase,\r
125 OUT UINTN *InterruptId\r
397bdc99
OM
126 )\r
127{\r
1b0ac0de 128 UINTN Value;\r
d5c6b7fc
OM
129 ARM_GIC_ARCH_REVISION Revision;\r
130\r
131 Revision = ArmGicGetSupportedArchRevision ();\r
132 if (Revision == ARM_GIC_ARCH_REVISION_2) {\r
133 Value = ArmGicV2AcknowledgeInterrupt (GicInterruptInterfaceBase);\r
134 // InterruptId is required for the caller to know if a valid or spurious\r
135 // interrupt has been read\r
136 ASSERT (InterruptId != NULL);\r
137 if (InterruptId != NULL) {\r
138 *InterruptId = Value & ARM_GIC_ICCIAR_ACKINTID;\r
139 }\r
d7133859
OM
140 } else if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
141 Value = ArmGicV3AcknowledgeInterrupt ();\r
d5c6b7fc
OM
142 } else {\r
143 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
144 // Report Spurious interrupt which is what the above controllers would\r
145 // return if no interrupt was available\r
146 Value = 1023;\r
1b0ac0de
OM
147 }\r
148\r
149 return Value;\r
397bdc99
OM
150}\r
151\r
152VOID\r
153EFIAPI\r
154ArmGicEndOfInterrupt (\r
155 IN UINTN GicInterruptInterfaceBase,\r
156 IN UINTN Source\r
157 )\r
158{\r
d5c6b7fc
OM
159 ARM_GIC_ARCH_REVISION Revision;\r
160\r
161 Revision = ArmGicGetSupportedArchRevision ();\r
162 if (Revision == ARM_GIC_ARCH_REVISION_2) {\r
163 ArmGicV2EndOfInterrupt (GicInterruptInterfaceBase, Source);\r
d7133859
OM
164 } else if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
165 ArmGicV3EndOfInterrupt (Source);\r
d5c6b7fc
OM
166 } else {\r
167 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
168 }\r
397bdc99
OM
169}\r
170\r
171VOID\r
172EFIAPI\r
173ArmGicEnableInterrupt (\r
174 IN UINTN GicDistributorBase,\r
175 IN UINTN Source\r
176 )\r
177{\r
178 UINT32 RegOffset;\r
179 UINTN RegShift;\r
180\r
181 // Calculate enable register offset and bit position\r
182 RegOffset = Source / 32;\r
183 RegShift = Source % 32;\r
184\r
185 // Write set-enable register\r
186 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset), 1 << RegShift);\r
187}\r
188\r
189VOID\r
190EFIAPI\r
191ArmGicDisableInterrupt (\r
192 IN UINTN GicDistributorBase,\r
193 IN UINTN Source\r
194 )\r
195{\r
196 UINT32 RegOffset;\r
197 UINTN RegShift;\r
198\r
199 // Calculate enable register offset and bit position\r
200 RegOffset = Source / 32;\r
201 RegShift = Source % 32;\r
202\r
203 // Write clear-enable register\r
204 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDICER + (4 * RegOffset), 1 << RegShift);\r
205}\r
206\r
207BOOLEAN\r
208EFIAPI\r
209ArmGicIsInterruptEnabled (\r
210 IN UINTN GicDistributorBase,\r
211 IN UINTN Source\r
212 )\r
213{\r
214 UINT32 RegOffset;\r
215 UINTN RegShift;\r
216\r
217 // Calculate enable register offset and bit position\r
218 RegOffset = Source / 32;\r
219 RegShift = Source % 32;\r
220\r
221 return ((MmioRead32 (GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset)) & (1 << RegShift)) != 0);\r
222}\r
60775c51
OM
223\r
224VOID\r
225EFIAPI\r
226ArmGicDisableDistributor (\r
227 IN INTN GicDistributorBase\r
228 )\r
229{\r
230 // Disable Gic Distributor\r
231 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x0);\r
232}\r
62d441fb 233\r
793ca69f
OM
234VOID\r
235EFIAPI\r
236ArmGicEnableInterruptInterface (\r
237 IN INTN GicInterruptInterfaceBase\r
238 )\r
239{\r
d5c6b7fc
OM
240 ARM_GIC_ARCH_REVISION Revision;\r
241\r
242 Revision = ArmGicGetSupportedArchRevision ();\r
243 if (Revision == ARM_GIC_ARCH_REVISION_2) {\r
244 ArmGicV2EnableInterruptInterface (GicInterruptInterfaceBase);\r
d7133859
OM
245 } else if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
246 ArmGicV3EnableInterruptInterface ();\r
d5c6b7fc
OM
247 } else {\r
248 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
249 }\r
793ca69f
OM
250}\r
251\r
252VOID\r
253EFIAPI\r
254ArmGicDisableInterruptInterface (\r
255 IN INTN GicInterruptInterfaceBase\r
256 )\r
257{\r
d5c6b7fc
OM
258 ARM_GIC_ARCH_REVISION Revision;\r
259\r
260 Revision = ArmGicGetSupportedArchRevision ();\r
261 if (Revision == ARM_GIC_ARCH_REVISION_2) {\r
262 ArmGicV2DisableInterruptInterface (GicInterruptInterfaceBase);\r
d7133859
OM
263 } else if (Revision == ARM_GIC_ARCH_REVISION_3) {\r
264 ArmGicV3DisableInterruptInterface ();\r
d5c6b7fc
OM
265 } else {\r
266 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);\r
267 }\r
793ca69f 268}\r