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