18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// Copyright (C) 2005-2017 Andes Technology Corporation 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <linux/linkage.h> 58c2ecf20Sopenharmony_ci#include <linux/init.h> 68c2ecf20Sopenharmony_ci#include <linux/pgtable.h> 78c2ecf20Sopenharmony_ci#include <asm/ptrace.h> 88c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h> 98c2ecf20Sopenharmony_ci#include <asm/page.h> 108c2ecf20Sopenharmony_ci#include <linux/sizes.h> 118c2ecf20Sopenharmony_ci#include <asm/thread_info.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_BIG_ENDIAN 148c2ecf20Sopenharmony_ci#define OF_DT_MAGIC 0xd00dfeed 158c2ecf20Sopenharmony_ci#else 168c2ecf20Sopenharmony_ci#define OF_DT_MAGIC 0xedfe0dd0 178c2ecf20Sopenharmony_ci#endif 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci .globl swapper_pg_dir 208c2ecf20Sopenharmony_ci .equ swapper_pg_dir, TEXTADDR - 0x4000 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* 238c2ecf20Sopenharmony_ci * Kernel startup entry point. 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_ci .section ".head.text", "ax" 268c2ecf20Sopenharmony_ci .type _stext, %function 278c2ecf20Sopenharmony_ciENTRY(_stext) 288c2ecf20Sopenharmony_ci setgie.d ! Disable interrupt 298c2ecf20Sopenharmony_ci isb 308c2ecf20Sopenharmony_ci/* 318c2ecf20Sopenharmony_ci * Disable I/D-cache and enable it at a proper time 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ci mfsr $r0, $mr8 348c2ecf20Sopenharmony_ci li $r1, #~(CACHE_CTL_mskIC_EN|CACHE_CTL_mskDC_EN) 358c2ecf20Sopenharmony_ci and $r0, $r0, $r1 368c2ecf20Sopenharmony_ci mtsr $r0, $mr8 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* 398c2ecf20Sopenharmony_ci * Process device tree blob 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_ci andi $r0,$r2,#0x3 428c2ecf20Sopenharmony_ci li $r10, 0 438c2ecf20Sopenharmony_ci bne $r0, $r10, _nodtb 448c2ecf20Sopenharmony_ci lwi $r0, [$r2] 458c2ecf20Sopenharmony_ci li $r1, OF_DT_MAGIC 468c2ecf20Sopenharmony_ci bne $r0, $r1, _nodtb 478c2ecf20Sopenharmony_ci move $r10, $r2 488c2ecf20Sopenharmony_ci_nodtb: 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* 518c2ecf20Sopenharmony_ci * Create a temporary mapping area for booting, before start_kernel 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_ci sethi $r4, hi20(swapper_pg_dir) 548c2ecf20Sopenharmony_ci li $p0, (PAGE_OFFSET - PHYS_OFFSET) 558c2ecf20Sopenharmony_ci sub $r4, $r4, $p0 568c2ecf20Sopenharmony_ci tlbop FlushAll ! invalidate TLB\n" 578c2ecf20Sopenharmony_ci isb 588c2ecf20Sopenharmony_ci mtsr $r4, $L1_PPTB ! load page table pointer\n" 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_DCACHE_DISABLE 618c2ecf20Sopenharmony_ci #define MMU_CTL_NTCC MMU_CTL_CACHEABLE_NON 628c2ecf20Sopenharmony_ci#else 638c2ecf20Sopenharmony_ci #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 648c2ecf20Sopenharmony_ci #define MMU_CTL_NTCC MMU_CTL_CACHEABLE_WT 658c2ecf20Sopenharmony_ci #else 668c2ecf20Sopenharmony_ci #define MMU_CTL_NTCC MMU_CTL_CACHEABLE_WB 678c2ecf20Sopenharmony_ci #endif 688c2ecf20Sopenharmony_ci#endif 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* set NTC cacheability, mutliple page size in use */ 718c2ecf20Sopenharmony_ci mfsr $r3, $MMU_CTL 728c2ecf20Sopenharmony_ci#if CONFIG_MEMORY_START >= 0xc0000000 738c2ecf20Sopenharmony_ci ori $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC3) 748c2ecf20Sopenharmony_ci#elif CONFIG_MEMORY_START >= 0x80000000 758c2ecf20Sopenharmony_ci ori $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC2) 768c2ecf20Sopenharmony_ci#elif CONFIG_MEMORY_START >= 0x40000000 778c2ecf20Sopenharmony_ci ori $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC1) 788c2ecf20Sopenharmony_ci#else 798c2ecf20Sopenharmony_ci ori $r3, $r3, (MMU_CTL_NTCC << MMU_CTL_offNTC0) 808c2ecf20Sopenharmony_ci#endif 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci#ifdef CONFIG_ANDES_PAGE_SIZE_4KB 838c2ecf20Sopenharmony_ci ori $r3, $r3, #(MMU_CTL_mskMPZIU) 848c2ecf20Sopenharmony_ci#else 858c2ecf20Sopenharmony_ci ori $r3, $r3, #(MMU_CTL_mskMPZIU|MMU_CTL_D8KB) 868c2ecf20Sopenharmony_ci#endif 878c2ecf20Sopenharmony_ci#ifdef CONFIG_HW_SUPPORT_UNALIGNMENT_ACCESS 888c2ecf20Sopenharmony_ci li $r0, #MMU_CTL_UNA 898c2ecf20Sopenharmony_ci or $r3, $r3, $r0 908c2ecf20Sopenharmony_ci#endif 918c2ecf20Sopenharmony_ci mtsr $r3, $MMU_CTL 928c2ecf20Sopenharmony_ci isb 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/* set page size and size of kernel image */ 958c2ecf20Sopenharmony_ci mfsr $r0, $MMU_CFG 968c2ecf20Sopenharmony_ci srli $r3, $r0, MMU_CFG_offfEPSZ 978c2ecf20Sopenharmony_ci zeb $r3, $r3 988c2ecf20Sopenharmony_ci bnez $r3, _extra_page_size_support 998c2ecf20Sopenharmony_ci#ifdef CONFIG_ANDES_PAGE_SIZE_4KB 1008c2ecf20Sopenharmony_ci li $r5, #SZ_4K ! Use 4KB page size 1018c2ecf20Sopenharmony_ci#else 1028c2ecf20Sopenharmony_ci li $r5, #SZ_8K ! Use 8KB page size 1038c2ecf20Sopenharmony_ci li $r3, #1 1048c2ecf20Sopenharmony_ci#endif 1058c2ecf20Sopenharmony_ci mtsr $r3, $TLB_MISC 1068c2ecf20Sopenharmony_ci b _image_size_check 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci_extra_page_size_support: ! Use epzs pages size 1098c2ecf20Sopenharmony_ci clz $r6, $r3 1108c2ecf20Sopenharmony_ci subri $r2, $r6, #31 1118c2ecf20Sopenharmony_ci li $r3, #1 1128c2ecf20Sopenharmony_ci sll $r3, $r3, $r2 1138c2ecf20Sopenharmony_ci /* MMU_CFG.EPSZ value -> meaning */ 1148c2ecf20Sopenharmony_ci mul $r5, $r3, $r3 1158c2ecf20Sopenharmony_ci slli $r5, $r5, #14 1168c2ecf20Sopenharmony_ci /* MMU_CFG.EPSZ -> TLB_MISC.ACC_PSZ */ 1178c2ecf20Sopenharmony_ci addi $r3, $r2, #0x2 1188c2ecf20Sopenharmony_ci mtsr $r3, $TLB_MISC 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci_image_size_check: 1218c2ecf20Sopenharmony_ci /* calculate the image maximum size accepted by TLB config */ 1228c2ecf20Sopenharmony_ci andi $r6, $r0, MMU_CFG_mskTBW 1238c2ecf20Sopenharmony_ci andi $r0, $r0, MMU_CFG_mskTBS 1248c2ecf20Sopenharmony_ci srli $r6, $r6, MMU_CFG_offTBW 1258c2ecf20Sopenharmony_ci srli $r0, $r0, MMU_CFG_offTBS 1268c2ecf20Sopenharmony_ci addi $r6, $r6, #0x1 ! MMU_CFG.TBW value -> meaning 1278c2ecf20Sopenharmony_ci addi $r0, $r0, #0x2 ! MMU_CFG.TBS value -> meaning 1288c2ecf20Sopenharmony_ci sll $r0, $r6, $r0 ! entries = k-way * n-set 1298c2ecf20Sopenharmony_ci mul $r6, $r0, $r5 ! max size = entries * page size 1308c2ecf20Sopenharmony_ci /* check kernel image size */ 1318c2ecf20Sopenharmony_ci la $r3, (_end - PAGE_OFFSET) 1328c2ecf20Sopenharmony_ci bgt $r3, $r6, __error 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci li $r2, #(PHYS_OFFSET + TLB_DATA_kernel_text_attr) 1358c2ecf20Sopenharmony_ci li $r3, PAGE_OFFSET 1368c2ecf20Sopenharmony_ci add $r6, $r6, $r3 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci_tlb: 1398c2ecf20Sopenharmony_ci mtsr $r3, $TLB_VPN 1408c2ecf20Sopenharmony_ci dsb 1418c2ecf20Sopenharmony_ci tlbop $r2, RWR 1428c2ecf20Sopenharmony_ci isb 1438c2ecf20Sopenharmony_ci add $r3, $r3, $r5 1448c2ecf20Sopenharmony_ci add $r2, $r2, $r5 1458c2ecf20Sopenharmony_ci bgt $r6, $r3, _tlb 1468c2ecf20Sopenharmony_ci mfsr $r3, $TLB_MISC ! setup access page size 1478c2ecf20Sopenharmony_ci li $r2, #~0xf 1488c2ecf20Sopenharmony_ci and $r3, $r3, $r2 1498c2ecf20Sopenharmony_ci#ifdef CONFIG_ANDES_PAGE_SIZE_8KB 1508c2ecf20Sopenharmony_ci ori $r3, $r3, #0x1 1518c2ecf20Sopenharmony_ci#endif 1528c2ecf20Sopenharmony_ci mtsr $r3, $TLB_MISC 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci mfsr $r0, $MISC_CTL ! Enable BTB, RTP, shadow sp, and HW_PRE 1558c2ecf20Sopenharmony_ci ori $r0, $r0, #MISC_init 1568c2ecf20Sopenharmony_ci mtsr $r0, $MISC_CTL 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci mfsr $p1, $PSW 1598c2ecf20Sopenharmony_ci li $r15, #~PSW_clr ! clear WBNA|DME|IME|DT|IT|POM|INTL|GIE 1608c2ecf20Sopenharmony_ci and $p1, $p1, $r15 1618c2ecf20Sopenharmony_ci ori $p1, $p1, #PSW_init 1628c2ecf20Sopenharmony_ci mtsr $p1, $IPSW ! when iret, it will automatically enable MMU 1638c2ecf20Sopenharmony_ci la $lp, __mmap_switched 1648c2ecf20Sopenharmony_ci mtsr $lp, $IPC 1658c2ecf20Sopenharmony_ci iret 1668c2ecf20Sopenharmony_ci nop 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci .type __switch_data, %object 1698c2ecf20Sopenharmony_ci__switch_data: 1708c2ecf20Sopenharmony_ci .long __bss_start ! $r6 1718c2ecf20Sopenharmony_ci .long _end ! $r7 1728c2ecf20Sopenharmony_ci .long __atags_pointer ! $atag_pointer 1738c2ecf20Sopenharmony_ci .long init_task ! $r9, move to $r25 1748c2ecf20Sopenharmony_ci .long init_thread_union + THREAD_SIZE ! $sp 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci/* 1788c2ecf20Sopenharmony_ci * The following fragment of code is executed with the MMU on in MMU mode, 1798c2ecf20Sopenharmony_ci * and uses absolute addresses; this is not position independent. 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_ci .align 1828c2ecf20Sopenharmony_ci .type __mmap_switched, %function 1838c2ecf20Sopenharmony_ci__mmap_switched: 1848c2ecf20Sopenharmony_ci la $r3, __switch_data 1858c2ecf20Sopenharmony_ci lmw.bim $r6, [$r3], $r9, #0b0001 1868c2ecf20Sopenharmony_ci move $r25, $r9 1878c2ecf20Sopenharmony_ci move $fp, #0 ! Clear BSS (and zero $fp) 1888c2ecf20Sopenharmony_ci beq $r7, $r6, _RRT 1898c2ecf20Sopenharmony_ci1: swi.bi $fp, [$r6], #4 1908c2ecf20Sopenharmony_ci bne $r7, $r6, 1b 1918c2ecf20Sopenharmony_ci swi $r10, [$r8] 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci_RRT: 1948c2ecf20Sopenharmony_ci b start_kernel 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci__error: 1978c2ecf20Sopenharmony_ci b __error 198