From dbfee0b5eb622c4227a06bfacfaa46e07b301c76 Mon Sep 17 00:00:00 2001
From: Olivier Martin <olivier.martin@arm.com>
Date: Tue, 25 Mar 2014 13:06:08 +0000
Subject: [PATCH 10/14] ArmPkg/ArmGic: Introduced support for GicV2 to
 ArmGicDxe

Change-Id: I95ceb55e10d6a8c09273032cb40991d4444ed34b
---
 ArmPkg/Drivers/ArmGic/ArmGicDxe.c         | 264 +-------------------------
 ArmPkg/Drivers/ArmGic/ArmGicDxe.h         |  11 ++
 ArmPkg/Drivers/ArmGic/ArmGicDxe.inf       |   2 +
 ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c | 302 ++++++++++++++++++++++++++++++
 4 files changed, 319 insertions(+), 260 deletions(-)
 mode change 100644 => 100755 ArmPkg/Drivers/ArmGic/ArmGicDxe.c
 mode change 100644 => 100755 ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
 create mode 100755 ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c

diff --git a/ArmPkg/Drivers/ArmGic/ArmGicDxe.c b/ArmPkg/Drivers/ArmGic/ArmGicDxe.c
old mode 100644
new mode 100755
index 97df9da..3f32165
--- a/ArmPkg/Drivers/ArmGic/ArmGicDxe.c
+++ b/ArmPkg/Drivers/ArmGic/ArmGicDxe.c
@@ -1,8 +1,6 @@
 /*++
 
-Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
-Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
-Portions copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR> 
+Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
 
 This program and the accompanying materials                          
 are licensed and made available under the terms and conditions of the BSD License         
@@ -14,7 +12,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
 Module Name:
 
-  Gic.c
+  ArmGicDxe.c
 
 Abstract:
 
@@ -28,206 +26,9 @@ Abstract:
 #include <Library/BaseMemoryLib.h>
 #include <Library/UefiLib.h>
 #include <Library/PcdLib.h>
-#include <Library/IoLib.h>
-#include <Library/ArmGicLib.h>
 
 #include "ArmGicDxe.h"
 
-#define ARM_GIC_DEFAULT_PRIORITY  0x80
-
-extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol;
-
-/**
-  Enable interrupt source Source.
-
-  @param This     Instance pointer for this protocol
-  @param Source   Hardware source of the interrupt
-
-  @retval EFI_SUCCESS       Source interrupt enabled.
-  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.
-
-**/
-EFI_STATUS
-EFIAPI
-EnableInterruptSource (
-  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,
-  IN HARDWARE_INTERRUPT_SOURCE          Source
-  )
-{
-  if (Source > mGicNumInterrupts) {
-    ASSERT(FALSE);
-    return EFI_UNSUPPORTED;
-  }
-  
-  return ArmGicEnableInterrupt (PcdGet32(PcdGicDistributorBase), Source);
-}
-
-/**
-  Disable interrupt source Source.
-
-  @param This     Instance pointer for this protocol
-  @param Source   Hardware source of the interrupt
-
-  @retval EFI_SUCCESS       Source interrupt disabled.
-  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.
-
-**/
-EFI_STATUS
-EFIAPI
-DisableInterruptSource (
-  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,
-  IN HARDWARE_INTERRUPT_SOURCE          Source
-  )
-{
-  if (Source > mGicNumInterrupts) {
-    ASSERT(FALSE);
-    return EFI_UNSUPPORTED;
-  }
-  
-  return ArmGicDisableInterrupt (PcdGet32(PcdGicDistributorBase), Source);
-}
-
-/**
-  Return current state of interrupt source Source.
-
-  @param This     Instance pointer for this protocol
-  @param Source   Hardware source of the interrupt
-  @param InterruptState  TRUE: source enabled, FALSE: source disabled.
-
-  @retval EFI_SUCCESS       InterruptState is valid
-  @retval EFI_DEVICE_ERROR  InterruptState is not valid
-
-**/
-EFI_STATUS
-EFIAPI
-GetInterruptSourceState (
-  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,
-  IN HARDWARE_INTERRUPT_SOURCE          Source,
-  IN BOOLEAN                            *InterruptState
-  )
-{
-  if (Source > mGicNumInterrupts) {
-    ASSERT(FALSE);
-    return EFI_UNSUPPORTED;
-  }
-    
-  *InterruptState = ArmGicIsInterruptEnabled (PcdGet32(PcdGicDistributorBase), Source);
-  
-  return EFI_SUCCESS;
-}
-
-/**
-  Signal to the hardware that the End Of Intrrupt state 
-  has been reached.
-
-  @param This     Instance pointer for this protocol
-  @param Source   Hardware source of the interrupt
-
-  @retval EFI_SUCCESS       Source interrupt EOI'ed.
-  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.
-
-**/
-EFI_STATUS
-EFIAPI
-EndOfInterrupt (
-  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,
-  IN HARDWARE_INTERRUPT_SOURCE          Source
-  )
-{
-  if (Source > mGicNumInterrupts) {
-    ASSERT(FALSE);
-    return EFI_UNSUPPORTED;
-  }
-
-  ArmGicEndOfInterrupt (PcdGet32(PcdGicInterruptInterfaceBase), Source);
-  return EFI_SUCCESS;
-}
-
-/**
-  EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
-
-  @param  InterruptType    Defines the type of interrupt or exception that
-                           occurred on the processor.This parameter is processor architecture specific.
-  @param  SystemContext    A pointer to the processor context when
-                           the interrupt occurred on the processor.
-
-  @return None
-
-**/
-VOID
-EFIAPI
-IrqInterruptHandler (
-  IN EFI_EXCEPTION_TYPE           InterruptType,
-  IN EFI_SYSTEM_CONTEXT           SystemContext
-  )
-{
-  UINT32                      GicInterrupt;
-  HARDWARE_INTERRUPT_HANDLER  InterruptHandler;
-
-  GicInterrupt = ArmGicAcknowledgeInterrupt (PcdGet32(PcdGicInterruptInterfaceBase));
-
-  // Special Interrupts (ID1020-ID1023) have an Interrupt ID greater than the number of interrupt (ie: Spurious interrupt).
-  if ((GicInterrupt & ARM_GIC_ICCIAR_ACKINTID) >= mGicNumInterrupts) {
-    // The special interrupt do not need to be acknowledge
-    return;
-  }
-  
-  InterruptHandler = gRegisteredInterruptHandlers[GicInterrupt];
-  if (InterruptHandler != NULL) {
-    // Call the registered interrupt handler.
-    InterruptHandler (GicInterrupt, SystemContext);
-  } else {
-    DEBUG ((EFI_D_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));
-  }
-
-  EndOfInterrupt (&gHardwareInterruptProtocol, GicInterrupt);
-}
-
-//
-// The protocol instance produced by this driver
-//
-EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = {
-  RegisterInterruptSource,
-  EnableInterruptSource,
-  DisableInterruptSource,
-  GetInterruptSourceState,
-  EndOfInterrupt
-};
-
-/**
-  Shutdown our hardware
-  
-  DXE Core will disable interrupts and turn off the timer and disable interrupts
-  after all the event handlers have run.
-
-  @param[in]  Event   The Event that is being processed
-  @param[in]  Context Event Context
-**/
-VOID
-EFIAPI
-ExitBootServicesEvent (
-  IN EFI_EVENT  Event,
-  IN VOID       *Context
-  )
-{
-  UINTN    Index;
-  
-  // Acknowledge all pending interrupts
-  for (Index = 0; Index < mGicNumInterrupts; Index++) {
-    DisableInterruptSource (&gHardwareInterruptProtocol, Index);
-  }
-
-  for (Index = 0; Index < mGicNumInterrupts; Index++) {
-    EndOfInterrupt (&gHardwareInterruptProtocol, Index);
-  }
-
-  // Disable Gic Interface
-  ArmGicDisableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase));
-
-  // Disable Gic Distributor
-  ArmGicDisableDistributor (PcdGet32(PcdGicDistributorBase));
-}
-
 /**
   Initialize the state information for the CPU Architectural Protocol
 
@@ -245,66 +46,9 @@ InterruptDxeInitialize (
   IN EFI_SYSTEM_TABLE   *SystemTable
   )
 {
-  EFI_STATUS              Status;
-  UINTN                   Index;
-  UINT32                  RegOffset;
-  UINTN                   RegShift;
-  UINT32                  CpuTarget;
-  
-  // Make sure the Interrupt Controller Protocol is not already installed in the system.
-  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
-
-  mGicNumInterrupts = ArmGicGetMaxNumInterrupts (PcdGet32(PcdGicDistributorBase));
-
-  for (Index = 0; Index < mGicNumInterrupts; Index++) {
-    DisableInterruptSource (&gHardwareInterruptProtocol, Index);
-    
-    // Set Priority 
-    RegOffset = Index / 4;
-    RegShift = (Index % 4) * 8;
-    MmioAndThenOr32 (
-      PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPR + (4*RegOffset),
-      ~(0xff << RegShift), 
-      ARM_GIC_DEFAULT_PRIORITY << RegShift
-      );
-  }
-
-  //
-  // Targets the interrupts to the Primary Cpu
-  //
-
-  // Only Primary CPU will run this code. We can identify our GIC CPU ID by reading
-  // the GIC Distributor Target register. The 8 first GICD_ITARGETSRn are banked to each
-  // connected CPU. These 8 registers hold the CPU targets fields for interrupts 0-31.
-  // More Info in the GIC Specification about "Interrupt Processor Targets Registers"
-  //
-  // Read the first Interrupt Processor Targets Register (that corresponds to the 4
-  // first SGIs)
-  CpuTarget = MmioRead32 (PcdGet32 (PcdGicDistributorBase) + ARM_GIC_ICDIPTR);
-
-  // The CPU target is a bit field mapping each CPU to a GIC CPU Interface. This value
-  // is 0 when we run on a uniprocessor platform.
-  if (CpuTarget != 0) {
-    // The 8 first Interrupt Processor Targets Registers are read-only
-    for (Index = 8; Index < (mGicNumInterrupts / 4); Index++) {
-      MmioWrite32 (PcdGet32 (PcdGicDistributorBase) + ARM_GIC_ICDIPTR + (Index * 4), CpuTarget);
-    }
-  }
-
-  // Set binary point reg to 0x7 (no preemption)
-  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCBPR, 0x7);
-
-  // Set priority mask reg to 0xff to allow all priorities through
-  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0xff);
-  
-  // Enable gic cpu interface
-  ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase));
+  EFI_STATUS  Status;
 
-  // Enable gic distributor
-  ArmGicEnableDistributor (PcdGet32(PcdGicDistributorBase));
-  
-  Status = InstallAndRegisterInterruptService (
-      &gHardwareInterruptProtocol, IrqInterruptHandler, ExitBootServicesEvent);
+  Status = GicV2DxeInitialize (ImageHandle, SystemTable);
 
   return Status;
 }
diff --git a/ArmPkg/Drivers/ArmGic/ArmGicDxe.h b/ArmPkg/Drivers/ArmGic/ArmGicDxe.h
index 4d22451..43bb888 100755
--- a/ArmPkg/Drivers/ArmGic/ArmGicDxe.h
+++ b/ArmPkg/Drivers/ArmGic/ArmGicDxe.h
@@ -15,8 +15,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #ifndef __ARM_GIC_DXE_H__
 #define __ARM_GIC_DXE_H__
 
+#include <Library/ArmGicLib.h>
 #include <Library/ArmLib.h>
 #include <Library/DebugLib.h>
+#include <Library/IoLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 
@@ -44,4 +46,13 @@ RegisterInterruptSource (
   IN HARDWARE_INTERRUPT_HANDLER         Handler
   );
 
+//
+// GicV2 API
+//
+EFI_STATUS
+GicV2DxeInitialize (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  );
+
 #endif
diff --git a/ArmPkg/Drivers/ArmGic/ArmGicDxe.inf b/ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
old mode 100644
new mode 100755
index a3529a9..5f46a91
--- a/ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
+++ b/ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
@@ -25,6 +25,8 @@
 [Sources.common]
   ArmGicDxe.c
   ArmGicCommonDxe.c
+  
+  GicV2/ArmGicV2Dxe.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c
new file mode 100755
index 0000000..e1f22b9
--- /dev/null
+++ b/ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c
@@ -0,0 +1,302 @@
+/*++
+
+Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
+Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
+Portions copyright (c) 2011-2014, ARM Ltd. All rights reserved.<BR>
+
+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.
+
+Module Name:
+
+  GicV2/ArmGicV2Dxe.c
+
+Abstract:
+
+  Driver implementing the GicV2 interrupt controller protocol
+
+--*/
+
+#include "ArmGicDxe.h"
+#include "GicV2/ArmGicV2Lib.h"
+
+#define ARM_GIC_DEFAULT_PRIORITY  0x80
+
+extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV2Protocol;
+
+/**
+  Enable interrupt source Source.
+
+  @param This     Instance pointer for this protocol
+  @param Source   Hardware source of the interrupt
+
+  @retval EFI_SUCCESS       Source interrupt enabled.
+  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+GicV2EnableInterruptSource (
+  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,
+  IN HARDWARE_INTERRUPT_SOURCE          Source
+  )
+{
+  if (Source > mGicNumInterrupts) {
+    ASSERT(FALSE);
+    return EFI_UNSUPPORTED;
+  }
+
+  return ArmGicEnableInterrupt (PcdGet32(PcdGicDistributorBase), Source);
+}
+
+/**
+  Disable interrupt source Source.
+
+  @param This     Instance pointer for this protocol
+  @param Source   Hardware source of the interrupt
+
+  @retval EFI_SUCCESS       Source interrupt disabled.
+  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+GicV2DisableInterruptSource (
+  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,
+  IN HARDWARE_INTERRUPT_SOURCE          Source
+  )
+{
+  if (Source > mGicNumInterrupts) {
+    ASSERT(FALSE);
+    return EFI_UNSUPPORTED;
+  }
+
+  return ArmGicDisableInterrupt (PcdGet32(PcdGicDistributorBase), Source);
+}
+
+/**
+  Return current state of interrupt source Source.
+
+  @param This     Instance pointer for this protocol
+  @param Source   Hardware source of the interrupt
+  @param InterruptState  TRUE: source enabled, FALSE: source disabled.
+
+  @retval EFI_SUCCESS       InterruptState is valid
+  @retval EFI_DEVICE_ERROR  InterruptState is not valid
+
+**/
+EFI_STATUS
+EFIAPI
+GicV2GetInterruptSourceState (
+  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,
+  IN HARDWARE_INTERRUPT_SOURCE          Source,
+  IN BOOLEAN                            *InterruptState
+  )
+{
+  if (Source > mGicNumInterrupts) {
+    ASSERT(FALSE);
+    return EFI_UNSUPPORTED;
+  }
+
+  *InterruptState = ArmGicIsInterruptEnabled (PcdGet32(PcdGicDistributorBase), Source);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Signal to the hardware that the End Of Intrrupt state
+  has been reached.
+
+  @param This     Instance pointer for this protocol
+  @param Source   Hardware source of the interrupt
+
+  @retval EFI_SUCCESS       Source interrupt EOI'ed.
+  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+GicV2EndOfInterrupt (
+  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,
+  IN HARDWARE_INTERRUPT_SOURCE          Source
+  )
+{
+  if (Source > mGicNumInterrupts) {
+    ASSERT(FALSE);
+    return EFI_UNSUPPORTED;
+  }
+
+  ArmGicV2EndOfInterrupt (PcdGet32(PcdGicInterruptInterfaceBase), Source);
+  return EFI_SUCCESS;
+}
+
+/**
+  EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
+
+  @param  InterruptType    Defines the type of interrupt or exception that
+                           occurred on the processor.This parameter is processor architecture specific.
+  @param  SystemContext    A pointer to the processor context when
+                           the interrupt occurred on the processor.
+
+  @return None
+
+**/
+VOID
+EFIAPI
+GicV2IrqInterruptHandler (
+  IN EFI_EXCEPTION_TYPE           InterruptType,
+  IN EFI_SYSTEM_CONTEXT           SystemContext
+  )
+{
+  UINT32                      GicInterrupt;
+  HARDWARE_INTERRUPT_HANDLER  InterruptHandler;
+
+  GicInterrupt = ArmGicV2AcknowledgeInterrupt (PcdGet32(PcdGicInterruptInterfaceBase));
+
+  // Special Interrupts (ID1020-ID1023) have an Interrupt ID greater than the number of interrupt (ie: Spurious interrupt).
+  if ((GicInterrupt & ARM_GIC_ICCIAR_ACKINTID) >= mGicNumInterrupts) {
+    // The special interrupt do not need to be acknowledge
+    return;
+  }
+
+  InterruptHandler = gRegisteredInterruptHandlers[GicInterrupt];
+  if (InterruptHandler != NULL) {
+    // Call the registered interrupt handler.
+    InterruptHandler (GicInterrupt, SystemContext);
+  } else {
+    DEBUG ((EFI_D_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));
+  }
+
+  GicV2EndOfInterrupt (&gHardwareInterruptV2Protocol, GicInterrupt);
+}
+
+//
+// The protocol instance produced by this driver
+//
+EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV2Protocol = {
+  RegisterInterruptSource,
+  GicV2EnableInterruptSource,
+  GicV2DisableInterruptSource,
+  GicV2GetInterruptSourceState,
+  GicV2EndOfInterrupt
+};
+
+/**
+  Shutdown our hardware
+
+  DXE Core will disable interrupts and turn off the timer and disable interrupts
+  after all the event handlers have run.
+
+  @param[in]  Event   The Event that is being processed
+  @param[in]  Context Event Context
+**/
+VOID
+EFIAPI
+GicV2ExitBootServicesEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  UINTN    Index;
+
+  // Acknowledge all pending interrupts
+  for (Index = 0; Index < mGicNumInterrupts; Index++) {
+    GicV2DisableInterruptSource (&gHardwareInterruptV2Protocol, Index);
+  }
+
+  for (Index = 0; Index < mGicNumInterrupts; Index++) {
+    GicV2EndOfInterrupt (&gHardwareInterruptV2Protocol, Index);
+  }
+
+  // Disable Gic Interface
+  ArmGicV2DisableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase));
+
+  // Disable Gic Distributor
+  ArmGicDisableDistributor (PcdGet32(PcdGicDistributorBase));
+}
+
+/**
+  Initialize the state information for the CPU Architectural Protocol
+
+  @param  ImageHandle   of the loaded driver
+  @param  SystemTable   Pointer to the System Table
+
+  @retval EFI_SUCCESS           Protocol registered
+  @retval EFI_OUT_OF_RESOURCES  Cannot allocate protocol data structure
+  @retval EFI_DEVICE_ERROR      Hardware problems
+
+**/
+EFI_STATUS
+GicV2DxeInitialize (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS              Status;
+  UINTN                   Index;
+  UINT32                  RegOffset;
+  UINTN                   RegShift;
+  UINT32                  CpuTarget;
+
+  // Make sure the Interrupt Controller Protocol is not already installed in the system.
+  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
+
+  mGicNumInterrupts = ArmGicGetMaxNumInterrupts (PcdGet32(PcdGicDistributorBase));
+
+  for (Index = 0; Index < mGicNumInterrupts; Index++) {
+    GicV2DisableInterruptSource (&gHardwareInterruptV2Protocol, Index);
+
+    // Set Priority
+    RegOffset = Index / 4;
+    RegShift = (Index % 4) * 8;
+    MmioAndThenOr32 (
+      PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPR + (4 * RegOffset),
+      ~(0xff << RegShift),
+      ARM_GIC_DEFAULT_PRIORITY << RegShift
+      );
+  }
+
+  //
+  // Targets the interrupts to the Primary Cpu
+  //
+
+  // Only Primary CPU will run this code. We can identify our GIC CPU ID by reading
+  // the GIC Distributor Target register. The 8 first GICD_ITARGETSRn are banked to each
+  // connected CPU. These 8 registers hold the CPU targets fields for interrupts 0-31.
+  // More Info in the GIC Specification about "Interrupt Processor Targets Registers"
+  //
+  // Read the first Interrupt Processor Targets Register (that corresponds to the 4
+  // first SGIs)
+  CpuTarget = MmioRead32 (PcdGet32 (PcdGicDistributorBase) + ARM_GIC_ICDIPTR);
+
+  // The CPU target is a bit field mapping each CPU to a GIC CPU Interface. This value
+  // is 0 when we run on a uniprocessor platform.
+  if (CpuTarget != 0) {
+    // The 8 first Interrupt Processor Targets Registers are read-only
+    for (Index = 8; Index < (mGicNumInterrupts / 4); Index++) {
+      MmioWrite32 (PcdGet32 (PcdGicDistributorBase) + ARM_GIC_ICDIPTR + (Index * 4), CpuTarget);
+    }
+  }
+
+  // Set binary point reg to 0x7 (no preemption)
+  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCBPR, 0x7);
+
+  // Set priority mask reg to 0xff to allow all priorities through
+  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0xff);
+
+  // Enable gic cpu interface
+  ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase));
+
+  // Enable gic distributor
+  ArmGicEnableDistributor (PcdGet32(PcdGicDistributorBase));
+
+  Status = InstallAndRegisterInterruptService (
+          &gHardwareInterruptV2Protocol, GicV2IrqInterruptHandler, GicV2ExitBootServicesEvent);
+
+  return Status;
+}
-- 
1.8.5

