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