From 102b0d2daa97dae68d3eed54d8fe37a9cc38a892 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 11:13:47 +0200 Subject: Adding upstream version 2.8.0+dfsg. Signed-off-by: Daniel Baumann --- plat/marvell/armada/common/marvell_ddr_info.c | 112 ++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 plat/marvell/armada/common/marvell_ddr_info.c (limited to 'plat/marvell/armada/common/marvell_ddr_info.c') diff --git a/plat/marvell/armada/common/marvell_ddr_info.c b/plat/marvell/armada/common/marvell_ddr_info.c new file mode 100644 index 0000000..7340996 --- /dev/null +++ b/plat/marvell/armada/common/marvell_ddr_info.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include + +#include + +#define DRAM_CH0_MMAP_LOW_REG(iface, cs, base) \ + (base + DRAM_CH0_MMAP_LOW_OFFSET + (iface) * 0x10000 + (cs) * 0x8) +#define DRAM_CH0_MMAP_HIGH_REG(iface, cs, base) \ + (DRAM_CH0_MMAP_LOW_REG(iface, cs, base) + 4) +#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_START_ADDR_HTOL_OFFS 32 + +#define DRAM_MAX_CS_NUM 2 + +#define DRAM_CS_ENABLED(iface, cs, base) \ + (mmio_read_32(DRAM_CH0_MMAP_LOW_REG(iface, cs, base)) & \ + DRAM_CS_VALID_ENABLED_MASK) +#define GET_DRAM_REGION_SIZE_CODE(iface, cs, base) \ + (mmio_read_32(DRAM_CH0_MMAP_LOW_REG(iface, cs, base)) & \ + DRAM_AREA_LENGTH_MASK) >> DRAM_AREA_LENGTH_OFFS + +/* Mapping between DDR area length and real DDR size is specific and looks like + * bellow: + * 0 => 384 MB + * 1 => 768 MB + * 2 => 1536 MB + * 3 => 3 GB + * 4 => 6 GB + * + * 7 => 8 MB + * 8 => 16 MB + * 9 => 32 MB + * 10 => 64 MB + * 11 => 128 MB + * 12 => 256 MB + * 13 => 512 MB + * 14 => 1 GB + * 15 => 2 GB + * 16 => 4 GB + * 17 => 8 GB + * 18 => 16 GB + * 19 => 32 GB + * 20 => 64 GB + * 21 => 128 GB + * 22 => 256 GB + * 23 => 512 GB + * 24 => 1 TB + * 25 => 2 TB + * 26 => 4 TB + * + * to calculate real size we need to use two different formulas: + * -- GET_DRAM_REGION_SIZE_ODD for values 0-4 (DRAM_REGION_SIZE_ODD) + * -- GET_DRAM_REGION_SIZE_EVEN for values 7-26 (DRAM_REGION_SIZE_EVEN) + * using mentioned formulas we cover whole mapping between "Area length" value + * and real size (see above mapping). + */ +#define DRAM_REGION_SIZE_EVEN(C) (((C) >= 7) && ((C) <= 26)) +#define GET_DRAM_REGION_SIZE_EVEN(C) ((uint64_t)1 << ((C) + 16)) +#define DRAM_REGION_SIZE_ODD(C) ((C) <= 4) +#define GET_DRAM_REGION_SIZE_ODD(C) ((uint64_t)0x18000000 << (C)) + + +uint64_t mvebu_get_dram_size(uint64_t ap_base_addr) +{ + uint64_t mem_size = 0; + uint8_t region_code; + uint8_t cs, iface; + + for (iface = 0; iface < DRAM_MAX_IFACE; iface++) { + for (cs = 0; cs < DRAM_MAX_CS_NUM; cs++) { + + /* Exit loop on first disabled DRAM CS */ + if (!DRAM_CS_ENABLED(iface, cs, ap_base_addr)) + break; + + /* Decode area length for current CS + * from register value + */ + region_code = + GET_DRAM_REGION_SIZE_CODE(iface, cs, + ap_base_addr); + + if (DRAM_REGION_SIZE_EVEN(region_code)) { + mem_size += + GET_DRAM_REGION_SIZE_EVEN(region_code); + } else if (DRAM_REGION_SIZE_ODD(region_code)) { + mem_size += + GET_DRAM_REGION_SIZE_ODD(region_code); + } else { + WARN("%s: Invalid mem region (0x%x) CS#%d\n", + __func__, region_code, cs); + return 0; + } + } + } + + return mem_size; +} -- cgit v1.2.3