From 4b9c7d6889496ef2aab37299ef2b5d97cc36a5bb Mon Sep 17 00:00:00 2001 From: Olivier Martin Date: Tue, 25 Mar 2014 13:03:03 +0000 Subject: [PATCH 09/14] ArmPkg/ArmGic: Introduced support for GicV2 to ArmGicLib The support for GIcV2 was already existing. This change separate the GicV2 specific functions from the common Gic code (in preparation for GicV3 support). Change-Id: Id8750593190f02231d2b9b0286ae4b15ac40267d --- ArmPkg/Drivers/ArmGic/ArmGicLib.c | 26 +++++- ArmPkg/Drivers/ArmGic/ArmGicLib.inf | 5 +- ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c | 25 ------ ArmPkg/Drivers/ArmGic/ArmGicSecLib.c | 101 ++++-------------------- ArmPkg/Drivers/ArmGic/ArmGicSecLib.inf | 5 +- ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.c | 37 +++++++++ ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.h | 98 +++++++++++++++++++++++ ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2NonSecLib.c | 42 ++++++++++ ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2SecLib.c | 98 +++++++++++++++++++++++ 9 files changed, 322 insertions(+), 115 deletions(-) mode change 100644 => 100755 ArmPkg/Drivers/ArmGic/ArmGicLib.inf mode change 100644 => 100755 ArmPkg/Drivers/ArmGic/ArmGicSecLib.c mode change 100644 => 100755 ArmPkg/Drivers/ArmGic/ArmGicSecLib.inf create mode 100755 ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.c create mode 100755 ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.h create mode 100755 ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2NonSecLib.c create mode 100755 ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2SecLib.c diff --git a/ArmPkg/Drivers/ArmGic/ArmGicLib.c b/ArmPkg/Drivers/ArmGic/ArmGicLib.c index 75286ba..14deaa4 100755 --- 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); } RETURN_STATUS @@ -64,8 +65,7 @@ ArmGicEndOfInterrupt ( IN UINTN Source ) { - MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCEIOR, Source); - return RETURN_SUCCESS; + return ArmGicV2EndOfInterrupt (GicInterruptInterfaceBase, Source); } RETURN_STATUS @@ -138,3 +138,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 old mode 100644 new mode 100755 index d5223df..4652348 --- a/ArmPkg/Drivers/ArmGic/ArmGicLib.inf +++ b/ArmPkg/Drivers/ArmGic/ArmGicLib.inf @@ -1,5 +1,5 @@ #/* @file -# Copyright (c) 2011-2012, ARM Limited. All rights reserved. +# 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 @@ -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 3ff9b48..06367f9 100755 --- 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 old mode 100644 new mode 100755 index f249eac..1fdd4d7 --- 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. @@ -93,41 +46,21 @@ ArmGicSetSecureInterrupts ( VOID EFIAPI -ArmGicEnableInterruptInterface ( - IN INTN GicInterruptInterfaceBase +ArmGicEnableDistributor ( + IN INTN GicDistributorBase ) { - // 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); + // Turn on the GIC distributor + MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 1); } VOID EFIAPI -ArmGicDisableInterruptInterface ( +ArmGicSetupNonSecure ( + IN UINTN MpId, + IN INTN GicDistributorBase, 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 ( - IN INTN GicDistributorBase - ) -{ - // Turn on the GIC distributor - MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 1); + ArmGicV2SetupNonSecure (MpId, GicDistributorBase, GicInterruptInterfaceBase); } diff --git a/ArmPkg/Drivers/ArmGic/ArmGicSecLib.inf b/ArmPkg/Drivers/ArmGic/ArmGicSecLib.inf old mode 100644 new mode 100755 index b888eb5..07e750f --- a/ArmPkg/Drivers/ArmGic/ArmGicSecLib.inf +++ b/ArmPkg/Drivers/ArmGic/ArmGicSecLib.inf @@ -1,5 +1,5 @@ #/* @file -# Copyright (c) 2011-2012, ARM Limited. All rights reserved. +# 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 @@ -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 100755 index 0000000..aecca0c --- /dev/null +++ b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.c @@ -0,0 +1,37 @@ +/** @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); +} + +RETURN_STATUS +EFIAPI +ArmGicV2EndOfInterrupt ( + IN UINTN GicInterruptInterfaceBase, + IN UINTN Source + ) +{ + MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCEIOR, Source); + return RETURN_SUCCESS; +} diff --git a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.h b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.h new file mode 100755 index 0000000..65674b2 --- /dev/null +++ b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.h @@ -0,0 +1,98 @@ +/** @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 + +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 + ); + +RETURN_STATUS +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 100755 index 0000000..0108894 --- /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 100755 index 0000000..5764bf3 --- /dev/null +++ b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2SecLib.c @@ -0,0 +1,98 @@ +/** @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; + + 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); +} + +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)); +} -- 1.8.5