diff options
author | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
---|---|---|
committer | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c')
-rw-r--r-- | roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c b/roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c new file mode 100644 index 000000000..ab102a622 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2015, Siemens AG + * Author: Jan Kiszka <jan.kiszka@siemens.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/psci.h> +#include <asm/arch/flow.h> +#include <asm/arch/powergate.h> +#include <asm/arch-tegra/ap.h> +#include <asm/arch-tegra/pmc.h> + +static void park_cpu(void) +{ + while (1) + asm volatile("wfi"); +} + +/** + * Initialize power management for application processors + */ +void psci_board_init(void) +{ + struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; + + writel((u32)park_cpu, EXCEP_VECTOR_CPU_RESET_VECTOR); + + /* + * The naturally expected order of putting these CPUs under Flow + * Controller regime would be + * - configure the Flow Controller + * - power up the CPUs + * - wait for the CPUs to hit wfi and be powered down again + * + * However, this doesn't work in practice. We rather need to power them + * up first and park them in wfi. While they are waiting there, we can + * indeed program the Flow Controller to powergate them on wfi, which + * will then happen immediately as they are already in that state. + */ + 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(&flow->cpu1_csr) & CSR_PWR_OFF_STS) || + !(readl(&flow->cpu2_csr) & CSR_PWR_OFF_STS) || + !(readl(&flow->cpu3_csr) & CSR_PWR_OFF_STS)) + /* wait */; +} |