summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacky Bai <ping.bai@nxp.com>2020-05-08 17:37:24 +0800
committerJacky Bai <ping.bai@nxp.com>2020-05-09 15:25:12 +0800
commit8cd4fa6dfff74b190294141bdc22634a7cb40a30 (patch)
tree9d8e35cd566675841a7df416f2c345376024eb26
parente9dfde639db8593aa12d779f1990c8bb276e711c (diff)
MLK-23821-04 plat: imx8m: Fix the rank to rank issue
update umctl2's setting based on phy training CDD value to workaround the rank-to-rank space issue. Signed-off-by: Jacky Bai <ping.bai@nxp.com> Reviewed-by: Anson Huang <anson.huang@nxp.com>
-rw-r--r--plat/imx/imx8m/ddr/dram.c24
-rw-r--r--plat/imx/imx8m/ddr/dram_retention.c29
-rw-r--r--plat/imx/imx8m/include/dram.h2
3 files changed, 55 insertions, 0 deletions
diff --git a/plat/imx/imx8m/ddr/dram.c b/plat/imx/imx8m/ddr/dram.c
index b886b931..b206c716 100644
--- a/plat/imx/imx8m/ddr/dram.c
+++ b/plat/imx/imx8m/ddr/dram.c
@@ -71,6 +71,27 @@ static void get_mr_values(uint32_t (*mr_value)[8])
}
}
+static void save_rank_setting(void)
+{
+ uint32_t i, offset;
+ uint32_t pstate_num = dram_info.num_fsp;
+
+ for(i = 0; i < pstate_num; i++) {
+ offset = i ? (i + 1) * 0x1000 : 0;
+ if (dram_info.dram_type == DDRC_LPDDR4) {
+ dram_info.rank_setting[i][0] = mmio_read_32(DDRC_DRAMTMG2(0) + offset);
+ } else {
+ dram_info.rank_setting[i][0] = mmio_read_32(DDRC_DRAMTMG2(0) + offset);
+ dram_info.rank_setting[i][1] = mmio_read_32(DDRC_DRAMTMG9(0) + offset);
+ }
+#if !defined(PLAT_imx8mq)
+ dram_info.rank_setting[i][2] = mmio_read_32(DDRC_RANKCTL(0) + offset);
+#endif
+ }
+#if defined(PLAT_imx8mq)
+ dram_info.rank_setting[0][2] = mmio_read_32(DDRC_RANKCTL(0));
+#endif
+}
/* Restore the ddrc configs */
void dram_umctl2_init(struct dram_timing_info *timing)
{
@@ -178,6 +199,9 @@ void dram_info_init(unsigned long dram_timing_base)
break;
dram_info.num_fsp = i;
+ /* save the DRAMTMG2/9 for rank to rank workaround */
+ save_rank_setting();
+
/* check if has bypass mode support */
if (dram_info.timing_info->fsp_table[i-1] < 666)
dram_info.bypass_mode = true;
diff --git a/plat/imx/imx8m/ddr/dram_retention.c b/plat/imx/imx8m/ddr/dram_retention.c
index b46d4410..6a19f0e7 100644
--- a/plat/imx/imx8m/ddr/dram_retention.c
+++ b/plat/imx/imx8m/ddr/dram_retention.c
@@ -19,6 +19,32 @@
#define CCM_SRC_CTRL(n) (CCM_SRC_CTRL_OFFSET + 0x10 * (n))
#define CCM_CCGR(n) (CCM_CCGR_OFFSET + 0x10 * (n))
+static void rank_setting_update(void)
+{
+ uint32_t i, offset;
+ uint32_t pstate_num = dram_info.num_fsp;
+
+ for (i = 0; i < pstate_num; i++) {
+ offset = i ? (i + 1) * 0x1000 : 0;
+ if (dram_info.dram_type == DDRC_LPDDR4) {
+ mmio_write_32(DDRC_DRAMTMG2(0) + offset,
+ dram_info.rank_setting[i][0]);
+ } else {
+ mmio_write_32(DDRC_DRAMTMG2(0) + offset,
+ dram_info.rank_setting[i][0]);
+ mmio_write_32(DDRC_DRAMTMG9(0) + offset,
+ dram_info.rank_setting[i][1]);
+ }
+#if !defined(PLAT_imx8mq)
+ mmio_write_32(DDRC_RANKCTL(0) + offset,
+ dram_info.rank_setting[i][2]);
+#endif
+ }
+#if defined(PLAT_imx8mq)
+ mmio_write_32(DDRC_RANKCTL(0), dram_info.rank_setting[0][2]);
+#endif
+}
+
void dram_enter_retention(void)
{
/* Wait DBGCAM to be empty */
@@ -132,6 +158,9 @@ void dram_exit_retention(void)
/* dram phy re-init */
dram_phy_init(dram_info.timing_info);
+ /* workaround for rank-to-rank issue */
+ rank_setting_update();
+
/* DWC_DDRPHYA_APBONLY0_MicroContMuxSel */
dwc_ddrphy_apb_wr(0xd0000, 0x0);
while (dwc_ddrphy_apb_rd(0x20097))
diff --git a/plat/imx/imx8m/include/dram.h b/plat/imx/imx8m/include/dram.h
index d221d27e..d0d5bf81 100644
--- a/plat/imx/imx8m/include/dram.h
+++ b/plat/imx/imx8m/include/dram.h
@@ -58,6 +58,8 @@ struct dram_info {
struct dram_timing_info *timing_info;
/* mr, emr, emr2, emr3, mr11, mr12, mr22, mr14 */
uint32_t mr_table[3][8];
+ /* used for workaround for rank to rank issue */
+ uint32_t rank_setting[3][3];
};
extern struct dram_info dram_info;