[U-Boot] [PATCH v2 1/4] core support of arm64

fenghua at phytium.com.cn fenghua at phytium.com.cn
Wed Aug 14 12:58:04 CEST 2013


From: David Feng <fenghua at phytium.com.cn>

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

Signed-off-by: David Feng <fenghua at phytium.com.cn>
---
Changes for v2:
    - fix EXPORT_FUNC macro to use register x9 according to "Scott Wood" mail
    - redefine some copyright text
    - add declaration of cache related functions, remove some compiler warnnings

 common/cmd_bdinfo.c         |   32 +++++++++++++++++++++
 common/fdt_support.c        |   66 ++++++++++++++++++++++---------------------
 common/image.c              |    5 ++--
 doc/README.arm64            |   10 +++++++
 examples/standalone/stubs.c |   13 +++++++++
 include/image.h             |    1 +
 lib/asm-offsets.c           |    4 ---
 7 files changed, 93 insertions(+), 38 deletions(-)
 create mode 100644 doc/README.arm64

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..578985a 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, x9 is a call-clobbered
+ * register
+ */
+#define EXPORT_FUNC(x) \
+	asm volatile (			\
+"	.globl " #x "\n"		\
+#x ":\n"				\
+"	ldr	x9, [x18, %0]\n"		\
+"	ldr	x9, [x9, %1]\n"		\
+"	br	x9\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/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..450514d 100644
--- a/lib/asm-offsets.c
+++ b/lib/asm-offsets.c
@@ -29,15 +29,11 @@ int main(void)
 
 	DEFINE(GD_BD, offsetof(struct global_data, bd));
 
-#if defined(CONFIG_ARM)
-
 	DEFINE(GD_RELOCADDR, offsetof(struct global_data, relocaddr));
 
 	DEFINE(GD_RELOC_OFF, offsetof(struct global_data, reloc_off));
 
 	DEFINE(GD_START_ADDR_SP, offsetof(struct global_data, start_addr_sp));
 
-#endif
-
 	return 0;
 }
-- 
1.7.9.5




More information about the U-Boot mailing list