Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 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 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 | /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2022 MediaTek Inc. All rights reserved. * * Author: Weijie Gao <weijie.gao@mediatek.com> */ #include <asm/cm.h> #include <asm/asm.h> #include <asm/regdef.h> #include <asm/cacheops.h> #include <asm/mipsregs.h> #include <asm/addrspace.h> #include <asm/mipsmtregs.h> #include "launch.h" .macro cache_loop curr, end, line_sz, op 10: cache \op, 0(\curr) PTR_ADDU \curr, \curr, \line_sz bne \curr, \end, 10b .endm .set mt /* * Join the coherent domain * a0 = number of cores */ LEAF(join_coherent_domain) /* * Enable coherence and allow interventions from all other cores. * (Write access enabled via GCR_ACCESS by core 0.) */ li t1, 1 sll t1, a0 addiu t1, -1 li t0, KSEG1ADDR(CONFIG_MIPS_CM_BASE) sw t1, GCR_Cx_COHERENCE(t0) ehb move t2, zero _next_coherent_core: sll t1, t2, GCR_Cx_OTHER_CORENUM_SHIFT sw t1, GCR_Cx_OTHER(t0) _busy_wait_coherent_core: lw t1, GCR_CO_COHERENCE(t0) beqz t1, _busy_wait_coherent_core addiu t2, 1 bne t2, a0, _next_coherent_core jr ra END(join_coherent_domain) /* * All VPEs other than VPE0 will go here. */ LEAF(launch_vpe_entry) mfc0 t0, CP0_EBASE and t0, t0, MIPS_EBASE_CPUNUM /* per-VPE cpulaunch_t */ li a0, KSEG0ADDR(CPULAUNCH) sll t1, t0, LOG2CPULAUNCH addu a0, t1 /* Set CPU online flag */ li t0, LAUNCH_FREADY sw t0, LAUNCH_FLAGS(a0) /* Enable count interrupt in mask, but do not enable interrupts */ mfc0 t0, CP0_STATUS ori t0, STATUSF_IP7 mtc0 t0, CP0_STATUS /* VPEs executing in wait code do not need a stack */ li t9, KSEG0ADDR(LAUNCH_WAITCODE) jr t9 END(launch_vpe_entry) /* * This function will not be executed in place. * It will be copied into memory, and VPEs other than VPE0 will be * started to run into this in-memory function. */ LEAF(launch_wait_code) .globl launch_wait_code_start launch_wait_code_start: move t0, a0 start_poll: /* Poll CPU go flag */ mtc0 zero, CP0_COUNT li t1, LAUNCHPERIOD mtc0 t1, CP0_COMPARE time_wait: /* Software wait */ mfc0 t2, CP0_COUNT subu t2, t1 bltz t2, time_wait /* Check the launch flag */ lw t3, LAUNCH_FLAGS(t0) and t3, LAUNCH_FGO beqz t3, start_poll /* Reset the counter and interrupts to give naive clients a chance */ mfc0 t1, CP0_STATUS ins t1, zero, STATUSB_IP7, 1 mtc0 t1, CP0_STATUS mfc0 t1, CP0_COUNT subu t1, 1 mtc0 t1, CP0_COMPARE /* Jump to kernel */ lw t9, LAUNCH_PC(t0) lw gp, LAUNCH_GP(t0) lw sp, LAUNCH_SP(t0) lw a0, LAUNCH_A0(t0) move a1, zero move a2, zero move a3, zero ori t3, LAUNCH_FGONE sw t3, LAUNCH_FLAGS(t0) jr t9 .globl launch_wait_code_end launch_wait_code_end: END(launch_wait_code) /* * Core1 will go here. */ LEAF(launch_core_entry) /* Disable caches */ bal mips_cache_disable /* Initialize L1 cache only */ li a0, CONFIG_SYS_ICACHE_SIZE li a1, CONFIG_SYS_ICACHE_LINE_SIZE li a2, CONFIG_SYS_DCACHE_SIZE li a3, CONFIG_SYS_DCACHE_LINE_SIZE mtc0 zero, CP0_TAGLO mtc0 zero, CP0_TAGLO, 2 ehb /* * Initialize the I-cache first, */ li t0, KSEG0 addu t1, t0, a0 /* clear tag to invalidate */ cache_loop t0, t1, a1, INDEX_STORE_TAG_I #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD /* fill once, so data field parity is correct */ PTR_LI t0, KSEG0 cache_loop t0, t1, a1, FILL /* invalidate again - prudent but not strictly necessary */ PTR_LI t0, KSEG0 cache_loop t0, t1, a1, INDEX_STORE_TAG_I #endif /* * then initialize D-cache. */ PTR_LI t0, KSEG0 PTR_ADDU t1, t0, a2 /* clear all tags */ cache_loop t0, t1, a3, INDEX_STORE_TAG_D #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD /* load from each line (in cached space) */ PTR_LI t0, KSEG0 2: LONG_L zero, 0(t0) PTR_ADDU t0, a3 bne t0, t1, 2b /* clear all tags */ PTR_LI t0, KSEG0 cache_loop t0, t1, a3, INDEX_STORE_TAG_D #endif /* Set Cache Mode */ mfc0 t0, CP0_CONFIG li t1, CONF_CM_CACHABLE_COW ins t0, t1, 0, 3 mtc0 t0, CP0_CONFIG /* Join the coherent domain */ li a0, 2 bal join_coherent_domain /* Bootup Core0/VPE1 */ bal boot_vpe1 b launch_vpe_entry END(launch_core_entry) /* * Bootup VPE1. * This subroutine must be executed from VPE0 with VPECONF0[MVP] already set. */ LEAF(boot_vpe1) mfc0 t0, CP0_MVPCONF0 /* a0 = number of TCs - 1 */ ext a0, t0, MVPCONF0_PTC_SHIFT, 8 beqz a0, _vpe1_init_done /* a1 = number of VPEs - 1 */ ext a1, t0, MVPCONF0_PVPE_SHIFT, 4 beqz a1, _vpe1_init_done /* a2 = current TC No. */ move a2, zero /* Enter VPE Configuration State */ mfc0 t0, CP0_MVPCONTROL or t0, MVPCONTROL_VPC mtc0 t0, CP0_MVPCONTROL ehb _next_tc: /* Set the TC number to be used on MTTR and MFTR instructions */ mfc0 t0, CP0_VPECONTROL ins t0, a2, 0, 8 mtc0 t0, CP0_VPECONTROL ehb /* TC0 is already bound */ beqz a2, _next_vpe /* Halt current TC */ li t0, TCHALT_H mttc0 t0, CP0_TCHALT ehb /* If there is spare TC, bind it to the last VPE (VPE[a1]) */ slt t1, a1, a2 bnez t1, _vpe_bind_tc move t1, a1 /* Set Exclusive TC for active TC */ mftc0 t0, CP0_VPECONF0 ins t0, a2, VPECONF0_XTC_SHIFT, 8 mttc0 t0, CP0_VPECONF0 move t1, a2 _vpe_bind_tc: /* Bind TC to a VPE */ mftc0 t0, CP0_TCBIND ins t0, t1, TCBIND_CURVPE_SHIFT, 4 mttc0 t0, CP0_TCBIND /* * Set up CP0_TCSTATUS register: * Disable Coprocessor Usable bits * Disable MDMX/DSP ASE * Clear Dirty TC * not dynamically allocatable * not allocated * Kernel mode * interrupt exempt * ASID 0 */ li t0, TCSTATUS_IXMT mttc0 t0, CP0_TCSTATUS _next_vpe: slt t1, a1, a2 bnez t1, _done_vpe # No more VPEs /* Disable TC multi-threading */ mftc0 t0, CP0_VPECONTROL ins t0, zero, VPECONTROL_TE_SHIFT, 1 mttc0 t0, CP0_VPECONTROL /* Skip following configuration for TC0 */ beqz a2, _done_vpe /* Deactivate VPE, set Master VPE */ mftc0 t0, CP0_VPECONF0 ins t0, zero, VPECONF0_VPA_SHIFT, 1 or t0, VPECONF0_MVP mttc0 t0, CP0_VPECONF0 mfc0 t0, CP0_STATUS mttc0 t0, CP0_STATUS mttc0 zero, CP0_EPC mttc0 zero, CP0_CAUSE mfc0 t0, CP0_CONFIG mttc0 t0, CP0_CONFIG /* * VPE1 of each core can execute cached as its L1 I$ has already * been initialized. * and the L2$ has been initialized or "disabled" via CCA override. */ PTR_LA t0, _start mttc0 t0, CP0_TCRESTART /* Unset Interrupt Exempt, set Activate Thread */ mftc0 t0, CP0_TCSTATUS ins t0, zero, TCSTATUS_IXMT_SHIFT, 1 ori t0, TCSTATUS_A mttc0 t0, CP0_TCSTATUS /* Resume TC */ mttc0 zero, CP0_TCHALT /* Activate VPE */ mftc0 t0, CP0_VPECONF0 ori t0, VPECONF0_VPA mttc0 t0, CP0_VPECONF0 _done_vpe: addu a2, 1 sltu t0, a0, a2 beqz t0, _next_tc mfc0 t0, CP0_MVPCONTROL /* Enable all activated VPE to execute */ ori t0, MVPCONTROL_EVP /* Exit VPE Configuration State */ ins t0, zero, MVPCONTROL_VPC_SHIFT, 1 mtc0 t0, CP0_MVPCONTROL ehb _vpe1_init_done: jr ra END(boot_vpe1) |