[Feature][T106]ZXW P56U09 code

Only Configure: Yes
Affected branch: master
Affected module: unknow
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: No
Doc Update: No

Change-Id: I3cbd8b420271eb20c2b40ebe5c78f83059cd42f3
diff --git a/boot/common/src/uboot/arch/arm/lib/bootm.c b/boot/common/src/uboot/arch/arm/lib/bootm.c
new file mode 100755
index 0000000..914259d
--- /dev/null
+++ b/boot/common/src/uboot/arch/arm/lib/bootm.c
@@ -0,0 +1,491 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * Copyright (C) 2001  Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <image.h>
+#include <u-boot/zlib.h>
+#include <asm/byteorder.h>
+#include <fdt.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <bootimg.h>
+#include <load_image.h> 
+#include <asm/arch/cpu.h>
+#include <asm/io.h>
+#include <fdt_support.h>
+#include <asm/arch/efuse.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
+    defined (CONFIG_CMDLINE_TAG) || \
+    defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_SERIAL_TAG) || \
+    defined (CONFIG_REVISION_TAG)
+static void setup_start_tag (bd_t *bd);
+
+# ifdef CONFIG_SETUP_MEMORY_TAGS
+static void setup_memory_tags (bd_t *bd);
+# endif
+static void setup_commandline_tag (bd_t *bd, char *commandline);
+
+# ifdef CONFIG_INITRD_TAG
+static void setup_initrd_tag (bd_t *bd, ulong initrd_start,
+			      ulong initrd_end);
+# endif
+static void setup_end_tag (bd_t *bd);
+
+static struct tag *params;
+#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
+
+static ulong get_sp(void);
+#if defined(CONFIG_OF_LIBFDT)
+static int bootm_linux_fdt(int machid, bootm_headers_t *images);
+#endif
+extern int rd_offset ;
+extern int rd_size;
+extern unsigned int g_sys_kernel_sdram_size;
+extern unsigned char g_ddr_size_flag;
+
+#define reg32(addr)			(*(volatile unsigned long *)(addr))
+
+void arch_lmb_reserve(struct lmb *lmb)
+{
+	ulong sp;
+
+	/*
+	 * Booting a (Linux) kernel image
+	 *
+	 * Allocate space for command line and board info - the
+	 * address should be as high as possible within the reach of
+	 * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
+	 * memory, which means far enough below the current stack
+	 * pointer.
+	 */
+	sp = get_sp();
+	debug("## Current stack ends at 0x%08lx ", sp);
+
+	/* adjust sp by 1K to be safe */
+	sp -= 1024;
+	lmb_reserve(lmb, sp,
+		    gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size - sp);
+}
+
+static void announce_and_cleanup(void)
+{
+	printf("\nStarting kernel ...\n");
+
+#ifdef CONFIG_USB_DEVICE
+	{
+		extern void udc_disconnect(void);
+		udc_disconnect();
+	}
+#endif
+	cleanup_before_linux();
+}
+
+//#ifdef CONFIG_ZX297520V3E_WATCH_CAP
+#if defined(CONFIG_ZX297520V3E_WATCH_CAP) || defined (CONFIG_ZX297520V3E_VEHICLE_DC) || defined (CONFIG_ZX297520V3E_VEHICLE_DC_REF)
+#define SYS_CPUCAP_PARAM_ADDR	0x10200C
+extern uint32_t arm_cpucap_ep;
+void set_cpucap_tag(int arch, uint parameter)
+{
+	uint32_t cap_tag_addr = 0;
+	
+	cap_tag_addr = arm_cpucap_ep - 0x8000 + 0x100;
+	
+	writel(0x0, SYS_CPUCAP_PARAM_ADDR);
+	writel(arch, SYS_CPUCAP_PARAM_ADDR+0x4);
+	writel(cap_tag_addr, SYS_CPUCAP_PARAM_ADDR+0x8);
+
+	memcpy(cap_tag_addr, parameter, 0x800);
+}
+#endif
+
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	bd_t	*bd = gd->bd;
+	char	*s;
+	int machid = bd->bi_arch_number; 
+	void	(*kernel_entry)(int zero, int arch, uint params);
+	
+
+#ifdef CONFIG_CMDLINE_TAG
+	char *commandline = getenv ("bootargs");
+#endif
+
+	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+	{
+		return 1;
+	}
+
+	
+	s = getenv ("machid");
+	if (s)
+	{
+		machid = simple_strtoul (s, NULL, 16);
+		printf ("Using machid 0x%x from environment\n", machid);
+	}
+
+	show_boot_progress (15);
+
+#ifdef CONFIG_OF_LIBFDT
+#if 0
+	if (images->ft_len)
+	{
+        debug("start device tree...\n");
+		//return bootm_linux_fdt(machid, images);
+		bootm_linux_fdt(machid, images);
+	}
+#endif
+#if defined(CONFIG_ZX297520V3E_VEHICLE_DC) || defined(CONFIG_ZX297520V3E_VEHICLE_DC_REF)
+        debug("start device tree...\n");
+		bootm_linux_fdt(machid, images);
+		//fdt_chosen(images->ft_addr, 1);
+#endif
+
+#endif
+
+	kernel_entry = (void (*)(int, int, uint))images->ep;
+
+	debug ("## Transferring control to Linux (at address %08lx) ...\n",
+	       (ulong) kernel_entry);
+
+#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
+    defined (CONFIG_CMDLINE_TAG) || \
+    defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_SERIAL_TAG) || \
+    defined (CONFIG_REVISION_TAG)
+	setup_start_tag (bd);
+#ifdef CONFIG_SERIAL_TAG
+	setup_serial_tag (&params);
+#endif
+#ifdef CONFIG_REVISION_TAG
+	setup_revision_tag (&params);
+#endif
+#ifdef CONFIG_SETUP_MEMORY_TAGS
+	setup_memory_tags (bd);
+#endif
+#ifdef CONFIG_CMDLINE_TAG
+	setup_commandline_tag (bd, commandline);
+#endif
+#ifdef CONFIG_INITRD_TAG
+	if (images->rd_start && images->rd_end)
+		setup_initrd_tag (bd, images->rd_start, images->rd_end);
+#endif
+	setup_end_tag(bd);
+#endif
+
+//#ifdef CONFIG_ZX297520V3E_WATCH_CAP	
+#if defined(CONFIG_ZX297520V3E_WATCH_CAP) || defined (CONFIG_ZX297520V3E_VEHICLE_DC) || defined (CONFIG_ZX297520V3E_VEHICLE_DC_REF)
+	memset(ICP_CAP_BUF_ADDR, 0, ICP_CAP_BUF_LEN);
+	memset(IRAM_BASE_ADDR_SYS_TRACE, 0, IRAM_BASE_LEN_SYS_TRACE);
+	if(!read_fota_update_flag())
+	{		
+		cap_poweron();
+		set_cpucap_tag(machid, bd->bi_boot_params);
+		start_cpucap_cores();
+	}
+#endif
+	printf("===chiid=0x%x,boot_params=0x%x\n", machid, bd->bi_boot_params);
+	announce_and_cleanup();
+	kernel_entry(0, machid, bd->bi_boot_params);
+
+	/* does not return */
+	return 1;
+}
+
+//add by zhouqi
+int do_booti_linux( boot_img_hdr *hdr )
+{
+	bd_t	*bd = gd->bd;
+	char	*s;
+	int	machid = bd->bi_arch_number;
+	void	(*kernel_entry)(int zero, int arch, uint params);
+
+#ifdef CONFIG_CMDLINE_TAG
+	char *commandline = getenv ("bootargs");
+#endif
+
+	s = getenv ("machid");
+	if (s) {
+		machid = simple_strtoul (s, NULL, 16);
+		printf ("Using machid 0x%x from environment\n", machid);
+	}
+
+	show_boot_progress (15);
+
+#ifdef CONFIG_OF_LIBFDT
+	//if (images->ft_len)
+		//return bootm_linux_fdt(machid, images);
+#endif
+
+	kernel_entry = (void (*)(int, int, uint))hdr->kernel_addr;
+
+	debug ("## Transferring control to Linux (at address %08lx) ...\n",
+	       (ulong) kernel_entry);
+
+#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
+    defined (CONFIG_CMDLINE_TAG) || \
+    defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_SERIAL_TAG) || \
+    defined (CONFIG_REVISION_TAG)
+	setup_start_tag (bd);
+#ifdef CONFIG_SERIAL_TAG
+	setup_serial_tag (&params);
+#endif
+#ifdef CONFIG_REVISION_TAG
+	setup_revision_tag (&params);
+#endif
+#ifdef CONFIG_SETUP_MEMORY_TAGS
+	setup_memory_tags (bd);
+#endif
+#ifdef CONFIG_CMDLINE_TAG
+	setup_commandline_tag (bd, commandline);
+#endif
+#ifdef CONFIG_INITRD_TAG
+	if (hdr->ramdisk_size)
+		setup_initrd_tag (bd, hdr->ramdisk_addr, hdr->ramdisk_size + hdr->ramdisk_addr);
+#endif
+	setup_end_tag(bd);
+#endif
+
+	announce_and_cleanup();
+
+	kernel_entry(0, machid, bd->bi_boot_params);
+	/* does not return */
+
+	return 1;
+}
+
+
+#if defined(CONFIG_OF_LIBFDT)
+static int fixup_memory_node(void *blob)
+{
+	bd_t	*bd = gd->bd;
+	int bank;
+	u64 start[CONFIG_NR_DRAM_BANKS];
+	u64 size[CONFIG_NR_DRAM_BANKS];
+
+	for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
+		//start[bank] = bd->bi_dram[bank].start;
+		//size[bank] = bd->bi_dram[bank].size;
+		start[bank] = DDR_BASE_ADDR_CAP;
+		if(g_ddr_size_flag == CHIP_DDR_IS_128M)
+		{
+			size[bank] = DDR_BASE_LEN_CAP;
+			reg32(IRAM_BASE_ADDR_BOOT_DDR) = DDR_BASE_LEN_CAP;
+		}		
+		else if(g_ddr_size_flag == CHIP_DDR_IS_256M) 
+		{
+			size[bank] = DDR_BASE_LEN_CAP + 0x8000000;
+			reg32(IRAM_BASE_ADDR_BOOT_DDR) = (DDR_BASE_LEN_CAP + 0x8000000);
+		}
+		else if(g_ddr_size_flag == CHIP_DDR_IS_512M) 
+		{
+			size[bank] = DDR_BASE_LEN_CAP + 0x18000000;
+			reg32(IRAM_BASE_ADDR_BOOT_DDR) = (DDR_BASE_LEN_CAP + 0x18000000);
+		}
+		else
+		{
+            debug("ddr size is error.\n");
+			return 0;
+		}
+	}
+	debug("size is 0x%llx\n",size[0]);
+	return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
+}
+
+static int bootm_linux_fdt(int machid, bootm_headers_t *images)
+{
+	ulong rd_len;
+	void (*kernel_entry)(int zero, int dt_machid, void *dtblob);
+	ulong of_size = images->ft_len;
+	char **of_flat_tree = &images->ft_addr;
+	ulong *initrd_start = &images->initrd_start;
+	ulong *initrd_end = &images->initrd_end;
+	struct lmb *lmb = &images->lmb;
+	int ret;
+
+	kernel_entry = (void (*)(int, int, void *))images->ep;
+
+	boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
+
+	rd_len = images->rd_end - images->rd_start;
+	ret = boot_ramdisk_high(lmb, images->rd_start, rd_len,
+				initrd_start, initrd_end);
+	if (ret)
+		return ret;
+
+	ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
+	if (ret)
+		return ret;
+
+	debug("## Transferring control to Linux (at address %08lx) ...\n",
+	       (ulong) kernel_entry);
+
+	fdt_chosen(*of_flat_tree, 1);
+	
+	fixup_memory_node(*of_flat_tree);
+
+#if 0
+	fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1);
+
+	announce_and_cleanup();
+
+	kernel_entry(0, machid, *of_flat_tree);
+	/* does not return */
+#endif 
+	return 1;
+}
+#endif
+
+#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
+    defined (CONFIG_CMDLINE_TAG) || \
+    defined (CONFIG_INITRD_TAG) || \
+    defined (CONFIG_SERIAL_TAG) || \
+    defined (CONFIG_REVISION_TAG)
+static void setup_start_tag (bd_t *bd)
+{
+	params = (struct tag *) bd->bi_boot_params;
+
+	params->hdr.tag = ATAG_CORE;
+	params->hdr.size = tag_size (tag_core);
+
+	params->u.core.flags = 0x1;//0;
+	params->u.core.pagesize =0x1000; //0;
+	params->u.core.rootdev = 0x0;//0;
+
+	params = tag_next (params);
+}
+
+
+#ifdef CONFIG_SETUP_MEMORY_TAGS
+static void setup_memory_tags (bd_t *bd)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
+	{
+		params->hdr.tag = ATAG_MEM;
+		params->hdr.size = tag_size (tag_mem32);
+
+		/* modify by zhouqi  2013/06/27 */
+		params->u.mem.start = read_sys_ddr_kernel_start();
+		params->u.mem.size = g_sys_kernel_sdram_size; //CONFIG_SYS_SDRAM_A9_SIZE;
+       
+		params = tag_next (params);
+	}
+}
+#endif /* CONFIG_SETUP_MEMORY_TAGS */
+
+
+static void setup_commandline_tag (bd_t *bd, char *commandline)
+{
+	char *p;
+
+	if (!commandline)
+		return;
+
+	/* eat leading white space */
+	for (p = commandline; *p == ' '; p++);
+
+	/* skip non-existent command lines so the kernel will still
+	 * use its default command line.
+	 */
+	if (*p == '\0')
+		return;
+
+	params->hdr.tag = ATAG_CMDLINE;
+	params->hdr.size =
+		(sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
+
+	strcpy (params->u.cmdline.cmdline, p);
+
+	params = tag_next (params);
+}
+
+
+#ifdef CONFIG_INITRD_TAG
+static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end)
+{
+	/* an ATAG_INITRD node tells the kernel where the compressed
+	 * ramdisk can be found. ATAG_RDIMG is a better name, actually.
+	 */
+	params->hdr.tag = ATAG_INITRD2;
+	params->hdr.size = tag_size (tag_initrd);
+
+	params->u.initrd.start = rd_offset;//initrd_start;
+	params->u.initrd.size =rd_size;//initrd_end - initrd_start;
+
+
+	params = tag_next (params);
+}
+#endif /* CONFIG_INITRD_TAG */
+
+#ifdef CONFIG_SERIAL_TAG
+void setup_serial_tag (struct tag **tmp)
+{
+	struct tag *params = *tmp;
+	struct tag_serialnr serialnr;
+	void get_board_serial(struct tag_serialnr *serialnr);
+
+	get_board_serial(&serialnr);
+	params->hdr.tag = ATAG_SERIAL;
+	params->hdr.size = tag_size (tag_serialnr);
+	params->u.serialnr.low = serialnr.low;
+	params->u.serialnr.high= serialnr.high;
+	params = tag_next (params);
+	*tmp = params;
+}
+#endif
+
+#ifdef CONFIG_REVISION_TAG
+void setup_revision_tag(struct tag **in_params)
+{
+	u32 rev = 0;
+	u32 get_board_rev(void);
+
+	rev = get_board_rev();
+	params->hdr.tag = ATAG_REVISION;
+	params->hdr.size = tag_size (tag_revision);
+	params->u.revision.rev = rev;
+	params = tag_next (params);
+}
+#endif  /* CONFIG_REVISION_TAG */
+
+static void setup_end_tag (bd_t *bd)
+{
+	params->hdr.tag = ATAG_NONE;
+	params->hdr.size = 0;
+}
+#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
+
+static ulong get_sp(void)
+{
+	ulong ret;
+
+	asm("mov %0, sp" : "=r"(ret) : );
+	return ret;
+}