162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 362306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 462306a36Sopenharmony_ci * for more details. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2005-2008 Cavium Networks, Inc 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#ifndef __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H 962306a36Sopenharmony_ci#define __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define CP0_CVMCTL_REG $9, 7 1262306a36Sopenharmony_ci#define CP0_CVMMEMCTL_REG $11,7 1362306a36Sopenharmony_ci#define CP0_PRID_REG $15, 0 1462306a36Sopenharmony_ci#define CP0_DCACHE_ERR_REG $27, 1 1562306a36Sopenharmony_ci#define CP0_PRID_OCTEON_PASS1 0x000d0000 1662306a36Sopenharmony_ci#define CP0_PRID_OCTEON_CN30XX 0x000d0200 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci.macro kernel_entry_setup 1962306a36Sopenharmony_ci # Registers set by bootloader: 2062306a36Sopenharmony_ci # (only 32 bits set by bootloader, all addresses are physical 2162306a36Sopenharmony_ci # addresses, and need to have the appropriate memory region set 2262306a36Sopenharmony_ci # by the kernel 2362306a36Sopenharmony_ci # a0 = argc 2462306a36Sopenharmony_ci # a1 = argv (kseg0 compat addr) 2562306a36Sopenharmony_ci # a2 = 1 if init core, zero otherwise 2662306a36Sopenharmony_ci # a3 = address of boot descriptor block 2762306a36Sopenharmony_ci .set push 2862306a36Sopenharmony_ci .set arch=octeon 2962306a36Sopenharmony_ci # Read the cavium mem control register 3062306a36Sopenharmony_ci dmfc0 v0, CP0_CVMMEMCTL_REG 3162306a36Sopenharmony_ci # Clear the lower 6 bits, the CVMSEG size 3262306a36Sopenharmony_ci dins v0, $0, 0, 6 3362306a36Sopenharmony_ci ori v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE 3462306a36Sopenharmony_ci dmtc0 v0, CP0_CVMMEMCTL_REG # Write the cavium mem control register 3562306a36Sopenharmony_ci dmfc0 v0, CP0_CVMCTL_REG # Read the cavium control register 3662306a36Sopenharmony_ci # Disable unaligned load/store support but leave HW fixup enabled 3762306a36Sopenharmony_ci # Needed for octeon specific memcpy 3862306a36Sopenharmony_ci or v0, v0, 0x5001 3962306a36Sopenharmony_ci xor v0, v0, 0x1001 4062306a36Sopenharmony_ci # First clear off CvmCtl[IPPCI] bit and move the performance 4162306a36Sopenharmony_ci # counters interrupt to IRQ 6 4262306a36Sopenharmony_ci dli v1, ~(7 << 7) 4362306a36Sopenharmony_ci and v0, v0, v1 4462306a36Sopenharmony_ci ori v0, v0, (6 << 7) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci mfc0 v1, CP0_PRID_REG 4762306a36Sopenharmony_ci and t1, v1, 0xfff8 4862306a36Sopenharmony_ci xor t1, t1, 0x9000 # 63-P1 4962306a36Sopenharmony_ci beqz t1, 4f 5062306a36Sopenharmony_ci and t1, v1, 0xfff8 5162306a36Sopenharmony_ci xor t1, t1, 0x9008 # 63-P2 5262306a36Sopenharmony_ci beqz t1, 4f 5362306a36Sopenharmony_ci and t1, v1, 0xfff8 5462306a36Sopenharmony_ci xor t1, t1, 0x9100 # 68-P1 5562306a36Sopenharmony_ci beqz t1, 4f 5662306a36Sopenharmony_ci and t1, v1, 0xff00 5762306a36Sopenharmony_ci xor t1, t1, 0x9200 # 66-PX 5862306a36Sopenharmony_ci bnez t1, 5f # Skip WAR for others. 5962306a36Sopenharmony_ci and t1, v1, 0x00ff 6062306a36Sopenharmony_ci slti t1, t1, 2 # 66-P1.2 and later good. 6162306a36Sopenharmony_ci beqz t1, 5f 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci4: # core-16057 work around 6462306a36Sopenharmony_ci or v0, v0, 0x2000 # Set IPREF bit. 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci5: # No core-16057 work around 6762306a36Sopenharmony_ci # Write the cavium control register 6862306a36Sopenharmony_ci dmtc0 v0, CP0_CVMCTL_REG 6962306a36Sopenharmony_ci sync 7062306a36Sopenharmony_ci # Flush dcache after config change 7162306a36Sopenharmony_ci cache 9, 0($0) 7262306a36Sopenharmony_ci # Zero all of CVMSEG to make sure parity is correct 7362306a36Sopenharmony_ci dli v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE 7462306a36Sopenharmony_ci dsll v0, 7 7562306a36Sopenharmony_ci beqz v0, 2f 7662306a36Sopenharmony_ci1: dsubu v0, 8 7762306a36Sopenharmony_ci sd $0, -32768(v0) 7862306a36Sopenharmony_ci bnez v0, 1b 7962306a36Sopenharmony_ci2: 8062306a36Sopenharmony_ci mfc0 v0, CP0_PRID_REG 8162306a36Sopenharmony_ci bbit0 v0, 15, 1f 8262306a36Sopenharmony_ci # OCTEON II or better have bit 15 set. Clear the error bits. 8362306a36Sopenharmony_ci and t1, v0, 0xff00 8462306a36Sopenharmony_ci dli v0, 0x9500 8562306a36Sopenharmony_ci bge t1, v0, 1f # OCTEON III has no DCACHE_ERR_REG COP0 8662306a36Sopenharmony_ci dli v0, 0x27 8762306a36Sopenharmony_ci dmtc0 v0, CP0_DCACHE_ERR_REG 8862306a36Sopenharmony_ci1: 8962306a36Sopenharmony_ci # Get my core id 9062306a36Sopenharmony_ci rdhwr v0, $0 9162306a36Sopenharmony_ci # Jump the master to kernel_entry 9262306a36Sopenharmony_ci bne a2, zero, octeon_main_processor 9362306a36Sopenharmony_ci nop 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci#ifdef CONFIG_SMP 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci # 9862306a36Sopenharmony_ci # All cores other than the master need to wait here for SMP bootstrap 9962306a36Sopenharmony_ci # to begin 10062306a36Sopenharmony_ci # 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ciocteon_spin_wait_boot: 10362306a36Sopenharmony_ci#ifdef CONFIG_RELOCATABLE 10462306a36Sopenharmony_ci PTR_LA t0, octeon_processor_relocated_kernel_entry 10562306a36Sopenharmony_ci LONG_L t0, (t0) 10662306a36Sopenharmony_ci beq zero, t0, 1f 10762306a36Sopenharmony_ci nop 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci jr t0 11062306a36Sopenharmony_ci nop 11162306a36Sopenharmony_ci1: 11262306a36Sopenharmony_ci#endif /* CONFIG_RELOCATABLE */ 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci # This is the variable where the next core to boot is stored 11562306a36Sopenharmony_ci PTR_LA t0, octeon_processor_boot 11662306a36Sopenharmony_ci # Get the core id of the next to be booted 11762306a36Sopenharmony_ci LONG_L t1, (t0) 11862306a36Sopenharmony_ci # Keep looping if it isn't me 11962306a36Sopenharmony_ci bne t1, v0, octeon_spin_wait_boot 12062306a36Sopenharmony_ci nop 12162306a36Sopenharmony_ci # Get my GP from the global variable 12262306a36Sopenharmony_ci PTR_LA t0, octeon_processor_gp 12362306a36Sopenharmony_ci LONG_L gp, (t0) 12462306a36Sopenharmony_ci # Get my SP from the global variable 12562306a36Sopenharmony_ci PTR_LA t0, octeon_processor_sp 12662306a36Sopenharmony_ci LONG_L sp, (t0) 12762306a36Sopenharmony_ci # Set the SP global variable to zero so the master knows we've started 12862306a36Sopenharmony_ci LONG_S zero, (t0) 12962306a36Sopenharmony_ci#ifdef __OCTEON__ 13062306a36Sopenharmony_ci syncw 13162306a36Sopenharmony_ci syncw 13262306a36Sopenharmony_ci#else 13362306a36Sopenharmony_ci sync 13462306a36Sopenharmony_ci#endif 13562306a36Sopenharmony_ci # Jump to the normal Linux SMP entry point 13662306a36Sopenharmony_ci j smp_bootstrap 13762306a36Sopenharmony_ci nop 13862306a36Sopenharmony_ci#else /* CONFIG_SMP */ 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci # 14162306a36Sopenharmony_ci # Someone tried to boot SMP with a non SMP kernel. All extra cores 14262306a36Sopenharmony_ci # will halt here. 14362306a36Sopenharmony_ci # 14462306a36Sopenharmony_ciocteon_wait_forever: 14562306a36Sopenharmony_ci wait 14662306a36Sopenharmony_ci b octeon_wait_forever 14762306a36Sopenharmony_ci nop 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci#endif /* CONFIG_SMP */ 15062306a36Sopenharmony_ciocteon_main_processor: 15162306a36Sopenharmony_ci .set pop 15262306a36Sopenharmony_ci.endm 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci/* 15562306a36Sopenharmony_ci * Do SMP slave processor setup necessary before we can safely execute C code. 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ci .macro smp_slave_setup 15862306a36Sopenharmony_ci .endm 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci#define USE_KEXEC_SMP_WAIT_FINAL 16162306a36Sopenharmony_ci .macro kexec_smp_wait_final 16262306a36Sopenharmony_ci .set push 16362306a36Sopenharmony_ci .set noreorder 16462306a36Sopenharmony_ci synci 0($0) 16562306a36Sopenharmony_ci .set pop 16662306a36Sopenharmony_ci .endm 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#endif /* __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H */ 169