| /* SPDX-License-Identifier: GPL-2.0 */ |
| /* |
| * Copyright (C) 2020 MediaTek Inc. |
| * |
| * Author: Weijie Gao <weijie.gao@mediatek.com> |
| */ |
| |
| #include <config.h> |
| #include <asm-offsets.h> |
| #include <asm/cacheops.h> |
| #include <asm/regdef.h> |
| #include <asm/mipsregs.h> |
| #include <asm/addrspace.h> |
| #include <asm/asm.h> |
| #include "mt7628.h" |
| |
| /* Set temporary stack address range */ |
| #ifndef CONFIG_SYS_INIT_SP_ADDR |
| #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + \ |
| CONFIG_SYS_INIT_SP_OFFSET) |
| #endif |
| |
| #define CACHE_STACK_SIZE 0x4000 |
| #define CACHE_STACK_BASE (CONFIG_SYS_INIT_SP_ADDR - CACHE_STACK_SIZE) |
| |
| #define DELAY_USEC(us) ((58 * (us)) / 3) |
| |
| .set noreorder |
| |
| LEAF(mips_sram_init) |
| #ifndef CONFIG_SKIP_LOWLEVEL_INIT |
| /* Setup CPU PLL */ |
| li t0, DELAY_USEC(1000000) |
| li t1, KSEG1ADDR(SYSCTL_BASE + SYSCTL_ROM_STATUS_REG) |
| li t2, KSEG1ADDR(SYSCTL_BASE + SYSCTL_CLKCFG0_REG) |
| |
| _check_rom_status: |
| lw t3, 0(t1) |
| andi t3, t3, 1 |
| bnez t3, _rom_normal |
| subu t0, t0, 1 |
| bnez t0, _check_rom_status |
| nop |
| |
| lw t3, 0(t2) |
| ori t3, (CPU_PLL_FROM_BBP | CPU_PLL_FROM_XTAL) |
| xori t3, CPU_PLL_FROM_BBP |
| b _cpu_pll_done |
| nop |
| |
| _rom_normal: |
| lw t3, 0(t2) |
| ori t3, (CPU_PLL_FROM_BBP | CPU_PLL_FROM_XTAL | \ |
| DIS_BBP_SLEEP | EN_BBP_CLK) |
| xori t3, (CPU_PLL_FROM_BBP | CPU_PLL_FROM_XTAL) |
| |
| _cpu_pll_done: |
| sw t3, 0(t2) |
| |
| li t2, KSEG1ADDR(RBUSCTL_BASE + RBUSCTL_DYN_CFG0_REG) |
| lw t3, 0(t2) |
| ori t3, t3, (CPU_FDIV_M | CPU_FFRAC_M) |
| xori t3, t3, (CPU_FDIV_M | CPU_FFRAC_M) |
| ori t3, t3, ((1 << CPU_FDIV_S) | (1 << CPU_FFRAC_S)) |
| sw t3, 0(t2) |
| |
| /* Clear WST & SPR bits in ErrCtl */ |
| mfc0 t0, CP0_ECC |
| ins t0, zero, 30, 2 |
| mtc0 t0, CP0_ECC |
| ehb |
| |
| /* Simply initialize I-Cache */ |
| li a0, 0 |
| li a1, CONFIG_SYS_ICACHE_SIZE |
| |
| mtc0 zero, CP0_TAGLO /* Zero to DDataLo */ |
| |
| 1: cache INDEX_STORE_TAG_I, 0(a0) |
| addiu a0, CONFIG_SYS_ICACHE_LINE_SIZE |
| bne a0, a1, 1b |
| nop |
| |
| /* Simply initialize D-Cache */ |
| li a0, 0 |
| li a1, CONFIG_SYS_DCACHE_SIZE |
| |
| mtc0 zero, CP0_TAGLO, 2 |
| |
| 2: cache INDEX_STORE_TAG_D, 0(a0) |
| addiu a0, CONFIG_SYS_DCACHE_LINE_SIZE |
| bne a0, a1, 2b |
| nop |
| |
| /* Set KSEG0 Cachable */ |
| mfc0 t0, CP0_CONFIG |
| and t0, t0, MIPS_CONF_IMPL |
| or t0, t0, CONF_CM_CACHABLE_NONCOHERENT |
| mtc0 t0, CP0_CONFIG |
| ehb |
| |
| /* Lock D-Cache */ |
| PTR_LI a0, CACHE_STACK_BASE /* D-Cache lock base */ |
| li a1, CACHE_STACK_SIZE /* D-Cache lock size */ |
| li a2, 0x1ffff800 /* Mask of DTagLo[PTagLo] */ |
| |
| 3: |
| /* Lock one cacheline */ |
| and t0, a0, a2 |
| ori t0, 0xe0 /* Valid & Dirty & Lock bits */ |
| mtc0 t0, CP0_TAGLO, 2 /* Write to DTagLo */ |
| ehb |
| cache INDEX_STORE_TAG_D, 0(a0) |
| |
| addiu a0, CONFIG_SYS_DCACHE_LINE_SIZE |
| sub a1, CONFIG_SYS_DCACHE_LINE_SIZE |
| bnez a1, 3b |
| nop |
| #endif /* CONFIG_SKIP_LOWLEVEL_INIT */ |
| |
| jr ra |
| nop |
| END(mips_sram_init) |
| |
| NESTED(lowlevel_init, 0, ra) |
| /* Save ra and do real lowlevel initialization */ |
| move s0, ra |
| |
| PTR_LA t9, mt7628_init |
| jalr t9 |
| nop |
| |
| move ra, s0 |
| |
| #if CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F) |
| /* Set malloc base */ |
| li t0, (CONFIG_SYS_INIT_SP_ADDR + 15) & (~15) |
| PTR_S t0, GD_MALLOC_BASE(k0) # gd->malloc_base offset |
| #endif |
| |
| /* Write back data in locked cache to DRAM */ |
| PTR_LI a0, CACHE_STACK_BASE /* D-Cache unlock base */ |
| li a1, CACHE_STACK_SIZE /* D-Cache unlock size */ |
| |
| 1: |
| cache HIT_WRITEBACK_INV_D, 0(a0) |
| addiu a0, CONFIG_SYS_DCACHE_LINE_SIZE |
| sub a1, CONFIG_SYS_DCACHE_LINE_SIZE |
| bnez a1, 1b |
| nop |
| |
| /* Set KSEG0 Uncached */ |
| mfc0 t0, CP0_CONFIG |
| and t0, t0, MIPS_CONF_IMPL |
| or t0, t0, CONF_CM_UNCACHED |
| mtc0 t0, CP0_CONFIG |
| ehb |
| |
| jr ra |
| nop |
| END(lowlevel_init) |