platform: msm_shared: Support 64 bit addresses for DDR partitions.

Support 64 bit addresses for DDR partitions. Add a new struct to save
device tree related parameters.

Change-Id: I713f8863bf5681915764f1026b3707be56cab097
diff --git a/platform/msm_shared/dev_tree.c b/platform/msm_shared/dev_tree.c
index 01c0303..ef81891 100644
--- a/platform/msm_shared/dev_tree.c
+++ b/platform/msm_shared/dev_tree.c
@@ -45,6 +45,8 @@
 	uint32_t size;
 };
 
+static struct dt_mem_node_info mem_node;
+
 static int platform_dt_match(struct dt_entry *cur_dt_entry, uint32_t target_variant_id, uint32_t subtype_mask);
 extern int target_is_emmc_boot(void);
 extern uint32_t target_dev_tree_mem(void *fdt, uint32_t memory_node_offset);
@@ -551,7 +553,6 @@
 				ret);
 	}
 
-
 	ret = fdt_appendprop_u32(fdt, offset, "reg", size);
 
 	if (ret)
@@ -563,37 +564,172 @@
 	return ret;
 }
 
-/* Function to add the subsequent RAM partition info to the device tree. */
-int dev_tree_add_mem_info(void *fdt, uint32_t offset, uint32_t addr, uint32_t size)
+static int dev_tree_query_memory_cell_sizes(void *fdt, struct dt_mem_node_info *mem_node, uint32_t mem_node_offset)
 {
-	static int mem_info_cnt = 0;
-	int ret;
+	int      len;
+	uint32_t *valp;
+	int      ret;
+	uint32_t offset;
 
-	if (!mem_info_cnt)
+	mem_node->offset = mem_node_offset;
+
+	/* Get offset of the root node */
+	ret = fdt_path_offset(fdt, "/");
+	if (ret < 0)
+	{
+		dprintf(CRITICAL, "Could not find memory node.\n");
+		return ret;
+	}
+
+	offset = ret;
+
+	/* Find the #address-cells size. */
+	valp = (uint32_t*)fdt_getprop(fdt, offset, "#address-cells", &len);
+	if (len <= 0)
+	{
+		if (len == -FDT_ERR_NOTFOUND)
+		{
+			/* Property not found.
+			* Assume standard sizes.
+			*/
+			mem_node->addr_cell_size = 2;
+			dprintf(CRITICAL, "Using default #addr_cell_size: %u\n", mem_node->addr_cell_size);
+		}
+		else
+		{
+			dprintf(CRITICAL, "Error finding the #address-cells property\n");
+			return len;
+		}
+	}
+	else
+		mem_node->addr_cell_size = fdt32_to_cpu(*valp);
+
+	/* Find the #size-cells size. */
+	valp = (uint32_t*)fdt_getprop(fdt, offset, "#size-cells", &len);
+	if (len <= 0)
+	{
+		if (len == -FDT_ERR_NOTFOUND)
+		{
+			/* Property not found.
+			* Assume standard sizes.
+			*/
+			mem_node->size_cell_size = 1;
+			dprintf(CRITICAL, "Using default #size_cell_size: %u\n", mem_node->size_cell_size);
+		}
+		else
+		{
+			dprintf(CRITICAL, "Error finding the #size-cells property\n");
+			return len;
+		}
+	}
+	else
+		mem_node->size_cell_size = fdt32_to_cpu(*valp);
+
+	return 0;
+}
+
+static void dev_tree_update_memory_node(uint32_t offset)
+{
+	mem_node.offset = offset;
+	mem_node.addr_cell_size = 1;
+	mem_node.size_cell_size = 1;
+}
+
+/* Function to add the subsequent RAM partition info to the device tree. */
+int dev_tree_add_mem_info(void *fdt, uint32_t offset, uint64_t addr, uint64_t size)
+{
+	int ret = 0;
+
+	if(smem_get_ram_ptable_version() >= 1)
+	{
+		ret = dev_tree_query_memory_cell_sizes(fdt, &mem_node, offset);
+		if (ret < 0)
+		{
+			dprintf(CRITICAL, "Could not find #address-cells and #size-cells properties: ret %d\n", ret);
+			return ret;
+		}
+
+	}
+	else
+	{
+		dev_tree_update_memory_node(offset);
+	}
+
+	if (!(mem_node.mem_info_cnt))
 	{
 		/* Replace any other reg prop in the memory node. */
-		ret = fdt_setprop_u32(fdt, offset, "reg", addr);
-		mem_info_cnt = 1;
+
+		/* cell_size is the number of 32 bit words used to represent an address/length in the device tree.
+		 * memory node in DT can be either 32-bit(cell-size = 1) or 64-bit(cell-size = 2).So when updating
+		 * the memory node in the device tree, we write one word or two words based on cell_size = 1 or 2.
+		 */
+
+		if(mem_node.addr_cell_size == 2)
+		{
+			ret = fdt_setprop_u32(fdt, mem_node.offset, "reg", addr >> 32);
+			if(ret)
+			{
+				dprintf(CRITICAL, "ERROR: Could not set prop reg for memory node\n");
+				return ret;
+			}
+
+			ret = fdt_appendprop_u32(fdt, mem_node.offset, "reg", (uint32_t)addr);
+			if(ret)
+			{
+				dprintf(CRITICAL, "ERROR: Could not append prop reg for memory node\n");
+				return ret;
+			}
+		}
+		else
+		{
+			ret = fdt_setprop_u32(fdt, mem_node.offset, "reg", (uint32_t)addr);
+			if(ret)
+			{
+				dprintf(CRITICAL, "ERROR: Could not set prop reg for memory node\n");
+				return ret;
+			}
+		}
+
+		mem_node.mem_info_cnt = 1;
 	}
 	else
 	{
 		/* Append the mem info to the reg prop for subsequent nodes.  */
-		ret = fdt_appendprop_u32(fdt, offset, "reg", addr);
+		if(mem_node.addr_cell_size == 2)
+		{
+			ret = fdt_appendprop_u32(fdt, mem_node.offset, "reg", addr >> 32);
+			if(ret)
+			{
+				dprintf(CRITICAL, "ERROR: Could not append prop reg for memory node\n");
+				return ret;
+			}
+		}
+
+		ret = fdt_appendprop_u32(fdt, mem_node.offset, "reg", (uint32_t)addr);
+		if(ret)
+		{
+			dprintf(CRITICAL, "ERROR: Could not append prop reg for memory node\n");
+			return ret;
+		}
 	}
 
-	if (ret)
+	if(mem_node.size_cell_size == 2)
 	{
-		dprintf(CRITICAL, "Failed to add the memory information addr: %d\n",
-				ret);
+		ret = fdt_appendprop_u32(fdt, mem_node.offset, "reg", size>>32);
+		if(ret)
+		{
+			dprintf(CRITICAL, "ERROR: Could not append prop reg for memory node\n");
+			return ret;
+		}
 	}
 
-
-	ret = fdt_appendprop_u32(fdt, offset, "reg", size);
+	ret = fdt_appendprop_u32(fdt, mem_node.offset, "reg", (uint32_t)size);
 
 	if (ret)
 	{
 		dprintf(CRITICAL, "Failed to add the memory information size: %d\n",
 				ret);
+		return ret;
 	}
 
 	return ret;
diff --git a/platform/msm_shared/include/dev_tree.h b/platform/msm_shared/include/dev_tree.h
index 85aa40d..1d9b9ad 100644
--- a/platform/msm_shared/include/dev_tree.h
+++ b/platform/msm_shared/include/dev_tree.h
@@ -84,6 +84,14 @@
 	uint32_t platform_subtype;
 };
 
+struct dt_mem_node_info
+{
+	uint32_t offset;
+	uint32_t mem_info_cnt;
+	uint32_t addr_cell_size;
+	uint32_t size_cell_size;
+};
+
 enum dt_err_codes
 {
 	DT_OP_SUCCESS,
@@ -92,7 +100,7 @@
 
 int dev_tree_validate(struct dt_table *table, unsigned int page_size, uint32_t *dt_hdr_size);
 int dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info);
-int update_device_tree(void *, const char *, void *, unsigned);
-int dev_tree_add_mem_info(void *fdt, uint32_t offset, uint32_t size, uint32_t addr);
+int update_device_tree(void *fdt, const char *, void *, unsigned);
+int dev_tree_add_mem_info(void *fdt, uint32_t offset, uint64_t size, uint64_t addr);
 void *dev_tree_appended(void *kernel, uint32_t kernel_size, void *tags);
 #endif