fdt: add memory bank decoding functions for board setup
authorNathan Rossi <nathan@nathanrossi.com>
Sun, 18 Dec 2016 14:03:34 +0000 (00:03 +1000)
committerMichal Simek <michal.simek@xilinx.com>
Tue, 20 Dec 2016 08:15:28 +0000 (09:15 +0100)
Add two functions for use by board implementations to decode the memory
banks of the /memory node so as to populate the global data with
ram_size and board info for memory banks.

The fdtdec_setup_memory_size() function decodes the first memory bank
and sets up the gd->ram_size with the size of the memory bank. This
function should be called from the boards dram_init().

The fdtdec_setup_memory_banksize() function decode the memory banks
(up to the CONFIG_NR_DRAM_BANKS) and populates the base address and size
into the gd->bd->bi_dram array of banks. This function should be called
from the boards dram_init_banksize().

Signed-off-by: Nathan Rossi <nathan@nathanrossi.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Michal Simek <monstr@monstr.eu>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
include/fdtdec.h
lib/fdtdec.c

index 27887c8c21ad7de8b9c29e1c7febd9f3a70bed8b..d074478f1415e4c9ca73b324ef7a856dbe1c93f6 100644 (file)
@@ -976,6 +976,40 @@ struct display_timing {
  */
 int fdtdec_decode_display_timing(const void *blob, int node, int index,
                                 struct display_timing *config);
+
+/**
+ * fdtdec_setup_memory_size() - decode and setup gd->ram_size
+ *
+ * Decode the /memory 'reg' property to determine the size of the first memory
+ * bank, populate the global data with the size of the first bank of memory.
+ *
+ * This function should be called from a boards dram_init(). This helper
+ * function allows for boards to query the device tree for DRAM size instead of
+ * hard coding the value in the case where the memory size cannot be detected
+ * automatically.
+ *
+ * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or
+ * invalid
+ */
+int fdtdec_setup_memory_size(void);
+
+/**
+ * fdtdec_setup_memory_banksize() - decode and populate gd->bd->bi_dram
+ *
+ * Decode the /memory 'reg' property to determine the address and size of the
+ * memory banks. Use this data to populate the global data board info with the
+ * phys address and size of memory banks.
+ *
+ * This function should be called from a boards dram_init_banksize(). This
+ * helper function allows for boards to query the device tree for memory bank
+ * information instead of hard coding the information in cases where it cannot
+ * be detected automatically.
+ *
+ * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or
+ * invalid
+ */
+int fdtdec_setup_memory_banksize(void);
+
 /**
  * Set up the device tree ready for use
  */
index 4e619c49a2ffb2332a06c62906753b3b2eba3262..81f47ef2c7f4cf0b6ea6966a9455518fd89c5e89 100644 (file)
@@ -1174,6 +1174,62 @@ int fdtdec_decode_display_timing(const void *blob, int parent, int index,
        return ret;
 }
 
+int fdtdec_setup_memory_size(void)
+{
+       int ret, mem;
+       struct fdt_resource res;
+
+       mem = fdt_path_offset(gd->fdt_blob, "/memory");
+       if (mem < 0) {
+               debug("%s: Missing /memory node\n", __func__);
+               return -EINVAL;
+       }
+
+       ret = fdt_get_resource(gd->fdt_blob, mem, "reg", 0, &res);
+       if (ret != 0) {
+               debug("%s: Unable to decode first memory bank\n", __func__);
+               return -EINVAL;
+       }
+
+       gd->ram_size = (phys_size_t)(res.end - res.start + 1);
+       debug("%s: Initial DRAM size %llx\n", __func__, (u64)gd->ram_size);
+
+       return 0;
+}
+
+#if defined(CONFIG_NR_DRAM_BANKS)
+int fdtdec_setup_memory_banksize(void)
+{
+       int bank, ret, mem;
+       struct fdt_resource res;
+
+       mem = fdt_path_offset(gd->fdt_blob, "/memory");
+       if (mem < 0) {
+               debug("%s: Missing /memory node\n", __func__);
+               return -EINVAL;
+       }
+
+       for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
+               ret = fdt_get_resource(gd->fdt_blob, mem, "reg", bank, &res);
+               if (ret == -FDT_ERR_NOTFOUND)
+                       break;
+               if (ret != 0)
+                       return -EINVAL;
+
+               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);
+       }
+
+       return 0;
+}
+#endif
+
 int fdtdec_setup(void)
 {
 #if CONFIG_IS_ENABLED(OF_CONTROL)