mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
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:
@@ -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
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
Reference in New Issue
Block a user