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>
diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
index 4c99a7b..f919ac3 100644
--- a/plat/nvidia/tegra/include/t186/tegra_def.h
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -261,11 +261,17 @@
 #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
  ******************************************************************************/
 #define TEGRA_SMMU_BASE			0x12000000
diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c
index e848eab..c401b85 100644
--- a/plat/nvidia/tegra/soc/t186/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t186/plat_setup.c
@@ -102,6 +102,8 @@
 			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 31e903e..fa39749 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>
@@ -44,10 +45,15 @@
 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 @@
 		     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 @@
 
 		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 fe1c588..0c2b0a4 100644
--- a/plat/nvidia/tegra/soc/t186/platform_t186.mk
+++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk
@@ -57,10 +57,10 @@
 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