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 12*d607f6faSrick.pic 13*d607f6faSrick 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/* 9437e5708aSMacpaul Lin * These are defined in the board-specific linker script. 9537e5708aSMacpaul Lin * Subtracting _start from them lets the linker put their 9637e5708aSMacpaul Lin * relative position in the executable instead of leaving 9737e5708aSMacpaul Lin * them null. 9837e5708aSMacpaul Lin */ 9937e5708aSMacpaul Lin#ifdef CONFIG_USE_IRQ 10037e5708aSMacpaul Lin/* IRQ stack memory (calculated at run-time) */ 10137e5708aSMacpaul Lin.globl IRQ_STACK_START 10237e5708aSMacpaul LinIRQ_STACK_START: 10337e5708aSMacpaul Lin .word 0x0badc0de 10437e5708aSMacpaul Lin 10537e5708aSMacpaul Lin/* IRQ stack memory (calculated at run-time) */ 10637e5708aSMacpaul Lin.globl FIQ_STACK_START 10737e5708aSMacpaul LinFIQ_STACK_START: 10837e5708aSMacpaul Lin .word 0x0badc0de 10937e5708aSMacpaul Lin#endif 11037e5708aSMacpaul Lin 11137e5708aSMacpaul Lin/* IRQ stack memory (calculated at run-time) + 8 bytes */ 11237e5708aSMacpaul Lin.globl IRQ_STACK_START_IN 11337e5708aSMacpaul LinIRQ_STACK_START_IN: 11437e5708aSMacpaul Lin .word 0x0badc0de 11537e5708aSMacpaul Lin 11637e5708aSMacpaul Lin/* 11737e5708aSMacpaul Lin * The bootstrap code of nds32 core 11837e5708aSMacpaul Lin */ 11937e5708aSMacpaul Lin 12037e5708aSMacpaul Linreset: 121*d607f6faSrick 122*d607f6faSrick/* 123*d607f6faSrick * gp = ~0 for burn mode 124*d607f6faSrick * = ~load_address for load mode 125*d607f6faSrick */ 126*d607f6faSrickreset_gp: 127*d607f6faSrick .relax_hint 0 128*d607f6faSrick sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_-8) 129*d607f6faSrick .relax_hint 0 130*d607f6faSrick ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_-4) 131*d607f6faSrick add5.pc $gp 132*d607f6faSrick 13337e5708aSMacpaul Linset_ivb: 13437e5708aSMacpaul Lin li $r0, 0x0 13537e5708aSMacpaul Lin 13637e5708aSMacpaul Lin /* turn on BTB */ 13737e5708aSMacpaul Lin mtsr $r0, $misc_ctl 13837e5708aSMacpaul Lin /* set IVIC, vector size: 4 bytes, base: 0x0 */ 13937e5708aSMacpaul Lin mtsr $r0, $ivb 14037e5708aSMacpaul Lin 14137e5708aSMacpaul Lin#ifndef CONFIG_SKIP_LOWLEVEL_INIT 142*d607f6faSrick jal lowlevel_init 143*d607f6faSrick/* 144*d607f6faSrick * gp = ~VMA for burn mode 145*d607f6faSrick * = ~load_address for load mode 146*d607f6faSrick */ 147*d607f6faSrickupdate_gp: 148*d607f6faSrick .relax_hint 0 149*d607f6faSrick sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_-8) 150*d607f6faSrick .relax_hint 0 151*d607f6faSrick ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_-4) 152*d607f6faSrick add5.pc $gp 15337e5708aSMacpaul Lin#endif 15437e5708aSMacpaul Lin 15537e5708aSMacpaul Lin/* 156*d607f6faSrick * do critical initializations first (shall be in short time) 157*d607f6faSrick * do self_relocation ASAP. 158*d607f6faSrick */ 159*d607f6faSrick 160*d607f6faSrick/* 16137e5708aSMacpaul Lin * Set the N1213 (Whitiger) core to superuser mode 16237e5708aSMacpaul Lin * According to spec, it is already when reset 16337e5708aSMacpaul Lin */ 16437e5708aSMacpaul Lin#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG 165*d607f6faSrick jal turnoff_watchdog 16637e5708aSMacpaul Lin#endif 16737e5708aSMacpaul Lin 16837e5708aSMacpaul Lin/* 16937e5708aSMacpaul Lin * Do CPU critical regs init only at reboot, 17037e5708aSMacpaul Lin * not when booting from ram 17137e5708aSMacpaul Lin */ 17237e5708aSMacpaul Lin#ifdef CONFIG_INIT_CRITICAL 173*d607f6faSrick jal cpu_init_crit ! Do CPU critical regs init 17437e5708aSMacpaul Lin#endif 17537e5708aSMacpaul Lin 17637e5708aSMacpaul Lin/* 17737e5708aSMacpaul Lin * Set stackpointer in internal RAM to call board_init_f 17837e5708aSMacpaul Lin * $sp must be 8-byte alignment for ABI compliance. 17937e5708aSMacpaul Lin */ 18037e5708aSMacpaul Lincall_board_init_f: 18137e5708aSMacpaul Lin li $sp, CONFIG_SYS_INIT_SP_ADDR 1822e88bb28SKun-Hua Huang li $r10, GD_SIZE /* get GD size */ 1832e88bb28SKun-Hua Huang sub $sp, $sp, $r10 /* GD start addr */ 1842e88bb28SKun-Hua Huang move $r10, $sp 18537e5708aSMacpaul Lin li $r0, 0x00000000 18637e5708aSMacpaul Lin 18737e5708aSMacpaul Lin#ifdef __PIC__ 18837e5708aSMacpaul Lin#ifdef __NDS32_N1213_43U1H__ 18937e5708aSMacpaul Lin/* __NDS32_N1213_43U1H__ implies NDS32 V0 ISA */ 19037e5708aSMacpaul Lin la $r15, board_init_f ! store function address into $r15 19137e5708aSMacpaul Lin#endif 19237e5708aSMacpaul Lin#endif 19337e5708aSMacpaul Lin j board_init_f ! jump to board_init_f() in lib/board.c 19437e5708aSMacpaul Lin 19537e5708aSMacpaul Lin/* 19637e5708aSMacpaul Lin * void relocate_code (addr_sp, gd, addr_moni) 19737e5708aSMacpaul Lin * 19837e5708aSMacpaul Lin * This "function" does not return, instead it continues in RAM 19937e5708aSMacpaul Lin * after relocating the monitor code. 20037e5708aSMacpaul Lin * 20137e5708aSMacpaul Lin */ 202*d607f6faSrick 203*d607f6faSrick/* 204*d607f6faSrick * gp = ~RAM_SIZE - TEXT_SIZE for burn/load mode 205*d607f6faSrick */ 206*d607f6faSrick 20737e5708aSMacpaul Lin.globl relocate_code 20837e5708aSMacpaul Linrelocate_code: 20937e5708aSMacpaul Lin move $r4, $r0 /* save addr_sp */ 21037e5708aSMacpaul Lin move $r5, $r1 /* save addr of gd */ 21137e5708aSMacpaul Lin move $r6, $r2 /* save addr of destination */ 21237e5708aSMacpaul Lin 21337e5708aSMacpaul Lin/* Set up the stack */ 21437e5708aSMacpaul Linstack_setup: 21537e5708aSMacpaul Lin move $sp, $r4 21637e5708aSMacpaul Lin 217*d607f6faSrick la $r0, _start@GOTOFF 21837e5708aSMacpaul Lin beq $r0, $r6, clear_bss /* skip relocation */ 21937e5708aSMacpaul Lin 220*d607f6faSrick la $r1, _end@GOTOFF 221*d607f6faSrick move $r2, $r6 /* r2 <- scratch for copy_loop */ 22237e5708aSMacpaul Lin 22337e5708aSMacpaul Lincopy_loop: 22437e5708aSMacpaul Lin lwi.p $r7, [$r0], #4 225*d607f6faSrick swi.p $r7, [$r2], #4 226*d607f6faSrick blt $r0, $r1, copy_loop 22737e5708aSMacpaul Lin 22837e5708aSMacpaul Lin/* 22937e5708aSMacpaul Lin * fix relocations related issues 23037e5708aSMacpaul Lin */ 23137e5708aSMacpaul Linfix_relocations: 232*d607f6faSrick l.w $r0, _TEXT_BASE@GOTOFF /* r0 <- Text base */ 23337e5708aSMacpaul Lin sub $r9, $r6, $r0 /* r9 <- relocation offset */ 23437e5708aSMacpaul Lin 235*d607f6faSrick la $r7, __rel_dyn_start@GOTOFF 236*d607f6faSrick add $r7, $r7, $r9 /* r2 <- rel __got_start in RAM */ 237*d607f6faSrick la $r8, __rel_dyn_end@GOTOFF 238*d607f6faSrick add $r8, $r8, $r9 /* r2 <- rel __got_start in RAM */ 239*d607f6faSrick li $r3, #0x2a /* R_NDS32_RELATIVE */ 240*d607f6faSrick1: 241*d607f6faSrick lmw.bim $r0, [$r7], $r2 /* r0,r1,r2 <- adr,type,addend */ 242*d607f6faSrick bne $r1, $r3, 2f 243*d607f6faSrick 244*d607f6faSrick add $r0, $r0, $r9 245*d607f6faSrick add $r2, $r2, $r9 246*d607f6faSrick sw $r2, [$r0] 247*d607f6faSrick2: 248*d607f6faSrick blt $r7, $r8, 1b 24937e5708aSMacpaul Lin 25037e5708aSMacpaul Linclear_bss: 251*d607f6faSrick la $r0, __bss_start@GOTOFF /* r0 <- rel __bss_start in FLASH */ 25237e5708aSMacpaul Lin add $r0, $r0, $r9 /* r0 <- rel __bss_start in FLASH */ 253*d607f6faSrick la $r1, __bss_end@GOTOFF /* r1 <- rel __bss_end in RAM */ 25437e5708aSMacpaul Lin add $r1, $r1, $r9 /* r0 <- rel __bss_end in RAM */ 25537e5708aSMacpaul Lin li $r2, 0x00000000 /* clear */ 25637e5708aSMacpaul Lin 25737e5708aSMacpaul Linclbss_l: 25837e5708aSMacpaul Lin sw $r2, [$r0] /* clear loop... */ 25937e5708aSMacpaul Lin addi $r0, $r0, #4 26037e5708aSMacpaul Lin bne $r0, $r1, clbss_l 26137e5708aSMacpaul Lin 26237e5708aSMacpaul Lin/* 26337e5708aSMacpaul Lin * We are done. Do not return, instead branch to second part of board 26437e5708aSMacpaul Lin * initialization, now running from RAM. 26537e5708aSMacpaul Lin */ 26637e5708aSMacpaul Lincall_board_init_r: 267*d607f6faSrick la $r0, board_init_r@GOTOFF 26837e5708aSMacpaul Lin move $lp, $r0 /* offset of board_init_r() */ 26937e5708aSMacpaul Lin add $lp, $lp, $r9 /* real address of board_init_r() */ 27037e5708aSMacpaul Lin /* setup parameters for board_init_r */ 27137e5708aSMacpaul Lin move $r0, $r5 /* gd_t */ 27237e5708aSMacpaul Lin move $r1, $r6 /* dest_addr */ 27337e5708aSMacpaul Lin 27437e5708aSMacpaul Lin#ifdef __PIC__ 27537e5708aSMacpaul Lin#ifdef __NDS32_N1213_43U1H__ /* NDS32 V0 ISA */ 27637e5708aSMacpaul Lin move $r15, $lp /* store function address into $r15 */ 27737e5708aSMacpaul Lin#endif 27837e5708aSMacpaul Lin#endif 27937e5708aSMacpaul Lin 28037e5708aSMacpaul Lin /* jump to it ... */ 28137e5708aSMacpaul Lin jr $lp /* jump to board_init_r() */ 28237e5708aSMacpaul Lin 28337e5708aSMacpaul Lin/* 28437e5708aSMacpaul Lin * Initialize CPU critical registers 28537e5708aSMacpaul Lin * 28637e5708aSMacpaul Lin * 1. Setup control registers 28737e5708aSMacpaul Lin * 1.1 Mask all IRQs 28837e5708aSMacpaul Lin * 1.2 Flush cache and TLB 28937e5708aSMacpaul Lin * 1.3 Disable MMU and cache 29037e5708aSMacpaul Lin * 2. Setup memory timing 29137e5708aSMacpaul Lin */ 29237e5708aSMacpaul Lin 29337e5708aSMacpaul Lincpu_init_crit: 29437e5708aSMacpaul Lin 29537e5708aSMacpaul Lin move $r0, $lp /* push ra */ 29637e5708aSMacpaul Lin 29737e5708aSMacpaul Lin /* Disable Interrupts by clear GIE in $PSW reg */ 29837e5708aSMacpaul Lin setgie.d 29937e5708aSMacpaul Lin 30037e5708aSMacpaul Lin /* Flush caches and TLB */ 30137e5708aSMacpaul Lin /* Invalidate caches */ 302*d607f6faSrick jal invalidate_icac 303*d607f6faSrick jal invalidate_dcac 30437e5708aSMacpaul Lin 30537e5708aSMacpaul Lin /* Flush TLB */ 30637e5708aSMacpaul Lin mfsr $p0, $MMU_CFG 30737e5708aSMacpaul Lin andi $p0, $p0, 0x3 ! MMPS 30837e5708aSMacpaul Lin li $p1, 0x2 ! TLB MMU 30937e5708aSMacpaul Lin bne $p0, $p1, 1f 31037e5708aSMacpaul Lin tlbop flushall ! Flush TLB 31137e5708aSMacpaul Lin 31237e5708aSMacpaul Lin1: 31337e5708aSMacpaul Lin ! Disable MMU, Dcache 31437e5708aSMacpaul Lin ! Whitiger is MMU disabled when reset 31537e5708aSMacpaul Lin ! Disable the D$ 31637e5708aSMacpaul Lin mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg 31737e5708aSMacpaul Lin li $p1, DIS_DCAC 31837e5708aSMacpaul Lin and $p0, $p0, $p1 ! Set DC_EN bit 31937e5708aSMacpaul Lin mtsr $p0, MR_CAC_CTL ! write back the $CACHE_CTL reg 32037e5708aSMacpaul Lin isb 32137e5708aSMacpaul Lin 32237e5708aSMacpaul Lin move $lp, $r0 32337e5708aSMacpaul Lin2: 32437e5708aSMacpaul Lin ret 32537e5708aSMacpaul Lin 32637e5708aSMacpaul Lin/* 32737e5708aSMacpaul Lin * Invalidate I$ 32837e5708aSMacpaul Lin */ 32937e5708aSMacpaul Lininvalidate_icac: 33037e5708aSMacpaul Lin ! read $cr1(I CAC/MEM cfg. reg.) configuration 33137e5708aSMacpaul Lin mfsr $t0, CR_ICAC_MEM 33237e5708aSMacpaul Lin 33337e5708aSMacpaul Lin ! Get the ISZ field 33437e5708aSMacpaul Lin andi $p0, $t0, ICAC_MEM_KBF_ISZ 33537e5708aSMacpaul Lin 33637e5708aSMacpaul Lin ! if $p0=0, then no I CAC existed 33737e5708aSMacpaul Lin beqz $p0, end_flush_icache 33837e5708aSMacpaul Lin 33937e5708aSMacpaul Lin ! get $p0 the index of I$ block 34037e5708aSMacpaul Lin srli $p0, $p0, 6 34137e5708aSMacpaul Lin 34237e5708aSMacpaul Lin ! $t1= bit width of I cache line size(ISZ) 34337e5708aSMacpaul Lin addi $t1, $p0, 2 34437e5708aSMacpaul Lin 34537e5708aSMacpaul Lin li $t4, 1 34637e5708aSMacpaul Lin sll $t5, $t4, $t1 ! get $t5 cache line size 34737e5708aSMacpaul Lin andi $p1, $t0, ICAC_MEM_KBF_ISET ! get the ISET field 34837e5708aSMacpaul Lin addi $t2, $p1, 6 ! $t2= bit width of ISET 34937e5708aSMacpaul Lin andi $p1, $t0, ICAC_MEM_KBF_IWAY ! get bitfield of Iway 35037e5708aSMacpaul Lin srli $p1, $p1, 3 35137e5708aSMacpaul Lin addi $p1, $p1, 1 ! then $p1 is I way number 35237e5708aSMacpaul Lin add $t3, $t2, $t1 ! SHIFT 35337e5708aSMacpaul Lin sll $p1, $p1, $t3 ! GET the total cache size 35437e5708aSMacpaul LinICAC_LOOP: 35537e5708aSMacpaul Lin sub $p1, $p1, $t5 35637e5708aSMacpaul Lin cctl $p1, L1I_IX_INVAL 35737e5708aSMacpaul Lin bnez $p1, ICAC_LOOP 35837e5708aSMacpaul Linend_flush_icache: 35937e5708aSMacpaul Lin ret 36037e5708aSMacpaul Lin 36137e5708aSMacpaul Lin/* 36237e5708aSMacpaul Lin * Invalidate D$ 36337e5708aSMacpaul Lin */ 36437e5708aSMacpaul Lininvalidate_dcac: 36537e5708aSMacpaul Lin ! read $cr2(D CAC/MEM cfg. reg.) configuration 36637e5708aSMacpaul Lin mfsr $t0, CR_DCAC_MEM 36737e5708aSMacpaul Lin 36837e5708aSMacpaul Lin ! Get the DSZ field 36937e5708aSMacpaul Lin andi $p0, $t0, DCAC_MEM_KBF_DSZ 37037e5708aSMacpaul Lin 37137e5708aSMacpaul Lin ! if $p0=0, then no D CAC existed 37237e5708aSMacpaul Lin beqz $p0, end_flush_dcache 37337e5708aSMacpaul Lin 37437e5708aSMacpaul Lin ! get $p0 the index of D$ block 37537e5708aSMacpaul Lin srli $p0, $p0, 6 37637e5708aSMacpaul Lin 37737e5708aSMacpaul Lin ! $t1= bit width of D cache line size(DSZ) 37837e5708aSMacpaul Lin addi $t1, $p0, 2 37937e5708aSMacpaul Lin 38037e5708aSMacpaul Lin li $t4, 1 38137e5708aSMacpaul Lin sll $t5, $t4, $t1 ! get $t5 cache line size 38237e5708aSMacpaul Lin andi $p1, $t0, DCAC_MEM_KBF_DSET ! get the DSET field 38337e5708aSMacpaul Lin addi $t2, $p1, 6 ! $t2= bit width of DSET 38437e5708aSMacpaul Lin andi $p1, $t0, DCAC_MEM_KBF_DWAY ! get bitfield of D way 38537e5708aSMacpaul Lin srli $p1, $p1, 3 38637e5708aSMacpaul Lin addi $p1, $p1, 1 ! then $p1 is D way number 38737e5708aSMacpaul Lin add $t3, $t2, $t1 ! SHIFT 38837e5708aSMacpaul Lin sll $p1, $p1, $t3 ! GET the total cache size 38937e5708aSMacpaul LinDCAC_LOOP: 39037e5708aSMacpaul Lin sub $p1, $p1, $t5 39137e5708aSMacpaul Lin cctl $p1, L1D_IX_INVAL 39237e5708aSMacpaul Lin bnez $p1, DCAC_LOOP 39337e5708aSMacpaul Linend_flush_dcache: 39437e5708aSMacpaul Lin ret 39537e5708aSMacpaul Lin 39637e5708aSMacpaul Lin/* 39737e5708aSMacpaul Lin * Interrupt handling 39837e5708aSMacpaul Lin */ 39937e5708aSMacpaul Lin 40037e5708aSMacpaul Lin/* 40137e5708aSMacpaul Lin * exception handlers 40237e5708aSMacpaul Lin */ 40337e5708aSMacpaul Lin .align 5 40437e5708aSMacpaul Lin 40537e5708aSMacpaul Lin.macro SAVE_ALL 40637e5708aSMacpaul Lin ! FIXME: Other way to get PC? 40737e5708aSMacpaul Lin ! FIXME: Update according to the newest spec!! 40837e5708aSMacpaul Lin1: 409b19cc6bfSrick li $r28, 1 41037e5708aSMacpaul Lin push $r28 41137e5708aSMacpaul Lin mfsr $r28, PSW ! $PSW 41237e5708aSMacpaul Lin push $r28 41337e5708aSMacpaul Lin mfsr $r28, EIT_EVA ! $ir1 $EVA 41437e5708aSMacpaul Lin push $r28 41537e5708aSMacpaul Lin mfsr $r28, EIT_ITYPE ! $ir2 $ITYPE 41637e5708aSMacpaul Lin push $r28 41737e5708aSMacpaul Lin mfsr $r28, EIT_MACH_ERR ! $ir3 Mach Error 41837e5708aSMacpaul Lin push $r28 41937e5708aSMacpaul Lin mfsr $r28, EIT_INTR_PSW ! $ir5 $IPSW 42037e5708aSMacpaul Lin push $r28 42137e5708aSMacpaul Lin mfsr $r28, EIT_PREV_IPSW ! $ir6 prev $IPSW 42237e5708aSMacpaul Lin push $r28 42337e5708aSMacpaul Lin mfsr $r28, EIT_PREV_EVA ! $ir7 prev $EVA 42437e5708aSMacpaul Lin push $r28 42537e5708aSMacpaul Lin mfsr $r28, EIT_PREV_ITYPE ! $ir8 prev $ITYPE 42637e5708aSMacpaul Lin push $r28 42737e5708aSMacpaul Lin mfsr $r28, EIT_INTR_PC ! $ir9 Interruption PC 42837e5708aSMacpaul Lin push $r28 42937e5708aSMacpaul Lin mfsr $r28, EIT_PREV_IPC ! $ir10 prev INTR_PC 43037e5708aSMacpaul Lin push $r28 43137e5708aSMacpaul Lin mfsr $r28, EIT_OVL_INTR_PC ! $ir11 Overflowed INTR_PC 43237e5708aSMacpaul Lin push $r28 43337e5708aSMacpaul Lin mfusr $r28, $d1.lo 43437e5708aSMacpaul Lin push $r28 43537e5708aSMacpaul Lin mfusr $r28, $d1.hi 43637e5708aSMacpaul Lin push $r28 43737e5708aSMacpaul Lin mfusr $r28, $d0.lo 43837e5708aSMacpaul Lin push $r28 43937e5708aSMacpaul Lin mfusr $r28, $d0.hi 44037e5708aSMacpaul Lin push $r28 44137e5708aSMacpaul Lin pushm $r0, $r30 ! store $sp-$r31, ra-$r30, $gp-$r29, $r28-$fp 44237e5708aSMacpaul Lin addi $sp, $sp, -4 ! make room for implicit pt_regs parameters 44337e5708aSMacpaul Lin.endm 44437e5708aSMacpaul Lin 44537e5708aSMacpaul Lin .align 5 44637e5708aSMacpaul Lintlb_fill: 44737e5708aSMacpaul Lin SAVE_ALL 44837e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 44937e5708aSMacpaul Lin li $r1, 1 ! Determine interruption type 45037e5708aSMacpaul Lin bal do_interruption 45137e5708aSMacpaul Lin 45237e5708aSMacpaul Lin .align 5 45337e5708aSMacpaul Lintlb_not_present: 45437e5708aSMacpaul Lin SAVE_ALL 45537e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 45637e5708aSMacpaul Lin li $r1, 2 ! Determine interruption type 45737e5708aSMacpaul Lin bal do_interruption 45837e5708aSMacpaul Lin 45937e5708aSMacpaul Lin .align 5 46037e5708aSMacpaul Lintlb_misc: 46137e5708aSMacpaul Lin SAVE_ALL 46237e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 46337e5708aSMacpaul Lin li $r1, 3 ! Determine interruption type 46437e5708aSMacpaul Lin bal do_interruption 46537e5708aSMacpaul Lin 46637e5708aSMacpaul Lin .align 5 46737e5708aSMacpaul Lintlb_vlpt_miss: 46837e5708aSMacpaul Lin SAVE_ALL 46937e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 47037e5708aSMacpaul Lin li $r1, 4 ! Determine interruption type 47137e5708aSMacpaul Lin bal do_interruption 47237e5708aSMacpaul Lin 47337e5708aSMacpaul Lin .align 5 4741a05bb3cSMacpaul Linmachine_error: 47537e5708aSMacpaul Lin SAVE_ALL 47637e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 47737e5708aSMacpaul Lin li $r1, 5 ! Determine interruption type 47837e5708aSMacpaul Lin bal do_interruption 47937e5708aSMacpaul Lin 48037e5708aSMacpaul Lin .align 5 48137e5708aSMacpaul Lindebug: 48237e5708aSMacpaul Lin SAVE_ALL 48337e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 48437e5708aSMacpaul Lin li $r1, 6 ! Determine interruption type 48537e5708aSMacpaul Lin bal do_interruption 48637e5708aSMacpaul Lin 48737e5708aSMacpaul Lin .align 5 48837e5708aSMacpaul Lingeneral_exception: 48937e5708aSMacpaul Lin SAVE_ALL 49037e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 49137e5708aSMacpaul Lin li $r1, 7 ! Determine interruption type 49237e5708aSMacpaul Lin bal do_interruption 49337e5708aSMacpaul Lin 49437e5708aSMacpaul Lin .align 5 4951a05bb3cSMacpaul Linsyscall: 49637e5708aSMacpaul Lin SAVE_ALL 49737e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 49837e5708aSMacpaul Lin li $r1, 8 ! Determine interruption type 49937e5708aSMacpaul Lin bal do_interruption 50037e5708aSMacpaul Lin 50137e5708aSMacpaul Lin .align 5 5021a05bb3cSMacpaul Lininternal_interrupt: 5031a05bb3cSMacpaul Lin SAVE_ALL 5041a05bb3cSMacpaul Lin move $r0, $sp ! To get the kernel stack 5051a05bb3cSMacpaul Lin li $r1, 9 ! Determine interruption type 5061a05bb3cSMacpaul Lin bal do_interruption 5071a05bb3cSMacpaul Lin 5081a05bb3cSMacpaul Lin .align 5 5091a05bb3cSMacpaul Linsoftware_interrupt: 5101a05bb3cSMacpaul Lin SAVE_ALL 5111a05bb3cSMacpaul Lin move $r0, $sp ! To get the kernel stack 5121a05bb3cSMacpaul Lin li $r1, 10 ! Determine interruption type 5131a05bb3cSMacpaul Lin bal do_interruption 5141a05bb3cSMacpaul Lin 5151a05bb3cSMacpaul Lin .align 5 51637e5708aSMacpaul Lin 51737e5708aSMacpaul Lin/* 51837e5708aSMacpaul Lin * void reset_cpu(ulong addr); 51937e5708aSMacpaul Lin * $r0: input address to jump to 52037e5708aSMacpaul Lin */ 52137e5708aSMacpaul Lin.globl reset_cpu 52237e5708aSMacpaul Linreset_cpu: 52337e5708aSMacpaul Lin/* No need to disable MMU because we never enable it */ 52437e5708aSMacpaul Lin 52537e5708aSMacpaul Lin bal invalidate_icac 52637e5708aSMacpaul Lin bal invalidate_dcac 52737e5708aSMacpaul Lin mfsr $p0, $MMU_CFG 52837e5708aSMacpaul Lin andi $p0, $p0, 0x3 ! MMPS 52937e5708aSMacpaul Lin li $p1, 0x2 ! TLB MMU 53037e5708aSMacpaul Lin bne $p0, $p1, 1f 53137e5708aSMacpaul Lin tlbop flushall ! Flush TLB 53237e5708aSMacpaul Lin1: 53337e5708aSMacpaul Lin mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg 53437e5708aSMacpaul Lin li $p1, DIS_DCAC 53537e5708aSMacpaul Lin and $p0, $p0, $p1 ! Clear the DC_EN bit 53637e5708aSMacpaul Lin mtsr $p0, MR_CAC_CTL ! Write back the $CACHE_CTL reg 53737e5708aSMacpaul Lin br $r0 ! Jump to the input address 538