Back to home page

OSCL-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 octeon_spin_wait_boot:
0103 #ifdef CONFIG_RELOCATABLE
0104     PTR_LA  t0, octeon_processor_relocated_kernel_entry
0105     LONG_L  t0, (t0)
0106     beq zero, t0, 1f
0107     nop
0108 
0109     jr  t0
0110     nop
0111 1:
0112 #endif /* CONFIG_RELOCATABLE */
0113 
0114     # This is the variable where the next core to boot is stored
0115     PTR_LA  t0, octeon_processor_boot
0116     # Get the core id of the next to be booted
0117     LONG_L  t1, (t0)
0118     # Keep looping if it isn't me
0119     bne t1, v0, octeon_spin_wait_boot
0120     nop
0121     # Get my GP from the global variable
0122     PTR_LA  t0, octeon_processor_gp
0123     LONG_L  gp, (t0)
0124     # Get my SP from the global variable
0125     PTR_LA  t0, octeon_processor_sp
0126     LONG_L  sp, (t0)
0127     # Set the SP global variable to zero so the master knows we've started
0128     LONG_S  zero, (t0)
0129 #ifdef __OCTEON__
0130     syncw
0131     syncw
0132 #else
0133     sync
0134 #endif
0135     # Jump to the normal Linux SMP entry point
0136     j   smp_bootstrap
0137     nop
0138 #else /* CONFIG_SMP */
0139 
0140     #
0141     # Someone tried to boot SMP with a non SMP kernel. All extra cores
0142     # will halt here.
0143     #
0144 octeon_wait_forever:
0145     wait
0146     b   octeon_wait_forever
0147     nop
0148 
0149 #endif /* CONFIG_SMP */
0150 octeon_main_processor:
0151     .set pop
0152 .endm
0153 
0154 /*
0155  * Do SMP slave processor setup necessary before we can safely execute C code.
0156  */
0157     .macro  smp_slave_setup
0158     .endm
0159 
0160 #define USE_KEXEC_SMP_WAIT_FINAL
0161     .macro  kexec_smp_wait_final
0162     .set push
0163     .set noreorder
0164     synci       0($0)
0165     .set pop
0166     .endm
0167 
0168 #endif /* __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H */