Merge "target: msm8226: Add support for board init to get platform info."
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index adeca41..a4aab73 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -104,6 +104,8 @@
 /* Assuming unauthorized kernel image by default */
 static int auth_kernel_img = 0;
 
+static uint32_t app_dev_tree = 0;
+
 static device_info device = {DEVICE_MAGIC, 0, 0};
 
 static struct udc_device surf_udc_device = {
@@ -412,7 +414,6 @@
 		dprintf(CRITICAL, "ERROR: Updating Device Tree Failed \n");
 		ASSERT(0);
 	}
-
 	dprintf(INFO, "Updating device tree: done\n");
 #else
 	/* Generating the Atags */
@@ -453,6 +454,7 @@
 	unsigned offset = 0;
 	unsigned long long ptn = 0;
 	const char *cmdline;
+	void *tags;
 	int index = INVALID_PTN;
 
 	unsigned char *image_addr = 0;
@@ -594,6 +596,16 @@
 
 			/* Read device device tree in the "tags_add */
 			memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry_ptr->offset, dt_entry_ptr->size);
+		} else {
+				/*
+				 * Look for appended device tree if DTB is not found in boot image
+				 * If found load the kernel & boot up
+				 */
+				app_dev_tree = dev_tree_appended((void*) hdr->kernel_addr);
+				if (!app_dev_tree) {
+					dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
+					return -1;
+				}
 		}
 		#endif
 		/* Make sure everything from scratch address is read before next step!*/
@@ -676,6 +688,16 @@
 				dprintf(CRITICAL, "ERROR: Cannot read device tree\n");
 				return -1;
 			}
+		} else {
+				/*
+				 * Look for appended device tree if DTB is not found in boot image
+				 * If found load the kernel & boot up
+				 */
+				app_dev_tree = dev_tree_appended((void*) hdr->kernel_addr);
+				if (!app_dev_tree) {
+					dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
+					return -1;
+				}
 		}
 		#endif
 	}
@@ -688,7 +710,17 @@
 		cmdline = DEFAULT_CMDLINE;
 	}
 
-	boot_linux((void *)hdr->kernel_addr, (unsigned *) hdr->tags_addr,
+	/*
+	 * If appended dev tree is found, update the atags with
+	 * memory address to the DTB appended location on RAM.
+	 * Else update with the atags address in the kernel header
+	 */
+	if (app_dev_tree)
+		tags = (void *)app_dev_tree;
+	else
+		tags = (void *)hdr->tags_addr;
+
+	boot_linux((void *)hdr->kernel_addr, (unsigned *)tags,
 		   (const char *)cmdline, board_machtype(),
 		   (void *)hdr->ramdisk_addr, hdr->ramdisk_size);
 
@@ -1134,6 +1166,17 @@
 		memmove((void*) hdr->tags_addr,
 				boot_image_start + dt_image_offset +  dt_entry_ptr->offset,
 				dt_entry_ptr->size);
+	} else {
+		/*
+		 * Look for appended device tree if DTB is not found in boot image
+		 * If found load the kernel & boot up
+		 */
+		memmove((void*) hdr->kernel_addr, boot_image_start + page_size, hdr->kernel_size);
+		app_dev_tree = dev_tree_appended((void*) hdr->kernel_addr);
+		if (!app_dev_tree) {
+			dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
+			return -1;
+		}
 	}
 
 	/* Everything looks fine. Return success. */
@@ -1147,6 +1190,7 @@
 	unsigned ramdisk_actual;
 	struct boot_img_hdr *hdr;
 	char *ptr = ((char*) data);
+	void *tags;
 
 	if (sz < sizeof(hdr)) {
 		fastboot_fail("invalid bootimage header");
@@ -1192,7 +1236,17 @@
 	memmove((void*) hdr->ramdisk_addr, ptr + page_size + kernel_actual, hdr->ramdisk_size);
 	memmove((void*) hdr->kernel_addr, ptr + page_size, hdr->kernel_size);
 
-	boot_linux((void*) hdr->kernel_addr, (void*) hdr->tags_addr,
+	/*
+	 * If appended dev tree is found, update the atags with
+	 * memory address to the DTB appended location on RAM.
+	 * Else update with the atags address in the kernel header
+	 */
+	if (app_dev_tree)
+		tags = (void *)app_dev_tree;
+	else
+		tags = (void *)hdr->tags_addr;
+
+	boot_linux((void*) hdr->kernel_addr, (void*) tags,
 		   (const char*) hdr->cmdline, board_machtype(),
 		   (void*) hdr->ramdisk_addr, hdr->ramdisk_size);
 }
diff --git a/platform/msm8960/gpio.c b/platform/msm8960/gpio.c
index 07d05a0..57d2591 100755
--- a/platform/msm8960/gpio.c
+++ b/platform/msm8960/gpio.c
@@ -253,11 +253,8 @@
 	int i = 0;
 	int num = 0;
 	struct pm8xxx_gpio_init *gpio_array;
-	uint32_t pmic_type;
 
-	pmic_type = board_pmic_type();
-
-	if (pmic_type == PMIC_IS_PM8917)
+	if (platform_pmic_type(PMIC_IS_PM8917))
 	{
 		num = ARRAY_SIZE(pm8917_keypad_gpios);
 		gpio_array = pm8917_keypad_gpios;
@@ -280,11 +277,8 @@
 	int i = 0;
 	int num = 0;
 	struct pm8xxx_gpio_init *gpio_array;
-	uint32_t pmic_type;
 
-	pmic_type = board_pmic_type();
-
-	if (pmic_type == PMIC_IS_PM8917)
+	if (platform_pmic_type(PMIC_IS_PM8917))
 	{
 		num = ARRAY_SIZE(pm8917_keypad_gpios_apq);
 		gpio_array = pm8917_keypad_gpios_apq;
diff --git a/platform/msm8960/platform.c b/platform/msm8960/platform.c
index ed0be2c..158b483 100644
--- a/platform/msm8960/platform.c
+++ b/platform/msm8960/platform.c
@@ -146,3 +146,23 @@
 {
 	return ticks_per_sec;
 }
+
+/* Return true if the pmic type matches */
+uint8_t platform_pmic_type(uint32_t pmic_type)
+{
+	uint8_t ret = 0;
+	uint8_t i = 0;
+	uint8_t num_ent = 0;
+	struct board_pmic_data pmic_info[SMEM_V7_SMEM_MAX_PMIC_DEVICES];
+
+	num_ent = board_pmic_info(&pmic_info, SMEM_V7_SMEM_MAX_PMIC_DEVICES);
+
+	for(i = 0; i < num_ent; i++) {
+		if (pmic_info[i].pmic_type == pmic_type) {
+			ret = 1;
+			break;
+		}
+	}
+
+	return ret;
+}
diff --git a/platform/msm_shared/board.c b/platform/msm_shared/board.c
index 220c6d3..58bf4a3 100644
--- a/platform/msm_shared/board.c
+++ b/platform/msm_shared/board.c
@@ -33,21 +33,23 @@
 #include <baseband.h>
 
 static struct board_data board = {UNKNOWN,
+	0,
 	HW_PLATFORM_UNKNOWN,
 	HW_PLATFORM_SUBTYPE_UNKNOWN,
 	LINUX_MACHTYPE_UNKNOWN,
 	BASEBAND_MSM,
-	PMIC_IS_INVALID,
-	0,
-	0};
+	{{PMIC_IS_INVALID, 0}, {PMIC_IS_INVALID, 0}, {PMIC_IS_INVALID, 0}},
+};
 
 static void platform_detect()
 {
 	struct smem_board_info_v6 board_info_v6;
 	struct smem_board_info_v7 board_info_v7;
+	struct smem_board_info_v8 board_info_v8;
 	unsigned int board_info_len = 0;
 	unsigned ret = 0;
 	unsigned format = 0;
+	uint8_t i;
 
 	ret = smem_read_alloc_entry_offset(SMEM_BOARD_INFO_LOCATION,
 						   &format, sizeof(format), 0);
@@ -83,8 +85,28 @@
 		board.platform_version = board_info_v7.board_info_v3.msm_version;
 		board.platform_hw = board_info_v7.board_info_v3.hw_platform;
 		board.platform_subtype = board_info_v7.platform_subtype;
-		board.pmic_type = board_info_v7.pmic_type;
-		board.pmic_version = board_info_v7.pmic_version;
+		board.pmic_info[0].pmic_type = board_info_v7.pmic_type;
+		board.pmic_info[0].pmic_version = board_info_v7.pmic_version;
+	}
+	else if (format == 8)
+	{
+		board_info_len = sizeof(board_info_v8);
+
+		ret = smem_read_alloc_entry(SMEM_BOARD_INFO_LOCATION,
+				&board_info_v8,
+				board_info_len);
+		if (ret)
+			return;
+
+		board.platform = board_info_v8.board_info_v3.msm_id;
+		board.platform_version = board_info_v8.board_info_v3.msm_version;
+		board.platform_hw = board_info_v8.board_info_v3.hw_platform;
+		board.platform_subtype = board_info_v8.platform_subtype;
+
+		for (i = 0; i < SMEM_V8_SMEM_MAX_PMIC_DEVICES; i++) {
+			board.pmic_info[i].pmic_type = board_info_v8.pmic_info[i].pmic_type;
+			board.pmic_info[i].pmic_version = board_info_v8.pmic_info[i].pmic_version;
+		}
 	}
 	else
 	{
@@ -120,14 +142,17 @@
 	return board.platform_hw;
 }
 
-uint32_t board_pmic_type()
+uint8_t board_pmic_info(struct board_pmic_data *info, uint8_t num_ent)
 {
-	return board.pmic_type;
-}
+	uint8_t i;
 
-uint32_t board_pmic_ver()
-{
-	return board.pmic_version;
+	for (i = 0; i < num_ent && i < SMEM_MAX_PMIC_DEVICES; i++) {
+		info->pmic_type = board.pmic_info[i].pmic_type;
+		info->pmic_version = board.pmic_info[i].pmic_version;
+		info++;
+	}
+
+	return (i--);
 }
 
 uint32_t board_soc_version()
diff --git a/platform/msm_shared/dev_tree.c b/platform/msm_shared/dev_tree.c
index 04caeb1..6a06a12 100644
--- a/platform/msm_shared/dev_tree.c
+++ b/platform/msm_shared/dev_tree.c
@@ -39,6 +39,28 @@
 extern int target_is_emmc_boot(void);
 extern uint32_t target_dev_tree_mem(void *fdt, uint32_t memory_node_offset);
 
+/*
+ * Argument:     Start address of the kernel loaded in RAM
+ * Return Value: DTB address : If appended device tree is found
+ *               '0'         : Otherwise
+ */
+uint32_t dev_tree_appended(void *kernel)
+{
+	uint32_t app_dtb_offset = 0;
+	uint32_t dtb_magic = 0;
+	uint32_t dtb = 0;
+
+	memcpy((void*) &app_dtb_offset, (void*) (kernel + DTB_OFFSET), sizeof(uint32_t));
+	memcpy((void*) &dtb_magic, (void*) (kernel + app_dtb_offset), sizeof(uint32_t));
+
+	if (dtb_magic == DTB_MAGIC) {
+		dprintf(INFO, "Found Appeneded Flattened Device tree\n");
+		dtb = (uint32_t) (kernel + app_dtb_offset);
+	}
+
+	return dtb;
+}
+
 /* Function to return the pointer to the start of the correct device tree
  *  based on the platform data.
  */
diff --git a/platform/msm_shared/include/board.h b/platform/msm_shared/include/board.h
index 7ede8ee..f863a26 100644
--- a/platform/msm_shared/include/board.h
+++ b/platform/msm_shared/include/board.h
@@ -30,8 +30,16 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
+#include <smem.h>
+
 #define LINUX_MACHTYPE_UNKNOWN 0
 #define BOARD_SOC_VERSION2     0x20000
+#define MAX_PMIC_DEVICES       SMEM_MAX_PMIC_DEVICES
+
+struct board_pmic_data {
+	uint32_t pmic_type;
+	uint32_t pmic_version;
+};
 
 struct board_data {
 	uint32_t platform;
@@ -40,8 +48,7 @@
 	uint32_t platform_subtype;
 	uint32_t target;
 	uint32_t baseband;
-	uint32_t pmic_type;
-	uint32_t pmic_version;
+	struct board_pmic_data pmic_info[MAX_PMIC_DEVICES];
 };
 
 void board_init();
@@ -51,8 +58,7 @@
 uint32_t board_target_id();
 uint32_t board_baseband();
 uint32_t board_hardware_id();
-uint32_t board_pmic_type();
-uint32_t board_pmic_ver();
+uint8_t board_pmic_info(struct board_pmic_data *, uint8_t num_ent);
 uint32_t board_soc_version();
 
 #endif
diff --git a/platform/msm_shared/include/dev_tree.h b/platform/msm_shared/include/dev_tree.h
index 5c58b38..389ab49 100644
--- a/platform/msm_shared/include/dev_tree.h
+++ b/platform/msm_shared/include/dev_tree.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -37,6 +37,9 @@
 #define DEV_TREE_VERSION        1
 #define DEV_TREE_HEADER_SIZE    12
 
+#define DTB_MAGIC               0xedfe0dd0
+#define DTB_OFFSET              0x2C
+
 struct dt_entry
 {
 	uint32_t platform_id;
@@ -62,5 +65,5 @@
 struct dt_entry * dev_tree_get_entry_ptr(struct dt_table *);
 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);
-
+uint32_t dev_tree_appended(void *);
 #endif
diff --git a/platform/msm_shared/smem.h b/platform/msm_shared/smem.h
index 58ca387..7dfce1d 100755
--- a/platform/msm_shared/smem.h
+++ b/platform/msm_shared/smem.h
@@ -33,6 +33,10 @@
 
 #include <sys/types.h>
 
+#define SMEM_V7_SMEM_MAX_PMIC_DEVICES   1
+#define SMEM_V8_SMEM_MAX_PMIC_DEVICES   3
+#define SMEM_MAX_PMIC_DEVICES           SMEM_V8_SMEM_MAX_PMIC_DEVICES
+
 struct smem_proc_comm {
 	unsigned command;
 	unsigned status;
@@ -91,8 +95,18 @@
    PMIC_IS_PM8038,
    PMIC_IS_PM8922,
    PMIC_IS_PM8917,
-   PMIC_IS_INVALID = 0xffffffff,
-} pm_model_type;
+   PMIC_IS_INVALID = 0x7fffffff,
+} pm_model_type_afly;
+
+typedef enum
+{
+	PMIC_IS_UNKNOWN   = 0,
+	PMIC_IS_PM8941    = 1,
+	PMIC_IS_PM8841    = 2,
+	PMIC_IS_PM8019    = 3,
+	PMIC_IS_PM8026    = 4,
+	PMIC_IS_PM8110    = 5,
+} pm_model_type_bfly;
 
 struct smem_board_info_v3 {
 	unsigned format;
@@ -134,6 +148,24 @@
 	unsigned buffer_align;	//Need for 8 bytes alignment while reading from shared memory.
 };
 
+struct smem_pmic_info {
+	unsigned pmic_type;
+	unsigned pmic_version;
+};
+
+struct smem_board_info_v8 {
+	struct smem_board_info_v3 board_info_v3;
+	unsigned platform_version;
+	unsigned fused_chip;
+	unsigned platform_subtype;
+	struct smem_pmic_info pmic_info[SMEM_V8_SMEM_MAX_PMIC_DEVICES];
+	/*
+	 * Need for 8 bytes alignment
+	 * while reading from shared memory
+	 */
+	unsigned buffer_align;
+};
+
 typedef struct {
 	unsigned key_len;
 	unsigned iv_len;
diff --git a/target/msm8226/meminfo.c b/target/msm8226/meminfo.c
index e5a53d2..3b92733 100644
--- a/target/msm8226/meminfo.c
+++ b/target/msm8226/meminfo.c
@@ -35,6 +35,8 @@
 #include <platform/iomap.h>
 #include <dev_tree.h>
 
+#define MB (1024*1024)
+
 /* Funtion to add the ram partition entries into device tree.
  * The function assumes that all the entire fixed memory regions should
  * be listed in the first bank of the passed in ddr regions.
@@ -54,6 +56,14 @@
         if((ram_ptable.parts[i].category == SDRAM) &&
            (ram_ptable.parts[i].type == SYS_MEMORY))
         {
+			if (ram_ptable.parts[i].start == 0x0)
+			{
+				/* Ensure that the size for this segment is > 1MB */
+				ASSERT(ram_ptable.parts[i].size > 1*MB);
+
+				ram_ptable.parts[i].start += 1*MB;
+				ram_ptable.parts[i].size  -= 1*MB;
+			}
 
 			/* Pass along all other usable memory regions to Linux */
 			ret = dev_tree_add_mem_info(fdt,
diff --git a/target/msm8960/keypad.c b/target/msm8960/keypad.c
index 82e049c..1639f19 100644
--- a/target/msm8960/keypad.c
+++ b/target/msm8960/keypad.c
@@ -134,11 +134,9 @@
 
 void msm8930_keypad_init(void)
 {
-	uint32_t pm_type = board_pmic_type();
-
 	msm8930_keypad_gpio_init();
 
-	if (pm_type == PMIC_IS_PM8917)
+	if (platform_pmic_type(PMIC_IS_PM8917))
 	{
 		ssbi_gpio_keypad_init(&msm8930_pm8917_qwerty_keypad);
 	}
@@ -150,11 +148,9 @@
 
 void apq8064_keypad_init(void)
 {
-	uint32_t pm_type = board_pmic_type();
-
 	apq8064_keypad_gpio_init();
 
-	if (pm_type == PMIC_IS_PM8917)
+	if (platform_pmic_type(PMIC_IS_PM8917))
 		ssbi_gpio_keypad_init(&apq8064_pm8917_qwerty_keypad);
 	else
 		ssbi_gpio_keypad_init(&apq8064_pm8921_qwerty_keypad);