Octeon uses different interrupt irq for timer and performance counters. Set CvmCtl[IPPCI] to correct irq value very early. Signed-off-by: Chandrakala Chavva <cchavva@caviumnetworks.com> Signed-off-by: David Daney <ddaney@caviumnetworks.com> To: linux-mips@linux-mips.org Cc: Chandrakala Chavva <cchavva@caviumnetworks.com> Patchwork: https://patchwork.linux-mips.org/patch/2085/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
		
			
				
	
	
		
			136 lines
		
	
	
	
		
			3.5 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
	
		
			3.5 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * 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-2008 Cavium Networks, Inc
 | 
						|
 */
 | 
						|
#ifndef __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H
 | 
						|
#define __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H
 | 
						|
 | 
						|
 | 
						|
#define CP0_CYCLE_COUNTER $9, 6
 | 
						|
#define CP0_CVMCTL_REG $9, 7
 | 
						|
#define CP0_CVMMEMCTL_REG $11,7
 | 
						|
#define CP0_PRID_REG $15, 0
 | 
						|
#define CP0_PRID_OCTEON_PASS1 0x000d0000
 | 
						|
#define CP0_PRID_OCTEON_CN30XX 0x000d0200
 | 
						|
 | 
						|
.macro  kernel_entry_setup
 | 
						|
	# Registers set by bootloader:
 | 
						|
	# (only 32 bits set by bootloader, all addresses are physical
 | 
						|
	# addresses, and need to have the appropriate memory region set
 | 
						|
	# by the kernel
 | 
						|
	# a0 = argc
 | 
						|
	# a1 = argv (kseg0 compat addr)
 | 
						|
	# a2 = 1 if init core, zero otherwise
 | 
						|
	# a3 = address of boot descriptor block
 | 
						|
	.set push
 | 
						|
	.set arch=octeon
 | 
						|
	# Read the cavium mem control register
 | 
						|
	dmfc0   v0, CP0_CVMMEMCTL_REG
 | 
						|
	# Clear the lower 6 bits, the CVMSEG size
 | 
						|
	dins    v0, $0, 0, 6
 | 
						|
	ori     v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE
 | 
						|
	dmtc0   v0, CP0_CVMMEMCTL_REG	# Write the cavium mem control register
 | 
						|
	dmfc0   v0, CP0_CVMCTL_REG	# Read the cavium control register
 | 
						|
#ifdef CONFIG_CAVIUM_OCTEON_HW_FIX_UNALIGNED
 | 
						|
	# Disable unaligned load/store support but leave HW fixup enabled
 | 
						|
	or  v0, v0, 0x5001
 | 
						|
	xor v0, v0, 0x1001
 | 
						|
#else
 | 
						|
	# Disable unaligned load/store and HW fixup support
 | 
						|
	or  v0, v0, 0x5001
 | 
						|
	xor v0, v0, 0x5001
 | 
						|
#endif
 | 
						|
	# Read the processor ID register
 | 
						|
	mfc0 v1, CP0_PRID_REG
 | 
						|
	# Disable instruction prefetching (Octeon Pass1 errata)
 | 
						|
	or  v0, v0, 0x2000
 | 
						|
	# Skip reenable of prefetching for Octeon Pass1
 | 
						|
	beq v1, CP0_PRID_OCTEON_PASS1, skip
 | 
						|
	nop
 | 
						|
	# Reenable instruction prefetching, not on Pass1
 | 
						|
	xor v0, v0, 0x2000
 | 
						|
	# Strip off pass number off of processor id
 | 
						|
	srl v1, 8
 | 
						|
	sll v1, 8
 | 
						|
	# CN30XX needs some extra stuff turned off for better performance
 | 
						|
	bne v1, CP0_PRID_OCTEON_CN30XX, skip
 | 
						|
	nop
 | 
						|
	# CN30XX Use random Icache replacement
 | 
						|
	or  v0, v0, 0x400
 | 
						|
	# CN30XX Disable instruction prefetching
 | 
						|
	or  v0, v0, 0x2000
 | 
						|
skip:
 | 
						|
	# First clear off CvmCtl[IPPCI] bit and move the performance
 | 
						|
	# counters interrupt to IRQ 6
 | 
						|
	li	v1, ~(7 << 7)
 | 
						|
	and	v0, v0, v1
 | 
						|
	ori	v0, v0, (6 << 7)
 | 
						|
	# Write the cavium control register
 | 
						|
	dmtc0   v0, CP0_CVMCTL_REG
 | 
						|
	sync
 | 
						|
	# Flush dcache after config change
 | 
						|
	cache   9, 0($0)
 | 
						|
	# Get my core id
 | 
						|
	rdhwr   v0, $0
 | 
						|
	# Jump the master to kernel_entry
 | 
						|
	bne     a2, zero, octeon_main_processor
 | 
						|
	nop
 | 
						|
 | 
						|
#ifdef CONFIG_SMP
 | 
						|
 | 
						|
	#
 | 
						|
	# All cores other than the master need to wait here for SMP bootstrap
 | 
						|
	# to begin
 | 
						|
	#
 | 
						|
 | 
						|
	# This is the variable where the next core to boot os stored
 | 
						|
	PTR_LA  t0, octeon_processor_boot
 | 
						|
octeon_spin_wait_boot:
 | 
						|
	# Get the core id of the next to be booted
 | 
						|
	LONG_L  t1, (t0)
 | 
						|
	# Keep looping if it isn't me
 | 
						|
	bne t1, v0, octeon_spin_wait_boot
 | 
						|
	nop
 | 
						|
	# Get my GP from the global variable
 | 
						|
	PTR_LA  t0, octeon_processor_gp
 | 
						|
	LONG_L  gp, (t0)
 | 
						|
	# Get my SP from the global variable
 | 
						|
	PTR_LA  t0, octeon_processor_sp
 | 
						|
	LONG_L  sp, (t0)
 | 
						|
	# Set the SP global variable to zero so the master knows we've started
 | 
						|
	LONG_S  zero, (t0)
 | 
						|
#ifdef __OCTEON__
 | 
						|
	syncw
 | 
						|
	syncw
 | 
						|
#else
 | 
						|
	sync
 | 
						|
#endif
 | 
						|
	# Jump to the normal Linux SMP entry point
 | 
						|
	j   smp_bootstrap
 | 
						|
	nop
 | 
						|
#else /* CONFIG_SMP */
 | 
						|
 | 
						|
	#
 | 
						|
	# Someone tried to boot SMP with a non SMP kernel. All extra cores
 | 
						|
	# will halt here.
 | 
						|
	#
 | 
						|
octeon_wait_forever:
 | 
						|
	wait
 | 
						|
	b   octeon_wait_forever
 | 
						|
	nop
 | 
						|
 | 
						|
#endif /* CONFIG_SMP */
 | 
						|
octeon_main_processor:
 | 
						|
	.set pop
 | 
						|
.endm
 | 
						|
 | 
						|
/*
 | 
						|
 * Do SMP slave processor setup necessary before we can savely execute C code.
 | 
						|
 */
 | 
						|
	.macro  smp_slave_setup
 | 
						|
	.endm
 | 
						|
 | 
						|
#endif /* __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H */
 |