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/ArmLib.h>
17 #include <Library/ArmPlatformLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/IoLib.h>
20 #include <Library/ArmGicLib.h>
21
22 /*
23 * This function configures the all interrupts to be Non-secure.
24 *
25 */
26 VOID
27 EFIAPI
ArmGicV2SetupNonSecure(IN UINTN MpId,IN INTN GicDistributorBase,IN INTN GicInterruptInterfaceBase)28 ArmGicV2SetupNonSecure (
29 IN UINTN MpId,
30 IN INTN GicDistributorBase,
31 IN INTN GicInterruptInterfaceBase
32 )
33 {
34 UINTN InterruptId;
35 UINTN CachedPriorityMask;
36 UINTN Index;
37 UINTN MaxInterrupts;
38
39 CachedPriorityMask = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR);
40
41 // Set priority Mask so that no interrupts get through to CPU
42 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0);
43
44 InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR);
45 MaxInterrupts = ArmGicGetMaxNumInterrupts (GicDistributorBase);
46
47 // Only try to clear valid interrupts. Ignore spurious interrupts.
48 while ((InterruptId & 0x3FF) < MaxInterrupts) {
49 // Some of the SGI's are still pending, read Ack register and send End of Interrupt Signal
50 ArmGicEndOfInterrupt (GicInterruptInterfaceBase, InterruptId);
51
52 // Next
53 InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR);
54 }
55
56 // Only the primary core should set the Non Secure bit to the SPIs (Shared Peripheral Interrupt).
57 if (ArmPlatformIsPrimaryCore (MpId)) {
58 // Ensure all GIC interrupts are Non-Secure
59 for (Index = 0; Index < (MaxInterrupts / 32); Index++) {
60 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), 0xffffffff);
61 }
62 } else {
63 // The secondary cores only set the Non Secure bit to their banked PPIs
64 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR, 0xffffffff);
65 }
66
67 // Ensure all interrupts can get through the priority mask
68 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, CachedPriorityMask);
69 }
70
71 VOID
72 EFIAPI
ArmGicV2EnableInterruptInterface(IN INTN GicInterruptInterfaceBase)73 ArmGicV2EnableInterruptInterface (
74 IN INTN GicInterruptInterfaceBase
75 )
76 {
77 // Set Priority Mask to allow interrupts
78 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0x000000FF);
79
80 // Enable CPU interface in Secure world
81 // Enable CPU interface in Non-secure World
82 // Signal Secure Interrupts to CPU using FIQ line *
83 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR,
84 ARM_GIC_ICCICR_ENABLE_SECURE |
85 ARM_GIC_ICCICR_ENABLE_NS |
86 ARM_GIC_ICCICR_SIGNAL_SECURE_TO_FIQ);
87 }
88
89 VOID
90 EFIAPI
ArmGicV2DisableInterruptInterface(IN INTN GicInterruptInterfaceBase)91 ArmGicV2DisableInterruptInterface (
92 IN INTN GicInterruptInterfaceBase
93 )
94 {
95 UINT32 ControlValue;
96
97 // Disable CPU interface in Secure world and Non-secure World
98 ControlValue = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR);
99 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, ControlValue & ~(ARM_GIC_ICCICR_ENABLE_SECURE | ARM_GIC_ICCICR_ENABLE_NS));
100 }
101