Vishal Bhoj | 82c8071 | 2015-12-15 21:13:33 +0530 | [diff] [blame] | 1 | /** @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 | */
|
| 26 | VOID
|
| 27 | EFIAPI
|
| 28 | ArmGicSetupNonSecure (
|
| 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 | */
|
| 72 | VOID
|
| 73 | EFIAPI
|
| 74 | ArmGicSetSecureInterrupts (
|
| 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 |
|
| 93 | VOID
|
| 94 | EFIAPI
|
| 95 | ArmGicEnableInterruptInterface (
|
| 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 |
|
| 111 | VOID
|
| 112 | EFIAPI
|
| 113 | ArmGicDisableInterruptInterface (
|
| 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 |
|
| 124 | VOID
|
| 125 | EFIAPI
|
| 126 | ArmGicEnableDistributor (
|
| 127 | IN INTN GicDistributorBase
|
| 128 | )
|
| 129 | {
|
| 130 | // Turn on the GIC distributor
|
| 131 | MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 1);
|
| 132 | }
|