/* SPDX-License-Identifier: GPL-2.0-only */ #include #include #include #include #include #include #include #include void mainboard_memory_init_params(FSPM_UPD *memupd) { const struct lpddr4_swizzle_cfg *cfg; const struct lpddr4_chan_swizzle_cfg *chan; uint8_t spd[0x80]; /* * Get DRAM configuration data from hwinfo block. * The configuration data from hwinfo block is a one-to-one * representation of the FSPM_UPD data starting with parameter * 'Package' (offset 0x4d) and ending before parameter * 'Ch0_Bit_swizzling' (offset 0x88). */ if (hwilib_find_blocks("hwinfo.hex")) { printk(BIOS_ERR, "HWInfo not found, use default values for FSP-M.\n"); return; } if (hwilib_get_field(SPD, spd, sizeof(spd)) != sizeof(spd)) { printk(BIOS_ERR, "SPD not found in HWInfo, use defaults for FSP-M.\n"); return; } memcpy(&memupd->FspmConfig.Package, &spd, (((uint8_t *)memupd->FspmConfig.Ch0_Bit_swizzling)- (&memupd->FspmConfig.Package))); /* * Some of the mc_apl1 boards use LPDDR4 memory. In this case, the * correct swizzle configuration is necessary. The default settings * for swizzling are 0, since the baseboard does not use LPDDR4 memory. */ cfg = variant_lpddr4_swizzle_config(); /* * CH0_DQB byte lanes in the bit swizzle configuration field are * not 1:1. The mapping within the swizzling field is: * indices [0:7] - byte lane 1 (DQS1) DQ[8:15] * indices [8:15] - byte lane 0 (DQS0) DQ[0:7] * indices [16:23] - byte lane 3 (DQS3) DQ[24:31] * indices [24:31] - byte lane 2 (DQS2) DQ[16:23] */ chan = &cfg->phys[LP4_PHYS_CH0B]; memcpy(&memupd->FspmConfig.Ch0_Bit_swizzling[0], &chan->dqs[LP4_DQS1], (size_t)DQ_BITS_PER_DQS); memcpy(&memupd->FspmConfig.Ch0_Bit_swizzling[8], &chan->dqs[LP4_DQS0], (size_t)DQ_BITS_PER_DQS); memcpy(&memupd->FspmConfig.Ch0_Bit_swizzling[16], &chan->dqs[LP4_DQS3], (size_t)DQ_BITS_PER_DQS); memcpy(&memupd->FspmConfig.Ch0_Bit_swizzling[24], &chan->dqs[LP4_DQS2], (size_t)DQ_BITS_PER_DQS); /* CH0_DQA byte lanes in the bit swizzle configuration field are 1:1. */ chan = &cfg->phys[LP4_PHYS_CH0A]; memcpy(&memupd->FspmConfig.Ch1_Bit_swizzling[0], &chan->dqs[LP4_DQS0], (size_t)DQ_BITS_PER_DQS); memcpy(&memupd->FspmConfig.Ch1_Bit_swizzling[8], &chan->dqs[LP4_DQS1], (size_t)DQ_BITS_PER_DQS); memcpy(&memupd->FspmConfig.Ch1_Bit_swizzling[16], &chan->dqs[LP4_DQS2], (size_t)DQ_BITS_PER_DQS); memcpy(&memupd->FspmConfig.Ch1_Bit_swizzling[24], &chan->dqs[LP4_DQS3], (size_t)DQ_BITS_PER_DQS); /* * CH1_DQB byte lanes in the bit swizzle configuration field are * not 1:1. The mapping within the swizzling field is: * indices [0:7] - byte lane 1 (DQS1) DQ[8:15] * indices [8:15] - byte lane 0 (DQS0) DQ[0:7] * indices [16:23] - byte lane 3 (DQS3) DQ[24:31] * indices [24:31] - byte lane 2 (DQS2) DQ[16:23] */ chan = &cfg->phys[LP4_PHYS_CH1B]; memcpy(&memupd->FspmConfig.Ch2_Bit_swizzling[0], &chan->dqs[LP4_DQS1], (size_t)DQ_BITS_PER_DQS); memcpy(&memupd->FspmConfig.Ch2_Bit_swizzling[8], &chan->dqs[LP4_DQS0], (size_t)DQ_BITS_PER_DQS); memcpy(&memupd->FspmConfig.Ch2_Bit_swizzling[16], &chan->dqs[LP4_DQS3], (size_t)DQ_BITS_PER_DQS); memcpy(&memupd->FspmConfig.Ch2_Bit_swizzling[24], &chan->dqs[LP4_DQS2], (size_t)DQ_BITS_PER_DQS); /* CH1_DQA byte lanes in the bit swizzle configuration field are 1:1. */ chan = &cfg->phys[LP4_PHYS_CH1A]; memcpy(&memupd->FspmConfig.Ch3_Bit_swizzling[0], &chan->dqs[LP4_DQS0], (size_t)DQ_BITS_PER_DQS); memcpy(&memupd->FspmConfig.Ch3_Bit_swizzling[8], &chan->dqs[LP4_DQS1], (size_t)DQ_BITS_PER_DQS); memcpy(&memupd->FspmConfig.Ch3_Bit_swizzling[16], &chan->dqs[LP4_DQS2], (size_t)DQ_BITS_PER_DQS); memcpy(&memupd->FspmConfig.Ch3_Bit_swizzling[24], &chan->dqs[LP4_DQS3], (size_t)DQ_BITS_PER_DQS); memupd->FspmConfig.MsgLevelMask = 0x0; memupd->FspmConfig.MrcDataSaving = 0x0; memupd->FspmConfig.MrcFastBoot = 0x1; }