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