From e3e12f52b214121840b44c91de5b3e5af5d3eb84 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 06 Nov 2023 03:04:41 +0000 Subject: [PATCH] rk3568 rt init --- kernel/drivers/gpu/arm/mali400/mali/platform/rk/rk.c | 206 +++++++++++++++++++++++++++++++++------------------ 1 files changed, 134 insertions(+), 72 deletions(-) diff --git a/kernel/drivers/gpu/arm/mali400/mali/platform/rk/rk.c b/kernel/drivers/gpu/arm/mali400/mali/platform/rk/rk.c index 9a012fd..4c6e7f9 100644 --- a/kernel/drivers/gpu/arm/mali400/mali/platform/rk/rk.c +++ b/kernel/drivers/gpu/arm/mali400/mali/platform/rk/rk.c @@ -34,7 +34,10 @@ #include <linux/dma-mapping.h> #include <linux/pm_runtime.h> #include <linux/delay.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.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> @@ -47,6 +50,7 @@ /*---------------------------------------------------------------------------*/ +#define RK3528_GPU_SD_SLP_HAST 0x10024 #define DEFAULT_UTILISATION_PERIOD_IN_MS (100) /* @@ -55,6 +59,7 @@ struct rk_context { /* mali device. */ struct device *dev; + struct regmap *grf; /* is the GPU powered on? */ bool is_powered; /* debug only, the period in ms to count gpu_utilisation. */ @@ -183,6 +188,10 @@ } platform->dev = dev; + platform->grf = syscon_regmap_lookup_by_phandle(dev->of_node, + "rockchip,grf"); + if (IS_ERR(platform->grf)) + platform->grf = NULL; platform->is_powered = false; platform->utilisation_period = DEFAULT_UTILISATION_PERIOD_IN_MS; @@ -232,73 +241,7 @@ 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 +303,107 @@ 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 /*---------------------------------------------------------------------------*/ @@ -376,8 +416,7 @@ #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK) struct mali_device *mdev = dev_get_drvdata(dev); - if (mdev->clock) - ret = clk_enable(mdev->clock); + ret = clk_bulk_enable(mdev->num_clks, mdev->clks); #endif return ret; } @@ -387,8 +426,7 @@ #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK) struct mali_device *mdev = dev_get_drvdata(dev); - if (mdev->clock) - clk_disable(mdev->clock); + clk_bulk_disable(mdev->num_clks, mdev->clks); #endif } @@ -432,6 +470,18 @@ goto fail_to_enable_regulator; } + if (cpu_is_rk3528()) { +#if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK) + struct mali_device *mdev = dev_get_drvdata(dev); + + clk_set_rate(mdev->clock, mdev->current_freq); +#endif + if (platform->grf) + regmap_write(platform->grf, + RK3528_GPU_SD_SLP_HAST, + 0xffff0000); + } + platform->is_powered = true; } @@ -449,6 +499,18 @@ struct rk_context *platform = s_rk_context; if (platform->is_powered) { + if (cpu_is_rk3528()) { +#if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_HAVE_CLK) + struct mali_device *mdev = dev_get_drvdata(dev); + + //use normal pll 200M for gpu when suspend + clk_set_rate(mdev->clock, 200000000); +#endif + if (platform->grf) + regmap_write(platform->grf, + RK3528_GPU_SD_SLP_HAST, + 0xfffffffd); + } rk_platform_disable_clk_gpu(dev); rk_platform_disable_gpu_regulator(dev); -- Gitblit v1.6.2