137e5708aSMacpaul Lin/* 237e5708aSMacpaul Lin * Andesboot - Startup Code for Whitiger core 337e5708aSMacpaul Lin * 437e5708aSMacpaul Lin * Copyright (C) 2006 Andes Technology Corporation 537e5708aSMacpaul Lin * Copyright (C) 2006 Shawn Lin <nobuhiro@andestech.com> 637e5708aSMacpaul Lin * Copyright (C) 2011 Macpaul Lin <macpaul@andestech.com> 737e5708aSMacpaul Lin * Greentime Hu <greentime@andestech.com> 837e5708aSMacpaul Lin * 91a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 1037e5708aSMacpaul Lin */ 1137e5708aSMacpaul Lin 12d607f6faSrick.pic 13d607f6faSrick 1437e5708aSMacpaul Lin#include <asm-offsets.h> 1537e5708aSMacpaul Lin#include <config.h> 1637e5708aSMacpaul Lin#include <common.h> 1737e5708aSMacpaul Lin#include <asm/macro.h> 1837e5708aSMacpaul Lin 1937e5708aSMacpaul Lin/* 2037e5708aSMacpaul Lin * Jump vector table for EVIC mode 2137e5708aSMacpaul Lin */ 2237e5708aSMacpaul Lin#define ENA_DCAC 2UL 2337e5708aSMacpaul Lin#define DIS_DCAC ~ENA_DCAC 2437e5708aSMacpaul Lin#define ICAC_MEM_KBF_ISET (0x07) ! I Cache sets per way 2537e5708aSMacpaul Lin#define ICAC_MEM_KBF_IWAY (0x07<<3) ! I cache ways 2637e5708aSMacpaul Lin#define ICAC_MEM_KBF_ISZ (0x07<<6) ! I cache line size 2737e5708aSMacpaul Lin#define DCAC_MEM_KBF_DSET (0x07) ! D Cache sets per way 2837e5708aSMacpaul Lin#define DCAC_MEM_KBF_DWAY (0x07<<3) ! D cache ways 2937e5708aSMacpaul Lin#define DCAC_MEM_KBF_DSZ (0x07<<6) ! D cache line size 3037e5708aSMacpaul Lin 3137e5708aSMacpaul Lin#define PSW $ir0 3237e5708aSMacpaul Lin#define EIT_INTR_PSW $ir1 ! interruption $PSW 3337e5708aSMacpaul Lin#define EIT_PREV_IPSW $ir2 ! previous $IPSW 3437e5708aSMacpaul Lin#define EIT_IVB $ir3 ! intr vector base address 3537e5708aSMacpaul Lin#define EIT_EVA $ir4 ! MMU related Exception VA reg 3637e5708aSMacpaul Lin#define EIT_PREV_EVA $ir5 ! previous $eva 3737e5708aSMacpaul Lin#define EIT_ITYPE $ir6 ! interruption type 3837e5708aSMacpaul Lin#define EIT_PREV_ITYPE $ir7 ! prev intr type 3937e5708aSMacpaul Lin#define EIT_MACH_ERR $ir8 ! machine error log 4037e5708aSMacpaul Lin#define EIT_INTR_PC $ir9 ! Interruption PC 4137e5708aSMacpaul Lin#define EIT_PREV_IPC $ir10 ! previous $IPC 4237e5708aSMacpaul Lin#define EIT_OVL_INTR_PC $ir11 ! overflow interruption PC 4337e5708aSMacpaul Lin#define EIT_PREV_P0 $ir12 ! prev $P0 4437e5708aSMacpaul Lin#define EIT_PREV_P1 $ir13 ! prev $p1 4537e5708aSMacpaul Lin#define CR_ICAC_MEM $cr1 ! I-cache/memory config reg 4637e5708aSMacpaul Lin#define CR_DCAC_MEM $cr2 ! D-cache/memory config reg 4737e5708aSMacpaul Lin#define MR_CAC_CTL $mr8 4837e5708aSMacpaul Lin 4937e5708aSMacpaul Lin.globl _start 5037e5708aSMacpaul Lin 5137e5708aSMacpaul Lin_start: j reset 5237e5708aSMacpaul Lin j tlb_fill 5337e5708aSMacpaul Lin j tlb_not_present 5437e5708aSMacpaul Lin j tlb_misc 5537e5708aSMacpaul Lin j tlb_vlpt_miss 561a05bb3cSMacpaul Lin j machine_error 5737e5708aSMacpaul Lin j debug 5837e5708aSMacpaul Lin j general_exception 591a05bb3cSMacpaul Lin j syscall 6037e5708aSMacpaul Lin j internal_interrupt ! H0I 6137e5708aSMacpaul Lin j internal_interrupt ! H1I 6237e5708aSMacpaul Lin j internal_interrupt ! H2I 6337e5708aSMacpaul Lin j internal_interrupt ! H3I 6437e5708aSMacpaul Lin j internal_interrupt ! H4I 6537e5708aSMacpaul Lin j internal_interrupt ! H5I 661a05bb3cSMacpaul Lin j software_interrupt ! S0I 6737e5708aSMacpaul Lin 6837e5708aSMacpaul Lin .balign 16 6937e5708aSMacpaul Lin 7037e5708aSMacpaul Lin/* 7137e5708aSMacpaul Lin * Andesboot Startup Code (reset vector) 7237e5708aSMacpaul Lin * 7337e5708aSMacpaul Lin * 1. bootstrap 7437e5708aSMacpaul Lin * 1.1 reset - start of u-boot 7537e5708aSMacpaul Lin * 1.2 to superuser mode - as is when reset 7637e5708aSMacpaul Lin * 1.4 Do lowlevel_init 7737e5708aSMacpaul Lin * - (this will jump out to lowlevel_init.S in SoC) 7837e5708aSMacpaul Lin * - (lowlevel_init) 7937e5708aSMacpaul Lin * 1.3 Turn off watchdog timer 8037e5708aSMacpaul Lin * - (this will jump out to watchdog.S in SoC) 8137e5708aSMacpaul Lin * - (turnoff_watchdog) 8237e5708aSMacpaul Lin * 2. Do critical init when reboot (not from mem) 8337e5708aSMacpaul Lin * 3. Relocate andesboot to ram 8437e5708aSMacpaul Lin * 4. Setup stack 8537e5708aSMacpaul Lin * 5. Jump to second stage (board_init_r) 8637e5708aSMacpaul Lin */ 8737e5708aSMacpaul Lin 8837e5708aSMacpaul Lin/* Note: TEXT_BASE is defined by the (board-dependent) linker script */ 8937e5708aSMacpaul Lin.globl _TEXT_BASE 9037e5708aSMacpaul Lin_TEXT_BASE: 9137e5708aSMacpaul Lin .word CONFIG_SYS_TEXT_BASE 9237e5708aSMacpaul Lin 9337e5708aSMacpaul Lin/* IRQ stack memory (calculated at run-time) + 8 bytes */ 9437e5708aSMacpaul Lin.globl IRQ_STACK_START_IN 9537e5708aSMacpaul LinIRQ_STACK_START_IN: 9637e5708aSMacpaul Lin .word 0x0badc0de 9737e5708aSMacpaul Lin 9837e5708aSMacpaul Lin/* 9937e5708aSMacpaul Lin * The bootstrap code of nds32 core 10037e5708aSMacpaul Lin */ 10137e5708aSMacpaul Lin 10237e5708aSMacpaul Linreset: 103d607f6faSrick 104d607f6faSrick/* 105d607f6faSrick * gp = ~0 for burn mode 106d607f6faSrick * = ~load_address for load mode 107d607f6faSrick */ 108d607f6faSrickreset_gp: 109d607f6faSrick .relax_hint 0 110d607f6faSrick sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_-8) 111d607f6faSrick .relax_hint 0 112d607f6faSrick ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_-4) 113d607f6faSrick add5.pc $gp 114d607f6faSrick 11537e5708aSMacpaul Linset_ivb: 11637e5708aSMacpaul Lin li $r0, 0x0 11737e5708aSMacpaul Lin /* turn on BTB */ 11837e5708aSMacpaul Lin mtsr $r0, $misc_ctl 11937e5708aSMacpaul Lin /* set IVIC, vector size: 4 bytes, base: 0x0 */ 12037e5708aSMacpaul Lin mtsr $r0, $ivb 121*b841b6e9Srick/* 122*b841b6e9Srick * MMU_CTL NTC0 Cacheable/Write-Back 123*b841b6e9Srick */ 124*b841b6e9Srick li $r0, ~0x3 125*b841b6e9Srick mfsr $r1, $mr8 126*b841b6e9Srick and $r1, $r1, $r0 127*b841b6e9Srick mtsr $r1, $mr8 128*b841b6e9Srick#if (!defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF)) 129*b841b6e9Srick li $r0, 0x4 130*b841b6e9Srick mfsr $r1, $mr0 131*b841b6e9Srick or $r1, $r1, $r0 132*b841b6e9Srick mtsr $r1, $mr0 133*b841b6e9Srick#endif 134*b841b6e9Srick 135*b841b6e9Srick#if !defined(CONFIG_SYS_ICACHE_OFF) 136*b841b6e9Srick li $r0, 0x1 137*b841b6e9Srick mfsr $r1, $mr8 138*b841b6e9Srick or $r1, $r1, $r0 139*b841b6e9Srick mtsr $r1, $mr8 140*b841b6e9Srick#endif 141*b841b6e9Srick 142*b841b6e9Srick#if !defined(CONFIG_SYS_DCACHE_OFF) 143*b841b6e9Srick li $r0, 0x2 144*b841b6e9Srick mfsr $r1, $mr8 145*b841b6e9Srick or $r1, $r1, $r0 146*b841b6e9Srick mtsr $r1, $mr8 147*b841b6e9Srick#endif 148*b841b6e9Srick 149*b841b6e9Srick jal mem_init 15037e5708aSMacpaul Lin 15137e5708aSMacpaul Lin#ifndef CONFIG_SKIP_LOWLEVEL_INIT 152d607f6faSrick jal lowlevel_init 153d607f6faSrick/* 154d607f6faSrick * gp = ~VMA for burn mode 155d607f6faSrick * = ~load_address for load mode 156d607f6faSrick */ 157d607f6faSrickupdate_gp: 158d607f6faSrick .relax_hint 0 159d607f6faSrick sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_-8) 160d607f6faSrick .relax_hint 0 161d607f6faSrick ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_-4) 162d607f6faSrick add5.pc $gp 16337e5708aSMacpaul Lin#endif 16437e5708aSMacpaul Lin/* 165d607f6faSrick * do critical initializations first (shall be in short time) 166d607f6faSrick * do self_relocation ASAP. 167d607f6faSrick */ 168d607f6faSrick 169d607f6faSrick/* 17037e5708aSMacpaul Lin * Set the N1213 (Whitiger) core to superuser mode 17137e5708aSMacpaul Lin * According to spec, it is already when reset 17237e5708aSMacpaul Lin */ 17337e5708aSMacpaul Lin#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG 174d607f6faSrick jal turnoff_watchdog 17537e5708aSMacpaul Lin#endif 17637e5708aSMacpaul Lin 17737e5708aSMacpaul Lin/* 17837e5708aSMacpaul Lin * Do CPU critical regs init only at reboot, 17937e5708aSMacpaul Lin * not when booting from ram 18037e5708aSMacpaul Lin */ 18137e5708aSMacpaul Lin#ifdef CONFIG_INIT_CRITICAL 182d607f6faSrick jal cpu_init_crit ! Do CPU critical regs init 18337e5708aSMacpaul Lin#endif 18437e5708aSMacpaul Lin 18537e5708aSMacpaul Lin/* 18637e5708aSMacpaul Lin * Set stackpointer in internal RAM to call board_init_f 18737e5708aSMacpaul Lin * $sp must be 8-byte alignment for ABI compliance. 18837e5708aSMacpaul Lin */ 18937e5708aSMacpaul Lincall_board_init_f: 19037e5708aSMacpaul Lin li $sp, CONFIG_SYS_INIT_SP_ADDR 19186132af7Srick move $r0, $sp 19286132af7Srick bal board_init_f_alloc_reserve 19386132af7Srick move $sp, $r0 19486132af7Srick bal board_init_f_init_reserve 19586132af7Srick#ifdef CONFIG_DEBUG_UART 19686132af7Srick bal debug_uart_init 19786132af7Srick#endif 19837e5708aSMacpaul Lin li $r0, 0x00000000 19937e5708aSMacpaul Lin#ifdef __PIC__ 20037e5708aSMacpaul Lin#ifdef __NDS32_N1213_43U1H__ 20137e5708aSMacpaul Lin/* __NDS32_N1213_43U1H__ implies NDS32 V0 ISA */ 20237e5708aSMacpaul Lin la $r15, board_init_f ! store function address into $r15 20337e5708aSMacpaul Lin#endif 20437e5708aSMacpaul Lin#endif 20537e5708aSMacpaul Lin j board_init_f ! jump to board_init_f() in lib/board.c 20637e5708aSMacpaul Lin 20737e5708aSMacpaul Lin/* 20837e5708aSMacpaul Lin * void relocate_code (addr_sp, gd, addr_moni) 20937e5708aSMacpaul Lin * 21037e5708aSMacpaul Lin * This "function" does not return, instead it continues in RAM 21137e5708aSMacpaul Lin * after relocating the monitor code. 21237e5708aSMacpaul Lin * 21337e5708aSMacpaul Lin */ 214d607f6faSrick 215d607f6faSrick/* 216d607f6faSrick * gp = ~RAM_SIZE - TEXT_SIZE for burn/load mode 217d607f6faSrick */ 218d607f6faSrick 21937e5708aSMacpaul Lin.globl relocate_code 22037e5708aSMacpaul Linrelocate_code: 22137e5708aSMacpaul Lin move $r4, $r0 /* save addr_sp */ 22237e5708aSMacpaul Lin move $r5, $r1 /* save addr of gd */ 22337e5708aSMacpaul Lin move $r6, $r2 /* save addr of destination */ 22437e5708aSMacpaul Lin 22537e5708aSMacpaul Lin/* Set up the stack */ 22637e5708aSMacpaul Linstack_setup: 22737e5708aSMacpaul Lin move $sp, $r4 22837e5708aSMacpaul Lin 229d607f6faSrick la $r0, _start@GOTOFF 23037e5708aSMacpaul Lin beq $r0, $r6, clear_bss /* skip relocation */ 23137e5708aSMacpaul Lin 232d607f6faSrick la $r1, _end@GOTOFF 233d607f6faSrick move $r2, $r6 /* r2 <- scratch for copy_loop */ 23437e5708aSMacpaul Lincopy_loop: 235*b841b6e9Srick lmw.bim $r11, [$r0], $r18 236*b841b6e9Srick smw.bim $r11, [$r2], $r18 237d607f6faSrick blt $r0, $r1, copy_loop 23837e5708aSMacpaul Lin/* 23937e5708aSMacpaul Lin * fix relocations related issues 24037e5708aSMacpaul Lin */ 24137e5708aSMacpaul Linfix_relocations: 242d607f6faSrick l.w $r0, _TEXT_BASE@GOTOFF /* r0 <- Text base */ 24337e5708aSMacpaul Lin sub $r9, $r6, $r0 /* r9 <- relocation offset */ 24437e5708aSMacpaul Lin 245d607f6faSrick la $r7, __rel_dyn_start@GOTOFF 246d607f6faSrick add $r7, $r7, $r9 /* r2 <- rel __got_start in RAM */ 247d607f6faSrick la $r8, __rel_dyn_end@GOTOFF 248d607f6faSrick add $r8, $r8, $r9 /* r2 <- rel __got_start in RAM */ 249d607f6faSrick li $r3, #0x2a /* R_NDS32_RELATIVE */ 250d607f6faSrick1: 251d607f6faSrick lmw.bim $r0, [$r7], $r2 /* r0,r1,r2 <- adr,type,addend */ 252d607f6faSrick bne $r1, $r3, 2f 253d607f6faSrick 254d607f6faSrick add $r0, $r0, $r9 255d607f6faSrick add $r2, $r2, $r9 256d607f6faSrick sw $r2, [$r0] 257d607f6faSrick2: 258d607f6faSrick blt $r7, $r8, 1b 25937e5708aSMacpaul Lin 26037e5708aSMacpaul Linclear_bss: 261d607f6faSrick la $r0, __bss_start@GOTOFF /* r0 <- rel __bss_start in FLASH */ 26237e5708aSMacpaul Lin add $r0, $r0, $r9 /* r0 <- rel __bss_start in FLASH */ 263d607f6faSrick la $r1, __bss_end@GOTOFF /* r1 <- rel __bss_end in RAM */ 26437e5708aSMacpaul Lin add $r1, $r1, $r9 /* r0 <- rel __bss_end in RAM */ 26537e5708aSMacpaul Lin li $r2, 0x00000000 /* clear */ 26637e5708aSMacpaul Lin 26737e5708aSMacpaul Linclbss_l: 26837e5708aSMacpaul Lin sw $r2, [$r0] /* clear loop... */ 26937e5708aSMacpaul Lin addi $r0, $r0, #4 27037e5708aSMacpaul Lin bne $r0, $r1, clbss_l 27137e5708aSMacpaul Lin 27237e5708aSMacpaul Lin/* 27337e5708aSMacpaul Lin * We are done. Do not return, instead branch to second part of board 27437e5708aSMacpaul Lin * initialization, now running from RAM. 27537e5708aSMacpaul Lin */ 27637e5708aSMacpaul Lincall_board_init_r: 277*b841b6e9Srick bal invalidate_icache_all 278*b841b6e9Srick bal flush_dcache_all 279d607f6faSrick la $r0, board_init_r@GOTOFF 28037e5708aSMacpaul Lin move $lp, $r0 /* offset of board_init_r() */ 28137e5708aSMacpaul Lin add $lp, $lp, $r9 /* real address of board_init_r() */ 28237e5708aSMacpaul Lin /* setup parameters for board_init_r */ 28337e5708aSMacpaul Lin move $r0, $r5 /* gd_t */ 28437e5708aSMacpaul Lin move $r1, $r6 /* dest_addr */ 28537e5708aSMacpaul Lin 28637e5708aSMacpaul Lin#ifdef __PIC__ 28737e5708aSMacpaul Lin#ifdef __NDS32_N1213_43U1H__ /* NDS32 V0 ISA */ 28837e5708aSMacpaul Lin move $r15, $lp /* store function address into $r15 */ 28937e5708aSMacpaul Lin#endif 29037e5708aSMacpaul Lin#endif 29137e5708aSMacpaul Lin 29237e5708aSMacpaul Lin /* jump to it ... */ 29337e5708aSMacpaul Lin jr $lp /* jump to board_init_r() */ 29437e5708aSMacpaul Lin 29537e5708aSMacpaul Lin/* 29637e5708aSMacpaul Lin * Initialize CPU critical registers 29737e5708aSMacpaul Lin * 29837e5708aSMacpaul Lin * 1. Setup control registers 29937e5708aSMacpaul Lin * 1.1 Mask all IRQs 30037e5708aSMacpaul Lin * 1.2 Flush cache and TLB 30137e5708aSMacpaul Lin * 1.3 Disable MMU and cache 30237e5708aSMacpaul Lin * 2. Setup memory timing 30337e5708aSMacpaul Lin */ 30437e5708aSMacpaul Lin 30537e5708aSMacpaul Lincpu_init_crit: 30637e5708aSMacpaul Lin 30737e5708aSMacpaul Lin move $r0, $lp /* push ra */ 30837e5708aSMacpaul Lin 30937e5708aSMacpaul Lin /* Disable Interrupts by clear GIE in $PSW reg */ 31037e5708aSMacpaul Lin setgie.d 31137e5708aSMacpaul Lin 31237e5708aSMacpaul Lin /* Flush caches and TLB */ 31337e5708aSMacpaul Lin /* Invalidate caches */ 314d607f6faSrick jal invalidate_icac 315d607f6faSrick jal invalidate_dcac 31637e5708aSMacpaul Lin 31737e5708aSMacpaul Lin /* Flush TLB */ 31837e5708aSMacpaul Lin mfsr $p0, $MMU_CFG 31937e5708aSMacpaul Lin andi $p0, $p0, 0x3 ! MMPS 32037e5708aSMacpaul Lin li $p1, 0x2 ! TLB MMU 32137e5708aSMacpaul Lin bne $p0, $p1, 1f 32237e5708aSMacpaul Lin tlbop flushall ! Flush TLB 32337e5708aSMacpaul Lin 32437e5708aSMacpaul Lin1: 32537e5708aSMacpaul Lin ! Disable MMU, Dcache 32637e5708aSMacpaul Lin ! Whitiger is MMU disabled when reset 32737e5708aSMacpaul Lin ! Disable the D$ 32837e5708aSMacpaul Lin mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg 32937e5708aSMacpaul Lin li $p1, DIS_DCAC 33037e5708aSMacpaul Lin and $p0, $p0, $p1 ! Set DC_EN bit 33137e5708aSMacpaul Lin mtsr $p0, MR_CAC_CTL ! write back the $CACHE_CTL reg 33237e5708aSMacpaul Lin isb 33337e5708aSMacpaul Lin 33437e5708aSMacpaul Lin move $lp, $r0 33537e5708aSMacpaul Lin2: 33637e5708aSMacpaul Lin ret 33737e5708aSMacpaul Lin 33837e5708aSMacpaul Lin/* 33937e5708aSMacpaul Lin * Invalidate I$ 34037e5708aSMacpaul Lin */ 34137e5708aSMacpaul Lininvalidate_icac: 34237e5708aSMacpaul Lin ! read $cr1(I CAC/MEM cfg. reg.) configuration 34337e5708aSMacpaul Lin mfsr $t0, CR_ICAC_MEM 34437e5708aSMacpaul Lin 34537e5708aSMacpaul Lin ! Get the ISZ field 34637e5708aSMacpaul Lin andi $p0, $t0, ICAC_MEM_KBF_ISZ 34737e5708aSMacpaul Lin 34837e5708aSMacpaul Lin ! if $p0=0, then no I CAC existed 34937e5708aSMacpaul Lin beqz $p0, end_flush_icache 35037e5708aSMacpaul Lin 35137e5708aSMacpaul Lin ! get $p0 the index of I$ block 35237e5708aSMacpaul Lin srli $p0, $p0, 6 35337e5708aSMacpaul Lin 35437e5708aSMacpaul Lin ! $t1= bit width of I cache line size(ISZ) 35537e5708aSMacpaul Lin addi $t1, $p0, 2 35637e5708aSMacpaul Lin 35737e5708aSMacpaul Lin li $t4, 1 35837e5708aSMacpaul Lin sll $t5, $t4, $t1 ! get $t5 cache line size 35937e5708aSMacpaul Lin andi $p1, $t0, ICAC_MEM_KBF_ISET ! get the ISET field 36037e5708aSMacpaul Lin addi $t2, $p1, 6 ! $t2= bit width of ISET 36137e5708aSMacpaul Lin andi $p1, $t0, ICAC_MEM_KBF_IWAY ! get bitfield of Iway 36237e5708aSMacpaul Lin srli $p1, $p1, 3 36337e5708aSMacpaul Lin addi $p1, $p1, 1 ! then $p1 is I way number 36437e5708aSMacpaul Lin add $t3, $t2, $t1 ! SHIFT 36537e5708aSMacpaul Lin sll $p1, $p1, $t3 ! GET the total cache size 36637e5708aSMacpaul LinICAC_LOOP: 36737e5708aSMacpaul Lin sub $p1, $p1, $t5 36837e5708aSMacpaul Lin cctl $p1, L1I_IX_INVAL 36937e5708aSMacpaul Lin bnez $p1, ICAC_LOOP 37037e5708aSMacpaul Linend_flush_icache: 37137e5708aSMacpaul Lin ret 37237e5708aSMacpaul Lin 37337e5708aSMacpaul Lin/* 37437e5708aSMacpaul Lin * Invalidate D$ 37537e5708aSMacpaul Lin */ 37637e5708aSMacpaul Lininvalidate_dcac: 37737e5708aSMacpaul Lin ! read $cr2(D CAC/MEM cfg. reg.) configuration 37837e5708aSMacpaul Lin mfsr $t0, CR_DCAC_MEM 37937e5708aSMacpaul Lin 38037e5708aSMacpaul Lin ! Get the DSZ field 38137e5708aSMacpaul Lin andi $p0, $t0, DCAC_MEM_KBF_DSZ 38237e5708aSMacpaul Lin 38337e5708aSMacpaul Lin ! if $p0=0, then no D CAC existed 38437e5708aSMacpaul Lin beqz $p0, end_flush_dcache 38537e5708aSMacpaul Lin 38637e5708aSMacpaul Lin ! get $p0 the index of D$ block 38737e5708aSMacpaul Lin srli $p0, $p0, 6 38837e5708aSMacpaul Lin 38937e5708aSMacpaul Lin ! $t1= bit width of D cache line size(DSZ) 39037e5708aSMacpaul Lin addi $t1, $p0, 2 39137e5708aSMacpaul Lin 39237e5708aSMacpaul Lin li $t4, 1 39337e5708aSMacpaul Lin sll $t5, $t4, $t1 ! get $t5 cache line size 39437e5708aSMacpaul Lin andi $p1, $t0, DCAC_MEM_KBF_DSET ! get the DSET field 39537e5708aSMacpaul Lin addi $t2, $p1, 6 ! $t2= bit width of DSET 39637e5708aSMacpaul Lin andi $p1, $t0, DCAC_MEM_KBF_DWAY ! get bitfield of D way 39737e5708aSMacpaul Lin srli $p1, $p1, 3 39837e5708aSMacpaul Lin addi $p1, $p1, 1 ! then $p1 is D way number 39937e5708aSMacpaul Lin add $t3, $t2, $t1 ! SHIFT 40037e5708aSMacpaul Lin sll $p1, $p1, $t3 ! GET the total cache size 40137e5708aSMacpaul LinDCAC_LOOP: 40237e5708aSMacpaul Lin sub $p1, $p1, $t5 40337e5708aSMacpaul Lin cctl $p1, L1D_IX_INVAL 40437e5708aSMacpaul Lin bnez $p1, DCAC_LOOP 40537e5708aSMacpaul Linend_flush_dcache: 40637e5708aSMacpaul Lin ret 40737e5708aSMacpaul Lin 40837e5708aSMacpaul Lin/* 40937e5708aSMacpaul Lin * Interrupt handling 41037e5708aSMacpaul Lin */ 41137e5708aSMacpaul Lin 41237e5708aSMacpaul Lin/* 41337e5708aSMacpaul Lin * exception handlers 41437e5708aSMacpaul Lin */ 41537e5708aSMacpaul Lin .align 5 41637e5708aSMacpaul Lin 41737e5708aSMacpaul Lin.macro SAVE_ALL 41837e5708aSMacpaul Lin ! FIXME: Other way to get PC? 41937e5708aSMacpaul Lin ! FIXME: Update according to the newest spec!! 42037e5708aSMacpaul Lin1: 421b19cc6bfSrick li $r28, 1 42237e5708aSMacpaul Lin push $r28 42337e5708aSMacpaul Lin mfsr $r28, PSW ! $PSW 42437e5708aSMacpaul Lin push $r28 42537e5708aSMacpaul Lin mfsr $r28, EIT_EVA ! $ir1 $EVA 42637e5708aSMacpaul Lin push $r28 42737e5708aSMacpaul Lin mfsr $r28, EIT_ITYPE ! $ir2 $ITYPE 42837e5708aSMacpaul Lin push $r28 42937e5708aSMacpaul Lin mfsr $r28, EIT_MACH_ERR ! $ir3 Mach Error 43037e5708aSMacpaul Lin push $r28 43137e5708aSMacpaul Lin mfsr $r28, EIT_INTR_PSW ! $ir5 $IPSW 43237e5708aSMacpaul Lin push $r28 43337e5708aSMacpaul Lin mfsr $r28, EIT_PREV_IPSW ! $ir6 prev $IPSW 43437e5708aSMacpaul Lin push $r28 43537e5708aSMacpaul Lin mfsr $r28, EIT_PREV_EVA ! $ir7 prev $EVA 43637e5708aSMacpaul Lin push $r28 43737e5708aSMacpaul Lin mfsr $r28, EIT_PREV_ITYPE ! $ir8 prev $ITYPE 43837e5708aSMacpaul Lin push $r28 43937e5708aSMacpaul Lin mfsr $r28, EIT_INTR_PC ! $ir9 Interruption PC 44037e5708aSMacpaul Lin push $r28 44137e5708aSMacpaul Lin mfsr $r28, EIT_PREV_IPC ! $ir10 prev INTR_PC 44237e5708aSMacpaul Lin push $r28 44337e5708aSMacpaul Lin mfsr $r28, EIT_OVL_INTR_PC ! $ir11 Overflowed INTR_PC 44437e5708aSMacpaul Lin push $r28 44537e5708aSMacpaul Lin mfusr $r28, $d1.lo 44637e5708aSMacpaul Lin push $r28 44737e5708aSMacpaul Lin mfusr $r28, $d1.hi 44837e5708aSMacpaul Lin push $r28 44937e5708aSMacpaul Lin mfusr $r28, $d0.lo 45037e5708aSMacpaul Lin push $r28 45137e5708aSMacpaul Lin mfusr $r28, $d0.hi 45237e5708aSMacpaul Lin push $r28 45337e5708aSMacpaul Lin pushm $r0, $r30 ! store $sp-$r31, ra-$r30, $gp-$r29, $r28-$fp 45437e5708aSMacpaul Lin addi $sp, $sp, -4 ! make room for implicit pt_regs parameters 45537e5708aSMacpaul Lin.endm 45637e5708aSMacpaul Lin 45737e5708aSMacpaul Lin .align 5 45837e5708aSMacpaul Lintlb_fill: 45937e5708aSMacpaul Lin SAVE_ALL 46037e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 46137e5708aSMacpaul Lin li $r1, 1 ! Determine interruption type 46237e5708aSMacpaul Lin bal do_interruption 46337e5708aSMacpaul Lin 46437e5708aSMacpaul Lin .align 5 46537e5708aSMacpaul Lintlb_not_present: 46637e5708aSMacpaul Lin SAVE_ALL 46737e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 46837e5708aSMacpaul Lin li $r1, 2 ! Determine interruption type 46937e5708aSMacpaul Lin bal do_interruption 47037e5708aSMacpaul Lin 47137e5708aSMacpaul Lin .align 5 47237e5708aSMacpaul Lintlb_misc: 47337e5708aSMacpaul Lin SAVE_ALL 47437e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 47537e5708aSMacpaul Lin li $r1, 3 ! Determine interruption type 47637e5708aSMacpaul Lin bal do_interruption 47737e5708aSMacpaul Lin 47837e5708aSMacpaul Lin .align 5 47937e5708aSMacpaul Lintlb_vlpt_miss: 48037e5708aSMacpaul Lin SAVE_ALL 48137e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 48237e5708aSMacpaul Lin li $r1, 4 ! Determine interruption type 48337e5708aSMacpaul Lin bal do_interruption 48437e5708aSMacpaul Lin 48537e5708aSMacpaul Lin .align 5 4861a05bb3cSMacpaul Linmachine_error: 48737e5708aSMacpaul Lin SAVE_ALL 48837e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 48937e5708aSMacpaul Lin li $r1, 5 ! Determine interruption type 49037e5708aSMacpaul Lin bal do_interruption 49137e5708aSMacpaul Lin 49237e5708aSMacpaul Lin .align 5 49337e5708aSMacpaul Lindebug: 49437e5708aSMacpaul Lin SAVE_ALL 49537e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 49637e5708aSMacpaul Lin li $r1, 6 ! Determine interruption type 49737e5708aSMacpaul Lin bal do_interruption 49837e5708aSMacpaul Lin 49937e5708aSMacpaul Lin .align 5 50037e5708aSMacpaul Lingeneral_exception: 50137e5708aSMacpaul Lin SAVE_ALL 50237e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 50337e5708aSMacpaul Lin li $r1, 7 ! Determine interruption type 50437e5708aSMacpaul Lin bal do_interruption 50537e5708aSMacpaul Lin 50637e5708aSMacpaul Lin .align 5 5071a05bb3cSMacpaul Linsyscall: 50837e5708aSMacpaul Lin SAVE_ALL 50937e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 51037e5708aSMacpaul Lin li $r1, 8 ! Determine interruption type 51137e5708aSMacpaul Lin bal do_interruption 51237e5708aSMacpaul Lin 51337e5708aSMacpaul Lin .align 5 5141a05bb3cSMacpaul Lininternal_interrupt: 5151a05bb3cSMacpaul Lin SAVE_ALL 5161a05bb3cSMacpaul Lin move $r0, $sp ! To get the kernel stack 5171a05bb3cSMacpaul Lin li $r1, 9 ! Determine interruption type 5181a05bb3cSMacpaul Lin bal do_interruption 5191a05bb3cSMacpaul Lin 5201a05bb3cSMacpaul Lin .align 5 5211a05bb3cSMacpaul Linsoftware_interrupt: 5221a05bb3cSMacpaul Lin SAVE_ALL 5231a05bb3cSMacpaul Lin move $r0, $sp ! To get the kernel stack 5241a05bb3cSMacpaul Lin li $r1, 10 ! Determine interruption type 5251a05bb3cSMacpaul Lin bal do_interruption 5261a05bb3cSMacpaul Lin 5271a05bb3cSMacpaul Lin .align 5 52837e5708aSMacpaul Lin 52937e5708aSMacpaul Lin/* 53037e5708aSMacpaul Lin * void reset_cpu(ulong addr); 53137e5708aSMacpaul Lin * $r0: input address to jump to 53237e5708aSMacpaul Lin */ 53337e5708aSMacpaul Lin.globl reset_cpu 53437e5708aSMacpaul Linreset_cpu: 53537e5708aSMacpaul Lin/* No need to disable MMU because we never enable it */ 53637e5708aSMacpaul Lin 53737e5708aSMacpaul Lin bal invalidate_icac 53837e5708aSMacpaul Lin bal invalidate_dcac 53937e5708aSMacpaul Lin mfsr $p0, $MMU_CFG 54037e5708aSMacpaul Lin andi $p0, $p0, 0x3 ! MMPS 54137e5708aSMacpaul Lin li $p1, 0x2 ! TLB MMU 54237e5708aSMacpaul Lin bne $p0, $p1, 1f 54337e5708aSMacpaul Lin tlbop flushall ! Flush TLB 54437e5708aSMacpaul Lin1: 54537e5708aSMacpaul Lin mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg 54637e5708aSMacpaul Lin li $p1, DIS_DCAC 54737e5708aSMacpaul Lin and $p0, $p0, $p1 ! Clear the DC_EN bit 54837e5708aSMacpaul Lin mtsr $p0, MR_CAC_CTL ! Write back the $CACHE_CTL reg 54937e5708aSMacpaul Lin br $r0 ! Jump to the input address 550