copper: Add Device Tree support

Add functionality to update device tree blob

Change-Id: I29b3c20ee58a370b860aec81a1c10e1095313d98
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 0dc1a52..f81a44b 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -49,6 +49,10 @@
 #include <platform.h>
 #include <crypto_hash.h>
 
+#if DEVICE_TREE
+#include <libfdt.h>
+#endif
+
 #include "image_verify.h"
 #include "recovery.h"
 #include "bootimg.h"
@@ -72,6 +76,10 @@
 #define RECOVERY_MODE   0x77665502
 #define FASTBOOT_MODE   0x77665500
 
+#if DEVICE_TREE
+int update_device_tree(const void *, char *, void *, unsigned);
+#endif
+
 static const char *emmc_cmdline = " androidboot.emmc=true";
 static const char *usb_sn_cmdline = " androidboot.serialno=";
 static const char *battchg_pause = " androidboot.mode=charger";
@@ -355,10 +363,21 @@
 		const char *cmdline, unsigned machtype,
 		void *ramdisk, unsigned ramdisk_size)
 {
+	int ret = 0;
 	void (*entry)(unsigned, unsigned, unsigned*) = kernel;
 
+#if DEVICE_TREE
+	/* Update the Device Tree */
+	ret = update_device_tree(tags, cmdline, ramdisk, ramdisk_size);
+	if(ret)
+	{
+		dprintf(CRITICAL, "ERROR: Updating Device Tree Failed \n");
+		ASSERT(0);
+	}
+#else
 	/* Generating the Atags */
 	generate_atags(tags, cmdline, ramdisk, ramdisk_size);
+#endif
 
 	dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d)\n",
 		kernel, ramdisk, ramdisk_size);
@@ -1395,3 +1414,68 @@
 	.init = aboot_init,
 APP_END
 
+#if DEVICE_TREE
+/* Device Tree Stuff */
+int update_device_tree(const void * fdt, char *cmdline,
+					   void *ramdisk, unsigned ramdisk_size)
+{
+	int ret = 0;
+	int offset;
+	uint32_t *memory_reg;
+	unsigned char *final_cmdline;
+	uint32_t len;
+
+	/* Check the device tree header */
+	ret = fdt_check_header(fdt);
+	if(ret)
+	{
+		dprintf(CRITICAL, "Invalid device tree header \n");
+		return ret;
+	}
+
+	/* Get offset of the memory node */
+	offset = fdt_path_offset(fdt,"/memory");
+
+	memory_reg = target_dev_tree_mem(&len);
+
+	/* Adding the memory values to the reg property */
+	ret = fdt_setprop(fdt, offset, "reg", memory_reg, sizeof(uint32_t) * len * 2);
+	if(ret)
+	{
+		dprintf(CRITICAL, "ERROR: Cannot update memory node\n");
+		return ret;
+	}
+
+	/* Get offset of the chosen node */
+	offset = fdt_path_offset(fdt, "/chosen");
+
+	/* Adding the cmdline to the chosen node */
+	final_cmdline = update_cmdline(cmdline);
+	ret = fdt_setprop_string(fdt, offset, "bootargs", final_cmdline);
+	if(ret)
+	{
+		dprintf(CRITICAL, "ERROR: Cannot update chosen node [bootargs]\n");
+		return ret;
+	}
+
+	/* Adding the initrd-start to the chosen node */
+	ret = fdt_setprop_cell(fdt, offset, "linux,initrd-start", ramdisk);
+	if(ret)
+	{
+		dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-start]\n");
+		return ret;
+	}
+
+	/* Adding the initrd-end to the chosen node */
+	ret = fdt_setprop_cell(fdt, offset, "linux,initrd-end", (ramdisk + ramdisk_size));
+	if(ret)
+	{
+		dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-end]\n");
+		return ret;
+	}
+
+	fdt_pack(fdt);
+
+	return ret;
+}
+#endif
diff --git a/lib/libfdt/rules.mk b/lib/libfdt/rules.mk
new file mode 100644
index 0000000..92059c3
--- /dev/null
+++ b/lib/libfdt/rules.mk
@@ -0,0 +1,9 @@
+LOCAL_PATH := $(GET_LOCAL_DIR)
+
+LIBFDT_INCLUDES = fdt.h libfdt.h
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
+
+INCLUDES += -I$(LOCAL_PATH)
+
+OBJS += $(addprefix $(LOCAL_PATH)/, $(LIBFDT_OBJS))
diff --git a/project/copper.mk b/project/copper.mk
index 175bf54..f3af929 100644
--- a/project/copper.mk
+++ b/project/copper.mk
@@ -11,3 +11,4 @@
 #DEFINES += WITH_DEBUG_DCC=1
 DEFINES += WITH_DEBUG_UART=1
 #DEFINES += WITH_DEBUG_FBCON=1
+#DEFINES += DEVICE_TREE=1
diff --git a/target/copper/atags.c b/target/copper/atags.c
index a93d0af..174ae77 100644
--- a/target/copper/atags.c
+++ b/target/copper/atags.c
@@ -26,6 +26,8 @@
  *
  */
 
+#if !DEVICE_TREE /* If not using device tree */
+
 #include <reg.h>
 #include <debug.h>
 #include <smem.h>
@@ -126,3 +128,6 @@
 {
 	return ((void *)SCRATCH_ADDR);
 }
+
+#endif /* DEVICE_TREE */
+
diff --git a/target/copper/meminfo.c b/target/copper/meminfo.c
new file mode 100644
index 0000000..2f2fdcc
--- /dev/null
+++ b/target/copper/meminfo.c
@@ -0,0 +1,122 @@
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Code Aurora nor
+ *       the names of its contributors may be used to endorse or promote
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#if DEVICE_TREE /* If using device tree */
+
+#include <reg.h>
+#include <debug.h>
+#include <malloc.h>
+#include <smem.h>
+#include <stdint.h>
+#include <libfdt.h>
+#include <platform/iomap.h>
+
+#define SIZE_1M             (1024 * 1024)
+
+typedef struct {
+	uint32_t size;
+	uint32_t start_addr;
+}mem_info;
+
+
+mem_info copper_default_fixed_memory[] = {
+	{	.size = (132 * SIZE_1M),
+		.start_addr = SDRAM_START_ADDR
+	},
+	{	.size = SIZE_1M,
+		.start_addr = SDRAM_START_ADDR +
+				(250 * SIZE_1M) +
+				(5 * SIZE_1M)
+	},
+	{	.size = (240 * SIZE_1M),
+		.start_addr = SDRAM_START_ADDR +
+				(16 * SIZE_1M) +
+				(256 * SIZE_1M)
+	},
+	{	.size = (512 * SIZE_1M),
+		.start_addr = (512 * SIZE_1M),
+	}
+};
+
+uint32_t *target_mem_dev_tree_create(uint32_t *ptr, uint32_t size, uint32_t addr)
+{
+	*ptr++ = cpu_to_fdt32(addr);
+	*ptr++ = cpu_to_fdt32(size);
+
+	return ptr;
+}
+
+uint32_t *target_dev_tree_create(uint32_t *ptr,
+								 mem_info usable_mem_map[],
+								 uint32_t num_regions)
+{
+	uint32_t i;
+
+	ASSERT(num_regions);
+
+	dprintf(SPEW, "Number of HLOS regions in 1st bank = %u\n", num_regions);
+
+	for (i = 0; i < num_regions; i++)
+	{
+            ptr = target_mem_dev_tree_create(ptr,
+                            usable_mem_map[i].size,
+                            usable_mem_map[i].start_addr);
+	}
+	return ptr;
+}
+
+uint32_t* target_dev_tree_mem(uint32_t *num_of_entries)
+{
+    struct smem_ram_ptable ram_ptable;
+	uint32_t *meminfo_ptr;
+	uint32_t num_of_sections;
+	uint32_t *ptr;
+
+	/* Make sure RAM partition table is initialized */
+	ASSERT(smem_ram_ptable_init(&ram_ptable));
+
+	num_of_sections = ARRAY_SIZE(copper_default_fixed_memory);
+	*num_of_entries = num_of_sections;
+
+	meminfo_ptr = (uint32_t*) malloc(sizeof(uint32_t) * num_of_sections * 2);
+	ptr = meminfo_ptr;
+
+	target_dev_tree_create(ptr,
+						   copper_default_fixed_memory,
+						   ARRAY_SIZE(copper_default_fixed_memory));
+
+    return meminfo_ptr;
+}
+
+void *target_get_scratch_address(void)
+{
+	return ((void *)SCRATCH_ADDR);
+}
+
+#endif /* DEVICE_TREE */
+
diff --git a/target/copper/rules.mk b/target/copper/rules.mk
index 0f6a21f..38b59d2 100644
--- a/target/copper/rules.mk
+++ b/target/copper/rules.mk
@@ -17,7 +17,8 @@
 MODULES += \
 	dev/keys \
     lib/ptable \
-	dev/pmic/pm8x41
+	dev/pmic/pm8x41 \
+    lib/libfdt
 
 DEFINES += \
 	MEMSIZE=$(MEMSIZE) \
@@ -31,4 +32,5 @@
 
 OBJS += \
     $(LOCAL_DIR)/init.o \
-	$(LOCAL_DIR)/atags.o
+    $(LOCAL_DIR)/atags.o \
+    $(LOCAL_DIR)/meminfo.o