Tegra194: SiP function ID to read SMMU_PER registers
This patch introduces SiP function ID, 0xC200FF00, to read SMMU_PER
error records from all supported SMMU blocks.
The register values are passed over to the client via CPU registers
X1 - X3, where
X1 = SMMU_PER[instance #1] | SMMU_PER[instance #0]
X2 = SMMU_PER[instance #3] | SMMU_PER[instance #2]
X3 = SMMU_PER[instance #5] | SMMU_PER[instance #4]
Change-Id: Id56263f558838ad05f6021f8432e618e99e190fc
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
diff --git a/plat/nvidia/tegra/soc/t194/plat_sip_calls.c b/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
index 33694a1..884762d 100644
--- a/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
+++ b/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
@@ -16,11 +16,13 @@
#include <common/runtime_svc.h>
#include <tegra_private.h>
#include <tegra_platform.h>
+#include <smmu.h>
#include <stdbool.h>
/*******************************************************************************
* Tegra194 SiP SMCs
******************************************************************************/
+#define TEGRA_SIP_GET_SMMU_PER 0xC200FF00U
/*******************************************************************************
* This function is responsible for handling all T194 SiP calls
@@ -34,13 +36,43 @@
void *handle,
uint64_t flags)
{
- int32_t ret = -ENOTSUP;
+ int32_t ret = 0;
+ uint32_t i, smmu_per[6] = {0};
+ uint32_t num_smmu_devices = plat_get_num_smmu_devices();
+ uint64_t per[3] = {0ULL};
- (void)smc_fid;
(void)x1;
(void)x4;
(void)cookie;
(void)flags;
+ switch (smc_fid) {
+ case TEGRA_SIP_GET_SMMU_PER:
+
+ /* make sure we dont go past the array length */
+ assert(num_smmu_devices <= ARRAY_SIZE(smmu_per));
+
+ /* read all supported SMMU_PER records */
+ for (i = 0U; i < num_smmu_devices; i++) {
+ smmu_per[i] = tegra_smmu_read_32(i, SMMU_GSR0_PER);
+ }
+
+ /* pack results into 3 64bit variables. */
+ per[0] = smmu_per[0] | ((uint64_t)smmu_per[1] << 32U);
+ per[1] = smmu_per[2] | ((uint64_t)smmu_per[3] << 32U);
+ per[2] = smmu_per[4] | ((uint64_t)smmu_per[5] << 32U);
+
+ /* provide the results via X1-X3 CPU registers */
+ write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1, per[0]);
+ write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X2, per[1]);
+ write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X3, per[2]);
+
+ break;
+
+ default:
+ ret = -ENOTSUP;
+ break;
+ }
+
return ret;
}