]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2SecLib.c
ArmPkg/ArmGicDxe: Fix double GIC EIOR write per interrupt
[mirror_edk2.git] / ArmPkg / Drivers / ArmGic / GicV2 / ArmGicV2SecLib.c
CommitLineData
793ca69f
OM
1/** @file\r
2*\r
3* Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
4*\r
5* This program and the accompanying materials\r
6* are licensed and made available under the terms and conditions of the BSD License\r
7* which accompanies this distribution. The full text of the license may be found at\r
8* http://opensource.org/licenses/bsd-license.php\r
9*\r
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12*\r
13**/\r
14\r
15#include <Base.h>\r
16#include <Library/ArmLib.h>\r
17#include <Library/ArmPlatformLib.h>\r
18#include <Library/DebugLib.h>\r
19#include <Library/IoLib.h>\r
20#include <Library/ArmGicLib.h>\r
21\r
22/*\r
23 * This function configures the all interrupts to be Non-secure.\r
24 *\r
25 */\r
26VOID\r
27EFIAPI\r
28ArmGicV2SetupNonSecure (\r
29 IN UINTN MpId,\r
30 IN INTN GicDistributorBase,\r
31 IN INTN GicInterruptInterfaceBase\r
32 )\r
33{\r
34 UINTN InterruptId;\r
35 UINTN CachedPriorityMask;\r
36 UINTN Index;\r
37 UINTN MaxInterrupts;\r
38\r
39 CachedPriorityMask = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR);\r
40\r
41 // Set priority Mask so that no interrupts get through to CPU\r
42 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0);\r
43\r
44 InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR);\r
45 MaxInterrupts = ArmGicGetMaxNumInterrupts (GicDistributorBase);\r
46\r
47 // Only try to clear valid interrupts. Ignore spurious interrupts.\r
48 while ((InterruptId & 0x3FF) < MaxInterrupts) {\r
49 // Some of the SGI's are still pending, read Ack register and send End of Interrupt Signal\r
50 ArmGicEndOfInterrupt (GicInterruptInterfaceBase, InterruptId);\r
51\r
52 // Next\r
53 InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR);\r
54 }\r
55\r
56 // Only the primary core should set the Non Secure bit to the SPIs (Shared Peripheral Interrupt).\r
57 if (ArmPlatformIsPrimaryCore (MpId)) {\r
58 // Ensure all GIC interrupts are Non-Secure\r
59 for (Index = 0; Index < (MaxInterrupts / 32); Index++) {\r
60 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), 0xffffffff);\r
61 }\r
62 } else {\r
63 // The secondary cores only set the Non Secure bit to their banked PPIs\r
64 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR, 0xffffffff);\r
65 }\r
66\r
67 // Ensure all interrupts can get through the priority mask\r
68 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, CachedPriorityMask);\r
69}\r
70\r
71VOID\r
72EFIAPI\r
73ArmGicV2EnableInterruptInterface (\r
74 IN INTN GicInterruptInterfaceBase\r
75 )\r
76{\r
77 // Set Priority Mask to allow interrupts\r
78 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0x000000FF);\r
79\r
80 // Enable CPU interface in Secure world\r
81 // Enable CPU interface in Non-secure World\r
82 // Signal Secure Interrupts to CPU using FIQ line *\r
83 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR,\r
84 ARM_GIC_ICCICR_ENABLE_SECURE |\r
85 ARM_GIC_ICCICR_ENABLE_NS |\r
86 ARM_GIC_ICCICR_SIGNAL_SECURE_TO_FIQ);\r
87}\r
88\r
89VOID\r
90EFIAPI\r
91ArmGicV2DisableInterruptInterface (\r
92 IN INTN GicInterruptInterfaceBase\r
93 )\r
94{\r
95 UINT32 ControlValue;\r
96\r
97 // Disable CPU interface in Secure world and Non-secure World\r
98 ControlValue = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR);\r
99 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, ControlValue & ~(ARM_GIC_ICCICR_ENABLE_SECURE | ARM_GIC_ICCICR_ENABLE_NS));\r
100}\r