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