]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
ram: stm32mp1: the property st, phy-cal becomes optional
authorPatrick Delaunay <patrick.delaunay@st.com>
Fri, 6 Mar 2020 10:14:11 +0000 (11:14 +0100)
committerPatrick Delaunay <patrick.delaunay@st.com>
Tue, 24 Mar 2020 13:23:30 +0000 (14:23 +0100)
This parameter "st,phy-cal" becomes optional and when it is
absent the built-in PHY calibration is done.

It is the case in the helper dtsi file "stm32mp15-ddr.dtsi"
except if DDR_PHY_CAL_SKIP is defined.

This patch also impact the ddr interactive mode
- the registers of the param 'phy.cal' are initialized to 0 when
  "st,phy-cal" is not present in device tree (default behavior when
  DDR_PHY_CAL_SKIP is not activated)
- the info 'cal' field can be use to change the calibration behavior
  - cal=1 => use param phy.cal to initialize the PHY, built-in training
             is skipped
  - cal=0 => param phy.cal is absent, built-in training is used (default)

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Acked-by: Patrice Chotard <patrice.chotard@st.com>
arch/arm/dts/stm32mp15-ddr.dtsi
doc/device-tree-bindings/memory-controllers/st,stm32mp1-ddr.txt
drivers/ram/stm32mp1/stm32mp1_ddr.c
drivers/ram/stm32mp1/stm32mp1_ddr.h
drivers/ram/stm32mp1/stm32mp1_interactive.c
drivers/ram/stm32mp1/stm32mp1_ram.c

index 38f29bb789e873cabbefbd61484293af6f619e5c..8b20b5e17357f33cd6396e6922661db06e3c88af 100644 (file)
                                DDR_MR3
                        >;
 
+#ifdef DDR_PHY_CAL_SKIP
                        st,phy-cal = <
                                DDR_DX0DLLCR
                                DDR_DX0DQTR
                                DDR_DX3DQSTR
                        >;
 
+#endif
+
                        status = "okay";
                };
        };
index ee708ce92c785f64d2b65b6e754f5c14d16b6f66..ac6a7df4327d15013b441add9df9ef5c88d52dba 100644 (file)
@@ -129,6 +129,8 @@ phyc attributes:
                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
index b9300dd6d164a3eb248906a4256b5b4cde39ae70..11b14ae6520f911268297eb9f1dab4c11395372c 100644 (file)
@@ -769,7 +769,8 @@ start:
  */
        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;
@@ -804,13 +805,16 @@ 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
@@ -818,14 +822,15 @@ 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);
+               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);
index 52b748f3ca210935dbbb258351df67c7828ec179..4998f0443944e2270323d64796732ece1b74ced3 100644 (file)
@@ -170,6 +170,7 @@ struct stm32mp1_ddr_config {
        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);
index cedf92cb5f10e334f7d8a29270c01454b39b64da..805c9ddaadc3760c85a93024c9d91dfc2598aabb 100644 (file)
@@ -106,7 +106,7 @@ static void stm32mp1_do_usage(void)
                "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"
@@ -160,6 +160,7 @@ static void stm32mp1_do_info(struct ddr_info *priv,
                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;
        }
 
@@ -208,6 +209,16 @@ static void stm32mp1_do_info(struct ddr_info *priv,
                }
                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]);
 }
 
index eb78f1198d727dceafb0322f9651d8ba96cf713a..b1e593f86bd6819cc4a13e1696772363149eebae 100644 (file)
@@ -65,18 +65,22 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
        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),
@@ -84,7 +88,7 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
                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);
@@ -103,11 +107,25 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
                                         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);