3 * Copyright (c) 2011-2015, ARM Limited. All rights reserved.
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
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.
16 #include <Library/ArmGicLib.h>
17 #include <Library/ArmLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/IoLib.h>
20 #include <Library/PcdLib.h>
22 #include "GicV2/ArmGicV2Lib.h"
23 #include "GicV3/ArmGicV3Lib.h"
26 * Return the base address of the GIC redistributor for the current CPU
28 * @param Revision GIC Revision. The GIC redistributor might have a different
29 * granularity following the GIC revision.
31 * @retval Base address of the associated GIC Redistributor
35 GicGetCpuRedistributorBase (
36 IN UINTN GicRedistributorBase
,
37 IN ARM_GIC_ARCH_REVISION Revision
44 UINTN GicRedistributorGranularity
;
45 UINTN GicCpuRedistributorBase
;
47 MpId
= ArmReadMpidr ();
48 // Define CPU affinity as Affinity0[0:8], Affinity1[9:15], Affinity2[16:23], Affinity3[24:32]
49 // whereas Affinity3 is defined at [32:39] in MPIDR
50 CpuAffinity
= (MpId
& (ARM_CORE_AFF0
| ARM_CORE_AFF1
| ARM_CORE_AFF2
)) | ((MpId
& ARM_CORE_AFF3
) >> 8);
52 if (Revision
== ARM_GIC_ARCH_REVISION_3
) {
53 // 2 x 64KB frame: Redistributor control frame + SGI Control & Generation frame
54 GicRedistributorGranularity
= ARM_GICR_CTLR_FRAME_SIZE
+ ARM_GICR_SGI_PPI_FRAME_SIZE
;
56 ASSERT_EFI_ERROR (EFI_UNSUPPORTED
);
60 GicCpuRedistributorBase
= GicRedistributorBase
;
62 for (Index
= 0; Index
< PcdGet32 (PcdCoreCount
); Index
++) {
63 Affinity
= MmioRead64 (GicCpuRedistributorBase
+ ARM_GICR_TYPER
) >> 32;
64 if (Affinity
== CpuAffinity
) {
65 return GicCpuRedistributorBase
;
68 // Move to the next GIC Redistributor frame
69 GicRedistributorBase
+= GicRedistributorGranularity
;
72 // The Redistributor has not been found for the current CPU
73 ASSERT_EFI_ERROR (EFI_NOT_FOUND
);
79 ArmGicGetInterfaceIdentification (
80 IN INTN GicInterruptInterfaceBase
83 // Read the GIC Identification Register
84 return MmioRead32 (GicInterruptInterfaceBase
+ ARM_GIC_ICCIIDR
);
89 ArmGicGetMaxNumInterrupts (
90 IN INTN GicDistributorBase
93 return 32 * ((MmioRead32 (GicDistributorBase
+ ARM_GIC_ICDICTR
) & 0x1F) + 1);
99 IN INTN GicDistributorBase
,
100 IN INTN TargetListFilter
,
101 IN INTN CPUTargetList
,
105 MmioWrite32 (GicDistributorBase
+ ARM_GIC_ICDSGIR
, ((TargetListFilter
& 0x3) << 24) | ((CPUTargetList
& 0xFF) << 16) | SgiId
);
109 * Acknowledge and return the value of the Interrupt Acknowledge Register
111 * InterruptId is returned separately from the register value because in
112 * the GICv2 the register value contains the CpuId and InterruptId while
113 * in the GICv3 the register value is only the InterruptId.
115 * @param GicInterruptInterfaceBase Base Address of the GIC CPU Interface
116 * @param InterruptId InterruptId read from the Interrupt Acknowledge Register
118 * @retval value returned by the Interrupt Acknowledge Register
123 ArmGicAcknowledgeInterrupt (
124 IN UINTN GicInterruptInterfaceBase
,
125 OUT UINTN
*InterruptId
129 ARM_GIC_ARCH_REVISION Revision
;
131 Revision
= ArmGicGetSupportedArchRevision ();
132 if (Revision
== ARM_GIC_ARCH_REVISION_2
) {
133 Value
= ArmGicV2AcknowledgeInterrupt (GicInterruptInterfaceBase
);
134 // InterruptId is required for the caller to know if a valid or spurious
135 // interrupt has been read
136 ASSERT (InterruptId
!= NULL
);
137 if (InterruptId
!= NULL
) {
138 *InterruptId
= Value
& ARM_GIC_ICCIAR_ACKINTID
;
140 } else if (Revision
== ARM_GIC_ARCH_REVISION_3
) {
141 Value
= ArmGicV3AcknowledgeInterrupt ();
143 ASSERT_EFI_ERROR (EFI_UNSUPPORTED
);
144 // Report Spurious interrupt which is what the above controllers would
145 // return if no interrupt was available
154 ArmGicEndOfInterrupt (
155 IN UINTN GicInterruptInterfaceBase
,
159 ARM_GIC_ARCH_REVISION Revision
;
161 Revision
= ArmGicGetSupportedArchRevision ();
162 if (Revision
== ARM_GIC_ARCH_REVISION_2
) {
163 ArmGicV2EndOfInterrupt (GicInterruptInterfaceBase
, Source
);
164 } else if (Revision
== ARM_GIC_ARCH_REVISION_3
) {
165 ArmGicV3EndOfInterrupt (Source
);
167 ASSERT_EFI_ERROR (EFI_UNSUPPORTED
);
173 ArmGicEnableInterrupt (
174 IN UINTN GicDistributorBase
,
175 IN UINTN GicRedistributorBase
,
181 ARM_GIC_ARCH_REVISION Revision
;
182 UINTN GicCpuRedistributorBase
;
184 // Calculate enable register offset and bit position
185 RegOffset
= Source
/ 32;
186 RegShift
= Source
% 32;
188 Revision
= ArmGicGetSupportedArchRevision ();
189 if (Revision
== ARM_GIC_ARCH_REVISION_2
) {
190 // Write set-enable register
191 MmioWrite32 (GicDistributorBase
+ ARM_GIC_ICDISER
+ (4 * RegOffset
), 1 << RegShift
);
193 GicCpuRedistributorBase
= GicGetCpuRedistributorBase (GicRedistributorBase
, Revision
);
194 if (GicCpuRedistributorBase
== 0) {
195 ASSERT_EFI_ERROR (EFI_NOT_FOUND
);
199 // Write set-enable register
200 MmioWrite32 (GicCpuRedistributorBase
+ ARM_GICR_CTLR_FRAME_SIZE
+ ARM_GICR_ISENABLER
+ (4 * RegOffset
), 1 << RegShift
);
206 ArmGicDisableInterrupt (
207 IN UINTN GicDistributorBase
,
208 IN UINTN GicRedistributorBase
,
214 ARM_GIC_ARCH_REVISION Revision
;
215 UINTN GicCpuRedistributorBase
;
217 // Calculate enable register offset and bit position
218 RegOffset
= Source
/ 32;
219 RegShift
= Source
% 32;
221 Revision
= ArmGicGetSupportedArchRevision ();
222 if (Revision
== ARM_GIC_ARCH_REVISION_2
) {
223 // Write clear-enable register
224 MmioWrite32 (GicDistributorBase
+ ARM_GIC_ICDICER
+ (4 * RegOffset
), 1 << RegShift
);
226 GicCpuRedistributorBase
= GicGetCpuRedistributorBase (GicRedistributorBase
, Revision
);
227 if (GicCpuRedistributorBase
== 0) {
231 // Write clear-enable register
232 MmioWrite32 (GicCpuRedistributorBase
+ ARM_GICR_CTLR_FRAME_SIZE
+ ARM_GICR_ICENABLER
+ (4 * RegOffset
), 1 << RegShift
);
238 ArmGicIsInterruptEnabled (
239 IN UINTN GicDistributorBase
,
240 IN UINTN GicRedistributorBase
,
246 ARM_GIC_ARCH_REVISION Revision
;
247 UINTN GicCpuRedistributorBase
;
250 // Calculate enable register offset and bit position
251 RegOffset
= Source
/ 32;
252 RegShift
= Source
% 32;
254 Revision
= ArmGicGetSupportedArchRevision ();
255 if (Revision
== ARM_GIC_ARCH_REVISION_2
) {
256 Interrupts
= ((MmioRead32 (GicDistributorBase
+ ARM_GIC_ICDISER
+ (4 * RegOffset
)) & (1 << RegShift
)) != 0);
258 GicCpuRedistributorBase
= GicGetCpuRedistributorBase (GicRedistributorBase
, Revision
);
259 if (GicCpuRedistributorBase
== 0) {
263 // Read set-enable register
264 Interrupts
= MmioRead32 (GicCpuRedistributorBase
+ ARM_GICR_CTLR_FRAME_SIZE
+ ARM_GICR_ISENABLER
+ (4 * RegOffset
));
267 return ((Interrupts
& (1 << RegShift
)) != 0);
272 ArmGicDisableDistributor (
273 IN INTN GicDistributorBase
276 // Disable Gic Distributor
277 MmioWrite32 (GicDistributorBase
+ ARM_GIC_ICDDCR
, 0x0);
282 ArmGicEnableInterruptInterface (
283 IN INTN GicInterruptInterfaceBase
286 ARM_GIC_ARCH_REVISION Revision
;
288 Revision
= ArmGicGetSupportedArchRevision ();
289 if (Revision
== ARM_GIC_ARCH_REVISION_2
) {
290 ArmGicV2EnableInterruptInterface (GicInterruptInterfaceBase
);
291 } else if (Revision
== ARM_GIC_ARCH_REVISION_3
) {
292 ArmGicV3EnableInterruptInterface ();
294 ASSERT_EFI_ERROR (EFI_UNSUPPORTED
);
300 ArmGicDisableInterruptInterface (
301 IN INTN GicInterruptInterfaceBase
304 ARM_GIC_ARCH_REVISION Revision
;
306 Revision
= ArmGicGetSupportedArchRevision ();
307 if (Revision
== ARM_GIC_ARCH_REVISION_2
) {
308 ArmGicV2DisableInterruptInterface (GicInterruptInterfaceBase
);
309 } else if (Revision
== ARM_GIC_ARCH_REVISION_3
) {
310 ArmGicV3DisableInterruptInterface ();
312 ASSERT_EFI_ERROR (EFI_UNSUPPORTED
);