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