Commit 41554fb2 authored by Harvey Hsieh's avatar Harvey Hsieh Committed by Varun Wadekar
Browse files

Tegra210: SE: add context save support



Tegra210B01 SoCs support atomic context save for the two SE
hardware engines. Tegra210 SoCs have support for only one SE
engine and support a software based save/restore mechanism
instead.

This patch updates the SE driver to make this change.

Change-Id: Ia5e5ed75d0fe011f17809684bbc2ed2338925946
Signed-off-by: default avatarHarvey Hsieh <hhsieh@nvidia.com>
parent 24902fae
...@@ -144,6 +144,9 @@ ...@@ -144,6 +144,9 @@
#define SE_CLK_ENB_BIT (U(1) << 31) #define SE_CLK_ENB_BIT (U(1) << 31)
#define TEGRA_CLK_OUT_ENB_W U(0x364) #define TEGRA_CLK_OUT_ENB_W U(0x364)
#define ENTROPY_RESET_BIT (U(1) << 21) #define ENTROPY_RESET_BIT (U(1) << 21)
#define TEGRA_CLK_RST_CTL_CLK_SRC_SE U(0x42C)
#define SE_CLK_SRC_MASK (U(7) << 29)
#define SE_CLK_SRC_CLK_M (U(6) << 29)
#define TEGRA_RST_DEV_SET_V U(0x430) #define TEGRA_RST_DEV_SET_V U(0x430)
#define SE_RESET_BIT (U(1) << 31) #define SE_RESET_BIT (U(1) << 31)
#define HDA_RESET_BIT (U(1) << 29) #define HDA_RESET_BIT (U(1) << 29)
......
/* /*
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
* PMC registers * PMC registers
*/ */
/* SC7 context save scratch register for T210 */
#define PMC_SCRATCH43_REG_OFFSET U(0x22C)
/* Secure scratch registers */ /* Secure scratch registers */
#define PMC_SECURE_SCRATCH4_OFFSET 0xC0U #define PMC_SECURE_SCRATCH4_OFFSET 0xC0U
#define PMC_SECURE_SCRATCH5_OFFSET 0xC4U #define PMC_SECURE_SCRATCH5_OFFSET 0xC4U
...@@ -435,6 +438,7 @@ ...@@ -435,6 +438,7 @@
((x) & ((0x1U) << SE_TZRAM_OP_REQ_SHIFT)) ((x) & ((0x1U) << SE_TZRAM_OP_REQ_SHIFT))
/* SE Interrupt */ /* SE Interrupt */
#define SE_INT_ENABLE_REG_OFFSET U(0xC)
#define SE_INT_STATUS_REG_OFFSET 0x10U #define SE_INT_STATUS_REG_OFFSET 0x10U
#define SE_INT_OP_DONE_SHIFT 4 #define SE_INT_OP_DONE_SHIFT 4
#define SE_INT_OP_DONE_CLEAR \ #define SE_INT_OP_DONE_CLEAR \
......
/* /*
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
* Constants and Macros * Constants and Macros
******************************************************************************/ ******************************************************************************/
#define TIMEOUT_100MS 100U // Timeout in 100ms #define TIMEOUT_100MS 100U /* Timeout in 100ms */
#define RNG_AES_KEY_INDEX 1 #define RNG_AES_KEY_INDEX 1
/******************************************************************************* /*******************************************************************************
* Data structure and global variables * Data structure and global variables
...@@ -68,14 +68,12 @@ ...@@ -68,14 +68,12 @@
* #--------------------------------# * #--------------------------------#
*/ */
/* Known pattern data */ /* Known pattern data for T210 */
static const uint32_t se_ctx_known_pattern_data[SE_CTX_KNOWN_PATTERN_SIZE_WORDS] = { static const uint8_t se_ctx_known_pattern_data[SE_CTX_KNOWN_PATTERN_SIZE] = {
/* 128 bit AES block */ /* 128 bit AES block */
0x0C0D0E0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08090A0B, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
0x04050607, };
0x00010203,
};
/* SE input and output linked list buffers */ /* SE input and output linked list buffers */
static tegra_se_io_lst_t se1_src_ll_buf; static tegra_se_io_lst_t se1_src_ll_buf;
...@@ -85,6 +83,9 @@ static tegra_se_io_lst_t se1_dst_ll_buf; ...@@ -85,6 +83,9 @@ static tegra_se_io_lst_t se1_dst_ll_buf;
static tegra_se_io_lst_t se2_src_ll_buf; static tegra_se_io_lst_t se2_src_ll_buf;
static tegra_se_io_lst_t se2_dst_ll_buf; static tegra_se_io_lst_t se2_dst_ll_buf;
/* SE1 context buffer, 132 blocks */
static __aligned(64) uint8_t se1_ctx_buf[SE_CTX_DRBG_BUFER_SIZE];
/* SE1 security engine device handle */ /* SE1 security engine device handle */
static tegra_se_dev_t se_dev_1 = { static tegra_se_dev_t se_dev_1 = {
.se_num = 1, .se_num = 1,
...@@ -97,10 +98,10 @@ static tegra_se_dev_t se_dev_1 = { ...@@ -97,10 +98,10 @@ static tegra_se_dev_t se_dev_1 = {
/* Setup DST buffers for SE operations */ /* Setup DST buffers for SE operations */
.dst_ll_buf = &se1_dst_ll_buf, .dst_ll_buf = &se1_dst_ll_buf,
/* Setup context save destination */ /* Setup context save destination */
.ctx_save_buf = (uint32_t *)(TEGRA_TZRAM_CARVEOUT_BASE), .ctx_save_buf = (uint32_t *)&se1_ctx_buf
}; };
/* SE2 security engine device handle */ /* SE2 security engine device handle (T210B01 only) */
static tegra_se_dev_t se_dev_2 = { static tegra_se_dev_t se_dev_2 = {
.se_num = 2, .se_num = 2,
/* Setup base address for se */ /* Setup base address for se */
...@@ -112,7 +113,7 @@ static tegra_se_dev_t se_dev_2 = { ...@@ -112,7 +113,7 @@ static tegra_se_dev_t se_dev_2 = {
/* Setup DST buffers for SE operations */ /* Setup DST buffers for SE operations */
.dst_ll_buf = &se2_dst_ll_buf, .dst_ll_buf = &se2_dst_ll_buf,
/* Setup context save destination */ /* Setup context save destination */
.ctx_save_buf = (uint32_t *)(TEGRA_TZRAM_CARVEOUT_BASE + 0x1000), .ctx_save_buf = (uint32_t *)(TEGRA_TZRAM_CARVEOUT_BASE + 0x1000)
}; };
static bool ecid_valid; static bool ecid_valid;
...@@ -201,18 +202,6 @@ static int32_t tegra_se_operation_complete(const tegra_se_dev_t *se_dev) ...@@ -201,18 +202,6 @@ static int32_t tegra_se_operation_complete(const tegra_se_dev_t *se_dev)
return ret; return ret;
} }
/*
* Returns true if the SE engine is configured to perform SE context save in
* hardware.
*/
static inline bool tegra_se_atomic_save_enabled(const tegra_se_dev_t *se_dev)
{
uint32_t val;
val = tegra_se_read_32(se_dev, SE_CTX_SAVE_AUTO_REG_OFFSET);
return (SE_CTX_SAVE_AUTO_ENABLE(val) == SE_CTX_SAVE_AUTO_EN);
}
/* /*
* Wait for SE engine to be idle and clear pending interrupts before * Wait for SE engine to be idle and clear pending interrupts before
* starting the next SE operation. * starting the next SE operation.
...@@ -223,6 +212,9 @@ static int32_t tegra_se_operation_prepare(const tegra_se_dev_t *se_dev) ...@@ -223,6 +212,9 @@ static int32_t tegra_se_operation_prepare(const tegra_se_dev_t *se_dev)
uint32_t val = 0; uint32_t val = 0;
uint32_t timeout; uint32_t timeout;
/* disable SE interrupt to prevent interrupt issued by SE operation */
tegra_se_write_32(se_dev, SE_INT_ENABLE_REG_OFFSET, 0U);
/* Wait for previous operation to finish */ /* Wait for previous operation to finish */
val = tegra_se_read_32(se_dev, SE_STATUS_OFFSET); val = tegra_se_read_32(se_dev, SE_STATUS_OFFSET);
for (timeout = 0; (val != 0U) && (timeout < TIMEOUT_100MS); timeout++) { for (timeout = 0; (val != 0U) && (timeout < TIMEOUT_100MS); timeout++) {
...@@ -629,19 +621,19 @@ static int tegra_se_lp_rsakeytable_context_save(tegra_se_dev_t *se_dev) ...@@ -629,19 +621,19 @@ static int tegra_se_lp_rsakeytable_context_save(tegra_se_dev_t *se_dev)
{ {
uint32_t val = 0; uint32_t val = 0;
int ret = 0; int ret = 0;
/* First the modulus and then the exponent must be /* For T210, First the modulus and then exponent must be
* encrypted and saved. This is repeated for SLOT 0 * encrypted and saved. This is repeated for SLOT 0
* and SLOT 1. Hence the order: * and SLOT 1. Hence the order:
* SLOT 0 exponent : RSA_KEY_INDEX : 0
* SLOT 0 modulus : RSA_KEY_INDEX : 1 * SLOT 0 modulus : RSA_KEY_INDEX : 1
* SLOT 1 exponent : RSA_KEY_INDEX : 2 * SLOT 0 exponent : RSA_KEY_INDEX : 0
* SLOT 1 modulus : RSA_KEY_INDEX : 3 * SLOT 1 modulus : RSA_KEY_INDEX : 3
* SLOT 1 exponent : RSA_KEY_INDEX : 2
*/ */
const unsigned int key_index_mod[TEGRA_SE_RSA_KEYSLOT_COUNT][2] = { const unsigned int key_index_mod[TEGRA_SE_RSA_KEYSLOT_COUNT][2] = {
/* RSA key slot 0 */ /* RSA key slot 0 */
{SE_RSA_KEY_INDEX_SLOT0_EXP, SE_RSA_KEY_INDEX_SLOT0_MOD}, {SE_RSA_KEY_INDEX_SLOT0_MOD, SE_RSA_KEY_INDEX_SLOT0_EXP},
/* RSA key slot 1 */ /* RSA key slot 1 */
{SE_RSA_KEY_INDEX_SLOT1_EXP, SE_RSA_KEY_INDEX_SLOT1_MOD}, {SE_RSA_KEY_INDEX_SLOT1_MOD, SE_RSA_KEY_INDEX_SLOT1_EXP},
}; };
se_dev->dst_ll_buf->last_buff_num = 0; se_dev->dst_ll_buf->last_buff_num = 0;
...@@ -876,8 +868,8 @@ static int tegra_se_context_save_sw(tegra_se_dev_t *se_dev) ...@@ -876,8 +868,8 @@ static int tegra_se_context_save_sw(tegra_se_dev_t *se_dev)
/* Write lp context buffer address into PMC scratch register */ /* Write lp context buffer address into PMC scratch register */
if (se_dev->se_num == 1) { if (se_dev->se_num == 1) {
/* SE context address */ /* SE context address, support T210 only */
mmio_write_32((uint64_t)TEGRA_PMC_BASE + PMC_SECURE_SCRATCH117_OFFSET, mmio_write_32((uint64_t)TEGRA_PMC_BASE + PMC_SCRATCH43_REG_OFFSET,
((uint64_t)(se_dev->ctx_save_buf))); ((uint64_t)(se_dev->ctx_save_buf)));
} else if (se_dev->se_num == 2) { } else if (se_dev->se_num == 2) {
/* SE2 & PKA1 context address */ /* SE2 & PKA1 context address */
...@@ -909,7 +901,10 @@ void tegra_se_init(void) ...@@ -909,7 +901,10 @@ void tegra_se_init(void)
/* Generate random SRK to initialize DRBG */ /* Generate random SRK to initialize DRBG */
tegra_se_generate_srk(&se_dev_1); tegra_se_generate_srk(&se_dev_1);
tegra_se_generate_srk(&se_dev_2);
if (tegra_chipid_is_t210_b01()) {
tegra_se_generate_srk(&se_dev_2);
}
/* determine if ECID is valid */ /* determine if ECID is valid */
val = mmio_read_32(TEGRA_FUSE_BASE + FUSE_JTAG_SECUREID_VALID); val = mmio_read_32(TEGRA_FUSE_BASE + FUSE_JTAG_SECUREID_VALID);
...@@ -932,6 +927,18 @@ static void tegra_se_enable_clocks(void) ...@@ -932,6 +927,18 @@ static void tegra_se_enable_clocks(void)
val &= ~ENTROPY_RESET_BIT; val &= ~ENTROPY_RESET_BIT;
mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEVICES_W, val); mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEVICES_W, val);
if (!tegra_chipid_is_t210_b01()) {
/*
* T210 SE clock source is turned off in kernel, to simplify
* SE clock source setting, we switch SE clock source to
* CLK_M, SE_CLK_DIVISOR = 0. T210 B01 SE clock source is
* always on, so don't need this setting.
*/
mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_RST_CTL_CLK_SRC_SE,
SE_CLK_SRC_CLK_M);
}
/* Enable SE clock */ /* Enable SE clock */
val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_V); val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_CLK_OUT_ENB_V);
val |= SE_CLK_ENB_BIT; val |= SE_CLK_ENB_BIT;
...@@ -975,43 +982,25 @@ int32_t tegra_se_suspend(void) ...@@ -975,43 +982,25 @@ int32_t tegra_se_suspend(void)
tegra_se_enable_clocks(); tegra_se_enable_clocks();
if (tegra_se_atomic_save_enabled(&se_dev_2) && if (tegra_chipid_is_t210_b01()) {
tegra_se_atomic_save_enabled(&se_dev_1)) { /* It is T210 B01, Atomic context save se2 and pka1 */
/* Atomic context save se2 and pka1 */
INFO("%s: SE2/PKA1 atomic context save\n", __func__); INFO("%s: SE2/PKA1 atomic context save\n", __func__);
if (ret == 0) { ret = tegra_se_context_save_atomic(&se_dev_2);
ret = tegra_se_context_save_atomic(&se_dev_2); if (ret != 0) {
} ERROR("%s: SE2 ctx save failed (%d)\n", __func__, ret);
/* Atomic context save se */
if (ret == 0) {
INFO("%s: SE1 atomic context save\n", __func__);
ret = tegra_se_context_save_atomic(&se_dev_1);
} }
if (ret == 0) { ret = tegra_se_context_save_atomic(&se_dev_1);
INFO("%s: SE atomic context save done\n", __func__); if (ret != 0) {
} ERROR("%s: SE1 ctx save failed (%d)\n", __func__, ret);
} else if (!tegra_se_atomic_save_enabled(&se_dev_2) &&
!tegra_se_atomic_save_enabled(&se_dev_1)) {
/* SW context save se2 and pka1 */
INFO("%s: SE2/PKA1 legacy(SW) context save\n", __func__);
if (ret == 0) {
ret = tegra_se_context_save_sw(&se_dev_2);
}
/* SW context save se */
if (ret == 0) {
INFO("%s: SE1 legacy(SW) context save\n", __func__);
ret = tegra_se_context_save_sw(&se_dev_1);
}
if (ret == 0) {
INFO("%s: SE SW context save done\n", __func__);
} }
} else { } else {
ERROR("%s: One SE set for atomic CTX save, the other is not\n", /* It is T210, SW context save se */
__func__); INFO("%s: SE1 legacy(SW) context save\n", __func__);
ret = tegra_se_context_save_sw(&se_dev_1);
if (ret != 0) {
ERROR("%s: SE1 ctx save failed (%d)\n", __func__, ret);
}
} }
tegra_se_disable_clocks(); tegra_se_disable_clocks();
...@@ -1080,5 +1069,8 @@ static void tegra_se_warm_boot_resume(const tegra_se_dev_t *se_dev) ...@@ -1080,5 +1069,8 @@ static void tegra_se_warm_boot_resume(const tegra_se_dev_t *se_dev)
void tegra_se_resume(void) void tegra_se_resume(void)
{ {
tegra_se_warm_boot_resume(&se_dev_1); tegra_se_warm_boot_resume(&se_dev_1);
tegra_se_warm_boot_resume(&se_dev_2);
if (tegra_chipid_is_t210_b01()) {
tegra_se_warm_boot_resume(&se_dev_2);
}
} }
...@@ -210,12 +210,9 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) ...@@ -210,12 +210,9 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
assert((stateid_afflvl1 == PLAT_MAX_OFF_STATE) || assert((stateid_afflvl1 == PLAT_MAX_OFF_STATE) ||
(stateid_afflvl1 == PSTATE_ID_SOC_POWERDN)); (stateid_afflvl1 == PSTATE_ID_SOC_POWERDN));
if (tegra_chipid_is_t210_b01()) { /* Suspend se/se2 and pka1 for T210 B01 and se for T210 */
if (tegra_se_suspend() != 0) {
/* Suspend se/se2 and pka1 */ ret = PSCI_E_INTERN_FAIL;
if (tegra_se_suspend() != 0) {
ret = PSCI_E_INTERN_FAIL;
}
} }
} else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) { } else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) {
......
...@@ -174,9 +174,7 @@ void plat_early_platform_setup(void) ...@@ -174,9 +174,7 @@ void plat_early_platform_setup(void)
} }
/* Initialize security engine driver */ /* Initialize security engine driver */
if (tegra_chipid_is_t210_b01()) { tegra_se_init();
tegra_se_init();
}
} }
/* Secure IRQs for Tegra186 */ /* Secure IRQs for Tegra186 */
......
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