[PATCH 01/16] lib: fdtdec: Handle multiple memory nodes
Heinrich Schuchardt
xypron.glpk at gmx.de
Tue Jun 11 14:26:02 CEST 2024
On 22.05.24 17:34, Jiaxun Yang wrote:
> Current code only tries to fetch the first memory node found in
> fdt tree and determine memory banks from multiple reg properties.
>
> Linux do allow multiple memory nodes in devicetree, rework
%/do allow/allows/
It is not Linux that allows it but
Devicetree Specification, Release v0.4
https://github.com/devicetree-org/devicetree-specification/releases/download/v0.4/devicetree-specification-v0.4.pdf
> fdtdec_setup_mem_size_base_lowest and fdtdec_setup_memory_banksize
> to iterate over all memory nodes.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang at flygoat.com>
> ---
> lib/fdtdec.c | 137 ++++++++++++++++++++++++++++++++++++-----------------------
> 1 file changed, 83 insertions(+), 54 deletions(-)
>
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index b2c59ab3818b..403b363043d6 100644
> --- a/lib/fdtdec.c
> +++ b/lib/fdtdec.c
> @@ -1075,90 +1075,119 @@ ofnode get_next_memory_node(ofnode mem)
> return mem;
> }
>
> +static void sort_memory_banks(int num)
> +{
> + int i, j;
> + phys_addr_t tmp_start;
> + phys_size_t tmp_size;
> + struct bd_info *bd = gd->bd;
> +
> + for (i = 0; i < num - 1; i++) {
> + for (j = i + 1; j < num; j++) {
> + if (bd->bi_dram[i].start > bd->bi_dram[j].start) {
> + tmp_start = bd->bi_dram[i].start;
> + tmp_size = bd->bi_dram[i].size;
> + bd->bi_dram[i].start = bd->bi_dram[j].start;
> + bd->bi_dram[i].size = bd->bi_dram[j].size;
> + bd->bi_dram[j].start = tmp_start;
> + bd->bi_dram[j].size = tmp_size;
> + }
> + }
> + }
Please, use qsort() instead.
> +}
> +
> int fdtdec_setup_memory_banksize(void)
> {
> - int bank, ret, reg = 0;
> - struct resource res;
> + int bank = 0;
> ofnode mem = ofnode_null();
>
> - mem = get_next_memory_node(mem);
> - if (!ofnode_valid(mem)) {
> - debug("%s: Missing /memory node\n", __func__);
> - return -EINVAL;
> - }
> + while (true) {
> + struct resource res;
> + int reg = 0;
>
> - for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
> - ret = ofnode_read_resource(mem, reg++, &res);
> - if (ret < 0) {
> - reg = 0;
> - mem = get_next_memory_node(mem);
> - if (!ofnode_valid(mem))
> - break;
> + mem = get_next_memory_node(mem);
> + if (!ofnode_valid(mem))
> + break;
>
> - ret = ofnode_read_resource(mem, reg++, &res);
> + while (true) {
> + int ret = ofnode_read_resource(mem, reg, &res);
Please, leave a blank line after declarations.
> if (ret < 0)
> break;
> - }
>
> - if (ret != 0)
> - return -EINVAL;
> + if (bank >= CONFIG_VAL(NR_DRAM_BANKS))
> + goto too_may_memory_banks;
>
> - gd->bd->bi_dram[bank].start = (phys_addr_t)res.start;
The conversion is superfluous.
> - gd->bd->bi_dram[bank].size =
> - (phys_size_t)(res.end - res.start + 1);
> + gd->bd->bi_dram[bank].start = (phys_addr_t)res.start;
> + gd->bd->bi_dram[bank].size =
> + (phys_size_t)(res.end - res.start + 1);
>
> - debug("%s: DRAM Bank #%d: start = 0x%llx, size = 0x%llx\n",
> - __func__, bank,
> - (unsigned long long)gd->bd->bi_dram[bank].start,
> - (unsigned long long)gd->bd->bi_dram[bank].size);
> + log_debug("%s: DRAM Bank #%d %s.%d: start = 0x%llx, size = 0x%llx\n",
> + __func__, bank, ofnode_get_name(mem), reg,
> + (unsigned long long)gd->bd->bi_dram[bank].start,
> + (unsigned long long)gd->bd->bi_dram[bank].size);
> + reg++;
> + bank++;
> + }
> }
>
> + if (!bank) {
> + log_warning("%s: Missing /memory node\n", __func__);
> + return -EINVAL;
> + }
> +
> + sort_memory_banks(bank);
> +
> return 0;
> +
> +too_may_memory_banks:
> + log_warning("%s: Too many memory banks\n", __func__);
> + return -EINVAL;
> }
>
> int fdtdec_setup_mem_size_base_lowest(void)
> {
> - int bank, ret, reg = 0;
> - struct resource res;
> - unsigned long base;
> - phys_size_t size;
> + int bank = 0;
> ofnode mem = ofnode_null();
> + __maybe_unused const char *final_name;
> + __maybe_unused int final_reg;
'__maybe_unused' is superfluous.
>
> gd->ram_base = (unsigned long)~0;
gd->ram_base = ULONG_MAX;
>
> - mem = get_next_memory_node(mem);
> - if (!ofnode_valid(mem)) {
> - debug("%s: Missing /memory node\n", __func__);
> - return -EINVAL;
> - }
> + while (true) {
> + struct resource res;
> + phys_size_t base, size;
> + int reg = 0;
>
> - for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
> - ret = ofnode_read_resource(mem, reg++, &res);
> - if (ret < 0) {
> - reg = 0;
> - mem = get_next_memory_node(mem);
> - if (!ofnode_valid(mem))
> - break;
> + mem = get_next_memory_node(mem);
> + if (!ofnode_valid(mem))
> + break;
>
> - ret = ofnode_read_resource(mem, reg++, &res);
> + while (true) {
> + int ret = ofnode_read_resource(mem, reg, &res);
> if (ret < 0)
> break;
> + base = res.start;
> + size = res.end - res.start + 1;
> + if (gd->ram_base > base && size) {
> + gd->ram_base = base;
> + gd->ram_size = size;
> + final_name = ofnode_get_name(mem);
> + final_reg = reg;
> + }
> + reg++;
> + bank++;
> }
> + }
>
> - if (ret != 0)
> - return -EINVAL;
> -
> - base = (unsigned long)res.start;
> - size = (phys_size_t)(res.end - res.start + 1);
> -
> - if (gd->ram_base > base && size) {
> - gd->ram_base = base;
> - gd->ram_size = size;
> - debug("%s: Initial DRAM base %lx size %lx\n",
> - __func__, base, (unsigned long)size);
> - }
> + if (!bank) {
> + log_warning("%s: Missing /memory node\n", __func__);
> + return -EINVAL;
> }
>
> + log_debug("%s: Initial DRAM %s.%d: base %lx size %lx\n",
> + __func__, final_name, final_reg,
> + (ulong)gd->ram_base, (ulong)gd->ram_size);
ram_base is already defined as unsigned long.
include/asm-generic/global_data.h:154:
unsigned long ram_base;
Best regards
Heinrich
> +
> return 0;
> }
>
>
More information about the U-Boot
mailing list