summaryrefslogtreecommitdiff
path: root/ArmPkg/Drivers
diff options
context:
space:
mode:
authorandrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524>2011-02-02 22:35:30 +0000
committerandrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524>2011-02-02 22:35:30 +0000
commit1bfda055dfbc52678655ab2ded721f9f7c0cd496 (patch)
treefbfa3654ec28d060955ff37e9e9365ad37179013 /ArmPkg/Drivers
parent7373d15a98fb571bf56688676c8ba950e6f62b8d (diff)
downloadedk2-platforms-1bfda055dfbc52678655ab2ded721f9f7c0cd496.tar.xz
Sync up ArmPkg with patch from mailing list. Changed name of BdsLib.h to BdsUnixLib.h and fixed a lot of issues with Xcode building.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11293 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ArmPkg/Drivers')
-rw-r--r--ArmPkg/Drivers/CpuDxe/CpuDxe.inf3
-rw-r--r--ArmPkg/Drivers/CpuDxe/Exception.c104
-rw-r--r--ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S29
-rw-r--r--ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm10
-rw-r--r--ArmPkg/Drivers/CpuDxe/ExceptionSupport.S10
-rw-r--r--ArmPkg/Drivers/CpuDxe/Mmu.c302
-rw-r--r--ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c119
-rw-r--r--ArmPkg/Drivers/PL180MciDxe/PL180Mci.c387
-rw-r--r--ArmPkg/Drivers/PL180MciDxe/PL180Mci.h117
-rw-r--r--ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf51
-rw-r--r--ArmPkg/Drivers/PL301Axi/PL301Axi.c108
-rw-r--r--ArmPkg/Drivers/PL301Axi/PL301Axi.inf29
-rw-r--r--ArmPkg/Drivers/PL310L2Cache/PL310L2Cache.c130
-rw-r--r--ArmPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf30
-rw-r--r--ArmPkg/Drivers/PL34xDmc/PL341Dmc.c373
-rw-r--r--ArmPkg/Drivers/PL34xDmc/PL341Dmc.inf29
-rw-r--r--ArmPkg/Drivers/PL35xSmc/InitializeSMC.S189
-rw-r--r--ArmPkg/Drivers/PL35xSmc/InitializeSMC.asm183
-rw-r--r--ArmPkg/Drivers/PL35xSmc/PL354SmcSec.inf30
-rw-r--r--ArmPkg/Drivers/PL390Gic/PL390GicDxe.c435
-rw-r--r--ArmPkg/Drivers/PL390Gic/PL390GicDxe.inf (renamed from ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf)99
-rw-r--r--ArmPkg/Drivers/PL390Gic/PL390GicNonSec.c97
-rw-r--r--ArmPkg/Drivers/PL390Gic/PL390GicNonSec.inf29
-rw-r--r--ArmPkg/Drivers/PL390Gic/PL390GicSec.c135
-rw-r--r--ArmPkg/Drivers/PL390Gic/PL390GicSec.inf29
25 files changed, 2612 insertions, 445 deletions
diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
index 2fc5fda691..25c0b880b2 100644
--- a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
@@ -67,10 +67,13 @@
gEfiDebugImageInfoTableGuid
[Pcd.common]
+ gArmTokenSpaceGuid.PcdVFPEnabled
gArmTokenSpaceGuid.PcdCpuVectorBaseAddress
[FeaturePcd.common]
gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport
+ gArmTokenSpaceGuid.PcdRelocateVectorTable
+ gArmTokenSpaceGuid.PcdEfiUncachedMemoryToStronglyOrdered
[depex]
gHardwareInterruptProtocolGuid
diff --git a/ArmPkg/Drivers/CpuDxe/Exception.c b/ArmPkg/Drivers/CpuDxe/Exception.c
index e0aca46cd7..21a4c035a9 100644
--- a/ArmPkg/Drivers/CpuDxe/Exception.c
+++ b/ArmPkg/Drivers/CpuDxe/Exception.c
@@ -14,6 +14,8 @@
#include "CpuDxe.h"
+//FIXME: Will not compile on non-ARMv7 builds
+#include <Chipset/ArmV7.h>
VOID
ExceptionHandlersStart (
@@ -127,6 +129,7 @@ InitializeExceptions (
EFI_PHYSICAL_ADDRESS Base;
UINT32 *VectorBase;
+ Status = EFI_SUCCESS;
//
// Disable interrupts
//
@@ -140,54 +143,63 @@ InitializeExceptions (
FiqEnabled = ArmGetFiqState ();
ArmDisableFiq ();
- //
- // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.
- //
- Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
-
- //
- // Reserve space for the exception handlers
- //
- Base = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdCpuVectorBaseAddress);
- VectorBase = (UINT32 *)(UINTN)Base;
- Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode, EFI_SIZE_TO_PAGES (Length), &Base);
- // If the request was for memory that's not in the memory map (which is often the case for 0x00000000
- // on embedded systems, for example, we don't want to hang up. So we'll check here for a status of
- // EFI_NOT_FOUND, and continue in that case.
- if (EFI_ERROR(Status) && (Status != EFI_NOT_FOUND)) {
- ASSERT_EFI_ERROR (Status);
- }
-
- // Save existing vector table, in case debugger is already hooked in
- CopyMem ((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof (gDebuggerExceptionHandlers));
-
- // Copy our assembly code into the page that contains the exception vectors.
- CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);
-
- //
- // Patch in the common Assembly exception handler
- //
- Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;
- *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;
-
- //
- // Initialize the C entry points for interrupts
- //
- for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {
- if ((gDebuggerExceptionHandlers[Index] == 0) || (gDebuggerExceptionHandlers[Index] == (VOID *)(UINTN)0xEAFFFFFE)) {
- // Exception handler contains branch to vector location (jmp $) so no handler
- // NOTE: This code assumes vectors are ARM and not Thumb code
- Status = RegisterInterruptHandler (Index, NULL);
- ASSERT_EFI_ERROR (Status);
- } else {
- // If the debugger has alread hooked put its vector back
- VectorBase[Index] = (UINT32)(UINTN)gDebuggerExceptionHandlers[Index];
- }
+ if (FeaturePcdGet(PcdRelocateVectorTable) == TRUE) {
+ //
+ // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.
+ //
+ Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
+
+ //
+ // Reserve space for the exception handlers
+ //
+ Base = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdCpuVectorBaseAddress);
+ VectorBase = (UINT32 *)(UINTN)Base;
+ Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode, EFI_SIZE_TO_PAGES (Length), &Base);
+ // If the request was for memory that's not in the memory map (which is often the case for 0x00000000
+ // on embedded systems, for example, we don't want to hang up. So we'll check here for a status of
+ // EFI_NOT_FOUND, and continue in that case.
+ if (EFI_ERROR(Status) && (Status != EFI_NOT_FOUND)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ // Save existing vector table, in case debugger is already hooked in
+ CopyMem ((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof (gDebuggerExceptionHandlers));
+
+ // Copy our assembly code into the page that contains the exception vectors.
+ CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);
+
+ //
+ // Patch in the common Assembly exception handler
+ //
+ Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;
+ *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;
+
+ //
+ // Initialize the C entry points for interrupts
+ //
+ for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {
+ if ((gDebuggerExceptionHandlers[Index] == 0) || (gDebuggerExceptionHandlers[Index] == (VOID *)(UINTN)0xEAFFFFFE)) {
+ // Exception handler contains branch to vector location (jmp $) so no handler
+ // NOTE: This code assumes vectors are ARM and not Thumb code
+ Status = RegisterInterruptHandler (Index, NULL);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ // If the debugger has alread hooked put its vector back
+ VectorBase[Index] = (UINT32)(UINTN)gDebuggerExceptionHandlers[Index];
+ }
+ }
+
+ // Flush Caches since we updated executable stuff
+ InvalidateInstructionCacheRange ((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length);
+
+ //Note: On ARM processor with the Security Extension, the Vector Table can be located anywhere in the memory.
+ // The Vector Base Address Register defines the location
+ ArmWriteVBar(PcdGet32(PcdCpuVectorBaseAddress));
+ } else {
+ // We do not copy the Exception Table at PcdGet32(PcdCpuVectorBaseAddress). We just set Vector Base Address to point into CpuDxe code.
+ ArmWriteVBar((UINT32)ExceptionHandlersStart);
}
- // Flush Caches since we updated executable stuff
- InvalidateInstructionCacheRange ((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length);
-
if (FiqEnabled) {
ArmEnableFiq ();
}
diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S
index 1c2bb62605..86d2a7135f 100644
--- a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S
+++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.S
@@ -14,6 +14,8 @@
#
#------------------------------------------------------------------------------
+#include <Library/PcdLib.h>
+
/*
This is the stack constructed by the exception handler (low address to high address)
@@ -50,22 +52,17 @@ This is the stack constructed by the exception handler (low address to high addr
*/
-.globl ASM_PFX(ExceptionHandlersStart)
-INTERWORK_FUNC(ExceptionHandlersStart)
-.globl ASM_PFX(ExceptionHandlersEnd)
-INTERWORK_FUNC(ExceptionHandlersEnd)
-.globl ASM_PFX(CommonExceptionEntry)
-INTERWORK_FUNC(CommonExceptionEntry)
-.globl ASM_PFX(AsmCommonExceptionEntry)
-INTERWORK_FUNC(AsmCommonExceptionEntry)
-.globl ASM_PFX(CommonCExceptionHandler)
-INTERWORK_FUNC(CommonCExceptionHandler)
+GCC_ASM_EXPORT(ExceptionHandlersStart)
+GCC_ASM_EXPORT(ExceptionHandlersEnd)
+GCC_ASM_EXPORT(CommonExceptionEntry)
+GCC_ASM_EXPORT(AsmCommonExceptionEntry)
+GCC_ASM_EXPORT(CommonCExceptionHandler)
.text
#if !defined(__APPLE__)
.fpu neon @ makes vpush/vpop assemble
#endif
-.align 3
+.align 5
//
@@ -198,10 +195,7 @@ ASM_PFX(FiqEntry):
// This gets patched by the C code that patches in the vector table
//
ASM_PFX(CommonExceptionEntry):
- .byte 0x12
- .byte 0x34
- .byte 0x56
- .byte 0x78
+ .word ASM_PFX(AsmCommonExceptionEntry)
ASM_PFX(ExceptionHandlersEnd):
@@ -254,8 +248,9 @@ NoAdjustNeeded:
@ R0 is ExceptionType
mov R1,SP @ R1 is SystemContext
+#if (FixedPcdGet32(PcdVFPEnabled))
vpush {d0-d15} @ save vstm registers in case they are used in optimizations
-
+#endif
/*
VOID
@@ -268,7 +263,9 @@ CommonCExceptionHandler (
*/
blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler
+#if (FixedPcdGet32(PcdVFPEnabled))
vpop {d0-d15}
+#endif
ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
mcr p15, 0, R1, c5, c0, 1 @ Write IFSR
diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm
index a8a477026e..240e1e38ae 100644
--- a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm
+++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.ARMv6.asm
@@ -14,7 +14,7 @@
//
//------------------------------------------------------------------------------
-
+#include <Library/PcdLib.h>
/*
@@ -61,6 +61,8 @@ This is the stack constructed by the exception handler (low address to high addr
PRESERVE8
AREA DxeExceptionHandlers, CODE, READONLY
+ ALIGN 32
+
//
// This code gets copied to the ARM vector table
// ExceptionHandlersStart - ExceptionHandlersEnd gets copied
@@ -190,7 +192,7 @@ FiqEntry
// This gets patched by the C code that patches in the vector table
//
CommonExceptionEntry
- dcd 0x12345678
+ dcd AsmCommonExceptionEntry
ExceptionHandlersEnd
@@ -243,7 +245,9 @@ NoAdjustNeeded
; R0 is ExceptionType
mov R1,SP ; R1 is SystemContext
+#if (FixedPcdGet32(PcdVFPEnabled))
vpush {d0-d15} ; save vstm registers in case they are used in optimizations
+#endif
/*
VOID
@@ -256,7 +260,9 @@ CommonCExceptionHandler (
*/
blx CommonCExceptionHandler ; Call exception handler
+#if (FixedPcdGet32(PcdVFPEnabled))
vpop {d0-d15}
+#endif
ldr R1, [SP, #0x4c] ; Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
mcr p15, 0, R1, c5, c0, 1 ; Write IFSR
diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S
index 223a383d36..96bd68246f 100644
--- a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S
+++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S
@@ -15,11 +15,11 @@
.text
.align 3
-.globl ASM_PFX(ExceptionHandlersStart)
-.globl ASM_PFX(ExceptionHandlersEnd)
-.globl ASM_PFX(CommonExceptionEntry)
-.globl ASM_PFX(AsmCommonExceptionEntry)
-.globl ASM_PFX(CommonCExceptionHandler)
+GCC_ASM_EXPORT(ExceptionHandlersStart)
+GCC_ASM_EXPORT(ExceptionHandlersEnd)
+GCC_ASM_EXPORT(CommonExceptionEntry)
+GCC_ASM_EXPORT(AsmCommonExceptionEntry)
+GCC_ASM_EXPORT(CommonCExceptionHandler)
ASM_PFX(ExceptionHandlersStart):
diff --git a/ArmPkg/Drivers/CpuDxe/Mmu.c b/ArmPkg/Drivers/CpuDxe/Mmu.c
index 3662e739e3..d7ea0eb551 100644
--- a/ArmPkg/Drivers/CpuDxe/Mmu.c
+++ b/ArmPkg/Drivers/CpuDxe/Mmu.c
@@ -15,129 +15,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
--*/
#include "CpuDxe.h"
-
-
-//
-// Translation/page table definitions
-//
+//FIXME: Remove this ARMv7 specific header
+#include <Chipset/ArmV7.h>
// First Level Descriptors
typedef UINT32 ARM_FIRST_LEVEL_DESCRIPTOR;
-// memory space covered by a first level descriptor
-#define ARM_PAGE_DESC_ENTRY_MVA_SIZE 0x00100000 // 1MB
-
-// number of first level descriptors to cover entire 32-bit memory space
-#define FIRST_LEVEL_ENTRY_COUNT (0xFFFFFFFF / ARM_PAGE_DESC_ENTRY_MVA_SIZE + 1)
-
-
-// page table 1st level descriptor entries
-#define ARM_PAGE_DESC_BASE_MASK 0xFFFFFC00
-#define ARM_PAGE_DESC_BASE_SHFIT 10
-#define ARM_PAGE_DESC_DOMAIN_MASK 0x000001E0
-#define ARM_PAGE_DESC_DOMAIN_SHIFT 5
-#define ARM_PAGE_DESC_NS 0x00000008
-
-#define ARM_FIRST_LEVEL_DESC_ALIGN 0x00004000 // 16KB
-
-// section 1st level desriptor entries
-#define ARM_SECTION_BASE_MASK 0xFFF00000
-#define ARM_SECTION_BASE_SHIFT 20
-#define ARM_SECTION_NS 0x00080000
-#define ARM_SECTION_nG 0x00020000
-#define ARM_SECTION_S 0x00010000
-#define ARM_SECTION_AP2 0x00008000
-#define ARM_SECTION_TEX_MASK 0x00007000
-#define ARM_SECTION_TEX_SHIFT 12
-#define ARM_SECTION_AP10_MASK 0x00000C00
-#define ARM_SECTION_AP10_SHIFT 10
-#define ARM_SECTION_DOMAIN_MASK 0x000001E0
-#define ARM_SECTION_DOMAIN_SHIFT 5
-#define ARM_SECTION_XN 0x00000010
-#define ARM_SECTION_C 0x00000008
-#define ARM_SECTION_B 0x00000004
-
-// section level AP[2:0] definitions
-#define ARM_SECTION_AP_NO_ACCESS 0 // AP[2:0] = 0
-#define ARM_SECTION_AP_READ_WRITE ARM_SECTION_AP10_MASK // AP[2:0] = 011
-#define ARM_SECTION_AP_READ_ONLY (ARM_SECTION_AP2 | ARM_SECTION_AP10_MASK) // AP[2:0] = 111
-
-// common 1st level descriptor fields
-#define ARM_DESC_TYPE_MASK 0x00000003
-
-// descriptor type values
-#define ARM_DESC_TYPE_FAULT 0x0
-#define ARM_DESC_TYPE_PAGE_TABLE 0x1
-#define ARM_DESC_TYPE_SECTION 0x2
-
-
// Second Level Descriptors
typedef UINT32 ARM_PAGE_TABLE_ENTRY;
-// small page 2nd level descriptor entries
-#define ARM_SMALL_PAGE_BASE_MASK 0xFFFFF000
-#define ARM_SMALL_PAGE_INDEX_MASK 0x000FF000
-#define ARM_SMALL_PAGE_BASE_SHIFT 12
-#define ARM_SMALL_PAGE_TEX_MASK 0x000001C0
-#define ARM_SMALL_PAGE_TEX_SHIFT 6
-#define ARM_SMALL_PAGE_XN 0x00000001
-
-// large page 2nd level descriptor entries
-#define ARM_LARGE_PAGE_BASE_MASK 0xFFFF0000
-#define ARM_LARGE_PAGE_BASE_SHIFT 16
-#define ARM_LARGE_PAGE_TEX_MASK 0x00007000
-#define ARM_LARGE_PAGE_TEX_SHIFT 12
-#define ARM_LARGE_PAGE_XN 0x00008000
-
-// common 2nd level desriptor fields
-#define ARM_PAGE_nG 0x00000800
-#define ARM_PAGE_S 0x00000400
-#define ARM_PAGE_AP2 0x00000200
-#define ARM_PAGE_AP10_MASK 0x00000030
-#define ARM_PAGE_AP10_SHIFT 4
-#define ARM_PAGE_C 0x00000008
-#define ARM_PAGE_B 0x00000004
-#define ARM_PAGE_DESC_TYPE_MASK 0x00000003
-
-// descriptor type values
-#define ARM_PAGE_TYPE_FAULT 0x0
-#define ARM_PAGE_TYPE_LARGE 0x1
-#define ARM_PAGE_TYPE_SMALL 0x2
-#define ARM_PAGE_TYPE_SMALL_XN 0x3
-
-#define SMALL_PAGE_TABLE_ENTRY_COUNT (ARM_PAGE_DESC_ENTRY_MVA_SIZE / SIZE_4KB)
-
-
-// Translation Table Base 0 fields
-#define ARM_TTBR0_BASE_MASK 0xFFFFC000
-#define ARM_TTBR0_BASE_SHIFT 14
-#define ARM_TTRB0_NOS 0x00000020
-
-// define the combination of interesting attributes: cacheability and access permissions
-#define ARM_SECTION_CACHEABILITY_MASK ( ARM_SECTION_TEX_MASK | ARM_SECTION_C | ARM_SECTION_B )
-#define ARM_SECTION_RW_PERMISSIONS_MASK ( ARM_SECTION_AP2 | ARM_SECTION_AP10_MASK )
-#define ARM_DESCRIPTOR_ATTRIBUTES ( ARM_SECTION_CACHEABILITY_MASK | ARM_SECTION_RW_PERMISSIONS_MASK | ARM_SECTION_XN )
-
-// cacheability values for section entries
-#define ARM_SECTION_STRONGLY_ORDERED 0
-#define ARM_SECTION_SHAREABLE_DEVICE ARM_SECTION_B
-#define ARM_SECTION_WRITE_THROUGH ARM_SECTION_C
-#define ARM_SECTION_WRITE_BACK_NWA ( ARM_SECTION_C| ARM_SECTION_B )
-#define ARM_SECTION_NORMAL_UNCACHEABLE ( 0x1 << ARM_SECTION_TEX_SHIFT )
-#define ARM_SECTION_WRITE_BACK ( ( 0x1 << ARM_SECTION_TEX_SHIFT ) | ARM_SECTION_C | ARM_SECTION_B )
-#define ARM_SECTION_NONSHAREABLE_DEVICE ( 0x2 << ARM_SECTION_TEX_SHIFT )
-
-// permissions values for section entries
-#define ARM_SECTION_NO_ACCESS 0
-#define ARM_SECTION_PRIV_ACCESS_ONLY ( 0x1 << ARM_SECTION_AP10_SHIFT)
-#define ARM_SECTION_USER_READ_ONLY ( 0x2 << ARM_SECTION_AP10_SHIFT)
-#define ARM_SECTION_FULL_ACCESS ( 0x3 << ARM_SECTION_AP10_SHIFT)
-#define ARM_SECTION_PRIV_READ_ONLY ( ARM_SECTION_AP2 | (0x1 << ARM_SECTION_AP10_SHIFT) )
-#define ARM_SECTION_READ_ONLY_DEP ( ARM_SECTION_AP2 | (0x2 << ARM_SECTION_AP10_SHIFT) )
-#define ARM_SECTION_READ_ONLY ( ARM_SECTION_AP2 | (0x3 << ARM_SECTION_AP10_SHIFT) )
-
-
-
EFI_STATUS
SectionToGcdAttributes (
IN UINT32 SectionAttributes,
@@ -147,47 +33,46 @@ SectionToGcdAttributes (
*GcdAttributes = 0;
// determine cacheability attributes
- switch(SectionAttributes & ARM_SECTION_CACHEABILITY_MASK) {
- case ARM_SECTION_STRONGLY_ORDERED:
+ switch(SectionAttributes & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) {
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED:
*GcdAttributes |= EFI_MEMORY_UC;
break;
- case ARM_SECTION_SHAREABLE_DEVICE:
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE:
*GcdAttributes |= EFI_MEMORY_UC;
break;
- case ARM_SECTION_WRITE_THROUGH:
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:
*GcdAttributes |= EFI_MEMORY_WT;
break;
- case ARM_SECTION_WRITE_BACK_NWA:
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC:
*GcdAttributes |= EFI_MEMORY_WB;
break;
- case ARM_SECTION_NORMAL_UNCACHEABLE:
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE:
*GcdAttributes |= EFI_MEMORY_WC;
break;
- case ARM_SECTION_WRITE_BACK:
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC:
*GcdAttributes |= EFI_MEMORY_WB;
break;
- case ARM_SECTION_NONSHAREABLE_DEVICE:
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE:
*GcdAttributes |= EFI_MEMORY_UC;
break;
default:
return EFI_UNSUPPORTED;
}
-
+
// determine protection attributes
- switch(SectionAttributes & ARM_SECTION_RW_PERMISSIONS_MASK) {
- case ARM_SECTION_NO_ACCESS: // no read, no write
+ switch(SectionAttributes & TT_DESCRIPTOR_SECTION_AP_MASK) {
+ case TT_DESCRIPTOR_SECTION_AP_NO_NO: // no read, no write
//*GcdAttributes |= EFI_MEMORY_WP | EFI_MEMORY_RP;
break;
- case ARM_SECTION_PRIV_ACCESS_ONLY:
- case ARM_SECTION_FULL_ACCESS:
+ case TT_DESCRIPTOR_SECTION_AP_RW_NO:
+ case TT_DESCRIPTOR_SECTION_AP_RW_RW:
// normal read/write access, do not add additional attributes
break;
// read only cases map to write-protect
- case ARM_SECTION_PRIV_READ_ONLY:
- case ARM_SECTION_READ_ONLY_DEP:
- case ARM_SECTION_READ_ONLY:
+ case TT_DESCRIPTOR_SECTION_AP_RO_NO:
+ case TT_DESCRIPTOR_SECTION_AP_RO_RO:
*GcdAttributes |= EFI_MEMORY_WP;
break;
@@ -196,7 +81,7 @@ SectionToGcdAttributes (
}
// now process eXectue Never attribute
- if ((SectionAttributes & ARM_SECTION_XN) != 0 ) {
+ if ((SectionAttributes & TT_DESCRIPTOR_SECTION_XN_MASK) != 0 ) {
*GcdAttributes |= EFI_MEMORY_XP;
}
@@ -369,22 +254,22 @@ SyncCacheConfig (
// with a way for GCD to query the CPU Arch. driver of the existing memory space attributes instead.
// obtain page table base
- FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)(ArmGetTranslationTableBaseAddress ());
+ FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)(ArmGetTTBR0BaseAddress ());
// iterate through each 1MB descriptor
NextRegionBase = NextRegionLength = 0;
- for (i=0; i< FIRST_LEVEL_ENTRY_COUNT; i++) {
+ for (i=0; i< TRANSLATION_TABLE_SECTION_COUNT; i++) {
// obtain existing descriptor and make sure it contains a valid Base Address even if it is a fault section
- Descriptor = FirstLevelTable[i] | (ARM_SECTION_BASE_MASK & (i << ARM_SECTION_BASE_SHIFT));
+ Descriptor = FirstLevelTable[i] | TT_DESCRIPTOR_SECTION_BASE_ADDRESS(i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
// extract attributes (cacheability and permissions)
- SectionAttributes = Descriptor & 0xDEC;
+ SectionAttributes = Descriptor & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK);
// do we already have an existing region (or are we about to finish)?
// Skip the first entry, and make sure we close on the last entry
- if ( (NextRegionLength > 0) || (i == (FIRST_LEVEL_ENTRY_COUNT-1)) ) {
+ if ( (NextRegionLength > 0) || (i == (TRANSLATION_TABLE_SECTION_COUNT-1)) ) {
// attributes are changing, update attributes in GCD
if (SectionAttributes != NextRegionAttributes) {
@@ -398,7 +283,7 @@ SyncCacheConfig (
// start on a new region
NextRegionLength = 0;
- NextRegionBase = Descriptor & ARM_SECTION_BASE_MASK;
+ NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(Descriptor);
}
}
@@ -407,7 +292,7 @@ SyncCacheConfig (
NextRegionAttributes = SectionAttributes;
}
- NextRegionLength += ARM_PAGE_DESC_ENTRY_MVA_SIZE;
+ NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;
} // section entry loop
@@ -444,37 +329,42 @@ UpdatePageEntries (
// EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)
// EntryValue: values at bit positions specified by EntryMask
- EntryMask = ARM_PAGE_DESC_TYPE_MASK;
- EntryValue = ARM_PAGE_TYPE_SMALL;
+ EntryMask = TT_DESCRIPTOR_PAGE_TYPE_MASK;
+ EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE;
// Although the PI spec is unclear on this the GCD guarantees that only
// one Attribute bit is set at a time, so we can safely use a switch statement
switch (Attributes) {
case EFI_MEMORY_UC:
// modify cacheability attributes
- EntryMask |= ARM_SMALL_PAGE_TEX_MASK | ARM_PAGE_C | ARM_PAGE_B;
- // map to strongly ordered
- EntryValue |= 0; // TEX[2:0] = 0, C=0, B=0
+ EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
+ if (FeaturePcdGet(PcdEfiUncachedMemoryToStronglyOrdered)) {
+ // map to strongly ordered
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0
+ } else {
+ // map to normal non-cachable
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
+ }
break;
case EFI_MEMORY_WC:
// modify cacheability attributes
- EntryMask |= ARM_SMALL_PAGE_TEX_MASK | ARM_PAGE_C | ARM_PAGE_B;
+ EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
// map to normal non-cachable
- EntryValue |= (0x1 << ARM_SMALL_PAGE_TEX_SHIFT); // TEX [2:0]= 001 = 0x2, B=0, C=0
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
break;
case EFI_MEMORY_WT:
// modify cacheability attributes
- EntryMask |= ARM_SMALL_PAGE_TEX_MASK | ARM_PAGE_C | ARM_PAGE_B;
+ EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
// write through with no-allocate
- EntryValue |= ARM_PAGE_C; // TEX [2:0] = 0, C=1, B=0
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0
break;
case EFI_MEMORY_WB:
// modify cacheability attributes
- EntryMask |= ARM_SMALL_PAGE_TEX_MASK | ARM_PAGE_C | ARM_PAGE_B;
+ EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;
// write back (with allocate)
- EntryValue |= (0x1 << ARM_SMALL_PAGE_TEX_SHIFT) | ARM_PAGE_C | ARM_PAGE_B; // TEX [2:0] = 001, C=1, B=1
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1
break;
case EFI_MEMORY_WP:
@@ -482,7 +372,7 @@ UpdatePageEntries (
case EFI_MEMORY_UCE:
// cannot be implemented UEFI definition unclear for ARM
// Cause a page fault if these ranges are accessed.
- EntryValue = ARM_PAGE_TYPE_FAULT;
+ EntryValue = TT_DESCRIPTOR_PAGE_TYPE_FAULT;
DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): setting page %lx with unsupported attribute %x will page fault on access\n", BaseAddress, Attributes));
break;
@@ -491,7 +381,7 @@ UpdatePageEntries (
}
// obtain page table base
- FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTranslationTableBaseAddress ();
+ FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
// calculate number of 4KB page table entries to change
NumPageEntries = Length/SIZE_4KB;
@@ -501,15 +391,15 @@ UpdatePageEntries (
for(p=0; p<NumPageEntries; p++) {
// calculate index into first level translation table for page table value
- FirstLevelIdx = ((BaseAddress + Offset) & ARM_SECTION_BASE_MASK) >> ARM_SECTION_BASE_SHIFT;
- ASSERT (FirstLevelIdx < FIRST_LEVEL_ENTRY_COUNT);
+ FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress + Offset) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
+ ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
// read the descriptor from the first level page table
Descriptor = FirstLevelTable[FirstLevelIdx];
// does this descriptor need to be converted from section entry to 4K pages?
- if ((Descriptor & ARM_DESC_TYPE_MASK) != ARM_DESC_TYPE_PAGE_TABLE ) {
- Status = ConvertSectionToPages (FirstLevelIdx << ARM_SECTION_BASE_SHIFT);
+ if (!TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(Descriptor)) {
+ Status = ConvertSectionToPages (FirstLevelIdx << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
if (EFI_ERROR(Status)) {
// exit for loop
break;
@@ -520,11 +410,11 @@ UpdatePageEntries (
}
// obtain page table base address
- PageTable = (ARM_PAGE_TABLE_ENTRY *)(Descriptor & ARM_SMALL_PAGE_BASE_MASK);
+ PageTable = (ARM_PAGE_TABLE_ENTRY *)TT_DESCRIPTOR_PAGE_BASE_ADDRESS(Descriptor);
// calculate index into the page table
- PageTableIndex = ((BaseAddress + Offset) & ARM_SMALL_PAGE_INDEX_MASK) >> ARM_SMALL_PAGE_BASE_SHIFT;
- ASSERT (PageTableIndex < SMALL_PAGE_TABLE_ENTRY_COUNT);
+ PageTableIndex = ((BaseAddress + Offset) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
+ ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);
// get the entry
CurrentPageTableEntry = PageTable[PageTableIndex];
@@ -541,8 +431,8 @@ UpdatePageEntries (
}
if (CurrentPageTableEntry != PageTableEntry) {
- Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << ARM_SECTION_BASE_SHIFT) + (PageTableIndex << ARM_SMALL_PAGE_BASE_SHIFT));
- if ((CurrentPageTableEntry & ARM_PAGE_C) == ARM_PAGE_C) {
+ Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SECTION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT));
+ if ((CurrentPageTableEntry & TT_DESCRIPTOR_PAGE_CACHEABLE_MASK) == TT_DESCRIPTOR_PAGE_CACHEABLE_MASK) {
// The current section mapping is cacheable so Clean/Invalidate the MVA of the page
// Note assumes switch(Attributes), not ARMv7 possibilities
WriteBackInvalidateDataCacheRange (Mva, SIZE_4KB);
@@ -586,38 +476,43 @@ UpdateSectionEntries (
// EntryValue: values at bit positions specified by EntryMask
// Make sure we handle a section range that is unmapped
- EntryMask = ARM_DESC_TYPE_MASK;
- EntryValue = ARM_DESC_TYPE_SECTION;
+ EntryMask = TT_DESCRIPTOR_SECTION_TYPE_MASK;
+ EntryValue = TT_DESCRIPTOR_SECTION_TYPE_SECTION;
// Although the PI spec is unclear on this the GCD guarantees that only
// one Attribute bit is set at a time, so we can safely use a switch statement
switch(Attributes) {
case EFI_MEMORY_UC:
// modify cacheability attributes
- EntryMask |= ARM_SECTION_CACHEABILITY_MASK;
- // map to strongly ordered
- EntryValue |= 0; // TEX[2:0] = 0, C=0, B=0
+ EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
+ if (FeaturePcdGet(PcdEfiUncachedMemoryToStronglyOrdered)) {
+ // map to strongly ordered
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0
+ } else {
+ // map to normal non-cachable
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
+ }
break;
case EFI_MEMORY_WC:
// modify cacheability attributes
- EntryMask |= ARM_SECTION_CACHEABILITY_MASK;
+ EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
// map to normal non-cachable
- EntryValue |= (0x1 << ARM_SECTION_TEX_SHIFT); // TEX [2:0]= 001 = 0x2, B=0, C=0
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
break;
case EFI_MEMORY_WT:
// modify cacheability attributes
- EntryMask |= ARM_SECTION_CACHEABILITY_MASK;
+ EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
// write through with no-allocate
- EntryValue |= ARM_SECTION_C; // TEX [2:0] = 0, C=1, B=0
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0
break;
case EFI_MEMORY_WB:
// modify cacheability attributes
- EntryMask |= ARM_SECTION_CACHEABILITY_MASK;
+ EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;
// write back (with allocate)
- EntryValue |= (0x1 << ARM_SECTION_TEX_SHIFT) | ARM_SECTION_C | ARM_SECTION_B; // TEX [2:0] = 001, C=1, B=1
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1
break;
case EFI_MEMORY_WP:
@@ -626,7 +521,7 @@ UpdateSectionEntries (
case EFI_MEMORY_UCE:
// cannot be implemented UEFI definition unclear for ARM
// Cause a page fault if these ranges are accessed.
- EntryValue = ARM_DESC_TYPE_FAULT;
+ EntryValue = TT_DESCRIPTOR_SECTION_TYPE_FAULT;
DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): setting section %lx with unsupported attribute %x will page fault on access\n", BaseAddress, Attributes));
break;
@@ -636,23 +531,23 @@ UpdateSectionEntries (
}
// obtain page table base
- FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTranslationTableBaseAddress ();
+ FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
// calculate index into first level translation table for start of modification
- FirstLevelIdx = (BaseAddress & ARM_SECTION_BASE_MASK) >> ARM_SECTION_BASE_SHIFT;
- ASSERT (FirstLevelIdx < FIRST_LEVEL_ENTRY_COUNT);
+ FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
+ ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
// calculate number of 1MB first level entries this applies to
- NumSections = Length / ARM_PAGE_DESC_ENTRY_MVA_SIZE;
+ NumSections = Length / TT_DESCRIPTOR_SECTION_SIZE;
// iterate through each descriptor
for(i=0; i<NumSections; i++) {
CurrentDescriptor = FirstLevelTable[FirstLevelIdx + i];
// has this descriptor already been coverted to pages?
- if ((CurrentDescriptor & ARM_DESC_TYPE_MASK) != ARM_DESC_TYPE_PAGE_TABLE ) {
+ if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(CurrentDescriptor)) {
// forward this 1MB range to page table function instead
- Status = UpdatePageEntries ((FirstLevelIdx + i) << ARM_SECTION_BASE_SHIFT, ARM_PAGE_DESC_ENTRY_MVA_SIZE, Attributes, VirtualMask);
+ Status = UpdatePageEntries ((FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT, TT_DESCRIPTOR_SECTION_SIZE, Attributes, VirtualMask);
} else {
// still a section entry
@@ -666,8 +561,8 @@ UpdateSectionEntries (
}
if (CurrentDescriptor != Descriptor) {
- Mva = (VOID *)(UINTN)(((UINTN)FirstLevelTable) << ARM_SECTION_BASE_SHIFT);
- if ((CurrentDescriptor & ARM_SECTION_C) == ARM_SECTION_C) {
+ Mva = (VOID *)(UINTN)(((UINTN)FirstLevelTable) << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
+ if ((CurrentDescriptor & TT_DESCRIPTOR_SECTION_CACHEABLE_MASK) == TT_DESCRIPTOR_SECTION_CACHEABLE_MASK) {
// The current section mapping is cacheable so Clean/Invalidate the MVA of the section
// Note assumes switch(Attributes), not ARMv7 possabilities
WriteBackInvalidateDataCacheRange (Mva, SIZE_1MB);
@@ -704,35 +599,20 @@ ConvertSectionToPages (
DEBUG ((EFI_D_PAGE, "Converting section at 0x%x to pages\n", (UINTN)BaseAddress));
// obtain page table base
- FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTranslationTableBaseAddress ();
+ FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
// calculate index into first level translation table for start of modification
- FirstLevelIdx = (BaseAddress & ARM_SECTION_BASE_MASK) >> ARM_SECTION_BASE_SHIFT;
- ASSERT (FirstLevelIdx < FIRST_LEVEL_ENTRY_COUNT);
+ FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
+ ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);
// get section attributes and convert to page attributes
SectionDescriptor = FirstLevelTable[FirstLevelIdx];
- PageDescriptor = ARM_PAGE_TYPE_SMALL;
- PageDescriptor |= ((SectionDescriptor & ARM_SECTION_TEX_MASK) >> ARM_SECTION_TEX_SHIFT) << ARM_SMALL_PAGE_TEX_SHIFT;
- if ((SectionDescriptor & ARM_SECTION_B) != 0) {
- PageDescriptor |= ARM_PAGE_B;
- }
- if ((SectionDescriptor & ARM_SECTION_C) != 0) {
- PageDescriptor |= ARM_PAGE_C;
- }
- PageDescriptor |= ((SectionDescriptor & ARM_SECTION_AP10_MASK) >> ARM_SECTION_AP10_SHIFT) << ARM_PAGE_AP10_SHIFT;
- if ((SectionDescriptor & ARM_SECTION_AP2) != 0) {
- PageDescriptor |= ARM_PAGE_AP2;
- }
- if ((SectionDescriptor & ARM_SECTION_XN) != 0) {
- PageDescriptor |= ARM_PAGE_TYPE_SMALL_XN;
- }
- if ((SectionDescriptor & ARM_SECTION_nG) != 0) {
- PageDescriptor |= ARM_PAGE_nG;
- }
- if ((SectionDescriptor & ARM_SECTION_S) != 0) {
- PageDescriptor |= ARM_PAGE_S;
- }
+ PageDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE;
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY(SectionDescriptor,0);
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_AP(SectionDescriptor);
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_XN(SectionDescriptor,0);
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_NG(SectionDescriptor);
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_S(SectionDescriptor);
// allocate a page table for the 4KB entries (we use up a full page even though we only need 1KB)
Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, 1, &PageTableAddr);
@@ -743,15 +623,15 @@ ConvertSectionToPages (
PageTable = (volatile ARM_PAGE_TABLE_ENTRY *)(UINTN)PageTableAddr;
// write the page table entries out
- for (i=0; i<(ARM_PAGE_DESC_ENTRY_MVA_SIZE/SIZE_4KB); i++) {
- PageTable[i] = ((BaseAddress + (i << 12)) & ARM_SMALL_PAGE_BASE_MASK) | PageDescriptor;
+ for (i=0; i < TRANSLATION_TABLE_PAGE_COUNT; i++) {
+ PageTable[i] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseAddress + (i << 12)) | PageDescriptor;
}
// flush d-cache so descriptors make it back to uncached memory for subsequent table walks
WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)PageTableAddr, SIZE_4KB);
// formulate page table entry, Domain=0, NS=0
- PageTableDescriptor = (((UINTN)PageTableAddr) & ARM_PAGE_DESC_BASE_MASK) | ARM_DESC_TYPE_PAGE_TABLE;
+ PageTableDescriptor = (((UINTN)PageTableAddr) & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) | TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;
// write the page table entry out, repalcing section entry
FirstLevelTable[FirstLevelIdx] = PageTableDescriptor;
@@ -910,7 +790,3 @@ VIRTUAL_UNCACHED_PAGES_PROTOCOL gVirtualUncachedPages = {
CpuConvertPagesToUncachedVirtualAddress,
CpuReconvertPages
};
-
-
-
-
diff --git a/ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c b/ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c
deleted file mode 100644
index 5498aabc75..0000000000
--- a/ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/** @file
-
- Copyright (c) 2008 - 2009, Apple Inc. 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.
-
-**/
-
-#include <Uefi.h>
-
-#include <Library/CacheMaintenanceLib.h>
-#include <Library/DebugLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-
-#include <Protocol/Cpu.h>
-#include <Protocol/DebugSupport.h>
-#include <Protocol/TimerDebugSupport.h>
-
-EFI_STATUS
-EFIAPI
-DebugSupportGetMaximumProcessorIndex (
- IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
- OUT UINTN *MaxProcessorIndex
- )
-{
- if (MaxProcessorIndex == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- *MaxProcessorIndex = 0;
-
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-EFIAPI
-DebugSupportRegisterPeriodicCallback (
- IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
- IN UINTN ProcessorIndex,
- IN EFI_PERIODIC_CALLBACK PeriodicCallback
- )
-{
- TIMER_DEBUG_SUPPORT_PROTOCOL *Timer;
- EFI_STATUS Status;
-
- Status = gBS->LocateProtocol(&gTimerDebugSupportProtocolGuid, NULL, (VOID **)&Timer);
- if (EFI_ERROR(Status)) {
- return Status;
- }
-
- Status = Timer->RegisterPeriodicCallback(Timer, PeriodicCallback);
-
- return Status;
-}
-
-EFI_STATUS
-EFIAPI
-DebugSupportRegisterExceptionCallback (
- IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
- IN UINTN ProcessorIndex,
- IN EFI_EXCEPTION_CALLBACK ExceptionCallback,
- IN EFI_EXCEPTION_TYPE ExceptionType
- )
-{
- EFI_CPU_ARCH_PROTOCOL *Cpu;
- EFI_STATUS Status;
-
- Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
- if (EFI_ERROR(Status)) {
- return Status;
- }
-
- Status = Cpu->RegisterInterruptHandler(Cpu, ExceptionType, (EFI_CPU_INTERRUPT_HANDLER)ExceptionCallback);
-
- return Status;
-}
-
-EFI_STATUS
-EFIAPI
-DebugSupportInvalidateInstructionCache (
- IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
- IN UINTN ProcessorIndex,
- IN VOID *Start,
- IN UINT64 Length
- )
-{
- InvalidateInstructionCacheRange(Start, Length);
- return EFI_SUCCESS;
-}
-
-EFI_DEBUG_SUPPORT_PROTOCOL mDebugSupport = {
- IsaArm,
- DebugSupportGetMaximumProcessorIndex,
- DebugSupportRegisterPeriodicCallback,
- DebugSupportRegisterExceptionCallback,
- DebugSupportInvalidateInstructionCache
-};
-
-EFI_STATUS
-DebugSupportDxeInitialize (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE Handle = NULL;
-
- ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiDebugSupportProtocolGuid);
- Status = gBS->InstallMultipleProtocolInterfaces(&Handle, &gEfiDebugSupportProtocolGuid, &mDebugSupport, NULL);
-
- return Status;
-}
-
diff --git a/ArmPkg/Drivers/PL180MciDxe/PL180Mci.c b/ArmPkg/Drivers/PL180MciDxe/PL180Mci.c
new file mode 100644
index 0000000000..fe6c904ff3
--- /dev/null
+++ b/ArmPkg/Drivers/PL180MciDxe/PL180Mci.c
@@ -0,0 +1,387 @@
+/** @file
+ This file implement the MMC Host Protocol for the ARM PrimeCell PL180.
+
+ Copyright (c) 2011, 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 "PL180Mci.h"
+
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+
+EFI_MMC_HOST_PROTOCOL *gpMmcHost;
+
+// Untested ...
+//#define USE_STREAM
+
+#define MMCI0_BLOCKLEN 512
+#define MMCI0_POW2_BLOCKLEN 9
+#define MMCI0_TIMEOUT 1000
+
+BOOLEAN MciIsPowerOn() {
+ return ((MmioRead32(MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);
+}
+
+EFI_STATUS MciInitialize() {
+ MCI_TRACE("MciInitialize()");
+ return EFI_SUCCESS;
+}
+
+BOOLEAN MciIsCardPresent() {
+ return (MmioRead32(FixedPcdGet32(PcdPL180SysMciRegAddress)) & 1);
+}
+
+BOOLEAN MciIsReadOnly() {
+ return (MmioRead32(FixedPcdGet32(PcdPL180SysMciRegAddress)) & 2);
+}
+
+// Convert block size to 2^n
+UINT32 GetPow2BlockLen(UINT32 BlockLen) {
+ UINTN Loop;
+ UINTN Pow2BlockLen;
+
+ Loop = 0x8000;
+ Pow2BlockLen = 15;
+ do {
+ Loop = (Loop >> 1) & 0xFFFF;
+ Pow2BlockLen--;
+ } while (Pow2BlockLen && (!(Loop & BlockLen)));
+
+ return Pow2BlockLen;
+}
+
+VOID MciPrepareDataPath(UINTN TransferDirection) {
+ // Set Data Length & Data Timer
+ MmioWrite32(MCI_DATA_TIMER_REG,0xFFFFFFF);
+ MmioWrite32(MCI_DATA_LENGTH_REG,MMCI0_BLOCKLEN);
+
+#ifndef USE_STREAM
+ //Note: we are using a hardcoded BlockLen (=512). If we decide to use a variable size, we could
+ // compute the pow2 of BlockLen with the above function GetPow2BlockLen()
+ MmioWrite32(MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | TransferDirection | (MMCI0_POW2_BLOCKLEN << 4));
+#else
+ MmioWrite32(MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | TransferDirection | MCI_DATACTL_STREAM_TRANS);
+#endif
+}
+
+EFI_STATUS MciSendCommand(MMC_CMD MmcCmd, UINT32 Argument) {
+ UINT32 Status;
+ UINT32 Timer;
+ UINT32 Cmd;
+
+ if ((MmcCmd == MMC_CMD17) || (MmcCmd == MMC_CMD11)) {
+ MciPrepareDataPath(MCI_DATACTL_CARD_TO_CONT);
+ } else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {
+ MciPrepareDataPath(MCI_DATACTL_CONT_TO_CARD);
+ }
+
+ // Create Command for PL180
+ Cmd = INDX(MmcCmd);
+ if (MmcCmd & MMC_CMD_WAIT_RESPONSE)
+ Cmd |= MCI_CPSM_WAIT_RESPONSE;
+ if (MmcCmd & MMC_CMD_LONG_RESPONSE)
+ Cmd |= MCI_CPSM_LONG_RESPONSE;
+
+ MmioWrite32(MCI_CLEAR_STATUS_REG,0x5FFF);
+ MmioWrite32(MCI_ARGUMENT_REG,Argument);
+ MmioWrite32(MCI_COMMAND_REG,Cmd);
+
+ Timer = 1000;
+ if (Cmd & MCI_CPSM_WAIT_RESPONSE) {
+ Status = MmioRead32(MCI_STATUS_REG);
+ while (!(Status & (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT)) && Timer) {
+ //NanoSecondDelay(10);
+ Status = MmioRead32(MCI_STATUS_REG);
+ Timer--;
+ }
+
+ if ((Timer == 0) || (Status == MCI_STATUS_CMD_CMDTIMEOUT)) {
+ //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%X\n",Cmd & 0x3F,MmioRead32(MCI_RESPONSE0_REG),Status));
+ return EFI_TIMEOUT;
+ } else if (!((Cmd & 0x3F) == INDX(1)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {
+ // The CMD1 does not contain CRC. We should ignore the CRC failed Status.
+ return EFI_CRC_ERROR;
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ Status = MmioRead32(MCI_STATUS_REG);
+ while (!(Status & MCI_STATUS_CMD_SENT) && Timer) {
+ //NanoSecondDelay(10);
+ Status = MmioRead32(MCI_STATUS_REG);
+ Timer--;
+ }
+
+ if (Timer == 0) {
+ //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT2! 0x%X\n",Cmd & 0x3F,MmioRead32(MCI_RESPONSE0_REG)));
+ return EFI_TIMEOUT;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+}
+
+EFI_STATUS MciReceiveResponse(MMC_RESPONSE_TYPE Type, UINT32* Buffer) {
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Type == MMC_RESPONSE_TYPE_R1) || (Type == MMC_RESPONSE_TYPE_R1b) ||
+ (Type == MMC_RESPONSE_TYPE_R3) || (Type == MMC_RESPONSE_TYPE_R6) ||
+ (Type == MMC_RESPONSE_TYPE_R7)) {
+ Buffer[0] = MmioRead32(MCI_RESPONSE0_REG);
+ Buffer[1] = MmioRead32(MCI_RESPONSE1_REG);
+ } else if (Type == MMC_RESPONSE_TYPE_R2) {
+ Buffer[0] = MmioRead32(MCI_RESPONSE0_REG);
+ Buffer[1] = MmioRead32(MCI_RESPONSE1_REG);
+ Buffer[2] = MmioRead32(MCI_RESPONSE2_REG);
+ Buffer[3] = MmioRead32(MCI_RESPONSE3_REG);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS MciReadBlockData(EFI_LBA Lba, UINTN Length, UINT32* Buffer) {
+ UINTN Loop;
+ UINTN Finish;
+ UINTN Timer;
+ UINTN Status;
+
+ // Read data from the RX FIFO
+ Loop = 0;
+ Finish = MMCI0_BLOCKLEN / 4;
+ Timer = MMCI0_TIMEOUT * 10;
+ do {
+ // Read the Status flags
+ Status = MmioRead32(MCI_STATUS_REG);
+ // Do eight reads if possible else a single read
+ if (Status & MCI_STATUS_CMD_RXFIFOHALFFULL) {
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ }
+ else if (!(Status & MCI_STATUS_CMD_RXFIFOEMPTY)) {
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ } else
+ Timer--;
+ } while ((Loop < Finish) && Timer);
+
+ if (Timer == 0) {
+ DEBUG ((EFI_D_ERROR, "MciReadBlockData: Timeout Status:0x%X Loop:%d // Finish:%d\n",MmioRead32(MCI_STATUS_REG),Loop,Finish));
+ return EFI_TIMEOUT;
+ } else
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS MciWriteBlockData(EFI_LBA Lba, UINTN Length, UINT32* Buffer) {
+ UINTN Loop;
+ UINTN Finish;
+ UINTN Timer;
+ UINTN Status;
+
+ // Write the data to the TX FIFO
+ Loop = 0;
+ Finish = MMCI0_BLOCKLEN / 4;
+ Timer = MMCI0_TIMEOUT * 100;
+ do {
+ // Read the Status flags
+ Status = MmioRead32(MCI_STATUS_REG);
+
+ // Do eight writes if possible else a single write
+ if (Status & MCI_STATUS_CMD_TXFIFOHALFEMPTY) {
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ }
+ else if (!(Status & MCI_STATUS_CMD_TXFIFOFULL)) {
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ }
+ else
+ Timer--;
+ } while ((Loop < Finish) && Timer);
+
+ ASSERT(Timer > 0);
+
+ // Wait for FIFO to drain
+ Timer = MMCI0_TIMEOUT;
+ Status = MmioRead32(MCI_STATUS_REG);
+/*#ifndef USE_STREAM
+ // Single block
+ while (((Status & MCI_STATUS_CMD_TXDONE) != MCI_STATUS_CMD_TXDONE) && Timer) {
+#else*/
+ // Stream
+ while (((Status & MCI_STATUS_CMD_DATAEND) != MCI_STATUS_CMD_DATAEND) && Timer) {
+//#endif
+ NanoSecondDelay(10);
+ Status = MmioRead32(MCI_STATUS_REG);
+ Timer--;
+ }
+
+ ASSERT(Timer > 0);
+
+ if (Timer == 0)
+ return EFI_TIMEOUT;
+ else
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS MciNotifyState(MMC_STATE State) {
+ UINT32 Data32;
+
+ switch(State) {
+ case MmcInvalidState:
+ ASSERT(0);
+ break;
+ case MmcHwInitializationState:
+ // If device already turn on then restart it
+ Data32 = MmioRead32(MCI_POWER_CONTROL_REG);
+ if ((Data32 & 0x2) == MCI_POWER_UP) {
+ MCI_TRACE("MciNotifyState(MmcHwInitializationState): TurnOff MCI");
+
+ // Turn off
+ MmioWrite32(MCI_CLOCK_CONTROL_REG, 0);
+ MmioWrite32(MCI_POWER_CONTROL_REG, 0);
+ MicroSecondDelay(100);
+ }
+
+ MCI_TRACE("MciNotifyState(MmcHwInitializationState): TurnOn MCI");
+ // Setup clock
+ // - 0x1D = 29 => should be the clock divider to be less than 400kHz at MCLK = 24Mhz
+ MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);
+ //MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE);
+
+ // Set the voltage
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_OPENDRAIN | (15<<2));
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_UP);
+ MicroSecondDelay(10);
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_ON);
+ MicroSecondDelay(100);
+
+ // Set Data Length & Data Timer
+ MmioWrite32(MCI_DATA_TIMER_REG,0xFFFFF);
+ MmioWrite32(MCI_DATA_LENGTH_REG,8);
+
+ ASSERT((MmioRead32(MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);
+ break;
+ case MmcIdleState:
+ MCI_TRACE("MciNotifyState(MmcIdleState)");
+ break;
+ case MmcReadyState:
+ MCI_TRACE("MciNotifyState(MmcReadyState)");
+ break;
+ case MmcIdentificationState:
+ MCI_TRACE("MciNotifyState(MmcIdentificationState)");
+ break;
+ case MmcStandByState:
+ MCI_TRACE("MciNotifyState(MmcStandByState)");
+
+ // Enable MCICMD push-pull drive
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | (15<<2) | MCI_POWER_ON);
+
+ /*// Set MMCI0 clock to 4MHz (24MHz may be possible with cache enabled)
+ MmioWrite32(MCI_CLOCK_CONTROL_REG,0x02 | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);*/
+ // Set MMCI0 clock to 24MHz (by bypassing the divider)
+ MmioWrite32(MCI_CLOCK_CONTROL_REG,MCI_CLOCK_BYPASS | MCI_CLOCK_ENABLE);
+ break;
+ case MmcTransferState:
+ //MCI_TRACE("MciNotifyState(MmcTransferState)");
+ break;
+ case MmcSendingDataState:
+ MCI_TRACE("MciNotifyState(MmcSendingDataState)");
+ break;
+ case MmcReceiveDataState:
+ MCI_TRACE("MciNotifyState(MmcReceiveDataState)");
+ break;
+ case MmcProgrammingState:
+ MCI_TRACE("MciNotifyState(MmcProgrammingState)");
+ break;
+ case MmcDisconnectState:
+ MCI_TRACE("MciNotifyState(MmcDisconnectState)");
+ break;
+ default:
+ ASSERT(0);
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_GUID mPL180MciDevicePathGuid = { 0x621b6fa5, 0x4dc1, 0x476f, 0xb9, 0xd8, 0x52, 0xc5, 0x57, 0xd8, 0x10, 0x70 };
+
+EFI_STATUS MciBuildDevicePath(EFI_DEVICE_PATH_PROTOCOL **DevicePath) {
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
+
+ NewDevicePathNode = CreateDeviceNode(HARDWARE_DEVICE_PATH,HW_VENDOR_DP,sizeof(VENDOR_DEVICE_PATH));
+ CopyGuid(&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid,&mPL180MciDevicePathGuid);
+
+ *DevicePath = NewDevicePathNode;
+ return EFI_SUCCESS;
+}
+
+EFI_MMC_HOST_PROTOCOL gMciHost = {
+ MciIsCardPresent,
+ MciIsReadOnly,
+ MciBuildDevicePath,
+ MciNotifyState,
+ MciSendCommand,
+ MciReceiveResponse,
+ MciReadBlockData,
+ MciWriteBlockData
+};
+
+EFI_STATUS
+PL180MciDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle = NULL;
+
+ MCI_TRACE("PL180MciDxeInitialize()");
+
+ //Publish Component Name, BlockIO protocol interfaces
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiMmcHostProtocolGuid, &gMciHost,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/ArmPkg/Drivers/PL180MciDxe/PL180Mci.h b/ArmPkg/Drivers/PL180MciDxe/PL180Mci.h
new file mode 100644
index 0000000000..2120716554
--- /dev/null
+++ b/ArmPkg/Drivers/PL180MciDxe/PL180Mci.h
@@ -0,0 +1,117 @@
+/** @file
+ Header for the MMC Host Protocol implementation for the ARM PrimeCell PL180.
+
+ Copyright (c) 2011, 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 __PL180_MCI_H
+#define __PL180_MCI_H
+
+#include <Uefi.h>
+
+#include <Protocol/MmcHost.h>
+
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PcdLib.h>
+
+#define PL180_MCI_DXE_VERSION 0x10
+
+#define MCI_SYSCTL FixedPcdGet32(PcdPL180MciBaseAddress)
+
+#define MCI_POWER_CONTROL_REG (MCI_SYSCTL+0x000)
+#define MCI_CLOCK_CONTROL_REG (MCI_SYSCTL+0x004)
+#define MCI_ARGUMENT_REG (MCI_SYSCTL+0x008)
+#define MCI_COMMAND_REG (MCI_SYSCTL+0x00C)
+#define MCI_RESPCMD_REG (MCI_SYSCTL+0x010)
+#define MCI_RESPONSE0_REG (MCI_SYSCTL+0x014)
+#define MCI_RESPONSE1_REG (MCI_SYSCTL+0x018)
+#define MCI_RESPONSE2_REG (MCI_SYSCTL+0x01C)
+#define MCI_RESPONSE3_REG (MCI_SYSCTL+0x020)
+#define MCI_DATA_TIMER_REG (MCI_SYSCTL+0x024)
+#define MCI_DATA_LENGTH_REG (MCI_SYSCTL+0x028)
+#define MCI_DATA_CTL_REG (MCI_SYSCTL+0x02C)
+#define MCI_DATA_COUNTER (MCI_SYSCTL+0x030)
+#define MCI_STATUS_REG (MCI_SYSCTL+0x034)
+#define MCI_CLEAR_STATUS_REG (MCI_SYSCTL+0x038)
+#define MCI_INT0_MASK_REG (MCI_SYSCTL+0x03C)
+#define MCI_INT1_MASK_REG (MCI_SYSCTL+0x040)
+#define MCI_FIFOCOUNT_REG (MCI_SYSCTL+0x048)
+#define MCI_FIFO_REG (MCI_SYSCTL+0x080)
+
+#define MCI_POWER_UP 0x2
+#define MCI_POWER_ON 0x3
+#define MCI_POWER_OPENDRAIN (1 << 6)
+#define MCI_POWER_ROD (1 << 7)
+
+#define MCI_CLOCK_ENABLE 0x100
+#define MCI_CLOCK_POWERSAVE 0x200
+#define MCI_CLOCK_BYPASS 0x400
+
+#define MCI_STATUS_CMD_CMDCRCFAIL 0x1
+#define MCI_STATUS_CMD_DATACRCFAIL 0x2
+#define MCI_STATUS_CMD_CMDTIMEOUT 0x4
+#define MCI_STATUS_CMD_DATATIMEOUT 0x8
+#define MCI_STATUS_CMD_RXOVERRUN 0x20
+#define MCI_STATUS_CMD_RESPEND 0x40
+#define MCI_STATUS_CMD_SENT 0x80
+#define MCI_STATUS_CMD_TXDONE (MCI_STATUS_CMD_DATAEND | MCI_STATUS_CMD_DATABLOCKEND)
+#define MCI_STATUS_CMD_DATAEND 0x000100 // Command Status - Data end
+#define MCI_STATUS_CMD_DATABLOCKEND 0x000400 // Command Status - Data end
+#define MCI_STATUS_CMD_ACTIVE 0x800
+#define MCI_STATUS_CMD_RXACTIVE (1 << 13)
+#define MCI_STATUS_CMD_RXFIFOHALFFULL 0x008000
+#define MCI_STATUS_CMD_RXFIFOEMPTY 0x080000
+#define MCI_STATUS_CMD_RXDATAAVAILBL (1 << 21)
+#define MCI_STATUS_CMD_TXACTIVE (1 << 12)
+#define MCI_STATUS_CMD_TXFIFOFULL (1 << 16)
+#define MCI_STATUS_CMD_TXFIFOHALFEMPTY (1 << 14)
+#define MCI_STATUS_CMD_TXFIFOEMPTY (1 << 18)
+#define MCI_STATUS_CMD_TXDATAAVAILBL (1 << 20)
+
+#define MCI_DATACTL_ENABLE 1
+#define MCI_DATACTL_CONT_TO_CARD 0
+#define MCI_DATACTL_CARD_TO_CONT 2
+#define MCI_DATACTL_BLOCK_TRANS 0
+#define MCI_DATACTL_STREAM_TRANS 4
+#define MCI_DATACTL_DMA_ENABLE 8
+
+#define INDX(CMD_INDX) ((CMD_INDX & 0x3F) | MCI_CPSM_ENABLED)
+
+#define MCI_CPSM_ENABLED (1 << 10)
+#define MCI_CPSM_WAIT_RESPONSE (1 << 6)
+#define MCI_CPSM_LONG_RESPONSE (1 << 7)
+
+#define MCI_TRACE(txt) DEBUG((EFI_D_BLKIO, "ARM_MCI: " txt "\n"))
+
+EFI_STATUS
+EFIAPI
+MciGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+MciGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+#endif
diff --git a/ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf b/ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf
new file mode 100644
index 0000000000..7ce555bd1d
--- /dev/null
+++ b/ArmPkg/Drivers/PL180MciDxe/PL180MciDxe.inf
@@ -0,0 +1,51 @@
+#/** @file
+# INF file for the MMC Host Protocol implementation for the ARM PrimeCell PL180.
+#
+# Copyright (c) 2011, 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.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL180MciDxe
+ FILE_GUID = 09831032-6fa3-4484-af4f-0a000a8d3a82
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PL180MciDxeInitialize
+
+[Sources.common]
+ PL180Mci.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ ArmLib
+ IoLib
+ TimerLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiMmcHostProtocolGuid
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdPL180SysMciRegAddress
+ gArmTokenSpaceGuid.PcdPL180MciBaseAddress
+
+[Depex]
+ TRUE
diff --git a/ArmPkg/Drivers/PL301Axi/PL301Axi.c b/ArmPkg/Drivers/PL301Axi/PL301Axi.c
new file mode 100644
index 0000000000..7241f5cef2
--- /dev/null
+++ b/ArmPkg/Drivers/PL301Axi/PL301Axi.c
@@ -0,0 +1,108 @@
+/** @file
+*
+* Copyright (c) 2011, 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 <Library/IoLib.h>
+#include <Library/DebugLib.h>
+
+#define PL301_QOS_TIDEMARK_MI_0 0x400
+#define PL301_QOS_ACCESSCONTROL_MI_0 0x404
+
+#define PL301_QOS_TIDEMARK_MI_1 0x420
+#define PL301_QOS_ACCESSCONTROL_MI_1 0x424
+
+#define PL301_QOS_TIDEMARK_MI_2 0x440
+#define PL301_QOS_ACCESSCONTROL_MI_2 0x444
+
+#define PL301_AR_ARB_MI_0 0x408
+#define PL301_AW_ARB_MI_0 0x40C
+
+#define PL301_AR_ARB_MI_1 0x428
+#define PL301_AW_ARB_MI_1 0x42C
+
+#define PL301_AR_ARB_MI_2 0x448
+#define PL301_AW_ARB_MI_2 0x44C
+
+#define PL301_MI_1_OFFSET 0x20
+#define PL301_MI_2_OFFSET 0x40
+#define PL301_MI_3_OFFSET 0x60
+#define PL301_MI_4_OFFSET 0x80
+#define PL301_MI_5_OFFSET 0xa0
+
+#define V2P_CA9_FAXI_MI0_TIDEMARK_VAL 0x6
+#define V2P_CA9_FAXI_MI0_ACCESSCNTRL_VAL 0x1
+
+#define V2P_CA9_FAXI_MI1_TIDEMARK_VAL 0x6
+#define V2P_CA9_FAXI_MI1_ACCESSCNTRL_VAL 0x1
+
+#define V2P_CA9_FAXI_MI2_TIDEMARK_VAL 0x6
+#define V2P_CA9_FAXI_MI2_ACCESSCNTRL_VAL 0x1
+
+
+#define FAxiWriteReg(reg,val) MmioWrite32(FAxiBase + reg, val)
+#define FAxiReadReg(reg) MmioRead32(FAxiBase + reg)
+
+// IN FAxiBase
+// Initialize PL301 Dynamic Memory Controller
+VOID PL301AxiInit(UINTN FAxiBase) {
+ // Configure Tidemark Register for Master Port 0 (MI 0)
+ FAxiWriteReg(PL301_QOS_TIDEMARK_MI_0, V2P_CA9_FAXI_MI0_TIDEMARK_VAL);
+
+ // Configure the Access Control Register (MI 0)
+ FAxiWriteReg(PL301_QOS_ACCESSCONTROL_MI_0, V2P_CA9_FAXI_MI0_ACCESSCNTRL_VAL);
+
+ // MP0
+ // Set priority for Read
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x00000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x01000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x02000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x03000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x04000200);
+
+ // Set priority for Write
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x00000100);
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x01000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x02000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x03000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x04000200);
+
+ // MP1
+ // Set priority for Read
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x00000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x01000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x02000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x03000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x04000200);
+
+ // Set priority for Write
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x00000100);
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x01000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x02000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x03000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x04000200);
+
+ // MP2
+ // Set priority for Read
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x00000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x01000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x02000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x03000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x04000100);
+
+ // Set priority for Write
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x00000100);
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x01000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x02000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x03000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x04000200);
+}
diff --git a/ArmPkg/Drivers/PL301Axi/PL301Axi.inf b/ArmPkg/Drivers/PL301Axi/PL301Axi.inf
new file mode 100644
index 0000000000..2358124887
--- /dev/null
+++ b/ArmPkg/Drivers/PL301Axi/PL301Axi.inf
@@ -0,0 +1,29 @@
+#/* @file
+# Copyright (c) 2011, 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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL301AxiSec
+ FILE_GUID = 2ea84160-aba0-11df-9896-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL301AxiLib
+
+[Sources]
+ PL301Axi.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
diff --git a/ArmPkg/Drivers/PL310L2Cache/PL310L2Cache.c b/ArmPkg/Drivers/PL310L2Cache/PL310L2Cache.c
new file mode 100644
index 0000000000..6cc6cc6193
--- /dev/null
+++ b/ArmPkg/Drivers/PL310L2Cache/PL310L2Cache.c
@@ -0,0 +1,130 @@
+/** @file
+*
+* Copyright (c) 2011, 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 <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ArmLib.h>
+#include <Library/L2X0CacheLib.h>
+#include <Library/PcdLib.h>
+
+#define L2x0WriteReg(reg,val) MmioWrite32(PcdGet32(PcdL2x0ControllerBase) + reg, val)
+#define L2x0ReadReg(reg) MmioRead32(PcdGet32(PcdL2x0ControllerBase) + reg)
+
+// Initialize PL320 L2 Cache Controller
+VOID L2x0CacheInit(UINTN L2x0Base, BOOLEAN CacheEnabled) {
+ UINT32 Data;
+ UINT32 Revision;
+ UINT32 Aux;
+ UINT32 PfCtl;
+ UINT32 PwrCtl;
+
+ // Check if L2x0 is present and is an ARM implementation
+ Data = L2x0ReadReg(L2X0_CACHEID);
+ if ((Data >> 24) != L2X0_CACHEID_IMPLEMENTER_ARM) {
+ ASSERT(0);
+ return;
+ }
+
+ // Check if L2x0 is PL310
+ if (((Data >> 6) & 0xF) != L2X0_CACHEID_PARTNUM_PL310) {
+ ASSERT(0);
+ return;
+ }
+
+ // RTL release
+ Revision = Data & 0x3F;
+
+ // Check if L2x0 is already enabled then we disable it
+ Data = L2x0ReadReg(L2X0_CTRL);
+ if (Data & L2X0_CTRL_ENABLED) {
+ L2x0WriteReg(L2X0_CTRL, L2X0_CTRL_DISABLED);
+ }
+
+ //
+ // Set up global configurations
+ //
+
+ // Auxiliary register: Non-secure interrupt access Control + Event monitor bus enable + SBO
+ Aux = L2X0_AUXCTRL_NSAC | L2X0_AUXCTRL_EM | L2X0_AUXCTRL_SBO;
+ // Use AWCACHE attributes for WA
+ Aux |= L2x0_AUXCTRL_AW_AWCACHE;
+ // Use default Size
+ Data = L2x0ReadReg(L2X0_AUXCTRL);
+ Aux |= Data & (0x7 << 17);
+ // Use default associativity
+ Aux |= Data & (0x1 << 16);
+ // Enabled I & D Prefetch
+ Aux |= L2x0_AUXCTRL_IPREFETCH | L2x0_AUXCTRL_DPREFETCH;
+
+ if (Revision >= 5) {
+ // Prefetch Offset Register
+ PfCtl = L2x0ReadReg(L2X0_PFCTRL);
+ // - Prefetch increment set to 0
+ // - Prefetch dropping off
+ // - Double linefills off
+ L2x0WriteReg(L2X0_PFCTRL, PfCtl);
+
+ // Power Control Register - L2X0_PWRCTRL
+ PwrCtl = L2x0ReadReg(L2X0_PWRCTRL);
+ // - Standby when idle off
+ // - Dynamic clock gating off
+ // - Nc,NC-shared dropping off
+ L2x0WriteReg(L2X0_PWRCTRL, PwrCtl);
+ }
+
+ if (Revision >= 4) {
+ // Tag RAM Latency register
+ // - Use default latency
+
+ // Data RAM Latency Control register
+ // - Use default latency
+ } else if (Revision >= 2) {
+ L2x0WriteReg(L230_TAG_LATENCY,
+ (L2_TAG_ACCESS_LATENCY << 8)
+ | (L2_TAG_ACCESS_LATENCY << 4)
+ | L2_TAG_SETUP_LATENCY
+ );
+
+ L2x0WriteReg(L230_DATA_LATENCY,
+ (L2_DATA_ACCESS_LATENCY << 8)
+ | (L2_DATA_ACCESS_LATENCY << 4)
+ | L2_DATA_SETUP_LATENCY
+ );
+ } else {
+ Aux |= (L2_TAG_ACCESS_LATENCY << 6)
+ | (L2_DATA_ACCESS_LATENCY << 3)
+ | L2_DATA_ACCESS_LATENCY;
+ }
+
+ // Write Auxiliary value
+ L2x0WriteReg(L2X0_AUXCTRL, Aux);
+
+ //
+ // Invalidate all entries in cache
+ //
+ L2x0WriteReg(L2X0_INVWAY, 0xffff);
+ // Poll cache maintenance register until invalidate operation is complete
+ while(L2x0ReadReg(L2X0_INVWAY) & 0xffff);
+
+ // Write to the Lockdown D and Lockdown I Register 9 if required
+ // - Not required
+
+ // Clear any residual raw interrupts
+ L2x0WriteReg(L2X0_INTCLEAR, 0x1FF);
+
+ // Enable the cache
+ if (CacheEnabled) {
+ L2x0WriteReg(L2X0_CTRL, L2X0_CTRL_ENABLED);
+ }
+}
diff --git a/ArmPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf b/ArmPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf
new file mode 100644
index 0000000000..73c9689ee5
--- /dev/null
+++ b/ArmPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf
@@ -0,0 +1,30 @@
+#/* @file
+# Copyright (c) 2011, 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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL310L2Cache
+ FILE_GUID = 16ad4fe0-b5b1-11df-8cbf-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = L2X0CacheLib
+
+[Sources]
+ PL310L2Cache.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdL2x0ControllerBase
diff --git a/ArmPkg/Drivers/PL34xDmc/PL341Dmc.c b/ArmPkg/Drivers/PL34xDmc/PL341Dmc.c
new file mode 100644
index 0000000000..9c62a1a92b
--- /dev/null
+++ b/ArmPkg/Drivers/PL34xDmc/PL341Dmc.c
@@ -0,0 +1,373 @@
+/** @file
+*
+* Copyright (c) 2011, 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 <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Drivers/PL341Dmc.h>
+
+//
+// DMC Configuration Register Map
+//
+#define DMC_STATUS_REG 0x00
+#define DMC_COMMAND_REG 0x04
+#define DMC_DIRECT_CMD_REG 0x08
+#define DMC_MEMORY_CONFIG_REG 0x0C
+#define DMC_REFRESH_PRD_REG 0x10
+#define DMC_CAS_LATENCY_REG 0x14
+#define DMC_WRITE_LATENCY_REG 0x18
+#define DMC_T_MRD_REG 0x1C
+#define DMC_T_RAS_REG 0x20
+#define DMC_T_RC_REG 0x24
+#define DMC_T_RCD_REG 0x28
+#define DMC_T_RFC_REG 0x2C
+#define DMC_T_RP_REG 0x30
+#define DMC_T_RRD_REG 0x34
+#define DMC_T_WR_REG 0x38
+#define DMC_T_WTR_REG 0x3C
+#define DMC_T_XP_REG 0x40
+#define DMC_T_XSR_REG 0x44
+#define DMC_T_ESR_REG 0x48
+#define DMC_MEMORY_CFG2_REG 0x4C
+#define DMC_MEMORY_CFG3_REG 0x50
+#define DMC_T_FAW_REG 0x54
+
+// Returns the state of the memory controller:
+#define DMC_STATUS_CONFIG 0x0
+#define DMC_STATUS_READY 0x1
+#define DMC_STATUS_PAUSED 0x2
+#define DMC_STATUS_LOWPOWER 0x3
+
+// Changes the state of the memory controller:
+#define DMC_COMMAND_GO 0x0
+#define DMC_COMMAND_SLEEP 0x1
+#define DMC_COMMAND_WAKEUP 0x2
+#define DMC_COMMAND_PAUSE 0x3
+#define DMC_COMMAND_CONFIGURE 0x4
+#define DMC_COMMAND_ACTIVEPAUSE 0x7
+
+// Determines the command required
+#define DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL 0x0
+#define DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH (0x1 << 18)
+#define DMC_DIRECT_CMD_MEMCMD_MODEREG (0x2 << 18)
+#define DMC_DIRECT_CMD_MEMCMD_EXTMODEREG (0x2 << 18)
+#define DMC_DIRECT_CMD_MEMCMD_NOP (0x3 << 18)
+#define DMC_DIRECT_CMD_MEMCMD_DPD (0x1 << 22)
+#define DMC_DIRECT_CMD_BANKADDR(n) ((n & 0x3) << 16)
+#define DMC_DIRECT_CMD_CHIP_ADDR(n) ((n & 0x3) << 20)
+
+
+//
+// AXI ID configuration register map
+//
+#define DMC_ID_0_CFG_REG 0x100
+#define DMC_ID_1_CFG_REG 0x104
+#define DMC_ID_2_CFG_REG 0x108
+#define DMC_ID_3_CFG_REG 0x10C
+#define DMC_ID_4_CFG_REG 0x110
+#define DMC_ID_5_CFG_REG 0x114
+#define DMC_ID_6_CFG_REG 0x118
+#define DMC_ID_7_CFG_REG 0x11C
+#define DMC_ID_8_CFG_REG 0x120
+#define DMC_ID_9_CFG_REG 0x124
+#define DMC_ID_10_CFG_REG 0x128
+#define DMC_ID_11_CFG_REG 0x12C
+#define DMC_ID_12_CFG_REG 0x130
+#define DMC_ID_13_CFG_REG 0x134
+#define DMC_ID_14_CFG_REG 0x138
+#define DMC_ID_15_CFG_REG 0x13C
+
+// Set the QoS
+#define DMC_ID_CFG_QOS_DISABLE 0
+#define DMC_ID_CFG_QOS_ENABLE 1
+#define DMC_ID_CFG_QOS_MIN 2
+
+
+//
+// Chip configuration register map
+//
+#define DMC_CHIP_0_CFG_REG 0x200
+#define DMC_CHIP_1_CFG_REG 0x204
+#define DMC_CHIP_2_CFG_REG 0x208
+#define DMC_CHIP_3_CFG_REG 0x20C
+
+//
+// User Defined Pins
+//
+#define DMC_USER_STATUS_REG 0x300
+#define DMC_USER_0_CFG_REG 0x304
+#define DMC_USER_1_CFG_REG 0x308
+#define DMC_FEATURE_CRTL_REG 0x30C
+#define DMC_USER_2_CFG_REG 0x310
+
+
+//
+// PHY Register Settings
+//
+#define TC_UIOLHNC_MASK 0x000003C0
+#define TC_UIOLHNC_SHIFT 0x6
+#define TC_UIOLHPC_MASK 0x0000003F
+#define TC_UIOLHPC_SHIFT 0x2
+#define TC_UIOHOCT_MASK 0x2
+#define TC_UIOHOCT_SHIFT 0x1
+#define TC_UIOHSTOP_SHIFT 0x0
+#define TC_UIOLHXC_VALUE 0x4
+
+//
+// Extended Mode Register settings
+//
+#define DDR_EMR_OCD_MASK 0x0000380
+#define DDR_EMR_OCD_SHIFT 0x7
+#define DDR_EMR_RTT_MASK 0x00000044 // DDR2 Device RTT (ODT) settings
+#define DDR_EMR_RTT_SHIFT 0x2
+#define DDR_EMR_ODS_MASK 0x00000002 // DDR2 Output Drive Strength
+#define DDR_EMR_ODS_SHIFT 0x0001
+// Termination Values:
+#define DDR_EMR_RTT_50 0x00000044 // DDR2 50 Ohm termination
+#define DDR_EMR_RTT_75R 0x00000004 // DDR2 75 Ohm termination
+#define DDR_EMR_RTT_150 0x00000040 // DDR2 150 Ohm termination
+// Output Drive Strength Values:
+#define DDR_EMR_ODS_FULL 0x0 // DDR2 Full Drive Strength
+#define DDR_EMR_ODS_HALF 0x1 // DDR2 Half Drive Strength
+// OCD values
+#define DDR_EMR_OCD_DEFAULT 0x7
+#define DDR_EMR_OCD_NS 0x0
+
+#define DDR_EMR_ODS_VAL DDR_EMR_ODS_FULL
+
+
+
+#define DmcWriteReg(reg,val) MmioWrite32(DmcBase + reg, val)
+#define DmcReadReg(reg) MmioRead32(DmcBase + reg)
+
+// Initialize PL341 Dynamic Memory Controller
+VOID PL341DmcInit(struct pl341_dmc_config *config) {
+ UINTN DmcBase = config->base;
+ UINT32 i, chip, val32;
+
+ // Set config mode
+ DmcWriteReg(DMC_COMMAND_REG, DMC_COMMAND_CONFIGURE);
+
+ //
+ // Setup the QoS AXI ID bits
+ //
+
+ if (config->has_qos) {
+ // CLCD AXIID = 000
+ DmcWriteReg(DMC_ID_0_CFG_REG, DMC_ID_CFG_QOS_ENABLE | DMC_ID_CFG_QOS_MIN);
+
+ // Default disable QoS
+ DmcWriteReg(DMC_ID_1_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_2_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_3_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_4_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_5_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_6_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_7_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_8_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_9_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_10_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_11_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_12_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_13_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_14_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_15_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ }
+
+ //
+ // Initialise memory controlller
+ //
+ DmcWriteReg(DMC_REFRESH_PRD_REG, config->refresh_prd);
+ DmcWriteReg(DMC_CAS_LATENCY_REG, config->cas_latency);
+ DmcWriteReg(DMC_WRITE_LATENCY_REG, config->write_latency);
+ DmcWriteReg(DMC_T_MRD_REG, config->t_mrd);
+ DmcWriteReg(DMC_T_RAS_REG, config->t_ras);
+ DmcWriteReg(DMC_T_RC_REG, config->t_rc);
+ DmcWriteReg(DMC_T_RCD_REG, config->t_rcd);
+ DmcWriteReg(DMC_T_RFC_REG, config->t_rfc);
+ DmcWriteReg(DMC_T_RP_REG, config->t_rp);
+ DmcWriteReg(DMC_T_RRD_REG, config->t_rrd);
+ DmcWriteReg(DMC_T_WR_REG, config->t_wr);
+ DmcWriteReg(DMC_T_WTR_REG, config->t_wtr);
+ DmcWriteReg(DMC_T_XP_REG, config->t_xp);
+ DmcWriteReg(DMC_T_XSR_REG, config->t_xsr);
+ DmcWriteReg(DMC_T_ESR_REG, config->t_esr);
+ DmcWriteReg(DMC_T_FAW_REG, config->t_faw);
+
+ // =======================================================================
+ // Initialise PL341 Mem Config Registers
+ // =======================================================================
+
+ // |======================================
+ // | Set PL341 Memory Config
+ // |======================================
+ DmcWriteReg(DMC_MEMORY_CONFIG_REG, config->memory_cfg);
+
+ // |======================================
+ // | Set PL341 Memory Config 2
+ // |======================================
+ DmcWriteReg(DMC_MEMORY_CFG2_REG, config->memory_cfg2);
+
+ // |======================================
+ // | Set PL341 Chip Select <n>
+ // |======================================
+ DmcWriteReg(DMC_CHIP_0_CFG_REG, config->chip_cfg0);
+ DmcWriteReg(DMC_CHIP_1_CFG_REG, config->chip_cfg1);
+ DmcWriteReg(DMC_CHIP_2_CFG_REG, config->chip_cfg2);
+ DmcWriteReg(DMC_CHIP_3_CFG_REG, config->chip_cfg3);
+
+ // |======================================
+ // | Set PL341 Memory Config 3
+ // |======================================
+ DmcWriteReg(DMC_MEMORY_CFG3_REG, config->memory_cfg3);
+
+ // |========================================================
+ // |Set Test Chip PHY Registers via PL341 User Config Reg
+ // |Note that user_cfgX registers are Write Only
+ // |
+ // |DLL Freq set = 250MHz - 266MHz
+ // |========================================================
+ DmcWriteReg(DMC_USER_0_CFG_REG, 0x7C924924);
+
+ // user_config2
+ // ------------
+ // Set defaults before calibrating the DDR2 buffer impendence
+ // -Disable ODT
+ // -Default drive strengths
+ DmcWriteReg(DMC_USER_2_CFG_REG, 0x40000198);
+
+ // |=======================================================
+ // |Auto calibrate the DDR2 buffers impendence
+ // |=======================================================
+ val32 = DmcReadReg(DMC_USER_STATUS_REG);
+ while (!(val32 & 0x100)) {
+ val32 = DmcReadReg(DMC_USER_STATUS_REG);
+ }
+
+ // Set the output driven strength
+ DmcWriteReg(DMC_USER_2_CFG_REG, 0x40800000 |
+ (TC_UIOLHXC_VALUE << TC_UIOLHNC_SHIFT) |
+ (TC_UIOLHXC_VALUE << TC_UIOLHPC_SHIFT) |
+ (0x1 << TC_UIOHOCT_SHIFT) |
+ (0x1 << TC_UIOHSTOP_SHIFT));
+
+ // |======================================
+ // | Set PL341 Feature Control Register
+ // |======================================
+ // | Disable early BRESP - use to optimise CLCD performance
+ DmcWriteReg(DMC_FEATURE_CRTL_REG, 0x00000001);
+
+ //=================
+ // Config memories
+ //=================
+
+ for (chip = 0; chip <= config-> max_chip; chip++) {
+ // send nop
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_NOP);
+ // pre-charge all
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL);
+
+ // delay
+ for (i = 0; i < 10; i++) {
+ val32 = DmcReadReg(DMC_STATUS_REG);
+ }
+
+ // set (EMR2) extended mode register 2
+ DmcWriteReg(DMC_DIRECT_CMD_REG,
+ DMC_DIRECT_CMD_CHIP_ADDR(chip) |
+ DMC_DIRECT_CMD_BANKADDR(2) |
+ DMC_DIRECT_CMD_MEMCMD_EXTMODEREG);
+ // set (EMR3) extended mode register 3
+ DmcWriteReg(DMC_DIRECT_CMD_REG,
+ DMC_DIRECT_CMD_CHIP_ADDR(chip) |
+ DMC_DIRECT_CMD_BANKADDR(3) |
+ DMC_DIRECT_CMD_MEMCMD_EXTMODEREG);
+
+ // =================================
+ // set (EMR) Extended Mode Register
+ // ==================================
+ // Put into OCD default state
+ DmcWriteReg(DMC_DIRECT_CMD_REG,
+ DMC_DIRECT_CMD_CHIP_ADDR(chip) |
+ DMC_DIRECT_CMD_BANKADDR(1) |
+ DMC_DIRECT_CMD_MEMCMD_EXTMODEREG);
+
+ // ===========================================================
+ // set (MR) mode register - With DLL reset
+ // ===========================================================
+ // Burst Length = 4 (010)
+ // Burst Type = Seq (0)
+ // Latency = 4 (100)
+ // Test mode = Off (0)
+ // DLL reset = Yes (1)
+ // Wr Recovery = 4 (011)
+ // PD = Normal (0)
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00080742);
+
+ // pre-charge all
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL);
+ // auto-refresh
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH);
+ // auto-refresh
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH);
+
+ // delay
+ for (i = 0; i < 10; i++) {
+ val32 = DmcReadReg(DMC_STATUS_REG);
+ }
+
+ // ===========================================================
+ // set (MR) mode register - Without DLL reset
+ // ===========================================================
+ // auto-refresh
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH);
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00080642);
+
+ // delay
+ for (i = 0; i < 10; i++) {
+ val32 = DmcReadReg(DMC_STATUS_REG);
+ }
+
+ // ======================================================
+ // set (EMR) extended mode register - Enable OCD defaults
+ // ======================================================
+ val32 = 0; //NOP
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00090000 |
+ (DDR_EMR_OCD_DEFAULT << DDR_EMR_OCD_SHIFT) |
+ DDR_EMR_RTT_75R |
+ (DDR_EMR_ODS_VAL << DDR_EMR_ODS_MASK));
+
+ // delay
+ for (i = 0; i < 10; i++) {
+ val32 = DmcReadReg(DMC_STATUS_REG);
+ }
+
+ // Set (EMR) extended mode register - OCD Exit
+ val32 = 0; //NOP
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00090000 |
+ (DDR_EMR_OCD_NS << DDR_EMR_OCD_SHIFT) |
+ DDR_EMR_RTT_75R |
+ (DDR_EMR_ODS_VAL << DDR_EMR_ODS_MASK));
+
+ }
+
+ //----------------------------------------
+ // go command
+ DmcWriteReg(DMC_COMMAND_REG, DMC_COMMAND_GO);
+
+ // wait for ready
+ val32 = DmcReadReg(DMC_STATUS_REG);
+ while (!(val32 & DMC_STATUS_READY)) {
+ val32 = DmcReadReg(DMC_STATUS_REG);
+ }
+}
diff --git a/ArmPkg/Drivers/PL34xDmc/PL341Dmc.inf b/ArmPkg/Drivers/PL34xDmc/PL341Dmc.inf
new file mode 100644
index 0000000000..1000058713
--- /dev/null
+++ b/ArmPkg/Drivers/PL34xDmc/PL341Dmc.inf
@@ -0,0 +1,29 @@
+#/* @file
+# Copyright (c) 2011, 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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL341Dmc
+ FILE_GUID = edf8da40-aad1-11df-a1f4-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL341DmcLib
+
+[Sources]
+ PL341Dmc.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
diff --git a/ArmPkg/Drivers/PL35xSmc/InitializeSMC.S b/ArmPkg/Drivers/PL35xSmc/InitializeSMC.S
new file mode 100644
index 0000000000..b3b597a50c
--- /dev/null
+++ b/ArmPkg/Drivers/PL35xSmc/InitializeSMC.S
@@ -0,0 +1,189 @@
+#
+# Copyright (c) 2011, 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 <AsmMacroIoLib.h>
+#include <Library/PcdLib.h>
+#include <AutoGen.h>
+#include <AsmMacroIoLib.h>
+
+#Start of the code section
+.text
+
+#Maintain 8 byte alignment
+.align 3
+
+#Export Initialize SMC symbol
+GCC_ASM_EXPORT(InitializeSMC)
+
+# Static memory configuation definitions for SMC
+.set SmcDirectCmd, 0x10
+.set SmcSetCycles, 0x14
+.set SmcSetOpMode, 0x18
+
+# CS0 CS0-Interf0 NOR1 flash on the motherboard
+# CS1 CS1-Interf0 Reserved for the motherboard
+# CS2 CS2-Interf0 SRAM on the motherboard
+# CS3 CS3-Interf0 memory-mapped Ethernet and USB controllers on the motherboard
+# CS4 CS0-Interf1 NOR2 flash on the motherboard
+# CS5 CS1-Interf1 memory-mapped peripherals
+# CS6 CS2-Interf1 memory-mapped peripherals
+# CS7 CS3-Interf1 system memory-mapped peripherals on the motherboard.
+
+# IN r1 SmcBase
+# IN r2 VideoSRamBase
+# NOTE: This code is been called before any stack has been setup. It means some registers
+# could be overwritten (case of 'r0')
+
+
+ASM_PFX(InitializeSMC):
+#
+# Setup NOR1 (CS0-Interface0)
+#
+
+ #Write to set_cycle register(holding register for NOR 1 cycle register or NAND cycle register)
+ #Read cycle timeout = 0xA (0:3)
+ #Write cycle timeout = 0x3(7:4)
+ #OE Assertion Delay = 0x9(11:8)
+ #WE Assertion delay = 0x3(15:12)
+ #Page cycle timeout = 0x2(19:16)
+ LoadConstantToReg (0x0002393A,r0) @ldr r0, = 0x0002393A
+ str r0, [r1, #SmcSetCycles]
+
+ #Write to set_opmode register(holding register for NOR 1 opomode register or NAND opmode register)
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000028 = ReadMemoryBurstLength:continuous
+ # 0x00000280 = WriteMemoryBurstLength:continuous
+ # 0x00000800 = Set Address Valid
+ LoadConstantToReg (0x00000AAA,r0) @ldr r0, = 0x00000AAA
+ str r0, [r1, #SmcSetOpMode]
+
+ #Write to direct_cmd register so that the NOR 1 registers(set-cycles and opmode) are updated with holding registers
+ # 0x00000000 = ChipSelect0-Interface 0
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x00400000,r0) @ldr r0, = 0x00400000
+ str r0, [r1, #SmcDirectCmd]
+
+
+#
+# Setup SRAM (CS2-Interface0)
+#
+ LoadConstantToReg (0x00027158,r0) @ldr r0, = 0x00027158
+ str r0, [r1, #SmcSetCycles]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000800 = Set Address Valid
+ LoadConstantToReg (0x00000802,r0) @ldr r0, = 0x00000802
+ str r0, [r1, #SmcSetOpMode]
+
+ # 0x01000000 = ChipSelect2-Interface 0
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x01400000,r0) @ldr r0, = 0x01400000
+ str r0, [r1, #SmcDirectCmd]
+
+#
+# USB/Eth/VRAM (CS3-Interface0)
+#
+ LoadConstantToReg (0x000CD2AA,r0) @ldr r0, = 0x000CD2AA
+ str r0, [r1, #SmcSetCycles]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000004 = Memory reads are synchronous
+ # 0x00000040 = Memory writes are synchronous
+ LoadConstantToReg (0x00000046,r0) @ldr r0, = 0x00000046
+ str r0, [r1, #SmcSetOpMode]
+
+ # 0x01800000 = ChipSelect3-Interface 0
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x01C00000,r0) @ldr r0, = 0x01C00000
+ str r0, [r1, #SmcDirectCmd]
+
+#
+# Setup NOR3 (CS0-Interface1)
+#
+ LoadConstantToReg (0x0002393A,r0) @ldr r0, = 0x0002393A
+ str r0, [r1, #SmcSetCycles]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000028 = ReadMemoryBurstLength:continuous
+ # 0x00000280 = WriteMemoryBurstLength:continuous
+ # 0x00000800 = Set Address Valid
+ LoadConstantToReg (0x00000AAA,r0) @ldr r0, = 0x00000AAA
+ str r0, [r1, #SmcSetOpMode]
+
+ # 0x02000000 = ChipSelect0-Interface 1
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x02400000,r0) @ldr r0, = 0x02400000
+ str r0, [r1, #SmcDirectCmd]
+
+#
+# Setup Peripherals (CS3-Interface1)
+#
+ LoadConstantToReg (0x00025156,r0) @ldr r0, = 0x00025156
+ str r0, [r1, #SmcSetCycles]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000004 = Memory reads are synchronous
+ # 0x00000040 = Memory writes are synchronous
+ LoadConstantToReg (0x00000046,r0) @ldr r0, = 0x00000046
+ str r0, [r1, #SmcSetOpMode]
+
+ # 0x03800000 = ChipSelect3-Interface 1
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x03C00000,r0) @ldr r0, = 0x03C00000
+ str r0, [r1, #SmcDirectCmd]
+
+#
+# Setup VRAM (CS1-Interface0)
+#
+ LoadConstantToReg (0x00049249,r0) @ldr r0, = 0x00049249
+ str r0, [r1, #SmcSetCycles]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000004 = Memory reads are synchronous
+ # 0x00000040 = Memory writes are synchronous
+ LoadConstantToReg (0x00000046,r0) @ldr r0, = 0x00000046
+ str r0, [r1, #SmcSetOpMode]
+
+ # 0x00800000 = ChipSelect1-Interface 0
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x00C00000,r0) @ldr r0, = 0x00C00000
+ str r0, [r1, #SmcDirectCmd]
+
+#
+# Page mode setup for VRAM
+#
+ #read current state
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ LoadConstantToReg (0x00000000,r0) @ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, [r2, #0]
+
+ #enable page mode
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ LoadConstantToReg (0x00000000,r0) @ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ LoadConstantToReg (0x00900090,r0) @ldr r0, = 0x00900090
+ str r0, [r2, #0]
+
+ #confirm page mode enabled
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ LoadConstantToReg (0x00000000,r0) @ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, [r2, #0]
+
+ bx lr
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED \ No newline at end of file
diff --git a/ArmPkg/Drivers/PL35xSmc/InitializeSMC.asm b/ArmPkg/Drivers/PL35xSmc/InitializeSMC.asm
new file mode 100644
index 0000000000..ebf6a7980e
--- /dev/null
+++ b/ArmPkg/Drivers/PL35xSmc/InitializeSMC.asm
@@ -0,0 +1,183 @@
+//
+// Copyright (c) 2011, 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 <AsmMacroIoLib.h>
+#include <Library/PcdLib.h>
+#include <AutoGen.h>
+
+ INCLUDE AsmMacroIoLib.inc
+
+ EXPORT InitializeSMC
+
+ PRESERVE8
+ AREA ModuleInitializeSMC, CODE, READONLY
+
+// Static memory configuation definitions for SMC
+SmcDirectCmd EQU 0x10
+SmcSetCycles EQU 0x14
+SmcSetOpMode EQU 0x18
+
+// CS0 CS0-Interf0 NOR1 flash on the motherboard
+// CS1 CS1-Interf0 Reserved for the motherboard
+// CS2 CS2-Interf0 SRAM on the motherboard
+// CS3 CS3-Interf0 memory-mapped Ethernet and USB controllers on the motherboard
+// CS4 CS0-Interf1 NOR2 flash on the motherboard
+// CS5 CS1-Interf1 memory-mapped peripherals
+// CS6 CS2-Interf1 memory-mapped peripherals
+// CS7 CS3-Interf1 system memory-mapped peripherals on the motherboard.
+
+// IN r1 SmcBase
+// IN r2 VideoSRamBase
+// NOTE: This code is been called before any stack has been setup. It means some registers
+// could be overwritten (case of 'r0')
+InitializeSMC
+//
+// Setup NOR1 (CS0-Interface0)
+//
+
+ //Write to set_cycle register(holding register for NOR 1 cycle register or NAND cycle register)
+ //Read cycle timeout = 0xA (0:3)
+ //Write cycle timeout = 0x3(7:4)
+ //OE Assertion Delay = 0x9(11:8)
+ //WE Assertion delay = 0x3(15:12)
+ //Page cycle timeout = 0x2(19:16)
+ ldr r0, = 0x0002393A
+ str r0, [r1, #SmcSetCycles]
+
+ //Write to set_opmode register(holding register for NOR 1 opomode register or NAND opmode register)
+ // 0x00000002 = MemoryWidth: 32bit
+ // 0x00000028 = ReadMemoryBurstLength:continuous
+ // 0x00000280 = WriteMemoryBurstLength:continuous
+ // 0x00000800 = Set Address Valid
+ ldr r0, = 0x00000AAA
+ str r0, [r1, #SmcSetOpMode]
+
+ //Write to direct_cmd register so that the NOR 1 registers(set-cycles and opmode) are updated with holding registers
+ // 0x00000000 = ChipSelect0-Interface 0
+ // 0x00400000 = CmdTypes: UpdateRegs
+ ldr r0, = 0x00400000
+ str r0, [r1, #SmcDirectCmd]
+
+//
+// Setup SRAM (CS2-Interface0)
+//
+ ldr r0, = 0x00027158
+ str r0, [r1, #SmcSetCycles]
+
+ // 0x00000002 = MemoryWidth: 32bit
+ // 0x00000800 = Set Address Valid
+ ldr r0, = 0x00000802
+ str r0, [r1, #SmcSetOpMode]
+
+ // 0x01000000 = ChipSelect2-Interface 0
+ // 0x00400000 = CmdTypes: UpdateRegs
+ ldr r0, = 0x01400000
+ str r0, [r1, #SmcDirectCmd]
+
+//
+// USB/Eth/VRAM (CS3-Interface0)
+//
+ ldr r0, = 0x000CD2AA
+ str r0, [r1, #SmcSetCycles]
+
+ // 0x00000002 = MemoryWidth: 32bit
+ // 0x00000004 = Memory reads are synchronous
+ // 0x00000040 = Memory writes are synchronous
+ ldr r0, = 0x00000046
+ str r0, [r1, #SmcSetOpMode]
+
+ // 0x01800000 = ChipSelect3-Interface 0
+ // 0x00400000 = CmdTypes: UpdateRegs
+ ldr r0, = 0x01C00000
+ str r0, [r1, #SmcDirectCmd]
+
+//
+// Setup NOR3 (CS0-Interface1)
+//
+ ldr r0, = 0x0002393A
+ str r0, [r1, #SmcSetCycles]
+
+ // 0x00000002 = MemoryWidth: 32bit
+ // 0x00000028 = ReadMemoryBurstLength:continuous
+ // 0x00000280 = WriteMemoryBurstLength:continuous
+ // 0x00000800 = Set Address Valid
+ ldr r0, = 0x00000AAA
+ str r0, [r1, #SmcSetOpMode]
+
+ // 0x02000000 = ChipSelect0-Interface 1
+ // 0x00400000 = CmdTypes: UpdateRegs
+ ldr r0, = 0x02400000
+ str r0, [r1, #SmcDirectCmd]
+
+//
+// Setup Peripherals (CS3-Interface1)
+//
+ ldr r0, = 0x00025156
+ str r0, [r1, #SmcSetCycles]
+
+ // 0x00000002 = MemoryWidth: 32bit
+ // 0x00000004 = Memory reads are synchronous
+ // 0x00000040 = Memory writes are synchronous
+ ldr r0, = 0x00000046
+ str r0, [r1, #SmcSetOpMode]
+
+ // 0x03800000 = ChipSelect3-Interface 1
+ // 0x00400000 = CmdTypes: UpdateRegs
+ ldr r0, = 0x03C00000
+ str r0, [r1, #SmcDirectCmd]
+
+//
+// Setup VRAM (CS1-Interface0)
+//
+ ldr r0, = 0x00049249
+ str r0, [r1, #SmcSetCycles]
+
+ // 0x00000002 = MemoryWidth: 32bit
+ // 0x00000004 = Memory reads are synchronous
+ // 0x00000040 = Memory writes are synchronous
+ ldr r0, = 0x00000046
+ str r0, [r1, #SmcSetOpMode]
+
+ // 0x00800000 = ChipSelect1-Interface 0
+ // 0x00400000 = CmdTypes: UpdateRegs
+ ldr r0, = 0x00C00000
+ str r0, [r1, #SmcDirectCmd]
+
+//
+// Page mode setup for VRAM
+//
+ //read current state
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, [r2, #0]
+
+ //enable page mode
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, = 0x00900090
+ str r0, [r2, #0]
+
+ //confirm page mode enabled
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, [r2, #0]
+
+ bx lr
+
+ END
diff --git a/ArmPkg/Drivers/PL35xSmc/PL354SmcSec.inf b/ArmPkg/Drivers/PL35xSmc/PL354SmcSec.inf
new file mode 100644
index 0000000000..188f080ffc
--- /dev/null
+++ b/ArmPkg/Drivers/PL35xSmc/PL354SmcSec.inf
@@ -0,0 +1,30 @@
+#/* @file
+# Copyright (c) 2011, 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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL354SmcSec
+ FILE_GUID = 10952220-aa32-11df-a438-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL354SmcSecLib
+
+[Sources.common]
+ InitializeSMC.asm | RVCT
+ InitializeSMC.S | GCC
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
diff --git a/ArmPkg/Drivers/PL390Gic/PL390GicDxe.c b/ArmPkg/Drivers/PL390Gic/PL390GicDxe.c
new file mode 100644
index 0000000000..da86bbcd84
--- /dev/null
+++ b/ArmPkg/Drivers/PL390Gic/PL390GicDxe.c
@@ -0,0 +1,435 @@
+/*++
+
+Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
+Portions copyright (c) 2010, Apple Inc. 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/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/HardwareInterrupt.h>
+
+#include <Drivers/PL390Gic.h>
+
+// number of 32-bit registers needed to represent those interrupts as a bit
+// (used for enable set, enable clear, pending set, pending clear, and active regs)
+#define GIC_NUM_REG_PER_INT_BITS (PcdGet32(PcdGicNumInterrupts) / 32)
+
+// number of 32-bit registers needed to represent those interrupts as two bits
+// (used for configuration reg)
+#define GIC_NUM_REG_PER_INT_CFG (PcdGet32(PcdGicNumInterrupts) / 16)
+
+// number of 32-bit registers needed to represent interrupts as 8-bit priority field
+// (used for priority regs)
+#define GIC_NUM_REG_PER_INT_BYTES (PcdGet32(PcdGicNumInterrupts) / 4)
+
+#define GIC_DEFAULT_PRIORITY 0x80
+
+extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol;
+
+//
+// Notifications
+//
+VOID *CpuProtocolNotificationToken = NULL;
+EFI_EVENT CpuProtocolNotificationEvent = (EFI_EVENT)NULL;
+EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
+
+HARDWARE_INTERRUPT_HANDLER gRegisteredInterruptHandlers[FixedPcdGet32(PcdGicNumInterrupts)];
+
+/**
+ 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 > PcdGet32(PcdGicNumInterrupts)) {
+ 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;
+ 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 > PcdGet32(PcdGicNumInterrupts)) {
+ 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) + 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 > PcdGet32(PcdGicNumInterrupts)) {
+ 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) + 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 > PcdGet32(PcdGicNumInterrupts)) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ // calculate enable register offset and bit position
+ RegOffset = Source / 32;
+ RegShift = Source % 32;
+
+ if ((MmioRead32 (PcdGet32(PcdGicDistributorBase) + 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 > PcdGet32(PcdGicNumInterrupts)) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + 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) + GIC_ICCIAR);
+ if (GicInterrupt >= PcdGet32(PcdGicNumInterrupts)) {
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCEIOR, GicInterrupt);
+ }
+
+ 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 i;
+
+ for (i = 0; i < PcdGet32(PcdGicNumInterrupts); i++) {
+ DisableInterruptSource (&gHardwareInterruptProtocol, i);
+ }
+
+ // Acknowledge all pending interrupts
+ for (i = 0; i < PcdGet32(PcdGicNumInterrupts); i++) {
+ DisableInterruptSource (&gHardwareInterruptProtocol, i);
+ }
+
+ for (i = 0; i < PcdGet32(PcdGicNumInterrupts); i++) {
+ EndOfInterrupt (&gHardwareInterruptProtocol, i);
+ }
+
+ // Disable Gic Interface
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCICR, 0x0);
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCPMR, 0x0);
+
+ // Disable Gic Distributor
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + GIC_ICDDCR, 0x0);
+}
+
+//
+// Notification routines
+//
+VOID
+CpuProtocolInstalledNotification (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_ARCH_PROTOCOL *Cpu;
+
+ //
+ // 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);
+}
+
+/**
+ 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 i;
+ UINT32 RegOffset;
+ UINTN RegShift;
+
+ // Make sure the Interrupt Controller Protocol is not already installed in the system.
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
+
+ for (i = 0; i < PcdGet32(PcdGicNumInterrupts); i++) {
+ DisableInterruptSource (&gHardwareInterruptProtocol, i);
+
+ // Set Priority
+ RegOffset = i / 4;
+ RegShift = (i % 4) * 8;
+ MmioAndThenOr32 (
+ PcdGet32(PcdGicDistributorBase) + GIC_ICDIPR+(4*RegOffset),
+ ~(0xff << RegShift),
+ GIC_DEFAULT_PRIORITY << RegShift
+ );
+ }
+
+ // configure interrupts for cpu 0
+ for (i = 0; i < GIC_NUM_REG_PER_INT_BYTES; i++) {
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + GIC_ICDIPTR + (i*4), 0x01010101);
+ }
+
+ // set binary point reg to 0x7 (no preemption)
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCBPR, 0x7);
+
+ // set priority mask reg to 0xff to allow all priorities through
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCPMR, 0xff);
+
+ // enable gic cpu interface
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + GIC_ICCICR, 0x1);
+
+ // enable gic distributor
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + GIC_ICDDCR, 0x1);
+
+ ZeroMem (&gRegisteredInterruptHandlers, sizeof (gRegisteredInterruptHandlers));
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &gHardwareInterruptHandle,
+ &gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ // Set up to be notified when the Cpu protocol is installed.
+ Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, CpuProtocolInstalledNotification, NULL, &CpuProtocolNotificationEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->RegisterProtocolNotify (&gEfiCpuArchProtocolGuid, CpuProtocolNotificationEvent, (VOID *)&CpuProtocolNotificationToken);
+ 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;
+}
diff --git a/ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf b/ArmPkg/Drivers/PL390Gic/PL390GicDxe.inf
index 31310fc6e8..907756542a 100644
--- a/ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf
+++ b/ArmPkg/Drivers/PL390Gic/PL390GicDxe.inf
@@ -1,44 +1,55 @@
-#/** @file
-#
-# DXE CPU driver
-#
-# Copyright (c) 2009 - 2010, Apple Inc. 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.
-#
-#**/
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = ArmDebugSupportDxe
- FILE_GUID = 2e7c151b-cbd8-4df6-a0e3-cde660067c6a
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
-
- ENTRY_POINT = DebugSupportDxeInitialize
-
-[Sources.common]
- DebugSupport.c
-
-[Packages]
- ArmPkg/ArmPkg.dec
- MdePkg/MdePkg.dec
-
-[LibraryClasses]
- BaseMemoryLib
- CacheMaintenanceLib
- UefiDriverEntryPoint
- ArmLib
-
-[Protocols]
- gEfiCpuArchProtocolGuid
- gEfiDebugSupportProtocolGuid
- gTimerDebugSupportProtocolGuid
-
-[Depex]
- TRUE \ No newline at end of file
+#/** @file
+#
+# Copyright (c) 2008 - 2010, Apple Inc. 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.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL390GicDxe
+ FILE_GUID = DE371F7C-DEC4-4D21-ADF1-593ABCC15882
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InterruptDxeInitialize
+
+
+[Sources.common]
+ PL390GicDxe.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ DebugLib
+ PrintLib
+ UefiDriverEntryPoint
+ IoLib
+
+[Guids]
+
+
+[Protocols]
+ gHardwareInterruptProtocolGuid
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd.common]
+ gArmTokenSpaceGuid.PcdGicDistributorBase
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+ gArmTokenSpaceGuid.PcdGicNumInterrupts
+
+[depex]
+ TRUE
diff --git a/ArmPkg/Drivers/PL390Gic/PL390GicNonSec.c b/ArmPkg/Drivers/PL390Gic/PL390GicNonSec.c
new file mode 100644
index 0000000000..e5faa40a33
--- /dev/null
+++ b/ArmPkg/Drivers/PL390Gic/PL390GicNonSec.c
@@ -0,0 +1,97 @@
+/** @file
+*
+* Copyright (c) 2011, 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 <Library/IoLib.h>
+#include <Drivers/PL390Gic.h>
+
+
+VOID
+EFIAPI
+PL390GicEnableInterruptInterface (
+ IN INTN GicInterruptInterfaceBase
+ )
+{
+ /*
+ * Enable the CPU interface in Non-Secure world
+ * Note: The ICCICR register is banked when Security extensions are implemented
+ */
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCICR,0x00000001);
+}
+
+VOID
+EFIAPI
+PL390GicEnableDistributor (
+ IN INTN GicDistributorBase
+ )
+{
+ /*
+ * Enable GIC distributor in Non-Secure world.
+ * Note: The ICDDCR register is banked when Security extensions are implemented
+ */
+ MmioWrite32(GicDistributorBase + GIC_ICDDCR, 0x00000001);
+}
+
+VOID
+EFIAPI
+PL390GicSendSgiTo (
+ IN INTN GicDistributorBase,
+ IN INTN TargetListFilter,
+ IN INTN CPUTargetList
+ )
+{
+ MmioWrite32(GicDistributorBase + GIC_ICDSGIR, ((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16));
+}
+
+UINT32
+EFIAPI
+PL390GicAcknowledgeSgiFrom (
+ IN INTN GicInterruptInterfaceBase,
+ IN INTN CoreId
+ )
+{
+ INTN InterruptId;
+
+ InterruptId = MmioRead32(GicInterruptInterfaceBase + GIC_ICCIAR);
+
+ //Check if the Interrupt ID is valid, The read from Interrupt Ack register returns CPU ID and Interrupt ID
+ if (((CoreId & 0x7) << 10) == (InterruptId & 0x1C00)) {
+ //Got SGI number 0 hence signal End of Interrupt by writing to ICCEOIR
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCEIOR, InterruptId);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+UINT32
+EFIAPI
+PL390GicAcknowledgeSgi2From (
+ IN INTN GicInterruptInterfaceBase,
+ IN INTN CoreId,
+ IN INTN SgiId
+ )
+{
+ INTN InterruptId;
+
+ InterruptId = MmioRead32(GicInterruptInterfaceBase + GIC_ICCIAR);
+
+ //Check if the Interrupt ID is valid, The read from Interrupt Ack register returns CPU ID and Interrupt ID
+ if((((CoreId & 0x7) << 10) | (SgiId & 0x3FF)) == (InterruptId & 0x1FFF)) {
+ //Got SGI number 0 hence signal End of Interrupt by writing to ICCEOIR
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCEIOR, InterruptId);
+ return 1;
+ } else {
+ return 0;
+ }
+}
diff --git a/ArmPkg/Drivers/PL390Gic/PL390GicNonSec.inf b/ArmPkg/Drivers/PL390Gic/PL390GicNonSec.inf
new file mode 100644
index 0000000000..f5ffd7febb
--- /dev/null
+++ b/ArmPkg/Drivers/PL390Gic/PL390GicNonSec.inf
@@ -0,0 +1,29 @@
+#/* @file
+# Copyright (c) 2011, 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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL390GicNonSec
+ FILE_GUID = 03d05ee4-cdeb-458c-9dfc-993f09bdf405
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL390GicNonSecLib
+
+[Sources]
+ PL390GicNonSec.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
diff --git a/ArmPkg/Drivers/PL390Gic/PL390GicSec.c b/ArmPkg/Drivers/PL390Gic/PL390GicSec.c
new file mode 100644
index 0000000000..46b14e0746
--- /dev/null
+++ b/ArmPkg/Drivers/PL390Gic/PL390GicSec.c
@@ -0,0 +1,135 @@
+/** @file
+*
+* Copyright (c) 2011, 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 <Library/IoLib.h>
+#include <Drivers/PL390Gic.h>
+
+/*
+ * This function configures the all interrupts to be Non-secure.
+ *
+ */
+VOID
+EFIAPI
+PL390GicSetupNonSecure (
+ IN INTN GicDistributorBase,
+ IN INTN GicInterruptInterfaceBase
+ )
+{
+ UINTN CachedPriorityMask = MmioRead32(GicInterruptInterfaceBase + GIC_ICCPMR);
+
+ //Set priority Mask so that no interrupts get through to CPU
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCPMR, 0);
+
+ //Check if there are any pending interrupts
+ while(0 != (MmioRead32(GicDistributorBase + GIC_ICDICPR) & 0xF))
+ {
+ //Some of the SGI's are still pending, read Ack register and send End of Interrupt Signal
+ UINTN InterruptId = MmioRead32(GicInterruptInterfaceBase + GIC_ICCIAR);
+
+ //Write to End of interrupt signal
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCEIOR, InterruptId);
+ }
+
+ // Ensure all GIC interrupts are Non-Secure
+ MmioWrite32(GicDistributorBase + GIC_ICDISR, 0xffffffff); // IRQs 0-31 are Non-Secure : Private Peripheral Interrupt[31:16] & Software Generated Interrupt[15:0]
+ MmioWrite32(GicDistributorBase + GIC_ICDISR + 4, 0xffffffff); // IRQs 32-63 are Non-Secure : Shared Peripheral Interrupt
+ MmioWrite32(GicDistributorBase + GIC_ICDISR + 8, 0xffffffff); // And another 32 in case we're on the testchip : Shared Peripheral Interrupt (2)
+
+ // Ensure all interrupts can get through the priority mask
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCPMR, CachedPriorityMask);
+}
+
+VOID
+EFIAPI
+PL390GicEnableInterruptInterface (
+ IN INTN GicInterruptInterfaceBase
+ )
+{
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCPMR, 0x000000FF); /* Set Priority Mask to allow interrupts */
+
+ /*
+ * Enable CPU interface in Secure world
+ * Enable CPU inteface in Non-secure World
+ * Signal Secure Interrupts to CPU using FIQ line *
+ */
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCICR,
+ GIC_ICCICR_ENABLE_SECURE(1) |
+ GIC_ICCICR_ENABLE_NS(1) |
+ GIC_ICCICR_ACK_CTL(0) |
+ GIC_ICCICR_SIGNAL_SECURE_TO_FIQ(1) |
+ GIC_ICCICR_USE_SBPR(0));
+}
+
+VOID
+EFIAPI
+PL390GicEnableDistributor (
+ IN INTN GicDistributorBase
+ )
+{
+ MmioWrite32(GicDistributorBase + GIC_ICDDCR, 1); // turn on the GIC distributor
+}
+
+VOID
+EFIAPI
+PL390GicSendSgiTo (
+ IN INTN GicDistributorBase,
+ IN INTN TargetListFilter,
+ IN INTN CPUTargetList
+ )
+{
+ MmioWrite32(GicDistributorBase + GIC_ICDSGIR, ((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16));
+}
+
+UINT32
+EFIAPI
+PL390GicAcknowledgeSgiFrom (
+ IN INTN GicInterruptInterfaceBase,
+ IN INTN CoreId
+ )
+{
+ INTN InterruptId;
+
+ InterruptId = MmioRead32(GicInterruptInterfaceBase + GIC_ICCIAR);
+
+ //Check if the Interrupt ID is valid, The read from Interrupt Ack register returns CPU ID and Interrupt ID
+ if (((CoreId & 0x7) << 10) == (InterruptId & 0x1C00)) {
+ //Got SGI number 0 hence signal End of Interrupt by writing to ICCEOIR
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCEIOR, InterruptId);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+UINT32
+EFIAPI
+PL390GicAcknowledgeSgi2From (
+ IN INTN GicInterruptInterfaceBase,
+ IN INTN CoreId,
+ IN INTN SgiId
+ )
+{
+ INTN InterruptId;
+
+ InterruptId = MmioRead32(GicInterruptInterfaceBase + GIC_ICCIAR);
+
+ //Check if the Interrupt ID is valid, The read from Interrupt Ack register returns CPU ID and Interrupt ID
+ if((((CoreId & 0x7) << 10) | (SgiId & 0x3FF)) == (InterruptId & 0x1FFF)) {
+ //Got SGI number 0 hence signal End of Interrupt by writing to ICCEOIR
+ MmioWrite32(GicInterruptInterfaceBase + GIC_ICCEIOR, InterruptId);
+ return 1;
+ } else {
+ return 0;
+ }
+}
diff --git a/ArmPkg/Drivers/PL390Gic/PL390GicSec.inf b/ArmPkg/Drivers/PL390Gic/PL390GicSec.inf
new file mode 100644
index 0000000000..9cbdb6e8b3
--- /dev/null
+++ b/ArmPkg/Drivers/PL390Gic/PL390GicSec.inf
@@ -0,0 +1,29 @@
+#/* @file
+# Copyright (c) 2011, 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.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL390GicSec
+ FILE_GUID = 85f3cf80-b5f4-11df-9855-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL390GicSecLib
+
+[Sources]
+ PL390GicSec.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]