diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c index 71bb05c0415d..a105a9f8c40a 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c @@ -28,6 +28,7 @@ #include #include +#include #include #if IS_ENABLED(CONFIG_DEVFREQ_THERMAL) #include @@ -35,6 +36,7 @@ #include #include +#include #include "mali_kbase_devfreq.h" #include @@ -125,6 +127,20 @@ void kbase_devfreq_opp_translate(struct kbase_device *kbdev, unsigned long freq, } } +static int kbase_devfreq_set_read_margin(struct device *dev, + struct rockchip_opp_info *opp_info, + unsigned long volt, + bool is_set_rm) +{ + if (opp_info->data && opp_info->data->set_read_margin) { + if (is_set_rm) + opp_info->data->set_read_margin(dev, opp_info, volt); + opp_info->volt_rm = volt; + } + + return 0; +} + int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data) { struct device *dev = data->dev; @@ -139,8 +155,16 @@ int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data) struct rockchip_opp_info *opp_info = &kbdev->opp_info; unsigned long old_freq = data->old_opp.rate; unsigned long new_freq = data->new_opp.rate; + bool is_set_rm = true; + bool is_set_clk = true; int ret = 0; + if (!pm_runtime_active(dev)) { + is_set_rm = false; + if (kbdev->scmi_clk) + is_set_clk = false; + } + ret = clk_bulk_prepare_enable(opp_info->num_clks, opp_info->clks); if (ret) { dev_err(dev, "failed to enable opp clks\n"); @@ -163,24 +187,23 @@ int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data) new_supply_vdd->u_volt); goto restore_voltage; } - if (opp_info->data->set_read_margin) - opp_info->data->set_read_margin(dev, opp_info, - new_supply_vdd->u_volt); + kbase_devfreq_set_read_margin(dev, opp_info, + new_supply_vdd->u_volt, + is_set_rm); } /* Change frequency */ dev_dbg(dev, "switching OPP: %lu Hz --> %lu Hz\n", old_freq, new_freq); - ret = clk_set_rate(clk, new_freq); - if (ret) { + if (is_set_clk && clk_set_rate(clk, new_freq)) { dev_err(dev, "failed to set clk rate: %d\n", ret); goto restore_rm; } /* Scaling down? Scale voltage after frequency */ if (new_freq < old_freq) { - if (opp_info->data->set_read_margin) - opp_info->data->set_read_margin(dev, opp_info, - new_supply_vdd->u_volt); + kbase_devfreq_set_read_margin(dev, opp_info, + new_supply_vdd->u_volt, + is_set_rm); ret = regulator_set_voltage(vdd_reg, new_supply_vdd->u_volt, INT_MAX); if (ret) { @@ -202,12 +225,11 @@ int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data) return 0; restore_freq: - if (clk_set_rate(clk, old_freq)) + if (is_set_clk && clk_set_rate(clk, old_freq)) dev_err(dev, "failed to restore old-freq %lu Hz\n", old_freq); restore_rm: - if (opp_info->data->set_read_margin) - opp_info->data->set_read_margin(dev, opp_info, - old_supply_vdd->u_volt); + kbase_devfreq_set_read_margin(dev, opp_info, old_supply_vdd->u_volt, + is_set_rm); restore_voltage: regulator_set_voltage(mem_reg, old_supply_mem->u_volt, INT_MAX); regulator_set_voltage(vdd_reg, old_supply_vdd->u_volt, INT_MAX); @@ -673,6 +695,8 @@ int kbase_devfreq_init(struct kbase_device *kbdev) else kbdev->current_freqs[i] = 0; } + if (strstr(__clk_get_name(kbdev->clocks[0]), "scmi")) + kbdev->scmi_clk = kbdev->clocks[0]; kbdev->current_nominal_freq = kbdev->current_freqs[0]; opp = devfreq_recommended_opp(kbdev->dev, &kbdev->current_nominal_freq, 0); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_defs.h index 53572123a4ab..46a0c0571ea9 100755 --- a/drivers/gpu/arm/bifrost/mali_kbase_defs.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_defs.h @@ -670,6 +670,7 @@ struct kbase_process { * @irqs.flags: irq flags * @clocks: Pointer to the input clock resources referenced by * the GPU device node. + * @scmi_clk: Pointer to the input scmi clock resources * @nr_clocks: Number of clocks set in the clocks array. * @regulators: Pointer to the structs corresponding to the * regulators referenced by the GPU device node. @@ -971,6 +972,7 @@ struct kbase_device { } irqs[3]; struct clk *clocks[BASE_MAX_NR_CLOCKS_REGULATORS]; + struct clk *scmi_clk; unsigned int nr_clocks; #if IS_ENABLED(CONFIG_REGULATOR) struct regulator *regulators[BASE_MAX_NR_CLOCKS_REGULATORS]; diff --git a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c index 6ec00ebc6d83..f1d07439006b 100755 --- a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c +++ b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c @@ -32,9 +32,12 @@ #include #include #include +#include #include "mali_kbase_rk.h" +#define POWER_DOWN_FREQ 200000000 + /** * @file mali_kbase_config_rk.c * 对 platform_config_of_rk 的具体实现. @@ -92,10 +95,12 @@ static void rk_pm_power_off_delay_work(struct work_struct *work) return; } + rockchip_monitor_volt_adjust_lock(kbdev->mdev_info); if (pm_runtime_enabled(kbdev->dev)) { D("to put_sync_suspend mali_dev."); pm_runtime_put_sync_suspend(kbdev->dev); } + rockchip_monitor_volt_adjust_unlock(kbdev->mdev_info); rk_pm_disable_clk(kbdev); @@ -186,11 +191,38 @@ struct kbase_platform_funcs_conf platform_funcs = { static int rk_pm_callback_runtime_on(struct kbase_device *kbdev) { + struct rockchip_opp_info *opp_info = &kbdev->opp_info; + int ret = 0; + + if (!kbdev->current_nominal_freq) + return 0; + + ret = clk_bulk_prepare_enable(opp_info->num_clks, opp_info->clks); + if (ret) { + dev_err(kbdev->dev, "failed to enable opp clks\n"); + return ret; + } + if (kbdev->scmi_clk) { + if (clk_set_rate(kbdev->scmi_clk, kbdev->current_nominal_freq)) + dev_err(kbdev->dev, "failed to restore clk rate\n"); + } + if (opp_info->data && opp_info->data->set_read_margin) + opp_info->data->set_read_margin(kbdev->dev, opp_info, + opp_info->volt_rm); + clk_bulk_disable_unprepare(opp_info->num_clks, opp_info->clks); + return 0; } static void rk_pm_callback_runtime_off(struct kbase_device *kbdev) { + struct rockchip_opp_info *opp_info = &kbdev->opp_info; + + if (kbdev->scmi_clk) { + if (clk_set_rate(kbdev->scmi_clk, POWER_DOWN_FREQ)) + dev_err(kbdev->dev, "failed to set power down rate\n"); + } + opp_info->current_rm = UINT_MAX; } static int rk_pm_callback_power_on(struct kbase_device *kbdev) @@ -224,6 +256,7 @@ static int rk_pm_callback_power_on(struct kbase_device *kbdev) goto out; } + rockchip_monitor_volt_adjust_lock(kbdev->mdev_info); /* 若 mali_dev 的 runtime_pm 是 enabled 的, 则... */ if (pm_runtime_enabled(kbdev->dev)) { D("to resume mali_dev syncly."); @@ -240,6 +273,7 @@ static int rk_pm_callback_power_on(struct kbase_device *kbdev) ret = 0; } } + rockchip_monitor_volt_adjust_unlock(kbdev->mdev_info); platform->is_powered = true; wake_lock(&platform->wake_lock);