diff options
Diffstat (limited to 'qemu/roms/u-boot/arch/nds32/cpu/n1213')
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/Makefile | 15 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/Makefile | 21 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/cpu.c | 68 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/lowlevel_init.S | 332 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/timer.c | 191 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/watchdog.S | 33 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/Makefile | 21 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/cpu.c | 67 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/lowlevel_init.S | 307 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/timer.c | 191 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/watchdog.S | 33 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/start.S | 529 | ||||
-rw-r--r-- | qemu/roms/u-boot/arch/nds32/cpu/n1213/u-boot.lds | 56 |
13 files changed, 1864 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/arch/nds32/cpu/n1213/Makefile b/qemu/roms/u-boot/arch/nds32/cpu/n1213/Makefile new file mode 100644 index 000000000..206d304d4 --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/Makefile @@ -0,0 +1,15 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright (C) 2011 Andes Technology Corporation +# Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com> +# Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +# necessary to create built-in.o +obj- := __dummy__.o + +extra-y = start.o diff --git a/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/Makefile b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/Makefile new file mode 100644 index 000000000..c21ce0282 --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/Makefile @@ -0,0 +1,21 @@ +# +# (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> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := cpu.o timer.o + +ifndef CONFIG_SKIP_LOWLEVEL_INIT +obj-y += lowlevel_init.o +endif + +ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG +obj-y += watchdog.o +endif diff --git a/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/cpu.c b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/cpu.c new file mode 100644 index 000000000..31d72712f --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/cpu.c @@ -0,0 +1,68 @@ +/* + * (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> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* 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(); + while (1) + ; +#endif /* CONFIG_FTWDT010_WATCHDOG */ + + /*NOTREACHED*/ +} diff --git a/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/lowlevel_init.S b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/lowlevel_init.S new file mode 100644 index 000000000..d6484b9cc --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/lowlevel_init.S @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2011 Andes Technology Corporation + * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com> + * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +.text + +#include <common.h> +#include <config.h> + +#include <asm/macro.h> +#include <generated/asm-offsets.h> + +/* + * parameters for the SDRAM controller + */ +#define SDMC_TP1_A (CONFIG_FTSDMC021_BASE + FTSDMC021_TP1) +#define SDMC_TP2_A (CONFIG_FTSDMC021_BASE + FTSDMC021_TP2) +#define SDMC_CR1_A (CONFIG_FTSDMC021_BASE + FTSDMC021_CR1) +#define SDMC_CR2_A (CONFIG_FTSDMC021_BASE + FTSDMC021_CR2) +#define SDMC_B0_BSR_A (CONFIG_FTSDMC021_BASE + FTSDMC021_BANK0_BSR) +#define SDMC_B1_BSR_A (CONFIG_FTSDMC021_BASE + FTSDMC021_BANK1_BSR) + +#define SDMC_TP1_D CONFIG_SYS_FTSDMC021_TP1 +#define SDMC_TP2_D CONFIG_SYS_FTSDMC021_TP2 +#define SDMC_CR1_D CONFIG_SYS_FTSDMC021_CR1 +#define SDMC_CR2_D CONFIG_SYS_FTSDMC021_CR2 + +#define SDMC_B0_BSR_D CONFIG_SYS_FTSDMC021_BANK0_BSR +#define SDMC_B1_BSR_D CONFIG_SYS_FTSDMC021_BANK1_BSR + + +/* + * for Orca and Emerald + */ +#define BOARD_ID_REG 0x104 +#define BOARD_ID_FAMILY_MASK 0xfff000 +#define BOARD_ID_FAMILY_V5 0x556000 +#define BOARD_ID_FAMILY_K7 0x74b000 + +/* + * parameters for the static memory controller + */ +#define SMC_BANK0_CR_A (CONFIG_FTSMC020_BASE + FTSMC020_BANK0_CR) +#define SMC_BANK0_TPR_A (CONFIG_FTSMC020_BASE + FTSMC020_BANK0_TPR) + +#define SMC_BANK0_CR_D FTSMC020_BANK0_LOWLV_CONFIG +#define SMC_BANK0_TPR_D FTSMC020_BANK0_LOWLV_TIMING + +/* + * 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) + +/* + * for Orca and Emerald + */ +#define AHBC_BSR4_A (CONFIG_FTAHBC020S_BASE + FTAHBC020S_SLAVE_BSR_4) +#define AHBC_BSR6_D CONFIG_SYS_FTAHBC020S_SLAVE_BSR_6 + +/* + * parameters for the pmu controoler + */ +#define PMU_PDLLCR0_A (CONFIG_FTPMU010_BASE + FTPMU010_PDLLCR0) + +/* + * numeric 7 segment display + */ +.macro led, num + write32 CONFIG_DEBUG_LED, \num +.endm + +/* + * Waiting for SDRAM to set up + */ +.macro wait_sdram + li $r0, CONFIG_FTSDMC021_BASE +1: + lwi $r1, [$r0+FTSDMC021_CR2] + bnez $r1, 1b +.endm + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +.globl lowlevel_init +lowlevel_init: + move $r10, $lp + + led 0x0 + jal mem_init + + led 0x10 + jal remap + +#if (defined(NDS32_EXT_FPU_DP) || defined(NDS32_EXT_FPU_SP)) + led 0x1f + jal enable_fpu +#endif + + led 0x20 + ret $r10 + +mem_init: + move $r11, $lp + + /* + * mem_init: + * There are 2 bank connected to FTSMC020 on AG101 + * BANK0: FLASH/ROM (SW5, J16), BANK1: OnBoard SDRAM. + * we need to set onboard SDRAM before remap and relocation. + */ + led 0x01 + + /* + * for Orca and Emerald + * disable write protection and reset bank size + */ + li $r0, SMC_BANK0_CR_A + lwi $r1, [$r0+#0x00] + ori $r1, $r1, 0x8f0 + xori $r1, $r1, 0x8f0 + /* + * check board + */ + li $r3, CONFIG_FTPMU010_BASE + BOARD_ID_REG + lwi $r3, [$r3] + li $r4, BOARD_ID_FAMILY_MASK + and $r3, $r3, $r4 + li $r4, BOARD_ID_FAMILY_K7 + xor $r4, $r3, $r4 + beqz $r4, use_flash_16bit_boot + /* + * 32-bit mode + */ +use_flash_32bit_boot: + ori $r1, $r1, 0x50 + li $r2, 0x00151151 + j sdram_b0_cr + /* + * 16-bit mode + */ +use_flash_16bit_boot: + ori $r1, $r1, 0x60 + li $r2, 0x00153153 + /* + * SRAM bank0 config + */ +sdram_b0_cr: + swi $r1, [$r0+#0x00] + swi $r2, [$r0+#0x04] + + /* + * config AHB Controller + */ + led 0x02 + + /* + * config PMU controller + */ + /* ftpmu010_dlldis_disable, must do it in lowleve_init */ + led 0x03 + setbf32 PMU_PDLLCR0_A, FTPMU010_PDLLCR0_DLLDIS ! 0x00010000 + + /* + * config SDRAM controller + */ + led 0x04 + write32 SDMC_TP1_A, SDMC_TP1_D ! 0x00011312 + led 0x05 + write32 SDMC_TP2_A, SDMC_TP2_D ! 0x00480180 + led 0x06 + write32 SDMC_CR1_A, SDMC_CR1_D ! 0x00002326 + + led 0x07 + write32 SDMC_CR2_A, FTSDMC021_CR2_IPREC ! 0x00000010 + wait_sdram + + led 0x08 + write32 SDMC_CR2_A, FTSDMC021_CR2_ISMR ! 0x00000004 + wait_sdram + + led 0x09 + write32 SDMC_CR2_A, FTSDMC021_CR2_IREF ! 0x00000008 + wait_sdram + + led 0x0a + 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 + */ + led 0x1a + write32 SDMC_B0_BSR_A, SDMC_B0_BSR_D ! 0x00001100 + write32 SDMC_B1_BSR_A, SDMC_B1_BSR_D ! 0x00001140 + + /* clear empty BSR registers */ + led 0x1b + li $r4, CONFIG_FTSDMC021_BASE + li $r5, 0x0 + swi $r5, [$r4 + FTSDMC021_BANK2_BSR] + swi $r5, [$r4 + FTSDMC021_BANK3_BSR] + +#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 0x11 + /* + * for Orca and Emerald + * read sdram base address automatically + */ + li $r5, AHBC_BSR6_A + lwi $r8, [$r5] + li $r4, 0xfff00000 + and $r4, $r4, $r8 + + + 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 0x1c + write32 SDMC_B0_BSR_A, 0x00001000 + write32 SDMC_B1_BSR_A, 0x00001040 + setbf15 AHBC_CR_A, FTAHBC020S_CR_REMAP ! 0x1 + + /* + * for Orca and Emerald + * extend sdram size from 256MB to 2GB + */ + li $r5, AHBC_BSR6_A + lwi $r6, [$r5] + li $r4, 0xfff0ffff + and $r6 ,$r4 , $r6 + li $r4, 0x000b0000 + or $r6, $r4, $r6 + swi $r6, [$r5] + + /* + * for Orca and Emerald + * extend rom base from 256MB to 2GB + */ + li $r4, AHBC_BSR4_A + lwi $r5, [$r4] + li $r6, 0xffffff + and $r5, $r5, $r6 + li $r6, 0x80000000 + or $r5, $r5, $r6 + swi $r5, [$r4] +#endif /* #ifdef CONFIG_MEM_REMAP */ + move $lp, $r11 +2: + ret + + /* + * enable_fpu: + * Some of Andes CPU version support FPU coprocessor, if so, + * and toolchain support FPU instruction set, we should enable it. + */ +#if (defined(NDS32_EXT_FPU_DP) || defined(NDS32_EXT_FPU_SP)) +enable_fpu: + mfsr $r0, $CPU_VER /* enable FPU if it exists */ + srli $r0, $r0, 3 + andi $r0, $r0, 1 + beqz $r0, 1f /* skip if no COP */ + mfsr $r0, $FUCOP_EXIST + srli $r0, $r0, 31 + beqz $r0, 1f /* skip if no FPU */ + mfsr $r0, $FUCOP_CTL + ori $r0, $r0, 1 + mtsr $r0, $FUCOP_CTL +1: + ret +#endif + +.globl show_led +show_led: + li $r8, (CONFIG_DEBUG_LED) + swi $r7, [$r8] + ret +#endif /* #ifndef CONFIG_SKIP_LOWLEVEL_INIT */ diff --git a/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/timer.c b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/timer.c new file mode 100644 index 000000000..758b35411 --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/timer.c @@ -0,0 +1,191 @@ +/* + * (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> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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 / 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) +{ + 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 / 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) +{ + 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/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/watchdog.S b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/watchdog.S new file mode 100644 index 000000000..8442241d7 --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag101/watchdog.S @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2011 Andes Technology Corporation + * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/arch-ag101/ag101.h> +#include <linux/linkage.h> + +.text + +#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG +ENTRY(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 + +ENDPROC(turnoff_watchdog) +#endif diff --git a/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/Makefile b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/Makefile new file mode 100644 index 000000000..c21ce0282 --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/Makefile @@ -0,0 +1,21 @@ +# +# (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> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := cpu.o timer.o + +ifndef CONFIG_SKIP_LOWLEVEL_INIT +obj-y += lowlevel_init.o +endif + +ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG +obj-y += watchdog.o +endif diff --git a/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/cpu.c b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/cpu.c new file mode 100644 index 000000000..2ee45d21c --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/cpu.c @@ -0,0 +1,67 @@ +/* + * (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> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* 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*/ +} diff --git a/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/lowlevel_init.S b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/lowlevel_init.S new file mode 100644 index 000000000..238410dde --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/lowlevel_init.S @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2011 Andes Technology Corporation + * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +.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 + +#if (defined(NDS32_EXT_FPU_DP) || defined(NDS32_EXT_FPU_SP)) + led 0x2f + jal enable_fpu +#endif + + 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 + + /* + * enable_fpu: + * Some of Andes CPU version support FPU coprocessor, if so, + * and toolchain support FPU instruction set, we should enable it. + */ +#if (defined(NDS32_EXT_FPU_DP) || defined(NDS32_EXT_FPU_SP)) +enable_fpu: + mfsr $r0, $CPU_VER /* enable FPU if it exists */ + srli $r0, $r0, 3 + andi $r0, $r0, 1 + beqz $r0, 1f /* skip if no COP */ + mfsr $r0, $FUCOP_EXIST + srli $r0, $r0, 31 + beqz $r0, 1f /* skip if no FPU */ + mfsr $r0, $FUCOP_CTL + ori $r0, $r0, 1 + mtsr $r0, $FUCOP_CTL +1: + ret +#endif + +.globl show_led +show_led: + li $r8, (CONFIG_DEBUG_LED) + swi $r7, [$r8] + ret +#endif /* #ifndef CONFIG_SKIP_LOWLEVEL_INIT */ diff --git a/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/timer.c b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/timer.c new file mode 100644 index 000000000..758b35411 --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/timer.c @@ -0,0 +1,191 @@ +/* + * (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> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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 / 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) +{ + 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 / 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) +{ + 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/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/watchdog.S b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/watchdog.S new file mode 100644 index 000000000..8f450af13 --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/ag102/watchdog.S @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2011 Andes Technology Corporation + * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/arch-ag102/ag102.h> +#include <linux/linkage.h> + +.text + +#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG +ENTRY(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 + +ENDPROC(turnoff_watchdog) +#endif diff --git a/qemu/roms/u-boot/arch/nds32/cpu/n1213/start.S b/qemu/roms/u-boot/arch/nds32/cpu/n1213/start.S new file mode 100644 index 000000000..34db79dd5 --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/start.S @@ -0,0 +1,529 @@ +/* + * Andesboot - Startup Code for Whitiger core + * + * Copyright (C) 2006 Andes Technology Corporation + * Copyright (C) 2006 Shawn Lin <nobuhiro@andestech.com> + * Copyright (C) 2011 Macpaul Lin <macpaul@andestech.com> + * Greentime Hu <greentime@andestech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm-offsets.h> +#include <config.h> +#include <common.h> +#include <asm/macro.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 $IPSW +#define EIT_IVB $ir3 ! intr vector base address +#define EIT_EVA $ir4 ! MMU related Exception VA reg +#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 ! I-cache/memory config reg +#define CR_DCAC_MEM $cr2 ! D-cache/memory config reg +#define MR_CAC_CTL $mr8 + +.globl _start + +_start: j reset + j tlb_fill + j tlb_not_present + j tlb_misc + j tlb_vlpt_miss + j machine_error + j debug + j general_exception + j syscall + j internal_interrupt ! H0I + j internal_interrupt ! H1I + j internal_interrupt ! H2I + j internal_interrupt ! H3I + j internal_interrupt ! H4I + j internal_interrupt ! H5I + j software_interrupt ! S0I + + .balign 16 + +/* + * Andesboot Startup Code (reset vector) + * + * 1. bootstrap + * 1.1 reset - start of u-boot + * 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 (board_init_r) + */ + +/* Note: TEXT_BASE is defined by the (board-dependent) linker script */ +.globl _TEXT_BASE +_TEXT_BASE: + .word CONFIG_SYS_TEXT_BASE + +/* + * These are defined in the board-specific linker script. + * Subtracting _start from them lets the linker put their + * relative position in the executable instead of leaving + * them null. + */ +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * The bootstrap code of nds32 core + */ + +reset: +set_ivb: + li $r0, 0x0 + + /* turn on BTB */ + mtsr $r0, $misc_ctl + /* set IVIC, vector size: 4 bytes, base: 0x0 */ + mtsr $r0, $ivb + +load_lli: +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + jal load_lowlevel_init + jral $p0 +#endif + +/* + * Set the N1213 (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 + +/* + * Set stackpointer in internal RAM to call board_init_f + * $sp must be 8-byte alignment for ABI compliance. + */ +call_board_init_f: + li $sp, CONFIG_SYS_INIT_SP_ADDR + li $r0, 0x00000000 + +#ifdef __PIC__ +#ifdef __NDS32_N1213_43U1H__ +/* __NDS32_N1213_43U1H__ implies NDS32 V0 ISA */ + la $r15, board_init_f ! store function address into $r15 +#endif +#endif + j board_init_f ! jump to board_init_f() in lib/board.c + +/* + * void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + */ +.globl relocate_code +relocate_code: + move $r4, $r0 /* save addr_sp */ + move $r5, $r1 /* save addr of gd */ + move $r6, $r2 /* save addr of destination */ + +/* Set up the stack */ +stack_setup: + move $sp, $r4 + + la $r0, _start + + beq $r0, $r6, clear_bss /* skip relocation */ + + move $r1, $r6 /* r1 <- scratch for copy_loop */ + la $r3, __bss_start + sub $r3, $r3, $r0 /* r3 <- __bss_start_ofs */ + add $r2, $r0, $r3 /* r2 <- source end address */ + +copy_loop: + lwi.p $r7, [$r0], #4 + swi.p $r7, [$r1], #4 + blt $r0, $r2, copy_loop + +/* + * fix relocations related issues + */ +fix_relocations: + l.w $r0, _TEXT_BASE /* r0 <- Text base */ + sub $r9, $r6, $r0 /* r9 <- relocation offset */ + +fix_got: +/* + * Now we want to update GOT. + * + * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object + * generated by GNU ld. Skip these reserved entries from relocation. + */ + la $r2, __got_start /* r2 <- rel __got_start in FLASH */ + add $r2, $r2, $r9 /* r2 <- rel __got_start in RAM */ + la $r3, __got_end /* r3 <- rel __got_end in FLASH */ + add $r3, $r3, $r9 /* r3 <- rel __got_end in RAM */ + addi $r2, $r2, #8 /* skipping first two entries */ +fix_got_loop: + lwi $r0, [$r2] /* r0 <- location in FLASH to fix up */ + add $r0, $r0, $r9 /* r0 <- location fix up to RAM */ + swi.p $r0, [$r2], #4 /* r0 <- store fix into .got in RAM */ + blt $r2, $r3, fix_got_loop + +clear_bss: + la $r0, __bss_start /* r0 <- rel __bss_start in FLASH */ + add $r0, $r0, $r9 /* r0 <- rel __bss_start in FLASH */ + la $r1, __bss_end /* r1 <- rel __bss_end in RAM */ + add $r1, $r1, $r9 /* r0 <- rel __bss_end in RAM */ + li $r2, 0x00000000 /* clear */ + +clbss_l: + sw $r2, [$r0] /* clear loop... */ + addi $r0, $r0, #4 + bne $r0, $r1, clbss_l + +/* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ +call_board_init_r: + la $r0, board_init_r + move $lp, $r0 /* offset of board_init_r() */ + add $lp, $lp, $r9 /* real address of board_init_r() */ + /* setup parameters for board_init_r */ + move $r0, $r5 /* gd_t */ + move $r1, $r6 /* dest_addr */ + +#ifdef __PIC__ +#ifdef __NDS32_N1213_43U1H__ /* NDS32 V0 ISA */ + move $r15, $lp /* store function address into $r15 */ +#endif +#endif + + /* jump to it ... */ + jr $lp /* jump to board_init_r() */ + +/* + * 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: + + move $r0, $lp /* push ra */ + + /* 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 + + move $lp, $r0 +2: + 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: + ! read $cr1(I CAC/MEM cfg. reg.) configuration + mfsr $t0, CR_ICAC_MEM + + ! Get the ISZ field + andi $p0, $t0, ICAC_MEM_KBF_ISZ + + ! if $p0=0, then no I CAC existed + beqz $p0, end_flush_icache + + ! get $p0 the index of I$ block + srli $p0, $p0, 6 + + ! $t1= bit width of I cache line size(ISZ) + addi $t1, $p0, 2 + + 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: + ! read $cr2(D CAC/MEM cfg. reg.) configuration + mfsr $t0, CR_DCAC_MEM + + ! Get the DSZ field + andi $p0, $t0, DCAC_MEM_KBF_DSZ + + ! if $p0=0, then no D CAC existed + beqz $p0, end_flush_dcache + + ! get $p0 the index of D$ block + srli $p0, $p0, 6 + + ! $t1= bit width of D cache line size(DSZ) + addi $t1, $p0, 2 + + 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 INTR_PC + push $r28 + mfsr $r28, EIT_OVL_INTR_PC ! $ir11 Overflowed INTR_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 ! 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 +machine_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 +syscall: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 8 ! Determine interruption type + bal do_interruption + + .align 5 +internal_interrupt: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 9 ! Determine interruption type + bal do_interruption + + .align 5 +software_interrupt: + SAVE_ALL + move $r0, $sp ! To get the kernel stack + li $r1, 10 ! 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/qemu/roms/u-boot/arch/nds32/cpu/n1213/u-boot.lds b/qemu/roms/u-boot/arch/nds32/cpu/n1213/u-boot.lds new file mode 100644 index 000000000..b88d7426b --- /dev/null +++ b/qemu/roms/u-boot/arch/nds32/cpu/n1213/u-boot.lds @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright (C) 2011 Andes Technology Corporation + * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com> + * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf32-nds32", "elf32-nds32", "elf32-nds32") +OUTPUT_ARCH(nds32) +ENTRY(_start) +SECTIONS +{ + . = ALIGN(4); + .text : + { + arch/nds32/cpu/n1213/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { *(.data*) } + + . = ALIGN(4); + + .got : { + __got_start = .; + *(.got.plt) *(.got) + __got_end = .; + } + + . = .; + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + + _end = .; + + .bss : { + __bss_start = .; + *(.bss) + . = ALIGN(4); + __bss_end = .; + } + +} |