From 4831ba2903d886d233400423c2a425fde170b367 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 15 Nov 2021 15:32:28 +0100 Subject: stm32mp1: ram: add read valid training support Add the read data eye training = training for optimal read valid placement (RVTRN) when the built-in calibration is executed for LPDDR2 and LPDDR3. This training is supported on the PUBL integrated in the STM32MP15x DDR subsystem and it is not required for DDR3. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/ram/stm32mp1/stm32mp1_ddr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/ram/stm32mp1/stm32mp1_ddr.c') diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.c b/drivers/ram/stm32mp1/stm32mp1_ddr.c index 0457166b127..1f8422518b0 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ddr.c +++ b/drivers/ram/stm32mp1/stm32mp1_ddr.c @@ -826,8 +826,12 @@ start: */ /* 10. configure PUBL PIR register to specify which training step to run */ - /* warning : RVTRN is not supported by this PUBL */ - stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN); + /* RVTRN is excuted only on LPDDR2/LPDDR3 */ + if (config->c_reg.mstr & DDRCTRL_MSTR_DDR3) + pir = DDRPHYC_PIR_QSTRN; + else + pir = DDRPHYC_PIR_QSTRN | DDRPHYC_PIR_RVTRN; + stm32mp1_ddrphy_init(priv->phy, pir); /* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */ ddrphy_idone_wait(priv->phy); -- cgit v1.2.3 From 9819fe345cc9de8ab1ca8c53999b5d460a8d0e7d Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 15 Nov 2021 15:32:29 +0100 Subject: stm32mp1: ram: remove the support of calibration result The support of a predefined DDR PHY tuning result is removed for STM32MP1 driver because it is not needed at the supported frequency when built-in calibration is executed. The calibration parameters were provided in the device tree by the optional node "st,phy-cal", activated in ddr helper file by the compilation flag DDR_PHY_CAL_SKIP and filled with values generated by the CubeMX DDR utilities. This patch - updates the binding file to remove "st,phy-cal" support - updates the device trees and remove the associated defines - simplifies the STM32MP1 DDR driver and remove the support of the optional parameter "st,phy-cal" After this patch, the built-in calibration is always executed and the calibration registers are moved in the phy dynamic part; that allows manual tests. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/ram/stm32mp1/stm32mp1_ddr.c | 65 +++++++++++++------------------------ 1 file changed, 23 insertions(+), 42 deletions(-) (limited to 'drivers/ram/stm32mp1/stm32mp1_ddr.c') diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.c b/drivers/ram/stm32mp1/stm32mp1_ddr.c index 1f8422518b0..9d086601a4a 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ddr.c +++ b/drivers/ram/stm32mp1/stm32mp1_ddr.c @@ -68,7 +68,6 @@ struct reg_desc { #define DDRPHY_REG_REG_SIZE 11 /* st,phy-reg */ #define DDRPHY_REG_TIMING_SIZE 10 /* st,phy-timing */ -#define DDRPHY_REG_CAL_SIZE 12 /* st,phy-cal */ #define DDRCTL_REG_REG(x) DDRCTL_REG(x, stm32mp1_ddrctrl_reg) static const struct reg_desc ddr_reg[DDRCTL_REG_REG_SIZE] = { @@ -178,22 +177,6 @@ static const struct reg_desc ddrphy_timing[DDRPHY_REG_TIMING_SIZE] = { DDRPHY_REG_TIMING(mr3), }; -#define DDRPHY_REG_CAL(x) DDRPHY_REG(x, stm32mp1_ddrphy_cal) -static const struct reg_desc ddrphy_cal[DDRPHY_REG_CAL_SIZE] = { - DDRPHY_REG_CAL(dx0dllcr), - DDRPHY_REG_CAL(dx0dqtr), - DDRPHY_REG_CAL(dx0dqstr), - DDRPHY_REG_CAL(dx1dllcr), - DDRPHY_REG_CAL(dx1dqtr), - DDRPHY_REG_CAL(dx1dqstr), - DDRPHY_REG_CAL(dx2dllcr), - DDRPHY_REG_CAL(dx2dqtr), - DDRPHY_REG_CAL(dx2dqstr), - DDRPHY_REG_CAL(dx3dllcr), - DDRPHY_REG_CAL(dx3dqtr), - DDRPHY_REG_CAL(dx3dqstr), -}; - /************************************************************** * DYNAMIC REGISTERS: only used for debug purpose (read/modify) **************************************************************/ @@ -218,12 +201,24 @@ static const struct reg_desc ddrphy_dyn[] = { DDRPHY_REG_DYN(zq0sr1), DDRPHY_REG_DYN(dx0gsr0), DDRPHY_REG_DYN(dx0gsr1), + DDRPHY_REG_DYN(dx0dllcr), + DDRPHY_REG_DYN(dx0dqtr), + DDRPHY_REG_DYN(dx0dqstr), DDRPHY_REG_DYN(dx1gsr0), DDRPHY_REG_DYN(dx1gsr1), + DDRPHY_REG_DYN(dx1dllcr), + DDRPHY_REG_DYN(dx1dqtr), + DDRPHY_REG_DYN(dx1dqstr), DDRPHY_REG_DYN(dx2gsr0), DDRPHY_REG_DYN(dx2gsr1), + DDRPHY_REG_DYN(dx2dllcr), + DDRPHY_REG_DYN(dx2dqtr), + DDRPHY_REG_DYN(dx2dqstr), DDRPHY_REG_DYN(dx3gsr0), DDRPHY_REG_DYN(dx3gsr1), + DDRPHY_REG_DYN(dx3dllcr), + DDRPHY_REG_DYN(dx3dqtr), + DDRPHY_REG_DYN(dx3dqstr), }; #define DDRPHY_REG_DYN_SIZE ARRAY_SIZE(ddrphy_dyn) @@ -240,7 +235,6 @@ enum reg_type { REG_MAP, REGPHY_REG, REGPHY_TIMING, - REGPHY_CAL, #ifdef CONFIG_STM32MP1_DDR_INTERACTIVE /* dynamic registers => managed in driver or not changed, * can be dumped in interactive mode @@ -264,8 +258,6 @@ struct ddr_reg_info { enum base_type base; }; -#define DDRPHY_REG_CAL(x) DDRPHY_REG(x, stm32mp1_ddrphy_cal) - const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = { [REG_REG] = { "static", ddr_reg, DDRCTL_REG_REG_SIZE, DDR_BASE}, @@ -279,8 +271,6 @@ const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = { "static", ddrphy_reg, DDRPHY_REG_REG_SIZE, DDRPHY_BASE}, [REGPHY_TIMING] = { "timing", ddrphy_timing, DDRPHY_REG_TIMING_SIZE, DDRPHY_BASE}, -[REGPHY_CAL] = { - "cal", ddrphy_cal, DDRPHY_REG_CAL_SIZE, DDRPHY_BASE}, #ifdef CONFIG_STM32MP1_DDR_INTERACTIVE [REG_DYN] = { "dyn", ddr_dyn, DDR_REG_DYN_SIZE, DDR_BASE}, @@ -456,9 +446,6 @@ static u32 get_par_addr(const struct stm32mp1_ddr_config *config, case REGPHY_TIMING: par_addr = (u32)&config->p_timing; break; - case REGPHY_CAL: - par_addr = (u32)&config->p_cal; - break; case REG_DYN: case REGPHY_DYN: case REG_TYPE_NB: @@ -774,8 +761,6 @@ start: */ set_reg(priv, REGPHY_REG, &config->p_reg); set_reg(priv, REGPHY_TIMING, &config->p_timing); - if (config->p_cal_present) - set_reg(priv, REGPHY_CAL, &config->p_cal); if (INTERACTIVE(STEP_PHY_INIT)) goto start; @@ -810,36 +795,32 @@ start: wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); - if (config->p_cal_present) { - log_debug("DDR DQS training skipped.\n"); - } else { - log_debug("DDR DQS training : "); + log_debug("DDR DQS training : "); /* 8. Disable Auto refresh and power down by setting * - RFSHCTL3.dis_au_refresh = 1 * - PWRCTL.powerdown_en = 0 * - DFIMISC.dfiinit_complete_en = 0 */ - stm32mp1_refresh_disable(priv->ctl); + stm32mp1_refresh_disable(priv->ctl); /* 9. Program PUBL PGCR to enable refresh during training and rank to train * not done => keep the programed value in PGCR */ /* 10. configure PUBL PIR register to specify which training step to run */ - /* RVTRN is excuted only on LPDDR2/LPDDR3 */ - if (config->c_reg.mstr & DDRCTRL_MSTR_DDR3) - pir = DDRPHYC_PIR_QSTRN; - else - pir = DDRPHYC_PIR_QSTRN | DDRPHYC_PIR_RVTRN; - stm32mp1_ddrphy_init(priv->phy, pir); + /* RVTRN is excuted only on LPDDR2/LPDDR3 */ + if (config->c_reg.mstr & DDRCTRL_MSTR_DDR3) + pir = DDRPHYC_PIR_QSTRN; + else + pir = DDRPHYC_PIR_QSTRN | DDRPHYC_PIR_RVTRN; + stm32mp1_ddrphy_init(priv->phy, pir); /* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */ - ddrphy_idone_wait(priv->phy); + ddrphy_idone_wait(priv->phy); /* 12. set back registers in step 8 to the orginal values if desidered */ - stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3, - config->c_reg.pwrctl); - } /* if (config->p_cal_present) */ + stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3, + config->c_reg.pwrctl); /* enable uMCTL2 AXI port 0 and 1 */ setbits_le32(&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN); -- cgit v1.2.3 From b3c29dc9e5f0ed2bef4f20927a8c9bba4342a1cb Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 15 Nov 2021 15:32:30 +0100 Subject: stm32mp1: ram: remove tuning support Remove the DDR interactive command tuning, as the support of a predefined DDR PHY tuning is removed for STM32MP1 driver in SPL and in TF-A and the result of this tuning will be never used. Moreover this SW tuning procedure can failed on some hardware configuration (to many BIST errors and no convergence); it will be no more supported in the next delivery of the DDR utilities included in the CubeMX tool of STMicroelectronics. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- drivers/ram/stm32mp1/stm32mp1_ddr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/ram/stm32mp1/stm32mp1_ddr.c') diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.c b/drivers/ram/stm32mp1/stm32mp1_ddr.c index 9d086601a4a..4d78aa5cb13 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ddr.c +++ b/drivers/ram/stm32mp1/stm32mp1_ddr.c @@ -557,7 +557,7 @@ static void ddrphy_idone_wait(struct stm32mp1_ddrphy *phy) (u32)&phy->pgsr, pgsr, ret); } -void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, u32 pir) +static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, u32 pir) { pir |= DDRPHYC_PIR_INIT; writel(pir, &phy->pir); @@ -626,7 +626,7 @@ static void wait_operating_mode(struct ddr_info *priv, int mode) log_debug("[0x%08x] stat = 0x%08x\n", (u32)&priv->ctl->stat, stat); } -void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl) +static void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl) { start_sw_done(ctl); /* quasi-dynamic register update*/ @@ -637,8 +637,8 @@ void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl) wait_sw_done_ack(ctl); } -void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, - u32 rfshctl3, u32 pwrctl) +static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, + u32 rfshctl3, u32 pwrctl) { start_sw_done(ctl); if (!(rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH)) -- cgit v1.2.3