123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- // SPDX-License-Identifier: GPL-2.0
- // Copyright (C) 2005-2017 Andes Technology Corporation
- #include <linux/linkage.h>
- #include <linux/init.h>
- #include <asm/ptrace.h>
- #include <asm/asm-offsets.h>
- #include <asm/page.h>
- #include <asm/pgtable.h>
- #include <asm/sizes.h>
- #include <asm/thread_info.h>
- #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
|