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