diff mbox

[U-Boot,v2,2/4] nds32/ag102: add ag102 soc support

Message ID 1322558107-20355-2-git-send-email-macpaul@andestech.com
State Superseded
Delegated to: Macpaul Lin
Headers show

Commit Message

Macpaul Lin Nov. 29, 2011, 9:15 a.m. UTC
Add lowlevel ag102 soc support.

Signed-off-by: Macpaul Lin <macpaul@andestech.com>
---
Changes for v2:
  - cpu.c:
   - 1. Remove unused variables.
   - 2. Replace while(1) in do_reset by hang().
   - 3. Clean up other coding styles.
  - timer.c: remove unneccessary static declaration

 arch/nds32/cpu/n1213/ag102/Makefile        |   58 ++++++
 arch/nds32/cpu/n1213/ag102/cpu.c           |  195 ++++++++++++++++++
 arch/nds32/cpu/n1213/ag102/lowlevel_init.S |  297 ++++++++++++++++++++++++++++
 arch/nds32/cpu/n1213/ag102/timer.c         |  205 +++++++++++++++++++
 arch/nds32/cpu/n1213/ag102/watchdog.S      |   48 +++++
 5 files changed, 803 insertions(+), 0 deletions(-)
 create mode 100644 arch/nds32/cpu/n1213/ag102/Makefile
 create mode 100644 arch/nds32/cpu/n1213/ag102/cpu.c
 create mode 100644 arch/nds32/cpu/n1213/ag102/lowlevel_init.S
 create mode 100644 arch/nds32/cpu/n1213/ag102/timer.c
 create mode 100644 arch/nds32/cpu/n1213/ag102/watchdog.S

Comments

Mike Frysinger Nov. 29, 2011, 6:43 p.m. UTC | #1
On Tuesday 29 November 2011 04:15:05 Macpaul Lin wrote:
> +.globl	turnoff_watchdog
> +turnoff_watchdog:

should be:
ENTRY(turnoff_watchdog)

> +	ret

and at the end, add:
ENDPROC(turnoff_watchdog)

seems a lot of the nds32 code could use this fixup ...
-mike
Macpaul Lin Nov. 30, 2011, 4:32 a.m. UTC | #2
Hi Mike,

2011/11/30 Mike Frysinger <vapier@gentoo.org>

> On Tuesday 29 November 2011 04:15:05 Macpaul Lin wrote:
> > +.globl       turnoff_watchdog
> > +turnoff_watchdog:
>
> should be:
> ENTRY(turnoff_watchdog)
>
> > +     ret
>
> and at the end, add:
> ENDPROC(turnoff_watchdog)
>
> seems a lot of the nds32 code could use this fixup ...
> -mike
>

Thanks for your suggestion, however, I'd like to confirm what is the
benefits of
these kind of implementation? I know there are such code in Linux.
One benefits might be alignment (marco ENDPROC), and the other looks like
for coding style.

For supporting this kind of implementation, I must to put header support
like linkage.h
from blackfin into nds32's common includes.
Currently I don't see other architecture support these kind of code.
Would you like to make some comment in more detail and also suggest other
custodians?
I think if this kind of implementation is good then it is worthy to be
adopt to other architectures as well
just like Linux.

Thanks.
Mike Frysinger Nov. 30, 2011, 4:41 a.m. UTC | #3
On Tuesday 29 November 2011 23:32:27 Macpaul Lin wrote:
> these kind of implementation? I know there are such code in Linux.
> One benefits might be alignment (marco ENDPROC), and the other looks like
> for coding style.

makes sure the visibility/alignment/ELF size is correct.  for the last part, 
gdb won't know where the func ends without it and taking a best guess.

> For supporting this kind of implementation, I must to put header support
> like linkage.h

err, i thought i saw u-boot had this in common code.  seems it is not (i must 
have been looking in the Linux tree).  don't worry about it until we get that 
addressed.
-mike
Macpaul Lin Nov. 30, 2011, 5:58 a.m. UTC | #4
Hi Mike and Wolfgang,

2011/11/30 Mike Frysinger <vapier@gentoo.org>

> > For supporting this kind of implementation, I must to put header support
> > like linkage.h
>
> err, i thought i saw u-boot had this in common code.  seems it is not (i
> must
> have been looking in the Linux tree).  don't worry about it until we get
> that
> addressed.
> -mike
>

I think you can send a patch to move linkage.h to common headers at first,
than we can move to this step by step.
I'll also fix this in these series of patches with manually added linkage.h
to NDS32
architecture. Hope your can do this move sooner hence I do not need to send
a commit
of adding linkage.h into NDS32. :-)

Thanks.
Macpaul Lin Nov. 30, 2011, 6:30 a.m. UTC | #5
Hi Mike,

2011/11/30 Macpaul Lin <macpaul@gmail.com>

> Hi Mike and Wolfgang,
>
> 2011/11/30 Mike Frysinger <vapier@gentoo.org>
>
>> > For supporting this kind of implementation, I must to put header support
>> > like linkage.h
>>
>> err, i thought i saw u-boot had this in common code.  seems it is not (i
>> must
>> have been looking in the Linux tree).  don't worry about it until we get
>> that
>> addressed.
>> -mike
>>
>
>
>
It seems the only architecture related part in this header are the
following codes.
#define __ALIGN .align          4
#define __ALIGN_STR             ".align 4"

In Linux, the common linkage.h will include only this part from
architectures' local linkage.h.

I think we can put the common linkage.h in "include/linux" folder is okay.
Macpaul Lin Nov. 30, 2011, 7:22 a.m. UTC | #6
Hi Mike,

2011/11/30 Macpaul Lin <macpaul@gmail.com>

> Hi Mike,
>
>  err, i thought i saw u-boot had this in common code.  seems it is not (i
>>> must
>>> have been looking in the Linux tree).  don't worry about it until we get
>>> that
>>> addressed.
>>> -mike
>>>
>>
>>
>>
> It seems the only architecture related part in this header are the
> following codes.
> #define __ALIGN .align          4
> #define __ALIGN_STR             ".align 4"
>
> In Linux, the common linkage.h will include only this part from
> architectures' local linkage.h.
>
> I think we can put the common linkage.h in "include/linux" folder is okay.
>
>
I have done this for blackfin also, but when I ran checkpatch to these
patches, I've got several
warnings and it looks those warnings should not be problem at all.
So I'll send these patches to you and hope you can run checkpatch, too and
see if there are
something need to be fixed.

Thanks.
diff mbox

Patch

diff --git a/arch/nds32/cpu/n1213/ag102/Makefile b/arch/nds32/cpu/n1213/ag102/Makefile
new file mode 100644
index 0000000..8716c4e
--- /dev/null
+++ b/arch/nds32/cpu/n1213/ag102/Makefile
@@ -0,0 +1,58 @@ 
+#
+# (C) Copyright 2009
+# Marvell Semiconductor <www.marvell.com>
+# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+#
+# Copyright (C) 2011 Andes Technology Corporation
+# Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
+# Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
+#
+# 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., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(SOC).o
+
+COBJS-y	:= cpu.o timer.o
+
+ifndef CONFIG_SKIP_LOWLEVEL_INIT
+SOBJS	:= lowlevel_init.o
+endif
+
+ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG
+SOBJS	+= watchdog.o
+endif
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS-y))
+
+all:	$(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/nds32/cpu/n1213/ag102/cpu.c b/arch/nds32/cpu/n1213/ag102/cpu.c
new file mode 100644
index 0000000..ed88b52
--- /dev/null
+++ b/arch/nds32/cpu/n1213/ag102/cpu.c
@@ -0,0 +1,195 @@ 
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * Copyright (C) 2011 Andes Technology Corporation
+ * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
+ * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
+ *
+ * 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
+ */
+
+/* CPU specific code */
+#include <common.h>
+#include <command.h>
+#include <watchdog.h>
+#include <asm/cache.h>
+
+#include <faraday/ftwdt010_wdt.h>
+
+/*
+ * cleanup_before_linux() is called just before we call linux
+ * it prepares the processor for linux
+ *
+ * we disable interrupt and caches.
+ */
+int cleanup_before_linux(void)
+{
+	disable_interrupts();
+
+#ifdef CONFIG_MMU
+	/* turn off I/D-cache */
+	icache_disable();
+	dcache_disable();
+
+	/* flush I/D-cache */
+	invalidate_icac();
+	invalidate_dcac();
+#endif
+
+	return 0;
+}
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	disable_interrupts();
+
+	/*
+	 * reset to the base addr of andesboot.
+	 * currently no ROM loader at addr 0.
+	 * do not use reset_cpu(0);
+	 */
+#ifdef CONFIG_FTWDT010_WATCHDOG
+	/*
+	 * workaround: if we use CONFIG_HW_WATCHDOG with ftwdt010, will lead
+	 * automatic hardware reset when booting Linux.
+	 * Please do not use CONFIG_HW_WATCHDOG and WATCHDOG_RESET() here.
+	 */
+	ftwdt010_wdt_reset();
+#endif /* CONFIG_FTWDT010_WATCHDOG */
+	hang();
+
+	/*NOTREACHED*/
+}
+
+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);
+	else
+		return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
+					>> DCM_CFG_OFF_DSZ) - 1);
+}
+
+void dcache_flush_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" : : "r"(start));
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start));
+		start += line_size;
+	}
+}
+
+void icache_inval_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size;
+
+	line_size = CACHE_LINE_SIZE(ICACHE);
+	while (end > start) {
+		__asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start));
+		start += line_size;
+	}
+}
+
+void flush_cache(unsigned long addr, unsigned long size)
+{
+	dcache_flush_range(addr, addr + size);
+	icache_inval_range(addr, addr + size);
+}
+
+void icache_enable(void)
+{
+	__asm__ __volatile__ (
+		"mfsr	$p0, $mr8\n\t"
+		"ori	$p0, $p0, 0x01\n\t"
+		"mtsr	$p0, $mr8\n\t"
+		"isb\n\t"
+	);
+}
+
+void icache_disable(void)
+{
+	__asm__ __volatile__ (
+		"mfsr	$p0, $mr8\n\t"
+		"li	$p1, ~0x01\n\t"
+		"and	$p0, $p0, $p1\n\t"
+		"mtsr	$p0, $mr8\n\t"
+		"isb\n\t"
+	);
+}
+
+int icache_status(void)
+{
+	int ret;
+
+	 __asm__ __volatile__ (
+		"mfsr	$p0, $mr8\n\t"
+		"andi	%0,  $p0, 0x01\n\t"
+		: "=r" (ret)
+		:
+		: "memory"
+	);
+
+	 return ret;
+}
+
+void dcache_enable(void)
+{
+	 __asm__ __volatile__ (
+		"mfsr	$p0, $mr8\n\t"
+		"ori	$p0, $p0, 0x02\n\t"
+		"mtsr	$p0, $mr8\n\t"
+		"isb\n\t"
+	);
+}
+
+void dcache_disable(void)
+{
+	 __asm__ __volatile__ (
+		"mfsr	$p0, $mr8\n\t"
+		"li	$p1, ~0x02\n\t"
+		"and	$p0, $p0, $p1\n\t"
+		"mtsr	$p0, $mr8\n\t"
+		"isb\n\t"
+	);
+}
+
+int dcache_status(void)
+{
+	int ret;
+
+	__asm__ __volatile__ (
+		"mfsr	$p0, $mr8\n\t"
+		"andi	%0, $p0, 0x02\n\t"
+		: "=r" (ret)
+		:
+		: "memory"
+	 );
+
+	 return ret;
+}
diff --git a/arch/nds32/cpu/n1213/ag102/lowlevel_init.S b/arch/nds32/cpu/n1213/ag102/lowlevel_init.S
new file mode 100644
index 0000000..d842afa
--- /dev/null
+++ b/arch/nds32/cpu/n1213/ag102/lowlevel_init.S
@@ -0,0 +1,297 @@ 
+/*
+ * Copyright (C) 2011 Andes Technology Corporation
+ * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
+ *
+ * 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
+ */
+
+.text
+
+#include <common.h>
+#include <config.h>
+
+#include <asm/macro.h>
+#include <generated/asm-offsets.h>
+
+/*
+ * parameters for Synopsys DWC DDR2/DDR1 Memory Controller
+ */
+#define DDR2C_BASE_A		(CONFIG_DWCDDR21MCTL_BASE)
+#define DDR2C_CCR_A		(DDR2C_BASE_A + DWCDDR21MCTL_CCR)
+#define DDR2C_DCR_A		(DDR2C_BASE_A + DWCDDR21MCTL_DCR)
+#define DDR2C_IOCR_A		(DDR2C_BASE_A + DWCDDR21MCTL_IOCR)
+#define DDR2C_CSR_A		(DDR2C_BASE_A + DWCDDR21MCTL_CSR)
+#define DDR2C_DRR_A		(DDR2C_BASE_A + DWCDDR21MCTL_DRR)
+#define DDR2C_DLLCR0_A		(DDR2C_BASE_A + DWCDDR21MCTL_DLLCR0)
+#define DDR2C_DLLCR1_A		(DDR2C_BASE_A + DWCDDR21MCTL_DLLCR1)
+#define DDR2C_DLLCR2_A		(DDR2C_BASE_A + DWCDDR21MCTL_DLLCR2)
+#define DDR2C_DLLCR3_A		(DDR2C_BASE_A + DWCDDR21MCTL_DLLCR3)
+#define DDR2C_DLLCR4_A		(DDR2C_BASE_A + DWCDDR21MCTL_DLLCR4)
+#define DDR2C_DLLCR5_A		(DDR2C_BASE_A + DWCDDR21MCTL_DLLCR5)
+#define DDR2C_DLLCR6_A		(DDR2C_BASE_A + DWCDDR21MCTL_DLLCR6)
+#define DDR2C_DLLCR7_A		(DDR2C_BASE_A + DWCDDR21MCTL_DLLCR7)
+#define DDR2C_DLLCR8_A		(DDR2C_BASE_A + DWCDDR21MCTL_DLLCR8)
+#define DDR2C_DLLCR9_A		(DDR2C_BASE_A + DWCDDR21MCTL_DLLCR9)
+#define DDR2C_RSLR0_A		(DDR2C_BASE_A + DWCDDR21MCTL_RSLR0)
+#define DDR2C_RDGR0_A		(DDR2C_BASE_A + DWCDDR21MCTL_RDGR0)
+#define DDR2C_DTAR_A		(DDR2C_BASE_A + DWCDDR21MCTL_DTAR)
+#define DDR2C_MR_A		(DDR2C_BASE_A + DWCDDR21MCTL_MR)
+
+#define DDR2C_CCR_D		CONFIG_SYS_DWCDDR21MCTL_CCR
+#define DDR2C_CCR_D2		CONFIG_SYS_DWCDDR21MCTL_CCR2
+#define DDR2C_DCR_D		CONFIG_SYS_DWCDDR21MCTL_DCR
+#define DDR2C_IOCR_D		CONFIG_SYS_DWCDDR21MCTL_IOCR
+#define DDR2C_CSR_D		CONFIG_SYS_DWCDDR21MCTL_CSR
+#define DDR2C_DRR_D		CONFIG_SYS_DWCDDR21MCTL_DRR
+#define DDR2C_RSLR0_D		CONFIG_SYS_DWCDDR21MCTL_RSLR0
+#define DDR2C_RDGR0_D		CONFIG_SYS_DWCDDR21MCTL_RDGR0
+#define DDR2C_DTAR_D		CONFIG_SYS_DWCDDR21MCTL_DTAR
+#define DDR2C_MR_D		CONFIG_SYS_DWCDDR21MCTL_MR
+
+#define DDR2C_DLLCR0_D	CONFIG_SYS_DWCDDR21MCTL_DLLCR0	/* 0-9 are same */
+
+/*
+ * parameters for the ahbc controller
+ */
+#define AHBC_CR_A		(CONFIG_FTAHBC020S_BASE + FTAHBC020S_CR)
+#define AHBC_BSR6_A	(CONFIG_FTAHBC020S_BASE + FTAHBC020S_SLAVE_BSR_6)
+
+#define AHBC_BSR6_D		CONFIG_SYS_FTAHBC020S_SLAVE_BSR_6
+
+/*
+ * parameters for the ANDES PCU controller
+ */
+#define PCU_PCS4_A		(CONFIG_ANDES_PCU_BASE + ANDES_PCU_PCS4)
+#define PCU_PCS4_D		CONFIG_SYS_ANDES_CPU_PCS4
+
+/*
+ * numeric 7 segment display
+ */
+.macro	led, num
+	write32	CONFIG_DEBUG_LED, \num
+.endm
+
+/*
+ * Waiting for SDRAM to set up
+ */
+/*
+.macro	wait_sdram
+	li	$r0, DDR2C_CSR_A
+1:
+	lwi	$r1, [$r0+FTSDMC021_CR2]
+	bnez	$r1, 1b
+.endm
+*/
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+.globl	lowlevel_init
+lowlevel_init:
+	move	$r10, $lp
+
+	/* U200 */
+!	led	0x00
+!	jal	scale_to_500mhz
+
+	led	0x10
+	jal	mem_init
+
+	led	0x20
+	jal	remap
+
+	led	0x30
+	ret	$r10
+
+scale_to_500mhz:
+	move	$r11, $lp
+
+	/*
+	 * scale to 500Mhz
+	 */
+	led	0x01
+	write32	PCU_PCS4_A, 0x1102000f			! save data to PCS4
+
+	move	$lp, $r11
+	ret
+
+mem_init:
+	move	$r11, $lp
+
+	/*
+	 * config AHB Controller
+	 */
+	led	0x12
+	write32	AHBC_BSR6_A, AHBC_BSR6_D
+
+	/*
+	 * config Synopsys DWC DDR2/DDR1 Memory Controller
+	 */
+ddr2c_init:
+set_dcr:
+	led	0x14
+	write32	DDR2C_DCR_A, DDR2C_DCR_D			! 0x000020d4
+
+auto_sizing:
+	/*
+	 * ebios: $r10->$r7, $r11->$r8, $r12->$r9, $r13->$r12, $r14->$r13
+	 */
+set_iocr:
+	led	0x19
+	write32 DDR2C_IOCR_A, DDR2C_IOCR_D
+set_drr:
+	led	0x16
+	write32	DDR2C_DRR_A, DDR2C_DRR_D			! 0x00034812
+set_dllcr:
+	led	0x18
+	write32 DDR2C_DLLCR0_A, DDR2C_DLLCR0_D
+	write32 DDR2C_DLLCR1_A, DDR2C_DLLCR0_D
+	write32 DDR2C_DLLCR2_A, DDR2C_DLLCR0_D
+	write32 DDR2C_DLLCR3_A, DDR2C_DLLCR0_D
+	write32 DDR2C_DLLCR4_A, DDR2C_DLLCR0_D
+	write32 DDR2C_DLLCR5_A, DDR2C_DLLCR0_D
+	write32 DDR2C_DLLCR6_A, DDR2C_DLLCR0_D
+	write32 DDR2C_DLLCR7_A, DDR2C_DLLCR0_D
+	write32 DDR2C_DLLCR8_A, DDR2C_DLLCR0_D
+	write32 DDR2C_DLLCR9_A, DDR2C_DLLCR0_D
+set_rslr0:
+	write32 DDR2C_RSLR0_A, DDR2C_RSLR0_D			! 0x00000040
+set_rdgr0:
+	write32 DDR2C_RDGR0_A, DDR2C_RDGR0_D			! 0x000055cf
+set_dtar:
+	led	0x15
+	write32	DDR2C_DTAR_A, DDR2C_DTAR_D			! 0x00100000
+set_mode:
+	led	0x17
+	write32	DDR2C_MR_A, DDR2C_MR_D				! 0x00000852
+set_ccr:
+	write32 DDR2C_CCR_A, DDR2C_CCR_D
+
+#ifdef TRIGGER_INIT:
+trigger_init:
+	write32 DDR2C_CCR_A, DDR2C_CCR_D			! 0x80020000
+
+	/* Wait for ddr init state to be set */
+	msync	ALL
+	isb
+
+	/* Wait until the config initialization is finish */
+1:
+	la	$r4, DDR2C_CSR_A
+	lwi	$r5, [$r4]
+	srli	$r5, $r5, 23
+	bnez	$r5, 1b
+#endif
+
+data_training:
+!	write32	DDR2C_CCR_A, DDR2C_CCR_D2			! 0x40020004
+
+	/* Wait for ddr init state to be set */
+	msync	ALL
+	isb
+
+	/* wait until the ddr data trainning is complete */
+1:
+	la	$r4, DDR2C_CSR_A
+	lwi	$r5, [$r4]
+	srli	$r6, $r5, 23
+	bnez	$r6, 1b
+
+	lwi	$r1, [$r4]
+	srli	$r6, $r5, 20
+	li	$r5, 0x00ffffff
+	swi	$r1, [$r4]
+	bnez	$r6, ddr2c_init
+
+	led	0x1a
+	move	$lp, $r11
+	ret
+
+remap:
+	move	$r11, $lp
+#ifdef __NDS32_N1213_43U1H__	/* NDS32 V0 ISA - AG101 Only */
+	bal	2f
+relo_base:
+	move	$r0, $lp
+#else
+relo_base:
+	mfusr	$r0, $pc
+#endif /* __NDS32_N1213_43U1H__ */
+
+	/*
+	 * Remapping
+	 */
+#ifdef CONFIG_MEM_REMAP
+	/*
+	 * Copy ROM code to SDRAM base for memory remap layout.
+	 * This is not the real relocation, the real relocation is the function
+	 * relocate_code() is start.S which supports the systems is memory
+	 * remapped or not.
+	 */
+	/*
+	 * Doing memory remap is essential for preparing some non-OS or RTOS
+	 * applications.
+	 *
+	 * This is also a must on ADP-AG101 board.
+	 * The reason is because the ROM/FLASH circuit on PCB board.
+	 * AG101-A0 board has 2 jumpers MA17 and SW5 to configure which
+	 * ROM/FLASH is used to boot.
+	 *
+	 * When SW5 = "0101", MA17 = LO, the ROM is connected to BANK0,
+	 * and the FLASH is connected to BANK1.
+	 * When SW5 = "1010", MA17 = HI, the ROM is disabled (still at BANK0),
+	 * and the FLASH is connected to BANK0.
+	 * It will occur problem when doing flash probing if the flash is at
+	 * BANK0 (0x00000000) while memory remapping was skipped.
+	 *
+	 * Other board like ADP-AG101P may not enable this since there is only
+	 * a FLASH connected to bank0.
+	 */
+	led	0x21
+	li	$r4, PHYS_SDRAM_0_AT_INIT		/* 0x10000000 */
+	li	$r5, 0x0
+	la	$r1, relo_base				/* get $pc or $lp */
+	sub	$r2, $r0, $r1
+	sethi	$r6, hi20(_end)
+	ori	$r6, $r6, lo12(_end)
+	add	$r6, $r6, $r2
+1:
+	lwi.p	$r7, [$r5], #4
+	swi.p	$r7, [$r4], #4
+	blt	$r5, $r6, 1b
+
+	/* set remap bit */
+	/*
+	 * MEM remap bit is operational
+	 * - use it to map writeable memory at 0x00000000, in place of flash
+	 * - before remap: flash/rom 0x00000000, sdram: 0x10000000-0x4fffffff
+	 * - after  remap: flash/rom 0x80000000, sdram: 0x00000000
+	 */
+	led	0x2c
+	setbf15	AHBC_CR_A, FTAHBC020S_CR_REMAP		! 0x1
+
+#endif /* #ifdef CONFIG_MEM_REMAP */
+	move	$lp, $r11
+2:
+	ret
+
+.globl show_led
+show_led:
+    li      $r8, (CONFIG_DEBUG_LED)
+    swi     $r7, [$r8]
+    ret
+#endif /* #ifndef CONFIG_SKIP_LOWLEVEL_INIT */
diff --git a/arch/nds32/cpu/n1213/ag102/timer.c b/arch/nds32/cpu/n1213/ag102/timer.c
new file mode 100644
index 0000000..caa36b8
--- /dev/null
+++ b/arch/nds32/cpu/n1213/ag102/timer.c
@@ -0,0 +1,205 @@ 
+/*
+ * (C) Copyright 2009 Faraday Technology
+ * Po-Yu Chuang <ratbert@faraday-tech.com>
+ *
+ * Copyright (C) 2011 Andes Technology Corporation
+ * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
+ * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <faraday/fttmr010.h>
+
+static ulong timestamp;
+static ulong lastdec;
+
+int timer_init(void)
+{
+	struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
+	unsigned int cr;
+
+	debug("%s()\n", __func__);
+
+	/* disable timers */
+	writel(0, &tmr->cr);
+
+#ifdef CONFIG_FTTMR010_EXT_CLK
+	/* use 32768Hz oscillator for RTC, WDT, TIMER */
+	ftpmu010_32768osc_enable();
+#endif
+
+	/* setup timer */
+	writel(TIMER_LOAD_VAL, &tmr->timer3_load);
+	writel(TIMER_LOAD_VAL, &tmr->timer3_counter);
+	writel(0, &tmr->timer3_match1);
+	writel(0, &tmr->timer3_match2);
+
+	/* we don't want timer to issue interrupts */
+	writel(FTTMR010_TM3_MATCH1 |
+	       FTTMR010_TM3_MATCH2 |
+	       FTTMR010_TM3_OVERFLOW,
+	       &tmr->interrupt_mask);
+
+	cr = readl(&tmr->cr);
+#ifdef CONFIG_FTTMR010_EXT_CLK
+	cr |= FTTMR010_TM3_CLOCK;	/* use external clock */
+#endif
+	cr |= FTTMR010_TM3_ENABLE;
+	writel(cr, &tmr->cr);
+
+	/* init the timestamp and lastdec value */
+	reset_timer_masked();
+
+	return 0;
+}
+
+/*
+ * timer without interrupts
+ */
+
+/*
+ * reset time
+ */
+void reset_timer_masked(void)
+{
+	struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
+
+	/* capure current decrementer value time */
+#ifdef CONFIG_FTTMR010_EXT_CLK
+	lastdec = readl(&tmr->timer3_counter) / (TIMER_CLOCK / CONFIG_SYS_HZ);
+#else
+	lastdec = readl(&tmr->timer3_counter) / (CONFIG_SYS_CLK_FREQ / 2);
+#endif
+	timestamp = 0;		/* start "advancing" time stamp from 0 */
+
+	debug("%s(): lastdec = %lx\n", __func__, lastdec);
+}
+
+void reset_timer(void)
+{
+	debug("%s()\n", __func__);
+	reset_timer_masked();
+}
+
+/*
+ * return timer ticks
+ */
+ulong get_timer_masked(void)
+{
+	struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
+
+	/* current tick value */
+#ifdef CONFIG_FTTMR010_EXT_CLK
+	ulong now = readl(&tmr->timer3_counter) / (TIMER_CLOCK / CONFIG_SYS_HZ);
+#else
+	ulong now = readl(&tmr->timer3_counter) / \
+			(CONFIG_SYS_CLK_FREQ / 2 / 1024);
+#endif
+
+	debug("%s(): now = %lx, lastdec = %lx\n", __func__, now, lastdec);
+
+	if (lastdec >= now) {
+		/*
+		 * normal mode (non roll)
+		 * move stamp fordward with absoulte diff ticks
+		 */
+		timestamp += lastdec - now;
+	} else {
+		/*
+		 * we have overflow of the count down timer
+		 *
+		 * nts = ts + ld + (TLV - now)
+		 * ts=old stamp, ld=time that passed before passing through -1
+		 * (TLV-now) amount of time after passing though -1
+		 * nts = new "advancing time stamp"...it could also roll and
+		 * cause problems.
+		 */
+		timestamp += lastdec + TIMER_LOAD_VAL - now;
+	}
+
+	lastdec = now;
+
+	debug("%s() returns %lx\n", __func__, timestamp);
+
+	return timestamp;
+}
+
+/*
+ * return difference between timer ticks and base
+ */
+ulong get_timer(ulong base)
+{
+	debug("%s(%lx)\n", __func__, base);
+	return get_timer_masked() - base;
+}
+
+void set_timer(ulong t)
+{
+	debug("%s(%lx)\n", __func__, t);
+	timestamp = t;
+}
+
+/* delay x useconds AND preserve advance timestamp value */
+void __udelay(unsigned long usec)
+{
+	struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE;
+
+#ifdef CONFIG_FTTMR010_EXT_CLK
+	long tmo = usec * (TIMER_CLOCK / 1000) / 1000;
+#else
+	long tmo = usec * ((CONFIG_SYS_CLK_FREQ / 2) / 1000) / 1000;
+#endif
+	unsigned long now, last = readl(&tmr->timer3_counter);
+
+	debug("%s(%lu)\n", __func__, usec);
+	while (tmo > 0) {
+		now = readl(&tmr->timer3_counter);
+		if (now > last) /* count down timer overflow */
+			tmo -= TIMER_LOAD_VAL + last - now;
+		else
+			tmo -= last - now;
+		last = now;
+	}
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	debug("%s()\n", __func__);
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	debug("%s()\n", __func__);
+#ifdef CONFIG_FTTMR010_EXT_CLK
+	return CONFIG_SYS_HZ;
+#else
+	return CONFIG_SYS_CLK_FREQ;
+#endif
+}
diff --git a/arch/nds32/cpu/n1213/ag102/watchdog.S b/arch/nds32/cpu/n1213/ag102/watchdog.S
new file mode 100644
index 0000000..fc39f3f
--- /dev/null
+++ b/arch/nds32/cpu/n1213/ag102/watchdog.S
@@ -0,0 +1,48 @@ 
+/*
+ * Copyright (C) 2011 Andes Technology Corporation
+ * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
+ *
+ * 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/arch-ag101/ag101.h>
+
+.text
+
+#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG
+.globl	turnoff_watchdog
+turnoff_watchdog:
+
+#define WD_CR		0xC
+#define WD_ENABLE	0x1
+
+	! Turn off the watchdog, according to Faraday FTWDT010 spec
+	li 	$p0, (CONFIG_FTWDT010_BASE+WD_CR)	! Get the addr of WD CR
+	lwi	$p1, [$p0]				! Get the config of WD
+	andi	$p1, $p1, 0x1f				! Wipe out useless bits
+	li	$r0, ~WD_ENABLE
+	and	$p1, $p1, $r0				! Set WD disable
+	sw	$p1, [$p0]				! Write back to WD CR
+
+	! Disable Interrupts by clear GIE in $PSW reg
+	setgie.d
+
+	ret
+
+#endif