summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/psci.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/psci.S')
-rw-r--r--arch/arm/mach-tegra/psci.S101
1 files changed, 101 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/psci.S b/arch/arm/mach-tegra/psci.S
new file mode 100644
index 0000000000..e4733e6383
--- /dev/null
+++ b/arch/arm/mach-tegra/psci.S
@@ -0,0 +1,101 @@
+/*
+ * 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