GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -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 */
@@ -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 */
@@ -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
@@ -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);
}
}
@@ -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();
}
}
}
@@ -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;
}
@@ -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;
}
@@ -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 */