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 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 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 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