
Add cpu support for nds32 arch. Included support of common cpu setting, core n1213, SoC ag101.
Signed-off-by: Macpaul Lin macpaul@andestech.com --- arch/nds32/config.mk | 34 +++ arch/nds32/cpu/Makefile | 52 ++++ arch/nds32/cpu/cpu.c | 197 +++++++++++++++ arch/nds32/cpu/lowlevel_init.S | 159 ++++++++++++ arch/nds32/cpu/n1213/Makefile | 51 ++++ arch/nds32/cpu/n1213/ag101/Makefile | 50 ++++ arch/nds32/cpu/n1213/ag101/cpu.c | 197 +++++++++++++++ arch/nds32/cpu/n1213/ag101/ftsmc020.c | 51 ++++ arch/nds32/cpu/n1213/ag101/timer.c | 213 ++++++++++++++++ arch/nds32/cpu/n1213/lowlevel_init.S | 159 ++++++++++++ arch/nds32/cpu/n1213/start.S | 447 +++++++++++++++++++++++++++++++++ arch/nds32/cpu/n1213/u-boot.lds | 68 +++++ arch/nds32/cpu/start.S | 447 +++++++++++++++++++++++++++++++++ 13 files changed, 2125 insertions(+), 0 deletions(-) create mode 100644 arch/nds32/config.mk create mode 100644 arch/nds32/cpu/Makefile create mode 100644 arch/nds32/cpu/cpu.c create mode 100644 arch/nds32/cpu/lowlevel_init.S create mode 100644 arch/nds32/cpu/n1213/Makefile create mode 100644 arch/nds32/cpu/n1213/ag101/Makefile create mode 100644 arch/nds32/cpu/n1213/ag101/cpu.c create mode 100644 arch/nds32/cpu/n1213/ag101/ftsmc020.c create mode 100644 arch/nds32/cpu/n1213/ag101/timer.c create mode 100644 arch/nds32/cpu/n1213/lowlevel_init.S create mode 100644 arch/nds32/cpu/n1213/start.S create mode 100644 arch/nds32/cpu/n1213/u-boot.lds create mode 100644 arch/nds32/cpu/start.S
diff --git a/arch/nds32/config.mk b/arch/nds32/config.mk new file mode 100644 index 0000000..89568c2 --- /dev/null +++ b/arch/nds32/config.mk @@ -0,0 +1,34 @@ +# +# (C) Copyright 2000-2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2010 +# 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 + +CROSS_COMPILE ?= nds32le-linux- + +STANDALONE_LOAD_ADDR = 0x300000 -T nds32.lds + +PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common +PLATFORM_CPPFLAGS += -DCONFIG_NDS32 -D__nds32__ -G0 -ffixed-8 + +LDSCRIPT := $(SRCTREE)/$(CPUDIR)/u-boot.lds diff --git a/arch/nds32/cpu/Makefile b/arch/nds32/cpu/Makefile new file mode 100644 index 0000000..818795a --- /dev/null +++ b/arch/nds32/cpu/Makefile @@ -0,0 +1,52 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2010 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 +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(CPU).a + +START = start.o +COBJS = cpu.o interrupts.o +SOBJS = lowlevel_init.o + +SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) +START := $(addprefix $(obj),$(START)) + +all: $(obj).depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/nds32/cpu/cpu.c b/arch/nds32/cpu/cpu.c new file mode 100644 index 0000000..e8b15cb --- /dev/null +++ b/arch/nds32/cpu/cpu.c @@ -0,0 +1,197 @@ +/* + * (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) 2010 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> + +/* + * setup up stack if necessary + */ +/* it makes no sense to use the caches if the MMU also isn't used */ +void cpu_init(void) +{ + _andesboot_real_end = _andesboot_end + CONFIG_STACKSIZE; +} + +/* + * cleanup_before_linux() is called just before we call linux + * it prepares the processor for linux + * + * we disable interrupt and caches. + */ +void cleanup_before_linux(void) +{ +#ifdef CONFIG_MMU + unsigned long i; +#endif + + disable_interrupts(); + +#ifdef CONFIG_MMU + /* turn off I/D-cache */ + icache_disable(); + dcache_disable(); + + /* flush I/D-cache */ + invalidate_icac(); + invalidate_dcac(); +#endif +} + +void do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + extern void reset_cpu(ulong addr); + + disable_interrupts(); + + /* + * reset to the base addr of andesboot. + * currently no ROM loader at addr 0. + * do not use reset_cpu(0); + */ + reset_cpu(TEXT_BASE); + + /*NOTREACHED*/ +} + +static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) +{ + if( cache == ICACHE) + return 8 << ( ( ( GET_ICM_CFG() & ICM_CFG_mskISZ) >> ICM_CFG_offISZ) - 1); + else + return 8 << ( ( ( GET_DCM_CFG() & DCM_CFG_mskDSZ) >> DCM_CFG_offDSZ) - 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/lowlevel_init.S b/arch/nds32/cpu/lowlevel_init.S new file mode 100644 index 0000000..f7fa12b --- /dev/null +++ b/arch/nds32/cpu/lowlevel_init.S @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2010 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 + */ + +.text + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +.globl lowlevel_init +lowlevel_init: + move $r10, $lp + jal mem_init + jal remap + + ret $r10 + +mem_init: + move $r11, $lp + li $r0, 0x90200000 + li $r1, 0x10000052 + swi $r1, [$r0] + li $r1, 0x00151151 + swi $r1, [$r0+0x4] + + li $r0, 0x90100018 + li $r1, 0x100b0000 + swi $r1, [$r0] + li $r0, 0x98100030 + lwi $r1, [$r0] + li $r2, 0x00010000 + or $r1, $r1, $r2 + swi $r1, [$r0] +#ifdef __NDS32_N1213_43U1H__ /* AG101 */ + lwi $r1, [$r0] + li $r2, 0x00e00000 + or $r1, $r1, $r2 + swi $r1, [$r0] + li $r0, 0x98100028 + lwi $r1, [$r0] + li $r2, 0x00000010 + or $r1, $r1, $r2 + swi $r1, [$r0] + li $r0, 0x9810004c + lwi $r1, [$r0] + li $r2, 0x0007f000 + or $r1, $r1, $r2 + swi $r1, [$r0] +#endif + li $r0, 0x90300000 + li $r1, 0x00011312 + swi $r1, [$r0] + li $r1, 0x00480180 + swi $r1, [$r0+0x4] + li $r1, 0x00002326 + swi $r1, [$r0+0x8] + li $r1, 0x00000010 + swi $r1, [$r0+0xc] +1: + lwi $r1, [$r0+0xc] + andi $r1, $r1, 0x1c + bnez $r1, 1b + + li $r1, 0x00000004 + swi $r1, [$r0+0xc] +2: + lwi $r1, [$r0+0xc] + bnez $r1, 2b + + li $r1, 0x00000008 + swi $r1, [$r0+0xc] +3: + lwi $r1, [$r0+0xc] + bnez $r1, 3b + + move $lp, $r11 + ret + +remap: + move $r11, $lp +#ifdef __NDS32_N1213_43U1H__ /* AG101 */ + bal 2f +relo_base: + move $r0, $lp +#else +relo_base: + mfusr $r0, $pc +#endif + + /* relocation, copy ROM code to SDRAM(current is at 0x10000000) */ + li $r4, 0x10000000 + li $r5, 0x0 + la $r1, relo_base + sub $r2, $r0, $r1 + sethi $r6, hi20(andesboot_end) + ori $r6, $r6, lo12(andesboot_end) + add $r6, $r6, $r2 +1: + lwi $r7, [$r5] + swi $r7, [$r4] + addi $r5, $r5, #4 + addi $r4, $r4, #4 + blt $r5, $r6, 1b + + /* Remapping */ + li $r0, 0x90300000 + li $r1, 0x00001100 + swi $r1, [$r0+0x10] + li $r1, 0x0 + swi $r1, [$r0+0x14] + swi $r1, [$r0+0x18] + swi $r1, [$r0+0x1c] + li $r1, 0x00001000 + swi $r1, [$r0+0x10] + + li $r0, 0x90100088 + lwi $r1, [$r0] + ori $r1, $r1, 0x1 + swi $r1, [$r0] + + li $r0, 0x90200000 +#ifdef __NDS32_N1213_43U1H__ /* AG101 */ + li $r1, 0x10400062 + swi $r1, [$r0+0x8] + li $r1, 0x000ff3ff + swi $r1, [$r0+0xc] +#else + li $r1, 0x10400062 + swi $r1, [$r0] +#endif + + move $lp, $r11 +2: + ret + +.globl show_led +show_led: + li $r8, 0x902ffffc ! 0x902ffffc + swi $r7, [$r8] + ret +#endif diff --git a/arch/nds32/cpu/n1213/Makefile b/arch/nds32/cpu/n1213/Makefile new file mode 100644 index 0000000..8aa4a9d --- /dev/null +++ b/arch/nds32/cpu/n1213/Makefile @@ -0,0 +1,51 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2010 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 +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(CPU).a + +START = start.o +SOBJS = lowlevel_init.o + +SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) +START := $(addprefix $(obj),$(START)) + +all: $(obj).depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/nds32/cpu/n1213/ag101/Makefile b/arch/nds32/cpu/n1213/ag101/Makefile new file mode 100644 index 0000000..4a10ecd --- /dev/null +++ b/arch/nds32/cpu/n1213/ag101/Makefile @@ -0,0 +1,50 @@ +# +# (C) Copyright 2009 +# Marvell Semiconductor <www.marvell.com> +# Written-by: Prafulla Wadaskar prafulla@marvell.com +# +# Copyright (C) 2010 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).a + +COBJS-y = cpu.o ftsmc020.o timer.o + +SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/nds32/cpu/n1213/ag101/cpu.c b/arch/nds32/cpu/n1213/ag101/cpu.c new file mode 100644 index 0000000..0c852b6 --- /dev/null +++ b/arch/nds32/cpu/n1213/ag101/cpu.c @@ -0,0 +1,197 @@ +/* + * (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) 2010 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> + +/* + * setup up stack if necessary + */ +/* it makes no sense to use the caches if the MMU also isn't used */ +void cpu_init(void) +{ + _andesboot_real_end = _andesboot_end + CONFIG_STACKSIZE; +} + +/* + * 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) +{ +#ifdef CONFIG_MMU + unsigned long i; +#endif + + disable_interrupts(); + +#ifdef CONFIG_MMU + /* turn off I/D-cache */ + icache_disable(); + dcache_disable(); + + /* flush I/D-cache */ + invalidate_icac(); + invalidate_dcac(); +#endif +} + +void do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + extern void reset_cpu(ulong addr); + + disable_interrupts(); + + /* + * reset to the base addr of andesboot. + * currently no ROM loader at addr 0. + * do not use reset_cpu(0); + */ + reset_cpu(TEXT_BASE); + + /*NOTREACHED*/ +} + +static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache) +{ + if( cache == ICACHE) + return 8 << ( ( ( GET_ICM_CFG() & ICM_CFG_mskISZ) >> ICM_CFG_offISZ) - 1); + else + return 8 << ( ( ( GET_DCM_CFG() & DCM_CFG_mskDSZ) >> DCM_CFG_offDSZ) - 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/ag101/ftsmc020.c b/arch/nds32/cpu/n1213/ag101/ftsmc020.c new file mode 100644 index 0000000..7646537 --- /dev/null +++ b/arch/nds32/cpu/n1213/ag101/ftsmc020.c @@ -0,0 +1,51 @@ +/* + * (C) Copyright 2009 Faraday Technology + * Po-Yu Chuang ratbert@faraday-tech.com + * + * 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 <config.h> +#include <common.h> +#include <asm/io.h> +#include <asm/arch/ftsmc020.h> + +struct ftsmc020_config { + unsigned int config; + unsigned int timing; +}; + +static struct ftsmc020_config config[] = CONFIG_SYS_FTSMC020_CONFIGS; + +static struct ftsmc020 *smc = (struct ftsmc020 *)CONFIG_FTSMC020_BASE; + +static void ftsmc020_setup_bank(unsigned int bank, struct ftsmc020_config *cfg) +{ + if (bank > 3) { + printf("bank # %u invalid\n", bank); + return; + } + + writel(cfg->config, &smc->bank[bank].cr); + writel(cfg->timing, &smc->bank[bank].tpr); +} + +void ftsmc020_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(config); i++) + ftsmc020_setup_bank(i, &config[i]); +} diff --git a/arch/nds32/cpu/n1213/ag101/timer.c b/arch/nds32/cpu/n1213/ag101/timer.c new file mode 100644 index 0000000..1e5c3c2 --- /dev/null +++ b/arch/nds32/cpu/n1213/ag101/timer.c @@ -0,0 +1,213 @@ +/* + * (C) Copyright 2009 Faraday Technology + * Po-Yu Chuang ratbert@faraday-tech.com + * + * Copyright (C) 2010 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 <asm/arch/ftpmu010.h> +#include <asm/arch/fttmr010.h> + +static ulong timestamp; +static ulong lastdec; + +static struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE; +static struct ftpmu010 *pmu = (struct ftpmu010 *)CONFIG_FTPMU010_BASE; + +int timer_init(void) +{ + unsigned int oscc; + unsigned int cr; + + debug("%s()\n", __func__); + + /* disable timers */ + writel(0, &tmr->cr); + +#ifdef CONFIG_EXT_CLK + /* + * use 32768Hz oscillator for RTC, WDT, TIMER + */ + + /* enable the 32768Hz oscillator */ + oscc = readl(&pmu->OSCC); + oscc &= ~(FTPMU010_OSCC_OSCL_OFF | FTPMU010_OSCC_OSCL_TRI); + writel(oscc, &pmu->OSCC); + + /* wait until ready */ + while (!(readl(&pmu->OSCC) & FTPMU010_OSCC_OSCL_STABLE)) + ; + + /* select 32768Hz oscillator */ + oscc = readl(&pmu->OSCC); + oscc |= FTPMU010_OSCC_OSCL_RTCLSEL; + writel(oscc, &pmu->OSCC); +#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_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) +{ + /* capure current decrementer value time */ +#ifdef CONFIG_EXT_CLK + lastdec = readl(&tmr->timer3_counter) / (TIMER_CLOCK / CONFIG_SYS_HZ); +#else + lastdec = readl(&tmr->timer3_counter) / (CONFIG_SYS_HZ); +#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) +{ + /* current tick value */ +#ifdef CONFIG_EXT_CLK + ulong now = readl(&tmr->timer3_counter) / (TIMER_CLOCK / CONFIG_SYS_HZ); +#else + ulong now = readl(&tmr->timer3_counter) / (CONFIG_SYS_HZ); +#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) +{ + long tmo = usec * (CONFIG_SYS_HZ / 1000) / 1000; + 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_EXT_CLK + return CONFIG_SYS_HZ; +#else + return CONFIG_SYS_CLK_FREQ; +#endif +} diff --git a/arch/nds32/cpu/n1213/lowlevel_init.S b/arch/nds32/cpu/n1213/lowlevel_init.S new file mode 100644 index 0000000..f7fa12b --- /dev/null +++ b/arch/nds32/cpu/n1213/lowlevel_init.S @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2010 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 + */ + +.text + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +.globl lowlevel_init +lowlevel_init: + move $r10, $lp + jal mem_init + jal remap + + ret $r10 + +mem_init: + move $r11, $lp + li $r0, 0x90200000 + li $r1, 0x10000052 + swi $r1, [$r0] + li $r1, 0x00151151 + swi $r1, [$r0+0x4] + + li $r0, 0x90100018 + li $r1, 0x100b0000 + swi $r1, [$r0] + li $r0, 0x98100030 + lwi $r1, [$r0] + li $r2, 0x00010000 + or $r1, $r1, $r2 + swi $r1, [$r0] +#ifdef __NDS32_N1213_43U1H__ /* AG101 */ + lwi $r1, [$r0] + li $r2, 0x00e00000 + or $r1, $r1, $r2 + swi $r1, [$r0] + li $r0, 0x98100028 + lwi $r1, [$r0] + li $r2, 0x00000010 + or $r1, $r1, $r2 + swi $r1, [$r0] + li $r0, 0x9810004c + lwi $r1, [$r0] + li $r2, 0x0007f000 + or $r1, $r1, $r2 + swi $r1, [$r0] +#endif + li $r0, 0x90300000 + li $r1, 0x00011312 + swi $r1, [$r0] + li $r1, 0x00480180 + swi $r1, [$r0+0x4] + li $r1, 0x00002326 + swi $r1, [$r0+0x8] + li $r1, 0x00000010 + swi $r1, [$r0+0xc] +1: + lwi $r1, [$r0+0xc] + andi $r1, $r1, 0x1c + bnez $r1, 1b + + li $r1, 0x00000004 + swi $r1, [$r0+0xc] +2: + lwi $r1, [$r0+0xc] + bnez $r1, 2b + + li $r1, 0x00000008 + swi $r1, [$r0+0xc] +3: + lwi $r1, [$r0+0xc] + bnez $r1, 3b + + move $lp, $r11 + ret + +remap: + move $r11, $lp +#ifdef __NDS32_N1213_43U1H__ /* AG101 */ + bal 2f +relo_base: + move $r0, $lp +#else +relo_base: + mfusr $r0, $pc +#endif + + /* relocation, copy ROM code to SDRAM(current is at 0x10000000) */ + li $r4, 0x10000000 + li $r5, 0x0 + la $r1, relo_base + sub $r2, $r0, $r1 + sethi $r6, hi20(andesboot_end) + ori $r6, $r6, lo12(andesboot_end) + add $r6, $r6, $r2 +1: + lwi $r7, [$r5] + swi $r7, [$r4] + addi $r5, $r5, #4 + addi $r4, $r4, #4 + blt $r5, $r6, 1b + + /* Remapping */ + li $r0, 0x90300000 + li $r1, 0x00001100 + swi $r1, [$r0+0x10] + li $r1, 0x0 + swi $r1, [$r0+0x14] + swi $r1, [$r0+0x18] + swi $r1, [$r0+0x1c] + li $r1, 0x00001000 + swi $r1, [$r0+0x10] + + li $r0, 0x90100088 + lwi $r1, [$r0] + ori $r1, $r1, 0x1 + swi $r1, [$r0] + + li $r0, 0x90200000 +#ifdef __NDS32_N1213_43U1H__ /* AG101 */ + li $r1, 0x10400062 + swi $r1, [$r0+0x8] + li $r1, 0x000ff3ff + swi $r1, [$r0+0xc] +#else + li $r1, 0x10400062 + swi $r1, [$r0] +#endif + + move $lp, $r11 +2: + ret + +.globl show_led +show_led: + li $r8, 0x902ffffc ! 0x902ffffc + swi $r7, [$r8] + ret +#endif diff --git a/arch/nds32/cpu/n1213/start.S b/arch/nds32/cpu/n1213/start.S new file mode 100644 index 0000000..ba9d9e6 --- /dev/null +++ b/arch/nds32/cpu/n1213/start.S @@ -0,0 +1,447 @@ +/* + * Andesboot - Startup Code for Whitiger core + * + * Copyright (c) 2001 Marius Gröger mag@sysgo.de + * Copyright (c) 2002 Alex Züpke azu@sysgo.de + * Copyright (c) 2002 Gary Jennejohn gj@denx.de + * + * Copyright (C) 2006 Andes Technology Corporation + * Copyright (C) 2006 Shawn Lin nobuhiro@andestech.com + * Copyright (C) 2010 Macpaul 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 <config.h> +#include <common.h> +#include <version.h> +#include <nds32_common.h> + +!======================================================================== +! Jump vector table for EVIC mode +!======================================================================== + +#define ENA_DCAC 2UL +#define DIS_DCAC ~ENA_DCAC +#define ICAC_MEM_kbfISET (0x07) ! I Cache sets per way +#define ICAC_MEM_kbfIWAY (0x07<<3) ! I cache ways +#define ICAC_MEM_kbfISZ (0x07<<6) ! I cache line size +#define DCAC_MEM_kbfDSET (0x07) ! D Cache sets per way +#define DCAC_MEM_kbfDWAY (0x07<<3) ! D cache ways +#define DCAC_MEM_kbfDSZ (0x07<<6) ! D cache line size + +#define psw $ir0 +#define EIT_INTR_PSW $ir1 /* interruption $PSW */ +#define EIT_PREV_IPSW $ir2 /* previous ... */ +#define EIT_IVB $ir3 /* intr vector base address */ +#define EIT_EVA $ir4 /* MMU related Exception Virtual Address register */ +#define EIT_PREV_EVA $ir5 /* previous $eva */ +#define EIT_ITYPE $ir6 /* interruption type */ +#define EIT_PREV_ITYPE $ir7 /* prev intr type */ +#define EIT_MACH_ERR $ir8 /* machine error log */ +#define EIT_INTR_PC $ir9 /* Interruption PC */ +#define EIT_PREV_IPC $ir10 /* previous $IPC */ +#define EIT_OVL_INTR_PC $ir11 /* overflow interruption PC */ +#define EIT_PREV_P0 $ir12 /* prev $P0 */ +#define EIT_PREV_P1 $ir13 /* prev $p1 */ +#define CR_ICAC_MEM $cr1 /* Insn cache/memory config register */ +#define CR_DCAC_MEM $cr2 /* Data cache/memory config register */ +#define MR_CAC_CTL $mr8 + + +.globl _start + +_start: b reset + b TLB_fill + b TLB_not_present + b TLB_misc + b TLB_VLPT_miss + b cache_parity_error + b debug + b general_exception + b internal_interrupt ! H0I + b internal_interrupt ! H1I + b internal_interrupt ! H2I + b internal_interrupt ! H3I + b internal_interrupt ! H4I + b internal_interrupt ! H5I + + .balign 16 + + +!======================================================================== +! Andesboot Startup Code (reset vector) +! +! 1. bootstrap +! 1.1 reset - start of Andesboot +! 1.2 to superuser mode - as is when reset +! 1.3 Turn off watchdog timer +! 2. Do critical init when reboot (not from mem) +! 3. Relocate andesboot to ram +! 4. Setup stack +! 5. Jump to second stage (start_andesboot) +!======================================================================== + +! Note: TEXT_BASE is defined by the (board-dependent) linker script +_TEXT_BASE: + .word TEXT_BASE + +.globl _andesboot_start +_andesboot_start: + .word _start + +! Note: andesboot_end is defined by the (board-dependent) linker script +.globl _andesboot_end +_andesboot_end: + .word andesboot_end + +! _andesboot_real_end is the first usable RAM address behind Andesboot +! and the various stacks +.globl _andesboot_real_end +_andesboot_real_end: + .word 0x0badc0de + + +!============================================= +! The bootstrap code of Andesboot +!============================================= + +reset: + +load_lli: +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + jal load_lowlevel_init + jral $p0 +#endif + + ! Set the Whitiger core to superuser mode + ! According to spec, it is already when reset + +#define WD_CR 0xC +#define WdEnable 0x1 + + ! Turn off the watchdog, according to Faraday FTWDT010 spec + li $p0, (NDS32_COMMON_WATCHDOG_BASE+WD_CR) ! Get the address of the WD CR + lwi $p1, [$p0] ! Get the WD configuration + andi $p1, $p1, 0x1f ! Wipe out useless bits + li $r0, ~WdEnable + 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 + +! Do CPU critical regs init only at reboot, not when booting from ram +#ifdef CONFIG_INIT_CRITICAL + bal cpu_init_crit ! Do CPU critical regs init +#endif +.align 2 +relocate: + ! relocate andesboot to RAM + jal 2f + !la $r0, _start ! $r0 = source start address + !l.w $r2, _andesboot_start ! Andesboot start address + !l.w $r3, _andesboot_end ! Andesboot end address + !sub $r2, $r3, $r2 ! $r2 = size of Andesboot + !l.w $r1, _TEXT_BASE ! $r1 = destination start address + move $r0, $lp + la $p0, _start + la $p1, relocate+4 + sub $p0, $p1, $p0 + sub $r0, $r0, $p0 + + la $p0, _andesboot_end + sub $p0, $p0, $p1 + move $r3, $lp + lw $r3, [$r3+$p0] ! _andesboot_end + addi $p0, $p0, -4 + move $r2, $lp + lw $r2, [$r2+$p0] ! _andesboot_start + sub $r2, $r3, $r2 + addi $p0, $p0, -4 + move $r1, $lp + lw $r1, [$r1+$p0] ! _TEXT_BASE + + ! $r0 = source address + ! $r1 = destination address + ! $r2 = size to copy +copy_loop: + lmw.bim $r3, [$r0], $r10 + smw.bim $r3, [$r1], $r10 + addi $r2, $r2, -32 + bgez $r2, copy_loop + + ! Set up the stack + l.w $p0, _andesboot_end ! Defined by the board linker script + li $p1, CONFIG_STACKSIZE ! (128*1024) defined in config.h + add $sp, $p0, $p1 + + bal flib_init_bss_memory + + ! Jump to start_andesboot (2nd phase) + l.w $p0, __start_andesboot + br $p0 + +__start_andesboot: .word start_andesboot + +!========================================================================= +! Initialize CPU critical registers +! +! 1. Setup control registers +! 1.1 Mask all IRQs +! 1.2 Flush cache and TLB +! 1.3 Disable MMU and cache +! 2. Setup memory timing +!========================================================================= + +cpu_init_crit: + !push ra + move $r0, $lp + ! Disable Interrupts by clear GIE in $PSW reg + setgie.d + + ! Flush caches and TLB + + ! Invalidate caches + bal invalidate_icac + bal invalidate_dcac + + ! Flush TLB + mfsr $p0, $MMU_CFG + andi $p0, $p0, 0x3 ! MMPS + li $p1, 0x2 ! TLB MMU + bne $p0, $p1, 1f + tlbop FlushAll ! Flush TLB + +1: + ! Disable MMU, Dcache + ! Whitiger is MMU disabled when reset + ! Disable the D$ + mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg + li $p1, DIS_DCAC + and $p0, $p0, $p1 ! Set DC_EN bit + mtsr $p0, MR_CAC_CTL ! write back the $CACHE_CTL reg + isb + + ! RAM is initialized in the dram_init()(board/nds32/cpe.c) + ! Remove the memsetup.S in the board directory. + !pop ra + + move $lp, $r0 +2: + ret + +flib_init_bss_memory: + smw.adm $r4, [$sp], $r6, #0x1 + + la $r4, __bss_start + la $r5, __bss_end + move $r6, #0 +1: + swi.p $r6, [$r4], #4 + blt $r4, $r5, 1b ! Check if done.. + + lmw.bim $r4, [$sp], $r6, #0x1 + ret + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +load_lowlevel_init: + la $r6, lowlevel_init + la $r7, load_lli + 4 + sub $p0, $r6, $r7 + add $p0, $p0, $lp +ret +#endif + +!======================================================= +! Invalidate I$ +!======================================================= +invalidate_icac: + mfsr $t0, CR_ICAC_MEM ! read $cr1(I CAC/MEM cfg. reg.) configuration + andi $p0, $t0, ICAC_MEM_kbfISZ ! Get the ISZ field + beqz $p0, end_flush_icache ! if $p0=0, then no I CAC existed + srli $p0, $p0, 6 ! get $p0 the index of I$ block + addi $t1, $p0, 2 ! $t1= bit width of I cache line size(ISZ) + li $t4, 1 + sll $t5, $t4, $t1 ! get $t5 cache line size + andi $p1, $t0, ICAC_MEM_kbfISET ! get the ISET field + addi $t2, $p1, 6 ! $t2= bit width of ISET + andi $p1, $t0, ICAC_MEM_kbfIWAY ! get bitfield of Iway + srli $p1, $p1, 3 + addi $p1, $p1, 1 ! then $p1 is I way number + add $t3, $t2, $t1 ! SHIFT + sll $p1, $p1, $t3 ! GET the total cache size +ICAC_LOOP: + sub $p1, $p1, $t5 + cctl $p1, L1I_IX_INVAL + bnez $p1, ICAC_LOOP +end_flush_icache: + ret +!======================================================= +! Invalidate D$ +!======================================================= +invalidate_dcac: + mfsr $t0, CR_DCAC_MEM ! read $cr2(D CAC/MEM cfg. reg.) configuration + andi $p0, $t0, DCAC_MEM_kbfDSZ ! Get the DSZ field + beqz $p0, end_flush_dcache ! if $p0=0, then no D CAC existed + srli $p0, $p0, 6 ! get $p0 the index of D$ block + addi $t1, $p0, 2 ! $t1= bit width of D cache line size(DSZ) + li $t4, 1 + sll $t5, $t4, $t1 ! get $t5 cache line size + andi $p1, $t0, DCAC_MEM_kbfDSET ! get the DSET field + addi $t2, $p1, 6 ! $t2= bit width of DSET + andi $p1, $t0, DCAC_MEM_kbfDWAY ! get bitfield of D way + srli $p1, $p1, 3 + addi $p1, $p1, 1 ! then $p1 is D way number + add $t3, $t2, $t1 ! SHIFT + sll $p1, $p1, $t3 ! GET the total cache size +DCAC_LOOP: + sub $p1, $p1, $t5 + cctl $p1, L1D_IX_INVAL + bnez $p1, DCAC_LOOP +end_flush_dcache: + ret + +!======================================================================== +! Interrupt handling +!======================================================================== + +/* + * exception handlers + */ + .align 5 + + .macro SAVE_ALL + ! FIXME: Other way to get PC? + ! FIXME: Update according to the newest spec!! +1: la $r28, 1 + push $r28 + mfsr $r28, psw ! $psw + push $r28 + mfsr $r28, EIT_EVA ! $ir1 $EVA + push $r28 + mfsr $r28, EIT_ITYPE ! $ir2 $ITYPE + push $r28 + mfsr $r28, EIT_MACH_ERR ! $ir3 Mach Error + push $r28 + mfsr $r28, EIT_INTR_PSW ! $ir5 $IPSW + push $r28 + mfsr $r28, EIT_PREV_IPSW ! $ir6 prev $IPSW + push $r28 + mfsr $r28, EIT_PREV_EVA ! $ir7 prev $EVA + push $r28 + mfsr $r28, EIT_PREV_ITYPE ! $ir8 prev $ITYPE + push $r28 + mfsr $r28, EIT_INTR_PC ! $ir9 Interruption PC + push $r28 + mfsr $r28, EIT_PREV_IPC ! $ir10 prev Interruption PC + push $r28 + mfsr $r28, EIT_OVL_INTR_PC ! $ir11:OVerflowed interruption PC + push $r28 + mfusr $r28, $d1.lo + push $r28 + mfusr $r28, $d1.hi + push $r28 + mfusr $r28, $d0.lo + push $r28 + mfusr $r28, $d0.hi + push $r28 + pushm $r0,$r30 /* we will also store $sp-$r31, ra-$r30, $gp-$r29, $r28-$fp */ + addi $sp, $sp, -4 ! make room for implicit pt_regs parameters + .endm + + .align 5 +TLB_fill: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 1 ! Determine interruption type + bal do_interruption + + .align 5 +TLB_not_present: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 2 ! Determine interruption type + bal do_interruption + + .align 5 +TLB_misc: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 3 ! Determine interruption type + bal do_interruption + + .align 5 +TLB_VLPT_miss: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 4 ! Determine interruption type + bal do_interruption + + .align 5 +cache_parity_error: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 5 ! Determine interruption type + bal do_interruption + + .align 5 +debug: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 6 ! Determine interruption type + bal do_interruption + + .align 5 +general_exception: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 7 ! Determine interruption type + bal do_interruption + + .align 5 +internal_interrupt: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 8 ! Determine interruption type + bal do_interruption + + .align 5 + +!=========================================== +!void reset_cpu(ulong addr); +! $r0: input address to jump to +!=========================================== +.globl reset_cpu +reset_cpu: +! No need to disable MMU because we never enable it! + + bal invalidate_icac + bal invalidate_dcac + mfsr $p0, $MMU_CFG + andi $p0, $p0, 0x3 ! MMPS + li $p1, 0x2 ! TLB MMU + bne $p0, $p1, 1f + tlbop FlushAll ! Flush TLB +1: + mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg + li $p1, DIS_DCAC + and $p0, $p0, $p1 ! Clear the DC_EN bit + mtsr $p0, MR_CAC_CTL ! Write back the $CACHE_CTL reg + br $r0 ! Jump to the input address diff --git a/arch/nds32/cpu/n1213/u-boot.lds b/arch/nds32/cpu/n1213/u-boot.lds new file mode 100644 index 0000000..3515ce0 --- /dev/null +++ b/arch/nds32/cpu/n1213/u-boot.lds @@ -0,0 +1,68 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright (C) 2010 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 + */ + +OUTPUT_FORMAT("elf32-nds32", "elf32-nds32", "elf32-nds32") +OUTPUT_ARCH(nds32) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + arch/nds32/cpu/n1213/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + __bss_end = .; + + . = ALIGN(4); + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } + + andesboot_end = .; + + . = 0x02000000; + .u_boot_ohci_data_st : { *(.u_boot_ohci_data_st) } +} diff --git a/arch/nds32/cpu/start.S b/arch/nds32/cpu/start.S new file mode 100644 index 0000000..ba9d9e6 --- /dev/null +++ b/arch/nds32/cpu/start.S @@ -0,0 +1,447 @@ +/* + * Andesboot - Startup Code for Whitiger core + * + * Copyright (c) 2001 Marius Gröger mag@sysgo.de + * Copyright (c) 2002 Alex Züpke azu@sysgo.de + * Copyright (c) 2002 Gary Jennejohn gj@denx.de + * + * Copyright (C) 2006 Andes Technology Corporation + * Copyright (C) 2006 Shawn Lin nobuhiro@andestech.com + * Copyright (C) 2010 Macpaul 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 <config.h> +#include <common.h> +#include <version.h> +#include <nds32_common.h> + +!======================================================================== +! Jump vector table for EVIC mode +!======================================================================== + +#define ENA_DCAC 2UL +#define DIS_DCAC ~ENA_DCAC +#define ICAC_MEM_kbfISET (0x07) ! I Cache sets per way +#define ICAC_MEM_kbfIWAY (0x07<<3) ! I cache ways +#define ICAC_MEM_kbfISZ (0x07<<6) ! I cache line size +#define DCAC_MEM_kbfDSET (0x07) ! D Cache sets per way +#define DCAC_MEM_kbfDWAY (0x07<<3) ! D cache ways +#define DCAC_MEM_kbfDSZ (0x07<<6) ! D cache line size + +#define psw $ir0 +#define EIT_INTR_PSW $ir1 /* interruption $PSW */ +#define EIT_PREV_IPSW $ir2 /* previous ... */ +#define EIT_IVB $ir3 /* intr vector base address */ +#define EIT_EVA $ir4 /* MMU related Exception Virtual Address register */ +#define EIT_PREV_EVA $ir5 /* previous $eva */ +#define EIT_ITYPE $ir6 /* interruption type */ +#define EIT_PREV_ITYPE $ir7 /* prev intr type */ +#define EIT_MACH_ERR $ir8 /* machine error log */ +#define EIT_INTR_PC $ir9 /* Interruption PC */ +#define EIT_PREV_IPC $ir10 /* previous $IPC */ +#define EIT_OVL_INTR_PC $ir11 /* overflow interruption PC */ +#define EIT_PREV_P0 $ir12 /* prev $P0 */ +#define EIT_PREV_P1 $ir13 /* prev $p1 */ +#define CR_ICAC_MEM $cr1 /* Insn cache/memory config register */ +#define CR_DCAC_MEM $cr2 /* Data cache/memory config register */ +#define MR_CAC_CTL $mr8 + + +.globl _start + +_start: b reset + b TLB_fill + b TLB_not_present + b TLB_misc + b TLB_VLPT_miss + b cache_parity_error + b debug + b general_exception + b internal_interrupt ! H0I + b internal_interrupt ! H1I + b internal_interrupt ! H2I + b internal_interrupt ! H3I + b internal_interrupt ! H4I + b internal_interrupt ! H5I + + .balign 16 + + +!======================================================================== +! Andesboot Startup Code (reset vector) +! +! 1. bootstrap +! 1.1 reset - start of Andesboot +! 1.2 to superuser mode - as is when reset +! 1.3 Turn off watchdog timer +! 2. Do critical init when reboot (not from mem) +! 3. Relocate andesboot to ram +! 4. Setup stack +! 5. Jump to second stage (start_andesboot) +!======================================================================== + +! Note: TEXT_BASE is defined by the (board-dependent) linker script +_TEXT_BASE: + .word TEXT_BASE + +.globl _andesboot_start +_andesboot_start: + .word _start + +! Note: andesboot_end is defined by the (board-dependent) linker script +.globl _andesboot_end +_andesboot_end: + .word andesboot_end + +! _andesboot_real_end is the first usable RAM address behind Andesboot +! and the various stacks +.globl _andesboot_real_end +_andesboot_real_end: + .word 0x0badc0de + + +!============================================= +! The bootstrap code of Andesboot +!============================================= + +reset: + +load_lli: +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + jal load_lowlevel_init + jral $p0 +#endif + + ! Set the Whitiger core to superuser mode + ! According to spec, it is already when reset + +#define WD_CR 0xC +#define WdEnable 0x1 + + ! Turn off the watchdog, according to Faraday FTWDT010 spec + li $p0, (NDS32_COMMON_WATCHDOG_BASE+WD_CR) ! Get the address of the WD CR + lwi $p1, [$p0] ! Get the WD configuration + andi $p1, $p1, 0x1f ! Wipe out useless bits + li $r0, ~WdEnable + 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 + +! Do CPU critical regs init only at reboot, not when booting from ram +#ifdef CONFIG_INIT_CRITICAL + bal cpu_init_crit ! Do CPU critical regs init +#endif +.align 2 +relocate: + ! relocate andesboot to RAM + jal 2f + !la $r0, _start ! $r0 = source start address + !l.w $r2, _andesboot_start ! Andesboot start address + !l.w $r3, _andesboot_end ! Andesboot end address + !sub $r2, $r3, $r2 ! $r2 = size of Andesboot + !l.w $r1, _TEXT_BASE ! $r1 = destination start address + move $r0, $lp + la $p0, _start + la $p1, relocate+4 + sub $p0, $p1, $p0 + sub $r0, $r0, $p0 + + la $p0, _andesboot_end + sub $p0, $p0, $p1 + move $r3, $lp + lw $r3, [$r3+$p0] ! _andesboot_end + addi $p0, $p0, -4 + move $r2, $lp + lw $r2, [$r2+$p0] ! _andesboot_start + sub $r2, $r3, $r2 + addi $p0, $p0, -4 + move $r1, $lp + lw $r1, [$r1+$p0] ! _TEXT_BASE + + ! $r0 = source address + ! $r1 = destination address + ! $r2 = size to copy +copy_loop: + lmw.bim $r3, [$r0], $r10 + smw.bim $r3, [$r1], $r10 + addi $r2, $r2, -32 + bgez $r2, copy_loop + + ! Set up the stack + l.w $p0, _andesboot_end ! Defined by the board linker script + li $p1, CONFIG_STACKSIZE ! (128*1024) defined in config.h + add $sp, $p0, $p1 + + bal flib_init_bss_memory + + ! Jump to start_andesboot (2nd phase) + l.w $p0, __start_andesboot + br $p0 + +__start_andesboot: .word start_andesboot + +!========================================================================= +! Initialize CPU critical registers +! +! 1. Setup control registers +! 1.1 Mask all IRQs +! 1.2 Flush cache and TLB +! 1.3 Disable MMU and cache +! 2. Setup memory timing +!========================================================================= + +cpu_init_crit: + !push ra + move $r0, $lp + ! Disable Interrupts by clear GIE in $PSW reg + setgie.d + + ! Flush caches and TLB + + ! Invalidate caches + bal invalidate_icac + bal invalidate_dcac + + ! Flush TLB + mfsr $p0, $MMU_CFG + andi $p0, $p0, 0x3 ! MMPS + li $p1, 0x2 ! TLB MMU + bne $p0, $p1, 1f + tlbop FlushAll ! Flush TLB + +1: + ! Disable MMU, Dcache + ! Whitiger is MMU disabled when reset + ! Disable the D$ + mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg + li $p1, DIS_DCAC + and $p0, $p0, $p1 ! Set DC_EN bit + mtsr $p0, MR_CAC_CTL ! write back the $CACHE_CTL reg + isb + + ! RAM is initialized in the dram_init()(board/nds32/cpe.c) + ! Remove the memsetup.S in the board directory. + !pop ra + + move $lp, $r0 +2: + ret + +flib_init_bss_memory: + smw.adm $r4, [$sp], $r6, #0x1 + + la $r4, __bss_start + la $r5, __bss_end + move $r6, #0 +1: + swi.p $r6, [$r4], #4 + blt $r4, $r5, 1b ! Check if done.. + + lmw.bim $r4, [$sp], $r6, #0x1 + ret + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +load_lowlevel_init: + la $r6, lowlevel_init + la $r7, load_lli + 4 + sub $p0, $r6, $r7 + add $p0, $p0, $lp +ret +#endif + +!======================================================= +! Invalidate I$ +!======================================================= +invalidate_icac: + mfsr $t0, CR_ICAC_MEM ! read $cr1(I CAC/MEM cfg. reg.) configuration + andi $p0, $t0, ICAC_MEM_kbfISZ ! Get the ISZ field + beqz $p0, end_flush_icache ! if $p0=0, then no I CAC existed + srli $p0, $p0, 6 ! get $p0 the index of I$ block + addi $t1, $p0, 2 ! $t1= bit width of I cache line size(ISZ) + li $t4, 1 + sll $t5, $t4, $t1 ! get $t5 cache line size + andi $p1, $t0, ICAC_MEM_kbfISET ! get the ISET field + addi $t2, $p1, 6 ! $t2= bit width of ISET + andi $p1, $t0, ICAC_MEM_kbfIWAY ! get bitfield of Iway + srli $p1, $p1, 3 + addi $p1, $p1, 1 ! then $p1 is I way number + add $t3, $t2, $t1 ! SHIFT + sll $p1, $p1, $t3 ! GET the total cache size +ICAC_LOOP: + sub $p1, $p1, $t5 + cctl $p1, L1I_IX_INVAL + bnez $p1, ICAC_LOOP +end_flush_icache: + ret +!======================================================= +! Invalidate D$ +!======================================================= +invalidate_dcac: + mfsr $t0, CR_DCAC_MEM ! read $cr2(D CAC/MEM cfg. reg.) configuration + andi $p0, $t0, DCAC_MEM_kbfDSZ ! Get the DSZ field + beqz $p0, end_flush_dcache ! if $p0=0, then no D CAC existed + srli $p0, $p0, 6 ! get $p0 the index of D$ block + addi $t1, $p0, 2 ! $t1= bit width of D cache line size(DSZ) + li $t4, 1 + sll $t5, $t4, $t1 ! get $t5 cache line size + andi $p1, $t0, DCAC_MEM_kbfDSET ! get the DSET field + addi $t2, $p1, 6 ! $t2= bit width of DSET + andi $p1, $t0, DCAC_MEM_kbfDWAY ! get bitfield of D way + srli $p1, $p1, 3 + addi $p1, $p1, 1 ! then $p1 is D way number + add $t3, $t2, $t1 ! SHIFT + sll $p1, $p1, $t3 ! GET the total cache size +DCAC_LOOP: + sub $p1, $p1, $t5 + cctl $p1, L1D_IX_INVAL + bnez $p1, DCAC_LOOP +end_flush_dcache: + ret + +!======================================================================== +! Interrupt handling +!======================================================================== + +/* + * exception handlers + */ + .align 5 + + .macro SAVE_ALL + ! FIXME: Other way to get PC? + ! FIXME: Update according to the newest spec!! +1: la $r28, 1 + push $r28 + mfsr $r28, psw ! $psw + push $r28 + mfsr $r28, EIT_EVA ! $ir1 $EVA + push $r28 + mfsr $r28, EIT_ITYPE ! $ir2 $ITYPE + push $r28 + mfsr $r28, EIT_MACH_ERR ! $ir3 Mach Error + push $r28 + mfsr $r28, EIT_INTR_PSW ! $ir5 $IPSW + push $r28 + mfsr $r28, EIT_PREV_IPSW ! $ir6 prev $IPSW + push $r28 + mfsr $r28, EIT_PREV_EVA ! $ir7 prev $EVA + push $r28 + mfsr $r28, EIT_PREV_ITYPE ! $ir8 prev $ITYPE + push $r28 + mfsr $r28, EIT_INTR_PC ! $ir9 Interruption PC + push $r28 + mfsr $r28, EIT_PREV_IPC ! $ir10 prev Interruption PC + push $r28 + mfsr $r28, EIT_OVL_INTR_PC ! $ir11:OVerflowed interruption PC + push $r28 + mfusr $r28, $d1.lo + push $r28 + mfusr $r28, $d1.hi + push $r28 + mfusr $r28, $d0.lo + push $r28 + mfusr $r28, $d0.hi + push $r28 + pushm $r0,$r30 /* we will also store $sp-$r31, ra-$r30, $gp-$r29, $r28-$fp */ + addi $sp, $sp, -4 ! make room for implicit pt_regs parameters + .endm + + .align 5 +TLB_fill: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 1 ! Determine interruption type + bal do_interruption + + .align 5 +TLB_not_present: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 2 ! Determine interruption type + bal do_interruption + + .align 5 +TLB_misc: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 3 ! Determine interruption type + bal do_interruption + + .align 5 +TLB_VLPT_miss: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 4 ! Determine interruption type + bal do_interruption + + .align 5 +cache_parity_error: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 5 ! Determine interruption type + bal do_interruption + + .align 5 +debug: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 6 ! Determine interruption type + bal do_interruption + + .align 5 +general_exception: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 7 ! Determine interruption type + bal do_interruption + + .align 5 +internal_interrupt: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 8 ! Determine interruption type + bal do_interruption + + .align 5 + +!=========================================== +!void reset_cpu(ulong addr); +! $r0: input address to jump to +!=========================================== +.globl reset_cpu +reset_cpu: +! No need to disable MMU because we never enable it! + + bal invalidate_icac + bal invalidate_dcac + mfsr $p0, $MMU_CFG + andi $p0, $p0, 0x3 ! MMPS + li $p1, 0x2 ! TLB MMU + bne $p0, $p1, 1f + tlbop FlushAll ! Flush TLB +1: + mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg + li $p1, DIS_DCAC + and $p0, $p0, $p1 ! Clear the DC_EN bit + mtsr $p0, MR_CAC_CTL ! Write back the $CACHE_CTL reg + br $r0 ! Jump to the input address