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