From patchwork Wed Feb 18 08:14:03 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 440821 X-Patchwork-Delegate: twarren@nvidia.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 3C7C714017E for ; Wed, 18 Feb 2015 19:15:30 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id CCBC64B64D; Wed, 18 Feb 2015 09:15:18 +0100 (CET) X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ABTZXXhLXQbJ; Wed, 18 Feb 2015 09:15:18 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id BF4B64B639; Wed, 18 Feb 2015 09:14:47 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 7BD024A053 for ; Wed, 18 Feb 2015 09:14:33 +0100 (CET) X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Hvev5eCC-Pln for ; Wed, 18 Feb 2015 09:14:33 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from david.siemens.de (david.siemens.de [192.35.17.14]) by theia.denx.de (Postfix) with ESMTPS id 200A14A058 for ; Wed, 18 Feb 2015 09:14:25 +0100 (CET) Received: from mail1.siemens.de (localhost [127.0.0.1]) by david.siemens.de (8.14.3/8.14.3) with ESMTP id t1I8EDTV008216; Wed, 18 Feb 2015 09:14:13 +0100 Received: from md1f2u6c.ww002.siemens.net ([139.22.39.106]) by mail1.siemens.de (8.14.3/8.14.3) with SMTP id t1I8E86V026156; Wed, 18 Feb 2015 09:14:13 +0100 From: Jan Kiszka To: U-Boot Mailing List , Tom Warren Date: Wed, 18 Feb 2015 09:14:03 +0100 Message-Id: <27f92794c702079de414b7fd49c6934710cffdf1.1424247246.git.jan.kiszka@siemens.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: References: In-Reply-To: References: Cc: Paul Walmsley , Ian Campbell , Thierry Reding Subject: [U-Boot] [PATCH v3 09/12] tegra124: Add PSCI support for Tegra124 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" 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 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 --- arch/arm/cpu/armv7/Makefile | 1 + arch/arm/cpu/armv7/tegra-common/Makefile | 1 + arch/arm/cpu/armv7/tegra-common/psci.S | 101 ++++++++++++++++++++++++++++++ arch/arm/cpu/armv7/tegra124/Makefile | 7 +++ arch/arm/cpu/armv7/tegra124/ap.c | 44 +++++++++++++ arch/arm/include/asm/arch-tegra124/flow.h | 5 ++ 6 files changed, 159 insertions(+) create mode 100644 arch/arm/cpu/armv7/tegra-common/psci.S create mode 100644 arch/arm/cpu/armv7/tegra124/Makefile create mode 100644 arch/arm/cpu/armv7/tegra124/ap.c diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile index 409e6f5..616b6cc 100644 --- a/arch/arm/cpu/armv7/Makefile +++ b/arch/arm/cpu/armv7/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_SOCFPGA) += socfpga/ obj-$(if $(filter stv0991,$(SOC)),y) += stv0991/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_TEGRA20) += tegra20/ +obj-$(CONFIG_TEGRA124) += tegra124/ obj-$(CONFIG_U8500) += u8500/ obj-$(CONFIG_ARCH_UNIPHIER) += uniphier/ obj-$(CONFIG_VF610) += vf610/ diff --git a/arch/arm/cpu/armv7/tegra-common/Makefile b/arch/arm/cpu/armv7/tegra-common/Makefile index 463c260..89355ca 100644 --- a/arch/arm/cpu/armv7/tegra-common/Makefile +++ b/arch/arm/cpu/armv7/tegra-common/Makefile @@ -7,4 +7,5 @@ # SPDX-License-Identifier: GPL-2.0+ # +obj-$(CONFIG_ARMV7_PSCI) += psci.o obj-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o diff --git a/arch/arm/cpu/armv7/tegra-common/psci.S b/arch/arm/cpu/armv7/tegra-common/psci.S new file mode 100644 index 0000000..b7501fb --- /dev/null +++ b/arch/arm/cpu/armv7/tegra-common/psci.S @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2014, NVIDIA + * Copyright (C) 2015, Siemens AG + * + * Authors: + * Thierry Reding + * Jan Kiszka + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + + .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 + ldr r4, =TEGRA_SB_CSR_0 + ldr r5, [r4] + orr r5, r5, #NS_RST_VEC_WR_DIS + str r5, [r4] + + mrc p15, 0, r4, c0, c0, 5 @ MPIDR + and r4, r4, #7 @ number of CPUs in cluster + bl psci_get_cpu_stack_top + mov sp, r5 + + bx r6 +ENDPROC(psci_arch_init) + +ENTRY(psci_cpu_off) + bl psci_cpu_off_common + + mrc p15, 0, r1, c0, c0, 5 @ MPIDR + and r1, r1, #7 @ number of CPUs in cluster + + get_csr_reg r1, r2, r3 + + ldr r6, =TEGRA_FLOW_CTRL_BASE + mov r5, #(CSR_ENABLE) + add r5, r1, lsl #CSR_WAIT_WFI_SHIFT + str r5, [r6, r2] + +_loop: wfi + b _loop +ENDPROC(psci_cpu_off) + +ENTRY(psci_cpu_on) + push {lr} + + mov r4, r1 + bl psci_get_cpu_stack_top @ get stack top of target CPU + str r2, [r5] @ 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 diff --git a/arch/arm/cpu/armv7/tegra124/Makefile b/arch/arm/cpu/armv7/tegra124/Makefile new file mode 100644 index 0000000..b907277 --- /dev/null +++ b/arch/arm/cpu/armv7/tegra124/Makefile @@ -0,0 +1,7 @@ +# +# (C) Copyright 2015, Siemens AG +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_ARMV7_PSCI) += ap.o diff --git a/arch/arm/cpu/armv7/tegra124/ap.c b/arch/arm/cpu/armv7/tegra124/ap.c new file mode 100644 index 0000000..eebc0ea --- /dev/null +++ b/arch/arm/cpu/armv7/tegra124/ap.c @@ -0,0 +1,44 @@ +/* + * (C) Copyright 2015, Siemens AG + * Author: Jan Kiszka + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +static void park_cpu(void) +{ + while (1) + asm volatile("wfi"); +} + +void ap_pm_init(void) +{ + struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; + struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE; + + writel((u32)park_cpu, EXCEP_VECTOR_CPU_RESET_VECTOR); + + tegra_powergate_power_on(TEGRA_POWERGATE_CPU1); + tegra_powergate_power_on(TEGRA_POWERGATE_CPU2); + tegra_powergate_power_on(TEGRA_POWERGATE_CPU3); + + writel((2 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu1_csr); + writel((4 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu2_csr); + writel((8 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu3_csr); + + writel(EVENT_MODE_STOP, &flow->halt_cpu1_events); + writel(EVENT_MODE_STOP, &flow->halt_cpu2_events); + writel(EVENT_MODE_STOP, &flow->halt_cpu3_events); + + while (readl(&pmc->pmc_pwrgate_status) & ((1 << TEGRA_POWERGATE_CPU1) | + (1 << TEGRA_POWERGATE_CPU2) | + (1 << TEGRA_POWERGATE_CPU3))) + /* wait */; +} diff --git a/arch/arm/include/asm/arch-tegra124/flow.h b/arch/arm/include/asm/arch-tegra124/flow.h index 0db1881..d5f24a0 100644 --- a/arch/arm/include/asm/arch-tegra124/flow.h +++ b/arch/arm/include/asm/arch-tegra124/flow.h @@ -37,4 +37,9 @@ struct flow_ctlr { /* FLOW_CTLR_CLUSTER_CONTROL_0 0x2c */ #define ACTIVE_LP (1 << 0) +/* CPUn_CSR_0 */ +#define CSR_ENABLE (1 << 0) +#define CSR_IMMEDIATE_WAKE (1 << 3) +#define CSR_WAIT_WFI_SHIFT 8 + #endif /* _TEGRA124_FLOW_H_ */