GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
+260
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MCE_PRIVATE_H
|
||||
#define MCE_PRIVATE_H
|
||||
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <tegra_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Macros to prepare CSTATE info request
|
||||
******************************************************************************/
|
||||
/* Description of the parameters for UPDATE_CSTATE_INFO request */
|
||||
#define CLUSTER_CSTATE_MASK ULL(0x7)
|
||||
#define CLUSTER_CSTATE_SHIFT U(0)
|
||||
#define CLUSTER_CSTATE_UPDATE_BIT (ULL(1) << 7)
|
||||
#define CCPLEX_CSTATE_MASK ULL(0x3)
|
||||
#define CCPLEX_CSTATE_SHIFT ULL(8)
|
||||
#define CCPLEX_CSTATE_UPDATE_BIT (ULL(1) << 15)
|
||||
#define SYSTEM_CSTATE_MASK ULL(0xF)
|
||||
#define SYSTEM_CSTATE_SHIFT ULL(16)
|
||||
#define SYSTEM_CSTATE_FORCE_UPDATE_SHIFT ULL(22)
|
||||
#define SYSTEM_CSTATE_FORCE_UPDATE_BIT (ULL(1) << 22)
|
||||
#define SYSTEM_CSTATE_UPDATE_BIT (ULL(1) << 23)
|
||||
#define CSTATE_WAKE_MASK_UPDATE_BIT (ULL(1) << 31)
|
||||
#define CSTATE_WAKE_MASK_SHIFT ULL(32)
|
||||
#define CSTATE_WAKE_MASK_CLEAR U(0xFFFFFFFF)
|
||||
|
||||
/*******************************************************************************
|
||||
* Auto-CC3 control macros
|
||||
******************************************************************************/
|
||||
#define MCE_AUTO_CC3_FREQ_MASK U(0x1FF)
|
||||
#define MCE_AUTO_CC3_FREQ_SHIFT U(0)
|
||||
#define MCE_AUTO_CC3_VTG_MASK U(0x7F)
|
||||
#define MCE_AUTO_CC3_VTG_SHIFT U(16)
|
||||
#define MCE_AUTO_CC3_ENABLE_BIT (U(1) << 31)
|
||||
|
||||
/*******************************************************************************
|
||||
* Macros for the 'IS_SC7_ALLOWED' command
|
||||
******************************************************************************/
|
||||
#define MCE_SC7_ALLOWED_MASK U(0x7)
|
||||
#define MCE_SC7_WAKE_TIME_SHIFT U(32)
|
||||
|
||||
/*******************************************************************************
|
||||
* Macros for 'read/write ctats' commands
|
||||
******************************************************************************/
|
||||
#define MCE_CSTATE_STATS_TYPE_SHIFT ULL(32)
|
||||
#define MCE_CSTATE_WRITE_DATA_LO_MASK U(0xF)
|
||||
|
||||
/*******************************************************************************
|
||||
* Macros for 'update crossover threshold' command
|
||||
******************************************************************************/
|
||||
#define MCE_CROSSOVER_THRESHOLD_TIME_SHIFT U(32)
|
||||
|
||||
/*******************************************************************************
|
||||
* MCA argument macros
|
||||
******************************************************************************/
|
||||
#define MCA_ARG_ERROR_MASK U(0xFF)
|
||||
#define MCA_ARG_FINISH_SHIFT U(24)
|
||||
#define MCA_ARG_FINISH_MASK U(0xFF)
|
||||
|
||||
/*******************************************************************************
|
||||
* Uncore PERFMON ARI macros
|
||||
******************************************************************************/
|
||||
#define UNCORE_PERFMON_CMD_READ U(0)
|
||||
#define UNCORE_PERFMON_CMD_WRITE U(1)
|
||||
|
||||
#define UNCORE_PERFMON_CMD_MASK U(0xFF)
|
||||
#define UNCORE_PERFMON_UNIT_GRP_MASK U(0xF)
|
||||
#define UNCORE_PERFMON_SELECTOR_MASK U(0xF)
|
||||
#define UNCORE_PERFMON_REG_MASK U(0xFF)
|
||||
#define UNCORE_PERFMON_CTR_MASK U(0xFF)
|
||||
#define UNCORE_PERFMON_RESP_STATUS_MASK U(0xFF)
|
||||
|
||||
/*******************************************************************************
|
||||
* Structure populated by arch specific code to export routines which perform
|
||||
* common low level MCE functions
|
||||
******************************************************************************/
|
||||
typedef struct arch_mce_ops {
|
||||
/*
|
||||
* This ARI request sets up the MCE to start execution on assertion
|
||||
* of STANDBYWFI, update the core power state and expected wake time,
|
||||
* then determine the proper power state to enter.
|
||||
*/
|
||||
int32_t (*enter_cstate)(uint32_t ari_base, uint32_t state,
|
||||
uint32_t wake_time);
|
||||
/*
|
||||
* This ARI request allows updating of the CLUSTER_CSTATE,
|
||||
* CCPLEX_CSTATE, and SYSTEM_CSTATE register values.
|
||||
*/
|
||||
int32_t (*update_cstate_info)(uint32_t ari_base,
|
||||
uint32_t cluster,
|
||||
uint32_t ccplex,
|
||||
uint32_t system,
|
||||
uint8_t sys_state_force,
|
||||
uint32_t wake_mask,
|
||||
uint8_t update_wake_mask);
|
||||
/*
|
||||
* This ARI request allows updating of power state crossover
|
||||
* threshold times. An index value specifies which crossover
|
||||
* state is being updated.
|
||||
*/
|
||||
int32_t (*update_crossover_time)(uint32_t ari_base,
|
||||
uint32_t type,
|
||||
uint32_t time);
|
||||
/*
|
||||
* This ARI request allows read access to statistical information
|
||||
* related to power states.
|
||||
*/
|
||||
uint64_t (*read_cstate_stats)(uint32_t ari_base,
|
||||
uint32_t state);
|
||||
/*
|
||||
* This ARI request allows write access to statistical information
|
||||
* related to power states.
|
||||
*/
|
||||
int32_t (*write_cstate_stats)(uint32_t ari_base,
|
||||
uint32_t state,
|
||||
uint32_t stats);
|
||||
/*
|
||||
* This ARI request allows the CPU to understand the features
|
||||
* supported by the MCE firmware.
|
||||
*/
|
||||
uint64_t (*call_enum_misc)(uint32_t ari_base, uint32_t cmd,
|
||||
uint32_t data);
|
||||
/*
|
||||
* This ARI request allows querying the CCPLEX to determine if
|
||||
* the CCx state is allowed given a target core C-state and wake
|
||||
* time. If the CCx state is allowed, the response indicates CCx
|
||||
* must be entered. If the CCx state is not allowed, the response
|
||||
* indicates CC6/CC7 can't be entered
|
||||
*/
|
||||
int32_t (*is_ccx_allowed)(uint32_t ari_base, uint32_t state,
|
||||
uint32_t wake_time);
|
||||
/*
|
||||
* This ARI request allows querying the CCPLEX to determine if
|
||||
* the SC7 state is allowed given a target core C-state and wake
|
||||
* time. If the SC7 state is allowed, all cores but the associated
|
||||
* core are offlined (WAKE_EVENTS are set to 0) and the response
|
||||
* indicates SC7 must be entered. If the SC7 state is not allowed,
|
||||
* the response indicates SC7 can't be entered
|
||||
*/
|
||||
int32_t (*is_sc7_allowed)(uint32_t ari_base, uint32_t state,
|
||||
uint32_t wake_time);
|
||||
/*
|
||||
* This ARI request allows a core to bring another offlined core
|
||||
* back online to the C0 state. Note that a core is offlined by
|
||||
* entering a C-state where the WAKE_MASK is all 0.
|
||||
*/
|
||||
int32_t (*online_core)(uint32_t ari_base, uint32_t cpuid);
|
||||
/*
|
||||
* This ARI request allows the CPU to enable/disable Auto-CC3 idle
|
||||
* state.
|
||||
*/
|
||||
int32_t (*cc3_ctrl)(uint32_t ari_base,
|
||||
uint32_t freq,
|
||||
uint32_t volt,
|
||||
uint8_t enable);
|
||||
/*
|
||||
* This ARI request allows updating the reset vector register for
|
||||
* D15 and A57 CPUs.
|
||||
*/
|
||||
int32_t (*update_reset_vector)(uint32_t ari_base);
|
||||
/*
|
||||
* This ARI request instructs the ROC to flush A57 data caches in
|
||||
* order to maintain coherency with the Denver cluster.
|
||||
*/
|
||||
int32_t (*roc_flush_cache)(uint32_t ari_base);
|
||||
/*
|
||||
* This ARI request instructs the ROC to flush A57 data caches along
|
||||
* with the caches covering ARM code in order to maintain coherency
|
||||
* with the Denver cluster.
|
||||
*/
|
||||
int32_t (*roc_flush_cache_trbits)(uint32_t ari_base);
|
||||
/*
|
||||
* This ARI request instructs the ROC to clean A57 data caches along
|
||||
* with the caches covering ARM code in order to maintain coherency
|
||||
* with the Denver cluster.
|
||||
*/
|
||||
int32_t (*roc_clean_cache)(uint32_t ari_base);
|
||||
/*
|
||||
* This ARI request reads/writes the Machine Check Arch. (MCA)
|
||||
* registers.
|
||||
*/
|
||||
uint64_t (*read_write_mca)(uint32_t ari_base,
|
||||
uint64_t cmd,
|
||||
uint64_t *data);
|
||||
/*
|
||||
* Some MC GSC (General Security Carveout) register values are
|
||||
* expected to be changed by TrustZone secure ARM code after boot.
|
||||
* Since there is no hardware mechanism for the CCPLEX to know
|
||||
* that an MC GSC register has changed to allow it to update its
|
||||
* own internal GSC register, there needs to be a mechanism that
|
||||
* can be used by ARM code to cause the CCPLEX to update its GSC
|
||||
* register value. This ARI request allows updating the GSC register
|
||||
* value for a certain carveout in the CCPLEX.
|
||||
*/
|
||||
int32_t (*update_ccplex_gsc)(uint32_t ari_base, uint32_t gsc_idx);
|
||||
/*
|
||||
* This ARI request instructs the CCPLEX to either shutdown or
|
||||
* reset the entire system
|
||||
*/
|
||||
void (*enter_ccplex_state)(uint32_t ari_base, uint32_t state_idx);
|
||||
/*
|
||||
* This ARI request reads/writes data from/to Uncore PERFMON
|
||||
* registers
|
||||
*/
|
||||
int32_t (*read_write_uncore_perfmon)(uint32_t ari_base,
|
||||
uint64_t req, uint64_t *data);
|
||||
/*
|
||||
* This ARI implements ARI_MISC_CCPLEX commands. This can be
|
||||
* used to enable/disable coresight clock gating.
|
||||
*/
|
||||
void (*misc_ccplex)(uint32_t ari_base, uint32_t index,
|
||||
uint32_t value);
|
||||
} arch_mce_ops_t;
|
||||
|
||||
/* declarations for ARI/NVG handler functions */
|
||||
int32_t ari_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time);
|
||||
int32_t ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex,
|
||||
uint32_t system, uint8_t sys_state_force, uint32_t wake_mask,
|
||||
uint8_t update_wake_mask);
|
||||
int32_t ari_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time);
|
||||
uint64_t ari_read_cstate_stats(uint32_t ari_base, uint32_t state);
|
||||
int32_t ari_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats);
|
||||
uint64_t ari_enumeration_misc(uint32_t ari_base, uint32_t cmd, uint32_t data);
|
||||
int32_t ari_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time);
|
||||
int32_t ari_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time);
|
||||
int32_t ari_online_core(uint32_t ari_base, uint32_t core);
|
||||
int32_t ari_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable);
|
||||
int32_t ari_reset_vector_update(uint32_t ari_base);
|
||||
int32_t ari_roc_flush_cache_trbits(uint32_t ari_base);
|
||||
int32_t ari_roc_flush_cache(uint32_t ari_base);
|
||||
int32_t ari_roc_clean_cache(uint32_t ari_base);
|
||||
uint64_t ari_read_write_mca(uint32_t ari_base, uint64_t cmd, uint64_t *data);
|
||||
int32_t ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx);
|
||||
void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx);
|
||||
int32_t ari_read_write_uncore_perfmon(uint32_t ari_base,
|
||||
uint64_t req, uint64_t *data);
|
||||
void ari_misc_ccplex(uint32_t ari_base, uint32_t index, uint32_t value);
|
||||
|
||||
int32_t nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time);
|
||||
int32_t nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex,
|
||||
uint32_t system, uint8_t sys_state_force, uint32_t wake_mask,
|
||||
uint8_t update_wake_mask);
|
||||
int32_t nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time);
|
||||
uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state);
|
||||
int32_t nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats);
|
||||
int32_t nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time);
|
||||
int32_t nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time);
|
||||
int32_t nvg_online_core(uint32_t ari_base, uint32_t core);
|
||||
int32_t nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable);
|
||||
|
||||
extern void nvg_set_request_data(uint64_t req, uint64_t data);
|
||||
extern void nvg_set_request(uint64_t req);
|
||||
extern uint64_t nvg_get_result(void);
|
||||
#endif /* MCE_PRIVATE_H */
|
||||
+437
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef T18X_ARI_H
|
||||
#define T18X_ARI_H
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* t18x_ari.h
|
||||
*
|
||||
* Global ARI definitions.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
enum {
|
||||
TEGRA_ARI_VERSION_MAJOR = 3U,
|
||||
TEGRA_ARI_VERSION_MINOR = 1U,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
/* indexes below get the core lock */
|
||||
TEGRA_ARI_MISC = 0U,
|
||||
/* index 1 is deprecated */
|
||||
/* index 2 is deprecated */
|
||||
/* index 3 is deprecated */
|
||||
TEGRA_ARI_ONLINE_CORE = 4U,
|
||||
|
||||
/* indexes below need cluster lock */
|
||||
TEGRA_ARI_MISC_CLUSTER = 41U,
|
||||
TEGRA_ARI_IS_CCX_ALLOWED = 42U,
|
||||
TEGRA_ARI_CC3_CTRL = 43U,
|
||||
|
||||
/* indexes below need ccplex lock */
|
||||
TEGRA_ARI_ENTER_CSTATE = 80U,
|
||||
TEGRA_ARI_UPDATE_CSTATE_INFO = 81U,
|
||||
TEGRA_ARI_IS_SC7_ALLOWED = 82U,
|
||||
/* index 83 is deprecated */
|
||||
TEGRA_ARI_PERFMON = 84U,
|
||||
TEGRA_ARI_UPDATE_CCPLEX_GSC = 85U,
|
||||
/* index 86 is depracated */
|
||||
/* index 87 is deprecated */
|
||||
TEGRA_ARI_ROC_FLUSH_CACHE_ONLY = 88U,
|
||||
TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS = 89U,
|
||||
TEGRA_ARI_MISC_CCPLEX = 90U,
|
||||
TEGRA_ARI_MCA = 91U,
|
||||
TEGRA_ARI_UPDATE_CROSSOVER = 92U,
|
||||
TEGRA_ARI_CSTATE_STATS = 93U,
|
||||
TEGRA_ARI_WRITE_CSTATE_STATS = 94U,
|
||||
TEGRA_ARI_COPY_MISCREG_AA64_RST = 95U,
|
||||
TEGRA_ARI_ROC_CLEAN_CACHE_ONLY = 96U,
|
||||
} tegra_ari_req_id_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_MISC_ECHO = 0U,
|
||||
TEGRA_ARI_MISC_VERSION = 1U,
|
||||
TEGRA_ARI_MISC_FEATURE_LEAF_0 = 2U,
|
||||
} tegra_ari_misc_index_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF = 0U,
|
||||
TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT = 1U,
|
||||
TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL = 2U,
|
||||
TEGRA_ARI_MISC_CCPLEX_EDBGREQ = 3U,
|
||||
} tegra_ari_misc_ccplex_index_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_CORE_C0 = 0U,
|
||||
TEGRA_ARI_CORE_C1 = 1U,
|
||||
TEGRA_ARI_CORE_C6 = 6U,
|
||||
TEGRA_ARI_CORE_C7 = 7U,
|
||||
TEGRA_ARI_CORE_WARMRSTREQ = 8U,
|
||||
} tegra_ari_core_sleep_state_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_CLUSTER_CC0 = 0U,
|
||||
TEGRA_ARI_CLUSTER_CC1 = 1U,
|
||||
TEGRA_ARI_CLUSTER_CC6 = 6U,
|
||||
TEGRA_ARI_CLUSTER_CC7 = 7U,
|
||||
} tegra_ari_cluster_sleep_state_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_CCPLEX_CCP0 = 0U,
|
||||
TEGRA_ARI_CCPLEX_CCP1 = 1U,
|
||||
TEGRA_ARI_CCPLEX_CCP3 = 3U, /* obsoleted */
|
||||
} tegra_ari_ccplex_sleep_state_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_SYSTEM_SC0 = 0U,
|
||||
TEGRA_ARI_SYSTEM_SC1 = 1U, /* obsoleted */
|
||||
TEGRA_ARI_SYSTEM_SC2 = 2U, /* obsoleted */
|
||||
TEGRA_ARI_SYSTEM_SC3 = 3U, /* obsoleted */
|
||||
TEGRA_ARI_SYSTEM_SC4 = 4U, /* obsoleted */
|
||||
TEGRA_ARI_SYSTEM_SC7 = 7U,
|
||||
TEGRA_ARI_SYSTEM_SC8 = 8U,
|
||||
} tegra_ari_system_sleep_state_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_CROSSOVER_C1_C6 = 0U,
|
||||
TEGRA_ARI_CROSSOVER_CC1_CC6 = 1U,
|
||||
TEGRA_ARI_CROSSOVER_CC1_CC7 = 2U,
|
||||
TEGRA_ARI_CROSSOVER_CCP1_CCP3 = 3U, /* obsoleted */
|
||||
TEGRA_ARI_CROSSOVER_CCP3_SC2 = 4U, /* obsoleted */
|
||||
TEGRA_ARI_CROSSOVER_CCP3_SC3 = 5U, /* obsoleted */
|
||||
TEGRA_ARI_CROSSOVER_CCP3_SC4 = 6U, /* obsoleted */
|
||||
TEGRA_ARI_CROSSOVER_CCP3_SC7 = 7U, /* obsoleted */
|
||||
TEGRA_ARI_CROSSOVER_SC0_SC7 = 7U,
|
||||
TEGRA_ARI_CROSSOVER_CCP3_SC1 = 8U, /* obsoleted */
|
||||
} tegra_ari_crossover_index_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_CSTATE_STATS_CLEAR = 0U,
|
||||
TEGRA_ARI_CSTATE_STATS_SC7_ENTRIES = 1U,
|
||||
TEGRA_ARI_CSTATE_STATS_SC4_ENTRIES, /* obsoleted */
|
||||
TEGRA_ARI_CSTATE_STATS_SC3_ENTRIES, /* obsoleted */
|
||||
TEGRA_ARI_CSTATE_STATS_SC2_ENTRIES, /* obsoleted */
|
||||
TEGRA_ARI_CSTATE_STATS_CCP3_ENTRIES, /* obsoleted */
|
||||
TEGRA_ARI_CSTATE_STATS_A57_CC6_ENTRIES,
|
||||
TEGRA_ARI_CSTATE_STATS_A57_CC7_ENTRIES,
|
||||
TEGRA_ARI_CSTATE_STATS_D15_CC6_ENTRIES,
|
||||
TEGRA_ARI_CSTATE_STATS_D15_CC7_ENTRIES,
|
||||
TEGRA_ARI_CSTATE_STATS_D15_0_C6_ENTRIES,
|
||||
TEGRA_ARI_CSTATE_STATS_D15_1_C6_ENTRIES,
|
||||
TEGRA_ARI_CSTATE_STATS_D15_0_C7_ENTRIES = 14U,
|
||||
TEGRA_ARI_CSTATE_STATS_D15_1_C7_ENTRIES,
|
||||
TEGRA_ARI_CSTATE_STATS_A57_0_C7_ENTRIES = 18U,
|
||||
TEGRA_ARI_CSTATE_STATS_A57_1_C7_ENTRIES,
|
||||
TEGRA_ARI_CSTATE_STATS_A57_2_C7_ENTRIES,
|
||||
TEGRA_ARI_CSTATE_STATS_A57_3_C7_ENTRIES,
|
||||
TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_0,
|
||||
TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_1,
|
||||
TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_0 = 26U,
|
||||
TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_1,
|
||||
TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_2,
|
||||
TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_3,
|
||||
} tegra_ari_cstate_stats_index_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_GSC_ALL = 0U,
|
||||
TEGRA_ARI_GSC_BPMP = 6U,
|
||||
TEGRA_ARI_GSC_APE = 7U,
|
||||
TEGRA_ARI_GSC_SPE = 8U,
|
||||
TEGRA_ARI_GSC_SCE = 9U,
|
||||
TEGRA_ARI_GSC_APR = 10U,
|
||||
TEGRA_ARI_GSC_TZRAM = 11U,
|
||||
TEGRA_ARI_GSC_SE = 12U,
|
||||
TEGRA_ARI_GSC_BPMP_TO_SPE = 16U,
|
||||
TEGRA_ARI_GSC_SPE_TO_BPMP = 17U,
|
||||
TEGRA_ARI_GSC_CPU_TZ_TO_BPMP = 18U,
|
||||
TEGRA_ARI_GSC_BPMP_TO_CPU_TZ = 19U,
|
||||
TEGRA_ARI_GSC_CPU_NS_TO_BPMP = 20U,
|
||||
TEGRA_ARI_GSC_BPMP_TO_CPU_NS = 21U,
|
||||
TEGRA_ARI_GSC_IPC_SE_SPE_SCE_BPMP = 22U,
|
||||
TEGRA_ARI_GSC_SC7_RESUME_FW = 23U,
|
||||
TEGRA_ARI_GSC_TZ_DRAM_IDX = 34U,
|
||||
TEGRA_ARI_GSC_VPR_IDX = 35U,
|
||||
} tegra_ari_gsc_index_t;
|
||||
|
||||
/* This macro will produce enums for __name##_LSB, __name##_MSB and __name##_MSK */
|
||||
#define TEGRA_ARI_ENUM_MASK_LSB_MSB(__name, __lsb, __msb) __name##_LSB = __lsb, __name##_MSB = __msb
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CLUSTER_CSTATE, 0U, 2U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CLUSTER_CSTATE_PRESENT, 7U, 7U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CCPLEX_CSTATE, 8U, 9U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CCPLEX_CSTATE_PRESENT, 15U, 15U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__SYSTEM_CSTATE, 16U, 19U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__IGNORE_CROSSOVERS, 22U, 22U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__SYSTEM_CSTATE_PRESENT, 23U, 23U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__WAKE_MASK_PRESENT, 31U, 31U),
|
||||
} tegra_ari_update_cstate_info_bitmasks_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL__EN, 0U, 0U),
|
||||
} tegra_ari_misc_ccplex_bitmasks_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__IDLE_FREQ, 0U, 8U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__IDLE_VOLT, 16U, 23U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__ENABLE, 31U, 31U),
|
||||
} tegra_ari_cc3_ctrl_bitmasks_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_MCA_NOP = 0U,
|
||||
TEGRA_ARI_MCA_READ_SERR = 1U,
|
||||
TEGRA_ARI_MCA_WRITE_SERR = 2U,
|
||||
TEGRA_ARI_MCA_CLEAR_SERR = 4U,
|
||||
TEGRA_ARI_MCA_REPORT_SERR = 5U,
|
||||
TEGRA_ARI_MCA_READ_INTSTS = 6U,
|
||||
TEGRA_ARI_MCA_WRITE_INTSTS = 7U,
|
||||
TEGRA_ARI_MCA_READ_PREBOOT_SERR = 8U,
|
||||
} tegra_ari_mca_commands_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_MCA_RD_WR_DPMU = 0U,
|
||||
TEGRA_ARI_MCA_RD_WR_IOB = 1U,
|
||||
TEGRA_ARI_MCA_RD_WR_MCB = 2U,
|
||||
TEGRA_ARI_MCA_RD_WR_CCE = 3U,
|
||||
TEGRA_ARI_MCA_RD_WR_CQX = 4U,
|
||||
TEGRA_ARI_MCA_RD_WR_CTU = 5U,
|
||||
TEGRA_ARI_MCA_RD_WR_JSR_MTS = 7U,
|
||||
TEGRA_ARI_MCA_RD_BANK_INFO = 0x0fU,
|
||||
TEGRA_ARI_MCA_RD_BANK_TEMPLATE = 0x10U,
|
||||
TEGRA_ARI_MCA_RD_WR_SECURE_ACCESS_REGISTER = 0x11U,
|
||||
TEGRA_ARI_MCA_RD_WR_GLOBAL_CONFIG_REGISTER = 0x12U,
|
||||
} tegra_ari_mca_rd_wr_indexes_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_MCA_RD_WR_ASERRX_CTRL = 0U,
|
||||
TEGRA_ARI_MCA_RD_WR_ASERRX_STATUS = 1U,
|
||||
TEGRA_ARI_MCA_RD_WR_ASERRX_ADDR = 2U,
|
||||
TEGRA_ARI_MCA_RD_WR_ASERRX_MISC1 = 3U,
|
||||
TEGRA_ARI_MCA_RD_WR_ASERRX_MISC2 = 4U,
|
||||
} tegra_ari_mca_read_asserx_subindexes_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_SETTING_ENABLES_NS_PERMITTED, 0U, 0U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_READING_STATUS_NS_PERMITTED, 1U, 1U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_PENDING_MCA_ERRORS_NS_PERMITTED, 2U, 2U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_CLEARING_MCA_INTERRUPTS_NS_PERMITTED, 3U, 3U),
|
||||
} tegra_ari_mca_secure_register_bitmasks_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_SERR_ERR_CODE, 0U, 15U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_PWM_ERR, 16U, 16U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_CRAB_ERR, 17U, 17U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_RD_WR_N, 18U, 18U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_UCODE_ERR, 19U, 19U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_PWM, 20U, 23U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_AV, 58U, 58U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_MV, 59U, 59U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_EN, 60U, 60U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_UC, 61U, 61U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_OVF, 62U, 62U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_VAL, 63U, 63U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_ADDR_ADDR, 0U, 41U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_ADDR_UCODE_ERRCD, 42U, 52U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_PWM_ERR, 0U, 0U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_CRAB_ERR, 1U, 1U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_UCODE_ERR, 3U, 3U),
|
||||
} tegra_ari_mca_aserr0_bitmasks_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_SERR_ERR_CODE, 0U, 15U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MSI_ERR, 16U, 16U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_IHI_ERR, 17U, 17U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CRI_ERR, 18U, 18U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MMCRAB_ERR, 19U, 19U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CSI_ERR, 20U, 20U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_RD_WR_N, 21U, 21U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_REQ_ERRT, 22U, 23U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_RESP_ERRT, 24U, 25U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_AV, 58U, 58U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MV, 59U, 59U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_EN, 60U, 60U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_UC, 61U, 61U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_OVF, 62U, 62U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_VAL, 63U, 63U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_AXI_ID, 0U, 7U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_ID, 8U, 27U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_CID, 28U, 31U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_CMD, 32U, 35U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_MSI_ERR, 0U, 0U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_IHI_ERR, 1U, 1U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_CRI_ERR, 2U, 2U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_MMCRAB_ERR, 3U, 3U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_CSI_ERR, 4U, 4U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_MISC_ADDR, 0U, 41U),
|
||||
} tegra_ari_mca_aserr1_bitmasks_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_SERR_ERR_CODE, 0U, 15U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_MC_ERR, 16U, 16U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_SYSRAM_ERR, 17U, 17U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_CLIENT_ID, 18U, 19U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_AV, 58U, 58U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_MV, 59U, 59U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_EN, 60U, 60U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_UC, 61U, 61U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_OVF, 62U, 62U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_VAL, 63U, 63U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_ID, 0U, 17U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_CMD, 18U, 21U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_ADDR, 22U, 53U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_CTRL_EN_MC_ERR, 0U, 0U),
|
||||
} tegra_ari_mca_aserr2_bitmasks_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_SERR_ERR_CODE, 0U, 15U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_TO_ERR, 16U, 16U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_STAT_ERR, 17U, 17U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_DST_ERR, 18U, 18U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_UNC_ERR, 19U, 19U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_MH_ERR, 20U, 20U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_PERR, 21U, 21U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_PSN_ERR, 22U, 22U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_AV, 58U, 58U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_MV, 59U, 59U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_EN, 60U, 60U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_UC, 61U, 61U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_OVF, 62U, 62U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_VAL, 63U, 63U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_ADDR_CMD, 0U, 5U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_ADDR_ADDR, 6U, 47U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_TO, 0U, 0U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_DIV4, 1U, 1U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_TLIMIT, 2U, 11U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_PSN_ERR_CORR_MSK, 12U, 25U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_MORE_INFO, 0U, 17U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_TO_INFO, 18U, 43U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_SRC, 44U, 45U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_TID, 46U, 52U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_TO_ERR, 0U, 0U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_STAT_ERR, 1U, 1U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_DST_ERR, 2U, 2U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_UNC_ERR, 3U, 3U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_MH_ERR, 4U, 4U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_PERR, 5U, 5U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_PSN_ERR, 6U, 19U),
|
||||
} tegra_ari_mca_aserr3_bitmasks_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_SERR_ERR_CODE, 0U, 15U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_SRC_ERR, 16U, 16U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_DST_ERR, 17U, 17U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_REQ_ERR, 18U, 18U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_RSP_ERR, 19U, 19U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_AV, 58U, 58U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_MV, 59U, 59U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_EN, 60U, 60U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_UC, 61U, 61U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_OVF, 62U, 62U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_VAL, 63U, 63U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_CTRL_EN_CPE_ERR, 0U, 0U),
|
||||
} tegra_ari_mca_aserr4_bitmasks_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_SERR_ERR_CODE, 0U, 15U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_CTUPAR, 16U, 16U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_MULTI, 17U, 17U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_AV, 58U, 58U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_MV, 59U, 59U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_EN, 60U, 60U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_UC, 61U, 61U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_OVF, 62U, 62U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_VAL, 63U, 63U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_SRC, 0U, 7U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_ID, 8U, 15U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_DATA, 16U, 26U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_CMD, 32U, 35U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_ADDR, 36U, 45U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_CTRL_EN_CTUPAR, 0U, 0U),
|
||||
} tegra_ari_mca_aserr5_bitmasks_t;
|
||||
|
||||
typedef enum {
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_SERR_ERR_CODE, 0U, 15U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_AV, 58U, 58U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_MV, 59U, 59U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_EN, 60U, 60U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_UC, 61U, 61U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_OVF, 62U, 62U),
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_STAT_VAL, 63U, 63U),
|
||||
|
||||
TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SERR1_ADDR_TBD_INFO, 0U, 63U),
|
||||
} tegra_ari_mca_serr1_bitmasks_t;
|
||||
|
||||
#undef TEGRA_ARI_ENUM_MASK_LSB_MSB
|
||||
|
||||
typedef enum {
|
||||
TEGRA_NVG_CHANNEL_PMIC = 0U,
|
||||
TEGRA_NVG_CHANNEL_POWER_PERF = 1U,
|
||||
TEGRA_NVG_CHANNEL_POWER_MODES = 2U,
|
||||
TEGRA_NVG_CHANNEL_WAKE_TIME = 3U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_INFO = 4U,
|
||||
TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 = 5U,
|
||||
TEGRA_NVG_CHANNEL_CROSSOVER_CC1_CC6 = 6U,
|
||||
TEGRA_NVG_CHANNEL_CROSSOVER_CC1_CC7 = 7U,
|
||||
TEGRA_NVG_CHANNEL_CROSSOVER_CCP1_CCP3 = 8U, /* obsoleted */
|
||||
TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC2 = 9U, /* obsoleted */
|
||||
TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC3 = 10U, /* obsoleted */
|
||||
TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC4 = 11U, /* obsoleted */
|
||||
TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC7 = 12U, /* obsoleted */
|
||||
TEGRA_NVG_CHANNEL_CROSSOVER_SC0_SC7 = 12U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR = 13U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_SC7_ENTRIES = 14U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_SC4_ENTRIES = 15U, /* obsoleted */
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_SC3_ENTRIES = 16U, /* obsoleted */
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_SC2_ENTRIES = 17U, /* obsoleted */
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_CCP3_ENTRIES = 18U, /* obsoleted */
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_CC6_ENTRIES = 19U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_CC7_ENTRIES = 20U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_CC6_ENTRIES = 21U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_CC7_ENTRIES = 22U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_0_C6_ENTRIES = 23U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_1_C6_ENTRIES = 24U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_2_C6_ENTRIES = 25U, /* Reserved (for Denver15 core 2) */
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_3_C6_ENTRIES = 26U, /* Reserved (for Denver15 core 3) */
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_0_C7_ENTRIES = 27U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_1_C7_ENTRIES = 28U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_2_C7_ENTRIES = 29U, /* Reserved (for Denver15 core 2) */
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_3_C7_ENTRIES = 30U, /* Reserved (for Denver15 core 3) */
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_0_C7_ENTRIES = 31U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_1_C7_ENTRIES = 32U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_2_C7_ENTRIES = 33U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_3_C7_ENTRIES = 34U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_0 = 35U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_1 = 36U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_2 = 37U, /* Reserved (for Denver15 core 2) */
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_3 = 38U, /* Reserved (for Denver15 core 3) */
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_0 = 39U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_1 = 40U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_2 = 41U,
|
||||
TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_3 = 42U,
|
||||
TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED = 43U,
|
||||
TEGRA_NVG_CHANNEL_ONLINE_CORE = 44U,
|
||||
TEGRA_NVG_CHANNEL_CC3_CTRL = 45U,
|
||||
TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC1 = 46U, /* obsoleted */
|
||||
TEGRA_NVG_CHANNEL_LAST_INDEX,
|
||||
} tegra_nvg_channel_id_t;
|
||||
|
||||
#endif /* T18X_ARI_H */
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
|
||||
.globl nvg_set_request_data
|
||||
.globl nvg_set_request
|
||||
.globl nvg_get_result
|
||||
|
||||
/* void nvg_set_request_data(uint64_t req, uint64_t data) */
|
||||
func nvg_set_request_data
|
||||
msr s3_0_c15_c1_2, x0
|
||||
msr s3_0_c15_c1_3, x1
|
||||
ret
|
||||
endfunc nvg_set_request_data
|
||||
|
||||
/* void nvg_set_request(uint64_t req) */
|
||||
func nvg_set_request
|
||||
msr s3_0_c15_c1_2, x0
|
||||
ret
|
||||
endfunc nvg_set_request
|
||||
|
||||
/* uint64_t nvg_get_result(void) */
|
||||
func nvg_get_result
|
||||
mrs x0, s3_0_c15_c1_3
|
||||
ret
|
||||
endfunc nvg_get_result
|
||||
+564
@@ -0,0 +1,564 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <denver.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <mce_private.h>
|
||||
#include <t18x_ari.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Register offsets for ARI request/results
|
||||
******************************************************************************/
|
||||
#define ARI_REQUEST 0x0U
|
||||
#define ARI_REQUEST_EVENT_MASK 0x4U
|
||||
#define ARI_STATUS 0x8U
|
||||
#define ARI_REQUEST_DATA_LO 0xCU
|
||||
#define ARI_REQUEST_DATA_HI 0x10U
|
||||
#define ARI_RESPONSE_DATA_LO 0x14U
|
||||
#define ARI_RESPONSE_DATA_HI 0x18U
|
||||
|
||||
/* Status values for the current request */
|
||||
#define ARI_REQ_PENDING 1U
|
||||
#define ARI_REQ_ONGOING 3U
|
||||
#define ARI_REQUEST_VALID_BIT (1U << 8)
|
||||
#define ARI_EVT_MASK_STANDBYWFI_BIT (1U << 7)
|
||||
|
||||
/* default timeout (us) to wait for ARI completion */
|
||||
#define ARI_MAX_RETRY_COUNT U(2000000)
|
||||
|
||||
/*******************************************************************************
|
||||
* ARI helper functions
|
||||
******************************************************************************/
|
||||
static inline uint32_t ari_read_32(uint32_t ari_base, uint32_t reg)
|
||||
{
|
||||
return mmio_read_32((uint64_t)ari_base + (uint64_t)reg);
|
||||
}
|
||||
|
||||
static inline void ari_write_32(uint32_t ari_base, uint32_t val, uint32_t reg)
|
||||
{
|
||||
mmio_write_32((uint64_t)ari_base + (uint64_t)reg, val);
|
||||
}
|
||||
|
||||
static inline uint32_t ari_get_request_low(uint32_t ari_base)
|
||||
{
|
||||
return ari_read_32(ari_base, ARI_REQUEST_DATA_LO);
|
||||
}
|
||||
|
||||
static inline uint32_t ari_get_request_high(uint32_t ari_base)
|
||||
{
|
||||
return ari_read_32(ari_base, ARI_REQUEST_DATA_HI);
|
||||
}
|
||||
|
||||
static inline uint32_t ari_get_response_low(uint32_t ari_base)
|
||||
{
|
||||
return ari_read_32(ari_base, ARI_RESPONSE_DATA_LO);
|
||||
}
|
||||
|
||||
static inline uint32_t ari_get_response_high(uint32_t ari_base)
|
||||
{
|
||||
return ari_read_32(ari_base, ARI_RESPONSE_DATA_HI);
|
||||
}
|
||||
|
||||
static inline void ari_clobber_response(uint32_t ari_base)
|
||||
{
|
||||
ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_LO);
|
||||
ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_HI);
|
||||
}
|
||||
|
||||
static int32_t ari_request_wait(uint32_t ari_base, uint32_t evt_mask, uint32_t req,
|
||||
uint32_t lo, uint32_t hi)
|
||||
{
|
||||
uint32_t retries = (uint32_t)ARI_MAX_RETRY_COUNT;
|
||||
uint32_t status;
|
||||
int32_t ret = 0;
|
||||
|
||||
/* program the request, event_mask, hi and lo registers */
|
||||
ari_write_32(ari_base, lo, ARI_REQUEST_DATA_LO);
|
||||
ari_write_32(ari_base, hi, ARI_REQUEST_DATA_HI);
|
||||
ari_write_32(ari_base, evt_mask, ARI_REQUEST_EVENT_MASK);
|
||||
ari_write_32(ari_base, req | ARI_REQUEST_VALID_BIT, ARI_REQUEST);
|
||||
|
||||
/*
|
||||
* For commands that have an event trigger, we should bypass
|
||||
* ARI_STATUS polling, since MCE is waiting for SW to trigger
|
||||
* the event.
|
||||
*/
|
||||
if (evt_mask != 0U) {
|
||||
ret = 0;
|
||||
} else {
|
||||
/* For shutdown/reboot commands, we dont have to check for timeouts */
|
||||
if ((req == TEGRA_ARI_MISC_CCPLEX) &&
|
||||
((lo == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) ||
|
||||
(lo == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT))) {
|
||||
ret = 0;
|
||||
} else {
|
||||
/*
|
||||
* Wait for the command response for not more than the timeout
|
||||
*/
|
||||
while (retries != 0U) {
|
||||
|
||||
/* read the command status */
|
||||
status = ari_read_32(ari_base, ARI_STATUS);
|
||||
if ((status & (ARI_REQ_ONGOING | ARI_REQ_PENDING)) == 0U) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* delay 1 us */
|
||||
udelay(1);
|
||||
|
||||
/* decrement the retry count */
|
||||
retries--;
|
||||
}
|
||||
|
||||
/* assert if the command timed out */
|
||||
if (retries == 0U) {
|
||||
ERROR("ARI request timed out: req %d on CPU %d\n",
|
||||
req, plat_my_core_pos());
|
||||
assert(retries != 0U);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t ari_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
|
||||
/* check for allowed power state */
|
||||
if ((state != TEGRA_ARI_CORE_C0) &&
|
||||
(state != TEGRA_ARI_CORE_C1) &&
|
||||
(state != TEGRA_ARI_CORE_C6) &&
|
||||
(state != TEGRA_ARI_CORE_C7)) {
|
||||
ERROR("%s: unknown cstate (%d)\n", __func__, state);
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
/* Enter the cstate, to be woken up after wake_time (TSC ticks) */
|
||||
ret = ari_request_wait(ari_base, ARI_EVT_MASK_STANDBYWFI_BIT,
|
||||
(uint32_t)TEGRA_ARI_ENTER_CSTATE, state, wake_time);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex,
|
||||
uint32_t system, uint8_t sys_state_force, uint32_t wake_mask,
|
||||
uint8_t update_wake_mask)
|
||||
{
|
||||
uint64_t val = 0U;
|
||||
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
/* update CLUSTER_CSTATE? */
|
||||
if (cluster != 0U) {
|
||||
val |= (cluster & CLUSTER_CSTATE_MASK) |
|
||||
CLUSTER_CSTATE_UPDATE_BIT;
|
||||
}
|
||||
|
||||
/* update CCPLEX_CSTATE? */
|
||||
if (ccplex != 0U) {
|
||||
val |= ((ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT) |
|
||||
CCPLEX_CSTATE_UPDATE_BIT;
|
||||
}
|
||||
|
||||
/* update SYSTEM_CSTATE? */
|
||||
if (system != 0U) {
|
||||
val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) |
|
||||
(((uint64_t)sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) |
|
||||
SYSTEM_CSTATE_UPDATE_BIT);
|
||||
}
|
||||
|
||||
/* update wake mask value? */
|
||||
if (update_wake_mask != 0U) {
|
||||
val |= CSTATE_WAKE_MASK_UPDATE_BIT;
|
||||
}
|
||||
|
||||
/* set the updated cstate info */
|
||||
return ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_UPDATE_CSTATE_INFO,
|
||||
(uint32_t)val, wake_mask);
|
||||
}
|
||||
|
||||
int32_t ari_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
|
||||
/* sanity check crossover type */
|
||||
if ((type == TEGRA_ARI_CROSSOVER_C1_C6) ||
|
||||
(type > TEGRA_ARI_CROSSOVER_CCP3_SC1)) {
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
/* update crossover threshold time */
|
||||
ret = ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_UPDATE_CROSSOVER, type, time);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t ari_read_cstate_stats(uint32_t ari_base, uint32_t state)
|
||||
{
|
||||
int32_t ret;
|
||||
uint64_t result;
|
||||
|
||||
/* sanity check crossover type */
|
||||
if (state == 0U) {
|
||||
result = EINVAL;
|
||||
} else {
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
ret = ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_CSTATE_STATS, state, 0U);
|
||||
if (ret != 0) {
|
||||
result = EINVAL;
|
||||
} else {
|
||||
result = (uint64_t)ari_get_response_low(ari_base);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t ari_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats)
|
||||
{
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
/* write the cstate stats */
|
||||
return ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_WRITE_CSTATE_STATS,
|
||||
state, stats);
|
||||
}
|
||||
|
||||
uint64_t ari_enumeration_misc(uint32_t ari_base, uint32_t cmd, uint32_t data)
|
||||
{
|
||||
uint64_t resp;
|
||||
int32_t ret;
|
||||
uint32_t local_data = data;
|
||||
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
/* ARI_REQUEST_DATA_HI is reserved for commands other than 'ECHO' */
|
||||
if (cmd != TEGRA_ARI_MISC_ECHO) {
|
||||
local_data = 0U;
|
||||
}
|
||||
|
||||
ret = ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_MISC, cmd, local_data);
|
||||
if (ret != 0) {
|
||||
resp = (uint64_t)ret;
|
||||
} else {
|
||||
/* get the command response */
|
||||
resp = ari_get_response_low(ari_base);
|
||||
resp |= ((uint64_t)ari_get_response_high(ari_base) << 32);
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
int32_t ari_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time)
|
||||
{
|
||||
int32_t ret;
|
||||
uint32_t result;
|
||||
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
ret = ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_IS_CCX_ALLOWED,
|
||||
state & 0x7U, wake_time);
|
||||
if (ret != 0) {
|
||||
ERROR("%s: failed (%d)\n", __func__, ret);
|
||||
result = 0U;
|
||||
} else {
|
||||
result = ari_get_response_low(ari_base) & 0x1U;
|
||||
}
|
||||
|
||||
/* 1 = CCx allowed, 0 = CCx not allowed */
|
||||
return (int32_t)result;
|
||||
}
|
||||
|
||||
int32_t ari_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time)
|
||||
{
|
||||
int32_t ret, result;
|
||||
|
||||
/* check for allowed power state */
|
||||
if ((state != TEGRA_ARI_CORE_C0) && (state != TEGRA_ARI_CORE_C1) &&
|
||||
(state != TEGRA_ARI_CORE_C6) && (state != TEGRA_ARI_CORE_C7)) {
|
||||
ERROR("%s: unknown cstate (%d)\n", __func__, state);
|
||||
result = EINVAL;
|
||||
} else {
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
ret = ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_IS_SC7_ALLOWED, state, wake_time);
|
||||
if (ret != 0) {
|
||||
ERROR("%s: failed (%d)\n", __func__, ret);
|
||||
result = 0;
|
||||
} else {
|
||||
/* 1 = SC7 allowed, 0 = SC7 not allowed */
|
||||
result = (ari_get_response_low(ari_base) != 0U) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t ari_online_core(uint32_t ari_base, uint32_t core)
|
||||
{
|
||||
uint64_t cpu = read_mpidr() & (MPIDR_CPU_MASK);
|
||||
uint64_t cluster = (read_mpidr() & (MPIDR_CLUSTER_MASK)) >>
|
||||
(MPIDR_AFFINITY_BITS);
|
||||
uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
|
||||
int32_t ret;
|
||||
|
||||
/* construct the current CPU # */
|
||||
cpu |= (cluster << 2);
|
||||
|
||||
/* sanity check target core id */
|
||||
if ((core >= MCE_CORE_ID_MAX) || (cpu == (uint64_t)core)) {
|
||||
ERROR("%s: unsupported core id (%d)\n", __func__, core);
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
/*
|
||||
* The Denver cluster has 2 CPUs only - 0, 1.
|
||||
*/
|
||||
if ((impl == DENVER_IMPL) && ((core == 2U) || (core == 3U))) {
|
||||
ERROR("%s: unknown core id (%d)\n", __func__, core);
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
ret = ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_ONLINE_CORE, core, 0U);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t ari_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
/*
|
||||
* If the enable bit is cleared, Auto-CC3 will be disabled by setting
|
||||
* the SW visible voltage/frequency request registers for all non
|
||||
* floorswept cores valid independent of StandbyWFI and disabling
|
||||
* the IDLE voltage/frequency request register. If set, Auto-CC3
|
||||
* will be enabled by setting the ARM SW visible voltage/frequency
|
||||
* request registers for all non floorswept cores to be enabled by
|
||||
* StandbyWFI or the equivalent signal, and always keeping the IDLE
|
||||
* voltage/frequency request register enabled.
|
||||
*/
|
||||
val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\
|
||||
((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\
|
||||
((enable != 0U) ? MCE_AUTO_CC3_ENABLE_BIT : 0U));
|
||||
|
||||
return ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_CC3_CTRL, val, 0U);
|
||||
}
|
||||
|
||||
int32_t ari_reset_vector_update(uint32_t ari_base)
|
||||
{
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
/*
|
||||
* Need to program the CPU reset vector one time during cold boot
|
||||
* and SC7 exit
|
||||
*/
|
||||
(void)ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_COPY_MISCREG_AA64_RST, 0U, 0U);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ari_roc_flush_cache_trbits(uint32_t ari_base)
|
||||
{
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
return ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS, 0U, 0U);
|
||||
}
|
||||
|
||||
int32_t ari_roc_flush_cache(uint32_t ari_base)
|
||||
{
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
return ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_ROC_FLUSH_CACHE_ONLY, 0U, 0U);
|
||||
}
|
||||
|
||||
int32_t ari_roc_clean_cache(uint32_t ari_base)
|
||||
{
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
return ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_ROC_CLEAN_CACHE_ONLY, 0U, 0U);
|
||||
}
|
||||
|
||||
uint64_t ari_read_write_mca(uint32_t ari_base, uint64_t cmd, uint64_t *data)
|
||||
{
|
||||
uint64_t mca_arg_data, result = 0;
|
||||
uint32_t resp_lo, resp_hi;
|
||||
uint32_t mca_arg_err, mca_arg_finish;
|
||||
int32_t ret;
|
||||
|
||||
/* Set data (write) */
|
||||
mca_arg_data = (data != NULL) ? *data : 0ULL;
|
||||
|
||||
/* Set command */
|
||||
ari_write_32(ari_base, (uint32_t)cmd, ARI_RESPONSE_DATA_LO);
|
||||
ari_write_32(ari_base, (uint32_t)(cmd >> 32U), ARI_RESPONSE_DATA_HI);
|
||||
|
||||
ret = ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_MCA,
|
||||
(uint32_t)mca_arg_data,
|
||||
(uint32_t)(mca_arg_data >> 32U));
|
||||
if (ret == 0) {
|
||||
resp_lo = ari_get_response_low(ari_base);
|
||||
resp_hi = ari_get_response_high(ari_base);
|
||||
|
||||
mca_arg_err = resp_lo & MCA_ARG_ERROR_MASK;
|
||||
mca_arg_finish = (resp_hi >> MCA_ARG_FINISH_SHIFT) &
|
||||
MCA_ARG_FINISH_MASK;
|
||||
|
||||
if (mca_arg_finish == 0U) {
|
||||
result = (uint64_t)mca_arg_err;
|
||||
} else {
|
||||
if (data != NULL) {
|
||||
resp_lo = ari_get_request_low(ari_base);
|
||||
resp_hi = ari_get_request_high(ari_base);
|
||||
*data = ((uint64_t)resp_hi << 32U) |
|
||||
(uint64_t)resp_lo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
/* sanity check GSC ID */
|
||||
if (gsc_idx > TEGRA_ARI_GSC_VPR_IDX) {
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
/*
|
||||
* The MCE code will read the GSC carveout value, corrseponding to
|
||||
* the ID, from the MC registers and update the internal GSC registers
|
||||
* of the CCPLEX.
|
||||
*/
|
||||
(void)ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_UPDATE_CCPLEX_GSC, gsc_idx, 0U);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx)
|
||||
{
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
/*
|
||||
* The MCE will shutdown or restart the entire system
|
||||
*/
|
||||
(void)ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_MISC_CCPLEX, state_idx, 0U);
|
||||
}
|
||||
|
||||
int32_t ari_read_write_uncore_perfmon(uint32_t ari_base, uint64_t req,
|
||||
uint64_t *data)
|
||||
{
|
||||
int32_t ret, result;
|
||||
uint32_t val, req_status;
|
||||
uint8_t req_cmd;
|
||||
|
||||
req_cmd = (uint8_t)(req & UNCORE_PERFMON_CMD_MASK);
|
||||
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
|
||||
/* sanity check input parameters */
|
||||
if ((req_cmd == UNCORE_PERFMON_CMD_READ) && (data == NULL)) {
|
||||
ERROR("invalid parameters\n");
|
||||
result = EINVAL;
|
||||
} else {
|
||||
/*
|
||||
* For "write" commands get the value that has to be written
|
||||
* to the uncore perfmon registers
|
||||
*/
|
||||
val = (req_cmd == UNCORE_PERFMON_CMD_WRITE) ?
|
||||
(uint32_t)*data : 0U;
|
||||
|
||||
ret = ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_PERFMON, val, (uint32_t)req);
|
||||
if (ret != 0) {
|
||||
result = ret;
|
||||
} else {
|
||||
/* read the command status value */
|
||||
req_status = ari_get_response_high(ari_base) &
|
||||
UNCORE_PERFMON_RESP_STATUS_MASK;
|
||||
|
||||
/*
|
||||
* For "read" commands get the data from the uncore
|
||||
* perfmon registers
|
||||
*/
|
||||
req_status &= UNCORE_PERFMON_RESP_STATUS_MASK;
|
||||
if ((req_status == 0U) && (req_cmd == UNCORE_PERFMON_CMD_READ)) {
|
||||
*data = ari_get_response_low(ari_base);
|
||||
}
|
||||
result = (int32_t)req_status;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ari_misc_ccplex(uint32_t ari_base, uint32_t index, uint32_t value)
|
||||
{
|
||||
/*
|
||||
* This invokes the ARI_MISC_CCPLEX commands. This can be
|
||||
* used to enable/disable coresight clock gating.
|
||||
*/
|
||||
|
||||
if ((index > TEGRA_ARI_MISC_CCPLEX_EDBGREQ) ||
|
||||
((index == TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL) &&
|
||||
(value > 1U))) {
|
||||
ERROR("%s: invalid parameters \n", __func__);
|
||||
} else {
|
||||
/* clean the previous response state */
|
||||
ari_clobber_response(ari_base);
|
||||
(void)ari_request_wait(ari_base, 0U,
|
||||
(uint32_t)TEGRA_ARI_MISC_CCPLEX, index, value);
|
||||
}
|
||||
}
|
||||
+476
@@ -0,0 +1,476 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <context.h>
|
||||
#include <denver.h>
|
||||
#include <lib/el3_runtime/context_mgmt.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mce.h>
|
||||
#include <mce_private.h>
|
||||
#include <t18x_ari.h>
|
||||
#include <tegra_def.h>
|
||||
#include <tegra_platform.h>
|
||||
|
||||
/* NVG functions handlers */
|
||||
static arch_mce_ops_t nvg_mce_ops = {
|
||||
.enter_cstate = nvg_enter_cstate,
|
||||
.update_cstate_info = nvg_update_cstate_info,
|
||||
.update_crossover_time = nvg_update_crossover_time,
|
||||
.read_cstate_stats = nvg_read_cstate_stats,
|
||||
.write_cstate_stats = nvg_write_cstate_stats,
|
||||
.call_enum_misc = ari_enumeration_misc,
|
||||
.is_ccx_allowed = nvg_is_ccx_allowed,
|
||||
.is_sc7_allowed = nvg_is_sc7_allowed,
|
||||
.online_core = nvg_online_core,
|
||||
.cc3_ctrl = nvg_cc3_ctrl,
|
||||
.update_reset_vector = ari_reset_vector_update,
|
||||
.roc_flush_cache = ari_roc_flush_cache,
|
||||
.roc_flush_cache_trbits = ari_roc_flush_cache_trbits,
|
||||
.roc_clean_cache = ari_roc_clean_cache,
|
||||
.read_write_mca = ari_read_write_mca,
|
||||
.update_ccplex_gsc = ari_update_ccplex_gsc,
|
||||
.enter_ccplex_state = ari_enter_ccplex_state,
|
||||
.read_write_uncore_perfmon = ari_read_write_uncore_perfmon,
|
||||
.misc_ccplex = ari_misc_ccplex
|
||||
};
|
||||
|
||||
/* ARI functions handlers */
|
||||
static arch_mce_ops_t ari_mce_ops = {
|
||||
.enter_cstate = ari_enter_cstate,
|
||||
.update_cstate_info = ari_update_cstate_info,
|
||||
.update_crossover_time = ari_update_crossover_time,
|
||||
.read_cstate_stats = ari_read_cstate_stats,
|
||||
.write_cstate_stats = ari_write_cstate_stats,
|
||||
.call_enum_misc = ari_enumeration_misc,
|
||||
.is_ccx_allowed = ari_is_ccx_allowed,
|
||||
.is_sc7_allowed = ari_is_sc7_allowed,
|
||||
.online_core = ari_online_core,
|
||||
.cc3_ctrl = ari_cc3_ctrl,
|
||||
.update_reset_vector = ari_reset_vector_update,
|
||||
.roc_flush_cache = ari_roc_flush_cache,
|
||||
.roc_flush_cache_trbits = ari_roc_flush_cache_trbits,
|
||||
.roc_clean_cache = ari_roc_clean_cache,
|
||||
.read_write_mca = ari_read_write_mca,
|
||||
.update_ccplex_gsc = ari_update_ccplex_gsc,
|
||||
.enter_ccplex_state = ari_enter_ccplex_state,
|
||||
.read_write_uncore_perfmon = ari_read_write_uncore_perfmon,
|
||||
.misc_ccplex = ari_misc_ccplex
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t ari_base;
|
||||
arch_mce_ops_t *ops;
|
||||
} mce_config_t;
|
||||
|
||||
/* Table to hold the per-CPU ARI base address and function handlers */
|
||||
static mce_config_t mce_cfg_table[MCE_ARI_APERTURES_MAX] = {
|
||||
{
|
||||
/* A57 Core 0 */
|
||||
.ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_0_OFFSET,
|
||||
.ops = &ari_mce_ops,
|
||||
},
|
||||
{
|
||||
/* A57 Core 1 */
|
||||
.ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_1_OFFSET,
|
||||
.ops = &ari_mce_ops,
|
||||
},
|
||||
{
|
||||
/* A57 Core 2 */
|
||||
.ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_2_OFFSET,
|
||||
.ops = &ari_mce_ops,
|
||||
},
|
||||
{
|
||||
/* A57 Core 3 */
|
||||
.ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_3_OFFSET,
|
||||
.ops = &ari_mce_ops,
|
||||
},
|
||||
{
|
||||
/* D15 Core 0 */
|
||||
.ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_4_OFFSET,
|
||||
.ops = &nvg_mce_ops,
|
||||
},
|
||||
{
|
||||
/* D15 Core 1 */
|
||||
.ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_5_OFFSET,
|
||||
.ops = &nvg_mce_ops,
|
||||
}
|
||||
};
|
||||
|
||||
static uint32_t mce_get_curr_cpu_ari_base(void)
|
||||
{
|
||||
uint64_t mpidr = read_mpidr();
|
||||
uint64_t cpuid = mpidr & MPIDR_CPU_MASK;
|
||||
uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
|
||||
|
||||
/*
|
||||
* T186 has 2 CPU clusters, one with Denver CPUs and the other with
|
||||
* ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU
|
||||
* numbers start from 0. In order to get the proper arch_mce_ops_t
|
||||
* struct, we have to convert the Denver CPU ids to the corresponding
|
||||
* indices in the mce_ops_table array.
|
||||
*/
|
||||
if (impl == DENVER_IMPL) {
|
||||
cpuid |= 0x4U;
|
||||
}
|
||||
|
||||
return mce_cfg_table[cpuid].ari_base;
|
||||
}
|
||||
|
||||
static arch_mce_ops_t *mce_get_curr_cpu_ops(void)
|
||||
{
|
||||
uint64_t mpidr = read_mpidr();
|
||||
uint64_t cpuid = mpidr & MPIDR_CPU_MASK;
|
||||
uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) &
|
||||
MIDR_IMPL_MASK;
|
||||
|
||||
/*
|
||||
* T186 has 2 CPU clusters, one with Denver CPUs and the other with
|
||||
* ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU
|
||||
* numbers start from 0. In order to get the proper arch_mce_ops_t
|
||||
* struct, we have to convert the Denver CPU ids to the corresponding
|
||||
* indices in the mce_ops_table array.
|
||||
*/
|
||||
if (impl == DENVER_IMPL) {
|
||||
cpuid |= 0x4U;
|
||||
}
|
||||
|
||||
return mce_cfg_table[cpuid].ops;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Common handler for all MCE commands
|
||||
******************************************************************************/
|
||||
int32_t mce_command_handler(uint64_t cmd, uint64_t arg0, uint64_t arg1,
|
||||
uint64_t arg2)
|
||||
{
|
||||
const arch_mce_ops_t *ops;
|
||||
gp_regs_t *gp_regs = get_gpregs_ctx(cm_get_context(NON_SECURE));
|
||||
uint32_t cpu_ari_base;
|
||||
uint64_t ret64 = 0, arg3, arg4, arg5;
|
||||
int32_t ret = 0;
|
||||
|
||||
assert(gp_regs != NULL);
|
||||
|
||||
/* get a pointer to the CPU's arch_mce_ops_t struct */
|
||||
ops = mce_get_curr_cpu_ops();
|
||||
|
||||
/* get the CPU's ARI base address */
|
||||
cpu_ari_base = mce_get_curr_cpu_ari_base();
|
||||
|
||||
switch (cmd) {
|
||||
case (uint64_t)MCE_CMD_ENTER_CSTATE:
|
||||
ret = ops->enter_cstate(cpu_ari_base, arg0, arg1);
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_UPDATE_CSTATE_INFO:
|
||||
/*
|
||||
* get the parameters required for the update cstate info
|
||||
* command
|
||||
*/
|
||||
arg3 = read_ctx_reg(gp_regs, CTX_GPREG_X4);
|
||||
arg4 = read_ctx_reg(gp_regs, CTX_GPREG_X5);
|
||||
arg5 = read_ctx_reg(gp_regs, CTX_GPREG_X6);
|
||||
|
||||
ret = ops->update_cstate_info(cpu_ari_base, (uint32_t)arg0,
|
||||
(uint32_t)arg1, (uint32_t)arg2, (uint8_t)arg3,
|
||||
(uint32_t)arg4, (uint8_t)arg5);
|
||||
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X4, (0ULL));
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X5, (0ULL));
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X6, (0ULL));
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_UPDATE_CROSSOVER_TIME:
|
||||
ret = ops->update_crossover_time(cpu_ari_base, arg0, arg1);
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_READ_CSTATE_STATS:
|
||||
ret64 = ops->read_cstate_stats(cpu_ari_base, arg0);
|
||||
|
||||
/* update context to return cstate stats value */
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X2, (ret64));
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_WRITE_CSTATE_STATS:
|
||||
ret = ops->write_cstate_stats(cpu_ari_base, arg0, arg1);
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_IS_CCX_ALLOWED:
|
||||
ret = ops->is_ccx_allowed(cpu_ari_base, arg0, arg1);
|
||||
|
||||
/* update context to return CCx status value */
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint64_t)(ret));
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_IS_SC7_ALLOWED:
|
||||
ret = ops->is_sc7_allowed(cpu_ari_base, arg0, arg1);
|
||||
|
||||
/* update context to return SC7 status value */
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint64_t)(ret));
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X3, (uint64_t)(ret));
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_ONLINE_CORE:
|
||||
ret = ops->online_core(cpu_ari_base, arg0);
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_CC3_CTRL:
|
||||
ret = ops->cc3_ctrl(cpu_ari_base, arg0, arg1, arg2);
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_ECHO_DATA:
|
||||
ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_ECHO,
|
||||
arg0);
|
||||
|
||||
/* update context to return if echo'd data matched source */
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X1, ((ret64 == arg0) ?
|
||||
1ULL : 0ULL));
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X2, ((ret64 == arg0) ?
|
||||
1ULL : 0ULL));
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_READ_VERSIONS:
|
||||
ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION,
|
||||
arg0);
|
||||
|
||||
/*
|
||||
* version = minor(63:32) | major(31:0). Update context
|
||||
* to return major and minor version number.
|
||||
*/
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X2, (ret64 >> 32ULL));
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_ENUM_FEATURES:
|
||||
ret64 = ops->call_enum_misc(cpu_ari_base,
|
||||
TEGRA_ARI_MISC_FEATURE_LEAF_0, arg0);
|
||||
|
||||
/* update context to return features value */
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE_TRBITS:
|
||||
ret = ops->roc_flush_cache_trbits(cpu_ari_base);
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE:
|
||||
ret = ops->roc_flush_cache(cpu_ari_base);
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_ROC_CLEAN_CACHE:
|
||||
ret = ops->roc_clean_cache(cpu_ari_base);
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_ENUM_READ_MCA:
|
||||
ret64 = ops->read_write_mca(cpu_ari_base, arg0, &arg1);
|
||||
|
||||
/* update context to return MCA data/error */
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X2, (arg1));
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X3, (ret64));
|
||||
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_ENUM_WRITE_MCA:
|
||||
ret64 = ops->read_write_mca(cpu_ari_base, arg0, &arg1);
|
||||
|
||||
/* update context to return MCA error */
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X1, (ret64));
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X3, (ret64));
|
||||
|
||||
break;
|
||||
|
||||
#if ENABLE_CHIP_VERIFICATION_HARNESS
|
||||
case (uint64_t)MCE_CMD_ENABLE_LATIC:
|
||||
/*
|
||||
* This call is not for production use. The constant value,
|
||||
* 0xFFFF0000, is specific to allowing for enabling LATIC on
|
||||
* pre-production parts for the chip verification harness.
|
||||
*
|
||||
* Enabling LATIC allows S/W to read the MINI ISPs in the
|
||||
* CCPLEX. The ISMs are used for various measurements relevant
|
||||
* to particular locations in the Silicon. They are small
|
||||
* counters which can be polled to determine how fast a
|
||||
* particular location in the Silicon is.
|
||||
*/
|
||||
ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(),
|
||||
0xFFFF0000);
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
case (uint64_t)MCE_CMD_UNCORE_PERFMON_REQ:
|
||||
ret = ops->read_write_uncore_perfmon(cpu_ari_base, arg0, &arg1);
|
||||
|
||||
/* update context to return data */
|
||||
write_ctx_reg(gp_regs, CTX_GPREG_X1, (arg1));
|
||||
break;
|
||||
|
||||
case (uint64_t)MCE_CMD_MISC_CCPLEX:
|
||||
ops->misc_ccplex(cpu_ari_base, arg0, arg1);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR("unknown MCE command (%" PRIu64 ")\n", cmd);
|
||||
ret = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to update the reset vector for CPUs
|
||||
******************************************************************************/
|
||||
int32_t mce_update_reset_vector(void)
|
||||
{
|
||||
const arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
|
||||
|
||||
ops->update_reset_vector(mce_get_curr_cpu_ari_base());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t mce_update_ccplex_gsc(tegra_ari_gsc_index_t gsc_idx)
|
||||
{
|
||||
const arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
|
||||
|
||||
ops->update_ccplex_gsc(mce_get_curr_cpu_ari_base(), gsc_idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to update carveout values for Video Memory Carveout region
|
||||
******************************************************************************/
|
||||
int32_t mce_update_gsc_videomem(void)
|
||||
{
|
||||
return mce_update_ccplex_gsc(TEGRA_ARI_GSC_VPR_IDX);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to update carveout values for TZDRAM aperture
|
||||
******************************************************************************/
|
||||
int32_t mce_update_gsc_tzdram(void)
|
||||
{
|
||||
return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZ_DRAM_IDX);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to shutdown/reset the entire system
|
||||
******************************************************************************/
|
||||
__dead2 void mce_enter_ccplex_state(uint32_t state_idx)
|
||||
{
|
||||
const arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
|
||||
|
||||
/* sanity check state value */
|
||||
if ((state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) &&
|
||||
(state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT)) {
|
||||
panic();
|
||||
}
|
||||
|
||||
ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(), state_idx);
|
||||
|
||||
/* wait till the CCPLEX powers down */
|
||||
for (;;) {
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to issue the UPDATE_CSTATE_INFO request
|
||||
******************************************************************************/
|
||||
void mce_update_cstate_info(const mce_cstate_info_t *cstate)
|
||||
{
|
||||
const arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
|
||||
|
||||
/* issue the UPDATE_CSTATE_INFO request */
|
||||
ops->update_cstate_info(mce_get_curr_cpu_ari_base(), cstate->cluster,
|
||||
cstate->ccplex, cstate->system, cstate->system_state_force,
|
||||
cstate->wake_mask, cstate->update_wake_mask);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to read the MCE firmware version and check if it is compatible
|
||||
* with interface header the BL3-1 was compiled against
|
||||
******************************************************************************/
|
||||
void mce_verify_firmware_version(void)
|
||||
{
|
||||
const arch_mce_ops_t *ops;
|
||||
uint32_t cpu_ari_base;
|
||||
uint64_t version;
|
||||
uint32_t major, minor;
|
||||
|
||||
/*
|
||||
* MCE firmware is not supported on simulation platforms.
|
||||
*/
|
||||
if (tegra_platform_is_emulation()) {
|
||||
|
||||
INFO("MCE firmware is not supported\n");
|
||||
|
||||
} else {
|
||||
/* get a pointer to the CPU's arch_mce_ops_t struct */
|
||||
ops = mce_get_curr_cpu_ops();
|
||||
|
||||
/* get the CPU's ARI base address */
|
||||
cpu_ari_base = mce_get_curr_cpu_ari_base();
|
||||
|
||||
/*
|
||||
* Read the MCE firmware version and extract the major and minor
|
||||
* version fields
|
||||
*/
|
||||
version = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION, 0);
|
||||
major = (uint32_t)version;
|
||||
minor = (uint32_t)(version >> 32);
|
||||
|
||||
INFO("MCE Version - HW=%d:%d, SW=%d:%d\n", major, minor,
|
||||
TEGRA_ARI_VERSION_MAJOR, TEGRA_ARI_VERSION_MINOR);
|
||||
|
||||
/*
|
||||
* Verify that the MCE firmware version and the interface header
|
||||
* match
|
||||
*/
|
||||
if (major != TEGRA_ARI_VERSION_MAJOR) {
|
||||
ERROR("ARI major version mismatch\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
if (minor < TEGRA_ARI_VERSION_MINOR) {
|
||||
ERROR("ARI minor version mismatch\n");
|
||||
panic();
|
||||
}
|
||||
}
|
||||
}
|
||||
+256
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <denver.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mce_private.h>
|
||||
#include <t18x_ari.h>
|
||||
#include <tegra_private.h>
|
||||
|
||||
int32_t nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
uint64_t val = 0ULL;
|
||||
|
||||
(void)ari_base;
|
||||
|
||||
/* check for allowed power state */
|
||||
if ((state != TEGRA_ARI_CORE_C0) && (state != TEGRA_ARI_CORE_C1) &&
|
||||
(state != TEGRA_ARI_CORE_C6) && (state != TEGRA_ARI_CORE_C7)) {
|
||||
ERROR("%s: unknown cstate (%d)\n", __func__, state);
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
/* time (TSC ticks) until the core is expected to get a wake event */
|
||||
nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_WAKE_TIME, wake_time);
|
||||
|
||||
/* set the core cstate */
|
||||
val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
|
||||
write_actlr_el1(val | (uint64_t)state);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and
|
||||
* SYSTEM_CSTATE values.
|
||||
*/
|
||||
int32_t nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex,
|
||||
uint32_t system, uint8_t sys_state_force, uint32_t wake_mask,
|
||||
uint8_t update_wake_mask)
|
||||
{
|
||||
uint64_t val = 0ULL;
|
||||
|
||||
(void)ari_base;
|
||||
|
||||
/* update CLUSTER_CSTATE? */
|
||||
if (cluster != 0U) {
|
||||
val |= ((uint64_t)cluster & CLUSTER_CSTATE_MASK) |
|
||||
CLUSTER_CSTATE_UPDATE_BIT;
|
||||
}
|
||||
|
||||
/* update CCPLEX_CSTATE? */
|
||||
if (ccplex != 0U) {
|
||||
val |= (((uint64_t)ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT) |
|
||||
CCPLEX_CSTATE_UPDATE_BIT;
|
||||
}
|
||||
|
||||
/* update SYSTEM_CSTATE? */
|
||||
if (system != 0U) {
|
||||
val |= (((uint64_t)system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) |
|
||||
(((uint64_t)sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) |
|
||||
SYSTEM_CSTATE_UPDATE_BIT);
|
||||
}
|
||||
|
||||
/* update wake mask value? */
|
||||
if (update_wake_mask != 0U) {
|
||||
val |= CSTATE_WAKE_MASK_UPDATE_BIT;
|
||||
}
|
||||
|
||||
/* set the wake mask */
|
||||
val &= CSTATE_WAKE_MASK_CLEAR;
|
||||
val |= ((uint64_t)wake_mask << CSTATE_WAKE_MASK_SHIFT);
|
||||
|
||||
/* set the updated cstate info */
|
||||
nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_CSTATE_INFO, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
|
||||
(void)ari_base;
|
||||
|
||||
/* sanity check crossover type */
|
||||
if (type > TEGRA_ARI_CROSSOVER_CCP3_SC1) {
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
/*
|
||||
* The crossover threshold limit types start from
|
||||
* TEGRA_CROSSOVER_TYPE_C1_C6 to TEGRA_CROSSOVER_TYPE_CCP3_SC7.
|
||||
* The command indices for updating the threshold be generated
|
||||
* by adding the type to the NVG_SET_THRESHOLD_CROSSOVER_C1_C6
|
||||
* command index.
|
||||
*/
|
||||
nvg_set_request_data((TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 +
|
||||
(uint64_t)type), (uint64_t)time);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state)
|
||||
{
|
||||
uint64_t ret;
|
||||
|
||||
(void)ari_base;
|
||||
|
||||
/* sanity check state */
|
||||
if (state == 0U) {
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
/*
|
||||
* The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES
|
||||
* to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for
|
||||
* reading the threshold can be generated by adding the type to
|
||||
* the NVG_CLEAR_CSTATE_STATS command index.
|
||||
*/
|
||||
nvg_set_request((TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR +
|
||||
(uint64_t)state));
|
||||
ret = nvg_get_result();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
(void)ari_base;
|
||||
|
||||
/*
|
||||
* The only difference between a CSTATE_STATS_WRITE and
|
||||
* CSTATE_STATS_READ is the usage of the 63:32 in the request.
|
||||
* 63:32 are set to '0' for a read, while a write contains the
|
||||
* actual stats value to be written.
|
||||
*/
|
||||
val = ((uint64_t)stats << MCE_CSTATE_STATS_TYPE_SHIFT) | state;
|
||||
|
||||
/*
|
||||
* The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES
|
||||
* to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for
|
||||
* reading the threshold can be generated by adding the type to
|
||||
* the NVG_CLEAR_CSTATE_STATS command index.
|
||||
*/
|
||||
nvg_set_request_data((TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR +
|
||||
(uint64_t)state), val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time)
|
||||
{
|
||||
(void)ari_base;
|
||||
(void)state;
|
||||
(void)wake_time;
|
||||
|
||||
/* This does not apply to the Denver cluster */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time)
|
||||
{
|
||||
uint64_t val;
|
||||
int32_t ret;
|
||||
|
||||
(void)ari_base;
|
||||
|
||||
/* check for allowed power state */
|
||||
if ((state != TEGRA_ARI_CORE_C0) && (state != TEGRA_ARI_CORE_C1) &&
|
||||
(state != TEGRA_ARI_CORE_C6) && (state != TEGRA_ARI_CORE_C7)) {
|
||||
ERROR("%s: unknown cstate (%d)\n", __func__, state);
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
/*
|
||||
* Request format -
|
||||
* 63:32 = wake time
|
||||
* 31:0 = C-state for this core
|
||||
*/
|
||||
val = ((uint64_t)wake_time << MCE_SC7_WAKE_TIME_SHIFT) |
|
||||
((uint64_t)state & MCE_SC7_ALLOWED_MASK);
|
||||
|
||||
/* issue command to check if SC7 is allowed */
|
||||
nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED, val);
|
||||
|
||||
/* 1 = SC7 allowed, 0 = SC7 not allowed */
|
||||
ret = (nvg_get_result() != 0ULL) ? 1 : 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t nvg_online_core(uint32_t ari_base, uint32_t core)
|
||||
{
|
||||
uint64_t cpu = read_mpidr() & MPIDR_CPU_MASK;
|
||||
uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
|
||||
int32_t ret = 0;
|
||||
|
||||
(void)ari_base;
|
||||
|
||||
/* sanity check code id */
|
||||
if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) {
|
||||
ERROR("%s: unsupported core id (%d)\n", __func__, core);
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
/*
|
||||
* The Denver cluster has 2 CPUs only - 0, 1.
|
||||
*/
|
||||
if ((impl == DENVER_IMPL) && ((core == 2U) || (core == 3U))) {
|
||||
ERROR("%s: unknown core id (%d)\n", __func__, core);
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
/* get a core online */
|
||||
nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_ONLINE_CORE,
|
||||
((uint64_t)core & MCE_CORE_ID_MASK));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
(void)ari_base;
|
||||
|
||||
/*
|
||||
* If the enable bit is cleared, Auto-CC3 will be disabled by setting
|
||||
* the SW visible voltage/frequency request registers for all non
|
||||
* floorswept cores valid independent of StandbyWFI and disabling
|
||||
* the IDLE voltage/frequency request register. If set, Auto-CC3
|
||||
* will be enabled by setting the ARM SW visible voltage/frequency
|
||||
* request registers for all non floorswept cores to be enabled by
|
||||
* StandbyWFI or the equivalent signal, and always keeping the IDLE
|
||||
* voltage/frequency request register enabled.
|
||||
*/
|
||||
val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\
|
||||
((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\
|
||||
((enable != 0U) ? MCE_AUTO_CC3_ENABLE_BIT : 0U));
|
||||
|
||||
nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_CC3_CTRL, (uint64_t)val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+277
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <bpmp_ipc.h>
|
||||
#include <pmc.h>
|
||||
#include <security_engine.h>
|
||||
#include <tegra_private.h>
|
||||
|
||||
#include "se_private.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Constants and Macros
|
||||
******************************************************************************/
|
||||
#define SE0_MAX_BUSY_TIMEOUT_MS U(100) /* 100ms */
|
||||
#define BYTES_IN_WORD U(4)
|
||||
#define SHA256_MAX_HASH_RESULT U(7)
|
||||
#define SHA256_DST_SIZE U(32)
|
||||
#define SHA_FIRST_OP U(1)
|
||||
#define MAX_SHA_ENGINE_CHUNK_SIZE U(0xFFFFFF)
|
||||
#define SHA256_MSG_LENGTH_ONETIME U(0xffff)
|
||||
|
||||
/*
|
||||
* Check that SE operation has completed after kickoff
|
||||
* This function is invoked after an SE operation has been started,
|
||||
* and it checks the following conditions:
|
||||
* 1. SE0_INT_STATUS = SE0_OP_DONE
|
||||
* 2. SE0_STATUS = IDLE
|
||||
* 3. SE0_ERR_STATUS is clean.
|
||||
*/
|
||||
static int32_t tegra_se_operation_complete(void)
|
||||
{
|
||||
uint32_t val = 0U;
|
||||
|
||||
/* Read SE0 interrupt register to ensure H/W operation complete */
|
||||
val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
|
||||
if (SE0_INT_OP_DONE(val) == SE0_INT_OP_DONE_CLEAR) {
|
||||
ERROR("%s: Engine busy state too many times! val = 0x%x\n",
|
||||
__func__, val);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* Read SE0 status idle to ensure H/W operation complete */
|
||||
val = tegra_se_read_32(SE0_SHA_STATUS_0);
|
||||
if (val != SE0_SHA_STATUS_IDLE) {
|
||||
ERROR("%s: Idle state timeout! val = 0x%x\n", __func__,
|
||||
val);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* Ensure that no errors are thrown during operation */
|
||||
val = tegra_se_read_32(SE0_ERR_STATUS_REG_OFFSET);
|
||||
if (val != SE0_ERR_STATUS_CLEAR) {
|
||||
ERROR("%s: Error during SE operation! val = 0x%x",
|
||||
__func__, val);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Security engine primitive normal operations
|
||||
*/
|
||||
static int32_t tegra_se_start_normal_operation(uint64_t src_addr,
|
||||
uint32_t nbytes, uint32_t last_buf, uint32_t src_len_inbytes)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
uint32_t val = 0U;
|
||||
uint32_t src_in_lo;
|
||||
uint32_t src_in_msb;
|
||||
uint32_t src_in_hi;
|
||||
|
||||
if ((src_addr == 0UL) || (nbytes == 0U))
|
||||
return -EINVAL;
|
||||
|
||||
src_in_lo = (uint32_t)src_addr;
|
||||
src_in_msb = ((uint32_t)(src_addr >> 32U) & 0xffU);
|
||||
src_in_hi = ((src_in_msb << SE0_IN_HI_ADDR_HI_0_MSB_SHIFT) |
|
||||
(nbytes & 0xffffffU));
|
||||
|
||||
/* set SRC_IN_ADDR_LO and SRC_IN_ADDR_HI*/
|
||||
tegra_se_write_32(SE0_IN_ADDR, src_in_lo);
|
||||
tegra_se_write_32(SE0_IN_HI_ADDR_HI, src_in_hi);
|
||||
|
||||
val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
|
||||
if (val > 0U) {
|
||||
tegra_se_write_32(SE0_INT_STATUS_REG_OFFSET, 0x00000U);
|
||||
}
|
||||
|
||||
/* Enable SHA interrupt for SE0 Operation */
|
||||
tegra_se_write_32(SE0_SHA_INT_ENABLE, 0x1aU);
|
||||
|
||||
/* flush to DRAM for SE to use the updated contents */
|
||||
flush_dcache_range(src_addr, src_len_inbytes);
|
||||
|
||||
/* Start SHA256 operation */
|
||||
if (last_buf == 1U) {
|
||||
tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START |
|
||||
SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD);
|
||||
} else {
|
||||
tegra_se_write_32(SE0_OPERATION_REG_OFFSET, SE0_OP_START);
|
||||
}
|
||||
|
||||
/* Wait for SE-operation to finish */
|
||||
udelay(SE0_MAX_BUSY_TIMEOUT_MS * 100U);
|
||||
|
||||
/* Check SE0 operation status */
|
||||
ret = tegra_se_operation_complete();
|
||||
if (ret != 0) {
|
||||
ERROR("SE operation complete Failed! 0x%x", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t tegra_se_calculate_sha256_hash(uint64_t src_addr,
|
||||
uint32_t src_len_inbyte)
|
||||
{
|
||||
uint32_t val, last_buf, i;
|
||||
int32_t ret = 0;
|
||||
uint32_t operations;
|
||||
uint64_t src_len_inbits;
|
||||
uint32_t len_bits_msb;
|
||||
uint32_t len_bits_lsb;
|
||||
uint32_t number_of_operations, max_bytes, bytes_left, remaining_bytes;
|
||||
|
||||
if (src_len_inbyte > MAX_SHA_ENGINE_CHUNK_SIZE) {
|
||||
ERROR("SHA input chunk size too big: 0x%x\n", src_len_inbyte);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (src_addr == 0UL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* number of bytes per operation */
|
||||
max_bytes = SHA256_HASH_SIZE_BYTES * SHA256_MSG_LENGTH_ONETIME;
|
||||
|
||||
src_len_inbits = src_len_inbyte * 8U;
|
||||
len_bits_msb = (uint32_t)(src_len_inbits >> 32U);
|
||||
len_bits_lsb = (uint32_t)(src_len_inbits & 0xFFFFFFFF);
|
||||
|
||||
/* program SE0_CONFIG for SHA256 operation */
|
||||
val = SE0_CONFIG_ENC_ALG_SHA | SE0_CONFIG_ENC_MODE_SHA256 |
|
||||
SE0_CONFIG_DEC_ALG_NOP | SE0_CONFIG_DST_HASHREG;
|
||||
tegra_se_write_32(SE0_SHA_CONFIG, val);
|
||||
|
||||
/* set SE0_SHA_MSG_LENGTH registers */
|
||||
tegra_se_write_32(SE0_SHA_MSG_LENGTH_0, len_bits_lsb);
|
||||
tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
|
||||
tegra_se_write_32(SE0_SHA_MSG_LENGTH_1, len_bits_msb);
|
||||
|
||||
/* zero out unused SE0_SHA_MSG_LENGTH and SE0_SHA_MSG_LEFT */
|
||||
tegra_se_write_32(SE0_SHA_MSG_LENGTH_2, 0U);
|
||||
tegra_se_write_32(SE0_SHA_MSG_LENGTH_3, 0U);
|
||||
tegra_se_write_32(SE0_SHA_MSG_LEFT_1, 0U);
|
||||
tegra_se_write_32(SE0_SHA_MSG_LEFT_2, 0U);
|
||||
tegra_se_write_32(SE0_SHA_MSG_LEFT_3, 0U);
|
||||
|
||||
number_of_operations = src_len_inbyte / max_bytes;
|
||||
remaining_bytes = src_len_inbyte % max_bytes;
|
||||
if (remaining_bytes > 0U) {
|
||||
number_of_operations += 1U;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Operations == 1: program SE0_SHA_TASK register to initiate SHA256
|
||||
* hash generation by setting
|
||||
* 1(SE0_SHA_CONFIG_HW_INIT_HASH) to SE0_SHA_TASK
|
||||
* and start SHA256-normal operation.
|
||||
* 2. 1 < Operations < number_of_operations: program SE0_SHA_TASK to
|
||||
* 0(SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE) to load
|
||||
* intermediate SHA256 digest result from
|
||||
* HASH_RESULT register to continue SHA256
|
||||
* generation and start SHA256-normal operation.
|
||||
* 3. Operations == number_of_operations: continue with step 2 and set
|
||||
* max_bytes to bytes_left to process final
|
||||
* hash-result generation and
|
||||
* start SHA256-normal operation.
|
||||
*/
|
||||
bytes_left = src_len_inbyte;
|
||||
for (operations = 1U; operations <= number_of_operations;
|
||||
operations++) {
|
||||
if (operations == SHA_FIRST_OP) {
|
||||
val = SE0_SHA_CONFIG_HW_INIT_HASH;
|
||||
} else {
|
||||
/* Load intermediate SHA digest result to
|
||||
* SHA:HASH_RESULT(0..7) to continue the SHA
|
||||
* calculation and tell the SHA engine to use it.
|
||||
*/
|
||||
for (i = 0U; (i / BYTES_IN_WORD) <=
|
||||
SHA256_MAX_HASH_RESULT; i += BYTES_IN_WORD) {
|
||||
val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 +
|
||||
i);
|
||||
tegra_se_write_32(SE0_SHA_HASH_RESULT_0 + i,
|
||||
val);
|
||||
}
|
||||
val = SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE;
|
||||
if (len_bits_lsb <= (max_bytes * 8U)) {
|
||||
len_bits_lsb = (remaining_bytes * 8U);
|
||||
} else {
|
||||
len_bits_lsb -= (max_bytes * 8U);
|
||||
}
|
||||
tegra_se_write_32(SE0_SHA_MSG_LEFT_0, len_bits_lsb);
|
||||
}
|
||||
tegra_se_write_32(SE0_SHA_TASK_CONFIG, val);
|
||||
|
||||
max_bytes = (SHA256_HASH_SIZE_BYTES *
|
||||
SHA256_MSG_LENGTH_ONETIME);
|
||||
if (bytes_left < max_bytes) {
|
||||
max_bytes = bytes_left;
|
||||
last_buf = 1U;
|
||||
} else {
|
||||
bytes_left = bytes_left - max_bytes;
|
||||
last_buf = 0U;
|
||||
}
|
||||
/* start operation */
|
||||
ret = tegra_se_start_normal_operation(src_addr, max_bytes,
|
||||
last_buf, src_len_inbyte);
|
||||
if (ret != 0) {
|
||||
ERROR("Error during SE operation! 0x%x", ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler to generate SHA256 and save SHA256 hash to PMC-Scratch register.
|
||||
*/
|
||||
int32_t tegra_se_save_sha256_hash(uint64_t bl31_base, uint32_t src_len_inbyte)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
uint32_t val = 0U, hash_offset = 0U, scratch_offset = 0U, security;
|
||||
|
||||
/*
|
||||
* Set SE_SOFT_SETTINGS=SE_SECURE to prevent NS process to change SE
|
||||
* registers.
|
||||
*/
|
||||
security = tegra_se_read_32(SE0_SECURITY);
|
||||
tegra_se_write_32(SE0_SECURITY, security | SE0_SECURITY_SE_SOFT_SETTING);
|
||||
|
||||
ret = tegra_se_calculate_sha256_hash(bl31_base, src_len_inbyte);
|
||||
if (ret != 0L) {
|
||||
ERROR("%s: SHA256 generation failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset SE_SECURE to previous value.
|
||||
*/
|
||||
tegra_se_write_32(SE0_SECURITY, security);
|
||||
|
||||
/* read SHA256_HASH_RESULT and save to PMC Scratch registers */
|
||||
scratch_offset = SECURE_SCRATCH_TZDRAM_SHA256_HASH_START;
|
||||
while (scratch_offset <= SECURE_SCRATCH_TZDRAM_SHA256_HASH_END) {
|
||||
|
||||
val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + hash_offset);
|
||||
mmio_write_32(TEGRA_SCRATCH_BASE + scratch_offset, val);
|
||||
|
||||
hash_offset += BYTES_IN_WORD;
|
||||
scratch_offset += BYTES_IN_WORD;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SE_PRIVATE_H
|
||||
#define SE_PRIVATE_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
/* SE0 security register */
|
||||
#define SE0_SECURITY U(0x18)
|
||||
#define SE0_SECURITY_SE_SOFT_SETTING (((uint32_t)1) << 16U)
|
||||
|
||||
/* SE0 config register */
|
||||
#define SE0_SHA_CONFIG U(0x104)
|
||||
#define SE0_SHA_TASK_CONFIG U(0x108)
|
||||
#define SE0_SHA_CONFIG_HW_INIT_HASH ((1U) << 0U)
|
||||
#define SE0_SHA_CONFIG_HW_INIT_HASH_DISABLE U(0)
|
||||
|
||||
#define SE0_CONFIG_ENC_ALG_SHIFT U(12)
|
||||
#define SE0_CONFIG_ENC_ALG_SHA \
|
||||
(((uint32_t)3) << SE0_CONFIG_ENC_ALG_SHIFT)
|
||||
#define SE0_CONFIG_DEC_ALG_SHIFT U(8)
|
||||
#define SE0_CONFIG_DEC_ALG_NOP \
|
||||
(((uint32_t)0) << SE0_CONFIG_DEC_ALG_SHIFT)
|
||||
#define SE0_CONFIG_DST_SHIFT U(2)
|
||||
#define SE0_CONFIG_DST_HASHREG \
|
||||
(((uint32_t)1) << SE0_CONFIG_DST_SHIFT)
|
||||
#define SHA256_HASH_SIZE_BYTES U(256)
|
||||
|
||||
#define SE0_CONFIG_ENC_MODE_SHIFT U(24)
|
||||
#define SE0_CONFIG_ENC_MODE_SHA256 \
|
||||
(((uint32_t)5) << SE0_CONFIG_ENC_MODE_SHIFT)
|
||||
|
||||
/* SHA input message length */
|
||||
#define SE0_SHA_MSG_LENGTH_0 U(0x11c)
|
||||
#define SE0_SHA_MSG_LENGTH_1 U(0x120)
|
||||
#define SE0_SHA_MSG_LENGTH_2 U(0x124)
|
||||
#define SE0_SHA_MSG_LENGTH_3 U(0x128)
|
||||
|
||||
/* SHA input message left */
|
||||
#define SE0_SHA_MSG_LEFT_0 U(0x12c)
|
||||
#define SE0_SHA_MSG_LEFT_1 U(0x130)
|
||||
#define SE0_SHA_MSG_LEFT_2 U(0x134)
|
||||
#define SE0_SHA_MSG_LEFT_3 U(0x138)
|
||||
|
||||
/* SE Hash Result */
|
||||
#define SE0_SHA_HASH_RESULT_0 U(0x13c)
|
||||
|
||||
/* SE OPERATION */
|
||||
#define SE0_OPERATION_REG_OFFSET U(0x17c)
|
||||
#define SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT U(16)
|
||||
#define SE0_UNIT_OPERATION_PKT_LASTBUF_FIELD \
|
||||
(((uint32_t)0x1) << SE0_UNIT_OPERATION_PKT_LASTBUF_SHIFT)
|
||||
#define SE0_OPERATION_SHIFT U(0)
|
||||
#define SE0_OP_START \
|
||||
(((uint32_t)0x1) << SE0_OPERATION_SHIFT)
|
||||
|
||||
/* SE Interrupt */
|
||||
#define SE0_SHA_INT_ENABLE U(0x180)
|
||||
|
||||
#define SE0_INT_STATUS_REG_OFFSET U(0x184)
|
||||
#define SE0_INT_OP_DONE_SHIFT U(4)
|
||||
#define SE0_INT_OP_DONE_CLEAR \
|
||||
(((uint32_t)0) << SE0_INT_OP_DONE_SHIFT)
|
||||
#define SE0_INT_OP_DONE(x) \
|
||||
((x) & (((uint32_t)0x1) << SE0_INT_OP_DONE_SHIFT))
|
||||
|
||||
/* SE SHA status */
|
||||
#define SE0_SHA_STATUS_0 U(0x188)
|
||||
#define SE0_SHA_STATUS_IDLE U(0)
|
||||
|
||||
/* SE error status */
|
||||
#define SE0_ERR_STATUS_REG_OFFSET U(0x18c)
|
||||
#define SE0_ERR_STATUS_CLEAR U(0)
|
||||
#define SE0_IN_ADDR U(0x10c)
|
||||
#define SE0_IN_HI_ADDR_HI U(0x110)
|
||||
#define SE0_IN_HI_ADDR_HI_0_MSB_SHIFT U(24)
|
||||
|
||||
/* SE error status */
|
||||
#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_START SECURE_SCRATCH_RSV63_LO
|
||||
#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_END SECURE_SCRATCH_RSV66_HI
|
||||
|
||||
/*******************************************************************************
|
||||
* Inline functions definition
|
||||
******************************************************************************/
|
||||
|
||||
static inline uint32_t tegra_se_read_32(uint32_t offset)
|
||||
{
|
||||
return mmio_read_32((uint32_t)(TEGRA_SE0_BASE + offset));
|
||||
}
|
||||
|
||||
static inline void tegra_se_write_32(uint32_t offset, uint32_t val)
|
||||
{
|
||||
mmio_write_32(((uint32_t)(TEGRA_SE0_BASE + offset)), val);
|
||||
}
|
||||
|
||||
#endif /* SE_PRIVATE_H */
|
||||
+700
@@ -0,0 +1,700 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <common/bl_common.h>
|
||||
|
||||
#include <mce.h>
|
||||
#include <memctrl_v2.h>
|
||||
#include <tegra186_private.h>
|
||||
#include <tegra_mc_def.h>
|
||||
#include <tegra_platform.h>
|
||||
#include <tegra_private.h>
|
||||
|
||||
extern uint64_t tegra_bl31_phys_base;
|
||||
|
||||
/*******************************************************************************
|
||||
* Array to hold stream_id override config register offsets
|
||||
******************************************************************************/
|
||||
const static uint32_t tegra186_streamid_override_regs[] = {
|
||||
MC_STREAMID_OVERRIDE_CFG_SDMMCRA,
|
||||
MC_STREAMID_OVERRIDE_CFG_SDMMCRAA,
|
||||
MC_STREAMID_OVERRIDE_CFG_SDMMCR,
|
||||
MC_STREAMID_OVERRIDE_CFG_SDMMCRAB,
|
||||
MC_STREAMID_OVERRIDE_CFG_SDMMCWA,
|
||||
MC_STREAMID_OVERRIDE_CFG_SDMMCWAA,
|
||||
MC_STREAMID_OVERRIDE_CFG_SDMMCW,
|
||||
MC_STREAMID_OVERRIDE_CFG_SDMMCWAB,
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Array to hold the security configs for stream IDs
|
||||
******************************************************************************/
|
||||
const static mc_streamid_security_cfg_t tegra186_streamid_sec_cfgs[] = {
|
||||
mc_make_sec_cfg(SCEW, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(AFIR, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(AFIW, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(NVDISPLAYR1, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(XUSB_DEVR, NON_SECURE, OVERRIDE, ENABLE),
|
||||
mc_make_sec_cfg(VICSRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(NVENCSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(TSECSRDB, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(AXISW, SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SDMMCWAB, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(AONDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(GPUSWR2, SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SATAW, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(UFSHCW, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SDMMCR, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SCEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(UFSHCR, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SDMMCWAA, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SESWR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(MPCORER, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(PTCR, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(BPMPW, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(ETRW, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(GPUSRD, SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(VICSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SCEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(HDAW, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(ISPWA, NON_SECURE, OVERRIDE, ENABLE),
|
||||
mc_make_sec_cfg(EQOSW, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(XUSB_HOSTW, NON_SECURE, OVERRIDE, ENABLE),
|
||||
mc_make_sec_cfg(TSECSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SDMMCRAA, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(VIW, NON_SECURE, OVERRIDE, ENABLE),
|
||||
mc_make_sec_cfg(AXISR, SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SDMMCW, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(BPMPDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(ISPRA, NON_SECURE, OVERRIDE, ENABLE),
|
||||
mc_make_sec_cfg(NVDECSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(XUSB_DEVW, NON_SECURE, OVERRIDE, ENABLE),
|
||||
mc_make_sec_cfg(NVDECSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(MPCOREW, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(NVDISPLAYR, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(BPMPDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(NVJPGSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(NVDECSRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(TSECSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(NVJPGSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SDMMCWA, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SCER, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(XUSB_HOSTR, NON_SECURE, OVERRIDE, ENABLE),
|
||||
mc_make_sec_cfg(VICSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(AONDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(AONW, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SDMMCRA, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(HOST1XDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(EQOSR, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SATAR, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(BPMPR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(HDAR, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SDMMCRAB, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(ETRR, NON_SECURE, OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(AONR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(SESRD, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(NVENCSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(GPUSWR, SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(TSECSWRB, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(ISPWB, NON_SECURE, OVERRIDE, ENABLE),
|
||||
mc_make_sec_cfg(GPUSRD2, SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(APEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(APER, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(APEW, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
mc_make_sec_cfg(APEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Array to hold the transaction override configs
|
||||
******************************************************************************/
|
||||
const static mc_txn_override_cfg_t tegra186_txn_override_cfgs[] = {
|
||||
mc_make_txn_override_cfg(BPMPW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(EQOSW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(NVJPGSWR, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(SDMMCWAA, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(MPCOREW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(SCEDMAW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(SDMMCW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(AXISW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(TSECSWR, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(GPUSWR, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(XUSB_HOSTW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(TSECSWRB, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(GPUSWR2, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(AONDMAW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(AONW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(SESWR, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(BPMPDMAW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(SDMMCWA, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(HDAW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(NVDECSWR, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(UFSHCW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(SATAW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(ETRW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(VICSWR, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(NVENCSWR, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(SDMMCWAB, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(ISPWB, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(APEW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(XUSB_DEVW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(AFIW, CGID_TAG_ADR),
|
||||
mc_make_txn_override_cfg(SCEW, CGID_TAG_ADR),
|
||||
};
|
||||
|
||||
static void tegra186_memctrl_reconfig_mss_clients(void)
|
||||
{
|
||||
#if ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS
|
||||
uint32_t val, wdata_0, wdata_1;
|
||||
|
||||
/*
|
||||
* Assert Memory Controller's HOTRESET_FLUSH_ENABLE signal for
|
||||
* boot and strongly ordered MSS clients to flush existing memory
|
||||
* traffic and stall future requests.
|
||||
*/
|
||||
val = tegra_mc_read_32(MC_CLIENT_HOTRESET_CTRL0);
|
||||
assert(val == MC_CLIENT_HOTRESET_CTRL0_RESET_VAL);
|
||||
|
||||
wdata_0 = MC_CLIENT_HOTRESET_CTRL0_HDA_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL0_AFI_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL0_SATA_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL0_XUSB_HOST_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL0_XUSB_DEV_FLUSH_ENB;
|
||||
tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL0, wdata_0);
|
||||
|
||||
/* Wait for HOTRESET STATUS to indicate FLUSH_DONE */
|
||||
do {
|
||||
val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS0);
|
||||
} while ((val & wdata_0) != wdata_0);
|
||||
|
||||
/* Wait one more time due to SW WAR for known legacy issue */
|
||||
do {
|
||||
val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS0);
|
||||
} while ((val & wdata_0) != wdata_0);
|
||||
|
||||
val = tegra_mc_read_32(MC_CLIENT_HOTRESET_CTRL1);
|
||||
assert(val == MC_CLIENT_HOTRESET_CTRL1_RESET_VAL);
|
||||
|
||||
wdata_1 = MC_CLIENT_HOTRESET_CTRL1_SDMMC4A_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL1_APE_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL1_SE_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL1_ETR_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL1_AXIS_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL1_EQOS_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL1_UFSHC_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL1_BPMP_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL1_AON_FLUSH_ENB |
|
||||
MC_CLIENT_HOTRESET_CTRL1_SCE_FLUSH_ENB;
|
||||
tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL1, wdata_1);
|
||||
|
||||
/* Wait for HOTRESET STATUS to indicate FLUSH_DONE */
|
||||
do {
|
||||
val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS1);
|
||||
} while ((val & wdata_1) != wdata_1);
|
||||
|
||||
/* Wait one more time due to SW WAR for known legacy issue */
|
||||
do {
|
||||
val = tegra_mc_read_32(MC_CLIENT_HOTRESET_STATUS1);
|
||||
} while ((val & wdata_1) != wdata_1);
|
||||
|
||||
/*
|
||||
* Change MEMTYPE_OVERRIDE from SO_DEV -> PASSTHRU for boot and
|
||||
* strongly ordered MSS clients. ROC needs to be single point
|
||||
* of control on overriding the memory type. So, remove TSA's
|
||||
* memtype override.
|
||||
*
|
||||
* MC clients with default SO_DEV override still enabled at TSA:
|
||||
* AONW, BPMPW, SCEW, APEW
|
||||
*/
|
||||
mc_set_tsa_passthrough(AFIW);
|
||||
mc_set_tsa_passthrough(HDAW);
|
||||
mc_set_tsa_passthrough(SATAW);
|
||||
mc_set_tsa_passthrough(XUSB_HOSTW);
|
||||
mc_set_tsa_passthrough(XUSB_DEVW);
|
||||
mc_set_tsa_passthrough(SDMMCWAB);
|
||||
mc_set_tsa_passthrough(APEDMAW);
|
||||
mc_set_tsa_passthrough(SESWR);
|
||||
mc_set_tsa_passthrough(ETRW);
|
||||
mc_set_tsa_passthrough(AXISW);
|
||||
mc_set_tsa_passthrough(EQOSW);
|
||||
mc_set_tsa_passthrough(UFSHCW);
|
||||
mc_set_tsa_passthrough(BPMPDMAW);
|
||||
mc_set_tsa_passthrough(AONDMAW);
|
||||
mc_set_tsa_passthrough(SCEDMAW);
|
||||
|
||||
/* Parker has no IO Coherency support and need the following:
|
||||
* Ordered MC Clients on Parker are AFI, EQOS, SATA, XUSB.
|
||||
* ISO clients(DISP, VI, EQOS) should never snoop caches and
|
||||
* don't need ROC/PCFIFO ordering.
|
||||
* ISO clients(EQOS) that need ordering should use PCFIFO ordering
|
||||
* and bypass ROC ordering by using FORCE_NON_COHERENT path.
|
||||
* FORCE_NON_COHERENT/FORCE_COHERENT config take precedence
|
||||
* over SMMU attributes.
|
||||
* Force all Normal memory transactions from ISO and non-ISO to be
|
||||
* non-coherent(bypass ROC, avoid cache snoop to avoid perf hit).
|
||||
* Force the SO_DEV transactions from ordered ISO clients(EQOS) to
|
||||
* non-coherent path and enable MC PCFIFO interlock for ordering.
|
||||
* Force the SO_DEV transactions from ordered non-ISO clients (PCIe,
|
||||
* XUSB, SATA) to coherent so that the transactions are
|
||||
* ordered by ROC.
|
||||
* PCFIFO ensure write ordering.
|
||||
* Read after Write ordering is maintained/enforced by MC clients.
|
||||
* Clients that need PCIe type write ordering must
|
||||
* go through ROC ordering.
|
||||
* Ordering enable for Read clients is not necessary.
|
||||
* R5's and A9 would get necessary ordering from AXI and
|
||||
* don't need ROC ordering enable:
|
||||
* - MMIO ordering is through dev mapping and MMIO
|
||||
* accesses bypass SMMU.
|
||||
* - Normal memory is accessed through SMMU and ordering is
|
||||
* ensured by client and AXI.
|
||||
* - Ack point for Normal memory is WCAM in MC.
|
||||
* - MMIO's can be early acked and AXI ensures dev memory ordering,
|
||||
* Client ensures read/write direction change ordering.
|
||||
* - See Bug 200312466 for more details.
|
||||
*
|
||||
* CGID_TAG_ADR is only present from T186 A02. As this code is common
|
||||
* between A01 and A02, tegra_memctrl_set_overrides() programs
|
||||
* CGID_TAG_ADR for the necessary clients on A02.
|
||||
*/
|
||||
mc_set_txn_override(HDAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(BPMPW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(PTCR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(NVDISPLAYR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(EQOSW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(NVJPGSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(ISPRA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SDMMCWAA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(VICSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(MPCOREW, CGID_TAG_DEFAULT, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
|
||||
mc_set_txn_override(GPUSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(AXISR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SCEDMAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SDMMCW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(EQOSR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
/* See bug 200131110 comment #35*/
|
||||
mc_set_txn_override(APEDMAR, CGID_TAG_CLIENT_AXI_ID, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(NVENCSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SDMMCRAB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(VICSRD1, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(BPMPDMAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(VIW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SDMMCRAA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(AXISW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(XUSB_DEVR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(UFSHCR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(TSECSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(GPUSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SATAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(XUSB_HOSTW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_COHERENT);
|
||||
mc_set_txn_override(TSECSWRB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(GPUSRD2, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SCEDMAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(GPUSWR2, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(AONDMAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
/* See bug 200131110 comment #35*/
|
||||
mc_set_txn_override(APEDMAW, CGID_TAG_CLIENT_AXI_ID, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(AONW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(HOST1XDMAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(ETRR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SESWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(NVJPGSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(NVDECSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(TSECSRDB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(BPMPDMAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(APER, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(NVDECSRD1, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(XUSB_HOSTR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(ISPWA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SESRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SCER, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(AONR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(MPCORER, CGID_TAG_DEFAULT, SO_DEV_ZERO, NO_OVERRIDE, NO_OVERRIDE);
|
||||
mc_set_txn_override(SDMMCWA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(HDAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(NVDECSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(UFSHCW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(AONDMAR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SATAW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_COHERENT);
|
||||
mc_set_txn_override(ETRW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(VICSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(NVENCSWR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
/* See bug 200131110 comment #35 */
|
||||
mc_set_txn_override(AFIR, CGID_TAG_DEFAULT, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SDMMCWAB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SDMMCRA, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(NVDISPLAYR1, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(ISPWB, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(BPMPR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(APEW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(SDMMCR, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
mc_set_txn_override(XUSB_DEVW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_COHERENT);
|
||||
mc_set_txn_override(TSECSRD, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
/*
|
||||
* See bug 200131110 comment #35 - there are no normal requests
|
||||
* and AWID for SO/DEV requests is hardcoded in RTL for a
|
||||
* particular PCIE controller
|
||||
*/
|
||||
mc_set_txn_override(AFIW, CGID_TAG_DEFAULT, SO_DEV_CLIENT_AXI_ID, FORCE_NON_COHERENT, FORCE_COHERENT);
|
||||
mc_set_txn_override(SCEW, CGID_TAG_DEFAULT, SO_DEV_ZERO, FORCE_NON_COHERENT, FORCE_NON_COHERENT);
|
||||
|
||||
/*
|
||||
* At this point, ordering can occur at ROC. So, remove PCFIFO's
|
||||
* control over ordering requests.
|
||||
*
|
||||
* Change PCFIFO_*_ORDERED_CLIENT from ORDERED -> UNORDERED for
|
||||
* boot and strongly ordered MSS clients
|
||||
*/
|
||||
val = MC_PCFIFO_CLIENT_CONFIG1_RESET_VAL &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(1, AFIW) &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(1, HDAW) &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(1, SATAW);
|
||||
tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG1, val);
|
||||
|
||||
val = MC_PCFIFO_CLIENT_CONFIG2_RESET_VAL &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(2, XUSB_HOSTW) &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(2, XUSB_DEVW);
|
||||
tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG2, val);
|
||||
|
||||
val = MC_PCFIFO_CLIENT_CONFIG3_RESET_VAL &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(3, SDMMCWAB);
|
||||
tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG3, val);
|
||||
|
||||
val = MC_PCFIFO_CLIENT_CONFIG4_RESET_VAL &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(4, SESWR) &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(4, ETRW) &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(4, AXISW) &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(4, UFSHCW) &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(4, BPMPDMAW) &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(4, AONDMAW) &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(4, SCEDMAW);
|
||||
/* EQOSW is the only client that has PCFIFO order enabled. */
|
||||
val |= mc_set_pcfifo_ordered_boot_so_mss(4, EQOSW);
|
||||
tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG4, val);
|
||||
|
||||
val = MC_PCFIFO_CLIENT_CONFIG5_RESET_VAL &
|
||||
mc_set_pcfifo_unordered_boot_so_mss(5, APEDMAW);
|
||||
tegra_mc_write_32(MC_PCFIFO_CLIENT_CONFIG5, val);
|
||||
|
||||
/*
|
||||
* Deassert HOTRESET FLUSH_ENABLE for boot and strongly ordered MSS
|
||||
* clients to allow memory traffic from all clients to start passing
|
||||
* through ROC
|
||||
*/
|
||||
val = tegra_mc_read_32(MC_CLIENT_HOTRESET_CTRL0);
|
||||
assert(val == wdata_0);
|
||||
|
||||
wdata_0 = MC_CLIENT_HOTRESET_CTRL0_RESET_VAL;
|
||||
tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL0, wdata_0);
|
||||
|
||||
val = tegra_mc_read_32(MC_CLIENT_HOTRESET_CTRL1);
|
||||
assert(val == wdata_1);
|
||||
|
||||
wdata_1 = MC_CLIENT_HOTRESET_CTRL1_RESET_VAL;
|
||||
tegra_mc_write_32(MC_CLIENT_HOTRESET_CTRL1, wdata_1);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void tegra186_memctrl_set_overrides(void)
|
||||
{
|
||||
uint32_t i, val;
|
||||
|
||||
/*
|
||||
* Set the MC_TXN_OVERRIDE registers for write clients.
|
||||
*/
|
||||
if ((tegra_chipid_is_t186()) &&
|
||||
(!tegra_platform_is_silicon() ||
|
||||
(tegra_platform_is_silicon() && (tegra_get_chipid_minor() == 1U)))) {
|
||||
|
||||
/*
|
||||
* GPU and NVENC settings for Tegra186 simulation and
|
||||
* Silicon rev. A01
|
||||
*/
|
||||
val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR);
|
||||
val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK;
|
||||
tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR,
|
||||
val | MC_TXN_OVERRIDE_CGID_TAG_ZERO);
|
||||
|
||||
val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR2);
|
||||
val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK;
|
||||
tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR2,
|
||||
val | MC_TXN_OVERRIDE_CGID_TAG_ZERO);
|
||||
|
||||
val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_NVENCSWR);
|
||||
val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK;
|
||||
tegra_mc_write_32(MC_TXN_OVERRIDE_CONFIG_NVENCSWR,
|
||||
val | MC_TXN_OVERRIDE_CGID_TAG_CLIENT_AXI_ID);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Settings for Tegra186 silicon rev. A02 and onwards.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(tegra186_txn_override_cfgs); i++) {
|
||||
val = tegra_mc_read_32(tegra186_txn_override_cfgs[i].offset);
|
||||
val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK;
|
||||
tegra_mc_write_32(tegra186_txn_override_cfgs[i].offset,
|
||||
val | tegra186_txn_override_cfgs[i].cgid_tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Array to hold MC context for Tegra186
|
||||
******************************************************************************/
|
||||
static __attribute__((aligned(16))) mc_regs_t tegra186_mc_context[] = {
|
||||
_START_OF_TABLE_,
|
||||
mc_make_sid_security_cfg(SCEW),
|
||||
mc_make_sid_security_cfg(AFIR),
|
||||
mc_make_sid_security_cfg(NVDISPLAYR1),
|
||||
mc_make_sid_security_cfg(XUSB_DEVR),
|
||||
mc_make_sid_security_cfg(VICSRD1),
|
||||
mc_make_sid_security_cfg(NVENCSWR),
|
||||
mc_make_sid_security_cfg(TSECSRDB),
|
||||
mc_make_sid_security_cfg(AXISW),
|
||||
mc_make_sid_security_cfg(SDMMCWAB),
|
||||
mc_make_sid_security_cfg(AONDMAW),
|
||||
mc_make_sid_security_cfg(GPUSWR2),
|
||||
mc_make_sid_security_cfg(SATAW),
|
||||
mc_make_sid_security_cfg(UFSHCW),
|
||||
mc_make_sid_security_cfg(AFIW),
|
||||
mc_make_sid_security_cfg(SDMMCR),
|
||||
mc_make_sid_security_cfg(SCEDMAW),
|
||||
mc_make_sid_security_cfg(UFSHCR),
|
||||
mc_make_sid_security_cfg(SDMMCWAA),
|
||||
mc_make_sid_security_cfg(APEDMAW),
|
||||
mc_make_sid_security_cfg(SESWR),
|
||||
mc_make_sid_security_cfg(MPCORER),
|
||||
mc_make_sid_security_cfg(PTCR),
|
||||
mc_make_sid_security_cfg(BPMPW),
|
||||
mc_make_sid_security_cfg(ETRW),
|
||||
mc_make_sid_security_cfg(GPUSRD),
|
||||
mc_make_sid_security_cfg(VICSWR),
|
||||
mc_make_sid_security_cfg(SCEDMAR),
|
||||
mc_make_sid_security_cfg(HDAW),
|
||||
mc_make_sid_security_cfg(ISPWA),
|
||||
mc_make_sid_security_cfg(EQOSW),
|
||||
mc_make_sid_security_cfg(XUSB_HOSTW),
|
||||
mc_make_sid_security_cfg(TSECSWR),
|
||||
mc_make_sid_security_cfg(SDMMCRAA),
|
||||
mc_make_sid_security_cfg(APER),
|
||||
mc_make_sid_security_cfg(VIW),
|
||||
mc_make_sid_security_cfg(APEW),
|
||||
mc_make_sid_security_cfg(AXISR),
|
||||
mc_make_sid_security_cfg(SDMMCW),
|
||||
mc_make_sid_security_cfg(BPMPDMAW),
|
||||
mc_make_sid_security_cfg(ISPRA),
|
||||
mc_make_sid_security_cfg(NVDECSWR),
|
||||
mc_make_sid_security_cfg(XUSB_DEVW),
|
||||
mc_make_sid_security_cfg(NVDECSRD),
|
||||
mc_make_sid_security_cfg(MPCOREW),
|
||||
mc_make_sid_security_cfg(NVDISPLAYR),
|
||||
mc_make_sid_security_cfg(BPMPDMAR),
|
||||
mc_make_sid_security_cfg(NVJPGSWR),
|
||||
mc_make_sid_security_cfg(NVDECSRD1),
|
||||
mc_make_sid_security_cfg(TSECSRD),
|
||||
mc_make_sid_security_cfg(NVJPGSRD),
|
||||
mc_make_sid_security_cfg(SDMMCWA),
|
||||
mc_make_sid_security_cfg(SCER),
|
||||
mc_make_sid_security_cfg(XUSB_HOSTR),
|
||||
mc_make_sid_security_cfg(VICSRD),
|
||||
mc_make_sid_security_cfg(AONDMAR),
|
||||
mc_make_sid_security_cfg(AONW),
|
||||
mc_make_sid_security_cfg(SDMMCRA),
|
||||
mc_make_sid_security_cfg(HOST1XDMAR),
|
||||
mc_make_sid_security_cfg(EQOSR),
|
||||
mc_make_sid_security_cfg(SATAR),
|
||||
mc_make_sid_security_cfg(BPMPR),
|
||||
mc_make_sid_security_cfg(HDAR),
|
||||
mc_make_sid_security_cfg(SDMMCRAB),
|
||||
mc_make_sid_security_cfg(ETRR),
|
||||
mc_make_sid_security_cfg(AONR),
|
||||
mc_make_sid_security_cfg(APEDMAR),
|
||||
mc_make_sid_security_cfg(SESRD),
|
||||
mc_make_sid_security_cfg(NVENCSRD),
|
||||
mc_make_sid_security_cfg(GPUSWR),
|
||||
mc_make_sid_security_cfg(TSECSWRB),
|
||||
mc_make_sid_security_cfg(ISPWB),
|
||||
mc_make_sid_security_cfg(GPUSRD2),
|
||||
mc_make_sid_override_cfg(APER),
|
||||
mc_make_sid_override_cfg(VICSRD),
|
||||
mc_make_sid_override_cfg(NVENCSRD),
|
||||
mc_make_sid_override_cfg(NVJPGSWR),
|
||||
mc_make_sid_override_cfg(AONW),
|
||||
mc_make_sid_override_cfg(BPMPR),
|
||||
mc_make_sid_override_cfg(BPMPW),
|
||||
mc_make_sid_override_cfg(HDAW),
|
||||
mc_make_sid_override_cfg(NVDISPLAYR1),
|
||||
mc_make_sid_override_cfg(APEDMAR),
|
||||
mc_make_sid_override_cfg(AFIR),
|
||||
mc_make_sid_override_cfg(AXISR),
|
||||
mc_make_sid_override_cfg(VICSRD1),
|
||||
mc_make_sid_override_cfg(TSECSRD),
|
||||
mc_make_sid_override_cfg(BPMPDMAW),
|
||||
mc_make_sid_override_cfg(MPCOREW),
|
||||
mc_make_sid_override_cfg(XUSB_HOSTR),
|
||||
mc_make_sid_override_cfg(GPUSWR),
|
||||
mc_make_sid_override_cfg(XUSB_DEVR),
|
||||
mc_make_sid_override_cfg(UFSHCW),
|
||||
mc_make_sid_override_cfg(XUSB_HOSTW),
|
||||
mc_make_sid_override_cfg(SDMMCWAB),
|
||||
mc_make_sid_override_cfg(SATAW),
|
||||
mc_make_sid_override_cfg(SCEDMAR),
|
||||
mc_make_sid_override_cfg(HOST1XDMAR),
|
||||
mc_make_sid_override_cfg(SDMMCWA),
|
||||
mc_make_sid_override_cfg(APEDMAW),
|
||||
mc_make_sid_override_cfg(SESWR),
|
||||
mc_make_sid_override_cfg(AXISW),
|
||||
mc_make_sid_override_cfg(AONDMAW),
|
||||
mc_make_sid_override_cfg(TSECSWRB),
|
||||
mc_make_sid_override_cfg(MPCORER),
|
||||
mc_make_sid_override_cfg(ISPWB),
|
||||
mc_make_sid_override_cfg(AONR),
|
||||
mc_make_sid_override_cfg(BPMPDMAR),
|
||||
mc_make_sid_override_cfg(HDAR),
|
||||
mc_make_sid_override_cfg(SDMMCRA),
|
||||
mc_make_sid_override_cfg(ETRW),
|
||||
mc_make_sid_override_cfg(GPUSWR2),
|
||||
mc_make_sid_override_cfg(EQOSR),
|
||||
mc_make_sid_override_cfg(TSECSWR),
|
||||
mc_make_sid_override_cfg(ETRR),
|
||||
mc_make_sid_override_cfg(NVDECSRD),
|
||||
mc_make_sid_override_cfg(TSECSRDB),
|
||||
mc_make_sid_override_cfg(SDMMCRAA),
|
||||
mc_make_sid_override_cfg(NVDECSRD1),
|
||||
mc_make_sid_override_cfg(SDMMCR),
|
||||
mc_make_sid_override_cfg(NVJPGSRD),
|
||||
mc_make_sid_override_cfg(SCEDMAW),
|
||||
mc_make_sid_override_cfg(SDMMCWAA),
|
||||
mc_make_sid_override_cfg(APEW),
|
||||
mc_make_sid_override_cfg(AONDMAR),
|
||||
mc_make_sid_override_cfg(PTCR),
|
||||
mc_make_sid_override_cfg(SCER),
|
||||
mc_make_sid_override_cfg(ISPRA),
|
||||
mc_make_sid_override_cfg(ISPWA),
|
||||
mc_make_sid_override_cfg(VICSWR),
|
||||
mc_make_sid_override_cfg(SESRD),
|
||||
mc_make_sid_override_cfg(SDMMCW),
|
||||
mc_make_sid_override_cfg(SDMMCRAB),
|
||||
mc_make_sid_override_cfg(EQOSW),
|
||||
mc_make_sid_override_cfg(GPUSRD2),
|
||||
mc_make_sid_override_cfg(SCEW),
|
||||
mc_make_sid_override_cfg(GPUSRD),
|
||||
mc_make_sid_override_cfg(NVDECSWR),
|
||||
mc_make_sid_override_cfg(XUSB_DEVW),
|
||||
mc_make_sid_override_cfg(SATAR),
|
||||
mc_make_sid_override_cfg(NVDISPLAYR),
|
||||
mc_make_sid_override_cfg(VIW),
|
||||
mc_make_sid_override_cfg(UFSHCR),
|
||||
mc_make_sid_override_cfg(NVENCSWR),
|
||||
mc_make_sid_override_cfg(AFIW),
|
||||
mc_smmu_bypass_cfg, /* TBU settings */
|
||||
_END_OF_TABLE_,
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to return the pointer to the MC's context struct
|
||||
******************************************************************************/
|
||||
mc_regs_t *plat_memctrl_get_sys_suspend_ctx(void)
|
||||
{
|
||||
/* index of _END_OF_TABLE_ */
|
||||
tegra186_mc_context[0].val = (uint32_t)(ARRAY_SIZE(tegra186_mc_context)) - 1U;
|
||||
|
||||
return tegra186_mc_context;
|
||||
}
|
||||
|
||||
void plat_memctrl_setup(void)
|
||||
{
|
||||
uint32_t val;
|
||||
unsigned int i;
|
||||
|
||||
/* Program all the Stream ID overrides */
|
||||
for (i = 0U; i < ARRAY_SIZE(tegra186_streamid_override_regs); i++) {
|
||||
tegra_mc_streamid_write_32(tegra186_streamid_override_regs[i],
|
||||
MC_STREAM_ID_MAX);
|
||||
}
|
||||
|
||||
/* Program the security config settings for all Stream IDs */
|
||||
for (i = 0U; i < ARRAY_SIZE(tegra186_streamid_sec_cfgs); i++) {
|
||||
val = (tegra186_streamid_sec_cfgs[i].override_enable << 16) |
|
||||
(tegra186_streamid_sec_cfgs[i].override_client_inputs << 8) |
|
||||
(tegra186_streamid_sec_cfgs[i].override_client_ns_flag << 0);
|
||||
tegra_mc_streamid_write_32(tegra186_streamid_sec_cfgs[i].offset, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-configure MSS to allow ROC to deal with ordering of the
|
||||
* Memory Controller traffic. This is needed as the Memory Controller
|
||||
* boots with MSS having all control, but ROC provides a performance
|
||||
* boost as compared to MSS.
|
||||
*/
|
||||
tegra186_memctrl_reconfig_mss_clients();
|
||||
|
||||
/* Program overrides for MC transactions */
|
||||
tegra186_memctrl_set_overrides();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to restore platform specific settings to the memory controller
|
||||
******************************************************************************/
|
||||
void plat_memctrl_restore(void)
|
||||
{
|
||||
/*
|
||||
* Re-configure MSS to allow ROC to deal with ordering of the
|
||||
* Memory Controller traffic. This is needed as the Memory Controller
|
||||
* boots with MSS having all control, but ROC provides a performance
|
||||
* boost as compared to MSS.
|
||||
*/
|
||||
tegra186_memctrl_reconfig_mss_clients();
|
||||
|
||||
/* Program overrides for MC transactions */
|
||||
tegra186_memctrl_set_overrides();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to program the scratch registers with TZDRAM settings for the
|
||||
* resume firmware
|
||||
******************************************************************************/
|
||||
void plat_memctrl_tzdram_setup(uint64_t phys_base, uint64_t size_in_bytes)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
/*
|
||||
* Setup the Memory controller to allow only secure accesses to
|
||||
* the TZDRAM carveout
|
||||
*/
|
||||
INFO("Configuring TrustZone DRAM Memory Carveout\n");
|
||||
|
||||
tegra_mc_write_32(MC_SECURITY_CFG0_0, (uint32_t)phys_base);
|
||||
tegra_mc_write_32(MC_SECURITY_CFG3_0, (uint32_t)(phys_base >> 32));
|
||||
tegra_mc_write_32(MC_SECURITY_CFG1_0, size_in_bytes >> 20);
|
||||
|
||||
/*
|
||||
* When TZ encryption is enabled, we need to setup TZDRAM
|
||||
* before CPU accesses TZ Carveout, else CPU will fetch
|
||||
* non-decrypted data. So save TZDRAM setting for SC7 resume
|
||||
* FW to restore.
|
||||
*
|
||||
* Scratch registers map:
|
||||
* RSV55_0 = CFG1[12:0] | CFG0[31:20]
|
||||
* RSV55_1 = CFG3[1:0]
|
||||
*/
|
||||
val = tegra_mc_read_32(MC_SECURITY_CFG1_0) & MC_SECURITY_SIZE_MB_MASK;
|
||||
val |= tegra_mc_read_32(MC_SECURITY_CFG0_0) & MC_SECURITY_BOM_MASK;
|
||||
mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_TZDRAM_ADDR_LO, val);
|
||||
|
||||
val = tegra_mc_read_32(MC_SECURITY_CFG3_0) & MC_SECURITY_BOM_HI_MASK;
|
||||
mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_TZDRAM_ADDR_HI, val);
|
||||
|
||||
/*
|
||||
* MCE propagates the security configuration values across the
|
||||
* CCPLEX.
|
||||
*/
|
||||
(void)mce_update_gsc_tzdram();
|
||||
}
|
||||
+472
@@ -0,0 +1,472 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <context.h>
|
||||
#include <cortex_a57.h>
|
||||
#include <denver.h>
|
||||
#include <lib/el3_runtime/context_mgmt.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <bpmp_ipc.h>
|
||||
#include <mce.h>
|
||||
#include <memctrl_v2.h>
|
||||
#include <security_engine.h>
|
||||
#include <smmu.h>
|
||||
#include <t18x_ari.h>
|
||||
#include <tegra186_private.h>
|
||||
#include <tegra_private.h>
|
||||
|
||||
extern void memcpy16(void *dest, const void *src, unsigned int length);
|
||||
|
||||
/* state id mask */
|
||||
#define TEGRA186_STATE_ID_MASK 0xFU
|
||||
/* constants to get power state's wake time */
|
||||
#define TEGRA186_WAKE_TIME_MASK 0x0FFFFFF0U
|
||||
#define TEGRA186_WAKE_TIME_SHIFT 4U
|
||||
/* default core wake mask for CPU_SUSPEND */
|
||||
#define TEGRA186_CORE_WAKE_MASK 0x180cU
|
||||
/* context size to save during system suspend */
|
||||
#define TEGRA186_SE_CONTEXT_SIZE 3U
|
||||
|
||||
static uint32_t se_regs[TEGRA186_SE_CONTEXT_SIZE];
|
||||
static struct tegra_psci_percpu_data {
|
||||
uint32_t wake_time;
|
||||
} __aligned(CACHE_WRITEBACK_GRANULE) tegra_percpu_data[PLATFORM_CORE_COUNT];
|
||||
|
||||
int32_t tegra_soc_validate_power_state(uint32_t power_state,
|
||||
psci_power_state_t *req_state)
|
||||
{
|
||||
uint8_t state_id = (uint8_t)psci_get_pstate_id(power_state) & TEGRA186_STATE_ID_MASK;
|
||||
uint32_t cpu = plat_my_core_pos();
|
||||
int32_t ret = PSCI_E_SUCCESS;
|
||||
|
||||
/* save the core wake time (in TSC ticks)*/
|
||||
tegra_percpu_data[cpu].wake_time = (power_state & TEGRA186_WAKE_TIME_MASK)
|
||||
<< TEGRA186_WAKE_TIME_SHIFT;
|
||||
|
||||
/*
|
||||
* Clean percpu_data[cpu] to DRAM. This needs to be done to ensure that
|
||||
* the correct value is read in tegra_soc_pwr_domain_suspend(), which
|
||||
* is called with caches disabled. It is possible to read a stale value
|
||||
* from DRAM in that function, because the L2 cache is not flushed
|
||||
* unless the cluster is entering CC6/CC7.
|
||||
*/
|
||||
clean_dcache_range((uint64_t)&tegra_percpu_data[cpu],
|
||||
sizeof(tegra_percpu_data[cpu]));
|
||||
|
||||
/* Sanity check the requested state id */
|
||||
switch (state_id) {
|
||||
case PSTATE_ID_CORE_IDLE:
|
||||
case PSTATE_ID_CORE_POWERDN:
|
||||
|
||||
if (psci_get_pstate_type(power_state) != PSTATE_TYPE_POWERDOWN) {
|
||||
ret = PSCI_E_INVALID_PARAMS;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Core powerdown request */
|
||||
req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id;
|
||||
req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
ERROR("%s: unsupported state id (%d)\n", __func__, state_id);
|
||||
ret = PSCI_E_INVALID_PARAMS;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state)
|
||||
{
|
||||
(void)cpu_state;
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
|
||||
{
|
||||
const plat_local_state_t *pwr_domain_state;
|
||||
uint8_t stateid_afflvl0, stateid_afflvl2;
|
||||
uint32_t cpu = plat_my_core_pos();
|
||||
const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
|
||||
mce_cstate_info_t cstate_info = { 0 };
|
||||
uint64_t mc_ctx_base;
|
||||
uint32_t val;
|
||||
|
||||
/* get the state ID */
|
||||
pwr_domain_state = target_state->pwr_domain_state;
|
||||
stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] &
|
||||
TEGRA186_STATE_ID_MASK;
|
||||
stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
|
||||
TEGRA186_STATE_ID_MASK;
|
||||
|
||||
if ((stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ||
|
||||
(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN)) {
|
||||
|
||||
/* Enter CPU idle/powerdown */
|
||||
val = (stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ?
|
||||
(uint32_t)TEGRA_ARI_CORE_C6 : (uint32_t)TEGRA_ARI_CORE_C7;
|
||||
(void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, (uint64_t)val,
|
||||
tegra_percpu_data[cpu].wake_time, 0U);
|
||||
|
||||
} else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
|
||||
|
||||
/* save SE registers */
|
||||
se_regs[0] = mmio_read_32(TEGRA_SE0_BASE +
|
||||
SE_MUTEX_WATCHDOG_NS_LIMIT);
|
||||
se_regs[1] = mmio_read_32(TEGRA_RNG1_BASE +
|
||||
RNG_MUTEX_WATCHDOG_NS_LIMIT);
|
||||
se_regs[2] = mmio_read_32(TEGRA_PKA1_BASE +
|
||||
PKA_MUTEX_WATCHDOG_NS_LIMIT);
|
||||
|
||||
/* save 'Secure Boot' Processor Feature Config Register */
|
||||
val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
|
||||
mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_BOOTP_FCFG, val);
|
||||
|
||||
/* save MC context to TZDRAM */
|
||||
mc_ctx_base = params_from_bl2->tzdram_base;
|
||||
tegra_mc_save_context((uintptr_t)mc_ctx_base);
|
||||
|
||||
/* Prepare for system suspend */
|
||||
cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7;
|
||||
cstate_info.system = (uint32_t)TEGRA_ARI_SYSTEM_SC7;
|
||||
cstate_info.system_state_force = 1;
|
||||
cstate_info.update_wake_mask = 1;
|
||||
mce_update_cstate_info(&cstate_info);
|
||||
|
||||
/* Loop until system suspend is allowed */
|
||||
do {
|
||||
val = (uint32_t)mce_command_handler(
|
||||
(uint64_t)MCE_CMD_IS_SC7_ALLOWED,
|
||||
(uint64_t)TEGRA_ARI_CORE_C7,
|
||||
MCE_CORE_SLEEP_TIME_INFINITE,
|
||||
0U);
|
||||
} while (val == 0U);
|
||||
|
||||
/* Instruct the MCE to enter system suspend state */
|
||||
(void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE,
|
||||
(uint64_t)TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U);
|
||||
|
||||
} else {
|
||||
; /* do nothing */
|
||||
}
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Helper function to check if this is the last ON CPU in the cluster
|
||||
******************************************************************************/
|
||||
static bool tegra_last_cpu_in_cluster(const plat_local_state_t *states,
|
||||
uint32_t ncpu)
|
||||
{
|
||||
plat_local_state_t target;
|
||||
bool last_on_cpu = true;
|
||||
uint32_t num_cpus = ncpu, pos = 0;
|
||||
|
||||
do {
|
||||
target = states[pos];
|
||||
if (target != PLAT_MAX_OFF_STATE) {
|
||||
last_on_cpu = false;
|
||||
}
|
||||
--num_cpus;
|
||||
pos++;
|
||||
} while (num_cpus != 0U);
|
||||
|
||||
return last_on_cpu;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Helper function to get target power state for the cluster
|
||||
******************************************************************************/
|
||||
static plat_local_state_t tegra_get_afflvl1_pwr_state(const plat_local_state_t *states,
|
||||
uint32_t ncpu)
|
||||
{
|
||||
uint32_t core_pos = (uint32_t)read_mpidr() & (uint32_t)MPIDR_CPU_MASK;
|
||||
uint32_t cpu = plat_my_core_pos();
|
||||
int32_t ret;
|
||||
plat_local_state_t target = states[core_pos];
|
||||
mce_cstate_info_t cstate_info = { 0 };
|
||||
|
||||
/* CPU suspend */
|
||||
if (target == PSTATE_ID_CORE_POWERDN) {
|
||||
/* Program default wake mask */
|
||||
cstate_info.wake_mask = TEGRA186_CORE_WAKE_MASK;
|
||||
cstate_info.update_wake_mask = 1;
|
||||
mce_update_cstate_info(&cstate_info);
|
||||
|
||||
/* Check if CCx state is allowed. */
|
||||
ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED,
|
||||
(uint64_t)TEGRA_ARI_CORE_C7,
|
||||
tegra_percpu_data[cpu].wake_time,
|
||||
0U);
|
||||
if (ret == 0) {
|
||||
target = PSCI_LOCAL_STATE_RUN;
|
||||
}
|
||||
}
|
||||
|
||||
/* CPU off */
|
||||
if (target == PLAT_MAX_OFF_STATE) {
|
||||
/* Enable cluster powerdn from last CPU in the cluster */
|
||||
if (tegra_last_cpu_in_cluster(states, ncpu)) {
|
||||
/* Enable CC7 state and turn off wake mask */
|
||||
cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7;
|
||||
cstate_info.update_wake_mask = 1;
|
||||
mce_update_cstate_info(&cstate_info);
|
||||
|
||||
/* Check if CCx state is allowed. */
|
||||
ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED,
|
||||
(uint64_t)TEGRA_ARI_CORE_C7,
|
||||
MCE_CORE_SLEEP_TIME_INFINITE,
|
||||
0U);
|
||||
if (ret == 0) {
|
||||
target = PSCI_LOCAL_STATE_RUN;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Turn off wake_mask */
|
||||
cstate_info.update_wake_mask = 1;
|
||||
mce_update_cstate_info(&cstate_info);
|
||||
target = PSCI_LOCAL_STATE_RUN;
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handler to calculate the proper target power level at the
|
||||
* specified affinity level
|
||||
******************************************************************************/
|
||||
plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl,
|
||||
const plat_local_state_t *states,
|
||||
uint32_t ncpu)
|
||||
{
|
||||
plat_local_state_t target = PSCI_LOCAL_STATE_RUN;
|
||||
uint32_t cpu = plat_my_core_pos();
|
||||
|
||||
/* System Suspend */
|
||||
if ((lvl == (uint32_t)MPIDR_AFFLVL2) &&
|
||||
(states[cpu] == PSTATE_ID_SOC_POWERDN)) {
|
||||
target = PSTATE_ID_SOC_POWERDN;
|
||||
}
|
||||
|
||||
/* CPU off, CPU suspend */
|
||||
if (lvl == (uint32_t)MPIDR_AFFLVL1) {
|
||||
target = tegra_get_afflvl1_pwr_state(states, ncpu);
|
||||
}
|
||||
|
||||
/* target cluster/system state */
|
||||
return target;
|
||||
}
|
||||
|
||||
int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
|
||||
{
|
||||
const plat_local_state_t *pwr_domain_state =
|
||||
target_state->pwr_domain_state;
|
||||
const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
|
||||
uint8_t stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
|
||||
TEGRA186_STATE_ID_MASK;
|
||||
uint64_t val;
|
||||
uint64_t src_len_in_bytes = (uint64_t)(((uintptr_t)(&__BL31_END__) -
|
||||
(uintptr_t)BL31_BASE));
|
||||
int32_t ret;
|
||||
|
||||
if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
|
||||
val = params_from_bl2->tzdram_base +
|
||||
tegra186_get_mc_ctx_size();
|
||||
|
||||
/* Initialise communication channel with BPMP */
|
||||
assert(tegra_bpmp_ipc_init() == 0);
|
||||
|
||||
/* Enable SE clock */
|
||||
ret = tegra_bpmp_ipc_enable_clock(TEGRA186_CLK_SE);
|
||||
if (ret != 0) {
|
||||
ERROR("Failed to enable clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate/save SHA256 of ATF during SC7 entry
|
||||
*/
|
||||
if (tegra_se_save_sha256_hash(BL31_BASE,
|
||||
(uint32_t)src_len_in_bytes) != 0) {
|
||||
ERROR("Hash calculation failed. Reboot\n");
|
||||
(void)tegra_soc_prepare_system_reset();
|
||||
}
|
||||
|
||||
/*
|
||||
* The TZRAM loses power when we enter system suspend. To
|
||||
* allow graceful exit from system suspend, we need to copy
|
||||
* BL3-1 over to TZDRAM.
|
||||
*/
|
||||
val = params_from_bl2->tzdram_base +
|
||||
tegra186_get_mc_ctx_size();
|
||||
memcpy16((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE,
|
||||
(uintptr_t)BL31_END - (uintptr_t)BL31_BASE);
|
||||
|
||||
/*
|
||||
* Save code base and size; this would be used by SC7-RF to
|
||||
* verify binary
|
||||
*/
|
||||
mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV68_LO,
|
||||
(uint32_t)val);
|
||||
mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV0_HI,
|
||||
(uint32_t)src_len_in_bytes);
|
||||
|
||||
ret = tegra_bpmp_ipc_disable_clock(TEGRA186_CLK_SE);
|
||||
if (ret != 0) {
|
||||
ERROR("Failed to disable clock\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
|
||||
{
|
||||
return PSCI_E_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
int32_t tegra_soc_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
int32_t ret = PSCI_E_SUCCESS;
|
||||
uint64_t target_cpu = mpidr & MPIDR_CPU_MASK;
|
||||
uint64_t target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >>
|
||||
MPIDR_AFFINITY_BITS;
|
||||
|
||||
if (target_cluster > ((uint32_t)PLATFORM_CLUSTER_COUNT - 1U)) {
|
||||
|
||||
ERROR("%s: unsupported CPU (0x%lx)\n", __func__, mpidr);
|
||||
ret = PSCI_E_NOT_PRESENT;
|
||||
|
||||
} else {
|
||||
/* construct the target CPU # */
|
||||
target_cpu |= (target_cluster << 2);
|
||||
|
||||
(void)mce_command_handler((uint64_t)MCE_CMD_ONLINE_CORE, target_cpu, 0U, 0U);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
uint8_t stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL];
|
||||
uint8_t stateid_afflvl0 = target_state->pwr_domain_state[MPIDR_AFFLVL0];
|
||||
mce_cstate_info_t cstate_info = { 0 };
|
||||
uint64_t impl, val;
|
||||
const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
|
||||
|
||||
impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
|
||||
|
||||
/*
|
||||
* Enable ECC and Parity Protection for Cortex-A57 CPUs (Tegra186
|
||||
* A02p and beyond).
|
||||
*/
|
||||
if ((plat_params->l2_ecc_parity_prot_dis != 1) && (impl != DENVER_IMPL)) {
|
||||
|
||||
val = read_l2ctlr_el1();
|
||||
val |= CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT;
|
||||
write_l2ctlr_el1(val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset power state info for CPUs when onlining, we set
|
||||
* deepest power when offlining a core but that may not be
|
||||
* requested by non-secure sw which controls idle states. It
|
||||
* will re-init this info from non-secure software when the
|
||||
* core come online.
|
||||
*/
|
||||
if (stateid_afflvl0 == PLAT_MAX_OFF_STATE) {
|
||||
|
||||
cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC1;
|
||||
cstate_info.update_wake_mask = 1;
|
||||
mce_update_cstate_info(&cstate_info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we are exiting from deep sleep and restore SE
|
||||
* context if we are.
|
||||
*/
|
||||
if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
|
||||
|
||||
mmio_write_32(TEGRA_SE0_BASE + SE_MUTEX_WATCHDOG_NS_LIMIT,
|
||||
se_regs[0]);
|
||||
mmio_write_32(TEGRA_RNG1_BASE + RNG_MUTEX_WATCHDOG_NS_LIMIT,
|
||||
se_regs[1]);
|
||||
mmio_write_32(TEGRA_PKA1_BASE + PKA_MUTEX_WATCHDOG_NS_LIMIT,
|
||||
se_regs[2]);
|
||||
|
||||
/* Init SMMU */
|
||||
tegra_smmu_init();
|
||||
|
||||
/*
|
||||
* Reset power state info for the last core doing SC7
|
||||
* entry and exit, we set deepest power state as CC7
|
||||
* and SC7 for SC7 entry which may not be requested by
|
||||
* non-secure SW which controls idle states.
|
||||
*/
|
||||
cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7;
|
||||
cstate_info.system = (uint32_t)TEGRA_ARI_SYSTEM_SC1;
|
||||
cstate_info.update_wake_mask = 1;
|
||||
mce_update_cstate_info(&cstate_info);
|
||||
}
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & (uint64_t)MIDR_IMPL_MASK;
|
||||
|
||||
(void)target_state;
|
||||
|
||||
/* Disable Denver's DCO operations */
|
||||
if (impl == DENVER_IMPL) {
|
||||
denver_disable_dco();
|
||||
}
|
||||
|
||||
/* Turn off CPU */
|
||||
(void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE,
|
||||
(uint64_t)TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U);
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
__dead2 void tegra_soc_prepare_system_off(void)
|
||||
{
|
||||
/* power off the entire system */
|
||||
mce_enter_ccplex_state((uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF);
|
||||
|
||||
wfi();
|
||||
|
||||
/* wait for the system to power down */
|
||||
for (;;) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t tegra_soc_prepare_system_reset(void)
|
||||
{
|
||||
mce_enter_ccplex_state((uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT);
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mce.h>
|
||||
#include <tegra_def.h>
|
||||
#include <tegra_private.h>
|
||||
|
||||
#define SCRATCH_SECURE_RSV1_SCRATCH_0 0x658U
|
||||
#define SCRATCH_SECURE_RSV1_SCRATCH_1 0x65CU
|
||||
|
||||
#define CPU_RESET_MODE_AA64 1U
|
||||
|
||||
/*******************************************************************************
|
||||
* Setup secondary CPU vectors
|
||||
******************************************************************************/
|
||||
void plat_secondary_setup(void)
|
||||
{
|
||||
uint32_t addr_low, addr_high;
|
||||
|
||||
INFO("Setting up secondary CPU boot\n");
|
||||
|
||||
/* TZDRAM base will be used as the "resume" address */
|
||||
addr_low = (uintptr_t)&tegra_secure_entrypoint | CPU_RESET_MODE_AA64;
|
||||
addr_high = (uintptr_t)(((uintptr_t)&tegra_secure_entrypoint >> 32U) & 0x7ffU);
|
||||
|
||||
/* save reset vector to be used during SYSTEM_SUSPEND exit */
|
||||
mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_LO,
|
||||
addr_low);
|
||||
mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI,
|
||||
addr_high);
|
||||
}
|
||||
+397
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <bl31/bl31.h>
|
||||
#include <bl31/interrupt_mgmt.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <common/ep_info.h>
|
||||
#include <common/interrupt_props.h>
|
||||
#include <context.h>
|
||||
#include <cortex_a57.h>
|
||||
#include <denver.h>
|
||||
#include <drivers/arm/gic_common.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/console.h>
|
||||
#include <lib/el3_runtime/context_mgmt.h>
|
||||
#include <lib/utils.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <mce.h>
|
||||
#include <memctrl.h>
|
||||
#include <smmu.h>
|
||||
#include <tegra_def.h>
|
||||
#include <tegra_platform.h>
|
||||
#include <tegra_private.h>
|
||||
|
||||
extern void memcpy16(void *dest, const void *src, unsigned int length);
|
||||
|
||||
/*******************************************************************************
|
||||
* Tegra186 CPU numbers in cluster #0
|
||||
*******************************************************************************
|
||||
*/
|
||||
#define TEGRA186_CLUSTER0_CORE2 2U
|
||||
#define TEGRA186_CLUSTER0_CORE3 3U
|
||||
|
||||
/*******************************************************************************
|
||||
* The Tegra power domain tree has a single system level power domain i.e. a
|
||||
* single root node. The first entry in the power domain descriptor specifies
|
||||
* the number of power domains at the highest power level.
|
||||
*******************************************************************************
|
||||
*/
|
||||
static const uint8_t tegra_power_domain_tree_desc[] = {
|
||||
/* No of root nodes */
|
||||
1,
|
||||
/* No of clusters */
|
||||
PLATFORM_CLUSTER_COUNT,
|
||||
/* No of CPU cores - cluster0 */
|
||||
PLATFORM_MAX_CPUS_PER_CLUSTER,
|
||||
/* No of CPU cores - cluster1 */
|
||||
PLATFORM_MAX_CPUS_PER_CLUSTER
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the Tegra default topology tree information.
|
||||
******************************************************************************/
|
||||
const uint8_t *plat_get_power_domain_tree_desc(void)
|
||||
{
|
||||
return tegra_power_domain_tree_desc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Table of regions to map using the MMU.
|
||||
*/
|
||||
static const mmap_region_t tegra_mmap[] = {
|
||||
MAP_REGION_FLAT(TEGRA_MISC_BASE, 0x10000U, /* 64KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_TSA_BASE, 0x20000U, /* 128KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_MC_STREAMID_BASE, 0x10000U, /* 64KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_MC_BASE, 0x10000U, /* 64KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000U, /* 128KB - UART A, B*/
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_UARTC_BASE, 0x20000U, /* 128KB - UART C, G */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_UARTD_BASE, 0x30000U, /* 192KB - UART D, E, F */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_FUSE_BASE, 0x10000U, /* 64KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000U, /* 128KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_SE0_BASE, 0x10000U, /* 64KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_PKA1_BASE, 0x10000U, /* 64KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_RNG1_BASE, 0x10000U, /* 64KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000U, /* 64KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_PMC_BASE, 0x40000U, /* 256KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_TMRUS_BASE, 0x1000U, /* 4KB */
|
||||
MT_DEVICE | MT_RO | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x10000U, /* 64KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_MMCRAB_BASE, 0x60000U, /* 384KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_ARM_ACTMON_CTR_BASE, 0x20000U, /* 128KB - ARM/Denver */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_SMMU0_BASE, 0x1000000U, /* 64KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_HSP_DBELL_BASE, 0x10000U, /* 64KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_BPMP_IPC_TX_PHYS_BASE, TEGRA_BPMP_IPC_CH_MAP_SIZE, /* 4KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(TEGRA_BPMP_IPC_RX_PHYS_BASE, TEGRA_BPMP_IPC_CH_MAP_SIZE, /* 4KB */
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
{0}
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Set up the pagetables as per the platform memory map & initialize the MMU
|
||||
******************************************************************************/
|
||||
const mmap_region_t *plat_get_mmio_map(void)
|
||||
{
|
||||
/* MMIO space */
|
||||
return tegra_mmap;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to get the System Counter Frequency
|
||||
******************************************************************************/
|
||||
uint32_t plat_get_syscnt_freq2(void)
|
||||
{
|
||||
return 31250000;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Maximum supported UART controllers
|
||||
******************************************************************************/
|
||||
#define TEGRA186_MAX_UART_PORTS 7
|
||||
|
||||
/*******************************************************************************
|
||||
* This variable holds the UART port base addresses
|
||||
******************************************************************************/
|
||||
static uint32_t tegra186_uart_addresses[TEGRA186_MAX_UART_PORTS + 1] = {
|
||||
0, /* undefined - treated as an error case */
|
||||
TEGRA_UARTA_BASE,
|
||||
TEGRA_UARTB_BASE,
|
||||
TEGRA_UARTC_BASE,
|
||||
TEGRA_UARTD_BASE,
|
||||
TEGRA_UARTE_BASE,
|
||||
TEGRA_UARTF_BASE,
|
||||
TEGRA_UARTG_BASE,
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Enable console corresponding to the console ID
|
||||
******************************************************************************/
|
||||
void plat_enable_console(int32_t id)
|
||||
{
|
||||
static console_t uart_console;
|
||||
uint32_t console_clock;
|
||||
|
||||
if ((id > 0) && (id < TEGRA186_MAX_UART_PORTS)) {
|
||||
/*
|
||||
* Reference clock used by the FPGAs is a lot slower.
|
||||
*/
|
||||
if (tegra_platform_is_fpga()) {
|
||||
console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
|
||||
} else {
|
||||
console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
|
||||
}
|
||||
|
||||
(void)console_16550_register(tegra186_uart_addresses[id],
|
||||
console_clock,
|
||||
TEGRA_CONSOLE_BAUDRATE,
|
||||
&uart_console);
|
||||
console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
|
||||
CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler for early platform setup
|
||||
******************************************************************************/
|
||||
void plat_early_platform_setup(void)
|
||||
{
|
||||
uint64_t impl, val;
|
||||
const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
|
||||
const struct tegra_bl31_params *arg_from_bl2 = plat_get_bl31_params();
|
||||
|
||||
/* Verify chip id is t186 */
|
||||
assert(tegra_chipid_is_t186());
|
||||
|
||||
/* sanity check MCE firmware compatibility */
|
||||
mce_verify_firmware_version();
|
||||
|
||||
/*
|
||||
* Do initial security configuration to allow DRAM/device access.
|
||||
*/
|
||||
tegra_memctrl_tzdram_setup(plat_params->tzdram_base,
|
||||
(uint32_t)plat_params->tzdram_size);
|
||||
|
||||
impl = (read_midr() >> MIDR_IMPL_SHIFT) & (uint64_t)MIDR_IMPL_MASK;
|
||||
|
||||
/*
|
||||
* Enable ECC and Parity Protection for Cortex-A57 CPUs (Tegra186
|
||||
* A02p and beyond).
|
||||
*/
|
||||
if ((plat_params->l2_ecc_parity_prot_dis != 1) &&
|
||||
(impl != (uint64_t)DENVER_IMPL)) {
|
||||
|
||||
val = read_l2ctlr_el1();
|
||||
val |= CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT;
|
||||
write_l2ctlr_el1(val);
|
||||
}
|
||||
|
||||
/*
|
||||
* The previous bootloader might not have placed the BL32 image
|
||||
* inside the TZDRAM. Platform handler to allow relocation of BL32
|
||||
* image to TZDRAM memory. This behavior might change per platform.
|
||||
*/
|
||||
plat_relocate_bl32_image(arg_from_bl2->bl32_image_info);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler for late platform setup
|
||||
******************************************************************************/
|
||||
void plat_late_platform_setup(void)
|
||||
{
|
||||
; /* do nothing */
|
||||
}
|
||||
|
||||
/* Secure IRQs for Tegra186 */
|
||||
static const interrupt_prop_t tegra186_interrupt_props[] = {
|
||||
INTR_PROP_DESC(TEGRA_SDEI_SGI_PRIVATE, PLAT_SDEI_CRITICAL_PRI,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
|
||||
INTR_PROP_DESC(TEGRA186_TOP_WDT_IRQ, PLAT_TEGRA_WDT_PRIO,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
|
||||
INTR_PROP_DESC(TEGRA186_AON_WDT_IRQ, PLAT_TEGRA_WDT_PRIO,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE)
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Initialize the GIC and SGIs
|
||||
******************************************************************************/
|
||||
void plat_gic_setup(void)
|
||||
{
|
||||
tegra_gic_setup(tegra186_interrupt_props, ARRAY_SIZE(tegra186_interrupt_props));
|
||||
tegra_gic_init();
|
||||
|
||||
/*
|
||||
* Initialize the FIQ handler only if the platform supports any
|
||||
* FIQ interrupt sources.
|
||||
*/
|
||||
tegra_fiq_handler_setup();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Return pointer to the BL31 params from previous bootloader
|
||||
******************************************************************************/
|
||||
struct tegra_bl31_params *plat_get_bl31_params(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PARAMS_ADDR);
|
||||
|
||||
return (struct tegra_bl31_params *)(uintptr_t)val;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Return pointer to the BL31 platform params from previous bootloader
|
||||
******************************************************************************/
|
||||
plat_params_from_bl2_t *plat_get_bl31_plat_params(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PLAT_PARAMS_ADDR);
|
||||
|
||||
return (plat_params_from_bl2_t *)(uintptr_t)val;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function implements a part of the critical interface between the psci
|
||||
* generic layer and the platform that allows the former to query the platform
|
||||
* to convert an MPIDR to a unique linear index. An error code (-1) is returned
|
||||
* in case the MPIDR is invalid.
|
||||
******************************************************************************/
|
||||
int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
{
|
||||
u_register_t cluster_id, cpu_id, pos;
|
||||
int32_t ret;
|
||||
|
||||
cluster_id = (mpidr >> (u_register_t)MPIDR_AFF1_SHIFT) & (u_register_t)MPIDR_AFFLVL_MASK;
|
||||
cpu_id = (mpidr >> (u_register_t)MPIDR_AFF0_SHIFT) & (u_register_t)MPIDR_AFFLVL_MASK;
|
||||
|
||||
/*
|
||||
* Validate cluster_id by checking whether it represents
|
||||
* one of the two clusters present on the platform.
|
||||
* Validate cpu_id by checking whether it represents a CPU in
|
||||
* one of the two clusters present on the platform.
|
||||
*/
|
||||
if ((cluster_id >= (u_register_t)PLATFORM_CLUSTER_COUNT) ||
|
||||
(cpu_id >= (u_register_t)PLATFORM_MAX_CPUS_PER_CLUSTER)) {
|
||||
ret = PSCI_E_NOT_PRESENT;
|
||||
} else {
|
||||
/* calculate the core position */
|
||||
pos = cpu_id + (cluster_id << 2U);
|
||||
|
||||
/* check for non-existent CPUs */
|
||||
if ((pos == TEGRA186_CLUSTER0_CORE2) || (pos == TEGRA186_CLUSTER0_CORE3)) {
|
||||
ret = PSCI_E_NOT_PRESENT;
|
||||
} else {
|
||||
ret = (int32_t)pos;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to relocate BL32 image to TZDRAM
|
||||
******************************************************************************/
|
||||
void plat_relocate_bl32_image(const image_info_t *bl32_img_info)
|
||||
{
|
||||
const plat_params_from_bl2_t *plat_bl31_params = plat_get_bl31_plat_params();
|
||||
const entry_point_info_t *bl32_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
|
||||
uint64_t tzdram_start, tzdram_end, bl32_start, bl32_end;
|
||||
|
||||
if ((bl32_img_info != NULL) && (bl32_ep_info != NULL)) {
|
||||
|
||||
/* Relocate BL32 if it resides outside of the TZDRAM */
|
||||
tzdram_start = plat_bl31_params->tzdram_base;
|
||||
tzdram_end = plat_bl31_params->tzdram_base +
|
||||
plat_bl31_params->tzdram_size;
|
||||
bl32_start = bl32_img_info->image_base;
|
||||
bl32_end = bl32_img_info->image_base + bl32_img_info->image_size;
|
||||
|
||||
assert(tzdram_end > tzdram_start);
|
||||
assert(bl32_end > bl32_start);
|
||||
assert(bl32_ep_info->pc > tzdram_start);
|
||||
assert(bl32_ep_info->pc < tzdram_end);
|
||||
|
||||
/* relocate BL32 */
|
||||
if ((bl32_start >= tzdram_end) || (bl32_end <= tzdram_start)) {
|
||||
|
||||
INFO("Relocate BL32 to TZDRAM\n");
|
||||
|
||||
(void)memcpy16((void *)(uintptr_t)bl32_ep_info->pc,
|
||||
(void *)(uintptr_t)bl32_start,
|
||||
bl32_img_info->image_size);
|
||||
|
||||
/* clean up non-secure intermediate buffer */
|
||||
zeromem((void *)(uintptr_t)bl32_start,
|
||||
bl32_img_info->image_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to indicate support for System Suspend
|
||||
******************************************************************************/
|
||||
bool plat_supports_system_suspend(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Platform specific runtime setup.
|
||||
******************************************************************************/
|
||||
void plat_runtime_setup(void)
|
||||
{
|
||||
/*
|
||||
* During cold boot, it is observed that the arbitration
|
||||
* bit is set in the Memory controller leading to false
|
||||
* error interrupts in the non-secure world. To avoid
|
||||
* this, clean the interrupt status register before
|
||||
* booting into the non-secure world
|
||||
*/
|
||||
tegra_memctrl_clear_pending_interrupts();
|
||||
|
||||
/*
|
||||
* During boot, USB3 and flash media (SDMMC/SATA) devices need
|
||||
* access to IRAM. Because these clients connect to the MC and
|
||||
* do not have a direct path to the IRAM, the MC implements AHB
|
||||
* redirection during boot to allow path to IRAM. In this mode
|
||||
* accesses to a programmed memory address aperture are directed
|
||||
* to the AHB bus, allowing access to the IRAM. This mode must be
|
||||
* disabled before we jump to the non-secure world.
|
||||
*/
|
||||
tegra_memctrl_disable_ahb_redirection();
|
||||
|
||||
/*
|
||||
* Verify the integrity of the previously configured SMMU(s)
|
||||
* settings
|
||||
*/
|
||||
tegra_smmu_verify();
|
||||
}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <common/runtime_svc.h>
|
||||
#include <denver.h>
|
||||
#include <lib/el3_runtime/context_mgmt.h>
|
||||
|
||||
#include <mce.h>
|
||||
#include <memctrl.h>
|
||||
#include <t18x_ari.h>
|
||||
#include <tegra_private.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Offset to read the ref_clk counter value
|
||||
******************************************************************************/
|
||||
#define REF_CLK_OFFSET 4ULL
|
||||
|
||||
/*******************************************************************************
|
||||
* Tegra186 SiP SMCs
|
||||
******************************************************************************/
|
||||
#define TEGRA_SIP_GET_ACTMON_CLK_COUNTERS 0xC2FFFE02
|
||||
#define TEGRA_SIP_MCE_CMD_ENTER_CSTATE 0xC2FFFF00
|
||||
#define TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO 0xC2FFFF01
|
||||
#define TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME 0xC2FFFF02
|
||||
#define TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS 0xC2FFFF03
|
||||
#define TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS 0xC2FFFF04
|
||||
#define TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED 0xC2FFFF05
|
||||
|
||||
#define TEGRA_SIP_MCE_CMD_CC3_CTRL 0xC2FFFF07
|
||||
#define TEGRA_SIP_MCE_CMD_ECHO_DATA 0xC2FFFF08
|
||||
#define TEGRA_SIP_MCE_CMD_READ_VERSIONS 0xC2FFFF09
|
||||
#define TEGRA_SIP_MCE_CMD_ENUM_FEATURES 0xC2FFFF0A
|
||||
#define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS 0xC2FFFF0B
|
||||
#define TEGRA_SIP_MCE_CMD_ENUM_READ_MCA 0xC2FFFF0C
|
||||
#define TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA 0xC2FFFF0D
|
||||
#define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE 0xC2FFFF0E
|
||||
#define TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE 0xC2FFFF0F
|
||||
#define TEGRA_SIP_MCE_CMD_ENABLE_LATIC 0xC2FFFF10
|
||||
#define TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ 0xC2FFFF11
|
||||
#define TEGRA_SIP_MCE_CMD_MISC_CCPLEX 0xC2FFFF12
|
||||
|
||||
/*******************************************************************************
|
||||
* This function is responsible for handling all T186 SiP calls
|
||||
******************************************************************************/
|
||||
int32_t plat_sip_handler(uint32_t smc_fid,
|
||||
uint64_t x1,
|
||||
uint64_t x2,
|
||||
uint64_t x3,
|
||||
uint64_t x4,
|
||||
const void *cookie,
|
||||
void *handle,
|
||||
uint64_t flags)
|
||||
{
|
||||
int32_t mce_ret, ret = 0;
|
||||
uint32_t impl, cpu;
|
||||
uint32_t base, core_clk_ctr, ref_clk_ctr;
|
||||
uint32_t local_smc_fid = smc_fid;
|
||||
uint64_t local_x1 = x1, local_x2 = x2, local_x3 = x3;
|
||||
|
||||
(void)x4;
|
||||
(void)cookie;
|
||||
(void)flags;
|
||||
|
||||
if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) {
|
||||
/* 32-bit function, clear top parameter bits */
|
||||
|
||||
local_x1 = (uint32_t)x1;
|
||||
local_x2 = (uint32_t)x2;
|
||||
local_x3 = (uint32_t)x3;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert SMC FID to SMC64, to support SMC32/SMC64 configurations
|
||||
*/
|
||||
local_smc_fid |= (SMC_64 << FUNCID_CC_SHIFT);
|
||||
|
||||
switch (local_smc_fid) {
|
||||
/*
|
||||
* Micro Coded Engine (MCE) commands reside in the 0x82FFFF00 -
|
||||
* 0x82FFFFFF SiP SMC space
|
||||
*/
|
||||
case TEGRA_SIP_MCE_CMD_ENTER_CSTATE:
|
||||
case TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO:
|
||||
case TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME:
|
||||
case TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS:
|
||||
case TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS:
|
||||
case TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED:
|
||||
case TEGRA_SIP_MCE_CMD_CC3_CTRL:
|
||||
case TEGRA_SIP_MCE_CMD_ECHO_DATA:
|
||||
case TEGRA_SIP_MCE_CMD_READ_VERSIONS:
|
||||
case TEGRA_SIP_MCE_CMD_ENUM_FEATURES:
|
||||
case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS:
|
||||
case TEGRA_SIP_MCE_CMD_ENUM_READ_MCA:
|
||||
case TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA:
|
||||
case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE:
|
||||
case TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE:
|
||||
case TEGRA_SIP_MCE_CMD_ENABLE_LATIC:
|
||||
case TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ:
|
||||
case TEGRA_SIP_MCE_CMD_MISC_CCPLEX:
|
||||
|
||||
/* clean up the high bits */
|
||||
local_smc_fid &= MCE_CMD_MASK;
|
||||
|
||||
/* execute the command and store the result */
|
||||
mce_ret = mce_command_handler(local_smc_fid, local_x1, local_x2, local_x3);
|
||||
write_ctx_reg(get_gpregs_ctx(handle),
|
||||
CTX_GPREG_X0, (uint64_t)(mce_ret));
|
||||
break;
|
||||
|
||||
/*
|
||||
* This function ID reads the Activity monitor's core/ref clock
|
||||
* counter values for a core/cluster.
|
||||
*
|
||||
* x1 = MPIDR of the target core
|
||||
* x2 = MIDR of the target core
|
||||
*/
|
||||
case TEGRA_SIP_GET_ACTMON_CLK_COUNTERS:
|
||||
|
||||
cpu = (uint32_t)x1 & MPIDR_CPU_MASK;
|
||||
impl = ((uint32_t)x2 >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
|
||||
|
||||
/* sanity check target CPU number */
|
||||
if (cpu > (uint32_t)PLATFORM_MAX_CPUS_PER_CLUSTER) {
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
/* get the base address for the current CPU */
|
||||
base = (impl == DENVER_IMPL) ? TEGRA_DENVER_ACTMON_CTR_BASE :
|
||||
TEGRA_ARM_ACTMON_CTR_BASE;
|
||||
|
||||
/* read the clock counter values */
|
||||
core_clk_ctr = mmio_read_32(base + (8ULL * cpu));
|
||||
ref_clk_ctr = mmio_read_32(base + (8ULL * cpu) + REF_CLK_OFFSET);
|
||||
|
||||
/* return the counter values as two different parameters */
|
||||
write_ctx_reg(get_gpregs_ctx(handle),
|
||||
CTX_GPREG_X1, (core_clk_ctr));
|
||||
write_ctx_reg(get_gpregs_ctx(handle),
|
||||
CTX_GPREG_X2, (ref_clk_ctr));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENOTSUP;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/bl_common.h>
|
||||
|
||||
#include <smmu.h>
|
||||
#include <tegra_def.h>
|
||||
#include <tegra_mc_def.h>
|
||||
|
||||
#define MAX_NUM_SMMU_DEVICES U(1)
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler to return the support SMMU devices number
|
||||
******************************************************************************/
|
||||
uint32_t plat_get_num_smmu_devices(void)
|
||||
{
|
||||
return MAX_NUM_SMMU_DEVICES;
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <common/bl_common.h>
|
||||
#include <memctrl_v2.h>
|
||||
#include <plat/common/common_def.h>
|
||||
#include <tegra_def.h>
|
||||
|
||||
#define TEGRA186_MC_CTX_SIZE 0x93
|
||||
|
||||
.globl tegra186_get_mc_ctx_size
|
||||
|
||||
/*
|
||||
* Tegra186 reset data (offset 0x0 - 0x420)
|
||||
*
|
||||
* 0x000: MC context start
|
||||
* 0x420: MC context end
|
||||
*/
|
||||
|
||||
.align 4
|
||||
__tegra186_mc_context:
|
||||
.rept TEGRA186_MC_CTX_SIZE
|
||||
.quad 0
|
||||
.endr
|
||||
|
||||
.align 4
|
||||
__tegra186_mc_context_end:
|
||||
|
||||
/* return the size of the MC context */
|
||||
func tegra186_get_mc_ctx_size
|
||||
adr x0, __tegra186_mc_context_end
|
||||
adr x1, __tegra186_mc_context
|
||||
sub x0, x0, x1
|
||||
ret
|
||||
endfunc tegra186_get_mc_ctx_size
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
#
|
||||
# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
||||
# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# platform configs
|
||||
ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS := 1
|
||||
$(eval $(call add_define,ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS))
|
||||
|
||||
ENABLE_CHIP_VERIFICATION_HARNESS := 0
|
||||
$(eval $(call add_define,ENABLE_CHIP_VERIFICATION_HARNESS))
|
||||
|
||||
RESET_TO_BL31 := 1
|
||||
|
||||
PROGRAMMABLE_RESET_ADDRESS := 0
|
||||
|
||||
COLD_BOOT_SINGLE_CPU := 1
|
||||
|
||||
RELOCATE_BL32_IMAGE := 1
|
||||
|
||||
# platform settings
|
||||
TZDRAM_BASE := 0x30000000
|
||||
$(eval $(call add_define,TZDRAM_BASE))
|
||||
|
||||
PLATFORM_CLUSTER_COUNT := 2
|
||||
$(eval $(call add_define,PLATFORM_CLUSTER_COUNT))
|
||||
|
||||
PLATFORM_MAX_CPUS_PER_CLUSTER := 4
|
||||
$(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER))
|
||||
|
||||
MAX_XLAT_TABLES := 25
|
||||
$(eval $(call add_define,MAX_XLAT_TABLES))
|
||||
|
||||
MAX_MMAP_REGIONS := 30
|
||||
$(eval $(call add_define,MAX_MMAP_REGIONS))
|
||||
|
||||
# platform files
|
||||
PLAT_INCLUDES += -Iplat/nvidia/tegra/include/t186 \
|
||||
-I${SOC_DIR}/drivers/include
|
||||
|
||||
BL31_SOURCES += ${TEGRA_GICv2_SOURCES} \
|
||||
drivers/ti/uart/aarch64/16550_console.S \
|
||||
lib/cpus/aarch64/denver.S \
|
||||
lib/cpus/aarch64/cortex_a57.S \
|
||||
${TEGRA_DRIVERS}/bpmp_ipc/intf.c \
|
||||
${TEGRA_DRIVERS}/bpmp_ipc/ivc.c \
|
||||
${TEGRA_DRIVERS}/gpcdma/gpcdma.c \
|
||||
${TEGRA_DRIVERS}/memctrl/memctrl_v2.c \
|
||||
${TEGRA_DRIVERS}/smmu/smmu.c \
|
||||
${SOC_DIR}/drivers/mce/mce.c \
|
||||
${SOC_DIR}/drivers/mce/ari.c \
|
||||
${SOC_DIR}/drivers/mce/nvg.c \
|
||||
${SOC_DIR}/drivers/mce/aarch64/nvg_helpers.S \
|
||||
$(SOC_DIR)/drivers/se/se.c \
|
||||
${SOC_DIR}/plat_memctrl.c \
|
||||
${SOC_DIR}/plat_psci_handlers.c \
|
||||
${SOC_DIR}/plat_setup.c \
|
||||
${SOC_DIR}/plat_secondary.c \
|
||||
${SOC_DIR}/plat_sip_calls.c \
|
||||
${SOC_DIR}/plat_smmu.c \
|
||||
${SOC_DIR}/plat_trampoline.S
|
||||
|
||||
# Enable workarounds for selected Cortex-A57 erratas.
|
||||
A57_DISABLE_NON_TEMPORAL_HINT := 1
|
||||
ERRATA_A57_806969 := 1
|
||||
ERRATA_A57_813419 := 1
|
||||
ERRATA_A57_813420 := 1
|
||||
ERRATA_A57_826974 := 1
|
||||
ERRATA_A57_826977 := 1
|
||||
ERRATA_A57_828024 := 1
|
||||
ERRATA_A57_829520 := 1
|
||||
ERRATA_A57_833471 := 1
|
||||
|
||||
# Enable higher performance Non-cacheable load forwarding
|
||||
A57_ENABLE_NONCACHEABLE_LOAD_FWD := 1
|
||||
Reference in New Issue
Block a user