2 * (C) Copyright 2015, Siemens AG
3 * Author: Jan Kiszka <jan.kiszka@siemens.com>
5 * SPDX-License-Identifier: GPL-2.0+
11 #include <asm/arch/flow.h>
12 #include <asm/arch/powergate.h>
13 #include <asm/arch-tegra/ap.h>
14 #include <asm/arch-tegra/pmc.h>
16 static void park_cpu(void)
23 * Initialize power management for application processors
25 void psci_board_init(void)
27 struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
29 writel((u32)park_cpu, EXCEP_VECTOR_CPU_RESET_VECTOR);
32 * The naturally expected order of putting these CPUs under Flow
33 * Controller regime would be
34 * - configure the Flow Controller
36 * - wait for the CPUs to hit wfi and be powered down again
38 * However, this doesn't work in practice. We rather need to power them
39 * up first and park them in wfi. While they are waiting there, we can
40 * indeed program the Flow Controller to powergate them on wfi, which
41 * will then happen immediately as they are already in that state.
43 tegra_powergate_power_on(TEGRA_POWERGATE_CPU1);
44 tegra_powergate_power_on(TEGRA_POWERGATE_CPU2);
45 tegra_powergate_power_on(TEGRA_POWERGATE_CPU3);
47 writel((2 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu1_csr);
48 writel((4 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu2_csr);
49 writel((8 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu3_csr);
51 writel(EVENT_MODE_STOP, &flow->halt_cpu1_events);
52 writel(EVENT_MODE_STOP, &flow->halt_cpu2_events);
53 writel(EVENT_MODE_STOP, &flow->halt_cpu3_events);
55 while (!(readl(&flow->cpu1_csr) & CSR_PWR_OFF_STS) ||
56 !(readl(&flow->cpu2_csr) & CSR_PWR_OFF_STS) ||
57 !(readl(&flow->cpu3_csr) & CSR_PWR_OFF_STS))