From patchwork Wed Apr 22 11:18:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 238282 List-Id: U-Boot discussion From: marex at denx.de (Marek Vasut) Date: Wed, 22 Apr 2020 13:18:12 +0200 Subject: [PATCH V3 4/6] ram: stm32mp1: Add support for multiple configs In-Reply-To: <20200422111814.121060-1-marex@denx.de> References: <20200422111814.121060-1-marex@denx.de> Message-ID: <20200422111814.121060-4-marex@denx.de> Add support for multiple DRAM configuration subnodes, while retaining the support for a single flat DRAM configuration node. This is useful on systems which can be manufactured in multiple configurations and where the DRAM configuration can be determined at runtime. The code is augmented by a function which can be overridden on board level, allowing a match on the configuration node name, very much like the fitImage configuration node name matching works. The default match is on the single top-level DRAM configuration, if matching on subnodes is required, then this board_stm32mp1_ddr_config_name_match() must be overridden. Signed-off-by: Marek Vasut Cc: Manivannan Sadhasivam Cc: Patrick Delaunay Cc: Patrice Chotard Reviewed-by: Patrick Delaunay --- V2: Match on compatible string V3: Rework the stm32mp1_ddr_get_ofnode() function --- drivers/ram/stm32mp1/stm32mp1_ram.c | 33 ++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/ram/stm32mp1/stm32mp1_ram.c b/drivers/ram/stm32mp1/stm32mp1_ram.c index 7b1adc5b24..8bcd861261 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ram.c +++ b/drivers/ram/stm32mp1/stm32mp1_ram.c @@ -57,6 +57,27 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) 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); @@ -64,6 +85,7 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev) unsigned int idx; struct clk axidcg; struct stm32mp1_ddr_config config; + ofnode node = stm32mp1_ddr_get_ofnode(dev); #define PARAM(x, y, z) \ { .name = x, \ @@ -91,9 +113,9 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev) 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; @@ -101,7 +123,7 @@ static __maybe_unused int stm32mp1_ddr_setup(struct udevice *dev) 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); @@ -182,7 +204,8 @@ static int stm32mp1_ddr_probe(struct udevice *dev) 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 }