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,79 @@
/*
* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MCE_PRIVATE_H
#define MCE_PRIVATE_H
#include <stdbool.h>
#include <tegra_def.h>
/*******************************************************************************
* Macros to prepare CSTATE info request
******************************************************************************/
/* Description of the parameters for UPDATE_CSTATE_INFO request */
#define CLUSTER_CSTATE_MASK 0x7U
#define CLUSTER_CSTATE_SHIFT 0X0U
#define CLUSTER_CSTATE_UPDATE_BIT (1U << 7)
#define CCPLEX_CSTATE_MASK 0x7U
#define CCPLEX_CSTATE_SHIFT 8U
#define CCPLEX_CSTATE_UPDATE_BIT (1U << 15)
#define SYSTEM_CSTATE_MASK 0xFU
#define SYSTEM_CSTATE_SHIFT 16U
#define SYSTEM_CSTATE_UPDATE_BIT (1U << 23)
#define CSTATE_WAKE_MASK_UPDATE_BIT (1U << 31)
#define CSTATE_WAKE_MASK_SHIFT 32U
#define CSTATE_WAKE_MASK_CLEAR 0xFFFFFFFFU
/*******************************************************************************
* Core ID mask (bits 3:0 in the online request)
******************************************************************************/
#define MCE_CORE_ID_MASK 0xFU
/*******************************************************************************
* C-state statistics macros
******************************************************************************/
#define MCE_STAT_ID_SHIFT 16U
/*******************************************************************************
* Security config macros
******************************************************************************/
#define STRICT_CHECKING_ENABLED_SET (1UL << 0)
#define STRICT_CHECKING_LOCKED_SET (1UL << 1)
/* declarations for NVG handler functions */
uint64_t nvg_get_version(void);
void nvg_set_wake_time(uint32_t wake_time);
void nvg_update_cstate_info(uint32_t cluster, uint32_t ccplex,
uint32_t system, uint32_t wake_mask, uint8_t update_wake_mask);
int32_t nvg_set_cstate_stat_query_value(uint64_t data);
uint64_t nvg_get_cstate_stat_query_value(void);
int32_t nvg_is_sc7_allowed(void);
int32_t nvg_online_core(uint32_t core);
int32_t nvg_update_ccplex_gsc(uint32_t gsc_idx);
int32_t nvg_enter_cstate(uint32_t state, uint32_t wake_time);
int32_t nvg_roc_clean_cache_trbits(void);
void nvg_enable_strict_checking_mode(void);
void nvg_verify_strict_checking_mode(void);
void nvg_system_shutdown(void);
void nvg_system_reboot(void);
void nvg_clear_hsm_corr_status(void);
/* declarations for assembly functions */
void nvg_set_request_data(uint64_t req, uint64_t data);
void nvg_set_request(uint64_t req);
uint64_t nvg_get_result(void);
uint64_t nvg_cache_clean(void);
uint64_t nvg_cache_clean_inval(void);
uint64_t nvg_cache_inval_all(void);
/* MCE helper functions */
void mce_enable_strict_checking(void);
void mce_verify_strict_checking(void);
void mce_system_shutdown(void);
void mce_system_reboot(void);
void mce_clear_hsm_corr_status(void);
#endif /* MCE_PRIVATE_H */
@@ -0,0 +1,15 @@
/*
* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef SE_H
#define SE_H
int32_t tegra_se_calculate_save_sha256(uint64_t src_addr,
uint32_t src_len_inbyte);
int32_t tegra_se_suspend(void);
void tegra_se_resume(void);
#endif /* SE_H */
@@ -0,0 +1,429 @@
/*
* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef T194_NVG_H
#define T194_NVG_H
#include <lib/utils_def.h>
/**
* t194_nvg.h - Header for the NVIDIA Generic interface (NVG).
* Official documentation for this interface is included as part
* of the T194 TRM.
*/
/**
* Current version - Major version increments may break backwards
* compatiblity and binary compatibility. Minor version increments
* occur when there is only new functionality.
*/
enum {
TEGRA_NVG_VERSION_MAJOR = U(6),
TEGRA_NVG_VERSION_MINOR = U(7)
};
typedef enum {
TEGRA_NVG_CHANNEL_VERSION = U(0),
TEGRA_NVG_CHANNEL_POWER_PERF = U(1),
TEGRA_NVG_CHANNEL_POWER_MODES = U(2),
TEGRA_NVG_CHANNEL_WAKE_TIME = U(3),
TEGRA_NVG_CHANNEL_CSTATE_INFO = U(4),
TEGRA_NVG_CHANNEL_CROSSOVER_C6_LOWER_BOUND = U(5),
TEGRA_NVG_CHANNEL_CROSSOVER_CC6_LOWER_BOUND = U(6),
TEGRA_NVG_CHANNEL_CROSSOVER_CG7_LOWER_BOUND = U(8),
TEGRA_NVG_CHANNEL_CSTATE_STAT_QUERY_REQUEST = U(10),
TEGRA_NVG_CHANNEL_CSTATE_STAT_QUERY_VALUE = U(11),
TEGRA_NVG_CHANNEL_NUM_CORES = U(20),
TEGRA_NVG_CHANNEL_UNIQUE_LOGICAL_ID = U(21),
TEGRA_NVG_CHANNEL_LOGICAL_TO_PHYSICAL_MAPPING = U(22),
TEGRA_NVG_CHANNEL_LOGICAL_TO_MPIDR = U(23),
TEGRA_NVG_CHANNEL_SHUTDOWN = U(42),
TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED = U(43),
TEGRA_NVG_CHANNEL_ONLINE_CORE = U(44),
TEGRA_NVG_CHANNEL_CC3_CTRL = U(45),
TEGRA_NVG_CHANNEL_CCPLEX_CACHE_CONTROL = U(49),
TEGRA_NVG_CHANNEL_UPDATE_CCPLEX_GSC = U(50),
TEGRA_NVG_CHANNEL_HSM_ERROR_CTRL = U(53),
TEGRA_NVG_CHANNEL_SECURITY_CONFIG = U(54),
TEGRA_NVG_CHANNEL_DEBUG_CONFIG = U(55),
TEGRA_NVG_CHANNEL_DDA_SNOC_MCF = U(56),
TEGRA_NVG_CHANNEL_DDA_MCF_ORD1 = U(57),
TEGRA_NVG_CHANNEL_DDA_MCF_ORD2 = U(58),
TEGRA_NVG_CHANNEL_DDA_MCF_ORD3 = U(59),
TEGRA_NVG_CHANNEL_DDA_MCF_ISO = U(60),
TEGRA_NVG_CHANNEL_DDA_MCF_SISO = U(61),
TEGRA_NVG_CHANNEL_DDA_MCF_NISO = U(62),
TEGRA_NVG_CHANNEL_DDA_MCF_NISO_REMOTE = U(63),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_ISO = U(64),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_SISO = U(65),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_NISO = U(66),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_NISO_REMOTE = U(67),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_L3FILL = U(68),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_L3WR = U(69),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_RSP_L3RD_DMA = U(70),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_RSP_MCFRD_DMA = U(71),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_GLOBAL = U(72),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_LL = U(73),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_L3D = U(74),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_FCM_RD = U(75),
TEGRA_NVG_CHANNEL_DDA_L3CTRL_FCM_WR = U(76),
TEGRA_NVG_CHANNEL_DDA_SNOC_GLOBAL_CTRL = U(77),
TEGRA_NVG_CHANNEL_DDA_SNOC_CLIENT_REQ_CTRL = U(78),
TEGRA_NVG_CHANNEL_DDA_SNOC_CLIENT_REPLENTISH_CTRL = U(79),
TEGRA_NVG_CHANNEL_RT_SAFE_MASK = U(80),
TEGRA_NVG_CHANNEL_RT_WINDOW_US = U(81),
TEGRA_NVG_CHANNEL_RT_FWD_PROGRESS_US = U(82),
TEGRA_NVG_CHANNEL_LAST_INDEX
} tegra_nvg_channel_id_t;
typedef enum {
NVG_STAT_QUERY_SC7_ENTRIES = U(1),
NVG_STAT_QUERY_CC6_ENTRIES = U(6),
NVG_STAT_QUERY_CG7_ENTRIES = U(7),
NVG_STAT_QUERY_C6_ENTRIES = U(10),
NVG_STAT_QUERY_C7_ENTRIES = U(14),
NVG_STAT_QUERY_SC7_RESIDENCY_SUM = U(32),
NVG_STAT_QUERY_CC6_RESIDENCY_SUM = U(41),
NVG_STAT_QUERY_CG7_RESIDENCY_SUM = U(46),
NVG_STAT_QUERY_C6_RESIDENCY_SUM = U(51),
NVG_STAT_QUERY_C7_RESIDENCY_SUM = U(56),
NVG_STAT_QUERY_SC7_ENTRY_TIME_SUM = U(60),
NVG_STAT_QUERY_CC6_ENTRY_TIME_SUM = U(61),
NVG_STAT_QUERY_CG7_ENTRY_TIME_SUM = U(62),
NVG_STAT_QUERY_C6_ENTRY_TIME_SUM = U(63),
NVG_STAT_QUERY_C7_ENTRY_TIME_SUM = U(64),
NVG_STAT_QUERY_SC7_EXIT_TIME_SUM = U(70),
NVG_STAT_QUERY_CC6_EXIT_TIME_SUM = U(71),
NVG_STAT_QUERY_CG7_EXIT_TIME_SUM = U(72),
NVG_STAT_QUERY_C6_EXIT_TIME_SUM = U(73),
NVG_STAT_QUERY_C7_EXIT_TIME_SUM = U(74),
NVG_STAT_QUERY_SC7_ENTRY_LAST = U(80),
NVG_STAT_QUERY_CC6_ENTRY_LAST = U(81),
NVG_STAT_QUERY_CG7_ENTRY_LAST = U(82),
NVG_STAT_QUERY_C6_ENTRY_LAST = U(83),
NVG_STAT_QUERY_C7_ENTRY_LAST = U(84),
NVG_STAT_QUERY_SC7_EXIT_LAST = U(90),
NVG_STAT_QUERY_CC6_EXIT_LAST = U(91),
NVG_STAT_QUERY_CG7_EXIT_LAST = U(92),
NVG_STAT_QUERY_C6_EXIT_LAST = U(93),
NVG_STAT_QUERY_C7_EXIT_LAST = U(94)
} tegra_nvg_stat_query_t;
typedef enum {
TEGRA_NVG_CORE_C0 = U(0),
TEGRA_NVG_CORE_C1 = U(1),
TEGRA_NVG_CORE_C6 = U(6),
TEGRA_NVG_CORE_C7 = U(7),
TEGRA_NVG_CORE_WARMRSTREQ = U(8)
} tegra_nvg_core_sleep_state_t;
typedef enum {
TEGRA_NVG_SHUTDOWN = U(0),
TEGRA_NVG_REBOOT = U(1)
} tegra_nvg_shutdown_reboot_state_t;
typedef enum {
TEGRA_NVG_CLUSTER_CC0 = U(0),
TEGRA_NVG_CLUSTER_AUTO_CC1 = U(1),
TEGRA_NVG_CLUSTER_CC6 = U(6)
} tegra_nvg_cluster_sleep_state_t;
typedef enum {
TEGRA_NVG_CG_CG0 = U(0),
TEGRA_NVG_CG_CG7 = U(7)
} tegra_nvg_cluster_group_sleep_state_t;
typedef enum {
TEGRA_NVG_SYSTEM_SC0 = U(0),
TEGRA_NVG_SYSTEM_SC7 = U(7),
TEGRA_NVG_SYSTEM_SC8 = U(8)
} tegra_nvg_system_sleep_state_t;
// ---------------------------------------------------------------------------
// NVG Data subformats
// ---------------------------------------------------------------------------
typedef union {
uint64_t flat;
struct nvg_version_channel_t {
uint32_t minor_version : U(32);
uint32_t major_version : U(32);
} bits;
} nvg_version_data_t;
typedef union {
uint64_t flat;
struct {
uint32_t perf_per_watt : U(1);
uint32_t reserved_31_1 : U(31);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_power_perf_channel_t;
typedef union {
uint64_t flat;
struct {
uint32_t low_battery : U(1);
uint32_t reserved_1_1 : U(1);
uint32_t battery_save : U(1);
uint32_t reserved_31_3 : U(29);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_power_modes_channel_t;
typedef union nvg_channel_1_data_u {
uint64_t flat;
struct nvg_channel_1_data_s {
uint32_t perf_per_watt_mode : U(1);
uint32_t reserved_31_1 : U(31);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_channel_1_data_t;
typedef union {
uint64_t flat;
struct {
uint32_t gpu_ways : U(5);
uint32_t reserved_7_5 : U(3);
uint32_t gpu_only_ways : U(5);
uint32_t reserved_31_13 : U(19);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_ccplex_cache_control_channel_t;
typedef union nvg_channel_2_data_u {
uint64_t flat;
struct nvg_channel_2_data_s {
uint32_t reserved_1_0 : U(2);
uint32_t battery_saver_mode : U(1);
uint32_t reserved_31_3 : U(29);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_channel_2_data_t;
typedef union {
uint64_t flat;
struct {
uint32_t wake_time : U(32);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_wake_time_channel_t;
typedef union {
uint64_t flat;
struct {
uint32_t cluster_state : U(3);
uint32_t reserved_6_3 : U(4);
uint32_t update_cluster : U(1);
uint32_t cg_cstate : U(3);
uint32_t reserved_14_11 : U(4);
uint32_t update_cg : U(1);
uint32_t system_cstate : U(4);
uint32_t reserved_22_20 : U(3);
uint32_t update_system : U(1);
uint32_t reserved_30_24 : U(7);
uint32_t update_wake_mask : U(1);
union {
uint32_t flat : U(32);
struct {
uint32_t vfiq : U(1);
uint32_t virq : U(1);
uint32_t fiq : U(1);
uint32_t irq : U(1);
uint32_t serror : U(1);
uint32_t reserved_10_5 : U(6);
uint32_t fiqout : U(1);
uint32_t irqout : U(1);
uint32_t reserved_31_13 : U(19);
} carmel;
} wake_mask;
} bits;
} nvg_cstate_info_channel_t;
typedef union {
uint64_t flat;
struct {
uint32_t crossover_value : U(32);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_lower_bound_channel_t;
typedef union {
uint64_t flat;
struct {
uint32_t unit_id : U(4);
uint32_t reserved_15_4 : U(12);
uint32_t stat_id : U(16);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_cstate_stat_query_channel_t;
typedef union {
uint64_t flat;
struct {
uint32_t num_cores : U(4);
uint32_t reserved_31_4 : U(28);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_num_cores_channel_t;
typedef union {
uint64_t flat;
struct {
uint32_t unique_core_id : U(3);
uint32_t reserved_31_3 : U(29);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_unique_logical_id_channel_t;
typedef union {
uint64_t flat;
struct {
uint32_t lcore0_pcore_id : U(4);
uint32_t lcore1_pcore_id : U(4);
uint32_t lcore2_pcore_id : U(4);
uint32_t lcore3_pcore_id : U(4);
uint32_t lcore4_pcore_id : U(4);
uint32_t lcore5_pcore_id : U(4);
uint32_t lcore6_pcore_id : U(4);
uint32_t lcore7_pcore_id : U(4);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_logical_to_physical_mappings_channel_t;
typedef union {
uint64_t flat;
struct nvg_logical_to_mpidr_channel_write_t {
uint32_t lcore_id : U(3);
uint32_t reserved_31_3 : U(29);
uint32_t reserved_63_32 : U(32);
} write;
struct nvg_logical_to_mpidr_channel_read_t {
uint32_t mpidr : U(32);
uint32_t reserved_63_32 : U(32);
} read;
} nvg_logical_to_mpidr_channel_t;
typedef union {
uint64_t flat;
struct {
uint32_t is_sc7_allowed : U(1);
uint32_t reserved_31_1 : U(31);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_is_sc7_allowed_channel_t;
typedef union {
uint64_t flat;
struct {
uint32_t core_id : U(4);
uint32_t reserved_31_4 : U(28);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_core_online_channel_t;
typedef union {
uint64_t flat;
struct {
uint32_t freq_req : U(9);
uint32_t reserved_30_9 : U(22);
uint32_t enable : U(1);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_cc3_control_channel_t;
typedef enum {
TEGRA_NVG_CHANNEL_UPDATE_GSC_ALL = U(0),
TEGRA_NVG_CHANNEL_UPDATE_GSC_NVDEC = U(1),
TEGRA_NVG_CHANNEL_UPDATE_GSC_WPR1 = U(2),
TEGRA_NVG_CHANNEL_UPDATE_GSC_WPR2 = U(3),
TEGRA_NVG_CHANNEL_UPDATE_GSC_TSECA = U(4),
TEGRA_NVG_CHANNEL_UPDATE_GSC_TSECB = U(5),
TEGRA_NVG_CHANNEL_UPDATE_GSC_BPMP = U(6),
TEGRA_NVG_CHANNEL_UPDATE_GSC_APE = U(7),
TEGRA_NVG_CHANNEL_UPDATE_GSC_SPE = U(8),
TEGRA_NVG_CHANNEL_UPDATE_GSC_SCE = U(9),
TEGRA_NVG_CHANNEL_UPDATE_GSC_APR = U(10),
TEGRA_NVG_CHANNEL_UPDATE_GSC_TZRAM = U(11),
TEGRA_NVG_CHANNEL_UPDATE_GSC_IPC_SE_TSEC = U(12),
TEGRA_NVG_CHANNEL_UPDATE_GSC_BPMP_TO_RCE = U(13),
TEGRA_NVG_CHANNEL_UPDATE_GSC_BPMP_TO_MCE = U(14),
TEGRA_NVG_CHANNEL_UPDATE_GSC_SE_SC7 = U(15),
TEGRA_NVG_CHANNEL_UPDATE_GSC_BPMP_TO_SPE = U(16),
TEGRA_NVG_CHANNEL_UPDATE_GSC_RCE = U(17),
TEGRA_NVG_CHANNEL_UPDATE_GSC_CPU_TZ_TO_BPMP = U(18),
TEGRA_NVG_CHANNEL_UPDATE_GSC_VM_ENCR1 = U(19),
TEGRA_NVG_CHANNEL_UPDATE_GSC_CPU_NS_TO_BPMP = U(20),
TEGRA_NVG_CHANNEL_UPDATE_GSC_OEM_SC7 = U(21),
TEGRA_NVG_CHANNEL_UPDATE_GSC_IPC_SE_SPE_SCE_BPMP = U(22),
TEGRA_NVG_CHANNEL_UPDATE_GSC_SC7_RESUME_FW = U(23),
TEGRA_NVG_CHANNEL_UPDATE_GSC_CAMERA_TASKLIST = U(24),
TEGRA_NVG_CHANNEL_UPDATE_GSC_XUSB = U(25),
TEGRA_NVG_CHANNEL_UPDATE_GSC_CV = U(26),
TEGRA_NVG_CHANNEL_UPDATE_GSC_VM_ENCR2 = U(27),
TEGRA_NVG_CHANNEL_UPDATE_GSC_HYPERVISOR_SW = U(28),
TEGRA_NVG_CHANNEL_UPDATE_GSC_SMMU_PAGETABLES = U(29),
TEGRA_NVG_CHANNEL_UPDATE_GSC_30 = U(30),
TEGRA_NVG_CHANNEL_UPDATE_GSC_31 = U(31),
TEGRA_NVG_CHANNEL_UPDATE_GSC_TZ_DRAM = U(32),
TEGRA_NVG_CHANNEL_UPDATE_GSC_NVLINK = U(33),
TEGRA_NVG_CHANNEL_UPDATE_GSC_SBS = U(34),
TEGRA_NVG_CHANNEL_UPDATE_GSC_VPR = U(35),
TEGRA_NVG_CHANNEL_UPDATE_GSC_LAST_INDEX
} tegra_nvg_channel_update_gsc_gsc_enum_t;
typedef union {
uint64_t flat;
struct {
uint32_t gsc_enum : U(16);
uint32_t reserved_31_16 : U(16);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_update_ccplex_gsc_channel_t;
typedef union {
uint64_t flat;
struct nvg_security_config_channel_t {
uint32_t strict_checking_enabled : U(1);
uint32_t strict_checking_locked : U(1);
uint32_t reserved_31_2 : U(30);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_security_config_t;
typedef union {
uint64_t flat;
struct nvg_shutdown_channel_t {
uint32_t reboot : U(1);
uint32_t reserved_31_1 : U(31);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_shutdown_t;
typedef union {
uint64_t flat;
struct nvg_debug_config_channel_t {
uint32_t enter_debug_state_on_mca : U(1);
uint32_t reserved_31_1 : U(31);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_debug_config_t;
typedef union {
uint64_t flat;
struct {
uint32_t uncorr : U(1);
uint32_t corr : U(1);
uint32_t reserved_31_2 : U(30);
uint32_t reserved_63_32 : U(32);
} bits;
} nvg_hsm_error_ctrl_channel_t;
extern nvg_debug_config_t nvg_debug_config;
#endif /* T194_NVG_H */
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2019, NVIDIA CORPORATION. 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
.globl nvg_cache_clean
.globl nvg_cache_clean_inval
.globl nvg_cache_inval_all
/* 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
/* uint64_t nvg_cache_clean(void) */
func nvg_cache_clean
mrs x0, s3_0_c15_c3_5
ret
endfunc nvg_cache_clean
/* uint64_t nvg_cache_clean_inval(void) */
func nvg_cache_clean_inval
mrs x0, s3_0_c15_c3_6
ret
endfunc nvg_cache_clean_inval
/* uint64_t nvg_cache_inval_all(void) */
func nvg_cache_inval_all
mrs x0, s3_0_c15_c3_7
ret
endfunc nvg_cache_inval_all
@@ -0,0 +1,255 @@
/*
* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <arch_helpers.h>
#include <assert.h>
#include <common/bl_common.h>
#include <context.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <common/debug.h>
#include <denver.h>
#include <mce.h>
#include <mce_private.h>
#include <platform_def.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <inttypes.h>
#include <t194_nvg.h>
#include <tegra_def.h>
#include <tegra_platform.h>
#include <tegra_private.h>
/* Handler to check if MCE firmware is supported */
static bool mce_firmware_not_supported(void)
{
bool status;
/* these platforms do not load MCE firmware */
status = tegra_platform_is_linsim() || tegra_platform_is_qt() ||
tegra_platform_is_virt_dev_kit();
return status;
}
/*******************************************************************************
* Common handler for all MCE commands
******************************************************************************/
int32_t mce_command_handler(uint64_t cmd, uint64_t arg0, uint64_t arg1,
uint64_t arg2)
{
int32_t ret = 0;
switch (cmd) {
case (uint64_t)MCE_CMD_ENTER_CSTATE:
ret = nvg_enter_cstate((uint32_t)arg0, (uint32_t)arg1);
if (ret < 0) {
ERROR("%s: enter_cstate failed(%d)\n", __func__, ret);
}
break;
case (uint64_t)MCE_CMD_IS_SC7_ALLOWED:
ret = nvg_is_sc7_allowed();
if (ret < 0) {
ERROR("%s: is_sc7_allowed failed(%d)\n", __func__, ret);
}
break;
case (uint64_t)MCE_CMD_ONLINE_CORE:
ret = nvg_online_core((uint32_t)arg0);
if (ret < 0) {
ERROR("%s: online_core failed(%d)\n", __func__, ret);
}
break;
default:
ERROR("unknown MCE command (%" PRIu64 ")\n", cmd);
ret = -EINVAL;
break;
}
return ret;
}
/*******************************************************************************
* Handler to update carveout values for Video Memory Carveout region
******************************************************************************/
int32_t mce_update_gsc_videomem(void)
{
int32_t ret;
/*
* MCE firmware is not running on simulation platforms.
*/
if (mce_firmware_not_supported()) {
ret = -EINVAL;
} else {
ret = nvg_update_ccplex_gsc((uint32_t)TEGRA_NVG_CHANNEL_UPDATE_GSC_VPR);
}
return ret;
}
/*******************************************************************************
* Handler to update carveout values for TZDRAM aperture
******************************************************************************/
int32_t mce_update_gsc_tzdram(void)
{
int32_t ret;
/*
* MCE firmware is not running on simulation platforms.
*/
if (mce_firmware_not_supported()) {
ret = -EINVAL;
} else {
ret = nvg_update_ccplex_gsc((uint32_t)TEGRA_NVG_CHANNEL_UPDATE_GSC_TZ_DRAM);
}
return ret;
}
/*******************************************************************************
* Handler to issue the UPDATE_CSTATE_INFO request
******************************************************************************/
void mce_update_cstate_info(const mce_cstate_info_t *cstate)
{
/* issue the UPDATE_CSTATE_INFO request */
nvg_update_cstate_info(cstate->cluster, cstate->ccplex, cstate->system,
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)
{
uint64_t version;
uint32_t major, minor;
/*
* MCE firmware is not running on simulation platforms.
*/
if (mce_firmware_not_supported()) {
return;
}
/*
* Read the MCE firmware version and extract the major and minor
* version fields
*/
version = nvg_get_version();
minor = (uint32_t)version;
major = (uint32_t)(version >> 32);
INFO("MCE Version - HW=%u:%u, SW=%u:%u\n", major, minor,
TEGRA_NVG_VERSION_MAJOR, TEGRA_NVG_VERSION_MINOR);
/*
* Verify that the MCE firmware version and the interface header
* match
*/
if (major != (uint32_t)TEGRA_NVG_VERSION_MAJOR) {
ERROR("MCE major version mismatch\n");
panic();
}
if (minor < (uint32_t)TEGRA_NVG_VERSION_MINOR) {
ERROR("MCE minor version mismatch\n");
panic();
}
}
#if ENABLE_STRICT_CHECKING_MODE
/*******************************************************************************
* Handler to enable the strict checking mode
******************************************************************************/
void mce_enable_strict_checking(void)
{
uint64_t sctlr = read_sctlr_el3();
int32_t ret = 0;
if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) {
/*
* Step1: TZ-DRAM and TZRAM should be setup before the MMU is
* enabled.
*
* The common code makes sure that TZDRAM/TZRAM are already
* enabled before calling into this handler. If this is not the
* case, the following sequence must be executed before moving
* on to step 2.
*
* tlbialle1is();
* tlbialle3is();
* dsbsy();
* isb();
*
*/
if ((sctlr & (uint64_t)SCTLR_M_BIT) == (uint64_t)SCTLR_M_BIT) {
tlbialle1is();
tlbialle3is();
dsbsy();
isb();
}
/*
* Step2: SCF flush - Clean and invalidate caches and clear the
* TR-bits
*/
ret = nvg_roc_clean_cache_trbits();
if (ret < 0) {
ERROR("%s: flush cache_trbits failed(%d)\n", __func__,
ret);
return;
}
/*
* Step3: Issue the SECURITY_CONFIG request to MCE to enable
* strict checking mode.
*/
nvg_enable_strict_checking_mode();
}
}
void mce_verify_strict_checking(void)
{
bool is_silicon = tegra_platform_is_silicon();
bool is_fpga = tegra_platform_is_fpga();
if (is_silicon || is_fpga) {
nvg_verify_strict_checking_mode();
}
}
#endif
/*******************************************************************************
* Handler to power down the entire system
******************************************************************************/
void mce_system_shutdown(void)
{
nvg_system_shutdown();
}
/*******************************************************************************
* Handler to reboot the entire system
******************************************************************************/
void mce_system_reboot(void)
{
nvg_system_reboot();
}
/*******************************************************************************
* Handler to clear CCPLEX->HSM correctable RAS error signal.
******************************************************************************/
void mce_clear_hsm_corr_status(void)
{
nvg_clear_hsm_corr_status();
}
@@ -0,0 +1,262 @@
/*
* Copyright (c) 2019-2020, NVIDIA CORPORATION. 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 <denver.h>
#include <lib/mmio.h>
#include <mce_private.h>
#include <platform_def.h>
#include <t194_nvg.h>
#include <tegra_private.h>
#define ID_AFR0_EL1_CACHE_OPS_SHIFT U(12)
#define ID_AFR0_EL1_CACHE_OPS_MASK U(0xF)
/*
* Reports the major and minor version of this interface.
*
* NVGDATA[0:31]: SW(R) Minor Version
* NVGDATA[32:63]: SW(R) Major Version
*/
uint64_t nvg_get_version(void)
{
nvg_set_request((uint64_t)TEGRA_NVG_CHANNEL_VERSION);
return (uint64_t)nvg_get_result();
}
/*
* Set the expected wake time in TSC ticks for the next low-power state the
* core enters.
*
* NVGDATA[0:31]: SW(RW), WAKE_TIME
*/
void nvg_set_wake_time(uint32_t wake_time)
{
/* time (TSC ticks) until the core is expected to get a wake event */
nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_WAKE_TIME, (uint64_t)wake_time);
}
/*
* This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and
* SYSTEM_CSTATE values.
*
* NVGDATA[0:2]: SW(RW), CLUSTER_CSTATE
* NVGDATA[7]: SW(W), update cluster flag
* NVGDATA[8:10]: SW(RW), CG_CSTATE
* NVGDATA[15]: SW(W), update ccplex flag
* NVGDATA[16:19]: SW(RW), SYSTEM_CSTATE
* NVGDATA[23]: SW(W), update system flag
* NVGDATA[31]: SW(W), update wake mask flag
* NVGDATA[32:63]: SW(RW), WAKE_MASK
*/
void nvg_update_cstate_info(uint32_t cluster, uint32_t ccplex,
uint32_t system, uint32_t wake_mask, uint8_t update_wake_mask)
{
uint64_t val = 0;
/* 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) |
SYSTEM_CSTATE_UPDATE_BIT;
}
/* update wake mask value? */
if (update_wake_mask != 0U) {
val |= CSTATE_WAKE_MASK_UPDATE_BIT;
}
/* set the wake mask */
val |= ((uint64_t)wake_mask & CSTATE_WAKE_MASK_CLEAR) << CSTATE_WAKE_MASK_SHIFT;
/* set the updated cstate info */
nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_CSTATE_INFO, val);
}
/*
* Return a non-zero value if the CCPLEX is able to enter SC7
*
* NVGDATA[0]: SW(R), Is allowed result
*/
int32_t nvg_is_sc7_allowed(void)
{
/* issue command to check if SC7 is allowed */
nvg_set_request((uint64_t)TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED);
/* 1 = SC7 allowed, 0 = SC7 not allowed */
return (int32_t)nvg_get_result();
}
/*
* Wake an offlined logical core. Note that a core is offlined by entering
* a C-state where the WAKE_MASK is all 0.
*
* NVGDATA[0:3]: SW(W) logical core to online
*/
int32_t nvg_online_core(uint32_t core)
{
int32_t ret = 0;
/* sanity check the core ID value */
if (core > (uint32_t)PLATFORM_CORE_COUNT) {
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;
}
/*
* MC GSC (General Security Carveout) register values are expected to be
* changed by TrustZone ARM code after boot.
*
* NVGDATA[0:15] SW(R) GSC enun
*/
int32_t nvg_update_ccplex_gsc(uint32_t gsc_idx)
{
int32_t ret = 0;
/* sanity check GSC ID */
if (gsc_idx > (uint32_t)TEGRA_NVG_CHANNEL_UPDATE_GSC_VPR) {
ERROR("%s: unknown gsc_idx (%u)\n", __func__, gsc_idx);
ret = -EINVAL;
} else {
nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_UPDATE_CCPLEX_GSC,
(uint64_t)gsc_idx);
}
return ret;
}
/*
* Cache clean and invalidate, clear TR-bit operation for all CCPLEX caches.
*/
int32_t nvg_roc_clean_cache_trbits(void)
{
int32_t ret = 0;
/* check if cache flush through mts is supported */
if (((read_id_afr0_el1() >> ID_AFR0_EL1_CACHE_OPS_SHIFT) &
ID_AFR0_EL1_CACHE_OPS_MASK) == 1U) {
if (nvg_cache_inval_all() == 0U) {
ERROR("%s: failed\n", __func__);
ret = -ENODEV;
}
} else {
ret = -ENOTSUP;
}
return ret;
}
/*
* Set the power state for a core
*/
int32_t nvg_enter_cstate(uint32_t state, uint32_t wake_time)
{
int32_t ret = 0;
uint64_t val = 0ULL;
/* check for allowed power state */
if ((state != (uint32_t)TEGRA_NVG_CORE_C0) &&
(state != (uint32_t)TEGRA_NVG_CORE_C1) &&
(state != (uint32_t)TEGRA_NVG_CORE_C6) &&
(state != (uint32_t)TEGRA_NVG_CORE_C7))
{
ERROR("%s: unknown cstate (%u)\n", __func__, state);
ret = -EINVAL;
} else {
/* time (TSC ticks) until the core is expected to get a wake event */
nvg_set_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;
}
#if ENABLE_STRICT_CHECKING_MODE
/*
* Enable strict checking mode
*
* NVGDATA[3] strict_check ON + lock
*/
void nvg_enable_strict_checking_mode(void)
{
uint64_t params = (uint64_t)(STRICT_CHECKING_ENABLED_SET |
STRICT_CHECKING_LOCKED_SET);
nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SECURITY_CONFIG, params);
}
void nvg_verify_strict_checking_mode(void)
{
uint64_t params = (uint64_t)(STRICT_CHECKING_ENABLED_SET |
STRICT_CHECKING_LOCKED_SET);
nvg_set_request((uint64_t)TEGRA_NVG_CHANNEL_SECURITY_CONFIG);
assert(params == (uint64_t)nvg_get_result());
}
#endif
/*
* Request a reboot
*
* NVGDATA[0]: reboot command
*/
void nvg_system_reboot(void)
{
/* issue command for reboot */
nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SHUTDOWN,
(uint64_t)TEGRA_NVG_REBOOT);
}
/*
* Request a shutdown
*
* NVGDATA[0]: shutdown command
*/
void nvg_system_shutdown(void)
{
/* issue command for shutdown */
nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SHUTDOWN,
(uint64_t)TEGRA_NVG_SHUTDOWN);
}
/*
* Request to clear CCPLEX->HSM correctable error signal.
* NVGDATA[1]: A write of 1 clears the CCPLEX->HSM correctable error signal,
* A write of 0 has no effect.
*/
void nvg_clear_hsm_corr_status(void)
{
nvg_hsm_error_ctrl_channel_t status = { .bits = { .corr = 1U, }, };
nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_HSM_ERROR_CTRL, status.flat);
}
@@ -0,0 +1,511 @@
/*
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <arch_helpers.h>
#include <bpmp_ipc.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <lib/psci/psci.h>
#include <se.h>
#include <tegra_platform.h>
#include "se_private.h"
/*******************************************************************************
* Constants and Macros
******************************************************************************/
#define ERR_STATUS_SW_CLEAR U(0xFFFFFFFF)
#define INT_STATUS_SW_CLEAR U(0xFFFFFFFF)
#define MAX_TIMEOUT_MS U(1000) /* Max. timeout of 1s */
#define NUM_SE_REGS_TO_SAVE U(4)
#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)
/*******************************************************************************
* Data structure and global variables
******************************************************************************/
static uint32_t se_regs[NUM_SE_REGS_TO_SAVE];
/*
* 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. SE_STATUS = IDLE
* 2. AHB bus data transfer is complete.
* 3. SE_ERR_STATUS is clean.
*/
static bool tegra_se_is_operation_complete(void)
{
uint32_t val = 0, timeout = 0, sha_status, aes_status;
int32_t ret = 0;
bool se_is_busy, txn_has_errors, txn_successful;
/*
* Poll the status register to check if the operation
* completed.
*/
do {
val = tegra_se_read_32(CTX_SAVE_AUTO_STATUS);
se_is_busy = ((val & CTX_SAVE_AUTO_SE_BUSY) != 0U);
/* sleep until SE finishes */
if (se_is_busy) {
mdelay(1);
timeout++;
}
} while (se_is_busy && (timeout < MAX_TIMEOUT_MS));
/* any transaction errors? */
txn_has_errors = (tegra_se_read_32(SHA_ERR_STATUS) != 0U) ||
(tegra_se_read_32(AES0_ERR_STATUS) != 0U);
/* transaction successful? */
sha_status = tegra_se_read_32(SHA_INT_STATUS) & SHA_SE_OP_DONE;
aes_status = tegra_se_read_32(AES0_INT_STATUS) & AES0_SE_OP_DONE;
txn_successful = (sha_status == SHA_SE_OP_DONE) &&
(aes_status == AES0_SE_OP_DONE);
if ((timeout == MAX_TIMEOUT_MS) || txn_has_errors || !txn_successful) {
ERROR("%s: Atomic context save operation failed!\n",
__func__);
ret = -ECANCELED;
}
return (ret == 0);
}
/*
* Wait for SE engine to be idle and clear any pending interrupts, before
* starting the next SE operation.
*/
static bool tegra_se_is_ready(void)
{
int32_t ret = 0;
uint32_t val = 0, timeout = 0;
bool se_is_ready;
/* Wait for previous operation to finish */
do {
val = tegra_se_read_32(CTX_SAVE_AUTO_STATUS);
se_is_ready = (val == CTX_SAVE_AUTO_SE_READY);
/* sleep until SE is ready */
if (!se_is_ready) {
mdelay(1);
timeout++;
}
} while (!se_is_ready && (timeout < MAX_TIMEOUT_MS));
if (timeout == MAX_TIMEOUT_MS) {
ERROR("%s: SE is not ready!\n", __func__);
ret = -ETIMEDOUT;
}
/* Clear any pending interrupts from previous operation */
tegra_se_write_32(AES0_INT_STATUS, INT_STATUS_SW_CLEAR);
tegra_se_write_32(AES1_INT_STATUS, INT_STATUS_SW_CLEAR);
tegra_se_write_32(RSA_INT_STATUS, INT_STATUS_SW_CLEAR);
tegra_se_write_32(SHA_INT_STATUS, INT_STATUS_SW_CLEAR);
/* Clear error status for each engine seen from current port */
tegra_se_write_32(AES0_ERR_STATUS, ERR_STATUS_SW_CLEAR);
tegra_se_write_32(AES1_ERR_STATUS, ERR_STATUS_SW_CLEAR);
tegra_se_write_32(RSA_ERR_STATUS, ERR_STATUS_SW_CLEAR);
tegra_se_write_32(SHA_ERR_STATUS, ERR_STATUS_SW_CLEAR);
return (ret == 0);
}
/*
* During System Suspend, this handler triggers the hardware context
* save operation.
*/
static int32_t tegra_se_save_context(void)
{
int32_t ret = -ECANCELED;
/*
* 1. Ensure all SE Driver including RNG1/PKA1 are shut down.
* TSEC/R5s are powergated/idle. All tasks on SE1~SE4, RNG1,
* PKA1 are wrapped up. SE0 is ready for use.
* 2. Clear interrupt/error in SE0 status register.
* 3. Scrub SE0 register to avoid false failure for illegal
* configuration. Probably not needed, dependent on HW
* implementation.
* 4. Check SE is ready for HW CTX_SAVE by polling
* SE_CTX_SAVE_AUTO_STATUS.SE_READY.
*
* Steps 1-4 are executed by tegra_se_is_ready().
*
* 5. Issue context save command.
* 6. Check SE is busy with CTX_SAVE, the command in step5 was not
* dropped for ongoing traffic in any of SE port/engine.
* 7. Poll SE register or wait for SE APB interrupt for task completion
* a. Polling: Read SE_CTX_SAVE_AUTO_STATUS.BUSY till it reports IDLE
* b. Interrupt: After receiving interrupt from SE APB, read
* SE_CTX_SAVE_AUTO_STATUS.BUSY till it reports IDLE.
* 8. Check AES0 and SHA ERR_STATUS to ensure no error case.
* 9. Check AES0 and SHA INT_STATUS to ensure operation has successfully
* completed.
*
* Steps 6-9 are executed by tegra_se_is_operation_complete().
*/
if (tegra_se_is_ready()) {
/* Issue context save command */
tegra_se_write_32(AES0_OPERATION, SE_OP_CTX_SAVE);
/* Wait for operation to finish */
if (tegra_se_is_operation_complete()) {
ret = 0;
}
}
return ret;
}
/*
* 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_sha256_hash_operation_complete(void)
{
uint32_t val = 0U;
/* Poll the SE interrupt register to ensure H/W operation complete */
val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
while (SE0_INT_OP_DONE(val) == SE0_INT_OP_DONE_CLEAR) {
val = tegra_se_read_32(SE0_INT_STATUS_REG_OFFSET);
if (SE0_INT_OP_DONE(val) != SE0_INT_OP_DONE_CLEAR) {
break;
}
}
/* Poll the SE status idle to ensure H/W operation complete */
val = tegra_se_read_32(SE0_SHA_STATUS_0);
while (val != SE0_SHA_STATUS_IDLE) {
val = tegra_se_read_32(SE0_SHA_STATUS_0);
if (val == SE0_SHA_STATUS_IDLE) {
break;
}
}
/* Ensure that no errors are thrown during operation */
val = tegra_se_read_32(SE0_ERR_STATUS_REG_OFFSET);
if (val != 0U) {
ERROR("%s: error during SE operation! 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)
{
uint32_t val = 0U;
uint32_t src_in_lo;
uint32_t src_in_msb;
uint32_t src_in_hi;
int32_t ret = 0;
if ((src_addr == 0ULL) || (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 & MAX_SHA_ENGINE_CHUNK_SIZE));
/* 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, 0x0U);
}
/* 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);
}
return ret;
}
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 == 0ULL) {
return -EINVAL;
}
/* number of bytes per operation */
max_bytes = (SHA256_HASH_SIZE_BYTES * SHA256_MSG_LENGTH_ONETIME);
src_len_inbits = (uint32_t)(src_len_inbyte * 8U);
len_bits_msb = (uint32_t)(src_len_inbits >> 32U);
len_bits_lsb = (uint32_t)src_len_inbits;
/* program SE0_CONFIG for SHA256 operation */
val = (uint32_t)(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;
}
static int32_t tegra_se_save_sha256_pmc_scratch(void)
{
uint32_t val = 0U, hash_offset = 0U, scratch_offset = 0U;
int32_t ret;
/* Check SE0 operation status */
ret = tegra_se_sha256_hash_operation_complete();
if (ret != 0) {
ERROR("SE operation complete Failed! 0x%x", ret);
return ret;
}
for (scratch_offset = SECURE_SCRATCH_TZDRAM_SHA256_HASH_START;
scratch_offset <= SECURE_SCRATCH_TZDRAM_SHA256_HASH_END;
scratch_offset += BYTES_IN_WORD) {
val = tegra_se_read_32(SE0_SHA_HASH_RESULT_0 + hash_offset);
mmio_write_32((uint32_t)(TEGRA_SCRATCH_BASE + scratch_offset),
val);
hash_offset += BYTES_IN_WORD;
}
return 0;
}
/*
* Handler to generate SHA256 and save HASH-result to pmc-scratch register
*/
int32_t tegra_se_calculate_save_sha256(uint64_t src_addr,
uint32_t src_len_inbyte)
{
uint32_t security;
int32_t val = 0;
/* 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);
/* Bootrom enable IN_ID bit in SE0_SHA_GSCID_0 register during SC7-exit, causing
* SE0 ignores SE0 operation, and therefore failure of 2nd iteration of SC7 cycle.
*/
tegra_se_write_32(SE0_SHA_GSCID_0, 0x0U);
/* Calculate SHA256 of BL31 */
val = tegra_se_calculate_sha256_hash(src_addr, src_len_inbyte);
if (val != 0) {
ERROR("%s: SHA256 generation failed\n", __func__);
return val;
}
/*
* Reset SE_SECURE to previous value.
*/
tegra_se_write_32(SE0_SECURITY, security);
/* copy sha256_dst to PMC Scratch register */
val = tegra_se_save_sha256_pmc_scratch();
if (val != 0) {
ERROR("%s: SE0 status Error.\n", __func__);
}
return val;
}
/*
* Handler to power down the SE hardware blocks - SE, RNG1 and PKA1. This
* needs to be called only during System Suspend.
*/
int32_t tegra_se_suspend(void)
{
int32_t ret = 0;
/* initialise communication channel with BPMP */
assert(tegra_bpmp_ipc_init() == 0);
/* Enable SE clock before SE context save */
ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE);
assert(ret == 0);
/* save SE registers */
se_regs[0] = mmio_read_32(TEGRA_SE0_BASE + SE0_MUTEX_WATCHDOG_NS_LIMIT);
se_regs[1] = mmio_read_32(TEGRA_SE0_BASE + SE0_AES0_ENTROPY_SRC_AGE_CTRL);
se_regs[2] = mmio_read_32(TEGRA_RNG1_BASE + RNG1_MUTEX_WATCHDOG_NS_LIMIT);
se_regs[3] = mmio_read_32(TEGRA_PKA1_BASE + PKA1_MUTEX_WATCHDOG_NS_LIMIT);
/* Save SE context. The BootROM restores it during System Resume */
ret = tegra_se_save_context();
if (ret != 0) {
ERROR("%s: context save failed (%d)\n", __func__, ret);
}
/* Disable SE clock after SE context save */
ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE);
assert(ret == 0);
return ret;
}
/*
* Handler to power up the SE hardware block(s) during System Resume.
*/
void tegra_se_resume(void)
{
int32_t ret = 0;
/* initialise communication channel with BPMP */
assert(tegra_bpmp_ipc_init() == 0);
/* Enable SE clock before SE context restore */
ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE);
assert(ret == 0);
/*
* When TZ takes over after System Resume, TZ should first reconfigure
* SE_MUTEX_WATCHDOG_NS_LIMIT, PKA1_MUTEX_WATCHDOG_NS_LIMIT,
* RNG1_MUTEX_WATCHDOG_NS_LIMIT and SE_ENTROPY_SRC_AGE_CTRL before
* other operations.
*/
mmio_write_32(TEGRA_SE0_BASE + SE0_MUTEX_WATCHDOG_NS_LIMIT, se_regs[0]);
mmio_write_32(TEGRA_SE0_BASE + SE0_AES0_ENTROPY_SRC_AGE_CTRL, se_regs[1]);
mmio_write_32(TEGRA_RNG1_BASE + RNG1_MUTEX_WATCHDOG_NS_LIMIT, se_regs[2]);
mmio_write_32(TEGRA_PKA1_BASE + PKA1_MUTEX_WATCHDOG_NS_LIMIT, se_regs[3]);
/* Disable SE clock after SE context restore */
ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE);
assert(ret == 0);
}
@@ -0,0 +1,165 @@
/*
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-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>
#include <tegra_def.h>
/* SE0 security register */
#define SE0_SECURITY U(0x18)
#define SE0_SECURITY_SE_SOFT_SETTING (((uint32_t)1) << 16U)
/* SE0 SHA GSCID register */
#define SE0_SHA_GSCID_0 U(0x100)
/* SE0 config register */
#define SE0_SHA_CONFIG U(0x104)
#define SE0_SHA_TASK_CONFIG U(0x108)
#define SE0_SHA_CONFIG_HW_INIT_HASH (((uint32_t)1) << 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_IN_ADDR U(0x10c)
#define SE0_IN_HI_ADDR_HI U(0x110)
#define SE0_IN_HI_ADDR_HI_0_MSB_SHIFT U(24)
/* 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)0U) << SE0_INT_OP_DONE_SHIFT)
#define SE0_INT_OP_DONE(x) \
((x) & (((uint32_t)0x1U) << 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)
/* SE error status */
#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_START SECURE_SCRATCH_RSV68_LO
#define SECURE_SCRATCH_TZDRAM_SHA256_HASH_END SECURE_SCRATCH_RSV71_HI
/* SE0_INT_ENABLE_0 */
#define SE0_INT_ENABLE U(0x88)
#define SE0_DISABLE_ALL_INT U(0x0)
/* SE0_INT_STATUS_0 */
#define SE0_INT_STATUS U(0x8C)
#define SE0_CLEAR_ALL_INT_STATUS U(0x3F)
/* SE0_SHA_INT_STATUS_0 */
#define SHA_INT_STATUS U(0x184)
#define SHA_SE_OP_DONE (U(1) << 4)
/* SE0_SHA_ERR_STATUS_0 */
#define SHA_ERR_STATUS U(0x18C)
/* SE0_AES0_INT_STATUS_0 */
#define AES0_INT_STATUS U(0x2F0)
#define AES0_SE_OP_DONE (U(1) << 4)
/* SE0_AES0_ERR_STATUS_0 */
#define AES0_ERR_STATUS U(0x2F8)
/* SE0_AES1_INT_STATUS_0 */
#define AES1_INT_STATUS U(0x4F0)
/* SE0_AES1_ERR_STATUS_0 */
#define AES1_ERR_STATUS U(0x4F8)
/* SE0_RSA_INT_STATUS_0 */
#define RSA_INT_STATUS U(0x758)
/* SE0_RSA_ERR_STATUS_0 */
#define RSA_ERR_STATUS U(0x760)
/* SE0_AES0_OPERATION_0 */
#define AES0_OPERATION U(0x238)
#define OP_MASK_BITS U(0x7)
#define SE_OP_CTX_SAVE U(0x3)
/* SE0_AES0_CTX_SAVE_CONFIG_0 */
#define CTX_SAVE_CONFIG U(0x2D4)
/* SE0_AES0_CTX_SAVE_AUTO_STATUS_0 */
#define CTX_SAVE_AUTO_STATUS U(0x300)
#define CTX_SAVE_AUTO_SE_READY U(0xFF)
#define CTX_SAVE_AUTO_SE_BUSY (U(0x1) << 31)
/* SE0_AES0_CTX_SAVE_AUTO_CTRL_0 */
#define CTX_SAVE_AUTO_CTRL U(0x304)
#define SE_CTX_SAVE_AUTO_EN (U(0x1) << 0)
#define SE_CTX_SAVE_AUTO_LOCK_EN (U(0x1) << 1)
/* SE0_AES0_CTX_SAVE_AUTO_START_ADDR_0 */
#define CTX_SAVE_AUTO_START_ADDR U(0x308)
/* SE0_AES0_CTX_SAVE_AUTO_START_ADDR_HI_0 */
#define CTX_SAVE_AUTO_START_ADDR_HI U(0x30C)
/*******************************************************************************
* 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 */