mali400: mali: Add rockchip simple-power-model support

Signed-off-by: Shaohan Yao <shaohan.yao@rock-chips.com>
Change-Id: I0f4edae3b6ad76d31fdc93a5cf96561afe0511ee
This commit is contained in:
Shaohan Yao
2022-12-15 10:26:08 +08:00
committed by Tao Huang
parent 2938e413fd
commit 791feb8cc2

View File

@@ -35,6 +35,7 @@
#include <linux/pm_runtime.h>
#include <linux/delay.h>
#include <linux/rockchip/cpu.h>
#include <soc/rockchip/rockchip_ipa.h>
#include <soc/rockchip/rockchip_opp_select.h>
#include <linux/mali/mali_utgard.h>
@@ -232,73 +233,7 @@ static u32 dynamic_coefficient;
static u32 static_coefficient;
static s32 ts[4];
static struct thermal_zone_device *gpu_tz;
static int power_model_simple_init(struct platform_device *pdev)
{
struct device_node *power_model_node;
const char *tz_name;
u32 static_power, dynamic_power;
u32 voltage, voltage_squared, voltage_cubed, frequency;
power_model_node = of_get_child_by_name(pdev->dev.of_node,
"power_model");
if (!power_model_node) {
dev_err(&pdev->dev, "could not find power_model node\n");
return -ENODEV;
}
if (!of_device_is_compatible(power_model_node,
"arm,mali-simple-power-model")) {
dev_err(&pdev->dev, "power_model incompatible with simple power model\n");
return -ENODEV;
}
if (of_property_read_string(power_model_node, "thermal-zone",
&tz_name)) {
dev_err(&pdev->dev, "ts in power_model not available\n");
return -EINVAL;
}
gpu_tz = thermal_zone_get_zone_by_name(tz_name);
if (IS_ERR(gpu_tz)) {
pr_warn_ratelimited("Error getting gpu thermal zone '%s'(%ld), not yet ready?\n",
tz_name,
PTR_ERR(gpu_tz));
gpu_tz = NULL;
}
if (of_property_read_u32(power_model_node, "static-power",
&static_power)) {
dev_err(&pdev->dev, "static-power in power_model not available\n");
return -EINVAL;
}
if (of_property_read_u32(power_model_node, "dynamic-power",
&dynamic_power)) {
dev_err(&pdev->dev, "dynamic-power in power_model not available\n");
return -EINVAL;
}
if (of_property_read_u32(power_model_node, "voltage",
&voltage)) {
dev_err(&pdev->dev, "voltage in power_model not available\n");
return -EINVAL;
}
if (of_property_read_u32(power_model_node, "frequency",
&frequency)) {
dev_err(&pdev->dev, "frequency in power_model not available\n");
return -EINVAL;
}
voltage_squared = (voltage * voltage) / 1000;
voltage_cubed = voltage * voltage * voltage;
static_coefficient = (static_power << 20) / (voltage_cubed >> 10);
dynamic_coefficient = (((dynamic_power * 1000) / voltage_squared)
* 1000) / frequency;
if (of_property_read_u32_array(power_model_node, "ts", (u32 *)ts, 4)) {
dev_err(&pdev->dev, "ts in power_model not available\n");
return -EINVAL;
}
return 0;
}
static struct ipa_power_model_data *model_data;
/* Calculate gpu static power example for reference */
static unsigned long rk_model_static_power(struct devfreq *devfreq,
@@ -360,10 +295,107 @@ static unsigned long rk_model_dynamic_power(struct devfreq *devfreq,
return dynamic_power;
}
struct devfreq_cooling_power rk_cooling_ops = {
static struct devfreq_cooling_power rk_cooling_ops = {
.get_static_power = rk_model_static_power,
.get_dynamic_power = rk_model_dynamic_power,
};
static unsigned long mali_devfreq_get_static_power(struct devfreq *devfreq,
unsigned long voltage)
{
return rockchip_ipa_get_static_power(model_data, voltage);
}
static int power_model_simple_init(struct platform_device *pdev)
{
struct device_node *power_model_node;
const char *tz_name;
u32 static_power, dynamic_power;
u32 voltage, voltage_squared, voltage_cubed, frequency;
if (of_find_compatible_node(pdev->dev.of_node, NULL, "simple-power-model")) {
of_property_read_u32(pdev->dev.of_node,
"dynamic-power-coefficient",
(u32 *)&rk_cooling_ops.dyn_power_coeff);
model_data = rockchip_ipa_power_model_init(&pdev->dev,
"gpu_leakage");
if (IS_ERR_OR_NULL(model_data)) {
model_data = NULL;
dev_err(&pdev->dev, "failed to initialize power model\n");
} else if (model_data->dynamic_coefficient) {
rk_cooling_ops.dyn_power_coeff =
model_data->dynamic_coefficient;
rk_cooling_ops.get_dynamic_power = NULL;
rk_cooling_ops.get_static_power = mali_devfreq_get_static_power;
}
if (!rk_cooling_ops.dyn_power_coeff) {
dev_err(&pdev->dev, "failed to get dynamic-coefficient\n");
return -EINVAL;
}
return 0;
}
power_model_node = of_get_child_by_name(pdev->dev.of_node,
"power_model");
if (!power_model_node) {
dev_err(&pdev->dev, "could not find power_model node\n");
return -ENODEV;
}
if (!of_device_is_compatible(power_model_node,
"arm,mali-simple-power-model")) {
dev_err(&pdev->dev, "power_model incompatible with simple power model\n");
return -ENODEV;
}
if (of_property_read_string(power_model_node, "thermal-zone",
&tz_name)) {
dev_err(&pdev->dev, "ts in power_model not available\n");
return -EINVAL;
}
gpu_tz = thermal_zone_get_zone_by_name(tz_name);
if (IS_ERR(gpu_tz)) {
pr_warn_ratelimited("Error getting gpu thermal zone '%s'(%ld), not yet ready?\n",
tz_name,
PTR_ERR(gpu_tz));
gpu_tz = NULL;
}
if (of_property_read_u32(power_model_node, "static-power",
&static_power)) {
dev_err(&pdev->dev, "static-power in power_model not available\n");
return -EINVAL;
}
if (of_property_read_u32(power_model_node, "dynamic-power",
&dynamic_power)) {
dev_err(&pdev->dev, "dynamic-power in power_model not available\n");
return -EINVAL;
}
if (of_property_read_u32(power_model_node, "voltage",
&voltage)) {
dev_err(&pdev->dev, "voltage in power_model not available\n");
return -EINVAL;
}
if (of_property_read_u32(power_model_node, "frequency",
&frequency)) {
dev_err(&pdev->dev, "frequency in power_model not available\n");
return -EINVAL;
}
voltage_squared = (voltage * voltage) / 1000;
voltage_cubed = voltage * voltage * voltage;
static_coefficient = (static_power << 20) / (voltage_cubed >> 10);
dynamic_coefficient = (((dynamic_power * 1000) / voltage_squared)
* 1000) / frequency;
if (of_property_read_u32_array(power_model_node, "ts", (u32 *)ts, 4)) {
dev_err(&pdev->dev, "ts in power_model not available\n");
return -EINVAL;
}
return 0;
}
#endif
/*---------------------------------------------------------------------------*/