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
This commit is contained in:
andrewfish
2011-02-02 22:35:30 +00:00
parent 7373d15a98
commit 1bfda055df
113 changed files with 7979 additions and 964 deletions

View File

@@ -67,10 +67,13 @@
gEfiDebugImageInfoTableGuid
[Pcd.common]
gArmTokenSpaceGuid.PcdVFPEnabled
gArmTokenSpaceGuid.PcdCpuVectorBaseAddress
[FeaturePcd.common]
gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport
gArmTokenSpaceGuid.PcdRelocateVectorTable
gArmTokenSpaceGuid.PcdEfiUncachedMemoryToStronglyOrdered
[depex]
gHardwareInterruptProtocolGuid

View File

@@ -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;
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);
//
// 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);
//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);
}
// 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);
if (FiqEnabled) {
ArmEnableFiq ();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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):

View File

@@ -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
};

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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]

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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]

View File

@@ -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

View File

@@ -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

View File

@@ -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]

View File

@@ -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;
}

View File

@@ -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
#/** @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

View File

@@ -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;
}
}

View File

@@ -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]

View File

@@ -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;
}
}

View File

@@ -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]