[U-Boot] [PATCH 2/2] nds32/Core_N1213: add N1213 cpu core support for NDS32 arch
Macpaul Lin
macpaul at andestech.com
Tue Oct 26 07:31:58 CEST 2010
Add N1213 cpu core support for NDS32 arch.
Included lowlevel_init procedures, and linker scripts.
NDS32 Core N1213 has the following features.
Core:
- 16-/32-bit mixable instruction format
- 32 general-purpose 32-bit registers
- 8-stage pipeline
- Dynamic branch prediction
- 32/64/128/256 BTB
- Return address stack (RAS)
- Vector interrupts for internal/external
- 3 HW-level nested interruptions
- User and super-user mode support
- Memory-mapped I/O
- Address space up to 4GB
Memory Management Unit:
- TLB
- Optional hardware page table walker
- Two groups of page size support
Memory Subsystem:
- I & D cache
- I & D local memory (LM)
Bus Interface:
- Synchronous/Asynchronous AHB bus: 0, 1 or 2 ports
start.S will start up the CPU core at first,
then jump to SoC dependent "lowlevel_init.S" and
"watchdog.S" to configure peripheral devices.
Signed-off-by: Macpaul Lin <macpaul at andestech.com>
---
arch/nds32/cpu/n1213/Makefile | 50 +++++
arch/nds32/cpu/n1213/start.S | 449 +++++++++++++++++++++++++++++++++++++++
arch/nds32/cpu/n1213/u-boot.lds | 68 ++++++
3 files changed, 567 insertions(+), 0 deletions(-)
create mode 100644 arch/nds32/cpu/n1213/Makefile
create mode 100644 arch/nds32/cpu/n1213/start.S
create mode 100644 arch/nds32/cpu/n1213/u-boot.lds
diff --git a/arch/nds32/cpu/n1213/Makefile b/arch/nds32/cpu/n1213/Makefile
new file mode 100644
index 0000000..3b66a57
--- /dev/null
+++ b/arch/nds32/cpu/n1213/Makefile
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2000, 2001, 2002
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# Copyright (C) 2010 Andes Technology Corporation
+# Shawn Lin, Andes Technology Corporation <nobuhiro at andestech.com>
+# Macpaul Lin, Andes Technology Corporation <macpaul at 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
+
+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/start.S b/arch/nds32/cpu/n1213/start.S
new file mode 100644
index 0000000..411fa1f
--- /dev/null
+++ b/arch/nds32/cpu/n1213/start.S
@@ -0,0 +1,449 @@
+/*
+ * Andesboot - Startup Code for Whitiger core
+ *
+ * Copyright (C) 2006 Andes Technology Corporation
+ * Copyright (C) 2006 Shawn Lin <nobuhiro at andestech.com>
+ * Copyright (C) 2010 Macpaul <macpaul at 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>
+
+!========================================================================
+! Jump vector table for EVIC mode
+!========================================================================
+
+#define ENA_DCAC 2UL
+#define DIS_DCAC ~ENA_DCAC
+#define ICAC_MEM_KBF_ISET (0x07) ! I Cache sets per way
+#define ICAC_MEM_KBF_IWAY (0x07<<3) ! I cache ways
+#define ICAC_MEM_KBF_ISZ (0x07<<6) ! I cache line size
+#define DCAC_MEM_KBF_DSET (0x07) ! D Cache sets per way
+#define DCAC_MEM_KBF_DWAY (0x07<<3) ! D cache ways
+#define DCAC_MEM_KBF_DSZ (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.4 Do lowlevel_init
+! - (this will jump out to lowlevel_init.S in SoC)
+! - (lowlevel_init)
+! 1.3 Turn off watchdog timer
+! - (this will jump out to watchdog.S in SoC)
+! - (turnoff_watchdog)
+! 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
+
+turnoff_wtdog:
+#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG
+ jal load_turnoff_watchdog
+ jral $p0
+#endif
+
+! 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
+
+#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG
+load_turnoff_watchdog:
+ la $r6, turnoff_watchdog
+ la $r7, turnoff_wtdog + 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_KBF_ISZ ! 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_KBF_ISET ! get the ISET field
+ addi $t2, $p1, 6 ! $t2= bit width of ISET
+ andi $p1, $t0, ICAC_MEM_KBF_IWAY ! 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_KBF_DSZ ! 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_KBF_DSET ! get the DSET field
+ addi $t2, $p1, 6 ! $t2= bit width of DSET
+ andi $p1, $t0, DCAC_MEM_KBF_DWAY ! 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 at denx.de.
+ *
+ * Copyright (C) 2010 Andes Technology Corporation
+ * Shawn Lin, Andes Technology Corporation <nobuhiro at andestech.com>
+ * Macpaul Lin, Andes Technology Corporation <macpaul at 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) }
+}
--
1.7.3.1
More information about the U-Boot
mailing list