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