summaryrefslogtreecommitdiff
path: root/plat/rockchip
diff options
context:
space:
mode:
authorLin Huang <hl@rock-chips.com>2017-02-22 18:24:55 +0800
committerCaesar Wang <wxt@rock-chips.com>2017-06-08 09:59:34 +0800
commita9059b9643932782c17a9a5366f7019817819d44 (patch)
tree01b019470b10c2eacf5375673a71b080894cdd74 /plat/rockchip
parentf9a050e41ba4a069e755273dab77fbeec795bd6a (diff)
rockchip/rk3399: fix DRAM gate training issue
The differential signal of DQS need keep low level before gate training. It need enable RPULL and disable PHY side ODT to ensure it when do gate training. But it can not access the PHY registers to do it when perform DFS.So the workaroud as below: It is ensure that the PHY's read gate is landing somewhere in the incoming DQS's pulses before it starts searching for pre-amble window. It need get the rddqs_delay_ps to calculate the start point of gate training for DFS. Change-Id: I79eabcf4ec9a9c8f4539f68a51f22afba49c72fe Signed-off-by: Lin Huang <hl@rock-chips.com>
Diffstat (limited to 'plat/rockchip')
-rw-r--r--plat/rockchip/rk3399/drivers/dram/dfs.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/plat/rockchip/rk3399/drivers/dram/dfs.c b/plat/rockchip/rk3399/drivers/dram/dfs.c
index 28d0d6a7..481dcc64 100644
--- a/plat/rockchip/rk3399/drivers/dram/dfs.c
+++ b/plat/rockchip/rk3399/drivers/dram/dfs.c
@@ -54,6 +54,7 @@ struct rk3399_saved_status {
static struct rk3399_dram_status rk3399_dram_status;
static struct rk3399_saved_status rk3399_suspend_status;
static uint32_t wrdqs_delay_val[2][2][4];
+static uint32_t rddqs_delay_ps;
static struct rk3399_sdram_default_config ddr3_default_config = {
.bl = 8,
@@ -1599,7 +1600,7 @@ static void gen_rk3399_phy_params(struct timing_related_config *timing_config,
mmio_clrsetbits_32(PHY_REG(i, 394), 0xf, tmp);
/* PHY_GTLVL_LAT_ADJ_START */
/* DENALI_PHY_80/208/336/464 4bits offset_16 */
- tmp = delay_frac_ps / 1000;
+ tmp = rddqs_delay_ps / (1000000 / pdram_timing->mhz) + 2;
mmio_clrsetbits_32(PHY_REG(i, 80), 0xf << 16, tmp << 16);
mmio_clrsetbits_32(PHY_REG(i, 208), 0xf << 16, tmp << 16);
mmio_clrsetbits_32(PHY_REG(i, 336), 0xf << 16, tmp << 16);
@@ -1830,6 +1831,7 @@ static void dram_low_power_config(void)
void dram_dfs_init(void)
{
uint32_t trefi0, trefi1, boot_freq;
+ uint32_t rddqs_adjust, rddqs_slave;
/* get sdram config for os reg */
get_dram_drv_odt_val(sdram_config.dramtype,
@@ -1875,8 +1877,31 @@ void dram_dfs_init(void)
/* Disable multicast */
mmio_clrbits_32(PHY_REG(0, 896), 1);
mmio_clrbits_32(PHY_REG(1, 896), 1);
-
dram_low_power_config();
+
+ /*
+ * If boot_freq isn't in the bypass mode, it can get the
+ * rddqs_delay_ps from the result of gate training
+ */
+ if (((mmio_read_32(PHY_REG(0, 86)) >> 8) & 0xf) != 0xc) {
+
+ /*
+ * Select PHY's frequency set to current_index
+ * index for get the result of gate Training
+ * from registers
+ */
+ mmio_clrsetbits_32(PHY_REG(0, 896), 0x3 << 8,
+ rk3399_dram_status.current_index << 8);
+ rddqs_slave = (mmio_read_32(PHY_REG(0, 77)) >> 16) & 0x3ff;
+ rddqs_slave = rddqs_slave * 1000000 / boot_freq / 512;
+
+ rddqs_adjust = mmio_read_32(PHY_REG(0, 78)) & 0xf;
+ rddqs_adjust = rddqs_adjust * 1000000 / boot_freq;
+ rddqs_delay_ps = rddqs_slave + rddqs_adjust -
+ (1000000 / boot_freq / 2);
+ } else {
+ rddqs_delay_ps = 3500;
+ }
}
/*