blob: b7c98b889f260b9cc1671c3a4b40b36d094a09e6 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <asm.h>
#include <arch/asm_macros.h>
#include <arch/defines.h>
tmp .req x9
cpuid .req x12
spintable .req x13
FUNCTION(bcm28xx_park_cpu)
// x0 is current cpuid
// x1 is the address of the spin table
// Save the arguments because we're about to trash x0 and x1
mov cpuid, x0
mov spintable, x1
// Disable the caches and the MMU
mrs tmp, sctlr_el1
bic tmp, tmp, #(1<<0) /* Disable MMU */
bic tmp, tmp, #(1<<12) /* Disable instruction cache */
bic tmp, tmp, #(1<<2) /* Disable data cache */
msr sctlr_el1, tmp
// Write zero into the spin table for the current core because the spin loop
// is programmed to spin until this vector is set to something other than
// 0.
str xzr, [x13, x12, lsl #3]
// Clean-invalidate all levels of the cache for this core.
// This ensures that we don't have cache entries lying around in the core
// after it has been shut down.
// The original implementation can be found in the ARMv8-A TRM or at the
// following URL: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/BABJDBHI.html
mrs x0, clidr_el1
and w3, w0, #0x07000000
lsr w3, w3, #23
cbz w3, finished
mov w10, #0
mov w8, #1
loop1:
add w2, w10, w10, lsr #1
lsr w1, w0, w2
and w1, w1, #0x7
cmp w1, #2
b.lt skip
msr csselr_el1, x10
isb
mrs x1, ccsidr_el1
and w2, w1, #7
add w2, w2, #4
ubfx w4, w1, #3, #10
clz w5, w4
lsl w9, w4, w5
lsl w16, w8, w5
loop2:
ubfx w7, w1, #13, #15
lsl w7, w7, w2
lsl w17, w8, w2
loop3:
orr w11, w10, w9
orr w11, w11, w7
dc cisw, x11
subs w7, w7, w17
b.ge loop3
subs x9, x9, x16
b.ge loop2
skip:
add w10, w10, #2
cmp w3, w10
dsb sy
b.gt loop1
finished:
ic iallu
isb
dsb sy
// Spin until somebody sets our CPU jump vector and signals us via a send event
// (SEV) instruction.
secondary_spin:
wfe
ldr tmp, [spintable, cpuid, lsl #3]
cbz tmp, secondary_spin
// Seconary CPUs shouldn't really care what we pass as arguments, but we
// zero them out anyway.
mov x0, 0
mov x1, 0
mov x2, 0
mov x3, 0
// Follow the new cpu vector.
br tmp
END_FUNCTION(bcm28xx_park_cpu)
/* This .ltorg emits any immediate constants here. We need to put this before
* the bcm28xx_park_cpu_end symbol because we intend to relocate the assembly
* contained within the mexec_asm[_end] block. Any constants needed by this
* block should also be relocated so we need to ensure that they occur before
* bcm28xx_park_cpu_end.
*/
.ltorg
DATA(bcm28xx_park_cpu_end)