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 } 60