rockchip: rk3399: improve write leveling flow
To improve sdram 800MHz and 933MHz stability, we need to modify write leveling flow to get the proper write leveling value. BUG=chrome-os-partner:56940 BRANCH=none TEST=Boot from kevin on 933MHz, and do stressapptest Change-Id: I5b24c93d4a57917fb9af7e5e2a95d8423ccbaa7e Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: d84bf25b3e5de373c7913e6d534a810cb984b3fd Original-Change-Id: I87efddf628c3683fcb85d6875e029cf3cbc482be Original-Signed-off-by: Jianqun Xu <jay.xu@rock-chips.com> Original-Signed-off-by: Xing Zheng <zhengxing@rock-chips.com> Original-Signed-off-by: Lin Huang <hl@rock-chips.com> Original-Reviewed-on: https://chromium-review.googlesource.com/384292 Original-Commit-Ready: Julius Werner <jwerner@chromium.org> Original-Tested-by: Julius Werner <jwerner@chromium.org> Original-Reviewed-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://review.coreboot.org/16716 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
committed by
Patrick Georgi
parent
547a059b34
commit
681b6b9433
@@ -580,10 +580,9 @@ static void check_write_leveling_value(u32 channel,
|
||||
const struct rk3399_sdram_params
|
||||
*sdram_params)
|
||||
{
|
||||
u32 *denali_pi = rk3399_ddr_pi[channel]->denali_pi;
|
||||
u32 *denali_ctl = rk3399_ddr_pctl[channel]->denali_ctl;
|
||||
u32 *denali_phy = rk3399_ddr_publ[channel]->denali_phy;
|
||||
u32 i, tmp;
|
||||
u32 obs_0, obs_1, obs_2, obs_3, obs_err = 0;
|
||||
u32 i, j;
|
||||
u32 wl_value[2][4];
|
||||
u32 rank = sdram_params->ch[channel].rank;
|
||||
|
||||
@@ -602,71 +601,43 @@ static void check_write_leveling_value(u32 channel,
|
||||
wl_value[i][3] = (read32(&denali_phy[447]) >> 16) & 0x3ff;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (((wl_value[0][i] > 0x1E0) || (wl_value[0][i] < 0x20)) &&
|
||||
((wl_value[1][i] > 0x1E0) || (wl_value[1][i] < 0x20))) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
setbits_le32(&denali_phy[79], 0x1 << 16);
|
||||
break;
|
||||
case 1:
|
||||
setbits_le32(&denali_phy[207], 0x1 << 16);
|
||||
break;
|
||||
case 2:
|
||||
setbits_le32(&denali_phy[335], 0x1 << 16);
|
||||
break;
|
||||
case 3:
|
||||
setbits_le32(&denali_phy[463], 0x1 << 16);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* PHY_8/136/264/392
|
||||
* phy_per_cs_training_multicast_en_X 1bit offset_16
|
||||
*/
|
||||
clrsetbits_le32(&denali_phy[8], 0x1 << 16, 0 << 16);
|
||||
clrsetbits_le32(&denali_phy[136], 0x1 << 16, 0 << 16);
|
||||
clrsetbits_le32(&denali_phy[264], 0x1 << 16, 0 << 16);
|
||||
clrsetbits_le32(&denali_phy[392], 0x1 << 16, 0 << 16);
|
||||
|
||||
for (i = 0; i < rank; i++) {
|
||||
|
||||
/* FIXME: denali_phy[463] value wrong if miss this delay */
|
||||
udelay(100);
|
||||
|
||||
/* PI_60 PI_WRLVL_EN:RW:8:2 */
|
||||
clrsetbits_le32(&denali_pi[60], 0x3 << 8, 0x2 << 8);
|
||||
/* PI_59 PI_WRLVL_REQ:WR:8:1,PI_WRLVL_CS:RW:16:2 */
|
||||
clrsetbits_le32(&denali_pi[59], (0x1 << 8) | (0x3 << 16),
|
||||
(0x1 << 8) | (i << 16));
|
||||
|
||||
select_per_cs_training_index(channel, i);
|
||||
while (1) {
|
||||
/* PI_174 PI_INT_STATUS:RD:8:25 */
|
||||
tmp = read32(&denali_pi[174]) >> 8;
|
||||
|
||||
/*
|
||||
* check status obs,
|
||||
* if error maybe can not get leveling done
|
||||
* PHY_40/168/296/424 phy_wrlvl_status_obs_X:0:13
|
||||
*/
|
||||
obs_0 = read32(&denali_phy[40]);
|
||||
obs_1 = read32(&denali_phy[168]);
|
||||
obs_2 = read32(&denali_phy[296]);
|
||||
obs_3 = read32(&denali_phy[424]);
|
||||
if (((obs_0 >> 12) & 0x1) ||
|
||||
((obs_1 >> 12) & 0x1) ||
|
||||
((obs_2 >> 12) & 0x1) ||
|
||||
((obs_3 >> 12) & 0x1))
|
||||
obs_err = 1;
|
||||
if ((((tmp >> 10) & 0x1) == 0x1) &&
|
||||
(((tmp >> 13) & 0x1) == 0x1) &&
|
||||
(((tmp >> 4) & 0x1) == 0x0) &&
|
||||
(obs_err == 0))
|
||||
break;
|
||||
else if ((((tmp >> 4) & 0x1) == 0x1) ||
|
||||
(obs_err == 1))
|
||||
printk(BIOS_DEBUG,
|
||||
"check_write_leveling_value error!!!\n");
|
||||
clrsetbits_le32(&denali_phy[8], 0x1 << 24, i << 24);
|
||||
clrsetbits_le32(&denali_phy[136], 0x1 << 24, i << 24);
|
||||
clrsetbits_le32(&denali_phy[264], 0x1 << 24, i << 24);
|
||||
clrsetbits_le32(&denali_phy[392], 0x1 << 24, i << 24);
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (wl_value[i][j] < 0x80)
|
||||
clrsetbits_le32(&denali_phy[63+j*128],
|
||||
0x3ff << 16,
|
||||
(wl_value[i][j]+0x200) << 16);
|
||||
else if ((wl_value[i][j] >= 0x80) &&
|
||||
(wl_value[i][j] < 0x100))
|
||||
clrsetbits_le32(&denali_phy[78+j*128],
|
||||
0x7 << 8, 0x1 << 8);
|
||||
}
|
||||
/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
|
||||
write32((&denali_pi[175]), 0x00003f7c);
|
||||
}
|
||||
|
||||
/* CTL_200 ctrlupd_req 1bit offset_8 */
|
||||
clrsetbits_le32(&denali_ctl[200], 0x1 << 8, 0x1 << 8);
|
||||
|
||||
/*
|
||||
* PHY_8/136/264/392
|
||||
* phy_per_cs_training_multicast_en_X 1bit offset_16
|
||||
*/
|
||||
clrsetbits_le32(&denali_phy[8], 0x1 << 16, 1 << 16);
|
||||
clrsetbits_le32(&denali_phy[136], 0x1 << 16, 1 << 16);
|
||||
clrsetbits_le32(&denali_phy[264], 0x1 << 16, 1 << 16);
|
||||
clrsetbits_le32(&denali_phy[392], 0x1 << 16, 1 << 16);
|
||||
}
|
||||
|
||||
static int data_training(u32 channel,
|
||||
|
Reference in New Issue
Block a user