/*---------------------------------------------------------------------------* Project: CtrBrom - library - init File: crt0_mmu.c Copyright 2009 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: $ $Rev$ $Author$ *---------------------------------------------------------------------------*/ #include #include void stupInitMMUTable( u32* t1Base, u32* t2Base ); /*---------------------------------------------------------------------------* Name: stupDisableCP15 Description: Disable Coprocessor 15 Arguments: None Returns: None *---------------------------------------------------------------------------*/ asm void stupDisableCP15( void ) { // MMU/Caches/BranchPrediction disable mrc p15, 0, r0, c1, c0, 0 ldr r1, =HW_C1_IC_ENABLE | HW_C1_DC_ENABLE \ | HW_C1_FORCE_AP_BIT \ | HW_C1_TEX_CB_REMAP \ | HW_C1_EXCEPT_BIG_ENDIAN \ | HW_C1_BR_PREDICT_ENABLE \ | HW_C1_LD_INTERWORK_DISABLE \ | HW_C1_UNALIGN_ACCESS_ENABLE \ | HW_C1_ALIGN_FAULT_ENABLE \ | HW_C1_ROM_PROTECT_ENABLE \ | HW_C1_MMU_PROTECT_ENABLE \ | HW_C1_MMU_ENABLE #ifndef SDK_MG20EMU orr r1, r1, #HW_C1_EXCEPT_VEC_UPPER #endif // SDK_MG20EMU bic r0, r0, r1 mcr p15, 0, r0, c1, c0, 0 mrc p15, 0, r0, c1, c0, 1 ldr r1, =HW_C1_EXCLUSIVE_L1C_L2C \ | HW_C1_BR_FOLDING_ENABLE \ | HW_C1_SBR_PREDICT_ENABLE \ | HW_C1_DBR_PREDICT_ENABLE \ | HW_C1_RETURN_STACK_ENABLE bic r0, r0, r1 mcr p15, 0, r0, c1, c0, 1 // Invalidate Caches mov r0, #0 mcr p15, 0, r0, c7, c5, 0 // Inst Cache mcr p15, 0, r0, c7, c6, 0 // Data cache // Wait for write buffer empty mcr p15, 0, r0, c7, c10, 4 bx lr } /*---------------------------------------------------------------------------* Name: stupEnableCP15 Description: Enable Coprocessor 15 Arguments: None Returns: None *---------------------------------------------------------------------------*/ asm void stupEnableCP15( void ) { // // Snoop Control Unit // ldr r3, =REG_SCU_CNT_ADDR ldr r0, [r3] orr r0, r0, #REG_OS_SCU_CNT_E_MASK str r0, [r3] // // Auxiliary Control // mrc p15, 0, r0, c1, c0, 1 ldr r1, =HW_C1_SMP_MODE \ | HW_C1_BR_FOLDING_ENABLE \ | HW_C1_SBR_PREDICT_ENABLE \ | HW_C1_DBR_PREDICT_ENABLE \ | HW_C1_RETURN_STACK_ENABLE orr r0, r0, r1 mcr p15, 0, r0, c1, c0, 1 // // Master Control // mrc p15, 0, r0, c1, c0, 0 ldr r1, = 0 \ | HW_C1_EXCEPT_LITTLE_ENDIAN \ | HW_C1_UNALIGN_ACCESS_ENABLE \ | HW_C1_BR_PREDICT_ENABLE \ | HW_C1_MMU_V6 \ | HW_C1_IC_ENABLE \ | HW_C1_DC_ENABLE \ | HW_C1_MMU_ENABLE #ifdef SDK_MG20EMU orr r1, r1, #HW_C1_EXCEPT_VEC_UPPER #endif // SDK_MG20EMU orr r0, r0, r1 mcr p15, 0, r0, c1, c0, 0 // Invalidate Caches mov r0, #0 mcr p15, 0, r0, c7, c5, 0 // Inst Cache mcr p15, 0, r0, c7, c6, 0 // Data cache // Wait for write buffer empty mcr p15, 0, r0, c7, c10, 4 bx lr } /*---------------------------------------------------------------------------* Name: stupInitMMU Description: Initialize MMU Arguments: None Returns: None *---------------------------------------------------------------------------*/ asm void stupInitMMU( u32* t1Base, u32* t2Base ) { stmfd sp!, {r4, lr} // stack requires 8byte alignment // Invalidate ITLB DTLB mov r3, #0 mcr p15, 0, r3, c8, c5, 0 mcr p15, 0, r3, c8, c6, 0 mov r2, #HW_C2_V5_T1_BOUNBARY_16KB // MMU L1 Table Base ldr r3, =HW_C2_0_T1_BASE_MASK_MIN mov r3, r3, ASR r2 and r3 ,r3, r0 orr r3, r3, #(HW_C2_WALK_L2C_CA_NC << HW_C2_WALK_L2C_CA_SFT) \ | HW_C2_WALK_ON_SHARED_MEM mcr p15, 0, r3, c2, c0, 0 ldr r3, =HW_C2_1_T1_BASE_MASK and r3 ,r3, r0 orr r3, r3, #(HW_C2_WALK_L2C_CA_NC << HW_C2_WALK_L2C_CA_SFT) \ | HW_C2_WALK_ON_SHARED_MEM mcr p15, 0, r3, c2, c0, 1 // MMU L1 Table Boundary mcr p15, 0, r2, c2, c0, 2 // Domain Access Permission #if 1 // miya ldr r3, =0x00000001 #else ldr r3, = HW_C3_DOMAIN_PACK( \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER \ ) #endif mcr p15, 0, r3, c3, c0, 0 // VFP Access Permission ldr r3, =HW_C1_VFP_AP_PACK( \ HW_C1_AP_PRIV, HW_C1_AP_PRIV ) mcr p15, 0, r3, c1, c0, 2 // Initialize MMU Table bl __cpp(stupInitMMUTable) ldmfd sp!, {r4, pc} // stack requires 8byte alignment } /*---------------------------------------------------------------------------* Name: stupInitMMUTable Description: Initialize MMU Table Arguments: None Returns: None *---------------------------------------------------------------------------*/ void stupInitMMUTable( u32* t1Base, u32* t2Base ) { u32* table; u32 paddr = (u32 )NULL; // Initialize as Access Prohibition table = t1Base; for ( paddr = (u32 )NULL; table < (void *)HW_BROM_MMU_T1_END; ) { *table++ = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_APX_NA, HW_MMU6_T1_RGT_STRONG_ORDER, HW_MMU6_T1_GLOBAL, HW_MMU6_T1_SHARED, HW_MMU6_T1_XN, 0); } table = t2Base; for ( paddr = (u32 )NULL; table < (void *)HW_BROM_MMU_T2_END; ) { *table++ = HW_MMU6_T2_SP_PACK( paddr, HW_MMU6_T2_APX_NA, HW_MMU6_T2_LP_RGT_STRONG_ORDER, HW_MMU6_T2_GLOBAL, HW_MMU6_T2_SHARED, HW_MMU6_T2_SP_XN); } // Main Memory Region (128MB cached) paddr = HW_MAIN_MEM; table = &t1Base[paddr/HW_MMU6_T1_SEC_SIZE]; while ( paddr < HW_MAIN_MEM_END ) { *table++ = HW_MMU6_T1_SUSEC_PACK( paddr, HW_MMU6_T1_APX_S_RW_U_NA, HW_MMU6_T1_RGT_L1C_WB_WA, HW_MMU6_T1_GLOBAL, HW_MMU6_T1_SHARED, #ifdef BROM_TARGET_BROM HW_MMU6_T1_XN #else // BROM_TARGET_FIRM || BROM_TARGET_APP FALSE #endif // BROM_TARGET_FIRM || BROM_TARGET_APP ); paddr += HW_MMU6_T1_SEC_SIZE; } #ifndef SDK_MG20EMU // MG20には拡張メインメモリは無い while ( paddr < HW_MAIN_MEM_EX_END ) { *table++ = HW_MMU6_T1_SUSEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_L1C_WB_WA, HW_MMU6_T1_GLOBAL, HW_MMU6_T1_SHARED, #ifdef BROM_TARGET_BROM HW_MMU6_T1_XN #else // BROM_TARGET_FIRM || BROM_TARGET_APP FALSE #endif // BROM_TARGET_FIRM || BROM_TARGET_APP ); paddr += HW_MMU6_T1_SEC_SIZE; } #else // SDK_MG20EMU // for AXI-WRAM & DSP-WRAM Emulation paddr = HW_MAIN_MEM_END - HW_MMU6_T1_SUSEC_SIZE; table = &t1Base[paddr/HW_MMU6_T1_SEC_SIZE]; while ( paddr < HW_MAIN_MEM_END ) { *table++ = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_S_RW_U_NA, HW_MMU6_T1_RGT_L1C_WB_WA, HW_MMU6_T1_GLOBAL, HW_MMU6_T1_SHARED, HW_MMU6_T1_XN, 0); paddr += HW_MMU6_T1_SEC_SIZE; } #endif // SDK_MG20EMU // IO Registers Region (16MB) paddr = HW_IOREG; table = &t1Base[paddr/HW_MMU6_T1_SEC_SIZE]; while ( paddr < HW_IOREG + HW_MMU6_T1_SUSEC_SIZE ) { *table++ = HW_MMU6_T1_SUSEC_PACK( paddr, HW_MMU6_T1_APX_S_RW_U_NA, HW_MMU6_T1_RGT_SHARED_DEV, HW_MMU6_T1_GLOBAL, HW_MMU6_T1_SHARED, HW_MMU6_T1_XN ); paddr += HW_MMU6_T1_SEC_SIZE; } // MPCore Registers Region (1MB) paddr = HW_MPCORE_REG; table = &t1Base[paddr/HW_MMU6_T1_SEC_SIZE]; *table++ = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_S_RW_U_NA, HW_MMU6_T1_RGT_NSHARED_DEV, HW_MMU6_T1_GLOBAL, FALSE, HW_MMU6_T1_XN, 0); // VRAM Region (4MB cached) paddr = HW_VRAM; table = &t1Base[paddr/HW_MMU6_T1_SEC_SIZE]; while ( paddr < HW_VRAM_END ) { *table++ = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_S_RW_U_NA, HW_MMU6_T1_RGT_L1C_WB_WA, HW_MMU6_T1_GLOBAL, HW_MMU6_T1_SHARED, HW_MMU6_T1_XN, 0); paddr += HW_MMU6_T1_SEC_SIZE; } #ifdef SDK_NE1EMU // NE1-TB DDR2 Registers Region (1MB) paddr = HW_NE1DDR2_REG; table = &t1Base[paddr/HW_MMU6_T1_SEC_SIZE]; *table++ = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_S_RW_U_NA, HW_MMU6_T1_RGT_SHARED_DEV, HW_MMU6_T1_GLOBAL, HW_MMU6_T1_SHARED, HW_MMU6_T1_XN, 0); #endif // SDK_NE1EMU // AXI-WRAM & DSP-WRAM Region (1MB cached & uncached) paddr = HW_DSP_WRAM; table = &t1Base[paddr/HW_MMU6_T1_SEC_SIZE]; *table = HW_MMU6_T1_COURSE_PACK( (u32)t2Base, 0 ); // T2 for Page table = &t2Base[paddr%HW_MMU6_T1_SEC_SIZE/HW_MMU6_T2_LP_ALIAS_SIZE]; while ( paddr < MATH_ROUNDDOWN(HW_BROM_MMU_TBL, HW_MMU6_T2_LP_SIZE) ) { *table++ = HW_MMU6_T2_LP_PACK( paddr, HW_MMU6_T2_APX_S_RW_U_NA, HW_MMU6_T2_LP_RGT_L1C_WB_WA, HW_MMU6_T2_GLOBAL, HW_MMU6_T2_SHARED, HW_MMU6_T2_LP_XN); paddr += HW_MMU6_T2_LP_ALIAS_SIZE; } while ( paddr < HW_BROM_MMU_TBL ) { *table++ = HW_MMU6_T2_SP_PACK( paddr, HW_MMU6_T2_APX_S_RW_U_NA, HW_MMU6_T2_SP_RGT_L1C_WB_WA, HW_MMU6_T2_GLOBAL, HW_MMU6_T2_SHARED, HW_MMU6_T2_SP_XN); paddr += HW_MMU6_T2_SP_SIZE; } // HW_BROM_MMU_TBL while ( paddr < HW_BROM_MMU_TBL_END ) { *table++ = HW_MMU6_T2_SP_PACK( paddr, HW_MMU6_T2_APX_S_RW_U_NA, HW_MMU6_T2_SP_RGT_SHARED_DEV, HW_MMU6_T2_GLOBAL, HW_MMU6_T2_SHARED, HW_MMU6_T2_SP_XN); paddr += HW_MMU6_T2_SP_SIZE; } // HW_AXI_WRAM_SHARED while ( paddr < HW_AXI_WRAM_SHARED_END ) { *table++ = HW_MMU6_T2_SP_PACK( paddr, HW_MMU6_T2_APX_S_RW_U_NA, HW_MMU6_T2_SP_RGT_SHARED_DEV, HW_MMU6_T2_GLOBAL, HW_MMU6_T2_SHARED, FALSE); // for exception veneer paddr += HW_MMU6_T2_SP_SIZE; } // Coarse page is 1KB boundary t2Base += MATH_ROUNDUP((HW_DSP_WRAM_SIZE+HW_AXI_WRAM_SIZE)/HW_MMU6_T2_SP_SIZE, HW_MMU6_T1_CORS_SIZE)/sizeof(t2Base[0]); // BROM Region (64KBx2 cached) paddr = HW_BROM_IMG; table = &t1Base[paddr/HW_MMU6_T1_SEC_SIZE]; *table = HW_MMU6_T1_COURSE_PACK( (u32)t2Base, 0 ); // T2 for Page table = &t2Base[paddr%HW_MMU6_T1_SEC_SIZE/HW_MMU6_T2_LP_ALIAS_SIZE]; while ( paddr != HW_BROM_END ) { *table++ = HW_MMU6_T2_LP_PACK( paddr, #ifdef BROM_TARGET_BROM HW_MMU6_T2_APX_S_RW_U_NA, #else // BROM_TARGET_FIRM || BROM_TARGET_APP HW_MMU6_T2_APX_S_RO_U_NA, #endif // BROM_TARGET_FIRM || BROM_TARGET_APP HW_MMU6_T2_LP_RGT_L1C_WB_WA, HW_MMU6_T2_GLOBAL, HW_MMU6_T2_SHARED, FALSE); paddr += HW_MMU6_T2_LP_ALIAS_SIZE; } // Coarse page is 1KB boundary t2Base += MATH_ROUNDUP(HW_BROM_SIZE*2/HW_MMU6_T2_LP_ALIAS_SIZE, HW_MMU6_T1_CORS_SIZE)/sizeof(t2Base[0]); }