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 ff8abc2f4142..5156a0684bcd 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.c @@ -134,10 +134,17 @@ int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data) struct regulator *vdd_reg = data->regulators[0]; struct regulator *mem_reg = data->regulators[1]; struct clk *clk = data->clk; + struct kbase_device *kbdev = dev_get_drvdata(dev); + 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; int ret = 0; + if (clk_bulk_prepare_enable(opp_info->num_clks, opp_info->clks) < 0) { + dev_err(dev, "failed to enable opp clks\n"); + return ret; + } + /* Scaling up? Scale voltage before frequency */ if (new_freq >= old_freq) { ret = regulator_set_voltage(mem_reg, new_supply_mem->u_volt, @@ -154,6 +161,9 @@ 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); } /* Change frequency */ @@ -166,6 +176,9 @@ int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data) /* 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); ret = regulator_set_voltage(vdd_reg, new_supply_vdd->u_volt, INT_MAX); if (ret) { @@ -182,11 +195,17 @@ int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data) } } + clk_bulk_disable_unprepare(opp_info->num_clks, opp_info->clks); + return 0; restore_freq: + if (opp_info->data->set_read_margin) + opp_info->data->set_read_margin(dev, opp_info, + old_supply_vdd->u_volt); if (clk_set_rate(clk, old_freq)) dev_err(dev, "failed to restore old-freq %lu Hz\n", old_freq); + clk_bulk_disable_unprepare(opp_info->num_clks, opp_info->clks); 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); diff --git a/drivers/gpu/arm/bifrost/mali_kbase_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_defs.h index 1ca5b036225a..79a9f807b89a 100755 --- a/drivers/gpu/arm/bifrost/mali_kbase_defs.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_defs.h @@ -70,6 +70,7 @@ #include #include #include +#include #if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM) #define KBASE_PM_RUNTIME 1 @@ -1014,6 +1015,7 @@ struct kbase_device { struct mutex kctx_list_lock; atomic_t group_max_uid_in_devices; + struct rockchip_opp_info opp_info; #ifdef CONFIG_MALI_BIFROST_DEVFREQ struct devfreq_dev_profile devfreq_profile; struct devfreq *devfreq; 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 4acd389a041c..572e44709c16 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 @@ -26,7 +26,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -444,9 +446,66 @@ static void kbase_platform_rk_remove_sysfs_files(struct device *dev) device_remove_file(dev, &dev_attr_utilisation); } +static int rk3588_gpu_set_read_margin(struct device *dev, + struct rockchip_opp_info *opp_info, + unsigned long volt) +{ + bool is_found = false; + int i, ret = 0; + u32 rm, val; + + if (!opp_info->grf || !opp_info->volt_rm_tbl) + return 0; + + for (i = 0; opp_info->volt_rm_tbl[i].rm != VOLT_RM_TABLE_END; i++) { + if (volt >= opp_info->volt_rm_tbl[i].volt) { + rm = opp_info->volt_rm_tbl[i].rm; + is_found = true; + break; + } + } + + if (!is_found) + return 0; + + dev_dbg(dev, "set rm to %d\n", rm); + + ret = regmap_read(opp_info->grf, 0x24, &val); + if (ret < 0) { + dev_err(dev, "failed to get rm from 0x24\n"); + return ret; + } + val &= ~0x1c; + regmap_write(opp_info->grf, 0x24, val | (rm << 2)); + + ret = regmap_read(opp_info->grf, 0x28, &val); + if (ret < 0) { + dev_err(dev, "failed to get rm from 0x28\n"); + return ret; + } + val &= ~0x1c; + regmap_write(opp_info->grf, 0x28, val | (rm << 2)); + + return 0; +} + +static const struct rockchip_opp_data rk3588_gpu_opp_data = { + .set_read_margin = rk3588_gpu_set_read_margin, +}; + +static const struct of_device_id rockchip_mali_of_match[] = { + { + .compatible = "rockchip,rk3588", + .data = (void *)&rk3588_gpu_opp_data, + }, + {}, +}; + int kbase_platform_rk_init_opp_table(struct kbase_device *kbdev) { - return rockchip_init_opp_table(kbdev->dev, NULL, + rockchip_get_opp_data(rockchip_mali_of_match, &kbdev->opp_info); + + return rockchip_init_opp_table(kbdev->dev, &kbdev->opp_info, "gpu_leakage", "mali"); }