[U-Boot] [PATCH] part1 of arm64. This patch provide u-boot with arm64 support. Currently it works on Foundation Model for armv8 or Fast Model for armv8.

fenghua at phytium.com.cn fenghua at phytium.com.cn
Sun Aug 11 18:05:23 CEST 2013


From: fenghua <fenghua at ligen-virtual-machine.(none)>

This patch provide u-boot with arm64 support. Currently, it works on
Foundation Model for armv8 or Fast Model for armv8.

Signed-off-by: fenghua <fenghua at ligen-virtual-machine.(none)>
---
 arch/arm64/config.mk                 |   32 +++
 arch/arm64/lib/Makefile              |   64 +++++
 arch/arm64/lib/board.c               |  456 ++++++++++++++++++++++++++++++++++
 arch/arm64/lib/bootm.c               |  211 ++++++++++++++++
 arch/arm64/lib/cache.c               |  282 +++++++++++++++++++++
 arch/arm64/lib/crt0.S                |  129 ++++++++++
 arch/arm64/lib/interrupts.c          |  109 ++++++++
 arch/arm64/lib/relocate.S            |   72 ++++++
 arch/arm64/lib/reset.c               |   37 +++
 arch/arm64/lib/timer.c               |   95 +++++++
 board/armltd/dts/vexpress64.dts      |  215 ++++++++++++++++
 board/armltd/vexpress64/Makefile     |   43 ++++
 board/armltd/vexpress64/vexpress64.c |   63 +++++
 boards.cfg                           |    1 +
 common/cmd_bdinfo.c                  |   32 +++
 common/fdt_support.c                 |   66 ++---
 common/image.c                       |    5 +-
 doc/README.arm64                     |   10 +
 examples/standalone/stubs.c          |   13 +
 include/configs/vexpress_aemv8a.h    |  200 +++++++++++++++
 include/image.h                      |    1 +
 lib/asm-offsets.c                    |    2 +-
 22 files changed, 2103 insertions(+), 35 deletions(-)
 create mode 100644 arch/arm64/config.mk
 create mode 100644 arch/arm64/lib/Makefile
 create mode 100644 arch/arm64/lib/board.c
 create mode 100644 arch/arm64/lib/bootm.c
 create mode 100644 arch/arm64/lib/cache.c
 create mode 100644 arch/arm64/lib/crt0.S
 create mode 100644 arch/arm64/lib/interrupts.c
 create mode 100644 arch/arm64/lib/relocate.S
 create mode 100644 arch/arm64/lib/reset.c
 create mode 100644 arch/arm64/lib/timer.c
 create mode 100644 board/armltd/dts/vexpress64.dts
 create mode 100644 board/armltd/vexpress64/Makefile
 create mode 100644 board/armltd/vexpress64/vexpress64.c
 create mode 100644 doc/README.arm64
 create mode 100644 include/configs/vexpress_aemv8a.h

diff --git a/arch/arm64/config.mk b/arch/arm64/config.mk
new file mode 100644
index 0000000..e40e983
--- /dev/null
+++ b/arch/arm64/config.mk
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2013	FengHua <fenghua at phytium.com.cn>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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
+#
+
+CROSS_COMPILE ?= /home/fenghua/DS-5-Workspace/gcc-linaro-aarch64-linux-gnu-4.8-2013.05_linux/bin/aarch64-linux-gnu-
+
+ifndef CONFIG_STANDALONE_LOAD_ADDR
+CONFIG_STANDALONE_LOAD_ADDR = 0x81000000
+endif
+
+PLATFORM_CPPFLAGS += -DCONFIG_ARM64 -fpic -mstrict-align
+
+# needed for relocation
+LDFLAGS_u-boot +=
diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile
new file mode 100644
index 0000000..87fa803
--- /dev/null
+++ b/arch/arm64/lib/Makefile
@@ -0,0 +1,64 @@
+#
+# (C) Copyright 2002-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(ARCH).o
+LIBGCC	= $(obj)libgcc.o
+
+COBJS-y	+= board.o
+COBJS-y	+= interrupts.o
+COBJS-y	+= reset.o
+COBJS-y	+= cache.o
+COBJS-y	+= timer.o
+
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
+
+SOBJS-y += crt0.o
+SOBJS-y += relocate.o
+
+SRCS	:= $(GLSOBJS:.o=.S) $(GLCOBJS:.o=.c) \
+	   $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+LGOBJS	:= $(addprefix $(obj),$(GLSOBJS)) \
+	   $(addprefix $(obj),$(GLCOBJS))
+
+# Always build libarm64.o
+TARGETS	:= $(LIB)
+
+all:	$(TARGETS)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+$(LIBGCC): $(obj).depend $(LGOBJS)
+	$(call cmd_link_o_target, $(LGOBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm64/lib/board.c b/arch/arm64/lib/board.c
new file mode 100644
index 0000000..a8147a5
--- /dev/null
+++ b/arch/arm64/lib/board.c
@@ -0,0 +1,456 @@
+/*
+ * (C) Copyright 2013
+ * David Feng, Phytium Technology <fenghua at phytium.com.cn>
+ *
+ * (C) Copyright 2002-2006
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger at sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <malloc.h>
+#include <stdio_dev.h>
+#include <version.h>
+#include <net.h>
+#include <serial.h>
+#include <nand.h>
+#include <onenand_uboot.h>
+#include <mmc.h>
+#include <libfdt.h>
+#include <fdtdec.h>
+#include <post.h>
+#include <logbuff.h>
+#include <pci.h>
+#include <fdt_support.h>
+#include <asm/arch/mmu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+ulong monitor_flash_len;
+
+/* The following functions defined in platform code */
+extern int dram_init(void);
+extern int arch_cpu_init(void);
+
+/* for the following variables, see start.S */
+extern ulong _bss_start_ofs;	/* BSS start relative to _start */
+extern ulong _bss_end_ofs;	/* BSS end relative to _start */
+extern ulong _end_ofs;		/* end of image relative to _start */
+
+static int init_baudrate(void)
+{
+	gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
+	return 0;
+}
+
+static int display_banner(void)
+{
+	printf("\n\n%s\n\n", version_string);
+	debug("U-Boot code: %lx -> %lx  BSS: -> %lx\n",
+		(ulong)CONFIG_SYS_TEXT_BASE,
+		(ulong)(CONFIG_SYS_TEXT_BASE + _bss_start_ofs),
+		(ulong)(CONFIG_SYS_TEXT_BASE + _bss_end_ofs));
+
+	return (0);
+}
+
+/*
+ * Default implementation of display_cpuinfo()
+ * Real implementation should be in platform code
+ */
+int __display_cpuinfo(void)
+{
+	return 0;
+}
+int display_cpuinfo(void)
+	__attribute__((weak, alias("__display_cpuinfo")));
+
+/*
+ * Default implementation of display_boardinfo()
+ * Real implementation should be in platform code
+ */
+static int __display_boardinfo(void)
+{
+	return 0;
+}
+int display_boardinfo(void)
+	__attribute__((weak, alias("__display_boardinfo")));
+
+/*
+ * Default implementation of board_early_init_f()
+ * Real implementation should be in platform code
+ */
+static int __board_early_init_f(void)
+{
+	return 0;
+}
+int board_early_init_f(void)
+	__attribute__((weak, alias("__board_early_init_f")));
+
+/*
+ * Default implementation of board_late_init()
+ * Real implementation should be in platform code
+ */
+static int __board_late_init(void)
+{
+	return 0;
+}
+int board_late_init(void)
+	__attribute__((weak, alias("__board_late_init")));
+
+/*
+ * All attempts to come up with a "common" initialization sequence
+ * that works for all boards and architectures failed: some of the
+ * requirements are just _too_ different. To get rid of the resulting
+ * mess of board dependent #ifdef'ed code we now make the whole
+ * initialization sequence configurable to the user.
+ *
+ * The requirements for any new initalization function is simple: it
+ * receives a pointer to the "global data" structure as it's only
+ * argument, and returns an integer return code, where 0 means
+ * "continue" and != 0 means "fatal error, hang the system".
+ */
+typedef int (init_fnc_t) (void);
+
+init_fnc_t *init_sequence[] = {
+	arch_cpu_init,		/* basic arch cpu dependent setup */
+	board_early_init_f,
+#ifdef CONFIG_OF_CONTROL
+	fdtdec_check_fdt,
+#endif
+	env_init,		/* initialize environment */
+	init_baudrate,		/* initialze baudrate settings */
+	serial_init,		/* serial communications setup */
+	console_init_f,		/* stage 1 init of console */
+	display_banner,		/* say that we are here */
+	display_cpuinfo,	/* display cpu info (and speed) */
+	display_boardinfo,	/* display board info */
+	dram_init,		/* configure available RAM banks */
+	NULL,
+};
+
+void board_init_f(ulong bootflag)
+{
+	bd_t *bd;
+	init_fnc_t **init_fnc_ptr;
+	gd_t *id;
+	ulong addr, addr_sp;
+	void *new_fdt = NULL;
+	size_t fdt_size = 0;
+
+	bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f");
+
+	/* Pointer is writable since we allocated a register for it */
+	memset((void *)gd, 0, sizeof(gd_t));
+
+	gd->bd = (bd_t *)(gd + 1);
+	gd->mon_len = _bss_end_ofs;
+
+	/*
+	 * Device Tree file can be merged in uboot.bin or appended after
+	 * uboot.bin as a seperate file. The following code initialize 
+	 * fdt block base address.
+	 */
+#ifdef CONFIG_OF_EMBED
+	/* Get a pointer to the FDT */
+	gd->fdt_blob = _binary_dt_dtb_start;
+#elif defined(CONFIG_OF_SEPARATE)
+	/* FDT is at end of image */
+	gd->fdt_blob = (void *)(CONFIG_SYS_TEXT_BASE + _end_ofs);
+#endif
+	/* Allow the early environment to override the fdt address */
+	gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
+						(uintptr_t)gd->fdt_blob);
+
+	/*
+	 * Calling system initialization functions in sequence.
+	 */
+	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
+		if ((*init_fnc_ptr)() != 0) {
+			hang ();
+		}
+	}
+
+#if defined(CONFIG_OF_CONTROL) || defined(CONFIG_OF_LIBFDT)
+	/* For now, put this check after the console is ready */
+	if (fdtdec_prepare_fdt()) {
+		panic("** CONFIG_OF_CONTROL defined but no FDT - please see doc/README.fdt-control");
+	}
+#endif
+
+	/*
+	 * Console has beeb setup, output debug messages
+	 */
+	debug("U-Boot code len: %08lX\n", gd->mon_len);
+
+	addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
+
+	debug("Top of RAM usable for U-Boot at: %08lx\n", addr);
+
+#ifdef CONFIG_LOGBUFFER
+#ifndef CONFIG_ALT_LB_ADDR
+	/* reserve kernel log buffer */
+	addr -= (LOGBUFF_RESERVE);
+	debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, addr);
+#endif
+#endif
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+	/* reserve MMU table and align it to PAGE_SIZE */
+	addr -= PAGE_SIZE;
+	addr &= PAGE_MASK;
+	gd->arch.tlb_addr = addr;
+	gd->arch.tlb_size = PAGE_SIZE;
+	debug("MMU table at: %08lx\n", addr);
+#endif
+
+	/*
+	 * reserve memory for U-Boot code, data & bss
+	 * align it to PAGE_SIZE
+	 */
+	addr -= gd->mon_len;
+	addr &= PAGE_MASK;
+	debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr);
+
+	/*
+	 * reserve memory for malloc() arena
+	 */
+	addr_sp = addr - TOTAL_MALLOC_LEN;
+	debug("Reserving %dk for malloc() at: %08lx\n", TOTAL_MALLOC_LEN >> 10, addr_sp);
+
+	/*
+	 * (permanently) allocate a Board Info struct
+	 */
+	addr_sp -= sizeof(bd_t);
+	bd = (bd_t *)addr_sp;
+	memcpy(bd, (void *)gd->bd, sizeof(bd_t));
+	gd->bd = bd;
+	gd->bd->bi_baudrate = gd->baudrate;
+	debug("Reserving %zu Bytes for Board Info at: %08lx\n", sizeof(bd_t), addr_sp);
+
+	/*
+	 * (permanently) allocate a Global Data struct
+	 */
+	addr_sp -= sizeof(gd_t);
+	id = (gd_t *)addr_sp;
+	debug("Reserving %zu Bytes for Global Data at: %08lx\n", sizeof(gd_t), addr_sp);
+
+#if defined(CONFIG_OF_CONTROL) || defined(CONFIG_OF_LIBFDT)
+	/*
+	 * If the device tree is sitting immediate above our image then we
+	 * must relocate it. If it is embedded in the data section, then it
+	 * will be relocated with other data.
+	 */
+	if (gd->fdt_blob) {
+		fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32);
+
+		addr_sp -= fdt_size;
+		new_fdt = (void *)addr_sp;
+		debug("Reserving %zu Bytes for FDT at: %08lx\n", fdt_size, addr_sp);
+	}
+#endif
+
+	/* 16-byte alignment for ABI compliance */
+	addr_sp &= ~0xf;
+	debug("New Stack Pointer is: %08lx\n", addr_sp);
+
+	gd->relocaddr = addr;
+	gd->start_addr_sp = addr_sp;
+	gd->reloc_off = addr - CONFIG_SYS_TEXT_BASE;
+	debug("Relocation Offset: %08lx\n", gd->reloc_off);
+
+	if (new_fdt) {
+		memcpy(new_fdt, gd->fdt_blob, fdt_size);
+		gd->fdt_blob = new_fdt;
+	}
+
+	memcpy(id, (void *)gd, sizeof(gd_t));
+}
+
+
+/*
+ ************************************************************************
+ *
+ * This is the next part of the initialization sequence: we are now
+ * running from RAM and have a "normal" C environment, i. e. global
+ * data can be written, BSS has been cleared, the stack size in not
+ * that critical any more, etc.
+ *
+ ************************************************************************
+ */
+
+void board_init_r(gd_t *id, ulong dest_addr)
+{
+#ifndef CONFIG_SYS_NO_FLASH
+	ulong flash_size;
+#endif
+
+	gd = id;
+
+	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
+	bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
+
+	/* before here, printf can not be used */
+	serial_initialize();
+
+	debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
+
+	monitor_flash_len = _end_ofs;
+
+	/* Enable caches */
+	enable_caches();
+
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+	/*
+	 * We have to relocate the command table manually
+	 */
+	fixup_cmdtable(ll_entry_start(cmd_tbl_t, cmd),
+			ll_entry_count(cmd_tbl_t, cmd));
+#endif /* CONFIG_NEEDS_MANUAL_RELOC */
+
+	/* there are some other pointer constants we must deal with */
+#ifndef CONFIG_ENV_IS_NOWHERE
+	env_name_spec += gd->reloc_off;
+#endif
+
+#ifdef CONFIG_LOGBUFFER
+	logbuff_init_ptrs();
+#endif
+
+	/* The Malloc area is immediately below the monitor copy in DRAM */
+	mem_malloc_init (dest_addr - TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN);
+
+#ifndef CONFIG_SYS_NO_FLASH
+	puts("Flash: ");
+
+	flash_size = flash_init();
+	if (flash_size > 0) {
+# ifdef CONFIG_SYS_FLASH_CHECKSUM
+		char *s = getenv("flashchecksum");
+
+		print_size(flash_size, "");
+		/*
+		 * Compute and print flash CRC if flashchecksum is set to 'y'
+		 *
+		 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
+		 */
+		if (s && (*s == 'y')) {
+			printf("  CRC: %08X", crc32(0,
+				(const unsigned char *) CONFIG_SYS_FLASH_BASE,
+				flash_size));
+		}
+		putc('\n');
+# else	/* !CONFIG_SYS_FLASH_CHECKSUM */
+		print_size(flash_size, "\n");
+# endif /* CONFIG_SYS_FLASH_CHECKSUM */
+	} else {
+		puts("*** failed ***\n");
+		hang();
+	}
+#endif
+
+#ifdef CONFIG_CMD_NAND
+	puts("NAND:  ");
+	nand_init();		/* go init the NAND */
+#endif
+
+#ifdef CONFIG_CMD_ONENAND
+	onenand_init();
+#endif
+
+#ifdef CONFIG_GENERIC_MMC
+	puts("MMC:   ");
+	mmc_initialize(gd->bd);
+#endif
+
+	/* initialize environment */
+	env_relocate();
+
+#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI)
+	pci_init();
+#endif
+
+	stdio_init();	/* get the devices list going. */
+
+	jumptable_init();
+
+#if defined(CONFIG_API)
+	/* Initialize API */
+	api_init();
+#endif
+
+	console_init_r();	/* fully init console as a device */
+
+	/* set up and enable exceptions */
+	interrupt_init();
+	enable_interrupts();
+
+	/* Initialize from environment */
+	load_addr = getenv_ulong("loadaddr", 16, load_addr);
+
+	board_late_init();
+
+#if defined(CONFIG_CMD_NET)
+	puts("Net:   ");
+	eth_initialize(gd->bd);
+#if defined(CONFIG_RESET_PHY_R)
+	debug("Reset Ethernet PHY\n");
+	reset_phy();
+#endif
+#endif
+
+#ifdef CONFIG_POST
+	post_run(NULL, POST_RAM | post_bootmode_get(0));
+#endif
+
+#ifdef CONFIG_OF_LIBFDT
+	set_working_fdt_addr((void *)gd->fdt_blob);
+#endif
+
+#ifdef CONFIG_LOGBUFFER
+	/*
+	 * Export available size of memory for Linux,
+	 * taking into account the protected RAM at top of memory
+	 */
+	{
+		ulong pram = 0;
+		uchar memsz[32];
+
+#ifndef CONFIG_ALT_LB_ADDR
+		/* Also take the logbuffer into account (pram is in kB) */
+		pram += (LOGBUFF_LEN + LOGBUFF_OVERHEAD) / 1024;
+#endif
+		sprintf((char *)memsz, "%ldk", (gd->ram_size / 1024) - pram);
+		setenv("mem", (char *)memsz);
+	}
+#endif
+
+	/* main_loop() can return to retry autoboot, if so just run it again. */
+	for (;;) {
+		main_loop();
+	}
+
+	/* NOTREACHED - no way out of command loop except booting */
+}
diff --git a/arch/arm64/lib/bootm.c b/arch/arm64/lib/bootm.c
new file mode 100644
index 0000000..af3bc09
--- /dev/null
+++ b/arch/arm64/lib/bootm.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2011
+ * Corscience GmbH & Co. KG - Simon Schwarz <schwarz at corscience.de>
+ *  - Added prep subcommand support
+ *  - Reorganized source - modeled after powerpc version
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger at sysgo.de>
+ *
+ * Copyright (C) 2001  Erik Mouw (J.A.K.Mouw at 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 <libfdt.h>
+#include <fdt_support.h>
+
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern int cleanup_before_linux(void);
+
+
+static ulong get_sp(void)
+{
+	ulong ret;
+
+	asm("mov %0, sp" : "=r"(ret) : );
+	return ret;
+}
+
+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 4K to be safe */
+	sp -= 4096;
+	lmb_reserve(lmb, sp,
+		    gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size - sp);
+}
+
+#ifdef CONFIG_OF_LIBFDT
+int arch_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;
+	}
+
+	return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
+}
+#endif
+
+/**
+ * announce_and_cleanup() - Print message and prepare for kernel boot
+ *
+ * @fake: non-zero to do everything except actually boot
+ */
+static void announce_and_cleanup(int fake)
+{
+	printf("\nStarting kernel ...%s\n\n", fake ?
+		"(fake run for tracing)" : "");
+	bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
+#ifdef CONFIG_BOOTSTAGE_FDT
+	if (flag == BOOTM_STATE_OS_FAKE_GO)
+		bootstage_fdt_add_report();
+#endif
+#ifdef CONFIG_BOOTSTAGE_REPORT
+	bootstage_report();
+#endif
+
+#ifdef CONFIG_USB_DEVICE
+	udc_disconnect();
+#endif
+	cleanup_before_linux();
+}
+
+/* Subcommand: PREP */
+static void boot_prep_linux(bootm_headers_t *images)
+{
+	if (!images->ft_len && gd->fdt_blob) {
+		images->ft_addr = (void *)gd->fdt_blob;
+		images->ft_len = fdt_totalsize(gd->fdt_blob);
+	}
+
+	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
+#ifdef CONFIG_OF_LIBFDT
+		debug("using: FDT\n");
+		if (image_setup_linux(images)) {
+			printf("FDT creation failed! hanging...");
+			hang();
+		}
+#endif
+	} else {
+		printf("FDT support not compiled in - hanging\n");
+		hang();
+	}
+}
+
+/* Subcommand: GO */
+static void boot_jump_linux(bootm_headers_t *images, int flag)
+{
+	void (*kernel_entry)(void *fdt_addr);
+	int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
+
+	kernel_entry = (void (*)(void *fdt_addr))images->ep;
+
+	debug("## Transferring control to Linux (at address %lx)" \
+		"...\n", (ulong)kernel_entry);
+	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
+
+	announce_and_cleanup(fake);
+
+	if (!fake)
+		kernel_entry(images->ft_addr);
+}
+
+/* Main Entry point for arm bootm implementation
+ *
+ * Modeled after the powerpc implementation
+ * DIFFERENCE: Instead of calling prep and go at the end
+ * they are called if subcommand is equal 0.
+ */
+int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+{
+	/* No need for those on ARM */
+	if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
+		return -1;
+
+	if (flag & BOOTM_STATE_OS_PREP) {
+		boot_prep_linux(images);
+		return 0;
+	}
+
+	if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
+		boot_jump_linux(images, flag);
+		return 0;
+	}
+
+	boot_prep_linux(images);
+	boot_jump_linux(images, flag);
+	return 0;
+}
+
+#ifdef CONFIG_CMD_BOOTZ
+
+struct zimage_header {
+	uint32_t	code[9];
+	uint32_t	zi_magic;
+	uint32_t	zi_start;
+	uint32_t	zi_end;
+};
+
+#define	LINUX_ARM_ZIMAGE_MAGIC	0x016f2818
+
+int bootz_setup(ulong image, ulong *start, ulong *end)
+{
+	struct zimage_header *zi;
+
+	zi = (struct zimage_header *)map_sysmem(image, 0);
+	if (zi->zi_magic != LINUX_ARM_ZIMAGE_MAGIC) {
+		puts("Bad Linux ARM zImage magic!\n");
+		return 1;
+	}
+
+	*start = zi->zi_start;
+	*end = zi->zi_end;
+
+	printf("Kernel image @ %#08lx [ %#08lx - %#08lx ]\n", image, *start,
+	      *end);
+
+	return 0;
+}
+
+#endif	/* CONFIG_CMD_BOOTZ */
diff --git a/arch/arm64/lib/cache.c b/arch/arm64/lib/cache.c
new file mode 100644
index 0000000..29c1ab2
--- /dev/null
+++ b/arch/arm64/lib/cache.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2013	David Feng <fenghua at phytium.com.cn>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <asm/system.h>
+#include <asm/processor.h>
+#include <asm/arch/mmu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/********************************************************************/
+
+/*
+ * Stub implementations for outer cache operations
+ */
+void __outer_cache_enable(void) {}
+void outer_cache_enable(void)
+	__attribute__((weak, alias("__outer_cache_enable")));
+
+void __outer_cache_disable(void) {}
+void outer_cache_disable(void)
+	__attribute__((weak, alias("__outer_cache_disable")));
+
+void __outer_cache_flush_all(void) {}
+void outer_cache_flush_all(void)
+ 	__attribute__((weak, alias("__outer_cache_flush_all")));
+
+void __outer_cache_inval_all(void) {}
+void outer_cache_inval_all(void)
+	__attribute__((weak, alias("__outer_cache_inval_all")));
+
+void __outer_cache_flush_range(unsigned long start, unsigned long end) {}
+void outer_cache_flush_range(unsigned long start, unsigned long end)
+	__attribute__((weak, alias("__outer_cache_flush_range")));
+
+void __outer_cache_inval_range(unsigned long start, unsigned long end) {}
+void outer_cache_inval_range(unsigned long start, unsigned long end)
+	__attribute__((weak, alias("__outer_cache_inval_range")));
+
+/********************************************************************/
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+
+static void set_section_dcache(u64 section, u64 memory_type)
+{
+	u64 *page_table = (u64 *)gd->arch.tlb_addr;
+	u64 value;
+
+	value = (section << SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF;
+	value |= PMD_ATTRINDX(memory_type);
+	page_table[section] = value;
+}
+
+/* to activate the MMU we need to set up virtual memory */
+static inline void mmu_setup(void)
+{
+	int i, j;
+	bd_t *bd = gd->bd;
+	static int table_initialized = 0;
+
+	if (!table_initialized) {
+		/* Setup an identity-mapping for all spaces */
+		for (i = 0; i < (PAGE_SIZE >> 3); i++)
+			set_section_dcache(i, MT_DEVICE_nGnRnE);
+
+		/* Setup an identity-mapping for all RAM space */
+		for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+			debug("%s: bank: %d\n", __func__, i);
+			for (j = bd->bi_dram[i].start >> SECTION_SHIFT;
+				 j < (bd->bi_dram[i].start + bd->bi_dram[i].size) >> SECTION_SHIFT;
+				 j++) {
+				set_section_dcache(i, MT_NORMAL);
+			}
+		}
+
+		/* load TTBR0 */
+		asm volatile("msr ttbr0_el2, %0" : : "r" (gd->arch.tlb_addr) : "memory");
+
+		table_initialized = 1;
+	}
+
+	/* and enable the mmu */
+	set_sctlr(get_sctlr() | CR_M);
+}
+
+/*
+ * Performs a invalidation of the entire data cache
+ * at all levels
+ */
+void invalidate_dcache_all(void)
+{
+	__flush_dcache_all();
+	outer_cache_inval_all();
+}
+
+/*
+ * Performs a clean & invalidation of the entire data cache
+ * at all levels
+ */
+void flush_dcache_all(void)
+{
+	__flush_dcache_all();
+	outer_cache_flush_all();
+}
+
+/*
+ * Invalidates range in all levels of D-cache/unified cache used:
+ * Affects the range [start, stop - 1]
+ */
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+	__flush_dcache_range(start, stop);
+	outer_cache_inval_range(start, stop);
+}
+
+/*
+ * Flush range(clean & invalidate) from all levels of D-cache/unified
+ * cache used:
+ * Affects the range [start, stop - 1]
+ */
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+	__flush_dcache_range(start, stop);
+	outer_cache_flush_range(start, stop);
+}
+
+void dcache_enable(void)
+{
+	uint32_t sctlr;
+
+	sctlr = get_sctlr();
+
+	/* The data cache is not active unless the mmu is enabled too */
+	if (!(sctlr & CR_M)) {
+		outer_cache_enable();
+		invalidate_dcache_all();
+		__invalidate_tlb_all();
+
+		mmu_setup();
+	}
+
+	set_sctlr(sctlr | CR_C);
+}
+
+void dcache_disable(void)
+{
+	uint32_t sctlr;
+
+	sctlr = get_sctlr();
+
+	/* if cache isn't enabled no need to disable */
+	if (!(sctlr & CR_C))
+		return;
+
+	set_sctlr(sctlr & ~(CR_C|CR_M));
+
+	flush_dcache_all();
+	__invalidate_tlb_all();
+}
+
+int dcache_status(void)
+{
+	return (get_sctlr() & CR_C) != 0;
+}
+
+#else
+
+void invalidate_dcache_all(void)
+{
+}
+
+void flush_dcache_all(void)
+{
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
+void dcache_enable(void)
+{
+}
+
+void dcache_disable(void)
+{
+}
+
+int dcache_status(void)
+{
+	return 0;
+}
+
+#endif /* CONFIG_SYS_DCACHE_OFF */
+
+/********************************************************************/
+
+#ifndef CONFIG_SYS_ICACHE_OFF
+
+void icache_enable(void)
+{
+	set_sctlr(get_sctlr() | CR_I);
+}
+
+void icache_disable(void)
+{
+	set_sctlr(get_sctlr() & ~CR_I);
+}
+
+int icache_status(void)
+{
+	return (get_sctlr() & CR_I) != 0;
+}
+
+void invalidate_icache_all(void)
+{
+	__invalidate_icache_all();
+}
+
+#else
+
+void icache_enable(void)
+{
+}
+
+void icache_disable(void)
+{
+}
+
+int icache_status(void)
+{
+	return 0;
+}
+
+void invalidate_icache_all(void)
+{
+}
+
+#endif /* CONFIG_SYS_ICACHE_OFF */
+
+/********************************************************************/
+
+/*
+ * Enable dCache & iCache, whether cache is actually enabled
+ * depend on CONFIG_SYS_DCACHE_OFF and CONFIG_SYS_ICACHE_OFF
+ */
+void enable_caches(void)
+{
+	icache_enable();
+	dcache_enable();
+}
+
+/*
+ * Flush range from all levels of d-cache/unified-cache used:
+ * Affects the range [start, start + size - 1]
+ */
+void flush_cache(unsigned long start, unsigned long size)
+{
+	flush_dcache_range(start, start + size);
+}
diff --git a/arch/arm64/lib/crt0.S b/arch/arm64/lib/crt0.S
new file mode 100644
index 0000000..d18a2dd
--- /dev/null
+++ b/arch/arm64/lib/crt0.S
@@ -0,0 +1,129 @@
+/*
+ * crt0 - C-runtime startup Code for ARM64 U-Boot
+ *
+ * Copyright (c) 2013  David Feng <fenghua at phytium.com.cn>
+ *
+ * Bsed on arm/lib/crt0.S by Albert ARIBAUD <albert.u.boot at aribaud.net>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <config.h>
+#include <asm-offsets.h>
+#include <linux/linkage.h>
+
+/*
+ * This file handles the target-independent stages of the U-Boot
+ * start-up where a C runtime environment is needed. Its entry point
+ * is _main and is branched into from the target's start.S file.
+ *
+ * _main execution sequence is:
+ *
+ * 1. Set up initial environment for calling board_init_f().
+ *    This environment only provides a stack and a place to store
+ *    the GD ('global data') structure, both located in some readily
+ *    available RAM (SRAM, locked cache...). In this context, VARIABLE
+ *    global data, initialized or not (BSS), are UNAVAILABLE; only
+ *    CONSTANT initialized data are available.
+ *
+ * 2. Call board_init_f(). This function prepares the hardware for
+ *    execution from system RAM (DRAM, DDR...) As system RAM may not
+ *    be available yet, , board_init_f() must use the current GD to
+ *    store any data which must be passed on to later stages. These
+ *    data include the relocation destination, the future stack, and
+ *    the future GD location.
+ *
+ * (the following applies only to non-SPL builds)
+ *
+ * 3. Set up intermediate environment where the stack and GD are the
+ *    ones allocated by board_init_f() in system RAM, but BSS and
+ *    initialized non-const data are still not available.
+ *
+ * 4. Call relocate_code(). This function relocates U-Boot from its
+ *    current location into the relocation destination computed by
+ *    board_init_f().
+ *
+ * 5. Set up final environment for calling board_init_r(). This
+ *    environment has BSS (initialized to 0), initialized non-const
+ *    data (initialized to their intended value), and stack in system
+ *    RAM. GD has retained values set by board_init_f(). Some CPUs
+ *    have some work left to do at this point regarding memory, so
+ *    call c_runtime_cpu_setup.
+ *
+ * 6. Branch to board_init_r().
+ */
+
+ENTRY(_main)
+
+/*
+ * Set up initial C runtime environment and call board_init_f(0).
+ */
+	ldr	x0, =(CONFIG_SYS_INIT_SP_ADDR)
+	sub	x0, x0, #GD_SIZE	/* allocate one GD above SP */
+	bic	sp, x0, #0xf		/* 16-byte alignment for ABI compliance */
+	mov	x18, sp			/* GD is above SP */
+	mov	x0, #0
+	bl	board_init_f
+
+/*
+ * Set up intermediate environment (new sp and gd) and call
+ * relocate_code(addr_moni). Trick here is that we'll return
+ * 'here' but relocated.
+ */
+	ldr	x0, [x18, #GD_START_ADDR_SP]	/* x0 = gd->start_addr_sp */
+	bic	sp, x0, #0xf			/* 16-byte alignment for ABI compliance */
+	ldr	x18, [x18, #GD_BD]		/* x18 = gd->bd */
+	sub	x18, x18, #GD_SIZE		/* new GD is below bd */
+
+	adr	lr, relocation_return
+	ldr	x9, [x18, #GD_RELOC_OFF]	/* x0 = gd->reloc_off */
+	add	lr, lr, x9			/* new return address after relocation */
+	ldr	x0, [x18, #GD_RELOCADDR]	/* x0 = gd->relocaddr */
+	b	relocate_code
+
+relocation_return:
+
+/*
+ * Set up final (full) environment
+ */
+	bl	c_runtime_cpu_setup		/* we still call old routine here */
+
+/*
+ * Clear BSS section
+ */
+	ldr	x9, [x18, #GD_RELOC_OFF]	/* x9 = gd->reloc_off */
+	ldr	x0, =__bss_start		/* x0 = __bss_start in FLASH */
+	add	x0, x0, x9			/* x0 = __bss_start in RAM */
+	ldr	x1, =__bss_end			/* x1 = __bss_end in FLASH */
+	add	x1, x1, x9			/* x1 = __bss_end in RAM */
+	mov	x2, #0
+clear_loop:
+	str	x2, [x0]
+	add	x0, x0, #8
+	cmp	x0, x1
+	b.lo	clear_loop
+
+	/* call board_init_r(gd_t *id, ulong dest_addr) */
+	mov	x0, x18				/* gd_t */
+	ldr	x1, [x18, #GD_RELOCADDR]	/* dest_addr */
+	b	board_init_r			/* PC relative jump */
+
+	/* NOTREACHED - board_init_r() does not return */
+
+ENDPROC(_main)
diff --git a/arch/arm64/lib/interrupts.c b/arch/arm64/lib/interrupts.c
new file mode 100644
index 0000000..b843785
--- /dev/null
+++ b/arch/arm64/lib/interrupts.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013	David Feng <fenghua at phytium.com.cn>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const char *handler[]= {
+	"Synchronous Abort",
+	"IRQ",
+	"FIQ",
+	"Error"
+};
+
+#ifdef CONFIG_USE_IRQ
+int interrupt_init (void)
+{
+	return 0;
+}
+
+/* enable IRQ interrupts */
+void enable_interrupts (void)
+{
+}
+
+/*
+ * disable IRQ/FIQ interrupts
+ * returns true if interrupts had been enabled before we disabled them
+ */
+int disable_interrupts (void)
+{
+	return 0;
+}
+#else
+int interrupt_init (void)
+{
+	return 0;
+}
+
+void enable_interrupts (void)
+{
+	return;
+}
+int disable_interrupts (void)
+{
+	return 0;
+}
+#endif /* CONFIG_USE_IRQ */
+
+
+void show_regs (struct pt_regs *regs)
+{
+	int i;
+
+	printf("PC is at %lx\n", regs->pc);
+	printf("LR is at %lx\n", regs->regs[30]);
+	printf("PSTATE: %08lx\n", regs->pstate);
+	printf("SP : %lx\n", regs->sp);
+	for (i = 29; i >= 0; i--) {
+		printf("x%-2d: %016lx ", i, regs->regs[i]);
+		if (i % 2 == 0)
+			printf("\n");
+	}
+	printf("\n");
+}
+
+/*
+ * bad_mode handles the impossible case in the exception vector.
+ */
+void bad_mode(struct pt_regs *pt_regs, int reason, unsigned int esr)
+{
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+	static int relocated = 0;
+
+	/* relocate boot function table */
+	if (!relocated) {
+		int i;
+		for (i = 0; i < ARRAY_SIZE(handler); i++)
+			handler[i] += gd->reloc_off;
+		relocated = 1;
+	}
+#endif
+
+	printf("Bad mode in \"%s\" handler detected, esr 0x%08x\n",
+		handler[reason], esr);
+
+	show_regs(pt_regs);
+
+	panic("Resetting CPU ...\n");
+}
diff --git a/arch/arm64/lib/relocate.S b/arch/arm64/lib/relocate.S
new file mode 100644
index 0000000..6bbcc2a
--- /dev/null
+++ b/arch/arm64/lib/relocate.S
@@ -0,0 +1,72 @@
+/*
+ * relocate - common relocation function for ARM64 U-Boot
+ *
+ * Copyright (c) 2013	David Feng <fenghua at phytium.com.cn>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+
+/*
+ * void relocate_code (addr_moni)
+ *
+ * This function relocates the monitor code.
+ *
+ * NOTE:
+ * Currently, ld with -pie produce errors. So, GOT is used
+ * and configuration CONFIG_NEEDS_MANUAL_RELOC is needed.
+ */
+ENTRY(relocate_code)
+	/*
+	 * Copy u-boot from flash to RAM
+	 */
+	ldr	x1, =__image_copy_start	/* x1 <- copy source */
+	cmp	x1, x0
+	b.eq	relocate_done		/* skip relocation */
+	mov	x2, x0			/* x2 <- copy destination */
+	ldr	x3, =__image_copy_end	/* x3 <- source end address */
+
+copy_loop:
+	ldp	x10, x11, [x1], #16	/* copy from source address [x1] */
+	stp	x10, x11, [x2], #16	/* copy to   target address [x2] */
+	cmp	x1, x3			/* until source end address [x3] */
+	b.lo	copy_loop
+
+	/*
+	 * Fix .reloc relocations
+	 */
+	ldr	x9, [x18, #GD_RELOC_OFF]/* x9 <- relocation offset */
+	ldr	x1, =__rel_got_start	/* x1 <- rel got start ofs */
+	add	x1, x1, x9		/* x1 <- rel got start in RAM */
+	ldr	x2, =__rel_got_end	/* x2 <- rel got end ofs */
+	add	x2, x2, x9		/* x2 <- rel got end in RAM */
+fixloop:
+	ldr	x10, [x1]		/* x10 <- address to be fixed up */
+	add	x10, x10, x9		/* x10 <- address to be fixed up in RAM*/
+	str	x10, [x1]
+	add	x1, x1, #8		/* each gotn entry is 8 bytes */
+	cmp	x1, x2
+	b.lo	fixloop
+
+relocate_done:
+	ret
+ENDPROC(relocate_code)
diff --git a/arch/arm64/lib/reset.c b/arch/arm64/lib/reset.c
new file mode 100644
index 0000000..32de7a3
--- /dev/null
+++ b/arch/arm64/lib/reset.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013	David Feng <fenghua at phytium.com.cn>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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>
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	puts("Resetting system ...\n");
+
+	udelay(50000);		/* wait 50 ms */
+
+	disable_interrupts();
+
+	reset_cpu(0);
+
+	/*NOTREACHED*/
+	return 0;
+}
diff --git a/arch/arm64/lib/timer.c b/arch/arm64/lib/timer.c
new file mode 100644
index 0000000..8c0cfcb
--- /dev/null
+++ b/arch/arm64/lib/timer.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013	David Feng <fenghua at phytium.com.cn>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <div64.h>
+
+/*
+ * Genertic Timer implementation of __udelay/get_timer/get_ticks/get_tbclk
+ * functions. If any other timers used, another implementation should be
+ * placed in platform code.
+ */
+
+static inline unsigned long tick_to_time(unsigned long tick)
+{
+	tick *= CONFIG_SYS_HZ;
+	do_div(tick, CONFIG_SYS_CNTFRQ);
+	return tick;
+}
+
+static inline unsigned long time_to_tick(unsigned long time)
+{
+	time *= CONFIG_SYS_CNTFRQ;
+	do_div(time, CONFIG_SYS_HZ);
+	return time;
+}
+
+/*
+ * Generic timer implementation of get_tbclk()
+ */
+ulong __get_tbclk (void)
+{
+	return CONFIG_SYS_HZ;
+}
+ulong get_tbclk(void)
+	__attribute__((weak, alias("__get_tbclk")));
+
+/*
+ * Generic timer implementation of get_timer()
+ */
+ulong __get_timer(ulong base)
+{
+	u64 cval;
+
+	isb();
+	asm volatile("mrs %0, cntpct_el0" : "=r" (cval));
+
+	tick_to_time(cval);
+
+	return tick_to_time(cval) - base;
+}
+ulong get_timer(ulong base)
+	__attribute__((weak, alias("__get_timer")));
+
+/*
+ * Generic timer implementation of get_ticks()
+ */
+unsigned long long __get_ticks(void)
+{
+	return get_timer(0);
+}
+unsigned long long get_ticks(void)
+	__attribute__((weak, alias("__get_ticks")));
+
+/*
+ * Generic timer implementation of __udelay()
+ */
+void ___udelay(ulong usec)
+{
+	unsigned long tmp;
+
+	tmp = get_ticks() + usec/1000;
+
+	while (get_ticks() < tmp);
+}
+void __udelay(ulong usec)
+	__attribute__((weak, alias("___udelay")));
diff --git a/board/armltd/dts/vexpress64.dts b/board/armltd/dts/vexpress64.dts
new file mode 100644
index 0000000..3814e01
--- /dev/null
+++ b/board/armltd/dts/vexpress64.dts
@@ -0,0 +1,215 @@
+/*
+ * ARM Ltd. Fast Models
+ *
+ * Architecture Envelope Model (AEM) ARMv8-A
+ * ARMAEMv8AMPCT
+ *
+ * RTSM_VE_AEMv8A.lisa
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x80000000 0x00010000;
+
+/ {
+	/* boot configurations for u-boot */
+	config {
+		/*bootdelay = <1>;*/
+		kernel-offset = <0x100000>;
+		rootdisk-offset = <0x800000>;
+		bootcmd = "bootm 0x100000 0x800000:0x2000000";
+	};
+};
+
+/ {
+	model = "RTSM_VE_AEMv8A";
+	compatible = "arm,rtsm_ve,aemv8a", "arm,vexpress";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	/* chosen */
+	/* generated by u-boot */
+
+
+	aliases {
+		serial0 = &v2m_serial0;
+		serial1 = &v2m_serial1;
+		serial2 = &v2m_serial2;
+		serial3 = &v2m_serial3;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x8000fff8>;
+		};
+		cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <1>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x8000fff8>;
+		};
+		cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <2>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x8000fff8>;
+		};
+		cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <3>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x8000fff8>;
+		};
+	};
+
+	memory at 80000000 {
+		device_type = "memory";
+		reg = <0x00000000 0x80000000 0 0x80000000>,
+		      <0x00000008 0x80000000 0 0x80000000>;
+	};
+
+	gic: interrupt-controller at 2c001000 {
+		compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+		reg = <0x0 0x2c001000 0 0x1000>,
+		      <0x0 0x2c002000 0 0x1000>,
+		      <0x0 0x2c004000 0 0x2000>,
+		      <0x0 0x2c006000 0 0x2000>;
+		interrupts = <1 9 0xf04>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <1 13 0xff01>,
+			     <1 14 0xff01>,
+			     <1 11 0xff01>,
+			     <1 10 0xff01>;
+		clock-frequency = <100000000>;
+	};
+
+	pmu {
+		compatible = "arm,armv8-pmuv3";
+		interrupts = <0 60 4>,
+			     <0 61 4>,
+			     <0 62 4>,
+			     <0 63 4>;
+	};
+
+	smb {
+		compatible = "simple-bus";
+
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <0 0 0 0x08000000 0x04000000>,
+			 <1 0 0 0x14000000 0x04000000>,
+			 <2 0 0 0x18000000 0x04000000>,
+			 <3 0 0 0x1c000000 0x04000000>,
+			 <4 0 0 0x0c000000 0x04000000>,
+			 <5 0 0 0x10000000 0x04000000>;
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 63>;
+		interrupt-map = <0 0  0 &gic 0  0 4>,
+				<0 0  1 &gic 0  1 4>,
+				<0 0  2 &gic 0  2 4>,
+				<0 0  3 &gic 0  3 4>,
+				<0 0  4 &gic 0  4 4>,
+				<0 0  5 &gic 0  5 4>,
+				<0 0  6 &gic 0  6 4>,
+				<0 0  7 &gic 0  7 4>,
+				<0 0  8 &gic 0  8 4>,
+				<0 0  9 &gic 0  9 4>,
+				<0 0 10 &gic 0 10 4>,
+				<0 0 11 &gic 0 11 4>,
+				<0 0 12 &gic 0 12 4>,
+				<0 0 13 &gic 0 13 4>,
+				<0 0 14 &gic 0 14 4>,
+				<0 0 15 &gic 0 15 4>,
+				<0 0 16 &gic 0 16 4>,
+				<0 0 17 &gic 0 17 4>,
+				<0 0 18 &gic 0 18 4>,
+				<0 0 19 &gic 0 19 4>,
+				<0 0 20 &gic 0 20 4>,
+				<0 0 21 &gic 0 21 4>,
+				<0 0 22 &gic 0 22 4>,
+				<0 0 23 &gic 0 23 4>,
+				<0 0 24 &gic 0 24 4>,
+				<0 0 25 &gic 0 25 4>,
+				<0 0 26 &gic 0 26 4>,
+				<0 0 27 &gic 0 27 4>,
+				<0 0 28 &gic 0 28 4>,
+				<0 0 29 &gic 0 29 4>,
+				<0 0 30 &gic 0 30 4>,
+				<0 0 31 &gic 0 31 4>,
+				<0 0 32 &gic 0 32 4>,
+				<0 0 33 &gic 0 33 4>,
+				<0 0 34 &gic 0 34 4>,
+				<0 0 35 &gic 0 35 4>,
+				<0 0 36 &gic 0 36 4>,
+				<0 0 37 &gic 0 37 4>,
+				<0 0 38 &gic 0 38 4>,
+				<0 0 39 &gic 0 39 4>,
+				<0 0 40 &gic 0 40 4>,
+				<0 0 41 &gic 0 41 4>,
+				<0 0 42 &gic 0 42 4>;
+
+		/include/ "aemv8a.dtsi"
+	};
+
+	panels {
+		panel at 0 {
+			compatible	= "panel";
+			mode		= "VGA";
+			refresh		= <60>;
+			xres		= <640>;
+			yres		= <480>;
+			pixclock	= <39721>;
+			left_margin	= <40>;
+			right_margin	= <24>;
+			upper_margin	= <32>;
+			lower_margin	= <11>;
+			hsync_len	= <96>;
+			vsync_len	= <2>;
+			sync		= <0>;
+			vmode		= "FB_VMODE_NONINTERLACED";
+			tim2		= "TIM2_BCD", "TIM2_IPC";
+			cntl		= "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)";
+			caps		= "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888";
+			bpp		= <16>;
+		};
+
+		panel at 1 {
+			compatible	= "panel";
+			mode		= "XVGA";
+			refresh		= <60>;
+			xres		= <1024>;
+			yres		= <768>;
+			pixclock	= <15748>;
+			left_margin	= <152>;
+			right_margin	= <48>;
+			upper_margin	= <23>;
+			lower_margin	= <3>;
+			hsync_len	= <104>;
+			vsync_len	= <4>;
+			sync		= <0>;
+			vmode		= "FB_VMODE_NONINTERLACED";
+			tim2		= "TIM2_BCD", "TIM2_IPC";
+			cntl		= "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)";
+			caps		= "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888";
+			bpp		= <16>;
+		};
+	};
+};
diff --git a/board/armltd/vexpress64/Makefile b/board/armltd/vexpress64/Makefile
new file mode 100644
index 0000000..77f0c3f
--- /dev/null
+++ b/board/armltd/vexpress64/Makefile
@@ -0,0 +1,43 @@
+#
+# (C) Copyright 2000-2004
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).o
+
+COBJS	:= vexpress64.o
+
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c
new file mode 100644
index 0000000..b86736d
--- /dev/null
+++ b/board/armltd/vexpress64/vexpress64.c
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2013
+ * Phytium Technology, <www.phytium.com.cn>
+ * David Feng, fenghua at phytium.com.cn
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <malloc.h>
+#include <errno.h>
+#include <netdev.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Board specific reset that is system reset.
+ */
+void reset_cpu(ulong addr)
+{
+}
+
+/*
+ * Default implementation of gpio related functiuons
+ * Real implementation should be in gpio driver.
+ * fdtdec.c need this function, but currenty no gpio driver defined
+ */
+int __gpio_get_value(unsigned gpio)
+{
+	return 0;
+}
+int gpio_get_value(unsigned gpio)
+	__attribute__((weak, alias("__gpio_get_value")));
+
+void __gpio_set_value(unsigned gpio, int vlaue)
+{
+	return;
+}
+void gpio_set_value(unsigned gpio, int vlaue)
+	__attribute__((weak, alias("__gpio_set_value")));
+
+void __gpio_request(unsigned gpio, const char *label)
+{
+	return;
+}
+void gpio_request(unsigned gpio, const char *label)
+	__attribute__((weak, alias("__gpio_request")));
diff --git a/boards.cfg b/boards.cfg
index 944ed4c..561b0d6 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -1182,5 +1182,6 @@ gr_ep2s60                    sparc       leon3       -                   gaisler
 grsim                        sparc       leon3       -                   gaisler
 gr_xc3s_1500                 sparc       leon3       -                   gaisler
 coreboot-x86                 x86         x86        coreboot            chromebook-x86 coreboot    coreboot:SYS_TEXT_BASE=0x01110000
+vexpress_aemv8a              arm64       armv8       vexpress64          armltd
 # Target                     ARCH        CPU         Board name          Vendor	        SoC         Options
 ########################################################################################################################
diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index af884b8..4a7b61b 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -517,6 +517,38 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	return 0;
 }
 
+#elif defined(CONFIG_ARM64)
+
+int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int i;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
+		print_num("DRAM bank",	i);
+		print_num("  -> start",	gd->bd->bi_dram[i].start);
+		print_num("  -> size",	gd->bd->bi_dram[i].size);
+	}
+
+	printf("baudrate    = %ld bps\n", gd->bd->bi_baudrate);
+
+	print_num("relocaddr", gd->relocaddr);
+	print_num("reloc off", gd->reloc_off);
+	print_num("sp start ", gd->start_addr_sp);
+#ifndef CONFIG_SYS_DCACHE_OFF
+	print_num("TLB addr", gd->arch.tlb_addr);
+#endif
+
+	printf("CPU frequency = %ld MHz\n", gd->cpu_clk);
+	printf("DDR frequency = %ld MHz\n", gd->mem_clk);
+
+#if defined(CONFIG_CMD_NET)
+	print_eth(0);
+	printf("ip_addr     = %s\n", getenv("ipaddr"));
+#endif
+
+	return 0;
+}
+
 #else
  #error "a case for this architecture does not exist!"
 #endif
diff --git a/common/fdt_support.c b/common/fdt_support.c
index b034c98..9bc5821 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -21,6 +21,34 @@
  */
 DECLARE_GLOBAL_DATA_PTR;
 
+/*
+ * Get cells len in bytes
+ *     if #NNNN-cells property is 2 then len is 8
+ *     otherwise len is 4
+ */
+static int get_cells_len(void *blob, char *nr_cells_name)
+{
+	const fdt32_t *cell;
+
+	cell = fdt_getprop(blob, 0, nr_cells_name, NULL);
+	if (cell && fdt32_to_cpu(*cell) == 2)
+		return 8;
+
+	return 4;
+}
+
+/*
+ * Write a 4 or 8 byte big endian cell
+ */
+static void write_cell(u8 *addr, u64 val, int size)
+{
+	int shift = (size - 1) * 8;
+	while (size-- > 0) {
+		*addr++ = (val >> shift) & 0xff;
+		shift -= 8;
+	}
+}
+
 /**
  * fdt_getprop_u32_default - Find a node and return it's property or a default
  *
@@ -131,9 +159,9 @@ static int fdt_fixup_stdout(void *fdt, int chosenoff)
 
 int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force)
 {
-	int   nodeoffset;
+	int   nodeoffset, addr_cell_len;
 	int   err, j, total;
-	fdt32_t  tmp;
+	fdt64_t  tmp;
 	const char *path;
 	uint64_t addr, size;
 
@@ -170,9 +198,11 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force)
 		return err;
 	}
 
+	addr_cell_len = get_cells_len(fdt, "#address-cells");
+
 	path = fdt_getprop(fdt, nodeoffset, "linux,initrd-start", NULL);
 	if ((path == NULL) || force) {
-		tmp = cpu_to_fdt32(initrd_start);
+		write_cell((u8 *)&tmp, initrd_start, addr_cell_len);
 		err = fdt_setprop(fdt, nodeoffset,
 			"linux,initrd-start", &tmp, sizeof(tmp));
 		if (err < 0) {
@@ -181,7 +211,7 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force)
 				fdt_strerror(err));
 			return err;
 		}
-		tmp = cpu_to_fdt32(initrd_end);
+		write_cell((u8 *)&tmp, initrd_end, addr_cell_len);
 		err = fdt_setprop(fdt, nodeoffset,
 			"linux,initrd-end", &tmp, sizeof(tmp));
 		if (err < 0) {
@@ -343,34 +373,6 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat,
 	do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create);
 }
 
-/*
- * Get cells len in bytes
- *     if #NNNN-cells property is 2 then len is 8
- *     otherwise len is 4
- */
-static int get_cells_len(void *blob, char *nr_cells_name)
-{
-	const fdt32_t *cell;
-
-	cell = fdt_getprop(blob, 0, nr_cells_name, NULL);
-	if (cell && fdt32_to_cpu(*cell) == 2)
-		return 8;
-
-	return 4;
-}
-
-/*
- * Write a 4 or 8 byte big endian cell
- */
-static void write_cell(u8 *addr, u64 val, int size)
-{
-	int shift = (size - 1) * 8;
-	while (size-- > 0) {
-		*addr++ = (val >> shift) & 0xff;
-		shift -= 8;
-	}
-}
-
 #ifdef CONFIG_NR_DRAM_BANKS
 #define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS
 #else
diff --git a/common/image.c b/common/image.c
index 56a5a62..7a24550 100644
--- a/common/image.c
+++ b/common/image.c
@@ -81,6 +81,7 @@ static const table_entry_t uimage_arch[] = {
 	{	IH_ARCH_NDS32,		"nds32",	"NDS32",	},
 	{	IH_ARCH_OPENRISC,	"or1k",		"OpenRISC 1000",},
 	{	IH_ARCH_SANDBOX,	"sandbox",	"Sandbox",	},
+	{	IH_ARCH_ARM64,		"arm64",	"ARM64",	},
 	{	-1,			"",		"",		},
 };
 
@@ -422,7 +423,7 @@ ulong getenv_bootm_low(void)
 
 #if defined(CONFIG_SYS_SDRAM_BASE)
 	return CONFIG_SYS_SDRAM_BASE;
-#elif defined(CONFIG_ARM)
+#elif defined(CONFIG_ARM) || defined(CONFIG_ARM64)
 	return gd->bd->bi_dram[0].start;
 #else
 	return 0;
@@ -444,7 +445,7 @@ phys_size_t getenv_bootm_size(void)
 		tmp = 0;
 
 
-#if defined(CONFIG_ARM)
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
 	return gd->bd->bi_dram[0].size - tmp;
 #else
 	return gd->bd->bi_memsize - tmp;
diff --git a/doc/README.arm64 b/doc/README.arm64
new file mode 100644
index 0000000..8fef26d
--- /dev/null
+++ b/doc/README.arm64
@@ -0,0 +1,10 @@
+Notes:
+
+1. Currenly, u-boot running at EL2.
+
+2. Currently, gcc-aarch64 produce error when compiling with pie and rel_dyn.
+   So, GOT is used to relocate u-boot and CONFIG_NEEDS_MANUAL_RELOC is needed.
+
+3. Currently, fdt should be in the first 512MB of RAM, so, fdt_high should be handled specially.
+   I define fdt_high as 0xa0000000 when CONFIG_SYS_SDRAM_BASE is 0x80000000.
+
diff --git a/examples/standalone/stubs.c b/examples/standalone/stubs.c
index 8fb1765..4e39b1b 100644
--- a/examples/standalone/stubs.c
+++ b/examples/standalone/stubs.c
@@ -195,6 +195,19 @@ gd_t *global_data;
 "	l.jr	r13\n"		\
 "	l.nop\n"				\
 	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r13");
+#elif defined(CONFIG_ARM64)
+/*
+ * x18 holds the pointer to the global_data, ip is a call-clobbered
+ * register
+ */
+#define EXPORT_FUNC(x) \
+	asm volatile (			\
+"	.globl " #x "\n"		\
+#x ":\n"				\
+"	ldr	x19, [x18, %0]\n"		\
+"	ldr	x19, [x19, %1]\n"		\
+"	br	x19\n"		\
+	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "x19");
 #else
 /*"	addi	$sp, $sp, -24\n"	\
 "	br	$r16\n"			\*/
diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8a.h
new file mode 100644
index 0000000..3c96987
--- /dev/null
+++ b/include/configs/vexpress_aemv8a.h
@@ -0,0 +1,200 @@
+/*
+ * Configuration for Versatile Express. Parts were derived from other ARM
+ *   configurations.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+#ifndef __VEXPRESS_AEMV8A_H
+#define __VEXPRESS_AEMV8A_H
+
+#define DEBUG
+
+#define CONFIG_SYS_NO_FLASH
+
+#define CONFIG_SUPPORT_RAW_INITRD
+
+#define CONFIG_SKIP_LOWLEVEL_INIT
+
+/* Cache Definitions */
+//#define CONFIG_SYS_DCACHE_OFF
+//#define CONFIG_SYS_ICACHE_OFF
+
+#define CONFIG_IDENT_STRING		" aarch64"
+#define CONFIG_BOOTP_VCI_STRING    	"U-boot.armv8.vexpress_aemv8a"
+
+/* Link Definitions */
+#define CONFIG_SYS_TEXT_BASE		0x80000000
+#define CONFIG_SYS_INIT_SP_ADDR         (CONFIG_SYS_SDRAM_BASE + 0x400000)
+
+/* Flat Device Tree Definitions */
+#define CONFIG_OF_EMBED
+#define CONFIG_OF_CONTROL
+#define CONFIG_OF_LIBFDT
+
+#define CONFIG_DEFAULT_DEVICE_TREE	vexpress64
+
+/* SMP Definitions */
+#define SECONDARY_CPU_MAILBOX		0x8000fff8
+
+/* CS register bases for the original memory map. */
+#define V2M_PA_CS0			0x00000000
+#define V2M_PA_CS1			0x14000000
+#define V2M_PA_CS2			0x18000000
+#define V2M_PA_CS3			0x1c000000
+#define V2M_PA_CS4			0x0c000000
+#define V2M_PA_CS5			0x10000000
+
+#define V2M_PERIPH_OFFSET(x)		(x << 16)
+#define V2M_SYSREGS			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(1))
+#define V2M_SYSCTL			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(2))
+#define V2M_SERIAL_BUS_PCI		(V2M_PA_CS3 + V2M_PERIPH_OFFSET(3))
+
+#define V2M_BASE			0x80000000
+
+/*
+ * Physical addresses, offset from V2M_PA_CS0-3
+ */
+#define V2M_NOR0			(V2M_PA_CS0)
+#define V2M_NOR1			(V2M_PA_CS4)
+#define V2M_SRAM			(V2M_PA_CS1)
+
+/* Common peripherals relative to CS7. */
+#define V2M_AACI			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(4))
+#define V2M_MMCI			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(5))
+#define V2M_KMI0			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(6))
+#define V2M_KMI1			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(7))
+
+#define V2M_UART0			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(9))
+#define V2M_UART1			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(10))
+#define V2M_UART2			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(11))
+#define V2M_UART3			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(12))
+
+#define V2M_WDT				(V2M_PA_CS3 + V2M_PERIPH_OFFSET(15))
+
+#define V2M_TIMER01			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(17))
+#define V2M_TIMER23			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(18))
+
+#define V2M_SERIAL_BUS_DVI		(V2M_PA_CS3 + V2M_PERIPH_OFFSET(22))
+#define V2M_RTC				(V2M_PA_CS3 + V2M_PERIPH_OFFSET(23))
+
+#define V2M_CF				(V2M_PA_CS3 + V2M_PERIPH_OFFSET(26))
+
+#define V2M_CLCD			(V2M_PA_CS3 + V2M_PERIPH_OFFSET(31))
+
+/* System register offsets. */
+#define V2M_SYS_CFGDATA			(V2M_SYSREGS + 0x0a0)
+#define V2M_SYS_CFGCTRL			(V2M_SYSREGS + 0x0a4)
+#define V2M_SYS_CFGSTAT			(V2M_SYSREGS + 0x0a8)
+
+/* Generic Timer Definitions */
+#define CONFIG_SYS_CNTFRQ		(0x1800000)	/* 24MHz */
+
+/* Generic Interrupt Controller Definitions */
+#define GIC_DIST_BASE			(0x2C001000)
+#define GIC_CPU_BASE			(0x2C002000)
+
+#define CONFIG_SYS_MEMTEST_START	V2M_BASE
+#define CONFIG_SYS_MEMTEST_END		(V2M_BASE + 0x80000000)
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + 128 * 1024)
+
+/* PL011 Serial Configuration */
+#define CONFIG_PL011_SERIAL
+#define CONFIG_PL011_CLOCK		24000000
+#define CONFIG_PL01x_PORTS		{(void *)CONFIG_SYS_SERIAL0, \
+					 (void *)CONFIG_SYS_SERIAL1}
+#define CONFIG_CONS_INDEX		0
+
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+#define CONFIG_SYS_SERIAL0		V2M_UART0
+#define CONFIG_SYS_SERIAL1		V2M_UART1
+
+/* Command line configuration */
+#define CONFIG_MENU
+//#define CONFIG_MENU_SHOW
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_BDI
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_PXE
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_FLASH
+#define CONFIG_CMD_IMI
+#define CONFIG_CMD_MEMORY
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_SAVEENV
+#define CONFIG_CMD_RUN
+#define CONFIG_CMD_BOOTD
+#define CONFIG_CMD_ECHO
+#define CONFIG_CMD_SOURCE
+#define CONFIG_CMD_FAT
+#define CONFIG_DOS_PARTITION
+
+/* BOOTP options */
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+#define CONFIG_BOOTP_PXE
+#define CONFIG_BOOTP_PXE_CLIENTARCH	0x100
+
+/* Miscellaneous configurable options */
+#define CONFIG_SYS_LOAD_ADDR		(V2M_BASE + 0x10000000)	/* load address */
+
+/* Physical Memory Map */
+#define CONFIG_NR_DRAM_BANKS		1
+#define PHYS_SDRAM_1			(V2M_BASE)	/* SDRAM Bank #1 */
+#define PHYS_SDRAM_1_SIZE		0x80000000	/* 2048 MB */
+#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+
+
+/* Initial environment variables */
+#define CONFIG_EXTRA_ENV_SETTINGS	\
+					"loadaddr=0x80100000\0"		\
+					"kernel_addr=0x100000\0"	\
+					"ramdisk_addr=0x800000\0"	\
+					"ramdisk_size=0x2000000\0"	\
+					"fdt_high=0xa0000000\0"		\
+					"console=ttyAMA0,38400n8\0"
+
+#define CONFIG_BOOTARGS			"console=ttyAMA0 root=/dev/ram0"
+#define CONFIG_BOOTCOMMAND		"bootm $kernel_addr $ramdisk_addr:$ramdisk_size"
+#define CONFIG_BOOTDELAY		-1
+
+/* Store environment at top of flash */
+#define CONFIG_ENV_IS_NOWHERE		1
+#define CONFIG_ENV_SIZE			0x1000
+
+/* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE		512	/* Console I/O Buffer Size */
+#define CONFIG_SYS_PROMPT		"VExpress# "
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
+					sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_HUSH_PARSER
+#define CONFIG_SYS_PROMPT_HUSH_PS2	"> "
+#define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE /* Boot args buffer */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_CMDLINE_EDITING		1
+#define CONFIG_SYS_MAXARGS		64	/* max command args */
+
+#endif /* __VEXPRESS_AEMV8A_H */
diff --git a/include/image.h b/include/image.h
index f93a393..491e547 100644
--- a/include/image.h
+++ b/include/image.h
@@ -156,6 +156,7 @@ struct lmb;
 #define IH_ARCH_SANDBOX		19	/* Sandbox architecture (test only) */
 #define IH_ARCH_NDS32	        20	/* ANDES Technology - NDS32  */
 #define IH_ARCH_OPENRISC        21	/* OpenRISC 1000  */
+#define IH_ARCH_ARM64		22	/* ARM64  */
 
 /*
  * Image Types
diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c
index 6ea7b03..6c53b62 100644
--- a/lib/asm-offsets.c
+++ b/lib/asm-offsets.c
@@ -29,7 +29,7 @@ int main(void)
 
 	DEFINE(GD_BD, offsetof(struct global_data, bd));
 
-#if defined(CONFIG_ARM)
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
 
 	DEFINE(GD_RELOCADDR, offsetof(struct global_data, relocaddr));
 
-- 
1.7.9.5




More information about the U-Boot mailing list