1/* 2 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights 3 * reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the NetLogic 9 * license below: 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in 19 * the documentation and/or other materials provided with the 20 * distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 31 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 32 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35#include <linux/init.h> 36 37#include <asm/asm.h> 38#include <asm/asm-offsets.h> 39#include <asm/regdef.h> 40#include <asm/mipsregs.h> 41#include <asm/stackframe.h> 42#include <asm/asmmacro.h> 43#include <asm/addrspace.h> 44 45#include <asm/netlogic/common.h> 46 47#include <asm/netlogic/xlp-hal/iomap.h> 48#include <asm/netlogic/xlp-hal/xlp.h> 49#include <asm/netlogic/xlp-hal/sys.h> 50#include <asm/netlogic/xlp-hal/cpucontrol.h> 51 52#define CP0_EBASE $15 53#define SYS_CPU_COHERENT_BASE(node) CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \ 54 XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \ 55 SYS_CPU_NONCOHERENT_MODE * 4 56 57.macro __config_lsu 58 li t0, LSU_DEFEATURE 59 mfcr t1, t0 60 61 lui t2, 0x4080 /* Enable Unaligned Access, L2HPE */ 62 or t1, t1, t2 63 li t2, ~0xe /* S1RCM */ 64 and t1, t1, t2 65 mtcr t1, t0 66 67 li t0, SCHED_DEFEATURE 68 lui t1, 0x0100 /* Experimental: Disable BRU accepting ALU ops */ 69 mtcr t1, t0 70.endm 71 72/* 73 * The cores can come start when they are woken up. This is also the NMI 74 * entry, so check that first. 75 * 76 * The data corresponding to reset is stored at RESET_DATA_PHYS location, 77 * this will have the thread mask (used when core is woken up) and the 78 * current NMI handler in case we reached here for an NMI. 79 * 80 * When a core or thread is newly woken up, it loops in a 'wait'. When 81 * the CPU really needs waking up, we send an NMI to it, with the NMI 82 * handler set to prom_boot_secondary_cpus 83 */ 84 85 .set noreorder 86 .set noat 87 .set arch=xlr /* for mfcr/mtcr, XLR is sufficient */ 88 89FEXPORT(nlm_reset_entry) 90 dmtc0 k0, $22, 6 91 dmtc0 k1, $22, 7 92 mfc0 k0, CP0_STATUS 93 li k1, 0x80000 94 and k1, k0, k1 95 beqz k1, 1f /* go to real reset entry */ 96 nop 97 li k1, CKSEG1ADDR(RESET_DATA_PHYS) /* NMI */ 98 ld k0, BOOT_NMI_HANDLER(k1) 99 jr k0 100 nop 101 1021: /* Entry point on core wakeup */ 103 mfc0 t0, CP0_EBASE, 1 104 mfc0 t1, CP0_EBASE, 1 105 srl t1, 5 106 andi t1, 0x3 /* t1 <- node */ 107 li t2, 0x40000 108 mul t3, t2, t1 /* t3 = node * 0x40000 */ 109 srl t0, t0, 2 110 and t0, t0, 0x7 /* t0 <- core */ 111 li t1, 0x1 112 sll t0, t1, t0 113 nor t0, t0, zero /* t0 <- ~(1 << core) */ 114 li t2, SYS_CPU_COHERENT_BASE(0) 115 add t2, t2, t3 /* t2 <- SYS offset for node */ 116 lw t1, 0(t2) 117 and t1, t1, t0 118 sw t1, 0(t2) 119 120 /* read back to ensure complete */ 121 lw t1, 0(t2) 122 sync 123 124 /* Configure LSU on Non-0 Cores. */ 125 __config_lsu 126 127/* 128 * Wake up sibling threads from the initial thread in 129 * a core. 130 */ 131EXPORT(nlm_boot_siblings) 132 li t0, CKSEG1ADDR(RESET_DATA_PHYS) 133 lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */ 134 li t0, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE) 135 mfcr t2, t0 136 or t2, t2, t1 137 mtcr t2, t0 138 139 /* 140 * The new hardware thread starts at the next instruction 141 * For all the cases other than core 0 thread 0, we will 142 * jump to the secondary wait function. 143 */ 144 mfc0 v0, CP0_EBASE, 1 145 andi v0, 0x7f /* v0 <- node/core */ 146 147#if 1 148 /* A0 errata - Write MMU_SETUP after changing thread mode register. */ 149 andi v1, v0, 0x3 /* v1 <- thread id */ 150 bnez v1, 2f 151 nop 152 153 li t0, MMU_SETUP 154 li t1, 0 155 mtcr t1, t0 156 ehb 157#endif 158 1592: beqz v0, 4f 160 nop 161 162 /* setup status reg */ 163 mfc0 t1, CP0_STATUS 164 li t0, ST0_BEV 165 or t1, t0 166 xor t1, t0 167#ifdef CONFIG_64BIT 168 ori t1, ST0_KX 169#endif 170 mtc0 t1, CP0_STATUS 171 /* mark CPU ready */ 172 PTR_LA t1, nlm_cpu_ready 173 sll v1, v0, 2 174 PTR_ADDU t1, v1 175 li t2, 1 176 sw t2, 0(t1) 177 /* Wait until NMI hits */ 1783: wait 179 j 3b 180 nop 181 182 /* 183 * For the boot CPU, we have to restore registers and 184 * return 185 */ 1864: dmfc0 t0, $4, 2 /* restore SP from UserLocal */ 187 li t1, 0xfadebeef 188 dmtc0 t1, $4, 2 /* restore SP from UserLocal */ 189 PTR_SUBU sp, t0, PT_SIZE 190 RESTORE_ALL 191 jr ra 192 nop 193EXPORT(nlm_reset_entry_end) 194 195FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */ 196 __config_lsu 197 dmtc0 sp, $4, 2 /* SP saved in UserLocal */ 198 SAVE_ALL 199 sync 200 /* find the location to which nlm_boot_siblings was relocated */ 201 li t0, CKSEG1ADDR(RESET_VEC_PHYS) 202 dla t1, nlm_reset_entry 203 dla t2, nlm_boot_siblings 204 dsubu t2, t1 205 daddu t2, t0 206 /* call it */ 207 jr t2 208 nop 209 /* not reached */ 210 211 __CPUINIT 212NESTED(nlm_boot_secondary_cpus, 16, sp) 213 PTR_LA t1, nlm_next_sp 214 PTR_L sp, 0(t1) 215 PTR_LA t1, nlm_next_gp 216 PTR_L gp, 0(t1) 217 218 /* a0 has the processor id */ 219 PTR_LA t0, nlm_early_init_secondary 220 jalr t0 221 nop 222 223 PTR_LA t0, smp_bootstrap 224 jr t0 225 nop 226END(nlm_boot_secondary_cpus) 227 __FINIT 228 229/* 230 * In case of RMIboot bootloader which is used on XLR boards, the CPUs 231 * be already woken up and waiting in bootloader code. 232 * This will get them out of the bootloader code and into linux. Needed 233 * because the bootloader area will be taken and initialized by linux. 234 */ 235 __CPUINIT 236NESTED(nlm_rmiboot_preboot, 16, sp) 237 mfc0 t0, $15, 1 # read ebase 238 andi t0, 0x1f # t0 has the processor_id() 239 andi t2, t0, 0x3 # thread no 240 sll t0, 2 # offset in cpu array 241 242 PTR_LA t1, nlm_cpu_ready # mark CPU ready 243 PTR_ADDU t1, t0 244 li t3, 1 245 sw t3, 0(t1) 246 247 bnez t2, 1f # skip thread programming 248 nop # for non zero hw threads 249 250 /* 251 * MMU setup only for first thread in core 252 */ 253 li t0, 0x400 254 mfcr t1, t0 255 li t2, 6 # XLR thread mode mask 256 nor t3, t2, zero 257 and t2, t1, t2 # t2 - current thread mode 258 li v0, CKSEG1ADDR(RESET_DATA_PHYS) 259 lw v1, BOOT_THREAD_MODE(v0) # v1 - new thread mode 260 sll v1, 1 261 beq v1, t2, 1f # same as request value 262 nop # nothing to do */ 263 264 and t2, t1, t3 # mask out old thread mode 265 or t1, t2, v1 # put in new value 266 mtcr t1, t0 # update core control 267 2681: wait 269 j 1b 270 nop 271END(nlm_rmiboot_preboot) 272 __FINIT 273