#include <common.h>
#include <clk.h>
#include <dm.h>
+#include <init.h>
+#include <log.h>
#include <ram.h>
#include <regmap.h>
#include <syscon.h>
"ddrphyc" /* LAST clock => used for get_rate() */
};
-int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed)
+int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed)
{
unsigned long ddrphy_clk;
unsigned long ddr_clk;
struct clk clk;
int ret;
- int idx;
+ unsigned int idx;
for (idx = 0; idx < ARRAY_SIZE(clkname); idx++) {
ret = clk_get_by_name(priv->dev, clkname[idx], &clk);
priv->clk = clk;
ddrphy_clk = clk_get_rate(&priv->clk);
- debug("DDR: mem_speed (%d MHz), RCC %d MHz\n",
- mem_speed, (u32)(ddrphy_clk / 1000 / 1000));
+ debug("DDR: mem_speed (%d kHz), RCC %d kHz\n",
+ mem_speed, (u32)(ddrphy_clk / 1000));
/* max 10% frequency delta */
- ddr_clk = abs(ddrphy_clk - mem_speed * 1000 * 1000);
- if (ddr_clk > (mem_speed * 1000 * 100)) {
- pr_err("DDR expected freq %d MHz, current is %d MHz\n",
- mem_speed, (u32)(ddrphy_clk / 1000 / 1000));
+ ddr_clk = abs(ddrphy_clk - mem_speed * 1000);
+ if (ddr_clk > (mem_speed * 100)) {
+ pr_err("DDR expected freq %d kHz, current is %d kHz\n",
+ mem_speed, (u32)(ddrphy_clk / 1000));
return -EINVAL;
}
return 0;
}
+__weak int board_stm32mp1_ddr_config_name_match(struct udevice *dev,
+ const char *name)
+{
+ return 0; /* Always match */
+}
+
+static ofnode stm32mp1_ddr_get_ofnode(struct udevice *dev)
+{
+ const char *name;
+ ofnode node;
+
+ dev_for_each_subnode(node, dev) {
+ name = ofnode_get_property(node, "compatible", NULL);
+
+ if (!board_stm32mp1_ddr_config_name_match(dev, name))
+ return node;
+ }
+
+ return dev_ofnode(dev);
+}
+
static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev)
{
struct ddr_info *priv = dev_get_priv(dev);
- int ret, idx;
+ int ret;
+ unsigned int idx;
struct clk axidcg;
struct stm32mp1_ddr_config config;
+ ofnode node = stm32mp1_ddr_get_ofnode(dev);
-#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);
- config.info.size = dev_read_u32_default(dev, "st,mem-size", 0);
- config.info.name = dev_read_string(dev, "st,mem-name");
+ config.info.speed = ofnode_read_u32_default(node, "st,mem-speed", 0);
+ config.info.size = ofnode_read_u32_default(node, "st,mem-size", 0);
+ config.info.name = ofnode_read_string(node, "st,mem-name");
if (!config.info.name) {
debug("%s: no st,mem-name\n", __func__);
return -EINVAL;
printf("RAM: %s\n", config.info.name);
for (idx = 0; idx < ARRAY_SIZE(param); idx++) {
- ret = dev_read_u32_array(dev, param[idx].name,
+ ret = ofnode_read_u32_array(node, param[idx].name,
(void *)((u32)&config +
param[idx].offset),
param[idx].size);
debug("%s: %s[0x%x] = %d\n", __func__,
param[idx].name, param[idx].size, ret);
- if (ret) {
- pr_err("%s: Cannot read %s\n",
- __func__, param[idx].name);
+ 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);
priv->info.base = STM32_DDR_BASE;
-#if !defined(CONFIG_STM32MP1_TRUSTED) && \
+#if !defined(CONFIG_TFABOOT) && \
(!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
priv->info.size = 0;
return stm32mp1_ddr_setup(dev);
#else
- priv->info.size = dev_read_u32_default(dev, "st,mem-size", 0);
+ ofnode node = stm32mp1_ddr_get_ofnode(dev);
+ priv->info.size = ofnode_read_u32_default(node, "st,mem-size", 0);
return 0;
#endif
}
.of_match = stm32mp1_ddr_ids,
.ops = &stm32mp1_ddr_ops,
.probe = stm32mp1_ddr_probe,
- .priv_auto_alloc_size = sizeof(struct ddr_info),
+ .priv_auto = sizeof(struct ddr_info),
};