diff --git a/ArmPkg/Drivers/ArmGic/ArmGicLib.c b/ArmPkg/Drivers/ArmGic/ArmGicLib.c index c0f3bfb4c2..666008638c 100644 --- a/ArmPkg/Drivers/ArmGic/ArmGicLib.c +++ b/ArmPkg/Drivers/ArmGic/ArmGicLib.c @@ -16,6 +16,8 @@ #include #include +#include "GicV2/ArmGicV2Lib.h" + UINTN EFIAPI ArmGicGetInterfaceIdentification ( @@ -53,8 +55,7 @@ ArmGicAcknowledgeInterrupt ( IN UINTN GicInterruptInterfaceBase ) { - // Read the Interrupt Acknowledge Register - return MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR); + return ArmGicV2AcknowledgeInterrupt (GicInterruptInterfaceBase); } VOID @@ -64,7 +65,7 @@ ArmGicEndOfInterrupt ( IN UINTN Source ) { - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCEIOR, Source); + ArmGicV2EndOfInterrupt (GicInterruptInterfaceBase, Source); } VOID @@ -129,3 +130,21 @@ ArmGicDisableDistributor ( // Disable Gic Distributor MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x0); } + +VOID +EFIAPI +ArmGicEnableInterruptInterface ( + IN INTN GicInterruptInterfaceBase + ) +{ + return ArmGicV2EnableInterruptInterface (GicInterruptInterfaceBase); +} + +VOID +EFIAPI +ArmGicDisableInterruptInterface ( + IN INTN GicInterruptInterfaceBase + ) +{ + return ArmGicV2DisableInterruptInterface (GicInterruptInterfaceBase); +} diff --git a/ArmPkg/Drivers/ArmGic/ArmGicLib.inf b/ArmPkg/Drivers/ArmGic/ArmGicLib.inf index a6e9d7e676..a3e110e69f 100644 --- a/ArmPkg/Drivers/ArmGic/ArmGicLib.inf +++ b/ArmPkg/Drivers/ArmGic/ArmGicLib.inf @@ -23,6 +23,9 @@ ArmGicLib.c ArmGicNonSecLib.c + GicV2/ArmGicV2Lib.c + GicV2/ArmGicV2NonSecLib.c + [LibraryClasses] IoLib diff --git a/ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c b/ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c index 3ff9b4888c..06367f9d77 100644 --- a/ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c +++ b/ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c @@ -16,31 +16,6 @@ #include #include - -VOID -EFIAPI -ArmGicEnableInterruptInterface ( - IN INTN GicInterruptInterfaceBase - ) -{ - /* - * Enable the CPU interface in Non-Secure world - * Note: The ICCICR register is banked when Security extensions are implemented - */ - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, 0x1); -} - -VOID -EFIAPI -ArmGicDisableInterruptInterface ( - IN INTN GicInterruptInterfaceBase - ) -{ - // Disable Gic Interface - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, 0x0); - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0x0); -} - VOID EFIAPI ArmGicEnableDistributor ( diff --git a/ArmPkg/Drivers/ArmGic/ArmGicSecLib.c b/ArmPkg/Drivers/ArmGic/ArmGicSecLib.c index f249eac36a..1fdd4d73bd 100644 --- a/ArmPkg/Drivers/ArmGic/ArmGicSecLib.c +++ b/ArmPkg/Drivers/ArmGic/ArmGicSecLib.c @@ -1,70 +1,23 @@ /** @file * -* Copyright (c) 2011-2013, ARM Limited. All rights reserved. -* -* This program and the accompanying materials -* are licensed and made available under the terms and conditions of the BSD License -* which accompanies this distribution. The full text of the license may be found at -* http://opensource.org/licenses/bsd-license.php +* Copyright (c) 2011-2014, ARM Limited. All rights reserved. * -* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. * **/ #include -#include -#include #include #include #include -/* - * This function configures the all interrupts to be Non-secure. - * - */ -VOID -EFIAPI -ArmGicSetupNonSecure ( - IN UINTN MpId, - IN INTN GicDistributorBase, - IN INTN GicInterruptInterfaceBase - ) -{ - UINTN InterruptId; - UINTN CachedPriorityMask; - UINTN Index; - - CachedPriorityMask = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR); - - // Set priority Mask so that no interrupts get through to CPU - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0); - - InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR); - - // Only try to clear valid interrupts. Ignore spurious interrupts. - while ((InterruptId & 0x3FF) < ArmGicGetMaxNumInterrupts (GicDistributorBase)) { - // Some of the SGI's are still pending, read Ack register and send End of Interrupt Signal - ArmGicEndOfInterrupt (GicInterruptInterfaceBase, InterruptId); - - // Next - InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR); - } - - // Only the primary core should set the Non Secure bit to the SPIs (Shared Peripheral Interrupt). - if (ArmPlatformIsPrimaryCore (MpId)) { - // Ensure all GIC interrupts are Non-Secure - for (Index = 0; Index < (ArmGicGetMaxNumInterrupts (GicDistributorBase) / 32); Index++) { - MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), 0xffffffff); - } - } else { - // The secondary cores only set the Non Secure bit to their banked PPIs - MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR, 0xffffffff); - } - - // Ensure all interrupts can get through the priority mask - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, CachedPriorityMask); -} +#include "GicV2/ArmGicV2Lib.h" /* * This function configures the interrupts set by the mask to be secure. @@ -91,37 +44,6 @@ ArmGicSetSecureInterrupts ( } } -VOID -EFIAPI -ArmGicEnableInterruptInterface ( - IN INTN GicInterruptInterfaceBase - ) -{ - // Set Priority Mask to allow interrupts - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0x000000FF); - - // Enable CPU interface in Secure world - // Enable CPU interface in Non-secure World - // Signal Secure Interrupts to CPU using FIQ line * - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, - ARM_GIC_ICCICR_ENABLE_SECURE | - ARM_GIC_ICCICR_ENABLE_NS | - ARM_GIC_ICCICR_SIGNAL_SECURE_TO_FIQ); -} - -VOID -EFIAPI -ArmGicDisableInterruptInterface ( - IN INTN GicInterruptInterfaceBase - ) -{ - UINT32 ControlValue; - - // Disable CPU interface in Secure world and Non-secure World - ControlValue = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR); - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, ControlValue & ~(ARM_GIC_ICCICR_ENABLE_SECURE | ARM_GIC_ICCICR_ENABLE_NS)); -} - VOID EFIAPI ArmGicEnableDistributor ( @@ -131,3 +53,14 @@ ArmGicEnableDistributor ( // Turn on the GIC distributor MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 1); } + +VOID +EFIAPI +ArmGicSetupNonSecure ( + IN UINTN MpId, + IN INTN GicDistributorBase, + IN INTN GicInterruptInterfaceBase + ) +{ + ArmGicV2SetupNonSecure (MpId, GicDistributorBase, GicInterruptInterfaceBase); +} diff --git a/ArmPkg/Drivers/ArmGic/ArmGicSecLib.inf b/ArmPkg/Drivers/ArmGic/ArmGicSecLib.inf index 0b25c8e093..439bb91dae 100644 --- a/ArmPkg/Drivers/ArmGic/ArmGicSecLib.inf +++ b/ArmPkg/Drivers/ArmGic/ArmGicSecLib.inf @@ -23,6 +23,9 @@ ArmGicLib.c ArmGicSecLib.c + GicV2/ArmGicV2Lib.c + GicV2/ArmGicV2SecLib.c + [Packages] ArmPkg/ArmPkg.dec ArmPlatformPkg/ArmPlatformPkg.dec diff --git a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.c b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.c new file mode 100644 index 0000000000..5ac1d89ac5 --- /dev/null +++ b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.c @@ -0,0 +1,36 @@ +/** @file +* +* Copyright (c) 2013-2014, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include +#include + +UINTN +EFIAPI +ArmGicV2AcknowledgeInterrupt ( + IN UINTN GicInterruptInterfaceBase + ) +{ + // Read the Interrupt Acknowledge Register + return MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR); +} + +VOID +EFIAPI +ArmGicV2EndOfInterrupt ( + IN UINTN GicInterruptInterfaceBase, + IN UINTN Source + ) +{ + MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCEIOR, Source); +} diff --git a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.h b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.h new file mode 100644 index 0000000000..bfe9040c83 --- /dev/null +++ b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.h @@ -0,0 +1,101 @@ +/** @file +* +* Copyright (c) 2013-2014, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#ifndef _ARM_GIC_V2_H_ +#define _ARM_GIC_V2_H_ + +// +// GIC definitions +// + +// +// GIC Distributor +// +#define ARM_GIC_ICDDCR 0x000 // Distributor Control Register +#define ARM_GIC_ICDICTR 0x004 // Interrupt Controller Type Register +#define ARM_GIC_ICDIIDR 0x008 // Implementer Identification Register + +// Each reg base below repeats for VE_NUM_ARM_GIC_REG_PER_INT_BITS (see GIC spec) +#define ARM_GIC_ICDISR 0x080 // Interrupt Security Registers +#define ARM_GIC_ICDISER 0x100 // Interrupt Set-Enable Registers +#define ARM_GIC_ICDICER 0x180 // Interrupt Clear-Enable Registers +#define ARM_GIC_ICDSPR 0x200 // Interrupt Set-Pending Registers +#define ARM_GIC_ICDICPR 0x280 // Interrupt Clear-Pending Registers +#define ARM_GIC_ICDABR 0x300 // Active Bit Registers + +// Each reg base below repeats for VE_NUM_ARM_GIC_REG_PER_INT_BYTES +#define ARM_GIC_ICDIPR 0x400 // Interrupt Priority Registers + +// Each reg base below repeats for VE_NUM_ARM_GIC_INTERRUPTS +#define ARM_GIC_ICDIPTR 0x800 // Interrupt Processor Target Registers +#define ARM_GIC_ICDICFR 0xC00 // Interrupt Configuration Registers + +#define ARM_GIC_ICDPPISR 0xD00 // PPI Status register + +// just one of these +#define ARM_GIC_ICDSGIR 0xF00 // Software Generated Interrupt Register + +// +// GIC Cpu interface +// +#define ARM_GIC_ICCICR 0x00 // CPU Interface Control Register +#define ARM_GIC_ICCPMR 0x04 // Interrupt Priority Mask Register +#define ARM_GIC_ICCBPR 0x08 // Binary Point Register +#define ARM_GIC_ICCIAR 0x0C // Interrupt Acknowledge Register +#define ARM_GIC_ICCEIOR 0x10 // End Of Interrupt Register +#define ARM_GIC_ICCRPR 0x14 // Running Priority Register +#define ARM_GIC_ICCPIR 0x18 // Highest Pending Interrupt Register +#define ARM_GIC_ICCABPR 0x1C // Aliased Binary Point Register +#define ARM_GIC_ICCIIDR 0xFC // Identification Register + +// Bit Mask for +#define ARM_GIC_ICCIAR_ACKINTID 0x3FF + +// Interrupts from 1020 to 1023 are considered as special interrupts (eg: spurious interrupts) +#define ARM_GIC_IS_SPECIAL_INTERRUPTS(Interrupt) (((Interrupt) >= 1020) && ((Interrupt) <= 1023)) + +VOID +EFIAPI +ArmGicV2SetupNonSecure ( + IN UINTN MpId, + IN INTN GicDistributorBase, + IN INTN GicInterruptInterfaceBase + ); + +VOID +EFIAPI +ArmGicV2EnableInterruptInterface ( + IN INTN GicInterruptInterfaceBase + ); + +VOID +EFIAPI +ArmGicV2DisableInterruptInterface ( + IN INTN GicInterruptInterfaceBase + ); + +UINTN +EFIAPI +ArmGicV2AcknowledgeInterrupt ( + IN UINTN GicInterruptInterfaceBase + ); + +VOID +EFIAPI +ArmGicV2EndOfInterrupt ( + IN UINTN GicInterruptInterfaceBase, + IN UINTN Source + ); + +#endif diff --git a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2NonSecLib.c b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2NonSecLib.c new file mode 100644 index 0000000000..92b764f422 --- /dev/null +++ b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2NonSecLib.c @@ -0,0 +1,42 @@ +/** @file +* +* Copyright (c) 2011-2014, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include +#include +#include + + +VOID +EFIAPI +ArmGicV2EnableInterruptInterface ( + IN INTN GicInterruptInterfaceBase + ) +{ + /* + * Enable the CPU interface in Non-Secure world + * Note: The ICCICR register is banked when Security extensions are implemented + */ + MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, 0x1); +} + +VOID +EFIAPI +ArmGicV2DisableInterruptInterface ( + IN INTN GicInterruptInterfaceBase + ) +{ + // Disable Gic Interface + MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, 0x0); + MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0x0); +} diff --git a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2SecLib.c b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2SecLib.c new file mode 100644 index 0000000000..ac1e0e4945 --- /dev/null +++ b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2SecLib.c @@ -0,0 +1,100 @@ +/** @file +* +* Copyright (c) 2011-2014, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include +#include +#include +#include +#include +#include + +/* + * This function configures the all interrupts to be Non-secure. + * + */ +VOID +EFIAPI +ArmGicV2SetupNonSecure ( + IN UINTN MpId, + IN INTN GicDistributorBase, + IN INTN GicInterruptInterfaceBase + ) +{ + UINTN InterruptId; + UINTN CachedPriorityMask; + UINTN Index; + UINTN MaxInterrupts; + + CachedPriorityMask = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR); + + // Set priority Mask so that no interrupts get through to CPU + MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0); + + InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR); + MaxInterrupts = ArmGicGetMaxNumInterrupts (GicDistributorBase); + + // Only try to clear valid interrupts. Ignore spurious interrupts. + while ((InterruptId & 0x3FF) < MaxInterrupts) { + // Some of the SGI's are still pending, read Ack register and send End of Interrupt Signal + ArmGicEndOfInterrupt (GicInterruptInterfaceBase, InterruptId); + + // Next + InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR); + } + + // Only the primary core should set the Non Secure bit to the SPIs (Shared Peripheral Interrupt). + if (ArmPlatformIsPrimaryCore (MpId)) { + // Ensure all GIC interrupts are Non-Secure + for (Index = 0; Index < (MaxInterrupts / 32); Index++) { + MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), 0xffffffff); + } + } else { + // The secondary cores only set the Non Secure bit to their banked PPIs + MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR, 0xffffffff); + } + + // Ensure all interrupts can get through the priority mask + MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, CachedPriorityMask); +} + +VOID +EFIAPI +ArmGicV2EnableInterruptInterface ( + IN INTN GicInterruptInterfaceBase + ) +{ + // Set Priority Mask to allow interrupts + MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0x000000FF); + + // Enable CPU interface in Secure world + // Enable CPU interface in Non-secure World + // Signal Secure Interrupts to CPU using FIQ line * + MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, + ARM_GIC_ICCICR_ENABLE_SECURE | + ARM_GIC_ICCICR_ENABLE_NS | + ARM_GIC_ICCICR_SIGNAL_SECURE_TO_FIQ); +} + +VOID +EFIAPI +ArmGicV2DisableInterruptInterface ( + IN INTN GicInterruptInterfaceBase + ) +{ + UINT32 ControlValue; + + // Disable CPU interface in Secure world and Non-secure World + ControlValue = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR); + MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, ControlValue & ~(ARM_GIC_ICCICR_ENABLE_SECURE | ARM_GIC_ICCICR_ENABLE_NS)); +} diff --git a/ArmPkg/Include/Library/ArmGicLib.h b/ArmPkg/Include/Library/ArmGicLib.h index 24f1966b56..f2d4c7b27c 100644 --- a/ArmPkg/Include/Library/ArmGicLib.h +++ b/ArmPkg/Include/Library/ArmGicLib.h @@ -76,9 +76,6 @@ #define ARM_GIC_ICCIIDR_GET_REVISION(IccIidr) (((IccIidr) >> 12) & 0xF) #define ARM_GIC_ICCIIDR_GET_IMPLEMENTER(IccIidr) ((IccIidr) & 0xFFF) -// Bit Mask for -#define ARM_GIC_ICCIAR_ACKINTID 0x3FF - UINTN EFIAPI ArmGicGetInterfaceIdentification (