/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2005 Embedded Alley Solutions, Inc */ #ifndef __ASM_MACH_KERNEL_ENTRY_INIT_H #define __ASM_MACH_KERNEL_ENTRY_INIT_H #include #include #define CO_CONFIGPR_VALID 0x3F1F41FF /* valid bits to write to ConfigPR */ #define HAZARD_CP0 nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; #define CACHE_OPC 0xBC000000 /* MIPS cache instruction opcode */ #define ICACHE_LINE_SIZE 32 /* Instruction cache line size bytes */ #define DCACHE_LINE_SIZE 32 /* Data cache line size in bytes */ #define ICACHE_SET_COUNT 256 /* Instruction cache set count */ #define DCACHE_SET_COUNT 128 /* Data cache set count */ #define ICACHE_SET_SIZE (ICACHE_SET_COUNT * ICACHE_LINE_SIZE) #define DCACHE_SET_SIZE (DCACHE_SET_COUNT * DCACHE_LINE_SIZE) .macro kernel_entry_setup .set push .set noreorder /* * PNX8550 entry point, when running a non compressed * kernel. When loading a zImage, the head.S code in * arch/mips/zboot/pnx8550 will init the caches and, * decompress the kernel, and branch to kernel_entry. */ cache_begin: li t0, (1<<28) mtc0 t0, CP0_STATUS /* cp0 usable */ HAZARD_CP0 mtc0 zero, CP0_CAUSE HAZARD_CP0 /* Set static virtual to phys address translation and TLB disabled */ mfc0 t0, CP0_CONFIG, 7 HAZARD_CP0 and t0, ~((1<<19) | (1<<20)) /* TLB/MAP cleared */ mtc0 t0, CP0_CONFIG, 7 HAZARD_CP0 /* CPU boots with kseg0 cache algo set to 0x2 -- uncached */ init_icache nop init_dcache nop cachePr4450ICReset nop cachePr4450DCReset nop /* read ConfigPR into t0 */ mfc0 t0, CP0_CONFIG, 7 HAZARD_CP0 /* enable the TLB */ or t0, (1<<19) /* disable the ICACHE: at least 10x slower */ /* or t0, (1<<26) */ /* disable the DCACHE; CONFIG_CPU_HAS_LLSC should not be set */ /* or t0, (1<<27) */ and t0, CO_CONFIGPR_VALID /* enable TLB. */ mtc0 t0, CP0_CONFIG, 7 HAZARD_CP0 cache_end: /* Setup CMEM_0 to MMIO address space, 2MB */ lui t0, 0x1BE0 addi t0, t0, 0x3 mtc0 $8, $22, 4 nop /* Setup CMEM_1, 128MB */ lui t0, 0x1000 addi t0, t0, 0xf mtc0 $8, $22, 5 nop /* Setup CMEM_2, 32MB */ lui t0, 0x1C00 addi t0, t0, 0xb mtc0 $8, $22, 6 nop /* Setup CMEM_3, 0MB */ lui t0, 0x0 addi t0, t0, 0x0 mtc0 $8, $22, 7 nop /* Enable cache */ mfc0 t0, CP0_CONFIG HAZARD_CP0 and t0, t0, 0xFFFFFFF8 or t0, t0, 3 mtc0 t0, CP0_CONFIG HAZARD_CP0 .set pop .endm .macro init_icache .set push .set noreorder /* Get Cache Configuration */ mfc0 t3, CP0_CONFIG, 1 HAZARD_CP0 /* get cache Line size */ srl t1, t3, 19 /* C0_CONFIGPR_IL_SHIFT */ andi t1, t1, 0x7 /* C0_CONFIGPR_IL_MASK */ beq t1, zero, pr4450_instr_cache_invalidated /* if zero instruction cache is absent */ nop addiu t0, t1, 1 ori t1, zero, 1 sllv t1, t1, t0 /* get max cache Index */ srl t2, t3, 22 /* C0_CONFIGPR_IS_SHIFT */ andi t2, t2, 0x7 /* C0_CONFIGPR_IS_MASK */ addiu t0, t2, 6 ori t2, zero, 1 sllv t2, t2, t0 /* get max cache way */ srl t3, t3, 16 /* C0_CONFIGPR_IA_SHIFT */ andi t3, t3, 0x7 /* C0_CONFIGPR_IA_MASK */ addiu t3, t3, 1 /* total no of cache lines */ multu t2, t3 /* max index * max way */ mflo t2 addiu t2, t2, -1 move t0, zero pr4450_next_instruction_cache_set: cache Index_Invalidate_I, 0(t0) addu t0, t0, t1 /* add bytes in a line */ bne t2, zero, pr4450_next_instruction_cache_set addiu t2, t2, -1 /* reduce no of lines to invalidate by one */ pr4450_instr_cache_invalidated: .set pop .endm .macro init_dcache .set push .set noreorder move t1, zero /* Store Tag Information */ mtc0 zero, CP0_TAGLO, 0 HAZARD_CP0 mtc0 zero, CP0_TAGHI, 0 HAZARD_CP0 /* Cache size is 16384 = 512 lines x 32 bytes per line */ or t2, zero, (128*4)-1 /* 512 lines */ /* Invalidate all lines */ 2: cache Index_Store_Tag_D, 0(t1) addiu t2, t2, -1 bne t2, zero, 2b addiu t1, t1, 32 /* 32 bytes in a line */ .set pop .endm .macro cachePr4450ICReset .set push .set noreorder /* Save CP0 status reg on entry; */ /* disable interrupts during cache reset */ mfc0 t0, CP0_STATUS /* T0 = interrupt status on entry */ HAZARD_CP0 mtc0 zero, CP0_STATUS /* disable CPU interrupts */ HAZARD_CP0 or t1, zero, zero /* T1 = starting cache index (0) */ ori t2, zero, (256 - 1) /* T2 = inst cache set cnt - 1 */ icache_invd_loop: /* 9 == register t1 */ .word CACHE_OPC | (9 << 21) | (Index_Invalidate_I << 16) | \ (0 * ICACHE_SET_SIZE) /* invalidate inst cache WAY0 */ .word CACHE_OPC | (9 << 21) | (Index_Invalidate_I << 16) | \ (1 * ICACHE_SET_SIZE) /* invalidate inst cache WAY1 */ addiu t1, t1, ICACHE_LINE_SIZE /* T1 = next cache line index */ bne t2, zero, icache_invd_loop /* T2 = 0 if all sets invalidated */ addiu t2, t2, -1 /* decrement T2 set cnt (delay slot) */ /* Initialize the latches in the instruction cache tag */ /* that drive the way selection tri-state bus drivers, by doing a */ /* dummy load while the instruction cache is still disabled. */ /* TODO: Is this needed ? */ la t1, KSEG0 /* T1 = cached memory base address */ lw zero, 0x0000(t1) /* (dummy read of first memory word) */ mtc0 t0, CP0_STATUS /* restore interrupt status on entry */ HAZARD_CP0 .set pop .endm .macro cachePr4450DCReset .set push .set noreorder mfc0 t0, CP0_STATUS /* T0 = interrupt status on entry */ HAZARD_CP0 mtc0 zero, CP0_STATUS /* disable CPU interrupts */ HAZARD_CP0 /* Writeback/invalidate entire data cache sets/ways/lines */ or t1, zero, zero /* T1 = starting cache index (0) */ ori t2, zero, (DCACHE_SET_COUNT - 1) /* T2 = data cache set cnt - 1 */ dcache_wbinvd_loop: /* 9 == register t1 */ .word CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \ (0 * DCACHE_SET_SIZE) /* writeback/invalidate WAY0 */ .word CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \ (1 * DCACHE_SET_SIZE) /* writeback/invalidate WAY1 */ .word CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \ (2 * DCACHE_SET_SIZE) /* writeback/invalidate WAY2 */ .word CACHE_OPC | (9 << 21) | (Index_Writeback_Inv_D << 16) | \ (3 * DCACHE_SET_SIZE) /* writeback/invalidate WAY3 */ addiu t1, t1, DCACHE_LINE_SIZE /* T1 = next data cache line index */ bne t2, zero, dcache_wbinvd_loop /* T2 = 0 when wbinvd entire cache */ addiu t2, t2, -1 /* decrement T2 set cnt (delay slot) */ /* Initialize the latches in the data cache tag that drive the way selection tri-state bus drivers, by doing a dummy load while the data cache is still in the disabled mode. TODO: Is this needed ? */ la t1, KSEG0 /* T1 = cached memory base address */ lw zero, 0x0000(t1) /* (dummy read of first memory word) */ mtc0 t0, CP0_STATUS /* restore interrupt status on entry */ HAZARD_CP0 .set pop .endm #endif /* __ASM_MACH_KERNEL_ENTRY_INIT_H */