From ba66d1f6654a4ddf14e73f684284606be7e18ad7 Mon Sep 17 00:00:00 2001 From: Marcin Wojtas Date: Wed, 25 Oct 2017 08:03:20 +0200 Subject: Marvell/Armada: Enable dynamic DRAM size detection Instead of using hardcoded value in PcdSystemMemorySize PCD, obtain DRAM size directly from SoC registers, which are filled by firmware during early initialization stage. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Marcin Wojtas Reviewed-by: Leif Lindholm --- .../Library/Armada70x0Lib/Armada70x0LibMem.c | 61 +++++++++++++++++++++- .../Library/Armada70x0Lib/Armada70x0LibMem.h | 25 +++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) (limited to 'Platform') diff --git a/Platform/Marvell/Armada/Library/Armada70x0Lib/Armada70x0LibMem.c b/Platform/Marvell/Armada/Library/Armada70x0Lib/Armada70x0LibMem.c index 978e4d3dd4..f384415d7a 100644 --- a/Platform/Marvell/Armada/Library/Armada70x0Lib/Armada70x0LibMem.c +++ b/Platform/Marvell/Armada/Library/Armada70x0Lib/Armada70x0LibMem.c @@ -50,6 +50,59 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. STATIC ARM_MEMORY_REGION_DESCRIPTOR mVirtualMemoryTable[MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS]; +// Obtain DRAM size basing on register values filled by early firmware. +STATIC +UINT64 +GetDramSize ( + IN OUT UINT64 *MemSize + ) +{ + UINT64 BaseAddr; + UINT8 RegionCode; + UINT8 Cs; + + *MemSize = 0; + + for (Cs = 0; Cs < DRAM_MAX_CS_NUM; Cs++) { + + /* Exit loop on first disabled DRAM CS */ + if (!DRAM_CS_ENABLED (Cs)) { + break; + } + + /* + * Sanity check for base address of next DRAM block. + * Only continuous space will be used. + */ + BaseAddr = GET_DRAM_REGION_BASE (Cs); + if (BaseAddr != *MemSize) { + DEBUG ((DEBUG_ERROR, + "%a: DRAM blocks are not contiguous, limit size to 0x%llx\n", + __FUNCTION__, + *MemSize)); + return EFI_SUCCESS; + } + + /* Decode area length for current CS from register value */ + RegionCode = GET_DRAM_REGION_SIZE_CODE (Cs); + + if (DRAM_REGION_SIZE_EVEN (RegionCode)) { + *MemSize += GET_DRAM_REGION_SIZE_EVEN (RegionCode); + } else if (DRAM_REGION_SIZE_ODD (RegionCode)) { + *MemSize += GET_DRAM_REGION_SIZE_ODD (RegionCode); + } else { + DEBUG ((DEBUG_ERROR, + "%a: Invalid memory region code (0x%x) for CS#%d\n", + __FUNCTION__, + RegionCode, + Cs)); + return EFI_INVALID_PARAMETER; + } + } + + return EFI_SUCCESS; +} + /** Return the Virtual Memory Map of your platform @@ -72,12 +125,18 @@ ArmPlatformGetVirtualMemoryMap ( UINT64 MemHighSize; UINT64 ConfigSpaceBaseAddr; EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes; + EFI_STATUS Status; ASSERT (VirtualMemoryMap != NULL); ConfigSpaceBaseAddr = FixedPcdGet64 (PcdConfigSpaceBaseAddress); - MemSize = FixedPcdGet64 (PcdSystemMemorySize); + // Obtain total memory size from the hardware. + Status = GetDramSize (&MemSize); + if (EFI_ERROR (Status)) { + MemSize = FixedPcdGet64 (PcdSystemMemorySize); + DEBUG ((DEBUG_ERROR, "Limit total memory size to %d MB\n", MemSize / 1024 / 1024)); + } if (DRAM_REMAP_ENABLED) { MemLowSize = MIN (DRAM_REMAP_TARGET, MemSize); diff --git a/Platform/Marvell/Armada/Library/Armada70x0Lib/Armada70x0LibMem.h b/Platform/Marvell/Armada/Library/Armada70x0Lib/Armada70x0LibMem.h index 8101cf370a..cc30e4aeed 100644 --- a/Platform/Marvell/Armada/Library/Armada70x0Lib/Armada70x0LibMem.h +++ b/Platform/Marvell/Armada/Library/Armada70x0Lib/Armada70x0LibMem.h @@ -46,3 +46,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (MmioRead32 (CCU_MC_RCR_REG) & REMAP_SIZE_MASK) + SIZE_1MB #define DRAM_REMAP_TARGET \ (MmioRead32 (CCU_MC_RTBR_REG) << TARGET_BASE_OFFS) + +#define DRAM_CH0_MMAP_LOW_REG(cs) (0xf0020200 + (cs) * 0x8) +#define DRAM_CS_VALID_ENABLED_MASK 0x1 +#define DRAM_AREA_LENGTH_OFFS 16 +#define DRAM_AREA_LENGTH_MASK (0x1f << DRAM_AREA_LENGTH_OFFS) +#define DRAM_START_ADDRESS_L_OFFS 23 +#define DRAM_START_ADDRESS_L_MASK (0x1ff << DRAM_START_ADDRESS_L_OFFS) +#define DRAM_CH0_MMAP_HIGH_REG(cs) (0xf0020204 + (cs) * 0x8) +#define DRAM_START_ADDR_HTOL_OFFS 32 + +#define DRAM_MAX_CS_NUM 8 + +#define DRAM_CS_ENABLED(Cs) \ + (MmioRead32 (DRAM_CH0_MMAP_LOW_REG (Cs)) & DRAM_CS_VALID_ENABLED_MASK) +#define GET_DRAM_REGION_BASE(Cs) \ + ((UINT64)MmioRead32 (DRAM_CH0_MMAP_HIGH_REG ((Cs))) << \ + DRAM_START_ADDR_HTOL_OFFS) | \ + (MmioRead32 (DRAM_CH0_MMAP_LOW_REG (Cs)) & DRAM_START_ADDRESS_L_MASK); +#define GET_DRAM_REGION_SIZE_CODE(Cs) \ + (MmioRead32 (DRAM_CH0_MMAP_LOW_REG ((Cs))) & \ + DRAM_AREA_LENGTH_MASK) >> DRAM_AREA_LENGTH_OFFS +#define DRAM_REGION_SIZE_EVEN(C) (((C) >= 7) && ((C) <= 26)) +#define GET_DRAM_REGION_SIZE_EVEN(C) ((UINT64)1 << ((C) + 16)) +#define DRAM_REGION_SIZE_ODD(C) ((C) <= 4) +#define GET_DRAM_REGION_SIZE_ODD(C) ((UINT64)0x18000000 << (C)) -- cgit v1.2.3