1*4882a593Smuzhiyun/* 2*4882a593Smuzhiyun * Andesboot - Startup Code for Whitiger core 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * Copyright (C) 2006 Andes Technology Corporation 5*4882a593Smuzhiyun * Copyright (C) 2006 Shawn Lin <nobuhiro@andestech.com> 6*4882a593Smuzhiyun * Copyright (C) 2011 Macpaul Lin <macpaul@andestech.com> 7*4882a593Smuzhiyun * Greentime Hu <greentime@andestech.com> 8*4882a593Smuzhiyun * 9*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+ 10*4882a593Smuzhiyun */ 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun.pic 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun#include <asm-offsets.h> 15*4882a593Smuzhiyun#include <config.h> 16*4882a593Smuzhiyun#include <common.h> 17*4882a593Smuzhiyun#include <asm/macro.h> 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun/* 20*4882a593Smuzhiyun * Jump vector table for EVIC mode 21*4882a593Smuzhiyun */ 22*4882a593Smuzhiyun#define ENA_DCAC 2UL 23*4882a593Smuzhiyun#define DIS_DCAC ~ENA_DCAC 24*4882a593Smuzhiyun#define ICAC_MEM_KBF_ISET (0x07) ! I Cache sets per way 25*4882a593Smuzhiyun#define ICAC_MEM_KBF_IWAY (0x07<<3) ! I cache ways 26*4882a593Smuzhiyun#define ICAC_MEM_KBF_ISZ (0x07<<6) ! I cache line size 27*4882a593Smuzhiyun#define DCAC_MEM_KBF_DSET (0x07) ! D Cache sets per way 28*4882a593Smuzhiyun#define DCAC_MEM_KBF_DWAY (0x07<<3) ! D cache ways 29*4882a593Smuzhiyun#define DCAC_MEM_KBF_DSZ (0x07<<6) ! D cache line size 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun#define PSW $ir0 32*4882a593Smuzhiyun#define EIT_INTR_PSW $ir1 ! interruption $PSW 33*4882a593Smuzhiyun#define EIT_PREV_IPSW $ir2 ! previous $IPSW 34*4882a593Smuzhiyun#define EIT_IVB $ir3 ! intr vector base address 35*4882a593Smuzhiyun#define EIT_EVA $ir4 ! MMU related Exception VA reg 36*4882a593Smuzhiyun#define EIT_PREV_EVA $ir5 ! previous $eva 37*4882a593Smuzhiyun#define EIT_ITYPE $ir6 ! interruption type 38*4882a593Smuzhiyun#define EIT_PREV_ITYPE $ir7 ! prev intr type 39*4882a593Smuzhiyun#define EIT_MACH_ERR $ir8 ! machine error log 40*4882a593Smuzhiyun#define EIT_INTR_PC $ir9 ! Interruption PC 41*4882a593Smuzhiyun#define EIT_PREV_IPC $ir10 ! previous $IPC 42*4882a593Smuzhiyun#define EIT_OVL_INTR_PC $ir11 ! overflow interruption PC 43*4882a593Smuzhiyun#define EIT_PREV_P0 $ir12 ! prev $P0 44*4882a593Smuzhiyun#define EIT_PREV_P1 $ir13 ! prev $p1 45*4882a593Smuzhiyun#define CR_ICAC_MEM $cr1 ! I-cache/memory config reg 46*4882a593Smuzhiyun#define CR_DCAC_MEM $cr2 ! D-cache/memory config reg 47*4882a593Smuzhiyun#define MR_CAC_CTL $mr8 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun.globl _start 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun_start: j reset 52*4882a593Smuzhiyun j tlb_fill 53*4882a593Smuzhiyun j tlb_not_present 54*4882a593Smuzhiyun j tlb_misc 55*4882a593Smuzhiyun j tlb_vlpt_miss 56*4882a593Smuzhiyun j machine_error 57*4882a593Smuzhiyun j debug 58*4882a593Smuzhiyun j general_exception 59*4882a593Smuzhiyun j syscall 60*4882a593Smuzhiyun j internal_interrupt ! H0I 61*4882a593Smuzhiyun j internal_interrupt ! H1I 62*4882a593Smuzhiyun j internal_interrupt ! H2I 63*4882a593Smuzhiyun j internal_interrupt ! H3I 64*4882a593Smuzhiyun j internal_interrupt ! H4I 65*4882a593Smuzhiyun j internal_interrupt ! H5I 66*4882a593Smuzhiyun j software_interrupt ! S0I 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun .balign 16 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun/* 71*4882a593Smuzhiyun * Andesboot Startup Code (reset vector) 72*4882a593Smuzhiyun * 73*4882a593Smuzhiyun * 1. bootstrap 74*4882a593Smuzhiyun * 1.1 reset - start of u-boot 75*4882a593Smuzhiyun * 1.2 to superuser mode - as is when reset 76*4882a593Smuzhiyun * 1.4 Do lowlevel_init 77*4882a593Smuzhiyun * - (this will jump out to lowlevel_init.S in SoC) 78*4882a593Smuzhiyun * - (lowlevel_init) 79*4882a593Smuzhiyun * 1.3 Turn off watchdog timer 80*4882a593Smuzhiyun * - (this will jump out to watchdog.S in SoC) 81*4882a593Smuzhiyun * - (turnoff_watchdog) 82*4882a593Smuzhiyun * 2. Do critical init when reboot (not from mem) 83*4882a593Smuzhiyun * 3. Relocate andesboot to ram 84*4882a593Smuzhiyun * 4. Setup stack 85*4882a593Smuzhiyun * 5. Jump to second stage (board_init_r) 86*4882a593Smuzhiyun */ 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun/* Note: TEXT_BASE is defined by the (board-dependent) linker script */ 89*4882a593Smuzhiyun.globl _TEXT_BASE 90*4882a593Smuzhiyun_TEXT_BASE: 91*4882a593Smuzhiyun .word CONFIG_SYS_TEXT_BASE 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun/* IRQ stack memory (calculated at run-time) + 8 bytes */ 94*4882a593Smuzhiyun.globl IRQ_STACK_START_IN 95*4882a593SmuzhiyunIRQ_STACK_START_IN: 96*4882a593Smuzhiyun .word 0x0badc0de 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun/* 99*4882a593Smuzhiyun * The bootstrap code of nds32 core 100*4882a593Smuzhiyun */ 101*4882a593Smuzhiyun 102*4882a593Smuzhiyunreset: 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun/* 105*4882a593Smuzhiyun * gp = ~0 for burn mode 106*4882a593Smuzhiyun * = ~load_address for load mode 107*4882a593Smuzhiyun */ 108*4882a593Smuzhiyunreset_gp: 109*4882a593Smuzhiyun .relax_hint 0 110*4882a593Smuzhiyun sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_-8) 111*4882a593Smuzhiyun .relax_hint 0 112*4882a593Smuzhiyun ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_-4) 113*4882a593Smuzhiyun add5.pc $gp 114*4882a593Smuzhiyun 115*4882a593Smuzhiyunset_ivb: 116*4882a593Smuzhiyun li $r0, 0x0 117*4882a593Smuzhiyun /* turn on BTB */ 118*4882a593Smuzhiyun mtsr $r0, $misc_ctl 119*4882a593Smuzhiyun /* set IVIC, vector size: 4 bytes, base: 0x0 */ 120*4882a593Smuzhiyun mtsr $r0, $ivb 121*4882a593Smuzhiyun/* 122*4882a593Smuzhiyun * MMU_CTL NTC0 Cacheable/Write-Back 123*4882a593Smuzhiyun */ 124*4882a593Smuzhiyun li $r0, ~0x3 125*4882a593Smuzhiyun mfsr $r1, $mr8 126*4882a593Smuzhiyun and $r1, $r1, $r0 127*4882a593Smuzhiyun mtsr $r1, $mr8 128*4882a593Smuzhiyun#if (!defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF)) 129*4882a593Smuzhiyun li $r0, 0x4 130*4882a593Smuzhiyun mfsr $r1, $mr0 131*4882a593Smuzhiyun or $r1, $r1, $r0 132*4882a593Smuzhiyun mtsr $r1, $mr0 133*4882a593Smuzhiyun#endif 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun#if !defined(CONFIG_SYS_ICACHE_OFF) 136*4882a593Smuzhiyun li $r0, 0x1 137*4882a593Smuzhiyun mfsr $r1, $mr8 138*4882a593Smuzhiyun or $r1, $r1, $r0 139*4882a593Smuzhiyun mtsr $r1, $mr8 140*4882a593Smuzhiyun#endif 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun#if !defined(CONFIG_SYS_DCACHE_OFF) 143*4882a593Smuzhiyun li $r0, 0x2 144*4882a593Smuzhiyun mfsr $r1, $mr8 145*4882a593Smuzhiyun or $r1, $r1, $r0 146*4882a593Smuzhiyun mtsr $r1, $mr8 147*4882a593Smuzhiyun#endif 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun jal mem_init 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun#ifndef CONFIG_SKIP_LOWLEVEL_INIT 152*4882a593Smuzhiyun jal lowlevel_init 153*4882a593Smuzhiyun/* 154*4882a593Smuzhiyun * gp = ~VMA for burn mode 155*4882a593Smuzhiyun * = ~load_address for load mode 156*4882a593Smuzhiyun */ 157*4882a593Smuzhiyunupdate_gp: 158*4882a593Smuzhiyun .relax_hint 0 159*4882a593Smuzhiyun sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_-8) 160*4882a593Smuzhiyun .relax_hint 0 161*4882a593Smuzhiyun ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_-4) 162*4882a593Smuzhiyun add5.pc $gp 163*4882a593Smuzhiyun#endif 164*4882a593Smuzhiyun/* 165*4882a593Smuzhiyun * do critical initializations first (shall be in short time) 166*4882a593Smuzhiyun * do self_relocation ASAP. 167*4882a593Smuzhiyun */ 168*4882a593Smuzhiyun 169*4882a593Smuzhiyun/* 170*4882a593Smuzhiyun * Set the N1213 (Whitiger) core to superuser mode 171*4882a593Smuzhiyun * According to spec, it is already when reset 172*4882a593Smuzhiyun */ 173*4882a593Smuzhiyun#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG 174*4882a593Smuzhiyun jal turnoff_watchdog 175*4882a593Smuzhiyun#endif 176*4882a593Smuzhiyun 177*4882a593Smuzhiyun/* 178*4882a593Smuzhiyun * Do CPU critical regs init only at reboot, 179*4882a593Smuzhiyun * not when booting from ram 180*4882a593Smuzhiyun */ 181*4882a593Smuzhiyun#ifdef CONFIG_INIT_CRITICAL 182*4882a593Smuzhiyun jal cpu_init_crit ! Do CPU critical regs init 183*4882a593Smuzhiyun#endif 184*4882a593Smuzhiyun 185*4882a593Smuzhiyun/* 186*4882a593Smuzhiyun * Set stackpointer in internal RAM to call board_init_f 187*4882a593Smuzhiyun * $sp must be 8-byte alignment for ABI compliance. 188*4882a593Smuzhiyun */ 189*4882a593Smuzhiyuncall_board_init_f: 190*4882a593Smuzhiyun li $sp, CONFIG_SYS_INIT_SP_ADDR 191*4882a593Smuzhiyun move $r0, $sp 192*4882a593Smuzhiyun bal board_init_f_alloc_reserve 193*4882a593Smuzhiyun move $sp, $r0 194*4882a593Smuzhiyun bal board_init_f_init_reserve 195*4882a593Smuzhiyun#ifdef CONFIG_DEBUG_UART 196*4882a593Smuzhiyun bal debug_uart_init 197*4882a593Smuzhiyun#endif 198*4882a593Smuzhiyun li $r0, 0x00000000 199*4882a593Smuzhiyun#ifdef __PIC__ 200*4882a593Smuzhiyun#ifdef __NDS32_N1213_43U1H__ 201*4882a593Smuzhiyun/* __NDS32_N1213_43U1H__ implies NDS32 V0 ISA */ 202*4882a593Smuzhiyun la $r15, board_init_f ! store function address into $r15 203*4882a593Smuzhiyun#endif 204*4882a593Smuzhiyun#endif 205*4882a593Smuzhiyun j board_init_f ! jump to board_init_f() in lib/board.c 206*4882a593Smuzhiyun 207*4882a593Smuzhiyun/* 208*4882a593Smuzhiyun * void relocate_code (addr_sp, gd, addr_moni) 209*4882a593Smuzhiyun * 210*4882a593Smuzhiyun * This "function" does not return, instead it continues in RAM 211*4882a593Smuzhiyun * after relocating the monitor code. 212*4882a593Smuzhiyun * 213*4882a593Smuzhiyun */ 214*4882a593Smuzhiyun 215*4882a593Smuzhiyun/* 216*4882a593Smuzhiyun * gp = ~RAM_SIZE - TEXT_SIZE for burn/load mode 217*4882a593Smuzhiyun */ 218*4882a593Smuzhiyun 219*4882a593Smuzhiyun.globl relocate_code 220*4882a593Smuzhiyunrelocate_code: 221*4882a593Smuzhiyun move $r4, $r0 /* save addr_sp */ 222*4882a593Smuzhiyun move $r5, $r1 /* save addr of gd */ 223*4882a593Smuzhiyun move $r6, $r2 /* save addr of destination */ 224*4882a593Smuzhiyun 225*4882a593Smuzhiyun/* Set up the stack */ 226*4882a593Smuzhiyunstack_setup: 227*4882a593Smuzhiyun move $sp, $r4 228*4882a593Smuzhiyun 229*4882a593Smuzhiyun la $r0, _start@GOTOFF 230*4882a593Smuzhiyun beq $r0, $r6, clear_bss /* skip relocation */ 231*4882a593Smuzhiyun 232*4882a593Smuzhiyun la $r1, _end@GOTOFF 233*4882a593Smuzhiyun move $r2, $r6 /* r2 <- scratch for copy_loop */ 234*4882a593Smuzhiyuncopy_loop: 235*4882a593Smuzhiyun lmw.bim $r11, [$r0], $r18 236*4882a593Smuzhiyun smw.bim $r11, [$r2], $r18 237*4882a593Smuzhiyun blt $r0, $r1, copy_loop 238*4882a593Smuzhiyun/* 239*4882a593Smuzhiyun * fix relocations related issues 240*4882a593Smuzhiyun */ 241*4882a593Smuzhiyunfix_relocations: 242*4882a593Smuzhiyun l.w $r0, _TEXT_BASE@GOTOFF /* r0 <- Text base */ 243*4882a593Smuzhiyun sub $r9, $r6, $r0 /* r9 <- relocation offset */ 244*4882a593Smuzhiyun 245*4882a593Smuzhiyun la $r7, __rel_dyn_start@GOTOFF 246*4882a593Smuzhiyun add $r7, $r7, $r9 /* r2 <- rel __got_start in RAM */ 247*4882a593Smuzhiyun la $r8, __rel_dyn_end@GOTOFF 248*4882a593Smuzhiyun add $r8, $r8, $r9 /* r2 <- rel __got_start in RAM */ 249*4882a593Smuzhiyun li $r3, #0x2a /* R_NDS32_RELATIVE */ 250*4882a593Smuzhiyun1: 251*4882a593Smuzhiyun lmw.bim $r0, [$r7], $r2 /* r0,r1,r2 <- adr,type,addend */ 252*4882a593Smuzhiyun bne $r1, $r3, 2f 253*4882a593Smuzhiyun 254*4882a593Smuzhiyun add $r0, $r0, $r9 255*4882a593Smuzhiyun add $r2, $r2, $r9 256*4882a593Smuzhiyun sw $r2, [$r0] 257*4882a593Smuzhiyun2: 258*4882a593Smuzhiyun blt $r7, $r8, 1b 259*4882a593Smuzhiyun 260*4882a593Smuzhiyunclear_bss: 261*4882a593Smuzhiyun la $r0, __bss_start@GOTOFF /* r0 <- rel __bss_start in FLASH */ 262*4882a593Smuzhiyun add $r0, $r0, $r9 /* r0 <- rel __bss_start in FLASH */ 263*4882a593Smuzhiyun la $r1, __bss_end@GOTOFF /* r1 <- rel __bss_end in RAM */ 264*4882a593Smuzhiyun add $r1, $r1, $r9 /* r0 <- rel __bss_end in RAM */ 265*4882a593Smuzhiyun li $r2, 0x00000000 /* clear */ 266*4882a593Smuzhiyun 267*4882a593Smuzhiyunclbss_l: 268*4882a593Smuzhiyun sw $r2, [$r0] /* clear loop... */ 269*4882a593Smuzhiyun addi $r0, $r0, #4 270*4882a593Smuzhiyun bne $r0, $r1, clbss_l 271*4882a593Smuzhiyun 272*4882a593Smuzhiyun/* 273*4882a593Smuzhiyun * We are done. Do not return, instead branch to second part of board 274*4882a593Smuzhiyun * initialization, now running from RAM. 275*4882a593Smuzhiyun */ 276*4882a593Smuzhiyuncall_board_init_r: 277*4882a593Smuzhiyun bal invalidate_icache_all 278*4882a593Smuzhiyun bal flush_dcache_all 279*4882a593Smuzhiyun la $r0, board_init_r@GOTOFF 280*4882a593Smuzhiyun move $lp, $r0 /* offset of board_init_r() */ 281*4882a593Smuzhiyun add $lp, $lp, $r9 /* real address of board_init_r() */ 282*4882a593Smuzhiyun /* setup parameters for board_init_r */ 283*4882a593Smuzhiyun move $r0, $r5 /* gd_t */ 284*4882a593Smuzhiyun move $r1, $r6 /* dest_addr */ 285*4882a593Smuzhiyun 286*4882a593Smuzhiyun#ifdef __PIC__ 287*4882a593Smuzhiyun#ifdef __NDS32_N1213_43U1H__ /* NDS32 V0 ISA */ 288*4882a593Smuzhiyun move $r15, $lp /* store function address into $r15 */ 289*4882a593Smuzhiyun#endif 290*4882a593Smuzhiyun#endif 291*4882a593Smuzhiyun 292*4882a593Smuzhiyun /* jump to it ... */ 293*4882a593Smuzhiyun jr $lp /* jump to board_init_r() */ 294*4882a593Smuzhiyun 295*4882a593Smuzhiyun/* 296*4882a593Smuzhiyun * Initialize CPU critical registers 297*4882a593Smuzhiyun * 298*4882a593Smuzhiyun * 1. Setup control registers 299*4882a593Smuzhiyun * 1.1 Mask all IRQs 300*4882a593Smuzhiyun * 1.2 Flush cache and TLB 301*4882a593Smuzhiyun * 1.3 Disable MMU and cache 302*4882a593Smuzhiyun * 2. Setup memory timing 303*4882a593Smuzhiyun */ 304*4882a593Smuzhiyun 305*4882a593Smuzhiyuncpu_init_crit: 306*4882a593Smuzhiyun 307*4882a593Smuzhiyun move $r0, $lp /* push ra */ 308*4882a593Smuzhiyun 309*4882a593Smuzhiyun /* Disable Interrupts by clear GIE in $PSW reg */ 310*4882a593Smuzhiyun setgie.d 311*4882a593Smuzhiyun 312*4882a593Smuzhiyun /* Flush caches and TLB */ 313*4882a593Smuzhiyun /* Invalidate caches */ 314*4882a593Smuzhiyun jal invalidate_icac 315*4882a593Smuzhiyun jal invalidate_dcac 316*4882a593Smuzhiyun 317*4882a593Smuzhiyun /* Flush TLB */ 318*4882a593Smuzhiyun mfsr $p0, $MMU_CFG 319*4882a593Smuzhiyun andi $p0, $p0, 0x3 ! MMPS 320*4882a593Smuzhiyun li $p1, 0x2 ! TLB MMU 321*4882a593Smuzhiyun bne $p0, $p1, 1f 322*4882a593Smuzhiyun tlbop flushall ! Flush TLB 323*4882a593Smuzhiyun 324*4882a593Smuzhiyun1: 325*4882a593Smuzhiyun ! Disable MMU, Dcache 326*4882a593Smuzhiyun ! Whitiger is MMU disabled when reset 327*4882a593Smuzhiyun ! Disable the D$ 328*4882a593Smuzhiyun mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg 329*4882a593Smuzhiyun li $p1, DIS_DCAC 330*4882a593Smuzhiyun and $p0, $p0, $p1 ! Set DC_EN bit 331*4882a593Smuzhiyun mtsr $p0, MR_CAC_CTL ! write back the $CACHE_CTL reg 332*4882a593Smuzhiyun isb 333*4882a593Smuzhiyun 334*4882a593Smuzhiyun move $lp, $r0 335*4882a593Smuzhiyun2: 336*4882a593Smuzhiyun ret 337*4882a593Smuzhiyun 338*4882a593Smuzhiyun/* 339*4882a593Smuzhiyun * Invalidate I$ 340*4882a593Smuzhiyun */ 341*4882a593Smuzhiyuninvalidate_icac: 342*4882a593Smuzhiyun ! read $cr1(I CAC/MEM cfg. reg.) configuration 343*4882a593Smuzhiyun mfsr $t0, CR_ICAC_MEM 344*4882a593Smuzhiyun 345*4882a593Smuzhiyun ! Get the ISZ field 346*4882a593Smuzhiyun andi $p0, $t0, ICAC_MEM_KBF_ISZ 347*4882a593Smuzhiyun 348*4882a593Smuzhiyun ! if $p0=0, then no I CAC existed 349*4882a593Smuzhiyun beqz $p0, end_flush_icache 350*4882a593Smuzhiyun 351*4882a593Smuzhiyun ! get $p0 the index of I$ block 352*4882a593Smuzhiyun srli $p0, $p0, 6 353*4882a593Smuzhiyun 354*4882a593Smuzhiyun ! $t1= bit width of I cache line size(ISZ) 355*4882a593Smuzhiyun addi $t1, $p0, 2 356*4882a593Smuzhiyun 357*4882a593Smuzhiyun li $t4, 1 358*4882a593Smuzhiyun sll $t5, $t4, $t1 ! get $t5 cache line size 359*4882a593Smuzhiyun andi $p1, $t0, ICAC_MEM_KBF_ISET ! get the ISET field 360*4882a593Smuzhiyun addi $t2, $p1, 6 ! $t2= bit width of ISET 361*4882a593Smuzhiyun andi $p1, $t0, ICAC_MEM_KBF_IWAY ! get bitfield of Iway 362*4882a593Smuzhiyun srli $p1, $p1, 3 363*4882a593Smuzhiyun addi $p1, $p1, 1 ! then $p1 is I way number 364*4882a593Smuzhiyun add $t3, $t2, $t1 ! SHIFT 365*4882a593Smuzhiyun sll $p1, $p1, $t3 ! GET the total cache size 366*4882a593SmuzhiyunICAC_LOOP: 367*4882a593Smuzhiyun sub $p1, $p1, $t5 368*4882a593Smuzhiyun cctl $p1, L1I_IX_INVAL 369*4882a593Smuzhiyun bnez $p1, ICAC_LOOP 370*4882a593Smuzhiyunend_flush_icache: 371*4882a593Smuzhiyun ret 372*4882a593Smuzhiyun 373*4882a593Smuzhiyun/* 374*4882a593Smuzhiyun * Invalidate D$ 375*4882a593Smuzhiyun */ 376*4882a593Smuzhiyuninvalidate_dcac: 377*4882a593Smuzhiyun ! read $cr2(D CAC/MEM cfg. reg.) configuration 378*4882a593Smuzhiyun mfsr $t0, CR_DCAC_MEM 379*4882a593Smuzhiyun 380*4882a593Smuzhiyun ! Get the DSZ field 381*4882a593Smuzhiyun andi $p0, $t0, DCAC_MEM_KBF_DSZ 382*4882a593Smuzhiyun 383*4882a593Smuzhiyun ! if $p0=0, then no D CAC existed 384*4882a593Smuzhiyun beqz $p0, end_flush_dcache 385*4882a593Smuzhiyun 386*4882a593Smuzhiyun ! get $p0 the index of D$ block 387*4882a593Smuzhiyun srli $p0, $p0, 6 388*4882a593Smuzhiyun 389*4882a593Smuzhiyun ! $t1= bit width of D cache line size(DSZ) 390*4882a593Smuzhiyun addi $t1, $p0, 2 391*4882a593Smuzhiyun 392*4882a593Smuzhiyun li $t4, 1 393*4882a593Smuzhiyun sll $t5, $t4, $t1 ! get $t5 cache line size 394*4882a593Smuzhiyun andi $p1, $t0, DCAC_MEM_KBF_DSET ! get the DSET field 395*4882a593Smuzhiyun addi $t2, $p1, 6 ! $t2= bit width of DSET 396*4882a593Smuzhiyun andi $p1, $t0, DCAC_MEM_KBF_DWAY ! get bitfield of D way 397*4882a593Smuzhiyun srli $p1, $p1, 3 398*4882a593Smuzhiyun addi $p1, $p1, 1 ! then $p1 is D way number 399*4882a593Smuzhiyun add $t3, $t2, $t1 ! SHIFT 400*4882a593Smuzhiyun sll $p1, $p1, $t3 ! GET the total cache size 401*4882a593SmuzhiyunDCAC_LOOP: 402*4882a593Smuzhiyun sub $p1, $p1, $t5 403*4882a593Smuzhiyun cctl $p1, L1D_IX_INVAL 404*4882a593Smuzhiyun bnez $p1, DCAC_LOOP 405*4882a593Smuzhiyunend_flush_dcache: 406*4882a593Smuzhiyun ret 407*4882a593Smuzhiyun 408*4882a593Smuzhiyun/* 409*4882a593Smuzhiyun * Interrupt handling 410*4882a593Smuzhiyun */ 411*4882a593Smuzhiyun 412*4882a593Smuzhiyun/* 413*4882a593Smuzhiyun * exception handlers 414*4882a593Smuzhiyun */ 415*4882a593Smuzhiyun .align 5 416*4882a593Smuzhiyun 417*4882a593Smuzhiyun.macro SAVE_ALL 418*4882a593Smuzhiyun ! FIXME: Other way to get PC? 419*4882a593Smuzhiyun ! FIXME: Update according to the newest spec!! 420*4882a593Smuzhiyun1: 421*4882a593Smuzhiyun li $r28, 1 422*4882a593Smuzhiyun push $r28 423*4882a593Smuzhiyun mfsr $r28, PSW ! $PSW 424*4882a593Smuzhiyun push $r28 425*4882a593Smuzhiyun mfsr $r28, EIT_EVA ! $ir1 $EVA 426*4882a593Smuzhiyun push $r28 427*4882a593Smuzhiyun mfsr $r28, EIT_ITYPE ! $ir2 $ITYPE 428*4882a593Smuzhiyun push $r28 429*4882a593Smuzhiyun mfsr $r28, EIT_MACH_ERR ! $ir3 Mach Error 430*4882a593Smuzhiyun push $r28 431*4882a593Smuzhiyun mfsr $r28, EIT_INTR_PSW ! $ir5 $IPSW 432*4882a593Smuzhiyun push $r28 433*4882a593Smuzhiyun mfsr $r28, EIT_PREV_IPSW ! $ir6 prev $IPSW 434*4882a593Smuzhiyun push $r28 435*4882a593Smuzhiyun mfsr $r28, EIT_PREV_EVA ! $ir7 prev $EVA 436*4882a593Smuzhiyun push $r28 437*4882a593Smuzhiyun mfsr $r28, EIT_PREV_ITYPE ! $ir8 prev $ITYPE 438*4882a593Smuzhiyun push $r28 439*4882a593Smuzhiyun mfsr $r28, EIT_INTR_PC ! $ir9 Interruption PC 440*4882a593Smuzhiyun push $r28 441*4882a593Smuzhiyun mfsr $r28, EIT_PREV_IPC ! $ir10 prev INTR_PC 442*4882a593Smuzhiyun push $r28 443*4882a593Smuzhiyun mfsr $r28, EIT_OVL_INTR_PC ! $ir11 Overflowed INTR_PC 444*4882a593Smuzhiyun push $r28 445*4882a593Smuzhiyun mfusr $r28, $d1.lo 446*4882a593Smuzhiyun push $r28 447*4882a593Smuzhiyun mfusr $r28, $d1.hi 448*4882a593Smuzhiyun push $r28 449*4882a593Smuzhiyun mfusr $r28, $d0.lo 450*4882a593Smuzhiyun push $r28 451*4882a593Smuzhiyun mfusr $r28, $d0.hi 452*4882a593Smuzhiyun push $r28 453*4882a593Smuzhiyun pushm $r0, $r30 ! store $sp-$r31, ra-$r30, $gp-$r29, $r28-$fp 454*4882a593Smuzhiyun addi $sp, $sp, -4 ! make room for implicit pt_regs parameters 455*4882a593Smuzhiyun.endm 456*4882a593Smuzhiyun 457*4882a593Smuzhiyun .align 5 458*4882a593Smuzhiyuntlb_fill: 459*4882a593Smuzhiyun SAVE_ALL 460*4882a593Smuzhiyun move $r0, $sp ! To get the kernel stack 461*4882a593Smuzhiyun li $r1, 1 ! Determine interruption type 462*4882a593Smuzhiyun bal do_interruption 463*4882a593Smuzhiyun 464*4882a593Smuzhiyun .align 5 465*4882a593Smuzhiyuntlb_not_present: 466*4882a593Smuzhiyun SAVE_ALL 467*4882a593Smuzhiyun move $r0, $sp ! To get the kernel stack 468*4882a593Smuzhiyun li $r1, 2 ! Determine interruption type 469*4882a593Smuzhiyun bal do_interruption 470*4882a593Smuzhiyun 471*4882a593Smuzhiyun .align 5 472*4882a593Smuzhiyuntlb_misc: 473*4882a593Smuzhiyun SAVE_ALL 474*4882a593Smuzhiyun move $r0, $sp ! To get the kernel stack 475*4882a593Smuzhiyun li $r1, 3 ! Determine interruption type 476*4882a593Smuzhiyun bal do_interruption 477*4882a593Smuzhiyun 478*4882a593Smuzhiyun .align 5 479*4882a593Smuzhiyuntlb_vlpt_miss: 480*4882a593Smuzhiyun SAVE_ALL 481*4882a593Smuzhiyun move $r0, $sp ! To get the kernel stack 482*4882a593Smuzhiyun li $r1, 4 ! Determine interruption type 483*4882a593Smuzhiyun bal do_interruption 484*4882a593Smuzhiyun 485*4882a593Smuzhiyun .align 5 486*4882a593Smuzhiyunmachine_error: 487*4882a593Smuzhiyun SAVE_ALL 488*4882a593Smuzhiyun move $r0, $sp ! To get the kernel stack 489*4882a593Smuzhiyun li $r1, 5 ! Determine interruption type 490*4882a593Smuzhiyun bal do_interruption 491*4882a593Smuzhiyun 492*4882a593Smuzhiyun .align 5 493*4882a593Smuzhiyundebug: 494*4882a593Smuzhiyun SAVE_ALL 495*4882a593Smuzhiyun move $r0, $sp ! To get the kernel stack 496*4882a593Smuzhiyun li $r1, 6 ! Determine interruption type 497*4882a593Smuzhiyun bal do_interruption 498*4882a593Smuzhiyun 499*4882a593Smuzhiyun .align 5 500*4882a593Smuzhiyungeneral_exception: 501*4882a593Smuzhiyun SAVE_ALL 502*4882a593Smuzhiyun move $r0, $sp ! To get the kernel stack 503*4882a593Smuzhiyun li $r1, 7 ! Determine interruption type 504*4882a593Smuzhiyun bal do_interruption 505*4882a593Smuzhiyun 506*4882a593Smuzhiyun .align 5 507*4882a593Smuzhiyunsyscall: 508*4882a593Smuzhiyun SAVE_ALL 509*4882a593Smuzhiyun move $r0, $sp ! To get the kernel stack 510*4882a593Smuzhiyun li $r1, 8 ! Determine interruption type 511*4882a593Smuzhiyun bal do_interruption 512*4882a593Smuzhiyun 513*4882a593Smuzhiyun .align 5 514*4882a593Smuzhiyuninternal_interrupt: 515*4882a593Smuzhiyun SAVE_ALL 516*4882a593Smuzhiyun move $r0, $sp ! To get the kernel stack 517*4882a593Smuzhiyun li $r1, 9 ! Determine interruption type 518*4882a593Smuzhiyun bal do_interruption 519*4882a593Smuzhiyun 520*4882a593Smuzhiyun .align 5 521*4882a593Smuzhiyunsoftware_interrupt: 522*4882a593Smuzhiyun SAVE_ALL 523*4882a593Smuzhiyun move $r0, $sp ! To get the kernel stack 524*4882a593Smuzhiyun li $r1, 10 ! Determine interruption type 525*4882a593Smuzhiyun bal do_interruption 526*4882a593Smuzhiyun 527*4882a593Smuzhiyun .align 5 528*4882a593Smuzhiyun 529*4882a593Smuzhiyun/* 530*4882a593Smuzhiyun * void reset_cpu(ulong addr); 531*4882a593Smuzhiyun * $r0: input address to jump to 532*4882a593Smuzhiyun */ 533*4882a593Smuzhiyun.globl reset_cpu 534*4882a593Smuzhiyunreset_cpu: 535*4882a593Smuzhiyun/* No need to disable MMU because we never enable it */ 536*4882a593Smuzhiyun 537*4882a593Smuzhiyun bal invalidate_icac 538*4882a593Smuzhiyun bal invalidate_dcac 539*4882a593Smuzhiyun mfsr $p0, $MMU_CFG 540*4882a593Smuzhiyun andi $p0, $p0, 0x3 ! MMPS 541*4882a593Smuzhiyun li $p1, 0x2 ! TLB MMU 542*4882a593Smuzhiyun bne $p0, $p1, 1f 543*4882a593Smuzhiyun tlbop flushall ! Flush TLB 544*4882a593Smuzhiyun1: 545*4882a593Smuzhiyun mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg 546*4882a593Smuzhiyun li $p1, DIS_DCAC 547*4882a593Smuzhiyun and $p0, $p0, $p1 ! Clear the DC_EN bit 548*4882a593Smuzhiyun mtsr $p0, MR_CAC_CTL ! Write back the $CACHE_CTL reg 549*4882a593Smuzhiyun br $r0 ! Jump to the input address 550