]> git.sur5r.net Git - u-boot/blob - arch/arm/mach-tegra/tegra124/psci.c
ARM: rmobile: Add R8A77995 SoC
[u-boot] / arch / arm / mach-tegra / tegra124 / psci.c
1 /*
2  * (C) Copyright 2015, Siemens AG
3  * Author: Jan Kiszka <jan.kiszka@siemens.com>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <asm/io.h>
10 #include <asm/psci.h>
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>
15
16 static void park_cpu(void)
17 {
18         while (1)
19                 asm volatile("wfi");
20 }
21
22 /**
23  * Initialize power management for application processors
24  */
25 void psci_board_init(void)
26 {
27         struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
28
29         writel((u32)park_cpu, EXCEP_VECTOR_CPU_RESET_VECTOR);
30
31         /*
32          * The naturally expected order of putting these CPUs under Flow
33          * Controller regime would be
34          *  - configure the Flow Controller
35          *  - power up the CPUs
36          *  - wait for the CPUs to hit wfi and be powered down again
37          *
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.
42          */
43         tegra_powergate_power_on(TEGRA_POWERGATE_CPU1);
44         tegra_powergate_power_on(TEGRA_POWERGATE_CPU2);
45         tegra_powergate_power_on(TEGRA_POWERGATE_CPU3);
46
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);
50
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);
54
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))
58                 /* wait */;
59 }