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 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 */ 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