diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile
index 008b0129f..89074c49d 100644
--- a/drivers/gpu/nvgpu/Makefile
+++ b/drivers/gpu/nvgpu/Makefile
@@ -215,7 +215,8 @@ nvgpu-$(CONFIG_DEBUG_FS) += \
os/linux/debug_ltc.o \
os/linux/debug_xve.o \
os/linux/debug_clk_gv100.o \
- os/linux/debug_volt.o
+ os/linux/debug_volt.o \
+ os/linux/debug_s_param.o
ifeq ($(CONFIG_NVGPU_TRACK_MEM_USAGE),y)
nvgpu-$(CONFIG_DEBUG_FS) += \
diff --git a/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.c b/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.c
index daeae9ffd..1e3fe731c 100644
--- a/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.c
+++ b/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.c
@@ -102,6 +102,85 @@ static int vfe_vars_pmustatus_instget(struct gk20a *g, void *pboardobjgrppmu,
return 0;
}
+static int vfe_var_get_s_param_value(struct gk20a *g,
+ struct vfe_var_single_sensed_fuse *fuse_value,
+ struct nv_pmu_boardobj *ppmudata)
+{
+ struct nv_pmu_perf_vfe_var_single_sensed_fuse_get_status *pstatus;
+ pstatus = (struct nv_pmu_perf_vfe_var_single_sensed_fuse_get_status *)
+ (void *)ppmudata;
+
+ nvgpu_log_info(g, " ");
+
+ if (pstatus->super.board_obj.type !=
+ fuse_value->super.super.super.super.type) {
+ nvgpu_err(g,"pmu data and boardobj type not matching");
+ return -EINVAL;
+ }
+
+ if(pstatus->fuse_value_integer.b_signed) {
+ fuse_value->b_fuse_value_signed =
+ pstatus->fuse_value_integer.b_signed;
+ fuse_value->fuse_value_integer =
+ (u32)pstatus->fuse_value_integer.data.signed_value;
+ fuse_value->fuse_value_hw_integer =
+ (u32)pstatus->fuse_value_hw_integer.data.signed_value;
+ } else {
+ fuse_value->b_fuse_value_signed =
+ pstatus->fuse_value_integer.b_signed;
+ fuse_value->fuse_value_integer =
+ pstatus->fuse_value_integer.data.unsigned_value;
+ fuse_value->fuse_value_hw_integer =
+ pstatus->fuse_value_hw_integer.data.unsigned_value;
+ }
+ return 0;
+}
+
+int nvgpu_vfe_var_boardobj_grp_get_status(struct gk20a *g) {
+ struct boardobjgrp *pboardobjgrp;
+ struct boardobjgrpmask *pboardobjgrpmask;
+ struct nv_pmu_boardobjgrp_super *pboardobjgrppmu;
+ struct boardobj *pboardobj = NULL;
+ struct nv_pmu_boardobj_query *pboardobjpmustatus = NULL;
+ struct vfe_var_single_sensed_fuse *single_sensed_fuse = NULL;
+ int status;
+ u8 index;
+
+ nvgpu_log_info(g, " ");
+ pboardobjgrp = &g->perf_pmu->vfe_varobjs.super.super;
+ pboardobjgrpmask = &g->perf_pmu->vfe_varobjs.super.mask.super;
+ status = pboardobjgrp->pmugetstatus(g, pboardobjgrp, pboardobjgrpmask);
+ if (status != 0) {
+ nvgpu_err(g, "err getting boardobjs from pmu");
+ return status;
+ }
+ pboardobjgrppmu = pboardobjgrp->pmu.getstatus.buf;
+
+ BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) {
+ single_sensed_fuse = (struct vfe_var_single_sensed_fuse *)
+ (void *)pboardobj;
+ status = pboardobjgrp->pmustatusinstget(g,
+ (struct nv_pmu_boardobjgrp *)(void *)pboardobjgrppmu,
+ &pboardobjpmustatus, index);
+ if (status != 0) {
+ nvgpu_err(g, "could not get status object instance");
+ return status;
+ }
+ /* At present we are updating only s_param,
+ * in future we can add other fields if required */
+ if (single_sensed_fuse->vfield_info.v_field_id ==
+ VFIELD_ID_S_PARAM) {
+ status = vfe_var_get_s_param_value(g, single_sensed_fuse,
+ (struct nv_pmu_boardobj *)(void *)pboardobjpmustatus);
+ if (status != 0) {
+ nvgpu_err(g, "could not get single sensed fuse value");
+ return status;
+ }
+ break;
+ }
+ }
+ return 0;
+}
int vfe_var_sw_setup(struct gk20a *g)
{
diff --git a/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.h b/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.h
index b7d9fb413..2ca228194 100644
--- a/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.h
+++ b/drivers/gpu/nvgpu/common/pmu/perf/vfe_var.h
@@ -106,4 +106,6 @@ struct vfe_var_single_sensed_temp {
int temp_default;
};
+int nvgpu_vfe_var_boardobj_grp_get_status(struct gk20a *g);
+
#endif /* NVGPU_PERF_VFE_VAR_H */
diff --git a/drivers/gpu/nvgpu/include/nvgpu/bios.h b/drivers/gpu/nvgpu/include/nvgpu/bios.h
index cbb2d4ca6..781416106 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/bios.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/bios.h
@@ -536,6 +536,7 @@ struct vbios_vfe_3x_equ_entry_struct {
#define VFIELD_CODE(pvregentry) ((pvregentry->strap_reg_desc & 0xE0U) >> 5U)
+#define VFIELD_ID_S_PARAM 0x07U
#define VFIELD_ID_STRAP_IDDQ 0x09U
#define VFIELD_ID_STRAP_IDDQ_1 0x0BU
diff --git a/drivers/gpu/nvgpu/os/linux/debug_s_param.c b/drivers/gpu/nvgpu/os/linux/debug_s_param.c
new file mode 100644
index 000000000..2cbbf9b81
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/debug_s_param.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include "os_linux.h"
+#include "include/nvgpu/bios.h"
+
+#include
+#include
+
+static int get_s_param_info(void *data, u64 *val)
+{
+ struct gk20a *g = (struct gk20a *)data;
+ struct boardobjgrp *pboardobjgrp;
+ struct boardobj *pboardobj = NULL;
+ struct vfe_var_single_sensed_fuse *single_sensed_fuse = NULL;
+ int status;
+ u8 index;
+
+ status = nvgpu_vfe_var_boardobj_grp_get_status(g);
+ if(status != 0) {
+ nvgpu_err(g, "Vfe_var get status failed");
+ return status;
+ }
+
+ pboardobjgrp = &g->perf_pmu->vfe_varobjs.super.super;
+
+ BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) {
+ single_sensed_fuse = (struct vfe_var_single_sensed_fuse *)
+ (void *)pboardobj;
+ if(single_sensed_fuse->vfield_info.v_field_id ==
+ VFIELD_ID_S_PARAM) {
+ *val = single_sensed_fuse->fuse_value_hw_integer;
+ }
+ }
+ return status;
+}
+DEFINE_SIMPLE_ATTRIBUTE(s_param_fops, get_s_param_info , NULL, "%llu\n");
+
+int nvgpu_s_param_init_debugfs(struct gk20a *g)
+{
+ struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
+ struct dentry *dbgentry;
+
+ dbgentry = debugfs_create_file(
+ "s_param", S_IRUGO, l->debugfs, g, &s_param_fops);
+ if (!dbgentry) {
+ pr_err("%s: Failed to make debugfs node\n", __func__);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/nvgpu/os/linux/debug_s_param.h b/drivers/gpu/nvgpu/os/linux/debug_s_param.h
new file mode 100644
index 000000000..f5250494e
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/debug_s_param.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __DEBUG_S_PARAM_TU104_H
+#define __DEBUG_S_PARAM_TU104_H
+
+#include
+
+#ifdef CONFIG_DEBUG_FS
+int nvgpu_s_param_init_debugfs(struct gk20a *g);
+#else
+static inline int nvgpu_s_param_init_debugfs(struct gk20a *g)
+{
+ return 0;
+}
+#endif
+
+#endif
diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c
index 494c51766..f6a20b0ce 100644
--- a/drivers/gpu/nvgpu/os/linux/module.c
+++ b/drivers/gpu/nvgpu/os/linux/module.c
@@ -241,6 +241,14 @@ int nvgpu_finalize_poweron_linux(struct nvgpu_os_linux *l)
}
}
+ if (l->ops.s_param.init_debugfs) {
+ err = l->ops.s_param.init_debugfs(g);
+ if (err) {
+ nvgpu_err(g, "failed to init linux s_param trace debugfs");
+ return err;
+ }
+ }
+
err = nvgpu_pmgr_init_debugfs_linux(l);
if (err) {
nvgpu_err(g, "failed to init linux pmgr debugfs");
diff --git a/drivers/gpu/nvgpu/os/linux/os_linux.h b/drivers/gpu/nvgpu/os/linux/os_linux.h
index 71e0c65d2..6c8b974aa 100644
--- a/drivers/gpu/nvgpu/os/linux/os_linux.h
+++ b/drivers/gpu/nvgpu/os/linux/os_linux.h
@@ -56,6 +56,10 @@ struct nvgpu_os_linux_ops {
struct {
int (*init_debugfs)(struct gk20a *g);
} volt;
+
+ struct {
+ int (*init_debugfs)(struct gk20a *g);
+ } s_param;
};
struct nvgpu_os_linux {
diff --git a/drivers/gpu/nvgpu/os/linux/os_ops_tu104.c b/drivers/gpu/nvgpu/os/linux/os_ops_tu104.c
index 94f279787..6b70b738a 100644
--- a/drivers/gpu/nvgpu/os/linux/os_ops_tu104.c
+++ b/drivers/gpu/nvgpu/os/linux/os_ops_tu104.c
@@ -19,6 +19,7 @@
#include "os/linux/debug_therm_gp106.h"
#include "os/linux/debug_clk_gv100.h"
#include "os/linux/debug_volt.h"
+#include "os/linux/debug_s_param.h"
static struct nvgpu_os_linux_ops tu104_os_linux_ops = {
.therm = {
@@ -30,6 +31,9 @@ static struct nvgpu_os_linux_ops tu104_os_linux_ops = {
.volt = {
.init_debugfs = nvgpu_volt_init_debugfs,
},
+ .s_param = {
+ .init_debugfs = nvgpu_s_param_init_debugfs,
+ },
};
void nvgpu_tu104_init_os_ops(struct nvgpu_os_linux *l)
@@ -37,4 +41,5 @@ void nvgpu_tu104_init_os_ops(struct nvgpu_os_linux *l)
l->ops.therm = tu104_os_linux_ops.therm;
l->ops.clk = tu104_os_linux_ops.clk;
l->ops.volt = tu104_os_linux_ops.volt;
+ l->ops.s_param = tu104_os_linux_ops.s_param;
}