diff --git a/plat/nvidia/tegra/soc/t186/drivers/include/mce.h b/plat/nvidia/tegra/soc/t186/drivers/include/mce.h new file mode 100644 index 000000000..7078b8bb2 --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/include/mce.h @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MCE_H__ +#define __MCE_H__ + +#include +#include + +/******************************************************************************* + * MCE apertures used by the ARI interface + * + * Aperture 0 - Cpu0 (ARM Cortex A-57) + * Aperture 1 - Cpu1 (ARM Cortex A-57) + * Aperture 2 - Cpu2 (ARM Cortex A-57) + * Aperture 3 - Cpu3 (ARM Cortex A-57) + * Aperture 4 - Cpu4 (Denver15) + * Aperture 5 - Cpu5 (Denver15) + ******************************************************************************/ +#define MCE_ARI_APERTURE_0_OFFSET 0x0 +#define MCE_ARI_APERTURE_1_OFFSET 0x10000 +#define MCE_ARI_APERTURE_2_OFFSET 0x20000 +#define MCE_ARI_APERTURE_3_OFFSET 0x30000 +#define MCE_ARI_APERTURE_4_OFFSET 0x40000 +#define MCE_ARI_APERTURE_5_OFFSET 0x50000 +#define MCE_ARI_APERTURE_OFFSET_MAX MCE_APERTURE_5_OFFSET + +/* number of apertures */ +#define MCE_ARI_APERTURES_MAX 6 + +/* each ARI aperture is 64KB */ +#define MCE_ARI_APERTURE_SIZE 0x10000 + +/******************************************************************************* + * CPU core ids - used by the MCE_ONLINE_CORE ARI + ******************************************************************************/ +typedef enum mce_core_id { + MCE_CORE_ID_DENVER_15_0, + MCE_CORE_ID_DENVER_15_1, + /* 2 and 3 are reserved */ + MCE_CORE_ID_A57_0 = 4, + MCE_CORE_ID_A57_1, + MCE_CORE_ID_A57_2, + MCE_CORE_ID_A57_3, + MCE_CORE_ID_MAX +} mce_core_id_t; + +#define MCE_CORE_ID_MASK 0x7 + +/******************************************************************************* + * MCE commands + ******************************************************************************/ +typedef enum mce_cmd { + MCE_CMD_ENTER_CSTATE = 0, + MCE_CMD_UPDATE_CSTATE_INFO, + MCE_CMD_UPDATE_CROSSOVER_TIME, + MCE_CMD_READ_CSTATE_STATS, + MCE_CMD_WRITE_CSTATE_STATS, + MCE_CMD_IS_SC7_ALLOWED, + MCE_CMD_ONLINE_CORE, + MCE_CMD_CC3_CTRL, + MCE_CMD_ECHO_DATA, + MCE_CMD_READ_VERSIONS, + MCE_CMD_ENUM_FEATURES, + MCE_CMD_ROC_FLUSH_CACHE_TRBITS, + MCE_CMD_ENUM_READ_MCA, + MCE_CMD_ENUM_WRITE_MCA, + MCE_CMD_ROC_FLUSH_CACHE, + MCE_CMD_ROC_CLEAN_CACHE, + MCE_CMD_IS_CCX_ALLOWED = 0xFE, + MCE_CMD_MAX = 0xFF, +} mce_cmd_t; + +#define MCE_CMD_MASK 0xFF + +/******************************************************************************* + * Macros to prepare CSTATE info request + ******************************************************************************/ +/* Description of the parameters for UPDATE_CSTATE_INFO request */ +#define CLUSTER_CSTATE_MASK 0x7 +#define CLUSTER_CSTATE_SHIFT 0 +#define CLUSTER_CSTATE_UPDATE_BIT (1 << 7) +#define CCPLEX_CSTATE_MASK 0x3 +#define CCPLEX_CSTATE_SHIFT 8 +#define CCPLEX_CSTATE_UPDATE_BIT (1 << 15) +#define SYSTEM_CSTATE_MASK 0xF +#define SYSTEM_CSTATE_SHIFT 16 +#define SYSTEM_CSTATE_FORCE_UPDATE_SHIFT 22 +#define SYSTEM_CSTATE_FORCE_UPDATE_BIT (1 << 22) +#define SYSTEM_CSTATE_UPDATE_BIT (1 << 23) +#define CSTATE_WAKE_MASK_UPDATE_BIT (1 << 31) +#define CSTATE_WAKE_MASK_SHIFT 32 +#define CSTATE_WAKE_MASK_CLEAR 0xFFFFFFFF + +/******************************************************************************* + * Auto-CC3 control macros + ******************************************************************************/ +#define MCE_AUTO_CC3_FREQ_MASK 0x1FF +#define MCE_AUTO_CC3_FREQ_SHIFT 0 +#define MCE_AUTO_CC3_VTG_MASK 0x7F +#define MCE_AUTO_CC3_VTG_SHIFT 16 +#define MCE_AUTO_CC3_ENABLE_BIT (1 << 31) + +/******************************************************************************* + * Macros for the 'IS_SC7_ALLOWED' command + ******************************************************************************/ +#define MCE_SC7_ALLOWED_MASK 0x7 +#define MCE_SC7_WAKE_TIME_SHIFT 32 + +/******************************************************************************* + * Macros for 'read/write ctats' commands + ******************************************************************************/ +#define MCE_CSTATE_STATS_TYPE_SHIFT 32 +#define MCE_CSTATE_WRITE_DATA_LO_MASK 0xF + +/******************************************************************************* + * Macros for 'update crossover threshold' command + ******************************************************************************/ +#define MCE_CROSSOVER_THRESHOLD_TIME_SHIFT 32 + +/******************************************************************************* + * Timeout value used to powerdown a core + ******************************************************************************/ +#define MCE_CORE_SLEEP_TIME_INFINITE 0xFFFFFFFF + +/******************************************************************************* + * MCA command struct + ******************************************************************************/ +typedef union mca_cmd { + struct command { + uint8_t cmd; + uint8_t idx; + uint8_t subidx; + } command; + struct input { + uint32_t low; + uint32_t high; + } input; + uint64_t data; +} mca_cmd_t; + +/******************************************************************************* + * MCA argument struct + ******************************************************************************/ +typedef union mca_arg { + struct err { + uint64_t error:8; + uint64_t unused:48; + uint64_t finish:8; + } err; + struct arg { + uint32_t low; + uint32_t high; + } arg; + uint64_t data; +} mca_arg_t; + +/******************************************************************************* + * 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. + */ + int (*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. + */ + int (*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. + */ + int (*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. + */ + int (*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 + */ + int (*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 + */ + int (*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. + */ + int (*online_core)(uint32_t ari_base, uint32_t cpuid); + /* + * This ARI request allows the CPU to enable/disable Auto-CC3 idle + * state. + */ + int (*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. + */ + int (*update_reset_vector)(uint32_t ari_base, + uint32_t addr_low, + uint32_t addr_high); + /* + * This ARI request instructs the ROC to flush A57 data caches in + * order to maintain coherency with the Denver cluster. + */ + int (*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. + */ + int (*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. + */ + int (*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, + mca_cmd_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. + */ + int (*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); +} arch_mce_ops_t; + +int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1, + uint64_t arg2); +int mce_update_reset_vector(uint32_t addr_lo, uint32_t addr_hi); +int mce_update_gsc_videomem(void); +int mce_update_gsc_tzdram(void); +int mce_update_gsc_tzram(void); +__dead2 void mce_enter_ccplex_state(uint32_t state_idx); + +/* declarations for ARI/NVG handler functions */ +int ari_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int 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); +int 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); +int 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); +int ari_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int ari_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int ari_online_core(uint32_t ari_base, uint32_t core); +int ari_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable); +int ari_reset_vector_update(uint32_t ari_base, uint32_t lo, uint32_t hi); +int ari_roc_flush_cache_trbits(uint32_t ari_base); +int ari_roc_flush_cache(uint32_t ari_base); +int ari_roc_clean_cache(uint32_t ari_base); +uint64_t ari_read_write_mca(uint32_t ari_base, mca_cmd_t cmd, uint64_t *data); +int 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); + +int nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int 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); +int 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); +int nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t val); +int nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int nvg_online_core(uint32_t ari_base, uint32_t core); +int nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable); + +#endif /* __MCE_H__ */ diff --git a/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h b/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h new file mode 100644 index 000000000..3e6054bd0 --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef T18X_TEGRA_ARI_H +#define T18X_TEGRA_ARI_H + +/* + * ---------------------------------------------------------------------------- + * t18x_ari.h + * + * Global ARI definitions. + * ---------------------------------------------------------------------------- + */ + +enum { + TEGRA_ARI_VERSION_MAJOR = 2, + TEGRA_ARI_VERSION_MINOR = 19, +}; + +typedef enum { + /* indexes below get the core lock */ + TEGRA_ARI_MISC = 0, + /* index 1 is deprecated */ + /* index 2 is deprecated */ + /* index 3 is deprecated */ + TEGRA_ARI_ONLINE_CORE = 4, + + /* indexes below need cluster lock */ + TEGRA_ARI_MISC_CLUSTER = 41, + TEGRA_ARI_IS_CCX_ALLOWED = 42, + TEGRA_ARI_CC3_CTRL = 43, + + /* indexes below need ccplex lock */ + TEGRA_ARI_ENTER_CSTATE = 80, + TEGRA_ARI_UPDATE_CSTATE_INFO = 81, + TEGRA_ARI_IS_SC7_ALLOWED = 82, + /* index 83 is deprecated */ + TEGRA_ARI_PERFMON = 84, + TEGRA_ARI_UPDATE_CCPLEX_GSC = 85, + /* index 86 is depracated */ + /* index 87 is deprecated */ + TEGRA_ARI_ROC_FLUSH_CACHE_ONLY = 88, + TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS = 89, + TEGRA_ARI_MISC_CCPLEX = 90, + TEGRA_ARI_MCA = 91, + TEGRA_ARI_UPDATE_CROSSOVER = 92, + TEGRA_ARI_CSTATE_STATS = 93, + TEGRA_ARI_WRITE_CSTATE_STATS = 94, + TEGRA_ARI_COPY_MISCREG_AA64_RST = 95, + TEGRA_ARI_ROC_CLEAN_CACHE_ONLY = 96, +} tegra_ari_req_id_t; + +typedef enum { + TEGRA_ARI_MISC_ECHO = 0, + TEGRA_ARI_MISC_VERSION = 1, + TEGRA_ARI_MISC_FEATURE_LEAF_0 = 2, +} tegra_ari_misc_index_t; + +typedef enum { + TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF = 0, + TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT = 1, + TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL = 2, +} tegra_ari_misc_ccplex_index_t; + +typedef enum { + TEGRA_ARI_CORE_C0 = 0, + TEGRA_ARI_CORE_C1 = 1, + TEGRA_ARI_CORE_C6 = 6, + TEGRA_ARI_CORE_C7 = 7, + TEGRA_ARI_CORE_WARMRSTREQ = 8, +} tegra_ari_core_sleep_state_t; + +typedef enum { + TEGRA_ARI_CLUSTER_CC0 = 0, + TEGRA_ARI_CLUSTER_CC1 = 1, + TEGRA_ARI_CLUSTER_CC6 = 6, + TEGRA_ARI_CLUSTER_CC7 = 7, +} tegra_ari_cluster_sleep_state_t; + +typedef enum { + TEGRA_ARI_CCPLEX_CCP0 = 0, + TEGRA_ARI_CCPLEX_CCP1 = 1, + TEGRA_ARI_CCPLEX_CCP3 = 3, +} tegra_ari_ccplex_sleep_state_t; + +typedef enum { + TEGRA_ARI_SYSTEM_SC0 = 0, + TEGRA_ARI_SYSTEM_SC1 = 1, + TEGRA_ARI_SYSTEM_SC2 = 2, + TEGRA_ARI_SYSTEM_SC3 = 3, + TEGRA_ARI_SYSTEM_SC4 = 4, + TEGRA_ARI_SYSTEM_SC7 = 7, + TEGRA_ARI_SYSTEM_SC8 = 8, +} tegra_ari_system_sleep_state_t; + +typedef enum { + TEGRA_ARI_CROSSOVER_C1_C6 = 0, + TEGRA_ARI_CROSSOVER_CC1_CC6 = 1, + TEGRA_ARI_CROSSOVER_CC1_CC7 = 2, + TEGRA_ARI_CROSSOVER_CCP1_CCP3 = 3, + TEGRA_ARI_CROSSOVER_CCP3_SC2 = 4, + TEGRA_ARI_CROSSOVER_CCP3_SC3 = 5, + TEGRA_ARI_CROSSOVER_CCP3_SC4 = 6, + TEGRA_ARI_CROSSOVER_CCP3_SC7 = 7, + TEGRA_ARI_CROSSOVER_CCP3_SC1 = 8, +} tegra_ari_crossover_index_t; + +typedef enum { + TEGRA_ARI_CSTATE_STATS_CLEAR = 0, + TEGRA_ARI_CSTATE_STATS_SC7_ENTRIES = 1, + TEGRA_ARI_CSTATE_STATS_SC4_ENTRIES, + TEGRA_ARI_CSTATE_STATS_SC3_ENTRIES, + TEGRA_ARI_CSTATE_STATS_SC2_ENTRIES, + TEGRA_ARI_CSTATE_STATS_CCP3_ENTRIES, + 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 = 14, + TEGRA_ARI_CSTATE_STATS_D15_1_C7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_A57_0_C7_ENTRIES = 18, + 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 = 26, + 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 = 0, + + TEGRA_ARI_GSC_BPMP = 6, + TEGRA_ARI_GSC_APE = 7, + TEGRA_ARI_GSC_SPE = 8, + TEGRA_ARI_GSC_SCE = 9, + TEGRA_ARI_GSC_APR = 10, + TEGRA_ARI_GSC_TZRAM = 11, + TEGRA_ARI_GSC_SE = 12, + + TEGRA_ARI_GSC_BPMP_TO_SPE = 16, + TEGRA_ARI_GSC_SPE_TO_BPMP = 17, + TEGRA_ARI_GSC_CPU_TZ_TO_BPMP = 18, + TEGRA_ARI_GSC_BPMP_TO_CPU_TZ = 19, + TEGRA_ARI_GSC_CPU_NS_TO_BPMP = 20, + TEGRA_ARI_GSC_BPMP_TO_CPU_NS = 21, + TEGRA_ARI_GSC_IPC_SE_SPE_SCE_BPMP = 22, + TEGRA_ARI_GSC_SC7_RESUME_FW = 23, + + TEGRA_ARI_GSC_TZ_DRAM_IDX = 34, + TEGRA_ARI_GSC_VPR_IDX = 35, +} 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, 0, 2), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CLUSTER_CSTATE_PRESENT, 7, 7), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CCPLEX_CSTATE, 8, 9), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CCPLEX_CSTATE_PRESENT, 15, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__SYSTEM_CSTATE, 16, 19), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__IGNORE_CROSSOVERS, 22, 22), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__SYSTEM_CSTATE_PRESENT, 23, 23), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__WAKE_MASK_PRESENT, 31, 31), +} tegra_ari_update_cstate_info_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL__EN, 0, 0), +} tegra_ari_misc_ccplex_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__IDLE_FREQ, 0, 8), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__IDLE_VOLT, 16, 23), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__ENABLE, 31, 31), +} tegra_ari_cc3_ctrl_bitmasks_t; + +typedef enum { + TEGRA_ARI_MCA_NOP = 0, + TEGRA_ARI_MCA_READ_SERR = 1, + TEGRA_ARI_MCA_WRITE_SERR = 2, + TEGRA_ARI_MCA_CLEAR_SERR = 4, + TEGRA_ARI_MCA_REPORT_SERR = 5, + TEGRA_ARI_MCA_READ_INTSTS = 6, + TEGRA_ARI_MCA_WRITE_INTSTS = 7, + TEGRA_ARI_MCA_READ_PREBOOT_SERR = 8, +} tegra_ari_mca_commands_t; + +typedef enum { + TEGRA_ARI_MCA_RD_WR_DPMU = 0, + TEGRA_ARI_MCA_RD_WR_IOB = 1, + TEGRA_ARI_MCA_RD_WR_MCB = 2, + TEGRA_ARI_MCA_RD_WR_CCE = 3, + TEGRA_ARI_MCA_RD_WR_CQX = 4, + TEGRA_ARI_MCA_RD_WR_CTU = 5, + TEGRA_ARI_MCA_RD_BANK_INFO = 0x0f, + TEGRA_ARI_MCA_RD_BANK_TEMPLATE = 0x10, + TEGRA_ARI_MCA_RD_WR_SECURE_ACCESS_REGISTER = 0x11, + TEGRA_ARI_MCA_RD_WR_GLOBAL_CONFIG_REGISTER = 0x12, +} tegra_ari_mca_rd_wr_indexes_t; + +typedef enum { + TEGRA_ARI_MCA_RD_WR_ASERRX_CTRL = 0, + TEGRA_ARI_MCA_RD_WR_ASERRX_STATUS = 1, + TEGRA_ARI_MCA_RD_WR_ASERRX_ADDR = 2, + TEGRA_ARI_MCA_RD_WR_ASERRX_MISC1 = 3, + TEGRA_ARI_MCA_RD_WR_ASERRX_MISC2 = 4, +} tegra_ari_mca_read_asserx_subindexes_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_SETTING_ENABLES_NS_PERMITTED, 0, 0), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_READING_STATUS_NS_PERMITTED, 1, 1), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_PENDING_MCA_ERRORS_NS_PERMITTED, 2, 2), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_CLEARING_MCA_INTERRUPTS_NS_PERMITTED, 3, 3), +} tegra_ari_mca_secure_register_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_SERR_ERR_CODE, 0, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_PWM_ERR, 16, 16), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_CRAB_ERR, 17, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_RD_WR_N, 18, 18), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_UCODE_ERR, 19, 19), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_PWM, 20, 23), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_AV, 58, 58), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_MV, 59, 59), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_EN, 60, 60), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_UC, 61, 61), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_OVF, 62, 62), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_VAL, 63, 63), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_ADDR_ADDR, 0, 41), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_ADDR_UCODE_ERRCD, 42, 52), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_PWM_ERR, 0, 0), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_CRAB_ERR, 1, 1), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_UCODE_ERR, 3, 3), +} tegra_ari_mca_aserr0_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_SERR_ERR_CODE, 0, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MSI_ERR, 16, 16), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_IHI_ERR, 17, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CRI_ERR, 18, 18), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MMCRAB_ERR, 19, 19), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CSI_ERR, 20, 20), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_RD_WR_N, 21, 21), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_REQ_ERRT, 22, 23), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_RESP_ERRT, 24, 25), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_AV, 58, 58), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MV, 59, 59), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_EN, 60, 60), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_UC, 61, 61), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_OVF, 62, 62), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_VAL, 63, 63), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_AXI_ID, 0, 7), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_ID, 8, 27), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_CID, 28, 31), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_CMD, 32, 35), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_MSI_ERR, 0, 0), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_IHI_ERR, 1, 1), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_CRI_ERR, 2, 2), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_MMCRAB_ERR, 3, 3), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_CSI_ERR, 4, 4), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_MISC_ADDR, 0, 41), +} tegra_ari_mca_aserr1_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_SERR_ERR_CODE, 0, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_MC_ERR, 16, 16), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_SYSRAM_ERR, 17, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_CLIENT_ID, 18, 19), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_AV, 58, 58), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_MV, 59, 59), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_EN, 60, 60), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_UC, 61, 61), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_OVF, 62, 62), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_VAL, 63, 63), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_ID, 0, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_CMD, 18, 21), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_ADDR, 22, 53), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_CTRL_EN_MC_ERR, 0, 0), +} tegra_ari_mca_aserr2_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_SERR_ERR_CODE, 0, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_TO_ERR, 16, 16), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_STAT_ERR, 17, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_DST_ERR, 18, 18), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_UNC_ERR, 19, 19), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_MH_ERR, 20, 20), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_PERR, 21, 21), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_PSN_ERR, 22, 22), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_AV, 58, 58), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_MV, 59, 59), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_EN, 60, 60), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_UC, 61, 61), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_OVF, 62, 62), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_VAL, 63, 63), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_ADDR_CMD, 0, 5), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_ADDR_ADDR, 6, 47), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_TO, 0, 0), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_DIV4, 1, 1), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_TLIMIT, 2, 11), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_PSN_ERR_CORR_MSK, 12, 25), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_MORE_INFO, 0, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_TO_INFO, 18, 43), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_SRC, 44, 45), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_TID, 46, 52), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_TO_ERR, 0, 0), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_STAT_ERR, 1, 1), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_DST_ERR, 2, 2), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_UNC_ERR, 3, 3), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_MH_ERR, 4, 4), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_PERR, 5, 5), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_PSN_ERR, 6, 19), +} tegra_ari_mca_aserr3_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_SERR_ERR_CODE, 0, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_SRC_ERR, 16, 16), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_DST_ERR, 17, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_REQ_ERR, 18, 18), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_RSP_ERR, 19, 19), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_AV, 58, 58), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_MV, 59, 59), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_EN, 60, 60), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_UC, 61, 61), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_OVF, 62, 62), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_VAL, 63, 63), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_CTRL_EN_CPE_ERR, 0, 0), +} tegra_ari_mca_aserr4_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_SERR_ERR_CODE, 0, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_CTUPAR, 16, 16), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_MULTI, 17, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_AV, 58, 58), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_MV, 59, 59), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_EN, 60, 60), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_UC, 61, 61), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_OVF, 62, 62), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_VAL, 63, 63), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_SRC, 0, 7), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_ID, 8, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_DATA, 16, 26), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_CMD, 32, 35), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_ADDR, 36, 45), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_CTRL_EN_CTUPAR, 0, 0), +} tegra_ari_mca_aserr5_bitmasks_t; + +#undef TEGRA_ARI_ENUM_MASK_LSB_MSB + +typedef enum { + TEGRA_NVG_CHANNEL_PMIC = 0, + TEGRA_NVG_CHANNEL_POWER_PERF = 1, + TEGRA_NVG_CHANNEL_POWER_MODES = 2, + TEGRA_NVG_CHANNEL_WAKE_TIME = 3, + TEGRA_NVG_CHANNEL_CSTATE_INFO = 4, + TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 = 5, + TEGRA_NVG_CHANNEL_CROSSOVER_CC1_CC6 = 6, + TEGRA_NVG_CHANNEL_CROSSOVER_CC1_CC7 = 7, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP1_CCP3 = 8, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC2 = 9, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC3 = 10, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC4 = 11, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC7 = 12, + TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR = 13, + TEGRA_NVG_CHANNEL_CSTATE_STATS_SC7_ENTRIES = 14, + TEGRA_NVG_CHANNEL_CSTATE_STATS_SC4_ENTRIES = 15, + TEGRA_NVG_CHANNEL_CSTATE_STATS_SC3_ENTRIES = 16, + TEGRA_NVG_CHANNEL_CSTATE_STATS_SC2_ENTRIES = 17, + TEGRA_NVG_CHANNEL_CSTATE_STATS_CCP3_ENTRIES = 18, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_CC6_ENTRIES = 19, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_CC7_ENTRIES = 20, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_CC6_ENTRIES = 21, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_CC7_ENTRIES = 22, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_0_C6_ENTRIES = 23, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_1_C6_ENTRIES = 24, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_2_C6_ENTRIES = 25, /* Reserved (for Denver15 core 2) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_3_C6_ENTRIES = 26, /* Reserved (for Denver15 core 3) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_0_C7_ENTRIES = 27, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_1_C7_ENTRIES = 28, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_2_C7_ENTRIES = 29, /* Reserved (for Denver15 core 2) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_3_C7_ENTRIES = 30, /* Reserved (for Denver15 core 3) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_0_C7_ENTRIES = 31, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_1_C7_ENTRIES = 32, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_2_C7_ENTRIES = 33, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_3_C7_ENTRIES = 34, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_0 = 35, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_1 = 36, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_2 = 37, /* Reserved (for Denver15 core 2) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_3 = 38, /* Reserved (for Denver15 core 3) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_0 = 39, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_1 = 40, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_2 = 41, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_3 = 42, + TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED = 43, + TEGRA_NVG_CHANNEL_ONLINE_CORE = 44, + TEGRA_NVG_CHANNEL_CC3_CTRL = 45, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC1 = 46, + TEGRA_NVG_CHANNEL_LAST_INDEX, +} tegra_nvg_channel_id_t; + +#endif /* T18X_TEGRA_ARI_H */ + + diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S b/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S new file mode 100644 index 000000000..e1398ccee --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + + .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 + isb + 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 diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c b/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c new file mode 100644 index 000000000..147a358ae --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Register offsets for ARI request/results + ******************************************************************************/ +#define ARI_REQUEST 0x0 +#define ARI_REQUEST_EVENT_MASK 0x4 +#define ARI_STATUS 0x8 +#define ARI_REQUEST_DATA_LO 0xC +#define ARI_REQUEST_DATA_HI 0x10 +#define ARI_RESPONSE_DATA_LO 0x14 +#define ARI_RESPONSE_DATA_HI 0x18 + +/* Status values for the current request */ +#define ARI_REQ_PENDING 1 +#define ARI_REQ_ONGOING 3 +#define ARI_REQUEST_VALID_BIT (1 << 8) +#define ARI_EVT_MASK_STANDBYWFI_BIT (1 << 7) + +/******************************************************************************* + * ARI helper functions + ******************************************************************************/ +static inline uint32_t ari_read_32(uint32_t ari_base, uint32_t reg) +{ + return mmio_read_32(ari_base + reg); +} + +static inline void ari_write_32(uint32_t ari_base, uint32_t val, uint32_t reg) +{ + mmio_write_32(ari_base + 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 int ari_request_wait(uint32_t ari_base, uint32_t evt_mask, uint32_t req, + uint32_t lo, uint32_t hi) +{ + int status; + + /* 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) + return 0; + + /* NOTE: add timeout check if needed */ + status = ari_read_32(ari_base, ARI_STATUS); + while (status & (ARI_REQ_ONGOING | ARI_REQ_PENDING)) + status = ari_read_32(ari_base, ARI_STATUS); + + return 0; +} + +int ari_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + /* 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); + return EINVAL; + } + + /* Enter the cstate, to be woken up after wake_time (TSC ticks) */ + return ari_request_wait(ari_base, ARI_EVT_MASK_STANDBYWFI_BIT, + TEGRA_ARI_ENTER_CSTATE, state, wake_time); +} + +int 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) +{ + uint32_t val = 0; + + /* update CLUSTER_CSTATE? */ + if (cluster) + val |= (cluster & CLUSTER_CSTATE_MASK) | + CLUSTER_CSTATE_UPDATE_BIT; + + /* update CCPLEX_CSTATE? */ + if (ccplex) + val |= (ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT | + CCPLEX_CSTATE_UPDATE_BIT; + + /* update SYSTEM_CSTATE? */ + if (system) + val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | + ((sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) | + SYSTEM_CSTATE_UPDATE_BIT); + + /* update wake mask value? */ + if (update_wake_mask) + val |= CSTATE_WAKE_MASK_UPDATE_BIT; + + /* set the updated cstate info */ + return ari_request_wait(ari_base, 0, TEGRA_ARI_UPDATE_CSTATE_INFO, val, + wake_mask); +} + +int ari_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time) +{ + /* sanity check crossover type */ + if ((type == TEGRA_ARI_CROSSOVER_C1_C6) || + (type > TEGRA_ARI_CROSSOVER_CCP3_SC1)) + return EINVAL; + + /* update crossover threshold time */ + return ari_request_wait(ari_base, 0, TEGRA_ARI_UPDATE_CROSSOVER, + type, time); +} + +uint64_t ari_read_cstate_stats(uint32_t ari_base, uint32_t state) +{ + int ret; + + /* sanity check crossover type */ + if (state == 0) + return EINVAL; + + ret = ari_request_wait(ari_base, 0, TEGRA_ARI_CSTATE_STATS, state, 0); + if (ret != 0) + return EINVAL; + + return (uint64_t)ari_get_response_low(ari_base); +} + +int ari_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats) +{ + /* write the cstate stats */ + return ari_request_wait(ari_base, 0, 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; + int ret; + + /* 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) + data = 0; + + ret = ari_request_wait(ari_base, 0, TEGRA_ARI_MISC, cmd, data); + if (ret) + return (uint64_t)ret; + + /* get the command response */ + resp = ari_get_response_low(ari_base); + resp |= ((uint64_t)ari_get_response_high(ari_base) << 32); + + return resp; +} + +int ari_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + int ret; + + ret = ari_request_wait(ari_base, 0, TEGRA_ARI_IS_CCX_ALLOWED, state & 0x7, + wake_time); + if (ret) { + ERROR("%s: failed (%d)\n", __func__, ret); + return 0; + } + + /* 1 = CCx allowed, 0 = CCx not allowed */ + return (ari_get_response_low(ari_base) & 0x1); +} + +int ari_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + int ret; + + /* 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); + return EINVAL; + } + + ret = ari_request_wait(ari_base, 0, TEGRA_ARI_IS_SC7_ALLOWED, state, + wake_time); + if (ret) { + ERROR("%s: failed (%d)\n", __func__, ret); + return 0; + } + + /* 1 = SC7 allowed, 0 = SC7 not allowed */ + return !!ari_get_response_low(ari_base); +} + +int ari_online_core(uint32_t ari_base, uint32_t core) +{ + int cpu = read_mpidr() & MPIDR_CPU_MASK; + int cluster = (read_mpidr() & MPIDR_CLUSTER_MASK) >> + MPIDR_AFFINITY_BITS; + int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + + /* construct the current CPU # */ + cpu |= (cluster << 2); + + /* sanity check target core id */ + if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) { + ERROR("%s: unsupported core id (%d)\n", __func__, core); + return EINVAL; + } + + /* + * The Denver cluster has 2 CPUs only - 0, 1. + */ + if (impl == DENVER_IMPL && ((core == 2) || (core == 3))) { + ERROR("%s: unknown core id (%d)\n", __func__, core); + return EINVAL; + } + + return ari_request_wait(ari_base, 0, TEGRA_ARI_ONLINE_CORE, core, 0); +} + +int ari_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable) +{ + int val; + + /* + * 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 ? MCE_AUTO_CC3_ENABLE_BIT : 0)); + + return ari_request_wait(ari_base, 0, TEGRA_ARI_CC3_CTRL, val, 0); +} + +int ari_reset_vector_update(uint32_t ari_base, uint32_t lo, uint32_t hi) +{ + /* + * Need to program the CPU reset vector one time during cold boot + * and SC7 exit + */ + ari_request_wait(ari_base, 0, TEGRA_ARI_COPY_MISCREG_AA64_RST, lo, hi); + + return 0; +} + +int ari_roc_flush_cache_trbits(uint32_t ari_base) +{ + return ari_request_wait(ari_base, 0, TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS, + 0, 0); +} + +int ari_roc_flush_cache(uint32_t ari_base) +{ + return ari_request_wait(ari_base, 0, TEGRA_ARI_ROC_FLUSH_CACHE_ONLY, + 0, 0); +} + +int ari_roc_clean_cache(uint32_t ari_base) +{ + return ari_request_wait(ari_base, 0, TEGRA_ARI_ROC_CLEAN_CACHE_ONLY, + 0, 0); +} + +uint64_t ari_read_write_mca(uint32_t ari_base, mca_cmd_t cmd, uint64_t *data) +{ + mca_arg_t mca_arg; + int ret; + + /* Set data (write) */ + mca_arg.data = data ? *data : 0ull; + + /* Set command */ + ari_write_32(ari_base, cmd.input.low, ARI_RESPONSE_DATA_LO); + ari_write_32(ari_base, cmd.input.high, ARI_RESPONSE_DATA_HI); + + ret = ari_request_wait(ari_base, 0, TEGRA_ARI_MCA, mca_arg.arg.low, + mca_arg.arg.high); + if (!ret) { + mca_arg.arg.low = ari_get_response_low(ari_base); + mca_arg.arg.high = ari_get_response_high(ari_base); + if (!mca_arg.err.finish) + return (uint64_t)mca_arg.err.error; + + if (data) { + mca_arg.arg.low = ari_get_request_low(ari_base); + mca_arg.arg.high = ari_get_request_high(ari_base); + *data = mca_arg.data; + } + } + + return 0; +} + +int ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx) +{ + /* sanity check GSC ID */ + if (gsc_idx > TEGRA_ARI_GSC_VPR_IDX) + return EINVAL; + + /* + * 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. + */ + ari_request_wait(ari_base, 0, TEGRA_ARI_UPDATE_CCPLEX_GSC, gsc_idx, 0); + + return 0; +} + +void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx) +{ + /* + * The MCE will shutdown or restart the entire system + */ + (void)ari_request_wait(ari_base, 0, TEGRA_ARI_MISC_CCPLEX, state_idx, 0); +} diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c new file mode 100644 index 000000000..981510708 --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 +}; + +/* 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 +}; + +typedef struct mce_config { + 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) +{ + uint32_t mpidr = read_mpidr(); + int cpuid = mpidr & MPIDR_CPU_MASK; + int 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 |= 0x4; + + return mce_cfg_table[cpuid].ari_base; +} + +static arch_mce_ops_t *mce_get_curr_cpu_ops(void) +{ + uint32_t mpidr = read_mpidr(); + int cpuid = mpidr & MPIDR_CPU_MASK; + int 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 |= 0x4; + + return mce_cfg_table[cpuid].ops; +} + +/******************************************************************************* + * Common handler for all MCE commands + ******************************************************************************/ +int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1, + uint64_t arg2) +{ + arch_mce_ops_t *ops; + uint32_t cpu_ari_base; + uint64_t ret64 = 0, arg3, arg4, arg5; + int ret = 0; + mca_cmd_t mca_cmd; + cpu_context_t *ctx = cm_get_context(NON_SECURE); + gp_regs_t *gp_regs = get_gpregs_ctx(ctx); + + assert(ctx); + assert(gp_regs); + + /* 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 MCE_CMD_ENTER_CSTATE: + ret = ops->enter_cstate(cpu_ari_base, arg0, arg1); + if (ret < 0) + ERROR("%s: enter_cstate failed(%d)\n", __func__, ret); + + break; + + case 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); + if (ret < 0) + ERROR("%s: update_cstate_info failed(%d)\n", + __func__, ret); + + write_ctx_reg(gp_regs, CTX_GPREG_X4, 0); + write_ctx_reg(gp_regs, CTX_GPREG_X5, 0); + write_ctx_reg(gp_regs, CTX_GPREG_X6, 0); + + break; + + case MCE_CMD_UPDATE_CROSSOVER_TIME: + ret = ops->update_crossover_time(cpu_ari_base, arg0, arg1); + if (ret < 0) + ERROR("%s: update_crossover_time failed(%d)\n", + __func__, ret); + + break; + + case 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 MCE_CMD_WRITE_CSTATE_STATS: + ret = ops->write_cstate_stats(cpu_ari_base, arg0, arg1); + if (ret < 0) + ERROR("%s: write_cstate_stats failed(%d)\n", + __func__, ret); + + break; + + case MCE_CMD_IS_CCX_ALLOWED: + ret = ops->is_ccx_allowed(cpu_ari_base, arg0, arg1); + if (ret < 0) { + ERROR("%s: is_ccx_allowed failed(%d)\n", __func__, ret); + break; + } + + /* update context to return CCx status value */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, ret); + + break; + + case MCE_CMD_IS_SC7_ALLOWED: + ret = ops->is_sc7_allowed(cpu_ari_base, arg0, arg1); + if (ret < 0) { + ERROR("%s: is_sc7_allowed failed(%d)\n", __func__, ret); + break; + } + + /* update context to return SC7 status value */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, ret); + write_ctx_reg(gp_regs, CTX_GPREG_X3, ret); + ret = 0; + + break; + + case MCE_CMD_ONLINE_CORE: + ret = ops->online_core(cpu_ari_base, arg0); + if (ret < 0) + ERROR("%s: online_core failed(%d)\n", __func__, ret); + + break; + + case MCE_CMD_CC3_CTRL: + ret = ops->cc3_ctrl(cpu_ari_base, arg0, arg1, arg2); + if (ret < 0) + ERROR("%s: cc3_ctrl failed(%d)\n", __func__, ret); + + break; + + case 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); + write_ctx_reg(gp_regs, CTX_GPREG_X2, ret64 == arg0); + + break; + + case 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, (uint32_t)ret64); + write_ctx_reg(gp_regs, CTX_GPREG_X2, (uint32_t)(ret64 >> 32)); + + break; + + case MCE_CMD_ENUM_FEATURES: + ret = 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); + + ret = 0; + + break; + + case MCE_CMD_ROC_FLUSH_CACHE_TRBITS: + ret = ops->roc_flush_cache_trbits(cpu_ari_base); + if (ret < 0) + ERROR("%s: flush cache_trbits failed(%d)\n", __func__, + ret); + + break; + + case MCE_CMD_ROC_FLUSH_CACHE: + ret = ops->roc_flush_cache(cpu_ari_base); + if (ret < 0) + ERROR("%s: flush cache failed(%d)\n", __func__, ret); + + break; + + case MCE_CMD_ROC_CLEAN_CACHE: + ret = ops->roc_clean_cache(cpu_ari_base); + if (ret < 0) + ERROR("%s: clean cache failed(%d)\n", __func__, ret); + + break; + + case MCE_CMD_ENUM_READ_MCA: + memcpy(&mca_cmd, &arg0, sizeof(arg0)); + ret64 = ops->read_write_mca(cpu_ari_base, mca_cmd, &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 MCE_CMD_ENUM_WRITE_MCA: + memcpy(&mca_cmd, &arg0, sizeof(arg0)); + ret64 = ops->read_write_mca(cpu_ari_base, mca_cmd, &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; + + default: + ERROR("unknown MCE command (%d)\n", cmd); + return EINVAL; + } + + return ret; +} + +/******************************************************************************* + * Handler to update the reset vector for CPUs + ******************************************************************************/ +int mce_update_reset_vector(uint32_t addr_lo, uint32_t addr_hi) +{ + arch_mce_ops_t *ops = mce_get_curr_cpu_ops(); + + ops->update_reset_vector(mce_get_curr_cpu_ari_base(), addr_lo, addr_hi); + + return 0; +} + +static int mce_update_ccplex_gsc(tegra_ari_gsc_index_t gsc_idx) +{ + 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 + ******************************************************************************/ +int mce_update_gsc_videomem(void) +{ + return mce_update_ccplex_gsc(TEGRA_ARI_GSC_VPR_IDX); +} + +/******************************************************************************* + * Handler to update carveout values for TZDRAM aperture + ******************************************************************************/ +int mce_update_gsc_tzdram(void) +{ + return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZ_DRAM_IDX); +} + +/******************************************************************************* + * Handler to update carveout values for TZ SysRAM aperture + ******************************************************************************/ +int mce_update_gsc_tzram(void) +{ + return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZRAM); +} + +/******************************************************************************* + * Handler to shutdown/reset the entire system + ******************************************************************************/ +__dead2 void mce_enter_ccplex_state(uint32_t state_idx) +{ + 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 (;;) + ; + + panic(); +} diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c b/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c new file mode 100644 index 000000000..25479a24b --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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); + +int nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + /* 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); + return EINVAL; + } + + /* time (TSC ticks) until the core is expected to get a wake event */ + nvg_set_request_data(TEGRA_NVG_CHANNEL_WAKE_TIME, wake_time); + + /* set the core cstate */ + write_actlr_el1(state); + + return 0; +} + +/* + * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and + * SYSTEM_CSTATE values. + */ +int 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 = 0; + + /* update CLUSTER_CSTATE? */ + if (cluster) + val |= (cluster & CLUSTER_CSTATE_MASK) | + CLUSTER_CSTATE_UPDATE_BIT; + + /* update CCPLEX_CSTATE? */ + if (ccplex) + val |= (ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT | + CCPLEX_CSTATE_UPDATE_BIT; + + /* update SYSTEM_CSTATE? */ + if (system) + val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | + ((sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) | + SYSTEM_CSTATE_UPDATE_BIT); + + /* update wake mask value? */ + if (update_wake_mask) + 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(TEGRA_NVG_CHANNEL_CSTATE_INFO, val); + + return 0; +} + +int nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time) +{ + /* sanity check crossover type */ + if (type > TEGRA_ARI_CROSSOVER_CCP3_SC1) + return EINVAL; + + /* + * 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 can 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 + type, + (uint64_t)time); + + return 0; +} + +uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state) +{ + /* sanity check state */ + if (state == 0) + return EINVAL; + + /* + * 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 + state); + + return (int64_t)nvg_get_result(); +} + +int nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats) +{ + uint64_t val; + + /* + * 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 + state, val); + + return 0; +} + +int nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + /* This does not apply to the Denver cluster */ + return 0; +} + +int nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + uint64_t val; + + /* 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); + return EINVAL; + } + + /* + * Request format - + * 63:32 = wake time + * 31:0 = C-state for this core + */ + val = ((uint64_t)wake_time << MCE_SC7_WAKE_TIME_SHIFT) | + (state & MCE_SC7_ALLOWED_MASK); + + /* issue command to check if SC7 is allowed */ + nvg_set_request_data(TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED, val); + + /* 1 = SC7 allowed, 0 = SC7 not allowed */ + return !!nvg_get_result(); +} + +int nvg_online_core(uint32_t ari_base, uint32_t core) +{ + int cpu = read_mpidr() & MPIDR_CPU_MASK; + int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + + /* sanity check code id */ + if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) { + ERROR("%s: unsupported core id (%d)\n", __func__, core); + return EINVAL; + } + + /* + * The Denver cluster has 2 CPUs only - 0, 1. + */ + if (impl == DENVER_IMPL && ((core == 2) || (core == 3))) { + ERROR("%s: unknown core id (%d)\n", __func__, core); + return EINVAL; + } + + /* get a core online */ + nvg_set_request_data(TEGRA_NVG_CHANNEL_ONLINE_CORE, core & MCE_CORE_ID_MASK); + + return 0; +} + +int nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable) +{ + int val; + + /* + * 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 ? MCE_AUTO_CC3_ENABLE_BIT : 0)); + + nvg_set_request_data(TEGRA_NVG_CHANNEL_CC3_CTRL, val); + + return 0; +} diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk index 374b6e617..e29282a39 100644 --- a/plat/nvidia/tegra/soc/t186/platform_t186.mk +++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk @@ -54,6 +54,10 @@ PLAT_INCLUDES += -I${SOC_DIR}/drivers/include BL31_SOURCES += lib/cpus/aarch64/denver.S \ lib/cpus/aarch64/cortex_a57.S \ ${COMMON_DIR}/drivers/memctrl/memctrl_v2.c \ + ${SOC_DIR}/drivers/mce/mce.c \ + ${SOC_DIR}/drivers/mce/ari.c \ + ${SOC_DIR}/drivers/mce/nvg.c \ + ${SOC_DIR}/drivers/mce/aarch64/nvg_helpers.S \ ${SOC_DIR}/plat_psci_handlers.c \ ${SOC_DIR}/plat_setup.c \ ${SOC_DIR}/plat_secondary.c \