1 /* 2 * Copyright (C) 2018 Marvell International Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * https://spdx.org/licenses 6 */ 7 8 #include <platform_def.h> 9 10 #include <common/debug.h> 11 #include <lib/mmio.h> 12 13 #include <ddr_info.h> 14 15 #define DRAM_CH0_MMAP_LOW_REG(iface, cs, base) \ 16 (base + DRAM_CH0_MMAP_LOW_OFFSET + (iface) * 0x10000 + (cs) * 0x8) 17 #define DRAM_CH0_MMAP_HIGH_REG(iface, cs, base) \ 18 (DRAM_CH0_MMAP_LOW_REG(iface, cs, base) + 4) 19 #define DRAM_CS_VALID_ENABLED_MASK 0x1 20 #define DRAM_AREA_LENGTH_OFFS 16 21 #define DRAM_AREA_LENGTH_MASK (0x1f << DRAM_AREA_LENGTH_OFFS) 22 #define DRAM_START_ADDRESS_L_OFFS 23 23 #define DRAM_START_ADDRESS_L_MASK \ 24 (0x1ff << DRAM_START_ADDRESS_L_OFFS) 25 #define DRAM_START_ADDR_HTOL_OFFS 32 26 27 #define DRAM_MAX_CS_NUM 2 28 29 #define DRAM_CS_ENABLED(iface, cs, base) \ 30 (mmio_read_32(DRAM_CH0_MMAP_LOW_REG(iface, cs, base)) & \ 31 DRAM_CS_VALID_ENABLED_MASK) 32 #define GET_DRAM_REGION_SIZE_CODE(iface, cs, base) \ 33 (mmio_read_32(DRAM_CH0_MMAP_LOW_REG(iface, cs, base)) & \ 34 DRAM_AREA_LENGTH_MASK) >> DRAM_AREA_LENGTH_OFFS 35 36 /* Mapping between DDR area length and real DDR size is specific and looks like 37 * below: 38 * 0 => 384 MB 39 * 1 => 768 MB 40 * 2 => 1536 MB 41 * 3 => 3 GB 42 * 4 => 6 GB 43 * 44 * 7 => 8 MB 45 * 8 => 16 MB 46 * 9 => 32 MB 47 * 10 => 64 MB 48 * 11 => 128 MB 49 * 12 => 256 MB 50 * 13 => 512 MB 51 * 14 => 1 GB 52 * 15 => 2 GB 53 * 16 => 4 GB 54 * 17 => 8 GB 55 * 18 => 16 GB 56 * 19 => 32 GB 57 * 20 => 64 GB 58 * 21 => 128 GB 59 * 22 => 256 GB 60 * 23 => 512 GB 61 * 24 => 1 TB 62 * 25 => 2 TB 63 * 26 => 4 TB 64 * 65 * to calculate real size we need to use two different formulas: 66 * -- GET_DRAM_REGION_SIZE_ODD for values 0-4 (DRAM_REGION_SIZE_ODD) 67 * -- GET_DRAM_REGION_SIZE_EVEN for values 7-26 (DRAM_REGION_SIZE_EVEN) 68 * using mentioned formulas we cover whole mapping between "Area length" value 69 * and real size (see above mapping). 70 */ 71 #define DRAM_REGION_SIZE_EVEN(C) (((C) >= 7) && ((C) <= 26)) 72 #define GET_DRAM_REGION_SIZE_EVEN(C) ((uint64_t)1 << ((C) + 16)) 73 #define DRAM_REGION_SIZE_ODD(C) ((C) <= 4) 74 #define GET_DRAM_REGION_SIZE_ODD(C) ((uint64_t)0x18000000 << (C)) 75 76 77 uint64_t mvebu_get_dram_size(uint64_t ap_base_addr) 78 { 79 uint64_t mem_size = 0; 80 uint8_t region_code; 81 uint8_t cs, iface; 82 83 for (iface = 0; iface < DRAM_MAX_IFACE; iface++) { 84 for (cs = 0; cs < DRAM_MAX_CS_NUM; cs++) { 85 86 /* Exit loop on first disabled DRAM CS */ 87 if (!DRAM_CS_ENABLED(iface, cs, ap_base_addr)) 88 break; 89 90 /* Decode area length for current CS 91 * from register value 92 */ 93 region_code = 94 GET_DRAM_REGION_SIZE_CODE(iface, cs, 95 ap_base_addr); 96 97 if (DRAM_REGION_SIZE_EVEN(region_code)) { 98 mem_size += 99 GET_DRAM_REGION_SIZE_EVEN(region_code); 100 } else if (DRAM_REGION_SIZE_ODD(region_code)) { 101 mem_size += 102 GET_DRAM_REGION_SIZE_ODD(region_code); 103 } else { 104 WARN("%s: Invalid mem region (0x%x) CS#%d\n", 105 __func__, region_code, cs); 106 return 0; 107 } 108 } 109 } 110 111 return mem_size; 112 } 113