Commit 82720675 authored by davidcunado-arm's avatar davidcunado-arm Committed by GitHub
Browse files

Merge pull request #884 from vwadekar/tegra186-platform-support-v3

Tegra186 platform support v3
parents ffe102ca c61cd638
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <smmu.h> #include <smmu.h>
#include <string.h> #include <string.h>
#include <tegra_def.h> #include <tegra_def.h>
#include <tegra_platform.h>
#include <xlat_tables.h> #include <xlat_tables.h>
#define TEGRA_GPU_RESET_REG_OFFSET 0x30 #define TEGRA_GPU_RESET_REG_OFFSET 0x30
...@@ -495,7 +496,6 @@ void tegra_memctrl_setup(void) ...@@ -495,7 +496,6 @@ void tegra_memctrl_setup(void)
uint32_t num_overrides = sizeof(streamid_overrides) / sizeof(uint32_t); uint32_t num_overrides = sizeof(streamid_overrides) / sizeof(uint32_t);
uint32_t num_sec_cfgs = sizeof(sec_cfgs) / sizeof(mc_streamid_security_cfg_t); uint32_t num_sec_cfgs = sizeof(sec_cfgs) / sizeof(mc_streamid_security_cfg_t);
uint32_t num_txn_overrides = sizeof(mc_override_cfgs) / sizeof(mc_txn_override_cfg_t); uint32_t num_txn_overrides = sizeof(mc_override_cfgs) / sizeof(mc_txn_override_cfg_t);
uint32_t chip_minor, chip_major;
int i; int i;
INFO("Tegra Memory Controller (v2)\n"); INFO("Tegra Memory Controller (v2)\n");
...@@ -543,12 +543,8 @@ void tegra_memctrl_setup(void) ...@@ -543,12 +543,8 @@ void tegra_memctrl_setup(void)
/* /*
* Set the MC_TXN_OVERRIDE registers for write clients. * Set the MC_TXN_OVERRIDE registers for write clients.
*/ */
chip_major = (mmio_read_32(TEGRA_MISC_BASE + HARDWARE_REVISION_OFFSET) >> if (!tegra_platform_is_silicon() ||
MAJOR_VERSION_SHIFT) & MAJOR_VERSION_MASK; (tegra_platform_is_silicon() && tegra_get_chipid_minor() == 1)) {
chip_minor = (mmio_read_32(TEGRA_MISC_BASE + HARDWARE_REVISION_OFFSET) >>
MINOR_VERSION_SHIFT) & MINOR_VERSION_MASK;
if ((chip_major == 0) || (chip_major > 0 && chip_minor == 1)) {
/* GPU and NVENC settings for rev. A01 */ /* GPU and NVENC settings for rev. A01 */
val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR); val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR);
...@@ -641,33 +637,55 @@ void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes) ...@@ -641,33 +637,55 @@ void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes)
*/ */
void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes) void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes)
{ {
uint64_t tzram_end = phys_base + size_in_bytes - 1; uint32_t index;
uint32_t total_128kb_blocks = size_in_bytes >> 17;
uint32_t residual_4kb_blocks = (size_in_bytes & 0x1FFFF) >> 12;
uint32_t val; uint32_t val;
/* /*
* Check if the TZRAM is locked already. * Reset the access configuration registers to restrict access
* to the TZRAM aperture
*/ */
if (tegra_mc_read_32(MC_TZRAM_REG_CTRL) == DISABLE_TZRAM_ACCESS) for (index = MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG0;
return; index <= MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS5;
index += 4)
tegra_mc_write_32(index, 0);
/* /*
* Setup the Memory controller to allow only secure accesses to * Allow CPU read/write access to the aperture
* the TZRAM carveout
*/ */
INFO("Configuring TrustZone RAM (SysRAM) Memory Carveout\n"); tegra_mc_write_32(MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG1,
TZRAM_CARVEOUT_CPU_WRITE_ACCESS_BIT |
TZRAM_CARVEOUT_CPU_READ_ACCESS_BIT);
/* Program the base and end values */ /*
tegra_mc_write_32(MC_TZRAM_BASE, (uint32_t)phys_base); * Set the TZRAM base. TZRAM base must be 4k aligned, at least.
tegra_mc_write_32(MC_TZRAM_END, (uint32_t)tzram_end); */
assert(!(phys_base & 0xFFF));
tegra_mc_write_32(MC_TZRAM_BASE_LO, (uint32_t)phys_base);
tegra_mc_write_32(MC_TZRAM_BASE_HI,
(uint32_t)(phys_base >> 32) & TZRAM_BASE_HI_MASK);
/* Extract the high address bits from the base/end values */ /*
val = (uint32_t)(phys_base >> 32) & TZRAM_ADDR_HI_BITS_MASK; * Set the TZRAM size
val |= (((uint32_t)(tzram_end >> 32) & TZRAM_ADDR_HI_BITS_MASK) << *
TZRAM_END_HI_BITS_SHIFT); * total size = (number of 128KB blocks) + (number of remaining 4KB
tegra_mc_write_32(MC_TZRAM_HI_ADDR_BITS, val); * blocks)
*
*/
val = (residual_4kb_blocks << TZRAM_SIZE_RANGE_4KB_SHIFT) |
total_128kb_blocks;
tegra_mc_write_32(MC_TZRAM_SIZE, val);
/* Disable further writes to the TZRAM setup registers */ /*
tegra_mc_write_32(MC_TZRAM_REG_CTRL, DISABLE_TZRAM_ACCESS); * Lock the configuration settings by disabling TZ-only lock
* and locking the configuration against any future changes
* at all.
*/
val = tegra_mc_read_32(MC_TZRAM_CARVEOUT_CFG);
val &= ~TZRAM_ENABLE_TZ_LOCK_BIT;
val |= TZRAM_LOCK_CFG_SETTINGS_BIT;
tegra_mc_write_32(MC_TZRAM_CARVEOUT_CFG, val);
/* /*
* MCE propogates the security configuration values across the * MCE propogates the security configuration values across the
......
...@@ -350,7 +350,7 @@ typedef struct mc_streamid_security_cfg { ...@@ -350,7 +350,7 @@ typedef struct mc_streamid_security_cfg {
.override_enable = OVERRIDE_ ## access \ .override_enable = OVERRIDE_ ## access \
} }
#endif /* __ASSMEBLY__ */ #endif /* __ASSEMBLY__ */
/******************************************************************************* /*******************************************************************************
* TZDRAM carveout configuration registers * TZDRAM carveout configuration registers
...@@ -367,15 +367,35 @@ typedef struct mc_streamid_security_cfg { ...@@ -367,15 +367,35 @@ typedef struct mc_streamid_security_cfg {
#define MC_VIDEO_PROTECT_SIZE_MB 0x64c #define MC_VIDEO_PROTECT_SIZE_MB 0x64c
/******************************************************************************* /*******************************************************************************
* TZRAM carveout configuration registers * TZRAM carveout (MC_SECURITY_CARVEOUT11) configuration registers
******************************************************************************/ ******************************************************************************/
#define MC_TZRAM_BASE 0x1850 #define MC_TZRAM_BASE_LO 0x2194
#define MC_TZRAM_END 0x1854 #define TZRAM_BASE_LO_SHIFT 12
#define MC_TZRAM_HI_ADDR_BITS 0x1588 #define TZRAM_BASE_LO_MASK 0xFFFFF
#define TZRAM_ADDR_HI_BITS_MASK 0x3 #define MC_TZRAM_BASE_HI 0x2198
#define TZRAM_END_HI_BITS_SHIFT 8 #define TZRAM_BASE_HI_SHIFT 0
#define MC_TZRAM_REG_CTRL 0x185c #define TZRAM_BASE_HI_MASK 3
#define DISABLE_TZRAM_ACCESS 1 #define MC_TZRAM_SIZE 0x219C
#define TZRAM_SIZE_RANGE_4KB_SHIFT 27
#define MC_TZRAM_CARVEOUT_CFG 0x2190
#define TZRAM_LOCK_CFG_SETTINGS_BIT (1 << 1)
#define TZRAM_ENABLE_TZ_LOCK_BIT (1 << 0)
#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG0 0x21A0
#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG1 0x21A4
#define TZRAM_CARVEOUT_CPU_WRITE_ACCESS_BIT (1 << 25)
#define TZRAM_CARVEOUT_CPU_READ_ACCESS_BIT (1 << 7)
#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG2 0x21A8
#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG3 0x21AC
#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG4 0x21B0
#define MC_TZRAM_CARVEOUT_CLIENT_ACCESS_CFG5 0x21B4
#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS0 0x21B8
#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS1 0x21BC
#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS2 0x21C0
#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS3 0x21C4
#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS4 0x21C8
#define MC_TZRAM_CARVEOUT_FORCE_INTERNAL_ACCESS5 0x21CC
/******************************************************************************* /*******************************************************************************
* Memory Controller Reset Control registers * Memory Controller Reset Control registers
......
...@@ -599,9 +599,16 @@ ...@@ -599,9 +599,16 @@
* SMMU Global Secure Aux. Configuration Register * SMMU Global Secure Aux. Configuration Register
******************************************************************************/ ******************************************************************************/
#define SMMU_GSR0_SECURE_ACR 0x10 #define SMMU_GSR0_SECURE_ACR 0x10
#define SMMU_GNSR_ACR (SMMU_GSR0_SECURE_ACR + 0x400)
#define SMMU_GSR0_PGSIZE_SHIFT 16 #define SMMU_GSR0_PGSIZE_SHIFT 16
#define SMMU_GSR0_PGSIZE_4K (0 << SMMU_GSR0_PGSIZE_SHIFT) #define SMMU_GSR0_PGSIZE_4K (0 << SMMU_GSR0_PGSIZE_SHIFT)
#define SMMU_GSR0_PGSIZE_64K (1 << SMMU_GSR0_PGSIZE_SHIFT) #define SMMU_GSR0_PGSIZE_64K (1 << SMMU_GSR0_PGSIZE_SHIFT)
#define SMMU_ACR_CACHE_LOCK_ENABLE_BIT (1 << 26)
/*******************************************************************************
* SMMU Global Aux. Control Register
******************************************************************************/
#define SMMU_CBn_ACTLR_CPRE_BIT (1 << 1)
/******************************************************************************* /*******************************************************************************
* SMMU configuration constants * SMMU configuration constants
......
...@@ -76,10 +76,6 @@ ...@@ -76,10 +76,6 @@
******************************************************************************/ ******************************************************************************/
#define TEGRA_MISC_BASE 0x00100000 #define TEGRA_MISC_BASE 0x00100000
#define HARDWARE_REVISION_OFFSET 0x4 #define HARDWARE_REVISION_OFFSET 0x4
#define MAJOR_VERSION_SHIFT 0x4
#define MAJOR_VERSION_MASK 0xF
#define MINOR_VERSION_SHIFT 0x10
#define MINOR_VERSION_MASK 0xF
#define MISCREG_PFCFG 0x200C #define MISCREG_PFCFG 0x200C
...@@ -105,6 +101,13 @@ ...@@ -105,6 +101,13 @@
#define TEGRA_UARTF_BASE 0x03150000 #define TEGRA_UARTF_BASE 0x03150000
#define TEGRA_UARTG_BASE 0x0C290000 #define TEGRA_UARTG_BASE 0x0C290000
/*******************************************************************************
* Tegra Fuse Controller related constants
******************************************************************************/
#define TEGRA_FUSE_BASE 0x03820000
#define OPT_SUBREVISION 0x248
#define SUBREVISION_MASK 0xFF
/******************************************************************************* /*******************************************************************************
* GICv2 & interrupt handling related constants * GICv2 & interrupt handling related constants
******************************************************************************/ ******************************************************************************/
...@@ -143,6 +146,8 @@ ...@@ -143,6 +146,8 @@
#define SECURE_SCRATCH_RSV6 0x680 #define SECURE_SCRATCH_RSV6 0x680
#define SECURE_SCRATCH_RSV11_LO 0x6A8 #define SECURE_SCRATCH_RSV11_LO 0x6A8
#define SECURE_SCRATCH_RSV11_HI 0x6AC #define SECURE_SCRATCH_RSV11_HI 0x6AC
#define SECURE_SCRATCH_RSV53_LO 0x7F8
#define SECURE_SCRATCH_RSV53_HI 0x7FC
/******************************************************************************* /*******************************************************************************
* Tegra Memory Mapped Control Register Access Bus constants * Tegra Memory Mapped Control Register Access Bus constants
...@@ -158,6 +163,6 @@ ...@@ -158,6 +163,6 @@
* Tegra TZRAM constants * Tegra TZRAM constants
******************************************************************************/ ******************************************************************************/
#define TEGRA_TZRAM_BASE 0x30000000 #define TEGRA_TZRAM_BASE 0x30000000
#define TEGRA_TZRAM_SIZE 0x50000 #define TEGRA_TZRAM_SIZE 0x40000
#endif /* __TEGRA_DEF_H__ */ #endif /* __TEGRA_DEF_H__ */
...@@ -95,12 +95,31 @@ typedef enum mce_cmd { ...@@ -95,12 +95,31 @@ typedef enum mce_cmd {
MCE_CMD_ROC_FLUSH_CACHE, MCE_CMD_ROC_FLUSH_CACHE,
MCE_CMD_ROC_CLEAN_CACHE, MCE_CMD_ROC_CLEAN_CACHE,
MCE_CMD_ENABLE_LATIC, MCE_CMD_ENABLE_LATIC,
MCE_CMD_UNCORE_PERFMON_REQ,
MCE_CMD_IS_CCX_ALLOWED = 0xFE, MCE_CMD_IS_CCX_ALLOWED = 0xFE,
MCE_CMD_MAX = 0xFF, MCE_CMD_MAX = 0xFF,
} mce_cmd_t; } mce_cmd_t;
#define MCE_CMD_MASK 0xFF #define MCE_CMD_MASK 0xFF
/*******************************************************************************
* Struct to prepare UPDATE_CSTATE_INFO request
******************************************************************************/
typedef struct mce_cstate_info {
/* cluster cstate value */
uint32_t cluster;
/* ccplex cstate value */
uint32_t ccplex;
/* system cstate value */
uint32_t system;
/* force system state? */
uint8_t system_state_force;
/* wake mask value */
uint32_t wake_mask;
/* update the wake mask? */
uint8_t update_wake_mask;
} mce_cstate_info_t;
/******************************************************************************* /*******************************************************************************
* Macros to prepare CSTATE info request * Macros to prepare CSTATE info request
******************************************************************************/ ******************************************************************************/
...@@ -183,6 +202,54 @@ typedef union mca_arg { ...@@ -183,6 +202,54 @@ typedef union mca_arg {
uint64_t data; uint64_t data;
} mca_arg_t; } mca_arg_t;
/*******************************************************************************
* Uncore PERFMON ARI struct
******************************************************************************/
typedef union uncore_perfmon_req {
struct perfmon_command {
/*
* Commands: 0 = READ, 1 = WRITE
*/
uint64_t cmd:8;
/*
* The unit group: L2=0, L3=1, ROC=2, MC=3, IOB=4
*/
uint64_t grp:4;
/*
* Unit selector: Selects the unit instance, with 0 = Unit
* = (number of units in group) - 1.
*/
uint64_t unit:4;
/*
* Selects the uncore perfmon register to access
*/
uint64_t reg:8;
/*
* Counter number. Selects which counter to use for
* registers NV_PMEVCNTR and NV_PMEVTYPER.
*/
uint64_t counter:8;
} perfmon_command;
struct perfmon_status {
/*
* Resulting command status
*/
uint64_t val:8;
uint64_t unused:24;
} perfmon_status;
uint64_t data;
} uncore_perfmon_req_t;
#define UNCORE_PERFMON_CMD_READ 0
#define UNCORE_PERFMON_CMD_WRITE 1
#define UNCORE_PERFMON_CMD_MASK 0xFF
#define UNCORE_PERFMON_UNIT_GRP_MASK 0xF
#define UNCORE_PERFMON_SELECTOR_MASK 0xF
#define UNCORE_PERFMON_REG_MASK 0xFF
#define UNCORE_PERFMON_CTR_MASK 0xFF
#define UNCORE_PERFMON_RESP_STATUS_MASK 0xFF
/******************************************************************************* /*******************************************************************************
* Structure populated by arch specific code to export routines which perform * Structure populated by arch specific code to export routines which perform
* common low level MCE functions * common low level MCE functions
...@@ -313,6 +380,12 @@ typedef struct arch_mce_ops { ...@@ -313,6 +380,12 @@ typedef struct arch_mce_ops {
* reset the entire system * reset the entire system
*/ */
void (*enter_ccplex_state)(uint32_t ari_base, uint32_t state_idx); void (*enter_ccplex_state)(uint32_t ari_base, uint32_t state_idx);
/*
* This ARI request reads/writes data from/to Uncore PERFMON
* registers
*/
int (*read_write_uncore_perfmon)(uint32_t ari_base,
uncore_perfmon_req_t req, uint64_t *data);
} arch_mce_ops_t; } arch_mce_ops_t;
int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1, int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1,
...@@ -322,6 +395,7 @@ int mce_update_gsc_videomem(void); ...@@ -322,6 +395,7 @@ int mce_update_gsc_videomem(void);
int mce_update_gsc_tzdram(void); int mce_update_gsc_tzdram(void);
int mce_update_gsc_tzram(void); int mce_update_gsc_tzram(void);
__dead2 void mce_enter_ccplex_state(uint32_t state_idx); __dead2 void mce_enter_ccplex_state(uint32_t state_idx);
void mce_update_cstate_info(mce_cstate_info_t *cstate);
void mce_verify_firmware_version(void); void mce_verify_firmware_version(void);
/* declarations for ARI/NVG handler functions */ /* declarations for ARI/NVG handler functions */
...@@ -344,6 +418,8 @@ int ari_roc_clean_cache(uint32_t ari_base); ...@@ -344,6 +418,8 @@ 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); 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); 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); void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx);
int ari_read_write_uncore_perfmon(uint32_t ari_base,
uncore_perfmon_req_t req, uint64_t *data);
int nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time); 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, int nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex,
......
...@@ -389,3 +389,41 @@ void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx) ...@@ -389,3 +389,41 @@ void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx)
*/ */
(void)ari_request_wait(ari_base, 0, TEGRA_ARI_MISC_CCPLEX, state_idx, 0); (void)ari_request_wait(ari_base, 0, TEGRA_ARI_MISC_CCPLEX, state_idx, 0);
} }
int ari_read_write_uncore_perfmon(uint32_t ari_base,
uncore_perfmon_req_t req, uint64_t *data)
{
int ret;
uint32_t val;
/* sanity check input parameters */
if (req.perfmon_command.cmd == UNCORE_PERFMON_CMD_READ && !data) {
ERROR("invalid parameters\n");
return EINVAL;
}
/*
* For "write" commands get the value that has to be written
* to the uncore perfmon registers
*/
val = (req.perfmon_command.cmd == UNCORE_PERFMON_CMD_WRITE) ?
*data : 0;
ret = ari_request_wait(ari_base, 0, TEGRA_ARI_PERFMON, val, req.data);
if (ret)
return ret;
/* read the command status value */
req.perfmon_status.val = ari_get_response_high(ari_base) &
UNCORE_PERFMON_RESP_STATUS_MASK;
/*
* For "read" commands get the data from the uncore
* perfmon registers
*/
if ((req.perfmon_status.val == 0) && (req.perfmon_command.cmd ==
UNCORE_PERFMON_CMD_READ))
*data = ari_get_response_low(ari_base);
return (int)req.perfmon_status.val;
}
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <sys/errno.h> #include <sys/errno.h>
#include <t18x_ari.h> #include <t18x_ari.h>
#include <tegra_def.h> #include <tegra_def.h>
#include <tegra_platform.h>
/* NVG functions handlers */ /* NVG functions handlers */
static arch_mce_ops_t nvg_mce_ops = { static arch_mce_ops_t nvg_mce_ops = {
...@@ -61,7 +62,8 @@ static arch_mce_ops_t nvg_mce_ops = { ...@@ -61,7 +62,8 @@ static arch_mce_ops_t nvg_mce_ops = {
.roc_clean_cache = ari_roc_clean_cache, .roc_clean_cache = ari_roc_clean_cache,
.read_write_mca = ari_read_write_mca, .read_write_mca = ari_read_write_mca,
.update_ccplex_gsc = ari_update_ccplex_gsc, .update_ccplex_gsc = ari_update_ccplex_gsc,
.enter_ccplex_state = ari_enter_ccplex_state .enter_ccplex_state = ari_enter_ccplex_state,
.read_write_uncore_perfmon = ari_read_write_uncore_perfmon
}; };
/* ARI functions handlers */ /* ARI functions handlers */
...@@ -82,7 +84,8 @@ static arch_mce_ops_t ari_mce_ops = { ...@@ -82,7 +84,8 @@ static arch_mce_ops_t ari_mce_ops = {
.roc_clean_cache = ari_roc_clean_cache, .roc_clean_cache = ari_roc_clean_cache,
.read_write_mca = ari_read_write_mca, .read_write_mca = ari_read_write_mca,
.update_ccplex_gsc = ari_update_ccplex_gsc, .update_ccplex_gsc = ari_update_ccplex_gsc,
.enter_ccplex_state = ari_enter_ccplex_state .enter_ccplex_state = ari_enter_ccplex_state,
.read_write_uncore_perfmon = ari_read_write_uncore_perfmon
}; };
typedef struct mce_config { typedef struct mce_config {
...@@ -173,6 +176,7 @@ int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1, ...@@ -173,6 +176,7 @@ int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1,
uint64_t ret64 = 0, arg3, arg4, arg5; uint64_t ret64 = 0, arg3, arg4, arg5;
int ret = 0; int ret = 0;
mca_cmd_t mca_cmd; mca_cmd_t mca_cmd;
uncore_perfmon_req_t req;
cpu_context_t *ctx = cm_get_context(NON_SECURE); cpu_context_t *ctx = cm_get_context(NON_SECURE);
gp_regs_t *gp_regs = get_gpregs_ctx(ctx); gp_regs_t *gp_regs = get_gpregs_ctx(ctx);
...@@ -374,6 +378,15 @@ int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1, ...@@ -374,6 +378,15 @@ int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1,
break; break;
#endif #endif
case MCE_CMD_UNCORE_PERFMON_REQ:
memcpy(&req, &arg0, sizeof(arg0));
ret = ops->read_write_uncore_perfmon(cpu_ari_base, req, &arg1);
/* update context to return data */
write_ctx_reg(gp_regs, CTX_GPREG_X1, arg1);
break;
default: default:
ERROR("unknown MCE command (%d)\n", cmd); ERROR("unknown MCE command (%d)\n", cmd);
return EINVAL; return EINVAL;
...@@ -448,6 +461,19 @@ __dead2 void mce_enter_ccplex_state(uint32_t state_idx) ...@@ -448,6 +461,19 @@ __dead2 void mce_enter_ccplex_state(uint32_t state_idx)
panic(); panic();
} }
/*******************************************************************************
* Handler to issue the UPDATE_CSTATE_INFO request
******************************************************************************/
void mce_update_cstate_info(mce_cstate_info_t *cstate)
{
arch_mce_ops_t *ops = mce_get_curr_cpu_ops();
/* issue the UPDATE_CSTATE_INFO request */
ops->update_cstate_info(mce_get_curr_cpu_ari_base(), cstate->cluster,
cstate->ccplex, cstate->system, cstate->system_state_force,
cstate->wake_mask, cstate->update_wake_mask);
}
/******************************************************************************* /*******************************************************************************
* Handler to read the MCE firmware version and check if it is compatible * Handler to read the MCE firmware version and check if it is compatible
* with interface header the BL3-1 was compiled against * with interface header the BL3-1 was compiled against
...@@ -457,7 +483,13 @@ void mce_verify_firmware_version(void) ...@@ -457,7 +483,13 @@ void mce_verify_firmware_version(void)
arch_mce_ops_t *ops; arch_mce_ops_t *ops;
uint32_t cpu_ari_base; uint32_t cpu_ari_base;
uint64_t version; uint64_t version;
uint32_t major, minor, chip_minor, chip_major; uint32_t major, minor;
/*
* MCE firmware is not running on simulation platforms.
*/
if (tegra_platform_is_emulation())
return;
/* get a pointer to the CPU's arch_mce_ops_t struct */ /* get a pointer to the CPU's arch_mce_ops_t struct */
ops = mce_get_curr_cpu_ops(); ops = mce_get_curr_cpu_ops();
...@@ -476,17 +508,6 @@ void mce_verify_firmware_version(void) ...@@ -476,17 +508,6 @@ void mce_verify_firmware_version(void)
INFO("MCE Version - HW=%d:%d, SW=%d:%d\n", major, minor, INFO("MCE Version - HW=%d:%d, SW=%d:%d\n", major, minor,
TEGRA_ARI_VERSION_MAJOR, TEGRA_ARI_VERSION_MINOR); TEGRA_ARI_VERSION_MAJOR, TEGRA_ARI_VERSION_MINOR);
/*
* MCE firmware is not running on simulation platforms. Simulation
* platforms are identified by v0.3 from the Tegra Chip ID value.
*/
chip_major = (mmio_read_32(TEGRA_MISC_BASE + HARDWARE_REVISION_OFFSET) >>
MAJOR_VERSION_SHIFT) & MAJOR_VERSION_MASK;
chip_minor = (mmio_read_32(TEGRA_MISC_BASE + HARDWARE_REVISION_OFFSET) >>
MINOR_VERSION_SHIFT) & MINOR_VERSION_MASK;
if ((chip_major == 0) && (chip_minor == 3))
return;
/* /*
* Verify that the MCE firmware version and the interface header * Verify that the MCE firmware version and the interface header
* match * match
......
...@@ -465,15 +465,42 @@ void tegra_smmu_save_context(uint64_t smmu_ctx_addr) ...@@ -465,15 +465,42 @@ void tegra_smmu_save_context(uint64_t smmu_ctx_addr)
(uint32_t)(smmu_ctx_addr >> 32)); (uint32_t)(smmu_ctx_addr >> 32));
} }
#define SMMU_NUM_CONTEXTS 64
#define SMMU_CONTEXT_BANK_MAX_IDX 64
/* /*
* Init SMMU during boot or "System Suspend" exit * Init SMMU during boot or "System Suspend" exit
*/ */
void tegra_smmu_init(void) void tegra_smmu_init(void)
{ {
uint32_t val; uint32_t val, i, ctx_base;
/* Program the SMMU pagesize */ /* Program the SMMU pagesize and reset CACHE_LOCK bit */
val = tegra_smmu_read_32(SMMU_GSR0_SECURE_ACR); val = tegra_smmu_read_32(SMMU_GSR0_SECURE_ACR);
val |= SMMU_GSR0_PGSIZE_64K; val |= SMMU_GSR0_PGSIZE_64K;
val &= ~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
tegra_smmu_write_32(SMMU_GSR0_SECURE_ACR, val);
/* reset CACHE LOCK bit for NS Aux. Config. Register */
val = tegra_smmu_read_32(SMMU_GNSR_ACR);
val &= ~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
tegra_smmu_write_32(SMMU_GNSR_ACR, val);
/* disable TCU prefetch for all contexts */
ctx_base = (SMMU_GSR0_PGSIZE_64K * SMMU_NUM_CONTEXTS) + SMMU_CBn_ACTLR;
for (i = 0; i < SMMU_CONTEXT_BANK_MAX_IDX; i++) {
val = tegra_smmu_read_32(ctx_base + (SMMU_GSR0_PGSIZE_64K * i));
val &= ~SMMU_CBn_ACTLR_CPRE_BIT;
tegra_smmu_write_32(ctx_base + (SMMU_GSR0_PGSIZE_64K * i), val);
}
/* set CACHE LOCK bit for NS Aux. Config. Register */
val = tegra_smmu_read_32(SMMU_GNSR_ACR);
val |= SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
tegra_smmu_write_32(SMMU_GNSR_ACR, val);
/* set CACHE LOCK bit for S Aux. Config. Register */
val = tegra_smmu_read_32(SMMU_GSR0_SECURE_ACR);
val |= SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
tegra_smmu_write_32(SMMU_GSR0_SECURE_ACR, val); tegra_smmu_write_32(SMMU_GSR0_SECURE_ACR, val);
} }
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <debug.h> #include <debug.h>
#include <denver.h> #include <denver.h>
#include <mce.h> #include <mce.h>
#include <platform.h>
#include <psci.h> #include <psci.h>
#include <smmu.h> #include <smmu.h>
#include <string.h> #include <string.h>
...@@ -71,12 +72,9 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state, ...@@ -71,12 +72,9 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state) psci_power_state_t *req_state)
{ {
int state_id = psci_get_pstate_id(power_state) & TEGRA186_STATE_ID_MASK; int state_id = psci_get_pstate_id(power_state) & TEGRA186_STATE_ID_MASK;
int cpu = read_mpidr() & MPIDR_CPU_MASK; int cpu = plat_my_core_pos();
int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
if (impl == DENVER_IMPL)
cpu |= 0x4;
/* save the core wake time (us) */
wake_time[cpu] = (power_state >> TEGRA186_WAKE_TIME_SHIFT) & wake_time[cpu] = (power_state >> TEGRA186_WAKE_TIME_SHIFT) &
TEGRA186_WAKE_TIME_MASK; TEGRA186_WAKE_TIME_MASK;
...@@ -84,10 +82,10 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state, ...@@ -84,10 +82,10 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state,
switch (state_id) { switch (state_id) {
case PSTATE_ID_CORE_IDLE: case PSTATE_ID_CORE_IDLE:
case PSTATE_ID_CORE_POWERDN: case PSTATE_ID_CORE_POWERDN:
/*
* Core powerdown request only for afflvl 0 /* Core powerdown request */
*/
req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id; req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id;
req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
break; break;
...@@ -103,20 +101,12 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) ...@@ -103,20 +101,12 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
{ {
const plat_local_state_t *pwr_domain_state; const plat_local_state_t *pwr_domain_state;
unsigned int stateid_afflvl0, stateid_afflvl2; unsigned int stateid_afflvl0, stateid_afflvl2;
int cpu = read_mpidr() & MPIDR_CPU_MASK; int cpu = plat_my_core_pos();
int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
cpu_context_t *ctx = cm_get_context(NON_SECURE);
gp_regs_t *gp_regs = get_gpregs_ctx(ctx);
plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
mce_cstate_info_t cstate_info = { 0 };
uint64_t smmu_ctx_base; uint64_t smmu_ctx_base;
uint32_t val; uint32_t val;
assert(ctx);
assert(gp_regs);
if (impl == DENVER_IMPL)
cpu |= 0x4;
/* get the state ID */ /* get the state ID */
pwr_domain_state = target_state->pwr_domain_state; pwr_domain_state = target_state->pwr_domain_state;
stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] & stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] &
...@@ -124,29 +114,14 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) ...@@ -124,29 +114,14 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] & stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
TEGRA186_STATE_ID_MASK; TEGRA186_STATE_ID_MASK;
if (stateid_afflvl0 == PSTATE_ID_CORE_IDLE) { if ((stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ||
(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN)) {
/* Program default wake mask */
write_ctx_reg(gp_regs, CTX_GPREG_X4, 0);
write_ctx_reg(gp_regs, CTX_GPREG_X5, TEGRA186_CORE_WAKE_MASK);
write_ctx_reg(gp_regs, CTX_GPREG_X6, 1);
(void)mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO, 0, 0, 0);
/* Prepare for cpu idle */
(void)mce_command_handler(MCE_CMD_ENTER_CSTATE,
TEGRA_ARI_CORE_C6, wake_time[cpu], 0);
} else if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) {
/* Program default wake mask */ /* Enter CPU idle/powerdown */
write_ctx_reg(gp_regs, CTX_GPREG_X4, 0); val = (stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ?
write_ctx_reg(gp_regs, CTX_GPREG_X5, TEGRA186_CORE_WAKE_MASK); TEGRA_ARI_CORE_C6 : TEGRA_ARI_CORE_C7;
write_ctx_reg(gp_regs, CTX_GPREG_X6, 1); (void)mce_command_handler(MCE_CMD_ENTER_CSTATE, val,
(void)mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO, 0, 0, 0); wake_time[cpu], 0);
/* Prepare for cpu powerdn */
(void)mce_command_handler(MCE_CMD_ENTER_CSTATE,
TEGRA_ARI_CORE_C7, wake_time[cpu], 0);
} else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { } else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
...@@ -170,11 +145,11 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) ...@@ -170,11 +145,11 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
tegra_smmu_save_context((uintptr_t)smmu_ctx_base); tegra_smmu_save_context((uintptr_t)smmu_ctx_base);
/* Prepare for system suspend */ /* Prepare for system suspend */
write_ctx_reg(gp_regs, CTX_GPREG_X4, 1); cstate_info.cluster = TEGRA_ARI_CLUSTER_CC7;
write_ctx_reg(gp_regs, CTX_GPREG_X5, 0); cstate_info.system = TEGRA_ARI_SYSTEM_SC7;
write_ctx_reg(gp_regs, CTX_GPREG_X6, 1); cstate_info.system_state_force = 1;
(void)mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO, cstate_info.update_wake_mask = 1;
TEGRA_ARI_CLUSTER_CC7, 0, TEGRA_ARI_SYSTEM_SC7); mce_update_cstate_info(&cstate_info);
/* Loop until system suspend is allowed */ /* Loop until system suspend is allowed */
do { do {
...@@ -187,13 +162,82 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) ...@@ -187,13 +162,82 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
/* Instruct the MCE to enter system suspend state */ /* Instruct the MCE to enter system suspend state */
(void)mce_command_handler(MCE_CMD_ENTER_CSTATE, (void)mce_command_handler(MCE_CMD_ENTER_CSTATE,
TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0); TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0);
}
return PSCI_E_SUCCESS;
}
/*******************************************************************************
* Platform handler to calculate the proper target power level at the
* specified affinity level
******************************************************************************/
plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
const plat_local_state_t *states,
unsigned int ncpu)
{
plat_local_state_t target = *states;
int cpu = plat_my_core_pos(), ret, cluster_powerdn = 1;
int core_pos = read_mpidr() & MPIDR_CPU_MASK;
mce_cstate_info_t cstate_info = { 0 };
/* get the current core's power state */
target = *(states + core_pos);
/* CPU suspend */
if (lvl == MPIDR_AFFLVL1 && target == PSTATE_ID_CORE_POWERDN) {
/* Program default wake mask */
cstate_info.wake_mask = TEGRA186_CORE_WAKE_MASK;
cstate_info.update_wake_mask = 1;
mce_update_cstate_info(&cstate_info);
/* Check if CCx state is allowed. */
ret = mce_command_handler(MCE_CMD_IS_CCX_ALLOWED,
TEGRA_ARI_CORE_C7, wake_time[cpu], 0);
if (ret)
return PSTATE_ID_CORE_POWERDN;
}
/* CPU off */
if (lvl == MPIDR_AFFLVL1 && target == PLAT_MAX_OFF_STATE) {
/* find out the number of ON cpus in the cluster */
do {
target = *states++;
if (target != PLAT_MAX_OFF_STATE)
cluster_powerdn = 0;
} while (--ncpu);
/* Enable cluster powerdn from last CPU in the cluster */
if (cluster_powerdn) {
/* Enable CC7 state and turn off wake mask */
cstate_info.cluster = TEGRA_ARI_CLUSTER_CC7;
cstate_info.update_wake_mask = 1;
mce_update_cstate_info(&cstate_info);
/* Check if CCx state is allowed. */
ret = mce_command_handler(MCE_CMD_IS_CCX_ALLOWED,
TEGRA_ARI_CORE_C7,
MCE_CORE_SLEEP_TIME_INFINITE,
0);
if (ret)
return PSTATE_ID_CORE_POWERDN;
} else { } else {
ERROR("%s: Unknown state id\n", __func__);
return PSCI_E_NOT_SUPPORTED; /* Turn off wake_mask */
cstate_info.update_wake_mask = 1;
mce_update_cstate_info(&cstate_info);
}
} }
return PSCI_E_SUCCESS; /* System Suspend */
if ((lvl == MPIDR_AFFLVL2) || (target == PSTATE_ID_SOC_POWERDN))
return PSTATE_ID_SOC_POWERDN;
/* default state */
return PSCI_LOCAL_STATE_RUN;
} }
int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
...@@ -244,8 +288,7 @@ int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) ...@@ -244,8 +288,7 @@ int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
{ {
int stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]; int stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL];
int stateid_afflvl0 = target_state->pwr_domain_state[MPIDR_AFFLVL0]; int stateid_afflvl0 = target_state->pwr_domain_state[MPIDR_AFFLVL0];
cpu_context_t *ctx = cm_get_context(NON_SECURE); mce_cstate_info_t cstate_info = { 0 };
gp_regs_t *gp_regs = get_gpregs_ctx(ctx);
/* /*
* Reset power state info for CPUs when onlining, we set * Reset power state info for CPUs when onlining, we set
...@@ -256,11 +299,9 @@ int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) ...@@ -256,11 +299,9 @@ int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
*/ */
if (stateid_afflvl0 == PLAT_MAX_OFF_STATE) { if (stateid_afflvl0 == PLAT_MAX_OFF_STATE) {
write_ctx_reg(gp_regs, CTX_GPREG_X4, 0); cstate_info.cluster = TEGRA_ARI_CLUSTER_CC1;
write_ctx_reg(gp_regs, CTX_GPREG_X5, 0); cstate_info.update_wake_mask = 1;
write_ctx_reg(gp_regs, CTX_GPREG_X6, 1); mce_update_cstate_info(&cstate_info);
mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO,
TEGRA_ARI_CLUSTER_CC1, 0, 0);
} }
/* /*
...@@ -280,15 +321,15 @@ int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) ...@@ -280,15 +321,15 @@ int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
tegra_smmu_init(); tegra_smmu_init();
/* /*
* Reset power state info for the last core doing SC7 entry and exit, * Reset power state info for the last core doing SC7
* we set deepest power state as CC7 and SC7 for SC7 entry which * entry and exit, we set deepest power state as CC7
* may not be requested by non-secure SW which controls idle states. * and SC7 for SC7 entry which may not be requested by
* non-secure SW which controls idle states.
*/ */
write_ctx_reg(gp_regs, CTX_GPREG_X4, 0); cstate_info.cluster = TEGRA_ARI_CLUSTER_CC7;
write_ctx_reg(gp_regs, CTX_GPREG_X5, 0); cstate_info.system = TEGRA_ARI_SYSTEM_SC1;
write_ctx_reg(gp_regs, CTX_GPREG_X6, 1); cstate_info.update_wake_mask = 1;
(void)mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO, mce_update_cstate_info(&cstate_info);
TEGRA_ARI_CLUSTER_CC7, 0, TEGRA_ARI_SYSTEM_SC1);
} }
return PSCI_E_SUCCESS; return PSCI_E_SUCCESS;
...@@ -296,33 +337,22 @@ int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) ...@@ -296,33 +337,22 @@ int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
{ {
cpu_context_t *ctx = cm_get_context(NON_SECURE);
gp_regs_t *gp_regs = get_gpregs_ctx(ctx);
int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
assert(ctx);
assert(gp_regs);
/* Turn off wake_mask */
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, 1);
mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO, TEGRA_ARI_CLUSTER_CC7,
0, 0);
/* Disable Denver's DCO operations */ /* Disable Denver's DCO operations */
if (impl == DENVER_IMPL) if (impl == DENVER_IMPL)
denver_disable_dco(); denver_disable_dco();
/* Turn off CPU */ /* Turn off CPU */
return mce_command_handler(MCE_CMD_ENTER_CSTATE, TEGRA_ARI_CORE_C7, (void)mce_command_handler(MCE_CMD_ENTER_CSTATE, TEGRA_ARI_CORE_C7,
MCE_CORE_SLEEP_TIME_INFINITE, 0); MCE_CORE_SLEEP_TIME_INFINITE, 0);
return PSCI_E_SUCCESS;
} }
__dead2 void tegra_soc_prepare_system_off(void) __dead2 void tegra_soc_prepare_system_off(void)
{ {
cpu_context_t *ctx = cm_get_context(NON_SECURE); mce_cstate_info_t cstate_info = { 0 };
gp_regs_t *gp_regs = get_gpregs_ctx(ctx);
uint32_t val; uint32_t val;
if (tegra186_system_powerdn_state == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) { if (tegra186_system_powerdn_state == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) {
...@@ -333,11 +363,11 @@ __dead2 void tegra_soc_prepare_system_off(void) ...@@ -333,11 +363,11 @@ __dead2 void tegra_soc_prepare_system_off(void)
} else if (tegra186_system_powerdn_state == TEGRA_ARI_SYSTEM_SC8) { } else if (tegra186_system_powerdn_state == TEGRA_ARI_SYSTEM_SC8) {
/* Prepare for quasi power down */ /* Prepare for quasi power down */
write_ctx_reg(gp_regs, CTX_GPREG_X4, 1); cstate_info.cluster = TEGRA_ARI_CLUSTER_CC7;
write_ctx_reg(gp_regs, CTX_GPREG_X5, 0); cstate_info.system = TEGRA_ARI_SYSTEM_SC8;
write_ctx_reg(gp_regs, CTX_GPREG_X6, 1); cstate_info.system_state_force = 1;
(void)mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO, cstate_info.update_wake_mask = 1;
TEGRA_ARI_CLUSTER_CC7, 0, TEGRA_ARI_SYSTEM_SC8); mce_update_cstate_info(&cstate_info);
/* loop until other CPUs power down */ /* loop until other CPUs power down */
do { do {
...@@ -357,6 +387,9 @@ __dead2 void tegra_soc_prepare_system_off(void) ...@@ -357,6 +387,9 @@ __dead2 void tegra_soc_prepare_system_off(void)
/* power down core */ /* power down core */
prepare_cpu_pwr_dwn(); prepare_cpu_pwr_dwn();
/* flush L1/L2 data caches */
dcsw_op_all(DCCISW);
} else { } else {
ERROR("%s: unsupported power down state (%d)\n", __func__, ERROR("%s: unsupported power down state (%d)\n", __func__,
tegra186_system_powerdn_state); tegra186_system_powerdn_state);
......
...@@ -30,19 +30,25 @@ ...@@ -30,19 +30,25 @@
#include <arch_helpers.h> #include <arch_helpers.h>
#include <assert.h> #include <assert.h>
#include <bl31.h>
#include <bl_common.h> #include <bl_common.h>
#include <console.h> #include <console.h>
#include <context.h> #include <context.h>
#include <context_mgmt.h> #include <context_mgmt.h>
#include <cortex_a57.h>
#include <debug.h> #include <debug.h>
#include <denver.h> #include <denver.h>
#include <interrupt_mgmt.h> #include <interrupt_mgmt.h>
#include <mce.h> #include <mce.h>
#include <platform.h> #include <platform.h>
#include <tegra_def.h> #include <tegra_def.h>
#include <tegra_platform.h>
#include <tegra_private.h> #include <tegra_private.h>
#include <xlat_tables.h> #include <xlat_tables.h>
DEFINE_RENAME_SYSREG_RW_FUNCS(l2ctlr_el1, L2CTLR_EL1)
extern uint64_t tegra_enable_l2_ecc_parity_prot;
/******************************************************************************* /*******************************************************************************
* The Tegra power domain tree has a single system level power domain i.e. a * The Tegra power domain tree has a single system level power domain i.e. a
* single root node. The first entry in the power domain descriptor specifies * single root node. The first entry in the power domain descriptor specifies
...@@ -72,7 +78,13 @@ static const mmap_region_t tegra_mmap[] = { ...@@ -72,7 +78,13 @@ static const mmap_region_t tegra_mmap[] = {
MT_DEVICE | MT_RW | MT_SECURE), MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(TEGRA_MC_BASE, 0x10000, /* 64KB */ MAP_REGION_FLAT(TEGRA_MC_BASE, 0x10000, /* 64KB */
MT_DEVICE | MT_RW | MT_SECURE), MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000, /* 128KB */ MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000, /* 128KB - UART A, B*/
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(TEGRA_UARTC_BASE, 0x20000, /* 128KB - UART C, G */
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(TEGRA_UARTD_BASE, 0x30000, /* 192KB - UART D, E, F */
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(TEGRA_FUSE_BASE, 0x10000, /* 64KB */
MT_DEVICE | MT_RW | MT_SECURE), MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000, /* 128KB */ MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000, /* 128KB */
MT_DEVICE | MT_RW | MT_SECURE), MT_DEVICE | MT_RW | MT_SECURE),
...@@ -142,6 +154,51 @@ uint32_t plat_get_console_from_id(int id) ...@@ -142,6 +154,51 @@ uint32_t plat_get_console_from_id(int id)
return tegra186_uart_addresses[id]; return tegra186_uart_addresses[id];
} }
/* represent chip-version as concatenation of major (15:12), minor (11:8) and subrev (7:0) */
#define TEGRA186_VER_A02P 0x1201
/*******************************************************************************
* Handler for early platform setup
******************************************************************************/
void plat_early_platform_setup(void)
{
int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
uint32_t chip_subrev, val;
/* sanity check MCE firmware compatibility */
mce_verify_firmware_version();
/*
* Enable ECC and Parity Protection for Cortex-A57 CPUs
* for Tegra A02p SKUs
*/
if (impl != DENVER_IMPL) {
/* get the major, minor and sub-version values */
chip_subrev = mmio_read_32(TEGRA_FUSE_BASE + OPT_SUBREVISION) &
SUBREVISION_MASK;
/* prepare chip version number */
val = (tegra_get_chipid_major() << 12) |
(tegra_get_chipid_minor() << 8) |
chip_subrev;
/* enable L2 ECC for Tegra186 A02P and beyond */
if (val >= TEGRA186_VER_A02P) {
val = read_l2ctlr_el1();
val |= L2_ECC_PARITY_PROTECTION_BIT;
write_l2ctlr_el1(val);
/*
* Set the flag to enable ECC/Parity Protection
* when we exit System Suspend or Cluster Powerdn
*/
tegra_enable_l2_ecc_parity_prot = 1;
}
}
}
/* Secure IRQs for Tegra186 */ /* Secure IRQs for Tegra186 */
static const irq_sec_cfg_t tegra186_sec_irqs[] = { static const irq_sec_cfg_t tegra186_sec_irqs[] = {
{ {
...@@ -173,9 +230,25 @@ void plat_gic_setup(void) ...@@ -173,9 +230,25 @@ void plat_gic_setup(void)
} }
/******************************************************************************* /*******************************************************************************
* Handler for early platform setup * Return pointer to the BL31 params from previous bootloader
******************************************************************************/ ******************************************************************************/
void plat_early_platform_setup(void) bl31_params_t *plat_get_bl31_params(void)
{ {
mce_verify_firmware_version(); uint32_t val;
val = mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV53_LO);
return (bl31_params_t *)(uintptr_t)val;
}
/*******************************************************************************
* Return pointer to the BL31 platform params from previous bootloader
******************************************************************************/
plat_params_from_bl2_t *plat_get_bl31_plat_params(void)
{
uint32_t val;
val = mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV53_HI);
return (plat_params_from_bl2_t *)(uintptr_t)val;
} }
...@@ -65,6 +65,7 @@ extern uint32_t tegra186_system_powerdn_state; ...@@ -65,6 +65,7 @@ extern uint32_t tegra186_system_powerdn_state;
#define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE 0x82FFFF0E #define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE 0x82FFFF0E
#define TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE 0x82FFFF0F #define TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE 0x82FFFF0F
#define TEGRA_SIP_MCE_CMD_ENABLE_LATIC 0x82FFFF10 #define TEGRA_SIP_MCE_CMD_ENABLE_LATIC 0x82FFFF10
#define TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ 0x82FFFF11
/******************************************************************************* /*******************************************************************************
* This function is responsible for handling all T186 SiP calls * This function is responsible for handling all T186 SiP calls
...@@ -102,6 +103,7 @@ int plat_sip_handler(uint32_t smc_fid, ...@@ -102,6 +103,7 @@ int plat_sip_handler(uint32_t smc_fid,
case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE: case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE:
case TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE: case TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE:
case TEGRA_SIP_MCE_CMD_ENABLE_LATIC: case TEGRA_SIP_MCE_CMD_ENABLE_LATIC:
case TEGRA_SIP_MCE_CMD_UNCORE_PERFMON_REQ:
/* clean up the high bits */ /* clean up the high bits */
smc_fid &= MCE_CMD_MASK; smc_fid &= MCE_CMD_MASK;
...@@ -112,32 +114,6 @@ int plat_sip_handler(uint32_t smc_fid, ...@@ -112,32 +114,6 @@ int plat_sip_handler(uint32_t smc_fid,
return 0; return 0;
case TEGRA_SIP_NEW_VIDEOMEM_REGION:
/* clean up the high bits */
x1 = (uint32_t)x1;
x2 = (uint32_t)x2;
/*
* Check if Video Memory overlaps TZDRAM (contains bl31/bl32)
* or falls outside of the valid DRAM range
*/
mce_ret = bl31_check_ns_address(x1, x2);
if (mce_ret)
return -ENOTSUP;
/*
* Check if Video Memory is aligned to 1MB.
*/
if ((x1 & 0xFFFFF) || (x2 & 0xFFFFF)) {
ERROR("Unaligned Video Memory base address!\n");
return -ENOTSUP;
}
/* new video memory carveout settings */
tegra_memctrl_videomem_setup(x1, x2);
return 0;
case TEGRA_SIP_SYSTEM_SHUTDOWN_STATE: case TEGRA_SIP_SYSTEM_SHUTDOWN_STATE:
/* clean up the high bits */ /* clean up the high bits */
......
...@@ -32,9 +32,18 @@ ...@@ -32,9 +32,18 @@
ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS := 1 ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS := 1
$(eval $(call add_define,ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS)) $(eval $(call add_define,ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS))
RELOCATE_TO_BL31_BASE := 1
$(eval $(call add_define,RELOCATE_TO_BL31_BASE))
ENABLE_CHIP_VERIFICATION_HARNESS := 0 ENABLE_CHIP_VERIFICATION_HARNESS := 0
$(eval $(call add_define,ENABLE_CHIP_VERIFICATION_HARNESS)) $(eval $(call add_define,ENABLE_CHIP_VERIFICATION_HARNESS))
RESET_TO_BL31 := 1
PROGRAMMABLE_RESET_ADDRESS := 1
COLD_BOOT_SINGLE_CPU := 1
# platform settings # platform settings
TZDRAM_BASE := 0x30000000 TZDRAM_BASE := 0x30000000
$(eval $(call add_define,TZDRAM_BASE)) $(eval $(call add_define,TZDRAM_BASE))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment