// SPDX-License-Identifier: GPL-2.0 // Copyright (C) 2005-2017 Andes Technology Corporation #include #include #include #include #include #include #include #include #ifdef CONFIG_CPU_BIG_ENDIAN #define OF_DT_MAGIC 0xd00dfeed #else #define OF_DT_MAGIC 0xedfe0dd0 #endif .globl swapper_pg_dir .equ swapper_pg_dir, TEXTADDR - 0x4000 /* * Kernel startup entry point. */ .section ".head.text", "ax" .type _stext, %function ENTRY(_stext) setgie.d ! Disable interrupt isb /* * Disable I/D-cache and enable it at a proper time */ mfsr $r0, $mr8 li $r1, #~(CACHE_CTL_mskIC_EN|CACHE_CTL_mskDC_EN) and $r0, $r0, $r1 mtsr $r0, $mr8 /* * Process device tree blob */ andi $r0,$r2,#0x3 li $r10, 0 bne $r0, $r10, _nodtb lwi $r0, [$r2] li $r1, OF_DT_MAGIC bne $r0, $r1, _nodtb move $r10, $r2 _nodtb: /* * Create a temporary mapping area for booting, before start_kernel */ sethi $r4, hi20(swapper_pg_dir) li $p0, (PAGE_OFFSET - PHYS_OFFSET) sub $r4, $r4, $p0 tlbop FlushAll ! invalidate TLB\n" isb mtsr $r4, $L1_PPTB ! load page table pointer\n" #ifdef CONFIG_CPU_DCACHE_DISABLE #define MMU_CTL_NTCC MMU_CTL_CACHEABLE_NON #else #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH #define MMU_CTL_NTCC MMU_CTL_CACHEABLE_WT #else #define MMU_CTL_NTCC MMU_CTL_CACHEABLE_WB #endif #endif /* set NTC cacheability, mutliple page size in use */ mfsr $r3, $MMU_CTL #if CONFIG_MEMORY_START >= 0xc0000000 ori $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC3) #elif CONFIG_MEMORY_START >= 0x80000000 ori $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC2) #elif CONFIG_MEMORY_START >= 0x40000000 ori $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC1) #else ori $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC0) #endif #ifdef CONFIG_ANDES_PAGE_SIZE_4KB ori $r3, $r3, #(MMU_CTL_mskMPZIU) #else ori $r3, $r3, #(MMU_CTL_mskMPZIU|MMU_CTL_D8KB) #endif #ifdef CONFIG_HW_SUPPORT_UNALIGNMENT_ACCESS li $r0, #MMU_CTL_UNA or $r3, $r3, $r0 #endif mtsr $r3, $MMU_CTL isb /* set page size and size of kernel image */ mfsr $r0, $MMU_CFG srli $r3, $r0, MMU_CFG_offfEPSZ zeb $r3, $r3 bnez $r3, _extra_page_size_support #ifdef CONFIG_ANDES_PAGE_SIZE_4KB li $r5, #SZ_4K ! Use 4KB page size #else li $r5, #SZ_8K ! Use 8KB page size li $r3, #1 #endif mtsr $r3, $TLB_MISC b _image_size_check _extra_page_size_support: ! Use epzs pages size clz $r6, $r3 subri $r2, $r6, #31 li $r3, #1 sll $r3, $r3, $r2 /* MMU_CFG.EPSZ value -> meaning */ mul $r5, $r3, $r3 slli $r5, $r5, #14 /* MMU_CFG.EPSZ -> TLB_MISC.ACC_PSZ */ addi $r3, $r2, #0x2 mtsr $r3, $TLB_MISC _image_size_check: /* calculate the image maximum size accepted by TLB config */ andi $r6, $r0, MMU_CFG_mskTBW andi $r0, $r0, MMU_CFG_mskTBS srli $r6, $r6, MMU_CFG_offTBW srli $r0, $r0, MMU_CFG_offTBS /* * we just map the kernel to the maximum way - 1 of tlb * reserver one way for UART VA mapping * it will cause page fault if UART mapping cover the kernel mapping * * direct mapping is not supported now. */ li $r2, 't' beqz $r6, __error ! MMU_CFG.TBW = 0 is direct mappin addi $r0, $r0, #0x2 ! MMU_CFG.TBS value -> meaning sll $r0, $r6, $r0 ! entries = k-way * n-set mul $r6, $r0, $r5 ! max size = entries * page size /* check kernel image size */ la $r3, (_end - PAGE_OFFSET) li $r2, 's' bgt $r3, $r6, __error li $r2, #(PHYS_OFFSET + TLB_DATA_kernel_text_attr) li $r3, PAGE_OFFSET add $r6, $r6, $r3 _tlb: mtsr $r3, $TLB_VPN dsb tlbop $r2, RWR isb add $r3, $r3, $r5 add $r2, $r2, $r5 bgt $r6, $r3, _tlb mfsr $r3, $TLB_MISC ! setup access page size li $r2, #~0xf and $r3, $r3, $r2 #ifdef CONFIG_ANDES_PAGE_SIZE_8KB ori $r3, $r3, #0x1 #endif mtsr $r3, $TLB_MISC mfsr $r0, $MISC_CTL ! Enable BTB and RTP and shadow sp ori $r0, $r0, #MISC_init mtsr $r0, $MISC_CTL mfsr $p1, $PSW li $r15, #~PSW_clr ! clear WBNA|DME|IME|DT|IT|POM|INTL|GIE and $p1, $p1, $r15 ori $p1, $p1, #PSW_init mtsr $p1, $IPSW ! when iret, it will automatically enable MMU la $lp, __mmap_switched mtsr $lp, $IPC iret nop .type __switch_data, %object __switch_data: .long __bss_start ! $r6 .long _end ! $r7 .long __atags_pointer ! $atag_pointer .long init_task ! $r9, move to $r25 .long init_thread_union + THREAD_SIZE ! $sp /* * The following fragment of code is executed with the MMU on in MMU mode, * and uses absolute addresses; this is not position independent. */ .align .type __mmap_switched, %function __mmap_switched: la $r3, __switch_data lmw.bim $r6, [$r3], $r9, #0b0001 move $r25, $r9 move $fp, #0 ! Clear BSS (and zero $fp) beq $r7, $r6, _RRT 1: swi.bi $fp, [$r6], #4 bne $r7, $r6, 1b swi $r10, [$r8] _RRT: b start_kernel __error: b __error