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