From 691bc22de951947bcc5d3bb637858fde7283781c Mon Sep 17 00:00:00 2001
From: Varun Wadekar <vwadekar@nvidia.com>
Date: Fri, 23 Sep 2016 14:28:16 -0700
Subject: [PATCH] Tegra186: read activity monitor's clock counter values

This patch adds a new SMC function ID to read the refclk and coreclk
clock counter values from the Activity Monitor. The non-secure world
requires this information to calculate the CPU's frequency.

Formula: "freq = (delta_coreclk / delta_refclk) * refclk_freq"

The following CPU registers have to be set by the non-secure driver
before issuing the SMC:

X1 = MPIDR of the target core
X2 = MIDR of the target core

Change-Id: I296d835def1f5788c17640c0c456b8f8f0e90824
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
---
 plat/nvidia/tegra/include/t186/tegra_def.h  |  8 ++++-
 plat/nvidia/tegra/soc/t186/plat_setup.c     |  2 ++
 plat/nvidia/tegra/soc/t186/plat_sip_calls.c | 40 ++++++++++++++++++++-
 plat/nvidia/tegra/soc/t186/platform_t186.mk |  4 +--
 4 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
index 4c99a7b04..f919ac378 100644
--- a/plat/nvidia/tegra/include/t186/tegra_def.h
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -261,10 +261,16 @@
 #define  SECURE_SCRATCH_RSV55_HI	0x80C
 
 /*******************************************************************************
- * Tegra Memory Mapped Control Register Access Bus constants
+ * Tegra Memory Mapped Control Register Access constants
  ******************************************************************************/
 #define TEGRA_MMCRAB_BASE		0x0E000000
 
+/*******************************************************************************
+ * Tegra Memory Mapped Activity Monitor Register Access constants
+ ******************************************************************************/
+#define TEGRA_ARM_ACTMON_CTR_BASE	0x0E060000
+#define TEGRA_DENVER_ACTMON_CTR_BASE	0x0E070000
+
 /*******************************************************************************
  * Tegra SMMU Controller constants
  ******************************************************************************/
diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c
index e848eabb7..c401b858f 100644
--- a/plat/nvidia/tegra/soc/t186/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t186/plat_setup.c
@@ -102,6 +102,8 @@ static const mmap_region_t tegra_mmap[] = {
 			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_MMCRAB_BASE, 0x60000, /* 384KB */
 			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(TEGRA_ARM_ACTMON_CTR_BASE, 0x20000, /* 128KB - ARM/Denver */
+			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(TEGRA_SMMU_BASE, 0x1000000, /* 64KB */
 			MT_DEVICE | MT_RW | MT_SECURE),
 	{0}
diff --git a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c
index 31e903eba..fa3974972 100644
--- a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c
+++ b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c
@@ -34,6 +34,7 @@
 #include <bl_common.h>
 #include <context_mgmt.h>
 #include <debug.h>
+#include <denver.h>
 #include <errno.h>
 #include <mce.h>
 #include <memctrl.h>
@@ -43,11 +44,16 @@
 
 extern uint32_t tegra186_system_powerdn_state;
 
+/*******************************************************************************
+ * Offset to read the ref_clk counter value
+ ******************************************************************************/
+#define REF_CLK_OFFSET		4
+
 /*******************************************************************************
  * Tegra186 SiP SMCs
  ******************************************************************************/
-#define TEGRA_SIP_NEW_VIDEOMEM_REGION			0x82000003
 #define TEGRA_SIP_SYSTEM_SHUTDOWN_STATE			0x82FFFE01
+#define TEGRA_SIP_GET_ACTMON_CLK_COUNTERS		0x82FFFE02
 #define TEGRA_SIP_MCE_CMD_ENTER_CSTATE			0x82FFFF00
 #define TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO		0x82FFFF01
 #define TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME		0x82FFFF02
@@ -81,6 +87,8 @@ int plat_sip_handler(uint32_t smc_fid,
 		     uint64_t flags)
 {
 	int mce_ret;
+	int impl, cpu;
+	uint32_t base, core_clk_ctr, ref_clk_ctr;
 
 	switch (smc_fid) {
 
@@ -143,6 +151,36 @@ int plat_sip_handler(uint32_t smc_fid,
 
 		return 0;
 
+	/*
+	 * This function ID reads the Activity monitor's core/ref clock
+	 * counter values for a core/cluster.
+	 *
+	 * x1 = MPIDR of the target core
+	 * x2 = MIDR of the target core
+	 */
+	case TEGRA_SIP_GET_ACTMON_CLK_COUNTERS:
+
+		cpu = (uint32_t)x1 & MPIDR_CPU_MASK;
+		impl = ((uint32_t)x2 >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
+
+		/* sanity check target CPU number */
+		if (cpu > PLATFORM_MAX_CPUS_PER_CLUSTER)
+			return -EINVAL;
+
+		/* get the base address for the current CPU */
+		base = (impl == DENVER_IMPL) ? TEGRA_DENVER_ACTMON_CTR_BASE :
+			TEGRA_ARM_ACTMON_CTR_BASE;
+
+		/* read the clock counter values */
+		core_clk_ctr = mmio_read_32(base + (8 * cpu));
+		ref_clk_ctr = mmio_read_32(base + (8 * cpu) + REF_CLK_OFFSET);
+
+		/* return the counter values as two different parameters */
+		write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, core_clk_ctr);
+		write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X2, ref_clk_ctr);
+
+		return 0;
+
 	default:
 		break;
 	}
diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk
index fe1c58848..0c2b0a470 100644
--- a/plat/nvidia/tegra/soc/t186/platform_t186.mk
+++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk
@@ -57,10 +57,10 @@ $(eval $(call add_define,PLATFORM_CLUSTER_COUNT))
 PLATFORM_MAX_CPUS_PER_CLUSTER		:= 4
 $(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER))
 
-MAX_XLAT_TABLES				:= 20
+MAX_XLAT_TABLES				:= 24
 $(eval $(call add_define,MAX_XLAT_TABLES))
 
-MAX_MMAP_REGIONS			:= 20
+MAX_MMAP_REGIONS			:= 24
 $(eval $(call add_define,MAX_MMAP_REGIONS))
 
 # platform files
-- 
GitLab