]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Drivers/ArmGic/ArmGicCommonDxe.c
ArmPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / ArmPkg / Drivers / ArmGic / ArmGicCommonDxe.c
CommitLineData
69b5dc9f
OM
1/*++\r
2\r
b0393756 3Copyright (c) 2013-2017, ARM Ltd. All rights reserved.<BR>\r
69b5dc9f 4\r
4059386c 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
69b5dc9f
OM
6\r
7--*/\r
8\r
9#include "ArmGicDxe.h"\r
10\r
11VOID\r
12EFIAPI\r
13IrqInterruptHandler (\r
14 IN EFI_EXCEPTION_TYPE InterruptType,\r
15 IN EFI_SYSTEM_CONTEXT SystemContext\r
16 );\r
17\r
18VOID\r
19EFIAPI\r
20ExitBootServicesEvent (\r
21 IN EFI_EVENT Event,\r
22 IN VOID *Context\r
23 );\r
24\r
69b5dc9f 25// Making this global saves a few bytes in image size\r
69b5dc9f
OM
26EFI_HANDLE gHardwareInterruptHandle = NULL;\r
27\r
69b5dc9f 28// Notifications\r
69b5dc9f
OM
29EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;\r
30\r
31// Maximum Number of Interrupts\r
32UINTN mGicNumInterrupts = 0;\r
33\r
34HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers = NULL;\r
35\r
8659306a
AB
36\r
37/**\r
38 Calculate GICD_ICFGRn base address and corresponding bit\r
39 field Int_config[1] of the GIC distributor register.\r
40\r
41 @param Source Hardware source of the interrupt.\r
42 @param RegAddress Corresponding GICD_ICFGRn base address.\r
43 @param Config1Bit Bit number of F Int_config[1] bit in the register.\r
44\r
45 @retval EFI_SUCCESS Source interrupt supported.\r
46 @retval EFI_UNSUPPORTED Source interrupt is not supported.\r
47**/\r
48EFI_STATUS\r
49GicGetDistributorIcfgBaseAndBit (\r
50 IN HARDWARE_INTERRUPT_SOURCE Source,\r
51 OUT UINTN *RegAddress,\r
52 OUT UINTN *Config1Bit\r
53 )\r
54{\r
55 UINTN RegIndex;\r
56 UINTN Field;\r
57\r
58 if (Source >= mGicNumInterrupts) {\r
59 ASSERT(Source < mGicNumInterrupts);\r
60 return EFI_UNSUPPORTED;\r
61 }\r
62\r
63 RegIndex = Source / ARM_GIC_ICDICFR_F_STRIDE; // NOTE: truncation is significant\r
64 Field = Source % ARM_GIC_ICDICFR_F_STRIDE;\r
65 *RegAddress = PcdGet64 (PcdGicDistributorBase)\r
66 + ARM_GIC_ICDICFR\r
67 + (ARM_GIC_ICDICFR_BYTES * RegIndex);\r
68 *Config1Bit = ((Field * ARM_GIC_ICDICFR_F_WIDTH)\r
69 + ARM_GIC_ICDICFR_F_CONFIG1_BIT);\r
70\r
71 return EFI_SUCCESS;\r
72}\r
73\r
74\r
75\r
0458b423
OM
76/**\r
77 Register Handler for the specified interrupt source.\r
78\r
79 @param This Instance pointer for this protocol\r
80 @param Source Hardware source of the interrupt\r
81 @param Handler Callback for interrupt. NULL to unregister\r
82\r
83 @retval EFI_SUCCESS Source was updated to support Handler.\r
84 @retval EFI_DEVICE_ERROR Hardware could not be programmed.\r
85\r
86**/\r
87EFI_STATUS\r
88EFIAPI\r
89RegisterInterruptSource (\r
90 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,\r
91 IN HARDWARE_INTERRUPT_SOURCE Source,\r
92 IN HARDWARE_INTERRUPT_HANDLER Handler\r
93 )\r
94{\r
599f004b 95 if (Source >= mGicNumInterrupts) {\r
0458b423
OM
96 ASSERT(FALSE);\r
97 return EFI_UNSUPPORTED;\r
98 }\r
99\r
100 if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {\r
101 return EFI_INVALID_PARAMETER;\r
102 }\r
103\r
104 if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {\r
105 return EFI_ALREADY_STARTED;\r
106 }\r
107\r
108 gRegisteredInterruptHandlers[Source] = Handler;\r
109\r
110 // If the interrupt handler is unregistered then disable the interrupt\r
111 if (NULL == Handler){\r
112 return This->DisableInterruptSource (This, Source);\r
113 } else {\r
114 return This->EnableInterruptSource (This, Source);\r
115 }\r
116}\r
117\r
61a7b0ec
AB
118STATIC VOID *mCpuArchProtocolNotifyEventRegistration;\r
119\r
120STATIC\r
121VOID\r
122EFIAPI\r
123CpuArchEventProtocolNotify (\r
124 IN EFI_EVENT Event,\r
125 IN VOID *Context\r
126 )\r
127{\r
128 EFI_CPU_ARCH_PROTOCOL *Cpu;\r
129 EFI_STATUS Status;\r
130\r
131 // Get the CPU protocol that this driver requires.\r
132 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);\r
133 if (EFI_ERROR (Status)) {\r
134 return;\r
135 }\r
136\r
137 // Unregister the default exception handler.\r
138 Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, NULL);\r
139 if (EFI_ERROR (Status)) {\r
140 DEBUG ((DEBUG_ERROR, "%a: Cpu->RegisterInterruptHandler() - %r\n",\r
141 __FUNCTION__, Status));\r
142 return;\r
143 }\r
144\r
145 // Register to receive interrupts\r
146 Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ,\r
147 Context);\r
148 if (EFI_ERROR (Status)) {\r
149 DEBUG ((DEBUG_ERROR, "%a: Cpu->RegisterInterruptHandler() - %r\n",\r
150 __FUNCTION__, Status));\r
151 }\r
152\r
153 gBS->CloseEvent (Event);\r
154}\r
155\r
69b5dc9f
OM
156EFI_STATUS\r
157InstallAndRegisterInterruptService (\r
158 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *InterruptProtocol,\r
8659306a 159 IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *Interrupt2Protocol,\r
69b5dc9f
OM
160 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler,\r
161 IN EFI_EVENT_NOTIFY ExitBootServicesEvent\r
162 )\r
163{\r
164 EFI_STATUS Status;\r
b0393756
EL
165 CONST UINTN RihArraySize =\r
166 (sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);\r
69b5dc9f
OM
167\r
168 // Initialize the array for the Interrupt Handlers\r
b0393756 169 gRegisteredInterruptHandlers = AllocateZeroPool (RihArraySize);\r
69b5dc9f
OM
170 if (gRegisteredInterruptHandlers == NULL) {\r
171 return EFI_OUT_OF_RESOURCES;\r
172 }\r
173\r
174 Status = gBS->InstallMultipleProtocolInterfaces (\r
175 &gHardwareInterruptHandle,\r
b0393756
EL
176 &gHardwareInterruptProtocolGuid,\r
177 InterruptProtocol,\r
8659306a
AB
178 &gHardwareInterrupt2ProtocolGuid,\r
179 Interrupt2Protocol,\r
69b5dc9f
OM
180 NULL\r
181 );\r
182 if (EFI_ERROR (Status)) {\r
183 return Status;\r
184 }\r
185\r
61a7b0ec
AB
186 //\r
187 // Install the interrupt handler as soon as the CPU arch protocol appears.\r
188 //\r
189 EfiCreateProtocolNotifyEvent (\r
190 &gEfiCpuArchProtocolGuid,\r
191 TPL_CALLBACK,\r
192 CpuArchEventProtocolNotify,\r
193 InterruptHandler,\r
194 &mCpuArchProtocolNotifyEventRegistration);\r
69b5dc9f
OM
195\r
196 // Register for an ExitBootServicesEvent\r
b0393756
EL
197 Status = gBS->CreateEvent (\r
198 EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
199 TPL_NOTIFY,\r
200 ExitBootServicesEvent,\r
201 NULL,\r
202 &EfiExitBootServicesEvent\r
203 );\r
69b5dc9f
OM
204\r
205 return Status;\r
206}\r