blob: d097b8a457c8c3b4a0cf93b2f8b94d96ec526f23 [file] [log] [blame]
Vishal Bhoj82c80712015-12-15 21:13:33 +05301/** @file
2*
3* Copyright (c) 2011-2012, ARM Limited. All rights reserved.
4# Copyright (c) Huawei Technologies Co., Ltd. 2013. All rights reserved.
5*
6* This program and the accompanying materials
7* are licensed and made available under the terms and conditions of the BSD License
8* which accompanies this distribution. The full text of the license may be found at
9* http://opensource.org/licenses/bsd-license.php
10*
11* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13*
14**/
15
16#include <Base.h>
17#include <Library/ArmLib.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 */
26VOID
27EFIAPI
28ArmGicSetupNonSecure (
29 IN UINTN MpId,
30 IN INTN GicDistributorBase,
31 IN INTN GicInterruptInterfaceBase
32 )
33{
34 UINTN InterruptId;
35 UINTN CachedPriorityMask;
36 UINTN Index;
37
38 CachedPriorityMask = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR);
39
40 // Set priority Mask so that no interrupts get through to CPU
41 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0);
42
43 // Check if there are any pending interrupts
44 //TODO: could be extended to take Peripheral interrupts into consideration, but at the moment only SGI's are taken into consideration.
45 while(0 != (MmioRead32 (GicDistributorBase + ARM_GIC_ICDICPR) & 0xF)) {
46 // Some of the SGI's are still pending, read Ack register and send End of Interrupt Signal
47 InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR);
48
49 // Write to End of interrupt signal
50 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCEIOR, InterruptId);
51 }
52
53 // Only the primary core should set the Non Secure bit to the SPIs (Shared Peripheral Interrupt).
54 if (((MpId) & PcdGet32(PcdArmPrimaryCoreMask)) == PcdGet32(PcdArmPrimaryCore)) {
55 // Ensure all GIC interrupts are Non-Secure
56 for (Index = 0; Index < (ArmGicGetMaxNumInterrupts (GicDistributorBase) / 32); Index++) {
57 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), 0xffffffff);
58 }
59 } else {
60 // The secondary cores only set the Non Secure bit to their banked PPIs
61 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR, 0xffffffff);
62 }
63
64 // Ensure all interrupts can get through the priority mask
65 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, CachedPriorityMask);
66}
67
68/*
69 * This function configures the interrupts set by the mask to be secure.
70 *
71 */
72VOID
73EFIAPI
74ArmGicSetSecureInterrupts (
75 IN UINTN GicDistributorBase,
76 IN UINTN* GicSecureInterruptMask,
77 IN UINTN GicSecureInterruptMaskSize
78 )
79{
80 UINTN Index;
81 UINT32 InterruptStatus;
82
83 // We must not have more interrupts defined by the mask than the number of available interrupts
84 ASSERT(GicSecureInterruptMaskSize <= (ArmGicGetMaxNumInterrupts (GicDistributorBase) / 32));
85
86 // Set all the interrupts defined by the mask as Secure
87 for (Index = 0; Index < GicSecureInterruptMaskSize; Index++) {
88 InterruptStatus = MmioRead32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4));
89 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), InterruptStatus & (~GicSecureInterruptMask[Index]));
90 }
91}
92
93VOID
94EFIAPI
95ArmGicEnableInterruptInterface (
96 IN INTN GicInterruptInterfaceBase
97 )
98{
99 // Set Priority Mask to allow interrupts
100 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0x000000FF);
101
102 // Enable CPU interface in Secure world
103 // Enable CPU interface in Non-secure World
104 // Signal Secure Interrupts to CPU using FIQ line *
105 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR,
106 ARM_GIC_ICCICR_ENABLE_SECURE |
107 ARM_GIC_ICCICR_ENABLE_NS |
108 ARM_GIC_ICCICR_SIGNAL_SECURE_TO_FIQ);
109}
110
111VOID
112EFIAPI
113ArmGicDisableInterruptInterface (
114 IN INTN GicInterruptInterfaceBase
115 )
116{
117 UINT32 ControlValue;
118
119 // Disable CPU interface in Secure world and Non-secure World
120 ControlValue = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR);
121 MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, ControlValue & ~(ARM_GIC_ICCICR_ENABLE_SECURE | ARM_GIC_ICCICR_ENABLE_NS));
122}
123
124VOID
125EFIAPI
126ArmGicEnableDistributor (
127 IN INTN GicDistributorBase
128 )
129{
130 // Turn on the GIC distributor
131 MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 1);
132}