u-boot-brain/arch/arm/mach-tegra/psci.S
Jan Kiszka ffdf9f9ae0 tegra124: Add PSCI support for Tegra124
This is based on Thierry Reding's work and uses Ian Campell's
preparatory patches. It comes with full support for CPU_ON/OFF PSCI
services. The algorithm used in this version for turning CPUs on and
off was proposed by Peter De Schrijver and Thierry Reding in
http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/210881. It
consists of first enabling CPU1..3 via the PMC, just to powergate them
again with the help of the Flow Controller. Once the Flow Controller is
in place, we can leave the PMC alone while processing CPU_ON and CPU_OFF
PSCI requests.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Tom Warren <twarren@nvidia.com>
2015-05-13 09:24:15 -07:00

102 lines
2.0 KiB
ArmAsm

/*
* Copyright (C) 2014, NVIDIA
* Copyright (C) 2015, Siemens AG
*
* Authors:
* Thierry Reding <treding@nvidia.com>
* Jan Kiszka <jan.kiszka@siemens.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <linux/linkage.h>
#include <asm/macro.h>
#include <asm/psci.h>
.pushsection ._secure.text, "ax"
.arch_extension sec
#define TEGRA_SB_CSR_0 0x6000c200
#define NS_RST_VEC_WR_DIS (1 << 1)
#define TEGRA_RESET_EXCEPTION_VECTOR 0x6000f100
#define TEGRA_FLOW_CTRL_BASE 0x60007000
#define FLOW_CTRL_CPU_CSR 0x08
#define CSR_ENABLE (1 << 0)
#define CSR_IMMEDIATE_WAKE (1 << 3)
#define CSR_WAIT_WFI_SHIFT 8
#define FLOW_CTRL_CPU1_CSR 0x18
@ converts CPU ID into FLOW_CTRL_CPUn_CSR offset
.macro get_csr_reg cpu, ofs, tmp
cmp \cpu, #0 @ CPU0?
lsl \tmp, \cpu, #3 @ multiple by 8 (register offset CPU1-3)
moveq \ofs, #FLOW_CTRL_CPU_CSR
addne \ofs, \tmp, #FLOW_CTRL_CPU1_CSR - 8
.endm
ENTRY(psci_arch_init)
mov r6, lr
mrc p15, 0, r5, c1, c1, 0 @ Read SCR
bic r5, r5, #1 @ Secure mode
mcr p15, 0, r5, c1, c1, 0 @ Write SCR
isb
@ lock reset vector for non-secure
ldr r4, =TEGRA_SB_CSR_0
ldr r5, [r4]
orr r5, r5, #NS_RST_VEC_WR_DIS
str r5, [r4]
bl psci_get_cpu_id @ CPU ID => r0
bl psci_get_cpu_stack_top @ stack top => r0
mov sp, r0
bx r6
ENDPROC(psci_arch_init)
ENTRY(psci_cpu_off)
bl psci_cpu_off_common
bl psci_get_cpu_id @ CPU ID => r0
get_csr_reg r0, r2, r3
ldr r6, =TEGRA_FLOW_CTRL_BASE
mov r5, #(CSR_ENABLE)
mov r4, #(1 << CSR_WAIT_WFI_SHIFT)
add r5, r4, lsl r0
str r5, [r6, r2]
_loop: wfi
b _loop
ENDPROC(psci_cpu_off)
ENTRY(psci_cpu_on)
push {lr}
mov r0, r1
bl psci_get_cpu_stack_top @ get stack top of target CPU
str r2, [r0] @ store target PC at stack top
dsb
ldr r6, =TEGRA_RESET_EXCEPTION_VECTOR
ldr r5, =psci_cpu_entry
str r5, [r6]
get_csr_reg r1, r2, r3
ldr r6, =TEGRA_FLOW_CTRL_BASE
mov r5, #(CSR_IMMEDIATE_WAKE | CSR_ENABLE)
str r5, [r6, r2]
mov r0, #ARM_PSCI_RET_SUCCESS @ Return PSCI_RET_SUCCESS
pop {pc}
ENDPROC(psci_cpu_on)
.globl psci_text_end
psci_text_end:
.popsection