kernel-entry-init.h 3.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * 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_CVMCTL_REG $9, 7
#define CP0_CVMMEMCTL_REG $11,7
#define CP0_PRID_REG $15, 0
14
#define CP0_DCACHE_ERR_REG $27, 1
15 16 17
#define CP0_PRID_OCTEON_PASS1 0x000d0000
#define CP0_PRID_OCTEON_CN30XX 0x000d0200

R
Ralf Baechle 已提交
18
.macro	kernel_entry_setup
19 20 21 22 23 24 25 26 27 28 29
	# 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
R
Ralf Baechle 已提交
30
	dmfc0	v0, CP0_CVMMEMCTL_REG
31
	# Clear the lower 6 bits, the CVMSEG size
R
Ralf Baechle 已提交
32 33 34 35
	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
36
	# Disable unaligned load/store support but leave HW fixup enabled
37
	# Needed for octeon specific memcpy
38 39
	or  v0, v0, 0x5001
	xor v0, v0, 0x1001
40 41
	# First clear off CvmCtl[IPPCI] bit and move the performance
	# counters interrupt to IRQ 6
42
	dli	v1, ~(7 << 7)
43 44
	and	v0, v0, v1
	ori	v0, v0, (6 << 7)
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

	mfc0	v1, CP0_PRID_REG
	and	t1, v1, 0xfff8
	xor	t1, t1, 0x9000		# 63-P1
	beqz	t1, 4f
	and	t1, v1, 0xfff8
	xor	t1, t1, 0x9008		# 63-P2
	beqz	t1, 4f
	and	t1, v1, 0xfff8
	xor	t1, t1, 0x9100		# 68-P1
	beqz	t1, 4f
	and	t1, v1, 0xff00
	xor	t1, t1, 0x9200		# 66-PX
	bnez	t1, 5f			# Skip WAR for others.
	and	t1, v1, 0x00ff
	slti	t1, t1, 2		# 66-P1.2 and later good.
	beqz	t1, 5f

4:	# core-16057 work around
	or	v0, v0, 0x2000		# Set IPREF bit.

5:	# No core-16057 work around
67
	# Write the cavium control register
R
Ralf Baechle 已提交
68
	dmtc0	v0, CP0_CVMCTL_REG
69 70
	sync
	# Flush dcache after config change
R
Ralf Baechle 已提交
71
	cache	9, 0($0)
72 73 74 75 76 77 78 79 80 81 82 83 84 85
	# Zero all of CVMSEG to make sure parity is correct
	dli	v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE
	dsll	v0, 7
	beqz	v0, 2f
1:	dsubu	v0, 8
	sd	$0, -32768(v0)
	bnez	v0, 1b
2:
	mfc0	v0, CP0_PRID_REG
	bbit0	v0, 15, 1f
	# OCTEON II or better have bit 15 set.  Clear the error bits.
	dli	v0, 0x27
	dmtc0	v0, CP0_DCACHE_ERR_REG
1:
86
	# Get my core id
R
Ralf Baechle 已提交
87
	rdhwr	v0, $0
88
	# Jump the master to kernel_entry
R
Ralf Baechle 已提交
89
	bne	a2, zero, octeon_main_processor
90 91 92 93 94 95 96 97 98 99
	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
R
Ralf Baechle 已提交
100
	PTR_LA	t0, octeon_processor_boot
101 102
octeon_spin_wait_boot:
	# Get the core id of the next to be booted
R
Ralf Baechle 已提交
103
	LONG_L	t1, (t0)
104 105 106 107
	# Keep looping if it isn't me
	bne t1, v0, octeon_spin_wait_boot
	nop
	# Get my GP from the global variable
R
Ralf Baechle 已提交
108 109
	PTR_LA	t0, octeon_processor_gp
	LONG_L	gp, (t0)
110
	# Get my SP from the global variable
R
Ralf Baechle 已提交
111 112
	PTR_LA	t0, octeon_processor_sp
	LONG_L	sp, (t0)
113
	# Set the SP global variable to zero so the master knows we've started
R
Ralf Baechle 已提交
114
	LONG_S	zero, (t0)
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
#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.
 */
R
Ralf Baechle 已提交
143
	.macro	smp_slave_setup
144 145 146
	.endm

#endif /* __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H */