diff --git a/src/soc/intel/apollolake/include/soc/meminit.h b/src/soc/intel/apollolake/include/soc/meminit.h index 6b892fcdff..3b0b507ddd 100644 --- a/src/soc/intel/apollolake/include/soc/meminit.h +++ b/src/soc/intel/apollolake/include/soc/meminit.h @@ -132,4 +132,10 @@ void meminit_lpddr4_by_sku(FSP_M_CONFIG *cfg, const struct lpddr4_cfg *lpcfg, size_t sku_id); void save_lpddr4_dimm_info(const struct lpddr4_cfg *lpcfg, size_t mem_sku); +/* Retrieve the amount of memory configured in the system in MiB. It's only + * valid during romstage. */ +size_t memory_in_system_in_mib(void); +/* Retrieve the requested i/o hole in MiB. Only valid in romstage. */ +size_t iohole_in_mib(void); + #endif /* _SOC_APOLLOLAKE_MEMINIT_H_ */ diff --git a/src/soc/intel/apollolake/meminit.c b/src/soc/intel/apollolake/meminit.c index ca9d742ae5..b0a5f4a534 100644 --- a/src/soc/intel/apollolake/meminit.c +++ b/src/soc/intel/apollolake/meminit.c @@ -12,6 +12,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ +#include #include #include #include @@ -20,6 +21,54 @@ #include #include +static size_t memory_size_mib CAR_GLOBAL; + +size_t memory_in_system_in_mib(void) +{ + return car_get_var(memory_size_mib); +} + +static void accumulate_channel_memory(int density, int dual_rank) +{ + /* For this platform LPDDR4 memory is 4 DRAM parts that are x32. 2 of + the parts are composed into a x64 memory channel. Thus there are 2 + channels composed of 2 DRAMs. */ + size_t sz; + + /* Per rank density in Gb */ + switch (density) { + case LP4_8Gb_DENSITY: + sz = 8; + break; + case LP4_12Gb_DENSITY: + sz = 12; + break; + case LP4_16Gb_DENSITY: + sz = 16; + break; + default: + printk(BIOS_ERR, "Invalid DRAM density: %d\n", density); + sz = 0; + break; + } + + /* Two DRAMs per channel. */ + sz *= 2; + + /* Two ranks per channel. */ + if (dual_rank) + sz *= 2; + + sz *= GiB / MiB; + + car_set_var(memory_size_mib, car_get_var(memory_size_mib) + sz); +} + +size_t iohole_in_mib(void) +{ + return 2 * (GiB / MiB); +} + static void set_lpddr4_defaults(FSP_M_CONFIG *cfg) { /* Enable memory down BGA since it's the only LPDDR4 packaging. */ @@ -35,8 +84,8 @@ static void set_lpddr4_defaults(FSP_M_CONFIG *cfg) cfg->DualRankSupportEnable = 1; /* Don't enforce a memory size limit. */ cfg->MemorySizeLimit = 0; - /* Use a 2GiB I/O hole -- field is in MiB units. */ - cfg->LowMemoryMaxValue = 2 * (GiB/MiB); + /* Field is in MiB units. */ + cfg->LowMemoryMaxValue = iohole_in_mib(); /* No restrictions on memory above 4GiB */ cfg->HighMemoryMaxValue = 0; @@ -268,8 +317,9 @@ void meminit_lpddr4_enable_channel(FSP_M_CONFIG *cfg, int logical_chan, break; default: printk(BIOS_ERR, "Invalid logical channel: %d\n", logical_chan); - break; + return; } + accumulate_channel_memory(rank_density, dual_rank); } void meminit_lpddr4_by_sku(FSP_M_CONFIG *cfg,