summaryrefslogtreecommitdiff
path: root/plat/nvidia
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2018-03-05 10:19:37 -0800
committerVarun Wadekar <vwadekar@nvidia.com>2019-01-31 08:48:56 -0800
commit2d5560f928544f375c9e757d3a271bac980c0bef (patch)
tree00a6b77ebf6467836062233f65698af2e8e4ae80 /plat/nvidia
parent278d599c11f356c05ac57b36a20e9eaa4b7fe721 (diff)
Tegra210: power off all DMA masters before System Suspend entry
This patch puts all the DMA masters in reset before starting the System Suspend sequence. This helps us make sure that there are no rogue agents in the system trying to over-write the SC7 Entry Firmware with their own. Change-Id: I7eb39999d229951e612fbfeb9f86c4efb8f98b5a Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Diffstat (limited to 'plat/nvidia')
-rw-r--r--plat/nvidia/tegra/include/t210/tegra_def.h53
-rw-r--r--plat/nvidia/tegra/soc/t210/plat_psci_handlers.c91
-rw-r--r--plat/nvidia/tegra/soc/t210/plat_setup.c2
3 files changed, 135 insertions, 11 deletions
diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h
index 02c5f135..eed443d1 100644
--- a/plat/nvidia/tegra/include/t210/tegra_def.h
+++ b/plat/nvidia/tegra/include/t210/tegra_def.h
@@ -41,6 +41,7 @@
* iRAM memory constants
******************************************************************************/
#define TEGRA_IRAM_BASE U(0x40000000)
+#define TEGRA_IRAM_A_SIZE U(0x10000) /* 64KB */
#define TEGRA_IRAM_SIZE U(40000) /* 256KB */
/*******************************************************************************
@@ -95,23 +96,55 @@
* Tegra Clock and Reset Controller constants
******************************************************************************/
#define TEGRA_CAR_RESET_BASE U(0x60006000)
+#define TEGRA_BOND_OUT_H U(0x74)
+#define APB_DMA_LOCK_BIT (U(1) << 2)
+#define AHB_DMA_LOCK_BIT (U(1) << 1)
+#define TEGRA_BOND_OUT_U U(0x78)
+#define IRAM_D_LOCK_BIT (U(1) << 23)
+#define IRAM_C_LOCK_BIT (U(1) << 22)
+#define IRAM_B_LOCK_BIT (U(1) << 21)
#define TEGRA_GPU_RESET_REG_OFFSET U(0x28C)
#define TEGRA_GPU_RESET_GPU_SET_OFFSET U(0x290)
#define GPU_RESET_BIT (U(1) << 24)
#define GPU_SET_BIT (U(1) << 24)
+#define TEGRA_RST_DEV_SET_Y U(0x2a8)
+#define NVENC_RESET_BIT (U(1) << 27)
+#define TSECB_RESET_BIT (U(1) << 14)
+#define APE_RESET_BIT (U(1) << 6)
+#define NVJPG_RESET_BIT (U(1) << 3)
+#define NVDEC_RESET_BIT (U(1) << 2)
+#define TEGRA_RST_DEV_SET_L U(0x300)
+#define HOST1X_RESET_BIT (U(1) << 28)
+#define ISP_RESET_BIT (U(1) << 23)
+#define USBD_RESET_BIT (U(1) << 22)
+#define VI_RESET_BIT (U(1) << 20)
+#define SDMMC4_RESET_BIT (U(1) << 15)
+#define SDMMC1_RESET_BIT (U(1) << 14)
+#define SDMMC2_RESET_BIT (U(1) << 9)
+#define TEGRA_RST_DEV_SET_H U(0x308)
+#define USB2_RESET_BIT (U(1) << 26)
+#define APBDMA_RESET_BIT (U(1) << 2)
+#define AHBDMA_RESET_BIT (U(1) << 1)
+#define TEGRA_RST_DEV_SET_U U(0x310)
+#define XUSB_DEV_RESET_BIT (U(1) << 31)
+#define XUSB_HOST_RESET_BIT (U(1) << 25)
+#define TSEC_RESET_BIT (U(1) << 19)
+#define PCIE_RESET_BIT (U(1) << 6)
+#define SDMMC3_RESET_BIT (U(1) << 5)
+#define TEGRA_RST_DEVICES_V U(0x358)
+#define TEGRA_RST_DEVICES_W U(0x35C)
+#define ENTROPY_CLK_ENB_BIT (U(1) << 21)
+#define TEGRA_CLK_OUT_ENB_V U(0x360)
+#define SE_CLK_ENB_BIT (U(1) << 31)
+#define TEGRA_CLK_OUT_ENB_W U(0x364)
+#define ENTROPY_RESET_BIT (U(1) << 21)
+#define TEGRA_RST_DEV_SET_V U(0x430)
+#define SE_RESET_BIT (U(1) << 31)
+#define HDA_RESET_BIT (U(1) << 29)
+#define SATA_RESET_BIT (U(1) << 28)
#define TEGRA_RST_DEV_CLR_V U(0x434)
#define TEGRA_CLK_ENB_V U(0x440)
-/* SE Clock Offsets */
-#define TEGRA_RST_DEVICES_V 0x358UL
-#define SE_RESET_BIT (0x1UL << 31)
-#define TEGRA_RST_DEVICES_W 0x35CUL
-#define ENTROPY_CLK_ENB_BIT (0x1UL << 21)
-#define TEGRA_CLK_OUT_ENB_V 0x360UL
-#define SE_CLK_ENB_BIT (0x1UL << 31)
-#define TEGRA_CLK_OUT_ENB_W 0x364UL
-#define ENTROPY_RESET_BIT (0x1UL << 21)
-
/*******************************************************************************
* Tegra Flow Controller constants
******************************************************************************/
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
index 4c49386b..4e9206f9 100644
--- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -21,6 +21,7 @@
#include <tegra_def.h>
#include <tegra_private.h>
#include <tegra_platform.h>
+#include <utils.h>
/*
* Register used to clear CPU reset signals. Each CPU has two reset
@@ -255,6 +256,74 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
return ret;
}
+static void tegra_reset_all_dma_masters(void)
+{
+ uint32_t val, mask;
+
+ /*
+ * Reset all possible DMA masters in the system.
+ */
+ val = GPU_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET, val);
+
+ val = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT |
+ NVJPG_RESET_BIT | NVDEC_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y, val);
+
+ val = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT |
+ VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT |
+ SDMMC2_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L, val);
+
+ val = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H, val);
+
+ val = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT |
+ PCIE_RESET_BIT | SDMMC3_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U, val);
+
+ val = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT;
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V, val);
+
+ /*
+ * If any of the DMA masters are still alive, assume
+ * that the system has been compromised and reboot.
+ */
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET);
+ mask = GPU_RESET_BIT;
+ if ((val & mask) != mask)
+ tegra_pmc_system_reset();
+
+ mask = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT |
+ NVJPG_RESET_BIT | NVDEC_RESET_BIT;
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y);
+ if ((val & mask) != mask)
+ tegra_pmc_system_reset();
+
+ mask = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT |
+ VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT |
+ SDMMC2_RESET_BIT;
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L);
+ if ((val & mask) != mask)
+ tegra_pmc_system_reset();
+
+ mask = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT;
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H);
+ if ((val & mask) != mask)
+ tegra_pmc_system_reset();
+
+ mask = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT |
+ PCIE_RESET_BIT | SDMMC3_RESET_BIT;
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U);
+ if ((val & mask) != mask)
+ tegra_pmc_system_reset();
+
+ val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V);
+ mask = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT;
+ if ((val & mask) != mask)
+ tegra_pmc_system_reset();
+}
+
int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
{
u_register_t mpidr = read_mpidr();
@@ -287,6 +356,28 @@ int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
/* Power off BPMP before we proceed */
tegra_fc_bpmp_off();
+ /* bond out IRAM banks B, C and D */
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_U,
+ IRAM_B_LOCK_BIT | IRAM_C_LOCK_BIT |
+ IRAM_D_LOCK_BIT);
+
+ /* bond out APB/AHB DMAs */
+ mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_H,
+ APB_DMA_LOCK_BIT | AHB_DMA_LOCK_BIT);
+
+ /* Power off BPMP before we proceed */
+ tegra_fc_bpmp_off();
+
+ /*
+ * Reset all the hardware blocks that can act as DMA
+ * masters on the bus.
+ */
+ tegra_reset_all_dma_masters();
+
+ /* clean up IRAM of any cruft */
+ zeromem((void *)(uintptr_t)TEGRA_IRAM_BASE,
+ TEGRA_IRAM_A_SIZE);
+
/* Copy the firmware to BPMP's internal RAM */
(void)memcpy((void *)(uintptr_t)TEGRA_IRAM_BASE,
(const void *)plat_params->sc7entry_fw_base,
diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c
index 4fdd5a8a..0aeb9fff 100644
--- a/plat/nvidia/tegra/soc/t210/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t210/plat_setup.c
@@ -160,7 +160,7 @@ void plat_late_platform_setup(void)
/* memmap TZDRAM area containing the SC7 Entry Firmware */
if (plat_params->sc7entry_fw_base && plat_params->sc7entry_fw_size) {
- assert(plat_params->sc7entry_fw_size <= TEGRA_IRAM_SIZE);
+ assert(plat_params->sc7entry_fw_size <= TEGRA_IRAM_A_SIZE);
/*
* Verify that the SC7 entry firmware resides inside the TZDRAM