nds32: Support AE3XX platform.

Support Andestech AE3xx platform: serial, timer device tree flow.

Signed-off-by: rick <rick@andestech.com>
diff --git a/arch/nds32/lib/Makefile b/arch/nds32/lib/Makefile
index 1a0d26f..c88ad72 100644
--- a/arch/nds32/lib/Makefile
+++ b/arch/nds32/lib/Makefile
@@ -11,4 +11,5 @@
 
 obj-y += cache.o
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
+obj-$(CONFIG_CMD_GO) += boot.o
 obj-y += interrupts.o
diff --git a/arch/nds32/lib/boot.c b/arch/nds32/lib/boot.c
new file mode 100644
index 0000000..f9c1c6b
--- /dev/null
+++ b/arch/nds32/lib/boot.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2011 Andes Technology Corporation
+ * Rick Chen, Andes Technology Corporation <rick@andestech.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+
+#include <common.h>
+#include <command.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+unsigned long do_go_exec(ulong (*entry)(int, char * const []),
+			 int argc, char * const argv[])
+{
+	cleanup_before_linux();
+
+	return entry(argc, argv);
+}
diff --git a/arch/nds32/lib/bootm.c b/arch/nds32/lib/bootm.c
index 7999167..4c95a41 100644
--- a/arch/nds32/lib/bootm.c
+++ b/arch/nds32/lib/bootm.c
@@ -11,6 +11,7 @@
 #include <image.h>
 #include <u-boot/zlib.h>
 #include <asm/byteorder.h>
+#include <asm/bootm.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -73,6 +74,15 @@
 	debug("## Transferring control to Linux (at address %08lx) ...\n",
 	       (ulong)theKernel);
 
+	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 if (BOOTM_ENABLE_TAGS) {
 #if defined(CONFIG_SETUP_MEMORY_TAGS) || \
 	defined(CONFIG_CMDLINE_TAG) || \
 	defined(CONFIG_INITRD_TAG) || \
@@ -107,16 +117,17 @@
 		udc_disconnect();
 	}
 #endif
-
+	}
 	cleanup_before_linux();
-
-	theKernel(0, machid, bd->bi_boot_params);
+	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
+		theKernel(0, machid, (unsigned long)images->ft_addr);
+	else
+		theKernel(0, machid, bd->bi_boot_params);
 	/* does not return */
 
 	return 1;
 }
 
-
 #if defined(CONFIG_SETUP_MEMORY_TAGS) || \
 	defined(CONFIG_CMDLINE_TAG) || \
 	defined(CONFIG_INITRD_TAG) || \
@@ -136,7 +147,6 @@
 	params = tag_next(params);
 }
 
-
 #ifdef CONFIG_SETUP_MEMORY_TAGS
 static void setup_memory_tags(bd_t *bd)
 {
@@ -154,7 +164,6 @@
 }
 #endif /* CONFIG_SETUP_MEMORY_TAGS */
 
-
 static void setup_commandline_tag(bd_t *bd, char *commandline)
 {
 	char *p;
@@ -182,7 +191,6 @@
 	params = tag_next(params);
 }
 
-
 #ifdef CONFIG_INITRD_TAG
 static void setup_initrd_tag(bd_t *bd, ulong initrd_start, ulong initrd_end)
 {
@@ -230,7 +238,6 @@
 }
 #endif  /* CONFIG_REVISION_TAG */
 
-
 static void setup_end_tag(bd_t *bd)
 {
 	params->hdr.tag = ATAG_NONE;
diff --git a/arch/nds32/lib/cache.c b/arch/nds32/lib/cache.c
index 866dc1a..8469481 100644
--- a/arch/nds32/lib/cache.c
+++ b/arch/nds32/lib/cache.c
@@ -7,32 +7,56 @@
  */
 
 #include <common.h>
+#if (!defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF))
+static inline unsigned long CACHE_SET(unsigned char cache)
+{
+	if (cache == ICACHE)
+		return 64 << ((GET_ICM_CFG() & ICM_CFG_MSK_ISET) \
+			>> ICM_CFG_OFF_ISET);
+	else
+		return 64 << ((GET_DCM_CFG() & DCM_CFG_MSK_DSET) \
+			>> DCM_CFG_OFF_DSET);
+}
+
+static inline unsigned long CACHE_WAY(unsigned char cache)
+{
+	if (cache == ICACHE)
+		return 1 + ((GET_ICM_CFG() & ICM_CFG_MSK_IWAY) \
+			>> ICM_CFG_OFF_IWAY);
+	else
+		return 1 + ((GET_DCM_CFG() & DCM_CFG_MSK_DWAY) \
+			>> DCM_CFG_OFF_DWAY);
+}
 
 static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache)
 {
 	if (cache == ICACHE)
 		return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
-					>> ICM_CFG_OFF_ISZ) - 1);
+			>> ICM_CFG_OFF_ISZ) - 1);
 	else
 		return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
-					>> DCM_CFG_OFF_DSZ) - 1);
+			>> DCM_CFG_OFF_DSZ) - 1);
 }
+#endif
 
-void flush_dcache_range(unsigned long start, unsigned long end)
+#ifndef CONFIG_SYS_ICACHE_OFF
+void invalidate_icache_all(void)
 {
-	unsigned long line_size;
+	unsigned long end, line_size;
+	line_size = CACHE_LINE_SIZE(ICACHE);
+	end = line_size * CACHE_WAY(ICACHE) * CACHE_SET(ICACHE);
+	do {
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
 
-	line_size = CACHE_LINE_SIZE(DCACHE);
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
 
-	while (end > start) {
-		asm volatile (
-			"\n\tcctl %0, L1D_VA_WB"
-			"\n\tcctl %0, L1D_VA_INVAL"
-			:
-			: "r" (start)
-		);
-		start += line_size;
-	}
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL" : : "r" (end));
+	} while (end > 0);
 }
 
 void invalidate_icache_range(unsigned long start, unsigned long end)
@@ -50,27 +74,6 @@
 	}
 }
 
-void invalidate_dcache_range(unsigned long start, unsigned long end)
-{
-	unsigned long line_size;
-
-	line_size = CACHE_LINE_SIZE(DCACHE);
-	while (end > start) {
-		asm volatile (
-			"\n\tcctl %0, L1D_VA_INVAL"
-			:
-			: "r"(start)
-		);
-		start += line_size;
-	}
-}
-
-void flush_cache(unsigned long addr, unsigned long size)
-{
-	flush_dcache_range(addr, addr + size);
-	invalidate_icache_range(addr, addr + size);
-}
-
 void icache_enable(void)
 {
 	asm volatile (
@@ -107,6 +110,81 @@
 	return ret;
 }
 
+#else
+void invalidate_icache_all(void)
+{
+}
+
+void invalidate_icache_range(unsigned long start, unsigned long end)
+{
+}
+
+void icache_enable(void)
+{
+}
+
+void icache_disable(void)
+{
+}
+
+int icache_status(void)
+{
+	return 0;
+}
+
+#endif
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void dcache_wbinval_all(void)
+{
+	unsigned long end, line_size;
+	line_size = CACHE_LINE_SIZE(DCACHE);
+	end = line_size * CACHE_WAY(DCACHE) * CACHE_SET(DCACHE);
+	do {
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
+		__asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
+		__asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
+		__asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1D_IX_WB" : : "r" (end));
+		__asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL" : : "r" (end));
+
+	} while (end > 0);
+}
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size;
+
+	line_size = CACHE_LINE_SIZE(DCACHE);
+
+	while (end > start) {
+		asm volatile (
+			"\n\tcctl %0, L1D_VA_WB"
+			"\n\tcctl %0, L1D_VA_INVAL" : : "r" (start)
+		);
+		start += line_size;
+	}
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size;
+
+	line_size = CACHE_LINE_SIZE(DCACHE);
+	while (end > start) {
+		asm volatile (
+			"\n\tcctl %0, L1D_VA_INVAL" : : "r"(start)
+		);
+		start += line_size;
+	}
+}
+
 void dcache_enable(void)
 {
 	asm volatile (
@@ -131,7 +209,6 @@
 int dcache_status(void)
 {
 	int ret;
-
 	asm volatile (
 		"mfsr	$p0, $mr8\n\t"
 		"andi	%0, $p0, 0x02\n\t"
@@ -139,6 +216,52 @@
 		:
 		: "memory"
 	);
-
 	return ret;
 }
+
+#else
+void dcache_wbinval_all(void)
+{
+}
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long end)
+{
+}
+
+void dcache_enable(void)
+{
+}
+
+void dcache_disable(void)
+{
+}
+
+int dcache_status(void)
+{
+	return 0;
+}
+
+#endif
+
+
+void flush_dcache_all(void)
+{
+	dcache_wbinval_all();
+}
+
+void cache_flush(void)
+{
+	flush_dcache_all();
+	invalidate_icache_all();
+}
+
+
+void flush_cache(unsigned long addr, unsigned long size)
+{
+	flush_dcache_range(addr, addr + size);
+	invalidate_icache_range(addr, addr + size);
+}