mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-05-02 17:00:53 +00:00

Enforce full include path for includes. Deprecate old paths. The following folders inside include/lib have been left unchanged: - include/lib/cpus/${ARCH} - include/lib/el3_runtime/${ARCH} The reason for this change is that having a global namespace for includes isn't a good idea. It defeats one of the advantages of having folders and it introduces problems that are sometimes subtle (because you may not know the header you are actually including if there are two of them). For example, this patch had to be created because two headers were called the same way:e0ea0928d5
("Fix gpio includes of mt8173 platform to avoid collision."). More recently, this patch has had similar problems:46f9b2c3a2
("drivers: add tzc380 support"). This problem was introduced in commit4ecca33988
("Move include and source files to logical locations"). At that time, there weren't too many headers so it wasn't a real issue. However, time has shown that this creates problems. Platforms that want to preserve the way they include headers may add the removed paths to PLAT_INCLUDES, but this is discouraged. Change-Id: I39dc53ed98f9e297a5966e723d1936d6ccf2fc8f Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
219 lines
6.6 KiB
C
219 lines
6.6 KiB
C
/*
|
|
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <assert.h>
|
|
|
|
#include <arch_helpers.h>
|
|
#include <cortex_a53.h>
|
|
#include <common/debug.h>
|
|
#include <drivers/delay_timer.h>
|
|
#include <lib/mmio.h>
|
|
|
|
#include <flowctrl.h>
|
|
#include <pmc.h>
|
|
#include <tegra_def.h>
|
|
|
|
#define CLK_RST_DEV_L_SET 0x300
|
|
#define CLK_RST_DEV_L_CLR 0x304
|
|
#define CLK_BPMP_RST (1 << 1)
|
|
|
|
#define EVP_BPMP_RESET_VECTOR 0x200
|
|
|
|
static const uint64_t flowctrl_offset_cpu_csr[4] = {
|
|
(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU0_CSR),
|
|
(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR),
|
|
(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 8),
|
|
(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 16)
|
|
};
|
|
|
|
static const uint64_t flowctrl_offset_halt_cpu[4] = {
|
|
(TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU0_EVENTS),
|
|
(TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS),
|
|
(TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 8),
|
|
(TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 16)
|
|
};
|
|
|
|
static const uint64_t flowctrl_offset_cc4_ctrl[4] = {
|
|
(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL),
|
|
(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 4),
|
|
(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 8),
|
|
(TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 12)
|
|
};
|
|
|
|
static inline void tegra_fc_cc4_ctrl(int cpu_id, uint32_t val)
|
|
{
|
|
mmio_write_32(flowctrl_offset_cc4_ctrl[cpu_id], val);
|
|
val = mmio_read_32(flowctrl_offset_cc4_ctrl[cpu_id]);
|
|
}
|
|
|
|
static inline void tegra_fc_cpu_csr(int cpu_id, uint32_t val)
|
|
{
|
|
mmio_write_32(flowctrl_offset_cpu_csr[cpu_id], val);
|
|
val = mmio_read_32(flowctrl_offset_cpu_csr[cpu_id]);
|
|
}
|
|
|
|
static inline void tegra_fc_halt_cpu(int cpu_id, uint32_t val)
|
|
{
|
|
mmio_write_32(flowctrl_offset_halt_cpu[cpu_id], val);
|
|
val = mmio_read_32(flowctrl_offset_halt_cpu[cpu_id]);
|
|
}
|
|
|
|
static void tegra_fc_prepare_suspend(int cpu_id, uint32_t csr)
|
|
{
|
|
uint32_t val;
|
|
|
|
val = FLOWCTRL_HALT_GIC_IRQ | FLOWCTRL_HALT_GIC_FIQ |
|
|
FLOWCTRL_HALT_LIC_IRQ | FLOWCTRL_HALT_LIC_FIQ |
|
|
FLOWCTRL_WAITEVENT;
|
|
tegra_fc_halt_cpu(cpu_id, val);
|
|
|
|
val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG |
|
|
FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu_id);
|
|
tegra_fc_cpu_csr(cpu_id, val | csr);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Powerdn the current CPU
|
|
******************************************************************************/
|
|
void tegra_fc_cpu_powerdn(uint32_t mpidr)
|
|
{
|
|
int cpu = mpidr & MPIDR_CPU_MASK;
|
|
|
|
VERBOSE("CPU%d powering down...\n", cpu);
|
|
tegra_fc_prepare_suspend(cpu, 0);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Suspend the current CPU cluster
|
|
******************************************************************************/
|
|
void tegra_fc_cluster_idle(uint32_t mpidr)
|
|
{
|
|
int cpu = mpidr & MPIDR_CPU_MASK;
|
|
uint32_t val;
|
|
|
|
VERBOSE("Entering cluster idle state...\n");
|
|
|
|
tegra_fc_cc4_ctrl(cpu, 0);
|
|
|
|
/* hardware L2 flush is faster for A53 only */
|
|
tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL,
|
|
!!MPIDR_AFFLVL1_VAL(mpidr));
|
|
|
|
/* suspend the CPU cluster */
|
|
val = FLOWCTRL_PG_CPU_NONCPU << FLOWCTRL_ENABLE_EXT;
|
|
tegra_fc_prepare_suspend(cpu, val);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Power down the current CPU cluster
|
|
******************************************************************************/
|
|
void tegra_fc_cluster_powerdn(uint32_t mpidr)
|
|
{
|
|
int cpu = mpidr & MPIDR_CPU_MASK;
|
|
uint32_t val;
|
|
|
|
VERBOSE("Entering cluster powerdn state...\n");
|
|
|
|
tegra_fc_cc4_ctrl(cpu, 0);
|
|
|
|
/* hardware L2 flush is faster for A53 only */
|
|
tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL,
|
|
read_midr() == CORTEX_A53_MIDR);
|
|
|
|
/* power down the CPU cluster */
|
|
val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT;
|
|
tegra_fc_prepare_suspend(cpu, val);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Suspend the entire SoC
|
|
******************************************************************************/
|
|
void tegra_fc_soc_powerdn(uint32_t mpidr)
|
|
{
|
|
int cpu = mpidr & MPIDR_CPU_MASK;
|
|
uint32_t val;
|
|
|
|
VERBOSE("Entering SoC powerdn state...\n");
|
|
|
|
tegra_fc_cc4_ctrl(cpu, 0);
|
|
|
|
tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL, 1);
|
|
|
|
val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT;
|
|
tegra_fc_prepare_suspend(cpu, val);
|
|
|
|
/* overwrite HALT register */
|
|
tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Power up the CPU
|
|
******************************************************************************/
|
|
void tegra_fc_cpu_on(int cpu)
|
|
{
|
|
tegra_fc_cpu_csr(cpu, FLOWCTRL_CSR_ENABLE);
|
|
tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT | FLOWCTRL_HALT_SCLK);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Power down the CPU
|
|
******************************************************************************/
|
|
void tegra_fc_cpu_off(int cpu)
|
|
{
|
|
uint32_t val;
|
|
|
|
/*
|
|
* Flow controller powers down the CPU during wfi. The CPU would be
|
|
* powered on when it receives any interrupt.
|
|
*/
|
|
val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG |
|
|
FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu);
|
|
tegra_fc_cpu_csr(cpu, val);
|
|
tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT);
|
|
tegra_fc_cc4_ctrl(cpu, 0);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Inform the BPMP that we have completed the cluster power up
|
|
******************************************************************************/
|
|
void tegra_fc_lock_active_cluster(void)
|
|
{
|
|
uint32_t val;
|
|
|
|
val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL);
|
|
val |= FLOWCTRL_BPMP_CLUSTER_PWRON_LOCK;
|
|
tegra_fc_write_32(FLOWCTRL_BPMP_CLUSTER_CONTROL, val);
|
|
val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Reset BPMP processor
|
|
******************************************************************************/
|
|
void tegra_fc_reset_bpmp(void)
|
|
{
|
|
uint32_t val;
|
|
|
|
/* halt BPMP */
|
|
tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
|
|
|
|
/* Assert BPMP reset */
|
|
mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
|
|
|
|
/* Restore reset address (stored in PMC_SCRATCH39) */
|
|
val = tegra_pmc_read_32(PMC_SCRATCH39);
|
|
mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, val);
|
|
while (val != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
|
|
; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
|
|
|
|
/* Wait for 2us before de-asserting the reset signal. */
|
|
udelay(2);
|
|
|
|
/* De-assert BPMP reset */
|
|
mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_CLR, CLK_BPMP_RST);
|
|
|
|
/* Un-halt BPMP */
|
|
tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, 0);
|
|
}
|