soc/intel/apollolake: add dual rank option to meminit

Despite the UPD comments the Chx_RankEnable fields are a bit
mask which indicates which ranks are enabled for physical
channel. Add the ability to set the rank mask correctly for
dual rank LPDDR4 modules.

BUG=chrome-os-partner:55446

Change-Id: I9dbed7bb6a4b512e57f6b4481180932a7cce91ff
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/15771
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Andrey Petrov <andrey.petrov@intel.com>
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
This commit is contained in:
Aaron Durbin 2016-07-21 09:57:15 -05:00
parent aa00e0893e
commit 17dbec1593
2 changed files with 22 additions and 12 deletions

View File

@ -92,13 +92,15 @@ void meminit_lpddr4(struct FSP_M_CONFIG *cfg, int speed);
* to the memory reference code. * to the memory reference code.
*/ */
void meminit_lpddr4_enable_channel(struct FSP_M_CONFIG *cfg, int logical_chan, void meminit_lpddr4_enable_channel(struct FSP_M_CONFIG *cfg, int logical_chan,
int device_density, int device_density, int dual_rank,
const struct lpddr4_swizzle_cfg *scfg); const struct lpddr4_swizzle_cfg *scfg);
struct lpddr4_sku { struct lpddr4_sku {
int speed; int speed;
int ch0_density; int ch0_density;
int ch1_density; int ch1_density;
int ch0_dual_rank;
int ch1_dual_rank;
}; };
struct lpddr4_cfg { struct lpddr4_cfg {

View File

@ -104,12 +104,14 @@ void meminit_lpddr4(struct FSP_M_CONFIG *cfg, int speed)
set_lpddr4_defaults(cfg); set_lpddr4_defaults(cfg);
} }
static void enable_logical_chan0(struct FSP_M_CONFIG *cfg, int device_density, static void enable_logical_chan0(struct FSP_M_CONFIG *cfg,
int device_density, int dual_rank,
const struct lpddr4_swizzle_cfg *scfg) const struct lpddr4_swizzle_cfg *scfg)
{ {
const struct lpddr4_chan_swizzle_cfg *chan; const struct lpddr4_chan_swizzle_cfg *chan;
/* Number of bytes to copy per DQS. */ /* Number of bytes to copy per DQS. */
const size_t sz = DQ_BITS_PER_DQS; const size_t sz = DQ_BITS_PER_DQS;
int rank_mask;
/* /*
* Logical channel 0 is comprised of physical channel 0 and 1. * Logical channel 0 is comprised of physical channel 0 and 1.
@ -118,9 +120,10 @@ static void enable_logical_chan0(struct FSP_M_CONFIG *cfg, int device_density,
*/ */
cfg->Ch0_DramDensity = device_density; cfg->Ch0_DramDensity = device_density;
cfg->Ch1_DramDensity = device_density; cfg->Ch1_DramDensity = device_density;
/* Enable rank 0 on both channels. */ /* Enable ranks on both channels depending on dual rank option. */
cfg->Ch0_RankEnable = 1; rank_mask = dual_rank ? 0x3 : 0x1;
cfg->Ch1_RankEnable = 1; cfg->Ch0_RankEnable = rank_mask;
cfg->Ch1_RankEnable = rank_mask;
/* /*
* CH0_DQB byte lanes in the bit swizzle configuration field are * CH0_DQB byte lanes in the bit swizzle configuration field are
@ -146,12 +149,14 @@ static void enable_logical_chan0(struct FSP_M_CONFIG *cfg, int device_density,
memcpy(&cfg->Ch1_Bit_swizzling[24], &chan->dqs[LP4_DQS3], sz); memcpy(&cfg->Ch1_Bit_swizzling[24], &chan->dqs[LP4_DQS3], sz);
} }
static void enable_logical_chan1(struct FSP_M_CONFIG *cfg, int device_density, static void enable_logical_chan1(struct FSP_M_CONFIG *cfg,
int device_density, int dual_rank,
const struct lpddr4_swizzle_cfg *scfg) const struct lpddr4_swizzle_cfg *scfg)
{ {
const struct lpddr4_chan_swizzle_cfg *chan; const struct lpddr4_chan_swizzle_cfg *chan;
/* Number of bytes to copy per DQS. */ /* Number of bytes to copy per DQS. */
const size_t sz = DQ_BITS_PER_DQS; const size_t sz = DQ_BITS_PER_DQS;
int rank_mask;
/* /*
* Logical channel 1 is comprised of physical channel 2 and 3. * Logical channel 1 is comprised of physical channel 2 and 3.
@ -160,9 +165,10 @@ static void enable_logical_chan1(struct FSP_M_CONFIG *cfg, int device_density,
*/ */
cfg->Ch2_DramDensity = device_density; cfg->Ch2_DramDensity = device_density;
cfg->Ch3_DramDensity = device_density; cfg->Ch3_DramDensity = device_density;
/* Enable rank 0 on both channels. */ /* Enable ranks on both channels depending on dual rank option. */
cfg->Ch2_RankEnable = 1; rank_mask = dual_rank ? 0x3 : 0x1;
cfg->Ch3_RankEnable = 1; cfg->Ch2_RankEnable = rank_mask;
cfg->Ch3_RankEnable = rank_mask;
/* /*
* CH1_DQB byte lanes in the bit swizzle configuration field are * CH1_DQB byte lanes in the bit swizzle configuration field are
@ -189,7 +195,7 @@ static void enable_logical_chan1(struct FSP_M_CONFIG *cfg, int device_density,
} }
void meminit_lpddr4_enable_channel(struct FSP_M_CONFIG *cfg, int logical_chan, void meminit_lpddr4_enable_channel(struct FSP_M_CONFIG *cfg, int logical_chan,
int device_density, int device_density, int dual_rank,
const struct lpddr4_swizzle_cfg *scfg) const struct lpddr4_swizzle_cfg *scfg)
{ {
if (device_density < LP4_8Gb_DENSITY || if (device_density < LP4_8Gb_DENSITY ||
@ -201,10 +207,10 @@ void meminit_lpddr4_enable_channel(struct FSP_M_CONFIG *cfg, int logical_chan,
switch (logical_chan) { switch (logical_chan) {
case LP4_LCH0: case LP4_LCH0:
enable_logical_chan0(cfg, device_density, scfg); enable_logical_chan0(cfg, device_density, dual_rank, scfg);
break; break;
case LP4_LCH1: case LP4_LCH1:
enable_logical_chan1(cfg, device_density, scfg); enable_logical_chan1(cfg, device_density, dual_rank, scfg);
break; break;
default: default:
printk(BIOS_ERR, "Invalid logical channel: %d\n", logical_chan); printk(BIOS_ERR, "Invalid logical channel: %d\n", logical_chan);
@ -233,6 +239,7 @@ void meminit_lpddr4_by_sku(struct FSP_M_CONFIG *cfg,
printk(BIOS_INFO, "LPDDR4 Ch0 density = %d\n", printk(BIOS_INFO, "LPDDR4 Ch0 density = %d\n",
sku->ch0_density); sku->ch0_density);
meminit_lpddr4_enable_channel(cfg, LP4_LCH0, sku->ch0_density, meminit_lpddr4_enable_channel(cfg, LP4_LCH0, sku->ch0_density,
sku->ch0_dual_rank,
lpcfg->swizzle_config); lpcfg->swizzle_config);
} }
@ -240,6 +247,7 @@ void meminit_lpddr4_by_sku(struct FSP_M_CONFIG *cfg,
printk(BIOS_INFO, "LPDDR4 Ch1 density = %d\n", printk(BIOS_INFO, "LPDDR4 Ch1 density = %d\n",
sku->ch1_density); sku->ch1_density);
meminit_lpddr4_enable_channel(cfg, LP4_LCH1, sku->ch1_density, meminit_lpddr4_enable_channel(cfg, LP4_LCH1, sku->ch1_density,
sku->ch1_dual_rank,
lpcfg->swizzle_config); lpcfg->swizzle_config);
} }
} }