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
*