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