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 * 937e5708aSMacpaul Lin * See file CREDITS for list of people who contributed to this 1037e5708aSMacpaul Lin * project. 1137e5708aSMacpaul Lin * 1237e5708aSMacpaul Lin * This program is free software; you can redistribute it and/or 1337e5708aSMacpaul Lin * modify it under the terms of the GNU General Public License as 1437e5708aSMacpaul Lin * published by the Free Software Foundation; either version 2 of 1537e5708aSMacpaul Lin * the License, or (at your option) any later version. 1637e5708aSMacpaul Lin * 1737e5708aSMacpaul Lin * This program is distributed in the hope that it will be useful, 1837e5708aSMacpaul Lin * but WITHOUT ANY WARRANTY; without even the implied warranty of 1937e5708aSMacpaul Lin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2037e5708aSMacpaul Lin * GNU General Public License for more details. 2137e5708aSMacpaul Lin * 2237e5708aSMacpaul Lin * You should have received a copy of the GNU General Public License 2337e5708aSMacpaul Lin * along with this program; if not, write to the Free Software 2437e5708aSMacpaul Lin * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 2537e5708aSMacpaul Lin * MA 02111-1307 USA 2637e5708aSMacpaul Lin */ 2737e5708aSMacpaul Lin 2837e5708aSMacpaul Lin#include <asm-offsets.h> 2937e5708aSMacpaul Lin#include <config.h> 3037e5708aSMacpaul Lin#include <common.h> 3137e5708aSMacpaul Lin#include <asm/macro.h> 3237e5708aSMacpaul Lin#include <version.h> 3337e5708aSMacpaul Lin 3437e5708aSMacpaul Lin/* 3537e5708aSMacpaul Lin * Jump vector table for EVIC mode 3637e5708aSMacpaul Lin */ 3737e5708aSMacpaul Lin#define ENA_DCAC 2UL 3837e5708aSMacpaul Lin#define DIS_DCAC ~ENA_DCAC 3937e5708aSMacpaul Lin#define ICAC_MEM_KBF_ISET (0x07) ! I Cache sets per way 4037e5708aSMacpaul Lin#define ICAC_MEM_KBF_IWAY (0x07<<3) ! I cache ways 4137e5708aSMacpaul Lin#define ICAC_MEM_KBF_ISZ (0x07<<6) ! I cache line size 4237e5708aSMacpaul Lin#define DCAC_MEM_KBF_DSET (0x07) ! D Cache sets per way 4337e5708aSMacpaul Lin#define DCAC_MEM_KBF_DWAY (0x07<<3) ! D cache ways 4437e5708aSMacpaul Lin#define DCAC_MEM_KBF_DSZ (0x07<<6) ! D cache line size 4537e5708aSMacpaul Lin 4637e5708aSMacpaul Lin#define PSW $ir0 4737e5708aSMacpaul Lin#define EIT_INTR_PSW $ir1 ! interruption $PSW 4837e5708aSMacpaul Lin#define EIT_PREV_IPSW $ir2 ! previous $IPSW 4937e5708aSMacpaul Lin#define EIT_IVB $ir3 ! intr vector base address 5037e5708aSMacpaul Lin#define EIT_EVA $ir4 ! MMU related Exception VA reg 5137e5708aSMacpaul Lin#define EIT_PREV_EVA $ir5 ! previous $eva 5237e5708aSMacpaul Lin#define EIT_ITYPE $ir6 ! interruption type 5337e5708aSMacpaul Lin#define EIT_PREV_ITYPE $ir7 ! prev intr type 5437e5708aSMacpaul Lin#define EIT_MACH_ERR $ir8 ! machine error log 5537e5708aSMacpaul Lin#define EIT_INTR_PC $ir9 ! Interruption PC 5637e5708aSMacpaul Lin#define EIT_PREV_IPC $ir10 ! previous $IPC 5737e5708aSMacpaul Lin#define EIT_OVL_INTR_PC $ir11 ! overflow interruption PC 5837e5708aSMacpaul Lin#define EIT_PREV_P0 $ir12 ! prev $P0 5937e5708aSMacpaul Lin#define EIT_PREV_P1 $ir13 ! prev $p1 6037e5708aSMacpaul Lin#define CR_ICAC_MEM $cr1 ! I-cache/memory config reg 6137e5708aSMacpaul Lin#define CR_DCAC_MEM $cr2 ! D-cache/memory config reg 6237e5708aSMacpaul Lin#define MR_CAC_CTL $mr8 6337e5708aSMacpaul Lin 6437e5708aSMacpaul Lin.globl _start 6537e5708aSMacpaul Lin 6637e5708aSMacpaul Lin_start: j reset 6737e5708aSMacpaul Lin j tlb_fill 6837e5708aSMacpaul Lin j tlb_not_present 6937e5708aSMacpaul Lin j tlb_misc 7037e5708aSMacpaul Lin j tlb_vlpt_miss 71*1a05bb3cSMacpaul Lin j machine_error 7237e5708aSMacpaul Lin j debug 7337e5708aSMacpaul Lin j general_exception 74*1a05bb3cSMacpaul Lin j syscall 7537e5708aSMacpaul Lin j internal_interrupt ! H0I 7637e5708aSMacpaul Lin j internal_interrupt ! H1I 7737e5708aSMacpaul Lin j internal_interrupt ! H2I 7837e5708aSMacpaul Lin j internal_interrupt ! H3I 7937e5708aSMacpaul Lin j internal_interrupt ! H4I 8037e5708aSMacpaul Lin j internal_interrupt ! H5I 81*1a05bb3cSMacpaul Lin j software_interrupt ! S0I 8237e5708aSMacpaul Lin 8337e5708aSMacpaul Lin .balign 16 8437e5708aSMacpaul Lin 8537e5708aSMacpaul Lin/* 8637e5708aSMacpaul Lin * Andesboot Startup Code (reset vector) 8737e5708aSMacpaul Lin * 8837e5708aSMacpaul Lin * 1. bootstrap 8937e5708aSMacpaul Lin * 1.1 reset - start of u-boot 9037e5708aSMacpaul Lin * 1.2 to superuser mode - as is when reset 9137e5708aSMacpaul Lin * 1.4 Do lowlevel_init 9237e5708aSMacpaul Lin * - (this will jump out to lowlevel_init.S in SoC) 9337e5708aSMacpaul Lin * - (lowlevel_init) 9437e5708aSMacpaul Lin * 1.3 Turn off watchdog timer 9537e5708aSMacpaul Lin * - (this will jump out to watchdog.S in SoC) 9637e5708aSMacpaul Lin * - (turnoff_watchdog) 9737e5708aSMacpaul Lin * 2. Do critical init when reboot (not from mem) 9837e5708aSMacpaul Lin * 3. Relocate andesboot to ram 9937e5708aSMacpaul Lin * 4. Setup stack 10037e5708aSMacpaul Lin * 5. Jump to second stage (board_init_r) 10137e5708aSMacpaul Lin */ 10237e5708aSMacpaul Lin 10337e5708aSMacpaul Lin/* Note: TEXT_BASE is defined by the (board-dependent) linker script */ 10437e5708aSMacpaul Lin.globl _TEXT_BASE 10537e5708aSMacpaul Lin_TEXT_BASE: 10637e5708aSMacpaul Lin .word CONFIG_SYS_TEXT_BASE 10737e5708aSMacpaul Lin 10837e5708aSMacpaul Lin/* 10937e5708aSMacpaul Lin * These are defined in the board-specific linker script. 11037e5708aSMacpaul Lin * Subtracting _start from them lets the linker put their 11137e5708aSMacpaul Lin * relative position in the executable instead of leaving 11237e5708aSMacpaul Lin * them null. 11337e5708aSMacpaul Lin */ 11437e5708aSMacpaul Lin#ifdef CONFIG_USE_IRQ 11537e5708aSMacpaul Lin/* IRQ stack memory (calculated at run-time) */ 11637e5708aSMacpaul Lin.globl IRQ_STACK_START 11737e5708aSMacpaul LinIRQ_STACK_START: 11837e5708aSMacpaul Lin .word 0x0badc0de 11937e5708aSMacpaul Lin 12037e5708aSMacpaul Lin/* IRQ stack memory (calculated at run-time) */ 12137e5708aSMacpaul Lin.globl FIQ_STACK_START 12237e5708aSMacpaul LinFIQ_STACK_START: 12337e5708aSMacpaul Lin .word 0x0badc0de 12437e5708aSMacpaul Lin#endif 12537e5708aSMacpaul Lin 12637e5708aSMacpaul Lin/* IRQ stack memory (calculated at run-time) + 8 bytes */ 12737e5708aSMacpaul Lin.globl IRQ_STACK_START_IN 12837e5708aSMacpaul LinIRQ_STACK_START_IN: 12937e5708aSMacpaul Lin .word 0x0badc0de 13037e5708aSMacpaul Lin 13137e5708aSMacpaul Lin/* 13237e5708aSMacpaul Lin * The bootstrap code of nds32 core 13337e5708aSMacpaul Lin */ 13437e5708aSMacpaul Lin 13537e5708aSMacpaul Linreset: 13637e5708aSMacpaul Linset_ivb: 13737e5708aSMacpaul Lin li $r0, 0x0 13837e5708aSMacpaul Lin 13937e5708aSMacpaul Lin /* turn on BTB */ 14037e5708aSMacpaul Lin mtsr $r0, $misc_ctl 14137e5708aSMacpaul Lin /* set IVIC, vector size: 4 bytes, base: 0x0 */ 14237e5708aSMacpaul Lin mtsr $r0, $ivb 14337e5708aSMacpaul Lin 14437e5708aSMacpaul Linload_lli: 14537e5708aSMacpaul Lin#ifndef CONFIG_SKIP_LOWLEVEL_INIT 14637e5708aSMacpaul Lin jal load_lowlevel_init 14737e5708aSMacpaul Lin jral $p0 14837e5708aSMacpaul Lin#endif 14937e5708aSMacpaul Lin 15037e5708aSMacpaul Lin/* 15137e5708aSMacpaul Lin * Set the N1213 (Whitiger) core to superuser mode 15237e5708aSMacpaul Lin * According to spec, it is already when reset 15337e5708aSMacpaul Lin */ 15437e5708aSMacpaul Linturnoff_wtdog: 15537e5708aSMacpaul Lin#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG 15637e5708aSMacpaul Lin jal load_turnoff_watchdog 15737e5708aSMacpaul Lin jral $p0 15837e5708aSMacpaul Lin#endif 15937e5708aSMacpaul Lin 16037e5708aSMacpaul Lin/* 16137e5708aSMacpaul Lin * Do CPU critical regs init only at reboot, 16237e5708aSMacpaul Lin * not when booting from ram 16337e5708aSMacpaul Lin */ 16437e5708aSMacpaul Lin#ifdef CONFIG_INIT_CRITICAL 16537e5708aSMacpaul Lin bal cpu_init_crit ! Do CPU critical regs init 16637e5708aSMacpaul Lin#endif 16737e5708aSMacpaul Lin 16837e5708aSMacpaul Lin/* 16937e5708aSMacpaul Lin * Set stackpointer in internal RAM to call board_init_f 17037e5708aSMacpaul Lin * $sp must be 8-byte alignment for ABI compliance. 17137e5708aSMacpaul Lin */ 17237e5708aSMacpaul Lincall_board_init_f: 17337e5708aSMacpaul Lin li $sp, CONFIG_SYS_INIT_SP_ADDR 17437e5708aSMacpaul Lin li $r0, 0x00000000 17537e5708aSMacpaul Lin 17637e5708aSMacpaul Lin#ifdef __PIC__ 17737e5708aSMacpaul Lin#ifdef __NDS32_N1213_43U1H__ 17837e5708aSMacpaul Lin/* __NDS32_N1213_43U1H__ implies NDS32 V0 ISA */ 17937e5708aSMacpaul Lin la $r15, board_init_f ! store function address into $r15 18037e5708aSMacpaul Lin#endif 18137e5708aSMacpaul Lin#endif 18237e5708aSMacpaul Lin j board_init_f ! jump to board_init_f() in lib/board.c 18337e5708aSMacpaul Lin 18437e5708aSMacpaul Lin/* 18537e5708aSMacpaul Lin * void relocate_code (addr_sp, gd, addr_moni) 18637e5708aSMacpaul Lin * 18737e5708aSMacpaul Lin * This "function" does not return, instead it continues in RAM 18837e5708aSMacpaul Lin * after relocating the monitor code. 18937e5708aSMacpaul Lin * 19037e5708aSMacpaul Lin */ 19137e5708aSMacpaul Lin.globl relocate_code 19237e5708aSMacpaul Linrelocate_code: 19337e5708aSMacpaul Lin move $r4, $r0 /* save addr_sp */ 19437e5708aSMacpaul Lin move $r5, $r1 /* save addr of gd */ 19537e5708aSMacpaul Lin move $r6, $r2 /* save addr of destination */ 19637e5708aSMacpaul Lin 19737e5708aSMacpaul Lin/* Set up the stack */ 19837e5708aSMacpaul Linstack_setup: 19937e5708aSMacpaul Lin move $sp, $r4 20037e5708aSMacpaul Lin 20137e5708aSMacpaul Lin la $r0, _start 20237e5708aSMacpaul Lin 20337e5708aSMacpaul Lin beq $r0, $r6, clear_bss /* skip relocation */ 20437e5708aSMacpaul Lin 20537e5708aSMacpaul Lin move $r1, $r6 /* r1 <- scratch for copy_loop */ 20637e5708aSMacpaul Lin la $r3, __bss_start 20737e5708aSMacpaul Lin sub $r3, $r3, $r0 /* r3 <- __bss_start_ofs */ 20837e5708aSMacpaul Lin add $r2, $r0, $r3 /* r2 <- source end address */ 20937e5708aSMacpaul Lin 21037e5708aSMacpaul Lincopy_loop: 21137e5708aSMacpaul Lin lwi.p $r7, [$r0], #4 21237e5708aSMacpaul Lin swi.p $r7, [$r1], #4 21337e5708aSMacpaul Lin blt $r0, $r2, copy_loop 21437e5708aSMacpaul Lin 21537e5708aSMacpaul Lin/* 21637e5708aSMacpaul Lin * fix relocations related issues 21737e5708aSMacpaul Lin */ 21837e5708aSMacpaul Linfix_relocations: 21937e5708aSMacpaul Lin l.w $r0, _TEXT_BASE /* r0 <- Text base */ 22037e5708aSMacpaul Lin sub $r9, $r6, $r0 /* r9 <- relocation offset */ 22137e5708aSMacpaul Lin 22237e5708aSMacpaul Linfix_got: 22337e5708aSMacpaul Lin/* 22437e5708aSMacpaul Lin * Now we want to update GOT. 22537e5708aSMacpaul Lin * 22637e5708aSMacpaul Lin * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object 22737e5708aSMacpaul Lin * generated by GNU ld. Skip these reserved entries from relocation. 22837e5708aSMacpaul Lin */ 22937e5708aSMacpaul Lin la $r2, __got_start /* r2 <- rel __got_start in FLASH */ 23037e5708aSMacpaul Lin add $r2, $r2, $r9 /* r2 <- rel __got_start in RAM */ 23137e5708aSMacpaul Lin la $r3, __got_end /* r3 <- rel __got_end in FLASH */ 23237e5708aSMacpaul Lin add $r3, $r3, $r9 /* r3 <- rel __got_end in RAM */ 23337e5708aSMacpaul Lin addi $r2, $r2, #8 /* skipping first two entries */ 23437e5708aSMacpaul Linfix_got_loop: 23537e5708aSMacpaul Lin lwi $r0, [$r2] /* r0 <- location in FLASH to fix up */ 23637e5708aSMacpaul Lin add $r0, $r0, $r9 /* r0 <- location fix up to RAM */ 23737e5708aSMacpaul Lin swi.p $r0, [$r2], #4 /* r0 <- store fix into .got in RAM */ 23837e5708aSMacpaul Lin blt $r2, $r3, fix_got_loop 23937e5708aSMacpaul Lin 24037e5708aSMacpaul Linclear_bss: 24137e5708aSMacpaul Lin la $r0, __bss_start /* r0 <- rel __bss_start in FLASH */ 24237e5708aSMacpaul Lin add $r0, $r0, $r9 /* r0 <- rel __bss_start in FLASH */ 24337e5708aSMacpaul Lin la $r1, __bss_end__ /* r1 <- rel __bss_end in RAM */ 24437e5708aSMacpaul Lin add $r1, $r1, $r9 /* r0 <- rel __bss_end in RAM */ 24537e5708aSMacpaul Lin li $r2, 0x00000000 /* clear */ 24637e5708aSMacpaul Lin 24737e5708aSMacpaul Linclbss_l: 24837e5708aSMacpaul Lin sw $r2, [$r0] /* clear loop... */ 24937e5708aSMacpaul Lin addi $r0, $r0, #4 25037e5708aSMacpaul Lin bne $r0, $r1, clbss_l 25137e5708aSMacpaul Lin 25237e5708aSMacpaul Lin/* 25337e5708aSMacpaul Lin * We are done. Do not return, instead branch to second part of board 25437e5708aSMacpaul Lin * initialization, now running from RAM. 25537e5708aSMacpaul Lin */ 25637e5708aSMacpaul Lincall_board_init_r: 25737e5708aSMacpaul Lin la $r0, board_init_r 25837e5708aSMacpaul Lin move $lp, $r0 /* offset of board_init_r() */ 25937e5708aSMacpaul Lin add $lp, $lp, $r9 /* real address of board_init_r() */ 26037e5708aSMacpaul Lin /* setup parameters for board_init_r */ 26137e5708aSMacpaul Lin move $r0, $r5 /* gd_t */ 26237e5708aSMacpaul Lin move $r1, $r6 /* dest_addr */ 26337e5708aSMacpaul Lin 26437e5708aSMacpaul Lin#ifdef __PIC__ 26537e5708aSMacpaul Lin#ifdef __NDS32_N1213_43U1H__ /* NDS32 V0 ISA */ 26637e5708aSMacpaul Lin move $r15, $lp /* store function address into $r15 */ 26737e5708aSMacpaul Lin#endif 26837e5708aSMacpaul Lin#endif 26937e5708aSMacpaul Lin 27037e5708aSMacpaul Lin /* jump to it ... */ 27137e5708aSMacpaul Lin jr $lp /* jump to board_init_r() */ 27237e5708aSMacpaul Lin 27337e5708aSMacpaul Lin/* 27437e5708aSMacpaul Lin * Initialize CPU critical registers 27537e5708aSMacpaul Lin * 27637e5708aSMacpaul Lin * 1. Setup control registers 27737e5708aSMacpaul Lin * 1.1 Mask all IRQs 27837e5708aSMacpaul Lin * 1.2 Flush cache and TLB 27937e5708aSMacpaul Lin * 1.3 Disable MMU and cache 28037e5708aSMacpaul Lin * 2. Setup memory timing 28137e5708aSMacpaul Lin */ 28237e5708aSMacpaul Lin 28337e5708aSMacpaul Lincpu_init_crit: 28437e5708aSMacpaul Lin 28537e5708aSMacpaul Lin move $r0, $lp /* push ra */ 28637e5708aSMacpaul Lin 28737e5708aSMacpaul Lin /* Disable Interrupts by clear GIE in $PSW reg */ 28837e5708aSMacpaul Lin setgie.d 28937e5708aSMacpaul Lin 29037e5708aSMacpaul Lin /* Flush caches and TLB */ 29137e5708aSMacpaul Lin /* Invalidate caches */ 29237e5708aSMacpaul Lin bal invalidate_icac 29337e5708aSMacpaul Lin bal invalidate_dcac 29437e5708aSMacpaul Lin 29537e5708aSMacpaul Lin /* Flush TLB */ 29637e5708aSMacpaul Lin mfsr $p0, $MMU_CFG 29737e5708aSMacpaul Lin andi $p0, $p0, 0x3 ! MMPS 29837e5708aSMacpaul Lin li $p1, 0x2 ! TLB MMU 29937e5708aSMacpaul Lin bne $p0, $p1, 1f 30037e5708aSMacpaul Lin tlbop flushall ! Flush TLB 30137e5708aSMacpaul Lin 30237e5708aSMacpaul Lin1: 30337e5708aSMacpaul Lin ! Disable MMU, Dcache 30437e5708aSMacpaul Lin ! Whitiger is MMU disabled when reset 30537e5708aSMacpaul Lin ! Disable the D$ 30637e5708aSMacpaul Lin mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg 30737e5708aSMacpaul Lin li $p1, DIS_DCAC 30837e5708aSMacpaul Lin and $p0, $p0, $p1 ! Set DC_EN bit 30937e5708aSMacpaul Lin mtsr $p0, MR_CAC_CTL ! write back the $CACHE_CTL reg 31037e5708aSMacpaul Lin isb 31137e5708aSMacpaul Lin 31237e5708aSMacpaul Lin move $lp, $r0 31337e5708aSMacpaul Lin2: 31437e5708aSMacpaul Lin ret 31537e5708aSMacpaul Lin 31637e5708aSMacpaul Lin#ifndef CONFIG_SKIP_LOWLEVEL_INIT 31737e5708aSMacpaul Linload_lowlevel_init: 31837e5708aSMacpaul Lin la $r6, lowlevel_init 31937e5708aSMacpaul Lin la $r7, load_lli + 4 32037e5708aSMacpaul Lin sub $p0, $r6, $r7 32137e5708aSMacpaul Lin add $p0, $p0, $lp 32237e5708aSMacpaul Linret 32337e5708aSMacpaul Lin#endif 32437e5708aSMacpaul Lin 32537e5708aSMacpaul Lin#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG 32637e5708aSMacpaul Linload_turnoff_watchdog: 32737e5708aSMacpaul Lin la $r6, turnoff_watchdog 32837e5708aSMacpaul Lin la $r7, turnoff_wtdog + 4 32937e5708aSMacpaul Lin sub $p0, $r6, $r7 33037e5708aSMacpaul Lin add $p0, $p0, $lp 33137e5708aSMacpaul Linret 33237e5708aSMacpaul Lin#endif 33337e5708aSMacpaul Lin 33437e5708aSMacpaul Lin/* 33537e5708aSMacpaul Lin * Invalidate I$ 33637e5708aSMacpaul Lin */ 33737e5708aSMacpaul Lininvalidate_icac: 33837e5708aSMacpaul Lin ! read $cr1(I CAC/MEM cfg. reg.) configuration 33937e5708aSMacpaul Lin mfsr $t0, CR_ICAC_MEM 34037e5708aSMacpaul Lin 34137e5708aSMacpaul Lin ! Get the ISZ field 34237e5708aSMacpaul Lin andi $p0, $t0, ICAC_MEM_KBF_ISZ 34337e5708aSMacpaul Lin 34437e5708aSMacpaul Lin ! if $p0=0, then no I CAC existed 34537e5708aSMacpaul Lin beqz $p0, end_flush_icache 34637e5708aSMacpaul Lin 34737e5708aSMacpaul Lin ! get $p0 the index of I$ block 34837e5708aSMacpaul Lin srli $p0, $p0, 6 34937e5708aSMacpaul Lin 35037e5708aSMacpaul Lin ! $t1= bit width of I cache line size(ISZ) 35137e5708aSMacpaul Lin addi $t1, $p0, 2 35237e5708aSMacpaul Lin 35337e5708aSMacpaul Lin li $t4, 1 35437e5708aSMacpaul Lin sll $t5, $t4, $t1 ! get $t5 cache line size 35537e5708aSMacpaul Lin andi $p1, $t0, ICAC_MEM_KBF_ISET ! get the ISET field 35637e5708aSMacpaul Lin addi $t2, $p1, 6 ! $t2= bit width of ISET 35737e5708aSMacpaul Lin andi $p1, $t0, ICAC_MEM_KBF_IWAY ! get bitfield of Iway 35837e5708aSMacpaul Lin srli $p1, $p1, 3 35937e5708aSMacpaul Lin addi $p1, $p1, 1 ! then $p1 is I way number 36037e5708aSMacpaul Lin add $t3, $t2, $t1 ! SHIFT 36137e5708aSMacpaul Lin sll $p1, $p1, $t3 ! GET the total cache size 36237e5708aSMacpaul LinICAC_LOOP: 36337e5708aSMacpaul Lin sub $p1, $p1, $t5 36437e5708aSMacpaul Lin cctl $p1, L1I_IX_INVAL 36537e5708aSMacpaul Lin bnez $p1, ICAC_LOOP 36637e5708aSMacpaul Linend_flush_icache: 36737e5708aSMacpaul Lin ret 36837e5708aSMacpaul Lin 36937e5708aSMacpaul Lin/* 37037e5708aSMacpaul Lin * Invalidate D$ 37137e5708aSMacpaul Lin */ 37237e5708aSMacpaul Lininvalidate_dcac: 37337e5708aSMacpaul Lin ! read $cr2(D CAC/MEM cfg. reg.) configuration 37437e5708aSMacpaul Lin mfsr $t0, CR_DCAC_MEM 37537e5708aSMacpaul Lin 37637e5708aSMacpaul Lin ! Get the DSZ field 37737e5708aSMacpaul Lin andi $p0, $t0, DCAC_MEM_KBF_DSZ 37837e5708aSMacpaul Lin 37937e5708aSMacpaul Lin ! if $p0=0, then no D CAC existed 38037e5708aSMacpaul Lin beqz $p0, end_flush_dcache 38137e5708aSMacpaul Lin 38237e5708aSMacpaul Lin ! get $p0 the index of D$ block 38337e5708aSMacpaul Lin srli $p0, $p0, 6 38437e5708aSMacpaul Lin 38537e5708aSMacpaul Lin ! $t1= bit width of D cache line size(DSZ) 38637e5708aSMacpaul Lin addi $t1, $p0, 2 38737e5708aSMacpaul Lin 38837e5708aSMacpaul Lin li $t4, 1 38937e5708aSMacpaul Lin sll $t5, $t4, $t1 ! get $t5 cache line size 39037e5708aSMacpaul Lin andi $p1, $t0, DCAC_MEM_KBF_DSET ! get the DSET field 39137e5708aSMacpaul Lin addi $t2, $p1, 6 ! $t2= bit width of DSET 39237e5708aSMacpaul Lin andi $p1, $t0, DCAC_MEM_KBF_DWAY ! get bitfield of D way 39337e5708aSMacpaul Lin srli $p1, $p1, 3 39437e5708aSMacpaul Lin addi $p1, $p1, 1 ! then $p1 is D way number 39537e5708aSMacpaul Lin add $t3, $t2, $t1 ! SHIFT 39637e5708aSMacpaul Lin sll $p1, $p1, $t3 ! GET the total cache size 39737e5708aSMacpaul LinDCAC_LOOP: 39837e5708aSMacpaul Lin sub $p1, $p1, $t5 39937e5708aSMacpaul Lin cctl $p1, L1D_IX_INVAL 40037e5708aSMacpaul Lin bnez $p1, DCAC_LOOP 40137e5708aSMacpaul Linend_flush_dcache: 40237e5708aSMacpaul Lin ret 40337e5708aSMacpaul Lin 40437e5708aSMacpaul Lin/* 40537e5708aSMacpaul Lin * Interrupt handling 40637e5708aSMacpaul Lin */ 40737e5708aSMacpaul Lin 40837e5708aSMacpaul Lin/* 40937e5708aSMacpaul Lin * exception handlers 41037e5708aSMacpaul Lin */ 41137e5708aSMacpaul Lin .align 5 41237e5708aSMacpaul Lin 41337e5708aSMacpaul Lin.macro SAVE_ALL 41437e5708aSMacpaul Lin ! FIXME: Other way to get PC? 41537e5708aSMacpaul Lin ! FIXME: Update according to the newest spec!! 41637e5708aSMacpaul Lin1: 41737e5708aSMacpaul Lin la $r28, 1 41837e5708aSMacpaul Lin push $r28 41937e5708aSMacpaul Lin mfsr $r28, PSW ! $PSW 42037e5708aSMacpaul Lin push $r28 42137e5708aSMacpaul Lin mfsr $r28, EIT_EVA ! $ir1 $EVA 42237e5708aSMacpaul Lin push $r28 42337e5708aSMacpaul Lin mfsr $r28, EIT_ITYPE ! $ir2 $ITYPE 42437e5708aSMacpaul Lin push $r28 42537e5708aSMacpaul Lin mfsr $r28, EIT_MACH_ERR ! $ir3 Mach Error 42637e5708aSMacpaul Lin push $r28 42737e5708aSMacpaul Lin mfsr $r28, EIT_INTR_PSW ! $ir5 $IPSW 42837e5708aSMacpaul Lin push $r28 42937e5708aSMacpaul Lin mfsr $r28, EIT_PREV_IPSW ! $ir6 prev $IPSW 43037e5708aSMacpaul Lin push $r28 43137e5708aSMacpaul Lin mfsr $r28, EIT_PREV_EVA ! $ir7 prev $EVA 43237e5708aSMacpaul Lin push $r28 43337e5708aSMacpaul Lin mfsr $r28, EIT_PREV_ITYPE ! $ir8 prev $ITYPE 43437e5708aSMacpaul Lin push $r28 43537e5708aSMacpaul Lin mfsr $r28, EIT_INTR_PC ! $ir9 Interruption PC 43637e5708aSMacpaul Lin push $r28 43737e5708aSMacpaul Lin mfsr $r28, EIT_PREV_IPC ! $ir10 prev INTR_PC 43837e5708aSMacpaul Lin push $r28 43937e5708aSMacpaul Lin mfsr $r28, EIT_OVL_INTR_PC ! $ir11 Overflowed INTR_PC 44037e5708aSMacpaul Lin push $r28 44137e5708aSMacpaul Lin mfusr $r28, $d1.lo 44237e5708aSMacpaul Lin push $r28 44337e5708aSMacpaul Lin mfusr $r28, $d1.hi 44437e5708aSMacpaul Lin push $r28 44537e5708aSMacpaul Lin mfusr $r28, $d0.lo 44637e5708aSMacpaul Lin push $r28 44737e5708aSMacpaul Lin mfusr $r28, $d0.hi 44837e5708aSMacpaul Lin push $r28 44937e5708aSMacpaul Lin pushm $r0, $r30 ! store $sp-$r31, ra-$r30, $gp-$r29, $r28-$fp 45037e5708aSMacpaul Lin addi $sp, $sp, -4 ! make room for implicit pt_regs parameters 45137e5708aSMacpaul Lin.endm 45237e5708aSMacpaul Lin 45337e5708aSMacpaul Lin .align 5 45437e5708aSMacpaul Lintlb_fill: 45537e5708aSMacpaul Lin SAVE_ALL 45637e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 45737e5708aSMacpaul Lin li $r1, 1 ! Determine interruption type 45837e5708aSMacpaul Lin bal do_interruption 45937e5708aSMacpaul Lin 46037e5708aSMacpaul Lin .align 5 46137e5708aSMacpaul Lintlb_not_present: 46237e5708aSMacpaul Lin SAVE_ALL 46337e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 46437e5708aSMacpaul Lin li $r1, 2 ! Determine interruption type 46537e5708aSMacpaul Lin bal do_interruption 46637e5708aSMacpaul Lin 46737e5708aSMacpaul Lin .align 5 46837e5708aSMacpaul Lintlb_misc: 46937e5708aSMacpaul Lin SAVE_ALL 47037e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 47137e5708aSMacpaul Lin li $r1, 3 ! Determine interruption type 47237e5708aSMacpaul Lin bal do_interruption 47337e5708aSMacpaul Lin 47437e5708aSMacpaul Lin .align 5 47537e5708aSMacpaul Lintlb_vlpt_miss: 47637e5708aSMacpaul Lin SAVE_ALL 47737e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 47837e5708aSMacpaul Lin li $r1, 4 ! Determine interruption type 47937e5708aSMacpaul Lin bal do_interruption 48037e5708aSMacpaul Lin 48137e5708aSMacpaul Lin .align 5 482*1a05bb3cSMacpaul Linmachine_error: 48337e5708aSMacpaul Lin SAVE_ALL 48437e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 48537e5708aSMacpaul Lin li $r1, 5 ! Determine interruption type 48637e5708aSMacpaul Lin bal do_interruption 48737e5708aSMacpaul Lin 48837e5708aSMacpaul Lin .align 5 48937e5708aSMacpaul Lindebug: 49037e5708aSMacpaul Lin SAVE_ALL 49137e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 49237e5708aSMacpaul Lin li $r1, 6 ! Determine interruption type 49337e5708aSMacpaul Lin bal do_interruption 49437e5708aSMacpaul Lin 49537e5708aSMacpaul Lin .align 5 49637e5708aSMacpaul Lingeneral_exception: 49737e5708aSMacpaul Lin SAVE_ALL 49837e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 49937e5708aSMacpaul Lin li $r1, 7 ! Determine interruption type 50037e5708aSMacpaul Lin bal do_interruption 50137e5708aSMacpaul Lin 50237e5708aSMacpaul Lin .align 5 503*1a05bb3cSMacpaul Linsyscall: 50437e5708aSMacpaul Lin SAVE_ALL 50537e5708aSMacpaul Lin move $r0, $sp ! To get the kernel stack 50637e5708aSMacpaul Lin li $r1, 8 ! Determine interruption type 50737e5708aSMacpaul Lin bal do_interruption 50837e5708aSMacpaul Lin 50937e5708aSMacpaul Lin .align 5 510*1a05bb3cSMacpaul Lininternal_interrupt: 511*1a05bb3cSMacpaul Lin SAVE_ALL 512*1a05bb3cSMacpaul Lin move $r0, $sp ! To get the kernel stack 513*1a05bb3cSMacpaul Lin li $r1, 9 ! Determine interruption type 514*1a05bb3cSMacpaul Lin bal do_interruption 515*1a05bb3cSMacpaul Lin 516*1a05bb3cSMacpaul Lin .align 5 517*1a05bb3cSMacpaul Linsoftware_interrupt: 518*1a05bb3cSMacpaul Lin SAVE_ALL 519*1a05bb3cSMacpaul Lin move $r0, $sp ! To get the kernel stack 520*1a05bb3cSMacpaul Lin li $r1, 10 ! Determine interruption type 521*1a05bb3cSMacpaul Lin bal do_interruption 522*1a05bb3cSMacpaul Lin 523*1a05bb3cSMacpaul Lin .align 5 52437e5708aSMacpaul Lin 52537e5708aSMacpaul Lin/* 52637e5708aSMacpaul Lin * void reset_cpu(ulong addr); 52737e5708aSMacpaul Lin * $r0: input address to jump to 52837e5708aSMacpaul Lin */ 52937e5708aSMacpaul Lin.globl reset_cpu 53037e5708aSMacpaul Linreset_cpu: 53137e5708aSMacpaul Lin/* No need to disable MMU because we never enable it */ 53237e5708aSMacpaul Lin 53337e5708aSMacpaul Lin bal invalidate_icac 53437e5708aSMacpaul Lin bal invalidate_dcac 53537e5708aSMacpaul Lin mfsr $p0, $MMU_CFG 53637e5708aSMacpaul Lin andi $p0, $p0, 0x3 ! MMPS 53737e5708aSMacpaul Lin li $p1, 0x2 ! TLB MMU 53837e5708aSMacpaul Lin bne $p0, $p1, 1f 53937e5708aSMacpaul Lin tlbop flushall ! Flush TLB 54037e5708aSMacpaul Lin1: 54137e5708aSMacpaul Lin mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg 54237e5708aSMacpaul Lin li $p1, DIS_DCAC 54337e5708aSMacpaul Lin and $p0, $p0, $p1 ! Clear the DC_EN bit 54437e5708aSMacpaul Lin mtsr $p0, MR_CAC_CTL ! Write back the $CACHE_CTL reg 54537e5708aSMacpaul Lin br $r0 ! Jump to the input address 546