fix(nxp-ddr): apply Max CDD values for warm boot
Timing CFG 0 and Timing CFG 4 are ddr controller registers that
have been affected by 1d phy training during cold boot. They are
needed to be stored and restored along with phy training values.
Signed-off-by: Maninder Singh <maninder.singh_1@nxp.com>
Signed-off-by: Jiafei Pan <Jiafei.Pan@nxp.com>
Change-Id: I29c55256e74456515aaeb098e2e0e3475697a466
diff --git a/drivers/nxp/ddr/phy-gen2/phy.c b/drivers/nxp/ddr/phy-gen2/phy.c
index b880569..e914ddb 100644
--- a/drivers/nxp/ddr/phy-gen2/phy.c
+++ b/drivers/nxp/ddr/phy-gen2/phy.c
@@ -371,7 +371,12 @@
#ifdef NXP_WARM_BOOT
int save_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_store,
- uint32_t num_of_phy, int train2d)
+ uint32_t num_of_phy, int train2d
+#ifdef NXP_APPLY_MAX_CDD
+ , struct ddr_ctrl_reg_values *ddrctrl_regs
+#endif
+ )
+
{
uint16_t *phy = NULL, value = 0x0;
uint32_t size = 1U, num_of_regs = 1U, phy_store = 0U;
@@ -438,6 +443,15 @@
ret = xspi_write(phy_store, training_2D_values,
size);
}
+
+#ifdef NXP_APPLY_MAX_CDD
+ /* Save DDR control register Timing CFG 0 and 4 */
+ phy_store += size;
+ size = sizeof(ddrctrl_regs);
+ if (ret != 0) {
+ ret = xspi_write(phy_store, ddrctrl_regs, size);
+ }
+#endif
/* Disable clocks in case they were disabled. */
phy_io_write16(phy, t_drtub |
csr_ucclk_hclk_enables_addr, 0x0);
@@ -453,7 +467,11 @@
}
int restore_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_restore,
- uint32_t num_of_phy, int train2d)
+ uint32_t num_of_phy, int train2d
+#ifdef NXP_APPLY_MAX_CDD
+ , struct ddr_ctrl_reg_values *ddrctrl_regs
+#endif
+ )
{
uint16_t *phy = NULL;
uint32_t size = 1U, num_of_regs = 1U, phy_store = 0U;
@@ -518,6 +536,11 @@
#endif
}
}
+#ifdef NXP_APPLY_MAX_CDD
+ phy_store = phy_store + size;
+ size = sizeof(ddrctrl_regs);
+ ret = xspi_read(phy_store, (uint32_t *)ddrctrl_regs, size);
+#endif
/* Disable clocks in case they were disabled. */
phy_io_write16(phy, t_drtub |
csr_ucclk_hclk_enables_addr, 0x0);
@@ -2454,6 +2477,9 @@
__unused const soc_info_t *soc_info;
#ifdef NXP_APPLY_MAX_CDD
unsigned int tcfg0, tcfg4, rank;
+#ifdef NXP_WARM_BOOT
+ struct ddr_ctrl_reg_values ddrctrl_regs;
+#endif
#endif
if (dimm_param == NULL) {
@@ -2558,11 +2584,19 @@
ret = restore_phy_training_values(priv->phy,
PHY_TRAINING_REGS_ON_FLASH,
priv->num_ctlrs,
- input.basic.train2d);
+ input.basic.train2d
+#ifdef NXP_APPLY_MAX_CDD
+ , &ddrctrl_regs
+#endif
+ );
if (ret != 0) {
ERROR("Restoring of training data failed %d\n", ret);
return ret;
}
+#ifdef NXP_APPLY_MAX_CDD
+ regs->timing_cfg[0] = ddrctrl_regs.timing_cfg0;
+ regs->timing_cfg[4] = ddrctrl_regs.timing_cfg4;
+#endif
} else {
#endif
/* Mapping IMG buffer firstly */
@@ -2625,12 +2659,20 @@
#ifdef NXP_WARM_BOOT
if (priv->warm_boot_flag != DDR_WRM_BOOT_NT_SUPPORTED &&
ret == 0) {
+#ifdef NXP_APPLY_MAX_CDD
+ ddrctrl_regs.timing_cfg0 = regs->timing_cfg[0];
+ ddrctrl_regs.timing_cfg4 = regs->timing_cfg[4];
+#endif
debug("save the phy training data\n");
//Save training data TBD
ret = save_phy_training_values(priv->phy,
PHY_TRAINING_REGS_ON_FLASH,
priv->num_ctlrs,
- input.basic.train2d);
+ input.basic.train2d
+#ifdef NXP_APPLY_MAX_CDD
+ , &ddrctrl_regs
+#endif
+ );
if (ret != 0) {
ERROR("Saving training data failed.");
ERROR("Warm boot will fail. Error=%d.\n", ret);
diff --git a/drivers/nxp/ddr/phy-gen2/phy.h b/drivers/nxp/ddr/phy-gen2/phy.h
index 15e80d1..5e80f36 100644
--- a/drivers/nxp/ddr/phy-gen2/phy.h
+++ b/drivers/nxp/ddr/phy-gen2/phy.h
@@ -11,11 +11,18 @@
/* To store sector size to be erase on flash*/
#define PHY_ERASE_SIZE F_SECTOR_ERASE_SZ
+/*Structure to save DDR controller timing register 0 and 4 values*/
+struct ddr_ctrl_reg_values {
+ uint32_t timing_cfg0;
+ uint32_t timing_cfg4;
+};
+
/*Structure to implement address-data map tuples to store PHY training values*/
struct phy_training_values {
uint32_t addr;
uint16_t data;
};
+
/* Saves PHY Training Register values after cold reset
*@param[in] phy_ptr array to store addresses of PHYs
*@param[in] address_to_store address to save PHY training register values
@@ -24,6 +31,8 @@
*to be saved
*@param[in] train2d flag to store whether 2D training registers are to
*be saved or not
+ *@param[in] ddrctrl_regs to save ddr controller registers in case
+ *NXP_APPLY_MAX_CDD is applied
*
*PHY training values will be stored on flash at contigous memory in the order:
*1D training registers, 2D training registers
@@ -31,9 +40,13 @@
*
*if train2d is false saving 2D training registers will be skipped
*/
-int save_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_store,
- uint32_t num_of_phy, int train2d);
+int save_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_store,
+ uint32_t num_of_phy, int train2d
+#ifdef NXP_APPLY_MAX_CDD
+ , struct ddr_ctrl_reg_values *ddrctrl_regs
+#endif
+ );
/*Restores PHY Training Register values after warm reset
*@param[in] phy_ptr array to store addresses of PHYs
*@param[in] address_to_store address to retrieve PHY training register
@@ -42,12 +55,17 @@
*to be restored
*@param[in] train2d flag to store whether 2D training registers are
*to be restored or not
- *
+ *@param[in] ddrctrl_regs to restore ddr controller registers in case
+ *NXP_APPLY_MAX_CDD is applied
*if train2d is false saving 2D training registers will be skipped
*/
int restore_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_restore,
- uint32_t num_of_phy, int train2d);
+ uint32_t num_of_phy, int train2d
+#ifdef NXP_APPLY_MAX_CDD
+ , struct ddr_ctrl_reg_values *ddrctrl_regs
+#endif
+ );
/*
* Address data tuples to store the PHY 1D