]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Drivers/ArmGic/ArmGicLib.c
ArmPkg/ArmGic: Added GicV3 detection
[mirror_edk2.git] / ArmPkg / Drivers / ArmGic / ArmGicLib.c
1 /** @file
2 *
3 * Copyright (c) 2011-2014, ARM Limited. All rights reserved.
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
15 #include <Base.h>
16 #include <Library/ArmGicLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/IoLib.h>
19
20 #include "GicV2/ArmGicV2Lib.h"
21
22 UINTN
23 EFIAPI
24 ArmGicGetInterfaceIdentification (
25 IN INTN GicInterruptInterfaceBase
26 )
27 {
28 // Read the GIC Identification Register
29 return MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIIDR);
30 }
31
32 UINTN
33 EFIAPI
34 ArmGicGetMaxNumInterrupts (
35 IN INTN GicDistributorBase
36 )
37 {
38 return 32 * ((MmioRead32 (GicDistributorBase + ARM_GIC_ICDICTR) & 0x1F) + 1);
39 }
40
41 VOID
42 EFIAPI
43 ArmGicSendSgiTo (
44 IN INTN GicDistributorBase,
45 IN INTN TargetListFilter,
46 IN INTN CPUTargetList,
47 IN INTN SgiId
48 )
49 {
50 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDSGIR, ((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16) | SgiId);
51 }
52
53 /*
54 * Acknowledge and return the value of the Interrupt Acknowledge Register
55 *
56 * InterruptId is returned separately from the register value because in
57 * the GICv2 the register value contains the CpuId and InterruptId while
58 * in the GICv3 the register value is only the InterruptId.
59 *
60 * @param GicInterruptInterfaceBase Base Address of the GIC CPU Interface
61 * @param InterruptId InterruptId read from the Interrupt Acknowledge Register
62 *
63 * @retval value returned by the Interrupt Acknowledge Register
64 *
65 */
66 UINTN
67 EFIAPI
68 ArmGicAcknowledgeInterrupt (
69 IN UINTN GicInterruptInterfaceBase,
70 OUT UINTN *InterruptId
71 )
72 {
73 UINTN Value;
74 ARM_GIC_ARCH_REVISION Revision;
75
76 Revision = ArmGicGetSupportedArchRevision ();
77 if (Revision == ARM_GIC_ARCH_REVISION_2) {
78 Value = ArmGicV2AcknowledgeInterrupt (GicInterruptInterfaceBase);
79 // InterruptId is required for the caller to know if a valid or spurious
80 // interrupt has been read
81 ASSERT (InterruptId != NULL);
82 if (InterruptId != NULL) {
83 *InterruptId = Value & ARM_GIC_ICCIAR_ACKINTID;
84 }
85 } else {
86 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
87 // Report Spurious interrupt which is what the above controllers would
88 // return if no interrupt was available
89 Value = 1023;
90 }
91
92 return Value;
93 }
94
95 VOID
96 EFIAPI
97 ArmGicEndOfInterrupt (
98 IN UINTN GicInterruptInterfaceBase,
99 IN UINTN Source
100 )
101 {
102 ARM_GIC_ARCH_REVISION Revision;
103
104 Revision = ArmGicGetSupportedArchRevision ();
105 if (Revision == ARM_GIC_ARCH_REVISION_2) {
106 ArmGicV2EndOfInterrupt (GicInterruptInterfaceBase, Source);
107 } else {
108 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
109 }
110 }
111
112 VOID
113 EFIAPI
114 ArmGicEnableInterrupt (
115 IN UINTN GicDistributorBase,
116 IN UINTN Source
117 )
118 {
119 UINT32 RegOffset;
120 UINTN RegShift;
121
122 // Calculate enable register offset and bit position
123 RegOffset = Source / 32;
124 RegShift = Source % 32;
125
126 // Write set-enable register
127 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset), 1 << RegShift);
128 }
129
130 VOID
131 EFIAPI
132 ArmGicDisableInterrupt (
133 IN UINTN GicDistributorBase,
134 IN UINTN Source
135 )
136 {
137 UINT32 RegOffset;
138 UINTN RegShift;
139
140 // Calculate enable register offset and bit position
141 RegOffset = Source / 32;
142 RegShift = Source % 32;
143
144 // Write clear-enable register
145 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDICER + (4 * RegOffset), 1 << RegShift);
146 }
147
148 BOOLEAN
149 EFIAPI
150 ArmGicIsInterruptEnabled (
151 IN UINTN GicDistributorBase,
152 IN UINTN Source
153 )
154 {
155 UINT32 RegOffset;
156 UINTN RegShift;
157
158 // Calculate enable register offset and bit position
159 RegOffset = Source / 32;
160 RegShift = Source % 32;
161
162 return ((MmioRead32 (GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset)) & (1 << RegShift)) != 0);
163 }
164
165 VOID
166 EFIAPI
167 ArmGicDisableDistributor (
168 IN INTN GicDistributorBase
169 )
170 {
171 // Disable Gic Distributor
172 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x0);
173 }
174
175 VOID
176 EFIAPI
177 ArmGicEnableInterruptInterface (
178 IN INTN GicInterruptInterfaceBase
179 )
180 {
181 ARM_GIC_ARCH_REVISION Revision;
182
183 Revision = ArmGicGetSupportedArchRevision ();
184 if (Revision == ARM_GIC_ARCH_REVISION_2) {
185 ArmGicV2EnableInterruptInterface (GicInterruptInterfaceBase);
186 } else {
187 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
188 }
189 }
190
191 VOID
192 EFIAPI
193 ArmGicDisableInterruptInterface (
194 IN INTN GicInterruptInterfaceBase
195 )
196 {
197 ARM_GIC_ARCH_REVISION Revision;
198
199 Revision = ArmGicGetSupportedArchRevision ();
200 if (Revision == ARM_GIC_ARCH_REVISION_2) {
201 ArmGicV2DisableInterruptInterface (GicInterruptInterfaceBase);
202 } else {
203 ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
204 }
205 }