drm/tegra: Add sysfs to trigger SOC power mode change.

For Sentry Mode SHR, Host1x client engine clock needs to configured
to a lower rate or clock-gated. a new IVC comand is added to send
power mode change notification to NvHost Server to perform the clock
rate update.

Jira HOSTX-5373

Change-Id: I9039c5243d5fd40f1da2f11e4449ea2e9b0dfc42
Signed-off-by: Mainak Sen <msen@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3181703
(cherry picked from commit dab7c0e0537cf1c18697f69fe9eba8a150b2245a)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3220776
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Raghavendra Vishnu Kumar <rvk@nvidia.com>
Reviewed-by: Sourab Gupta <sourabg@nvidia.com>
This commit is contained in:
Mainak Sen
2024-07-25 11:53:17 +00:00
committed by Jon Hunter
parent 49d30a84cc
commit 7afa86700c

View File

@@ -15,6 +15,8 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <soc/tegra/bpmp.h> #include <soc/tegra/bpmp.h>
#include <soc/tegra/virt/hv-ivc.h> #include <soc/tegra/virt/hv-ivc.h>
@@ -30,26 +32,33 @@
#define TEGRA_VHOST_CMD_SUSPEND 2 #define TEGRA_VHOST_CMD_SUSPEND 2
#define TEGRA_VHOST_CMD_RESUME 3 #define TEGRA_VHOST_CMD_RESUME 3
#define TEGRA_VHOST_CMD_GET_CONNECTION_ID 4 #define TEGRA_VHOST_CMD_GET_CONNECTION_ID 4
#define TEGRA_VHOST_CMD_POWER_MODE_CHANGE 5
struct tegra_vhost_connect_params { struct tegra_vhost_connect_params {
u32 module; u32 module;
u64 connection_id; u64 connection_id;
}; };
struct tegra_vhost_power_mode_change_params {
u32 ip_op_mode;
};
struct tegra_vhost_cmd_msg { struct tegra_vhost_cmd_msg {
u32 cmd; u32 cmd;
int ret; int ret;
u64 connection_id; u64 connection_id;
struct tegra_vhost_connect_params connect; struct tegra_vhost_connect_params connect;
struct tegra_vhost_power_mode_change_params pw_mode;
}; };
struct virt_engine { struct virt_engine {
struct device *dev; struct device *dev;
int connection_id; int connection_id;
struct tegra_drm_client client; struct tegra_drm_client client;
struct dentry *actmon_debugfs_dir; struct dentry *actmon_debugfs_dir;
struct kobject kobj;
struct kobj_attribute powermode_attr;
u32 powermode;
const char *name; const char *name;
unsigned long rate; unsigned long rate;
}; };
@@ -263,6 +272,16 @@ static int virt_engine_resume(struct device *dev)
return virt_engine_transfer(&msg, sizeof(msg)); return virt_engine_transfer(&msg, sizeof(msg));
} }
static int virt_engine_power_mode_change(struct virt_engine *virt, u32 ip_op_mode)
{
struct tegra_vhost_cmd_msg msg = { 0 };
struct tegra_vhost_power_mode_change_params *p = &msg.pw_mode;
msg.cmd = TEGRA_VHOST_CMD_POWER_MODE_CHANGE;
p->ip_op_mode = ip_op_mode;
return virt_engine_transfer(&msg, sizeof(msg));
}
static int mrq_debug_open(struct tegra_bpmp *bpmp, const char *name, static int mrq_debug_open(struct tegra_bpmp *bpmp, const char *name,
u32 *fd, u32 *len, bool write) u32 *fd, u32 *len, bool write)
{ {
@@ -530,6 +549,65 @@ static void virt_engine_cleanup_actmon_debugfs(struct virt_engine *virt)
debugfs_remove_recursive(virt->actmon_debugfs_dir); debugfs_remove_recursive(virt->actmon_debugfs_dir);
} }
static ssize_t virt_engine_powermode_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct virt_engine *virt = container_of(kobj, struct virt_engine, kobj);
return sprintf(buf, "%d\n", virt->powermode);
}
static ssize_t virt_engine_powermode_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
struct virt_engine *virt;
int ret;
virt = container_of(kobj, struct virt_engine, kobj);
ret = kstrtoint(buf, 0, &virt->powermode);
if (ret < 0)
return ret;
/* Send Power Mode transition command to NvHost_Server VM */
virt_engine_power_mode_change(virt, virt->powermode);
return count;
}
static struct kobj_type ktype_powermode = {
.sysfs_ops = &kobj_sysfs_ops,
};
static int virt_engine_sysfs_init(struct virt_engine *virt)
{
int ret;
if (virt == NULL)
return -EINVAL;
/* Create sysfs file */
virt->powermode_attr.attr.name = "mode";
virt->powermode_attr.attr.mode = 0644;
virt->powermode_attr.show = virt_engine_powermode_show;
virt->powermode_attr.store = virt_engine_powermode_store;
sysfs_attr_init(&virt->powermode_attr.attr);
/* Initialize kobject */
ret = kobject_init_and_add(&virt->kobj, &ktype_powermode, &virt->dev->kobj, "powerprofile");
if (ret) {
kobject_put(&virt->kobj);
return ret;
}
ret = sysfs_create_file(&virt->kobj, &virt->powermode_attr.attr);
if (ret)
kobject_put(&virt->kobj);
return ret;
}
static void virt_engine_sysfs_exit(struct virt_engine *virt)
{
sysfs_remove_file(&virt->kobj, &virt->powermode_attr.attr);
kobject_put(&virt->kobj);
}
static const struct of_device_id tegra_virt_engine_of_match[] = { static const struct of_device_id tegra_virt_engine_of_match[] = {
{ .compatible = "nvidia,tegra234-host1x-virtual-engine" }, { .compatible = "nvidia,tegra234-host1x-virtual-engine" },
{ }, { },
@@ -700,6 +778,7 @@ static int virt_engine_probe(struct platform_device *pdev)
} }
virt_engine_setup_actmon_debugfs(virt); virt_engine_setup_actmon_debugfs(virt);
virt_engine_sysfs_init(virt);
#ifndef CONFIG_TEGRA_SYSTEM_TYPE_ACK #ifndef CONFIG_TEGRA_SYSTEM_TYPE_ACK
hwpm_ip_index = virt_engine_get_ip_index(pdev->name); hwpm_ip_index = virt_engine_get_ip_index(pdev->name);
@@ -747,6 +826,7 @@ static int virt_engine_remove(struct platform_device *pdev)
} }
#endif #endif
virt_engine_cleanup_actmon_debugfs(virt_engine); virt_engine_cleanup_actmon_debugfs(virt_engine);
virt_engine_sysfs_exit(virt_engine);
virt_engine_cleanup(); virt_engine_cleanup();
host1x_client_unregister(&virt_engine->client.base); host1x_client_unregister(&virt_engine->client.base);