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