DDR_MR3
>;
+#ifdef DDR_PHY_CAL_SKIP
st,phy-cal = <
DDR_DX0DLLCR
DDR_DX0DQTR
DDR_DX3DQSTR
>;
+#endif
+
status = "okay";
};
};
MR3
- st,phy-cal : phy cal depending of calibration or tuning of DDR
+ This parameter is optional; when it is absent the built-in PHY
+ calibration is done.
for STM32MP15x: 12 values are requested in this order
DX0DLLCR
DX0DQTR
*/
set_reg(priv, REGPHY_REG, &config->p_reg);
set_reg(priv, REGPHY_TIMING, &config->p_timing);
- set_reg(priv, REGPHY_CAL, &config->p_cal);
+ if (config->p_cal_present)
+ set_reg(priv, REGPHY_CAL, &config->p_cal);
if (INTERACTIVE(STEP_PHY_INIT))
goto start;
wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL);
- debug("DDR DQS training : ");
+ if (config->p_cal_present) {
+ debug("DDR DQS training skipped.\n");
+ } else {
+ 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 */
/* warning : RVTRN is not supported by this PUBL */
- stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN);
+ stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN);
/* 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);
+ stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3,
+ config->c_reg.pwrctl);
+ } /* if (config->p_cal_present) */
/* enable uMCTL2 AXI port 0 and 1 */
setbits_le32(&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
struct stm32mp1_ddrphy_reg p_reg;
struct stm32mp1_ddrphy_timing p_timing;
struct stm32mp1_ddrphy_cal p_cal;
+ bool p_cal_present;
};
int stm32mp1_ddr_clk_enable(struct ddr_info *priv, u32 mem_speed);
"help displays help\n"
"info displays DDR information\n"
"info <param> <val> changes DDR information\n"
- " with <param> = step, name, size or speed\n"
+ " with <param> = step, name, size, speed or cal\n"
"freq displays the DDR PHY frequency in kHz\n"
"freq <freq> changes the DDR PHY frequency\n"
"param [type|reg] prints input parameters\n"
printf("name = %s\n", config->info.name);
printf("size = 0x%x\n", config->info.size);
printf("speed = %d kHz\n", config->info.speed);
+ printf("cal = %d\n", config->p_cal_present);
return;
}
}
return;
}
+ if (!strcmp(argv[1], "cal")) {
+ if (strict_strtoul(argv[2], 10, &value) < 0 ||
+ (value != 0 && value != 1)) {
+ printf("invalid value %s\n", argv[2]);
+ } else {
+ config->p_cal_present = value;
+ printf("cal = %d\n", config->p_cal_present);
+ }
+ return;
+ }
printf("argument %s invalid\n", argv[1]);
}
struct clk axidcg;
struct stm32mp1_ddr_config config;
-#define PARAM(x, y) \
- { x,\
- offsetof(struct stm32mp1_ddr_config, y),\
- sizeof(config.y) / sizeof(u32)}
+#define PARAM(x, y, z) \
+ { .name = x, \
+ .offset = offsetof(struct stm32mp1_ddr_config, y), \
+ .size = sizeof(config.y) / sizeof(u32), \
+ .present = z, \
+ }
-#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x)
-#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x)
+#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x, NULL)
+#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x, NULL)
+#define PHY_PARAM_OPT(x) PARAM("st,phy-"#x, p_##x, &config.p_##x##_present)
const struct {
const char *name; /* name in DT */
const u32 offset; /* offset in config struct */
const u32 size; /* size of parameters */
+ bool * const present; /* presence indication for opt */
} param[] = {
CTL_PARAM(reg),
CTL_PARAM(timing),
CTL_PARAM(perf),
PHY_PARAM(reg),
PHY_PARAM(timing),
- PHY_PARAM(cal)
+ PHY_PARAM_OPT(cal)
};
config.info.speed = dev_read_u32_default(dev, "st,mem-speed", 0);
param[idx].size);
debug("%s: %s[0x%x] = %d\n", __func__,
param[idx].name, param[idx].size, ret);
- if (ret) {
+ if (ret &&
+ (ret != -FDT_ERR_NOTFOUND || !param[idx].present)) {
pr_err("%s: Cannot read %s, error=%d\n",
__func__, param[idx].name, ret);
return -EINVAL;
}
+ if (param[idx].present) {
+ /* save presence of optional parameters */
+ *param[idx].present = true;
+ if (ret == -FDT_ERR_NOTFOUND) {
+ *param[idx].present = false;
+#ifdef CONFIG_STM32MP1_DDR_INTERACTIVE
+ /* reset values if used later */
+ memset((void *)((u32)&config +
+ param[idx].offset),
+ 0, param[idx].size * sizeof(u32));
+#endif
+ }
+ }
}
ret = clk_get_by_name(dev, "axidcg", &axidcg);