Tegra194: pwr_mgmt: introduce power management support
This patch introduces support to enter the System Suspend power state. The
required context is saved to allow the platform to enter and resume from
the state.
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Change-Id: Iaeaf065f87a2b20981aa92a14fa964802fada20c
diff --git a/plat/nvidia/tegra194/include/platform_def.h b/plat/nvidia/tegra194/include/platform_def.h
index 2ad63eb..af08357 100644
--- a/plat/nvidia/tegra194/include/platform_def.h
+++ b/plat/nvidia/tegra194/include/platform_def.h
@@ -139,6 +139,7 @@
/*******************************************************************************
* Platform MMIO devices
******************************************************************************/
+#define TEGRA194_MC_BASE U(0x02C10000)
#define TEGRA194_GICD_BASE U(0x03881000)
#define TEGRA194_GICC_BASE U(0x03882000)
#define TEGRA194_SPE_BASE U(0x0C168000)
@@ -146,5 +147,15 @@
#define TEGRA194_RTC_BASE U(0x0C2A0000)
#define TEGRA194_TMRUS_BASE U(0x0C2E0000)
#define SYS_CNT_BASE1 TEGRA194_TMRUS_BASE
+#define TEGRA194_SCRATCH_BASE U(0x0C390000)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Platform functions
+ */
+void tegra194_pwr_mgmt_setup(void);
+
+#endif /* __ASSEMBLY__ */
#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/nvidia/tegra194/platform.mk b/plat/nvidia/tegra194/platform.mk
index 494ed1e..1d3c50a 100644
--- a/plat/nvidia/tegra194/platform.mk
+++ b/plat/nvidia/tegra194/platform.mk
@@ -13,9 +13,10 @@
drivers/ti/uart/aarch64/16550_console.S \
plat/nvidia/tegra194/helpers.S \
plat/nvidia/tegra194/pwr_state.c \
+ plat/nvidia/tegra194/pwr_mgmt.c \
+ plat/nvidia/tegra194/setup.c \
plat/nvidia/tegra194/topology.c \
- plat/nvidia/tegra194/timers.c \
- plat/nvidia/tegra194/setup.c
+ plat/nvidia/tegra194/timers.c
PLAT_TESTS_SKIP_LIST := plat/nvidia/tegra194/tests_to_skip.txt
diff --git a/plat/nvidia/tegra194/pwr_mgmt.c b/plat/nvidia/tegra194/pwr_mgmt.c
new file mode 100644
index 0000000..0ba2e55
--- /dev/null
+++ b/plat/nvidia/tegra194/pwr_mgmt.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stddef.h>
+
+#include <utils_def.h>
+
+/*******************************************************************************
+ * Memory Controller SMMU Bypass config register
+ ******************************************************************************/
+#define MC_SMMU_BYPASS_CONFIG U(0x1820)
+
+/*******************************************************************************
+ * Secure Scratch 73 to save base address of SMMU register context
+ ******************************************************************************/
+#define SCRATCH_SECURE_RSV73_SCRATCH U(0x2ac)
+
+typedef struct mc_regs {
+ uint32_t reg;
+ uint32_t val;
+} mc_regs_t;
+
+#define mc_smmu_bypass_cfg \
+ { \
+ .reg = TEGRA194_MC_BASE + MC_SMMU_BYPASS_CONFIG, \
+ .val = 0x00000000U, \
+ }
+
+#define START_OF_TABLE \
+ { \
+ .reg = 0xCAFE05C7U, \
+ .val = 0x00000000U, \
+ }
+
+#define END_OF_TABLE \
+ { \
+ .reg = 0xFFFFFFFFU, \
+ .val = 0xFFFFFFFFU, \
+ }
+
+/*******************************************************************************
+ * Array to hold MC context for Tegra194
+ ******************************************************************************/
+static __attribute__((aligned(16))) mc_regs_t tegra194_mc_context[] = {
+ START_OF_TABLE,
+ mc_smmu_bypass_cfg, /* TBU settings */
+ END_OF_TABLE,
+};
+
+void tegra194_pwr_mgmt_setup(void)
+{
+ /* index of END_OF_TABLE */
+ tegra194_mc_context[0].val = ARRAY_SIZE(tegra194_mc_context) - 1U;
+
+ /* save SMMU context for SC7-RF to restore */
+ mmio_write_32(TEGRA194_SCRATCH_BASE + SCRATCH_SECURE_RSV73_SCRATCH,
+ ((uintptr_t)tegra194_mc_context) >> 12);
+}
diff --git a/plat/nvidia/tegra194/setup.c b/plat/nvidia/tegra194/setup.c
index 818caa6..e83d303 100644
--- a/plat/nvidia/tegra194/setup.c
+++ b/plat/nvidia/tegra194/setup.c
@@ -24,6 +24,8 @@
* DRAM aperture for NVM : 256MB
*/
static const mmap_region_t tegra194_mmap[] = {
+ MAP_REGION_FLAT(TEGRA194_MC_BASE, 0x2000, /* 8KB */
+ MT_DEVICE | MT_RW | MT_NS),
MAP_REGION_FLAT(TEGRA194_GICD_BASE, 0x1000, /* 4KB */
MT_DEVICE | MT_RW | MT_NS),
MAP_REGION_FLAT(TEGRA194_GICC_BASE, 0x1000, /* 4KB */
@@ -34,6 +36,8 @@
MT_DEVICE | MT_RW | MT_NS),
MAP_REGION_FLAT(TEGRA194_TMRUS_BASE, 0x1000, /* 4KB */
MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(TEGRA194_SCRATCH_BASE, 0x1000, /* 4KB */
+ MT_DEVICE | MT_RW | MT_NS),
MAP_REGION_FLAT(DRAM_BASE + TFTF_NVM_OFFSET, TFTF_NVM_SIZE,
MT_MEMORY | MT_RW | MT_NS),
{0}
@@ -62,4 +66,7 @@
gicv2_setup_distif();
gicv2_probe_gic_cpu_id();
gicv2_setup_cpuif();
+
+ /* Setup power management dependencies */
+ tegra194_pwr_mgmt_setup();
}