]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPkg/Drivers/PL390Gic/PL390GicDxe.c
ARM Packages: Fixed line endings
[mirror_edk2.git] / ArmPkg / Drivers / PL390Gic / PL390GicDxe.c
index 1a8239e73a5e9bc07f2f468cf334cc9a366ad3aa..590cdb7056f593f9caeae01ec2a43ec5674a82a5 100644 (file)
-/*++
-
-Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
-Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
-Portions copyright (c) 2011-2012, 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:
-
-  Gic.c
-
-Abstract:
-
-  Driver implementing the GIC interrupt controller protocol
-
---*/
-
-#include <PiDxe.h>
-
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiLib.h>
-#include <Library/PcdLib.h>
-#include <Library/IoLib.h>
-#include <Library/ArmGicLib.h>
-
-#include <Protocol/Cpu.h>
-#include <Protocol/HardwareInterrupt.h>
-
-#define ARM_GIC_DEFAULT_PRIORITY  0x80
-
-extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol;
-
-//
-// Notifications
-//
-EFI_EVENT EfiExitBootServicesEvent      = (EFI_EVENT)NULL;
-
-// Maximum Number of Interrupts
-UINTN mGicNumInterrupts                 = 0;
-
-HARDWARE_INTERRUPT_HANDLER  *gRegisteredInterruptHandlers = NULL;
-
-/**
-  Register Handler for the specified interrupt source.
-
-  @param This     Instance pointer for this protocol
-  @param Source   Hardware source of the interrupt
-  @param Handler  Callback for interrupt. NULL to unregister
-
-  @retval EFI_SUCCESS Source was updated to support Handler.
-  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.
-
-**/
-EFI_STATUS
-EFIAPI
-RegisterInterruptSource (
-  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,
-  IN HARDWARE_INTERRUPT_SOURCE          Source,
-  IN HARDWARE_INTERRUPT_HANDLER         Handler
-  )
-{
-  if (Source > mGicNumInterrupts) {
-    ASSERT(FALSE);
-    return EFI_UNSUPPORTED;
-  }
-  
-  if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
-    return EFI_ALREADY_STARTED;
-  }
-
-  gRegisteredInterruptHandlers[Source] = Handler;
-
-  // If the interrupt handler is unregistered then disable the interrupt
-  if (NULL == Handler){
-       return This->DisableInterruptSource (This, Source);
-  } else {
-       return This->EnableInterruptSource (This, Source);
-  }
-}
-
-/**
-  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
-  )
-{
-  UINT32    RegOffset;
-  UINTN     RegShift;
-  
-  if (Source > mGicNumInterrupts) {
-    ASSERT(FALSE);
-    return EFI_UNSUPPORTED;
-  }
-  
-  // Calculate enable register offset and bit position
-  RegOffset = Source / 32;
-  RegShift = Source % 32;
-
-  // Write set-enable register
-  MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDISER + (4*RegOffset), 1 << RegShift);
-  
-  return EFI_SUCCESS;
-}
-
-/**
-  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
-  )
-{
-  UINT32    RegOffset;
-  UINTN     RegShift;
-  
-  if (Source > mGicNumInterrupts) {
-    ASSERT(FALSE);
-    return EFI_UNSUPPORTED;
-  }
-  
-  // Calculate enable register offset and bit position
-  RegOffset = Source / 32;
-  RegShift = Source % 32;
-
-  // Write set-enable register
-  MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDICER + (4*RegOffset), 1 << RegShift);
-  
-  return EFI_SUCCESS;
-}
-
-/**
-  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
-  )
-{
-  UINT32    RegOffset;
-  UINTN     RegShift;
-  
-  if (Source > mGicNumInterrupts) {
-    ASSERT(FALSE);
-    return EFI_UNSUPPORTED;
-  }
-  
-  // calculate enable register offset and bit position
-  RegOffset = Source / 32;
-  RegShift = Source % 32;
-    
-  if ((MmioRead32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDISER + (4*RegOffset)) & (1<<RegShift)) == 0) {
-    *InterruptState = FALSE;
-  } else {
-    *InterruptState = TRUE;
-  }
-  
-  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;
-  }
-
-  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCEIOR, 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 = MmioRead32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCIAR);
-
-  // Special Interrupts (ID1020-ID1023) have an Interrupt ID greater than the number of interrupt (ie: Spurious interrupt).
-  if (GicInterrupt >= 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);
-}
-
-//
-// Making this global saves a few bytes in image size
-//
-EFI_HANDLE  gHardwareInterruptHandle = NULL;
-
-//
-// 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
-  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCICR, 0x0);
-  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0x0);
-
-  // Disable Gic Distributor
-  MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDDCR, 0x0);
-}
-
-/**
-  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
-InterruptDxeInitialize (
-  IN EFI_HANDLE         ImageHandle,
-  IN EFI_SYSTEM_TABLE   *SystemTable
-  )
-{
-  EFI_STATUS              Status;
-  UINTN                   Index;
-  UINT32                  RegOffset;
-  UINTN                   RegShift;
-  EFI_CPU_ARCH_PROTOCOL   *Cpu;
-  UINT32                  CpuTarget;
-  
-  // Check PcdGicPrimaryCoreId has been set in case the Primary Core is not the core 0 of Cluster 0
-  DEBUG_CODE_BEGIN();
-  if ((PcdGet32(PcdArmPrimaryCore) != 0) && (PcdGet32 (PcdGicPrimaryCoreId) == 0)) {
-    DEBUG((EFI_D_WARN,"Warning: the PCD PcdGicPrimaryCoreId does not seem to be set up for the configuration.\n"));
-  }
-  DEBUG_CODE_END();
-
-  // 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
-      );
-  }
-
-  // Configure interrupts for Primary Cpu
-  CpuTarget = (1 << PcdGet32 (PcdGicPrimaryCoreId));
-  CpuTarget |= (CpuTarget << 24) | (CpuTarget << 16) | (CpuTarget << 8);
-  for (Index = 0; 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
-  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCICR, 0x1);
-
-  // Enable gic distributor
-  MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDDCR, 0x1);
-  
-  // Initialize the array for the Interrupt Handlers
-  gRegisteredInterruptHandlers = (HARDWARE_INTERRUPT_HANDLER*)AllocateZeroPool (sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
-  
-  Status = gBS->InstallMultipleProtocolInterfaces (
-                  &gHardwareInterruptHandle,
-                  &gHardwareInterruptProtocolGuid,   &gHardwareInterruptProtocol,
-                  NULL
-                  );
-  ASSERT_EFI_ERROR (Status);
-  
-  //
-  // Get the CPU protocol that this driver requires.
-  //
-  Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
-  ASSERT_EFI_ERROR(Status);
-
-  //
-  // Unregister the default exception handler.
-  //
-  Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL);
-  ASSERT_EFI_ERROR(Status);
-
-  //
-  // Register to receive interrupts
-  //
-  Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);
-  ASSERT_EFI_ERROR(Status);
-
-  // Register for an ExitBootServicesEvent
-  Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
-  ASSERT_EFI_ERROR (Status);
-
-  return Status;
-}
+/*++\r
+\r
+Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>\r
+Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>\r
+Portions copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR> \r
+\r
+This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.   \r
+\r
+Module Name:\r
+\r
+  Gic.c\r
+\r
+Abstract:\r
+\r
+  Driver implementing the GIC interrupt controller protocol\r
+\r
+--*/\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/ArmGicLib.h>\r
+\r
+#include <Protocol/Cpu.h>\r
+#include <Protocol/HardwareInterrupt.h>\r
+\r
+#define ARM_GIC_DEFAULT_PRIORITY  0x80\r
+\r
+extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol;\r
+\r
+//\r
+// Notifications\r
+//\r
+EFI_EVENT EfiExitBootServicesEvent      = (EFI_EVENT)NULL;\r
+\r
+// Maximum Number of Interrupts\r
+UINTN mGicNumInterrupts                 = 0;\r
+\r
+HARDWARE_INTERRUPT_HANDLER  *gRegisteredInterruptHandlers = NULL;\r
+\r
+/**\r
+  Register Handler for the specified interrupt source.\r
+\r
+  @param This     Instance pointer for this protocol\r
+  @param Source   Hardware source of the interrupt\r
+  @param Handler  Callback for interrupt. NULL to unregister\r
+\r
+  @retval EFI_SUCCESS Source was updated to support Handler.\r
+  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterInterruptSource (\r
+  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,\r
+  IN HARDWARE_INTERRUPT_SOURCE          Source,\r
+  IN HARDWARE_INTERRUPT_HANDLER         Handler\r
+  )\r
+{\r
+  if (Source > mGicNumInterrupts) {\r
+    ASSERT(FALSE);\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+\r
+  gRegisteredInterruptHandlers[Source] = Handler;\r
+\r
+  // If the interrupt handler is unregistered then disable the interrupt\r
+  if (NULL == Handler){\r
+       return This->DisableInterruptSource (This, Source);\r
+  } else {\r
+       return This->EnableInterruptSource (This, Source);\r
+  }\r
+}\r
+\r
+/**\r
+  Enable interrupt source Source.\r
+\r
+  @param This     Instance pointer for this protocol\r
+  @param Source   Hardware source of the interrupt\r
+\r
+  @retval EFI_SUCCESS       Source interrupt enabled.\r
+  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EnableInterruptSource (\r
+  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,\r
+  IN HARDWARE_INTERRUPT_SOURCE          Source\r
+  )\r
+{\r
+  UINT32    RegOffset;\r
+  UINTN     RegShift;\r
+  \r
+  if (Source > mGicNumInterrupts) {\r
+    ASSERT(FALSE);\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  // Calculate enable register offset and bit position\r
+  RegOffset = Source / 32;\r
+  RegShift = Source % 32;\r
+\r
+  // Write set-enable register\r
+  MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDISER + (4*RegOffset), 1 << RegShift);\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Disable interrupt source Source.\r
+\r
+  @param This     Instance pointer for this protocol\r
+  @param Source   Hardware source of the interrupt\r
+\r
+  @retval EFI_SUCCESS       Source interrupt disabled.\r
+  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DisableInterruptSource (\r
+  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,\r
+  IN HARDWARE_INTERRUPT_SOURCE          Source\r
+  )\r
+{\r
+  UINT32    RegOffset;\r
+  UINTN     RegShift;\r
+  \r
+  if (Source > mGicNumInterrupts) {\r
+    ASSERT(FALSE);\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  // Calculate enable register offset and bit position\r
+  RegOffset = Source / 32;\r
+  RegShift = Source % 32;\r
+\r
+  // Write set-enable register\r
+  MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDICER + (4*RegOffset), 1 << RegShift);\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Return current state of interrupt source Source.\r
+\r
+  @param This     Instance pointer for this protocol\r
+  @param Source   Hardware source of the interrupt\r
+  @param InterruptState  TRUE: source enabled, FALSE: source disabled.\r
+\r
+  @retval EFI_SUCCESS       InterruptState is valid\r
+  @retval EFI_DEVICE_ERROR  InterruptState is not valid\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetInterruptSourceState (\r
+  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,\r
+  IN HARDWARE_INTERRUPT_SOURCE          Source,\r
+  IN BOOLEAN                            *InterruptState\r
+  )\r
+{\r
+  UINT32    RegOffset;\r
+  UINTN     RegShift;\r
+  \r
+  if (Source > mGicNumInterrupts) {\r
+    ASSERT(FALSE);\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  \r
+  // calculate enable register offset and bit position\r
+  RegOffset = Source / 32;\r
+  RegShift = Source % 32;\r
+    \r
+  if ((MmioRead32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDISER + (4*RegOffset)) & (1<<RegShift)) == 0) {\r
+    *InterruptState = FALSE;\r
+  } else {\r
+    *InterruptState = TRUE;\r
+  }\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Signal to the hardware that the End Of Intrrupt state \r
+  has been reached.\r
+\r
+  @param This     Instance pointer for this protocol\r
+  @param Source   Hardware source of the interrupt\r
+\r
+  @retval EFI_SUCCESS       Source interrupt EOI'ed.\r
+  @retval EFI_DEVICE_ERROR  Hardware could not be programmed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EndOfInterrupt (\r
+  IN EFI_HARDWARE_INTERRUPT_PROTOCOL    *This,\r
+  IN HARDWARE_INTERRUPT_SOURCE          Source\r
+  )\r
+{\r
+  if (Source > mGicNumInterrupts) {\r
+    ASSERT(FALSE);\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCEIOR, Source);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.\r
+\r
+  @param  InterruptType    Defines the type of interrupt or exception that\r
+                           occurred on the processor.This parameter is processor architecture specific.\r
+  @param  SystemContext    A pointer to the processor context when\r
+                           the interrupt occurred on the processor.\r
+\r
+  @return None\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+IrqInterruptHandler (\r
+  IN EFI_EXCEPTION_TYPE           InterruptType,\r
+  IN EFI_SYSTEM_CONTEXT           SystemContext\r
+  )\r
+{\r
+  UINT32                      GicInterrupt;\r
+  HARDWARE_INTERRUPT_HANDLER  InterruptHandler;\r
+\r
+  GicInterrupt = MmioRead32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCIAR);\r
+\r
+  // Special Interrupts (ID1020-ID1023) have an Interrupt ID greater than the number of interrupt (ie: Spurious interrupt).\r
+  if (GicInterrupt >= mGicNumInterrupts) {\r
+    // The special interrupt do not need to be acknowledge\r
+    return;\r
+  }\r
+  \r
+  InterruptHandler = gRegisteredInterruptHandlers[GicInterrupt];\r
+  if (InterruptHandler != NULL) {\r
+    // Call the registered interrupt handler.\r
+    InterruptHandler (GicInterrupt, SystemContext);\r
+  } else {\r
+    DEBUG ((EFI_D_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));\r
+  }\r
+\r
+  EndOfInterrupt (&gHardwareInterruptProtocol, GicInterrupt);\r
+}\r
+\r
+//\r
+// Making this global saves a few bytes in image size\r
+//\r
+EFI_HANDLE  gHardwareInterruptHandle = NULL;\r
+\r
+//\r
+// The protocol instance produced by this driver\r
+//\r
+EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = {\r
+  RegisterInterruptSource,\r
+  EnableInterruptSource,\r
+  DisableInterruptSource,\r
+  GetInterruptSourceState,\r
+  EndOfInterrupt\r
+};\r
+\r
+/**\r
+  Shutdown our hardware\r
+  \r
+  DXE Core will disable interrupts and turn off the timer and disable interrupts\r
+  after all the event handlers have run.\r
+\r
+  @param[in]  Event   The Event that is being processed\r
+  @param[in]  Context Event Context\r
+**/\r
+VOID\r
+EFIAPI\r
+ExitBootServicesEvent (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  )\r
+{\r
+  UINTN    Index;\r
+  \r
+  // Acknowledge all pending interrupts\r
+  for (Index = 0; Index < mGicNumInterrupts; Index++) {\r
+    DisableInterruptSource (&gHardwareInterruptProtocol, Index);\r
+  }\r
+\r
+  for (Index = 0; Index < mGicNumInterrupts; Index++) {\r
+    EndOfInterrupt (&gHardwareInterruptProtocol, Index);\r
+  }\r
+\r
+  // Disable Gic Interface\r
+  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCICR, 0x0);\r
+  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0x0);\r
+\r
+  // Disable Gic Distributor\r
+  MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDDCR, 0x0);\r
+}\r
+\r
+/**\r
+  Initialize the state information for the CPU Architectural Protocol\r
+\r
+  @param  ImageHandle   of the loaded driver\r
+  @param  SystemTable   Pointer to the System Table\r
+\r
+  @retval EFI_SUCCESS           Protocol registered\r
+  @retval EFI_OUT_OF_RESOURCES  Cannot allocate protocol data structure\r
+  @retval EFI_DEVICE_ERROR      Hardware problems\r
+\r
+**/\r
+EFI_STATUS\r
+InterruptDxeInitialize (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  UINTN                   Index;\r
+  UINT32                  RegOffset;\r
+  UINTN                   RegShift;\r
+  EFI_CPU_ARCH_PROTOCOL   *Cpu;\r
+  UINT32                  CpuTarget;\r
+  \r
+  // Check PcdGicPrimaryCoreId has been set in case the Primary Core is not the core 0 of Cluster 0\r
+  DEBUG_CODE_BEGIN();\r
+  if ((PcdGet32(PcdArmPrimaryCore) != 0) && (PcdGet32 (PcdGicPrimaryCoreId) == 0)) {\r
+    DEBUG((EFI_D_WARN,"Warning: the PCD PcdGicPrimaryCoreId does not seem to be set up for the configuration.\n"));\r
+  }\r
+  DEBUG_CODE_END();\r
+\r
+  // Make sure the Interrupt Controller Protocol is not already installed in the system.\r
+  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);\r
+\r
+  mGicNumInterrupts = ArmGicGetMaxNumInterrupts (PcdGet32(PcdGicDistributorBase));\r
+\r
+  for (Index = 0; Index < mGicNumInterrupts; Index++) {\r
+    DisableInterruptSource (&gHardwareInterruptProtocol, Index);\r
+    \r
+    // Set Priority \r
+    RegOffset = Index / 4;\r
+    RegShift = (Index % 4) * 8;\r
+    MmioAndThenOr32 (\r
+      PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPR + (4*RegOffset),\r
+      ~(0xff << RegShift), \r
+      ARM_GIC_DEFAULT_PRIORITY << RegShift\r
+      );\r
+  }\r
+\r
+  // Configure interrupts for Primary Cpu\r
+  CpuTarget = (1 << PcdGet32 (PcdGicPrimaryCoreId));\r
+  CpuTarget |= (CpuTarget << 24) | (CpuTarget << 16) | (CpuTarget << 8);\r
+  for (Index = 0; Index < (mGicNumInterrupts / 4); Index++) {\r
+    MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPTR + (Index*4), CpuTarget);\r
+  }\r
+\r
+  // Set binary point reg to 0x7 (no preemption)\r
+  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCBPR, 0x7);\r
+\r
+  // Set priority mask reg to 0xff to allow all priorities through\r
+  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0xff);\r
+  \r
+  // Enable gic cpu interface\r
+  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCICR, 0x1);\r
+\r
+  // Enable gic distributor\r
+  MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDDCR, 0x1);\r
+  \r
+  // Initialize the array for the Interrupt Handlers\r
+  gRegisteredInterruptHandlers = (HARDWARE_INTERRUPT_HANDLER*)AllocateZeroPool (sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);\r
+  \r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &gHardwareInterruptHandle,\r
+                  &gHardwareInterruptProtocolGuid,   &gHardwareInterruptProtocol,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  //\r
+  // Get the CPU protocol that this driver requires.\r
+  //\r
+  Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  //\r
+  // Unregister the default exception handler.\r
+  //\r
+  Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  //\r
+  // Register to receive interrupts\r
+  //\r
+  Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  // Register for an ExitBootServicesEvent\r
+  Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return Status;\r
+}\r