From: Przemyslaw Marczak Date: Mon, 28 Jul 2014 09:16:47 +0000 (+0200) Subject: fdtdec: add function: fdtdec_decode_memory() X-Git-Tag: accepted/tizen/unified/20170418.072224~94 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8fe5750395ee38927a34b8817c6f1d2246101216;p=platform%2Fkernel%2Fu-boot.git fdtdec: add function: fdtdec_decode_memory() This function can be used for decode memory node from device tree file. Currently supports decoding of a single memory node with a multiple ranges specified by the reg property with size of address and size cells specified in a root node. Function parameters: - blob: ptr to device tree - start: ptr to banks start address array - size: ptr to banks size array - max_banks: max number of banks to fill Two of args: start or size can be NULL e.g. if only each bank size is needed. Sample use case: memory { device_type = "memory"; reg = <0x40000000 ... 0x10000000 ... 0x50000000 ... 0x10000000 ... ... ... ... ...>; }; Change-Id: I2f3defb89cf62d81377fb7882dbbae79b4472af2 Signed-off-by: Przemyslaw Marczak --- diff --git a/include/fdtdec.h b/include/fdtdec.h index d074478..86a5bf4 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -818,6 +818,34 @@ enum fmap_hash_t { FMAP_HASH_SHA256, }; +/** + * fdt_decode_memory: Find a memory node, fill start, size arrays, + * and return filled banks number. + * + * @blob: ptr to device tree + * @start: ptr to banks start address array + * @size: ptr to banks size array + * @max_banks: max number of banks to fill + * + * @Returns number of filled banks or 0 on error. + * + * To get the size of each memory bank only, the @start pointer can be NULL. + * The same with bank start address if the @size pointer is NULL. + * + * Currently supports a single memory node with multiple ranges + * specified by the reg property with address and size cells size + * specified in a root node. + * memory { + * device_type = "memory"; + * reg = <0x40000000 0x10000000 ... + * 0x50000000 0x10000000 ... + * ... ... >; + * }; + * +*/ +int fdtdec_decode_memory(const void *blob, uint64_t start[], uint64_t size[], + int max_banks); + /* A flash map entry, containing an offset and length */ struct fmap_entry { uint32_t offset; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 4044d1b..1018d87 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -13,6 +13,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -932,6 +933,112 @@ int fdtdec_decode_region(const void *blob, int node, const char *prop_name, return 0; } +int fdtdec_decode_memory(const void *blob, uint64_t start[], + uint64_t size[], int max_banks) +{ + const fdt32_t *reg; + const fdt32_t *cell; + uint64_t val; + int node_off; + int reg_len, reg_cells; + int addr_len, addr_cells, size_len, size_cells; + int bank_len, bank_cells, bank_count, reg_banks; + int cell_off; + int err, i; + + debug("# DBG: start: %s\n", __func__); + + if (!start && !size) + return 0; + + /* Get parent address bytes len */ + cell = fdt_getprop(blob, 0, "#address-cells", NULL); + if (cell) + addr_cells = fdt32_to_cpu(*cell); + else + addr_cells = 1; + + cell = fdt_getprop(blob, 0, "#size-cells", NULL); + if (cell) + size_cells = fdt32_to_cpu(*cell); + else + size_cells = 1; + + bank_cells = addr_cells + size_cells; + + /* Get len in bytes */ + addr_len = addr_cells << 2; + size_len = size_cells << 2; + bank_len = addr_len + size_len; + + debug("# DBG: parent: addr_cells: %x size_cells: %x\n", addr_cells, + size_cells); + debug("# DBG: parent: addr_len:%x [B] size_len:%x [B]\n", addr_len, + size_len); + debug("# DBG: bank: len: %x [B] cells: %x\n", bank_len, bank_cells); + + /* Check if memory node exists */ + node_off = fdt_path_offset(blob, "/memory"); + debug("# DBG: fdt path offset: %d\n", node_off); + + if (node_off < 0) { + debug("# DBG: fdt path not found: error: %x\n", node_off); + return 0; + } + + reg = (uint32_t *)fdt_getprop(blob, node_off, "reg", ®_len); + if (!reg) { + debug("# DBG: fdt prop: reg - not found.\n"); + return 0; + } + reg_banks = reg_len / bank_len; + reg_cells = reg_banks * bank_cells; + debug("# DBG: Reg: len: %d [B]; cells: %d; banks:%d\n", reg_len, + reg_cells, + reg_banks); + + if (reg_banks > max_banks) { + bank_count = max_banks; + debug("# DBG: Warning! Can init only:%d banks!", bank_count); + } else { + bank_count = reg_banks; + debug("# DBG: Warning! Found:%d banks!", bank_count); + } + + debug("\n# DBG: setting banks info:\n"); + + cell_off = 0; + for (i = 0; i < bank_count; i++) { + if (start) { + err = fdt_read_prop(reg, reg_cells, cell_off, &val, + addr_cells); + if (err) + return 0; + + start[i] = val; + debug("# DBG: start: %#llx\n", val); + } + + cell_off += addr_cells; + + if (size) { + err = fdt_read_prop(reg, reg_cells, cell_off, &val, + size_cells); + if (err) + return 0; + + size[i] = val; + debug("# DBG: size: %#llx\n", val); + } + + cell_off += size_cells; + } + + debug("# DBG: %s: finished\n", __func__); + + return i; +} + /** * Read a flash entry from the fdt *