Back to home page

LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2005-2008 Cavium Networks, Inc
0007  */
0008 #ifndef __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H
0009 #define __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H
0010 
0011 #define CP0_CVMCTL_REG $9, 7
0012 #define CP0_CVMMEMCTL_REG $11,7
0013 #define CP0_PRID_REG $15, 0
0014 #define CP0_DCACHE_ERR_REG $27, 1
0015 #define CP0_PRID_OCTEON_PASS1 0x000d0000
0016 #define CP0_PRID_OCTEON_CN30XX 0x000d0200
0017 
0018 .macro  kernel_entry_setup
0019     # Registers set by bootloader:
0020     # (only 32 bits set by bootloader, all addresses are physical
0021     # addresses, and need to have the appropriate memory region set
0022     # by the kernel
0023     # a0 = argc
0024     # a1 = argv (kseg0 compat addr)
0025     # a2 = 1 if init core, zero otherwise
0026     # a3 = address of boot descriptor block
0027     .set push
0028     .set arch=octeon
0029     # Read the cavium mem control register
0030     dmfc0   v0, CP0_CVMMEMCTL_REG
0031     # Clear the lower 6 bits, the CVMSEG size
0032     dins    v0, $0, 0, 6
0033     ori v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE
0034     dmtc0   v0, CP0_CVMMEMCTL_REG   # Write the cavium mem control register
0035     dmfc0   v0, CP0_CVMCTL_REG  # Read the cavium control register
0036     # Disable unaligned load/store support but leave HW fixup enabled
0037     # Needed for octeon specific memcpy
0038     or  v0, v0, 0x5001
0039     xor v0, v0, 0x1001
0040     # First clear off CvmCtl[IPPCI] bit and move the performance
0041     # counters interrupt to IRQ 6
0042     dli v1, ~(7 << 7)
0043     and v0, v0, v1
0044     ori v0, v0, (6 << 7)
0045 
0046     mfc0    v1, CP0_PRID_REG
0047     and t1, v1, 0xfff8
0048     xor t1, t1, 0x9000      # 63-P1
0049     beqz    t1, 4f
0050     and t1, v1, 0xfff8
0051     xor t1, t1, 0x9008      # 63-P2
0052     beqz    t1, 4f
0053     and t1, v1, 0xfff8
0054     xor t1, t1, 0x9100      # 68-P1
0055     beqz    t1, 4f
0056     and t1, v1, 0xff00
0057     xor t1, t1, 0x9200      # 66-PX
0058     bnez    t1, 5f          # Skip WAR for others.
0059     and t1, v1, 0x00ff
0060     slti    t1, t1, 2       # 66-P1.2 and later good.
0061     beqz    t1, 5f
0062 
0063 4:  # core-16057 work around
0064     or  v0, v0, 0x2000      # Set IPREF bit.
0065 
0066 5:  # No core-16057 work around
0067     # Write the cavium control register
0068     dmtc0   v0, CP0_CVMCTL_REG
0069     sync
0070     # Flush dcache after config change
0071     cache   9, 0($0)
0072     # Zero all of CVMSEG to make sure parity is correct
0073     dli v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE
0074     dsll    v0, 7
0075     beqz    v0, 2f
0076 1:  dsubu   v0, 8
0077     sd  $0, -32768(v0)
0078     bnez    v0, 1b
0079 2:
0080     mfc0    v0, CP0_PRID_REG
0081     bbit0   v0, 15, 1f
0082     # OCTEON II or better have bit 15 set.  Clear the error bits.
0083     and t1, v0, 0xff00
0084     dli v0, 0x9500
0085     bge t1, v0, 1f  # OCTEON III has no DCACHE_ERR_REG COP0
0086     dli v0, 0x27
0087     dmtc0   v0, CP0_DCACHE_ERR_REG
0088 1:
0089     # Get my core id
0090     rdhwr   v0, $0
0091     # Jump the master to kernel_entry
0092     bne a2, zero, octeon_main_processor
0093     nop
0094 
0095 #ifdef CONFIG_SMP
0096 
0097     #
0098     # All cores other than the master need to wait here for SMP bootstrap
0099     # to begin
0100     #
0101 
0102     # This is the variable where the next core to boot os stored
0103     PTR_LA  t0, octeon_processor_boot
0104 octeon_spin_wait_boot:
0105     # Get the core id of the next to be booted
0106     LONG_L  t1, (t0)
0107     # Keep looping if it isn't me
0108     bne t1, v0, octeon_spin_wait_boot
0109     nop
0110     # Get my GP from the global variable
0111     PTR_LA  t0, octeon_processor_gp
0112     LONG_L  gp, (t0)
0113     # Get my SP from the global variable
0114     PTR_LA  t0, octeon_processor_sp
0115     LONG_L  sp, (t0)
0116     # Set the SP global variable to zero so the master knows we've started
0117     LONG_S  zero, (t0)
0118 #ifdef __OCTEON__
0119     syncw
0120     syncw
0121 #else
0122     sync
0123 #endif
0124     # Jump to the normal Linux SMP entry point
0125     j   smp_bootstrap
0126     nop
0127 #else /* CONFIG_SMP */
0128 
0129     #
0130     # Someone tried to boot SMP with a non SMP kernel. All extra cores
0131     # will halt here.
0132     #
0133 octeon_wait_forever:
0134     wait
0135     b   octeon_wait_forever
0136     nop
0137 
0138 #endif /* CONFIG_SMP */
0139 octeon_main_processor:
0140     .set pop
0141 .endm
0142 
0143 /*
0144  * Do SMP slave processor setup necessary before we can safely execute C code.
0145  */
0146     .macro  smp_slave_setup
0147     .endm
0148 
0149 #endif /* __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H */