uboot/arch/arm/mach-tegra/tegra124/psci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2015, Siemens AG
   4 * Author: Jan Kiszka <jan.kiszka@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
  15static void park_cpu(void)
  16{
  17        while (1)
  18                asm volatile("wfi");
  19}
  20
  21/**
  22 * Initialize power management for application processors
  23 */
  24void 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