diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index 01edb773ea32..2ec4339a7a97 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -113,8 +112,6 @@ struct rockchip_dmcfreq { struct devfreq_event_dev **edev; struct mutex lock; /* serializes access to video_info_list */ struct dram_timing *timing; - struct regulator *vdd_center; - struct regulator *mem_reg; struct notifier_block status_nb; struct notifier_block panic_nb; struct list_head video_info_list; @@ -123,6 +120,7 @@ struct rockchip_dmcfreq { struct input_handler input_handler; struct monitor_dev_info *mdev_info; struct share_params *set_rate_params; + struct rockchip_opp_info opp_info; unsigned long *nocp_bw; unsigned long rate; @@ -159,16 +157,10 @@ struct rockchip_dmcfreq { int edev_count; int dfi_id; int nocp_cpu_id; - int regulator_count; bool is_fixed; bool is_set_rate_direct; - struct thermal_cooling_device *devfreq_cooling; - u32 static_coefficient; - s32 ts[4]; - struct thermal_zone_device *ddr_tz; - unsigned int touchboostpulse_duration_val; u64 touchboostpulse_endtime; @@ -177,14 +169,13 @@ struct rockchip_dmcfreq { static struct pm_qos_request pm_qos; -static int rockchip_dmcfreq_opp_helper(struct dev_pm_set_opp_data *data); +static int rockchip_dmcfreq_check_rate_volt(struct monitor_dev_info *info); static struct monitor_dev_profile dmc_mdevp = { .type = MONITOR_TYPE_DEV, .low_temp_adjust = rockchip_monitor_dev_low_temp_adjust, .high_temp_adjust = rockchip_monitor_dev_high_temp_adjust, - .update_volt = rockchip_monitor_check_rate_volt, - .set_opp = rockchip_dmcfreq_opp_helper, + .check_rate_volt = rockchip_dmcfreq_check_rate_volt, }; static inline unsigned long is_dualview(unsigned long status) @@ -380,30 +371,41 @@ static int rockchip_dmcfreq_set_volt(struct device *dev, struct regulator *reg, return ret; } -static int rockchip_dmcfreq_opp_helper(struct dev_pm_set_opp_data *data) +static int rockchip_dmcfreq_opp_set_rate(struct device *dev, + struct rockchip_dmcfreq *dmcfreq, + unsigned long *freq) { - struct dev_pm_opp_supply *old_supply_vdd = &data->old_opp.supplies[0]; - struct dev_pm_opp_supply *new_supply_vdd = &data->new_opp.supplies[0]; - struct regulator *vdd_reg = data->regulators[0]; - struct dev_pm_opp_supply *old_supply_mem; - struct dev_pm_opp_supply *new_supply_mem; - struct regulator *mem_reg; - struct device *dev = data->dev; - struct clk *clk = data->clk; - struct rockchip_dmcfreq *dmcfreq = dev_get_drvdata(dev); + struct rockchip_opp_info *opp_info = &dmcfreq->opp_info; + unsigned int reg_count = opp_info->regulator_count; + struct regulator *vdd_reg = NULL; + struct regulator *mem_reg = NULL; + struct clk *clk = opp_info->clk; + struct dev_pm_opp *opp; + struct dev_pm_opp_supply supplies[2]; + unsigned long old_freq = dmcfreq->rate; + unsigned long new_freq; + int old_volt = dmcfreq->volt; + int old_volt_mem = dmcfreq->mem_volt; struct cpufreq_policy *policy; - unsigned long old_freq = data->old_opp.rate; - unsigned long freq = data->new_opp.rate; - unsigned int reg_count = data->regulator_count; bool is_cpufreq_changed = false; unsigned int cpu_cur, cpufreq_cur; int ret = 0; - if (reg_count > 1) { - old_supply_mem = &data->old_opp.supplies[1]; - new_supply_mem = &data->new_opp.supplies[1]; - mem_reg = data->regulators[1]; + vdd_reg = opp_info->regulators[0]; + if (reg_count > 1) + mem_reg = opp_info->regulators[1]; + + opp = dev_pm_opp_find_freq_ceil(dev, freq); + if (IS_ERR(opp)) { + opp = dev_pm_opp_find_freq_floor(dev, freq); + if (IS_ERR(opp)) + return PTR_ERR(opp); } + new_freq = *freq; + ret = dev_pm_opp_get_supplies(opp, supplies); + if (ret) + return ret; + dev_pm_opp_put(opp); /* * We need to prevent cpu hotplug from happening while a dmc freq rate @@ -426,7 +428,7 @@ static int rockchip_dmcfreq_opp_helper(struct dev_pm_set_opp_data *data) if (!policy) { dev_err(dev, "cpu%d policy NULL\n", cpu_cur); ret = -EINVAL; - goto cpufreq; + goto cpus_unlock; } down_write(&policy->rwsem); cpufreq_cur = cpufreq_quick_get(cpu_cur); @@ -447,18 +449,17 @@ static int rockchip_dmcfreq_opp_helper(struct dev_pm_set_opp_data *data) } /* Scaling up? Scale voltage before frequency */ - if (freq >= old_freq) { + if (new_freq >= old_freq) { if (reg_count > 1) { ret = rockchip_dmcfreq_set_volt(dev, mem_reg, - new_supply_mem, "mem"); + &supplies[1], "mem"); if (ret) goto restore_voltage; } - ret = rockchip_dmcfreq_set_volt(dev, vdd_reg, new_supply_vdd, - "vdd"); + ret = rockchip_dmcfreq_set_volt(dev, vdd_reg, &supplies[0], "vdd"); if (ret) goto restore_voltage; - if (freq == old_freq) + if (new_freq == old_freq) goto out; } @@ -471,7 +472,7 @@ static int rockchip_dmcfreq_opp_helper(struct dev_pm_set_opp_data *data) */ while (!rockchip_dmcfreq_write_trylock()) cond_resched(); - dev_dbg(dev, "%lu Hz --> %lu Hz\n", old_freq, freq); + dev_dbg(dev, "%lu Hz --> %lu Hz\n", old_freq, new_freq); if (dmcfreq->set_rate_params) { dmcfreq->set_rate_params->lcdc_type = rk_drm_get_lcdc_type(); @@ -480,9 +481,9 @@ static int rockchip_dmcfreq_opp_helper(struct dev_pm_set_opp_data *data) } if (dmcfreq->is_set_rate_direct) - ret = rockchip_ddr_set_rate(freq); + ret = rockchip_ddr_set_rate(new_freq); else - ret = clk_set_rate(clk, freq); + ret = clk_set_rate(clk, new_freq); rockchip_dmcfreq_write_unlock(); if (ret) { @@ -500,45 +501,45 @@ static int rockchip_dmcfreq_opp_helper(struct dev_pm_set_opp_data *data) dmcfreq->rate = clk_get_rate(clk); /* If get the incorrect rate, set voltage to old value. */ - if (dmcfreq->rate != freq) { + if (dmcfreq->rate != new_freq) { dev_err(dev, "Get wrong frequency, Request %lu, Current %lu\n", - freq, dmcfreq->rate); + new_freq, dmcfreq->rate); ret = -EINVAL; goto restore_voltage; } /* Scaling down? Scale voltage after frequency */ - if (freq < old_freq) { - ret = rockchip_dmcfreq_set_volt(dev, vdd_reg, new_supply_vdd, + if (new_freq < old_freq) { + ret = rockchip_dmcfreq_set_volt(dev, vdd_reg, &supplies[0], "vdd"); if (ret) goto restore_freq; if (reg_count > 1) { ret = rockchip_dmcfreq_set_volt(dev, mem_reg, - new_supply_mem, "mem"); + &supplies[1], "mem"); if (ret) goto restore_freq; } } - dmcfreq->volt = new_supply_vdd->u_volt; + dmcfreq->volt = supplies[0].u_volt; if (reg_count > 1) - dmcfreq->mem_volt = new_supply_mem->u_volt; + dmcfreq->mem_volt = supplies[1].u_volt; goto out; restore_freq: if (dmcfreq->is_set_rate_direct) - ret = rockchip_ddr_set_rate(freq); + ret = rockchip_ddr_set_rate(new_freq); else - ret = clk_set_rate(clk, freq); + ret = clk_set_rate(clk, new_freq); if (ret) dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n", __func__, old_freq); restore_voltage: - if (reg_count > 1 && old_supply_mem->u_volt) - rockchip_dmcfreq_set_volt(dev, mem_reg, old_supply_mem, "mem"); - if (old_supply_vdd->u_volt) - rockchip_dmcfreq_set_volt(dev, vdd_reg, old_supply_vdd, "vdd"); + if (reg_count > 1 && old_volt_mem) + regulator_set_voltage(mem_reg, old_volt_mem, INT_MAX); + if (old_volt) + regulator_set_voltage(vdd_reg, old_volt, INT_MAX); out: if (dmcfreq->min_cpu_freq) { if (is_cpufreq_changed) @@ -547,39 +548,49 @@ out: up_write(&policy->rwsem); cpufreq_cpu_put(policy); } -cpufreq: +cpus_unlock: cpus_read_unlock(); return ret; } +static int rockchip_dmcfreq_check_rate_volt(struct monitor_dev_info *info) +{ + struct device *dev = info->dev; + struct rockchip_dmcfreq *dmcfreq = dev_get_drvdata(dev); + struct rockchip_opp_info *opp_info = &dmcfreq->opp_info; + unsigned long cur_freq = dmcfreq->rate; + + rockchip_opp_dvfs_lock(opp_info); + rockchip_dmcfreq_opp_set_rate(dev, dmcfreq, &cur_freq); + opp_info->is_rate_volt_checked = true; + rockchip_opp_dvfs_unlock(opp_info); + + return 0; +} + static int rockchip_dmcfreq_target(struct device *dev, unsigned long *freq, u32 flags) { struct rockchip_dmcfreq *dmcfreq = dev_get_drvdata(dev); + struct rockchip_opp_info *opp_info = &dmcfreq->opp_info; struct devfreq *devfreq; - struct dev_pm_opp *opp; int ret = 0; - if (!dmc_mdevp.is_checked) + if (!opp_info->is_rate_volt_checked) return -EINVAL; - opp = devfreq_recommended_opp(dev, freq, flags); - if (IS_ERR(opp)) { - dev_err(dev, "Failed to find opp for %lu Hz\n", *freq); - return PTR_ERR(opp); - } - dev_pm_opp_put(opp); - - rockchip_monitor_volt_adjust_lock(dmcfreq->mdev_info); - ret = dev_pm_opp_set_rate(dev, *freq); - if (!ret) { - if (dmcfreq->info.devfreq) { - devfreq = dmcfreq->info.devfreq; - devfreq->last_status.current_frequency = *freq; + rockchip_opp_dvfs_lock(opp_info); + if (dmcfreq->rate != *freq) { + ret = rockchip_dmcfreq_opp_set_rate(dev, dmcfreq, freq); + if (!ret) { + if (dmcfreq->info.devfreq) { + devfreq = dmcfreq->info.devfreq; + devfreq->last_status.current_frequency = *freq; + } } } - rockchip_monitor_volt_adjust_unlock(dmcfreq->mdev_info); + rockchip_opp_dvfs_unlock(opp_info); return ret; } @@ -588,6 +599,7 @@ static int rockchip_dmcfreq_get_dev_status(struct device *dev, struct devfreq_dev_status *stat) { struct rockchip_dmcfreq *dmcfreq = dev_get_drvdata(dev); + struct rockchip_opp_info *opp_info = &dmcfreq->opp_info; struct devfreq_event_data edata; int i, ret = 0; @@ -598,7 +610,7 @@ static int rockchip_dmcfreq_get_dev_status(struct device *dev, * RK3588 platform may crash if the CPU and MCU access the DFI/DMC * registers at same time. */ - rockchip_monitor_volt_adjust_lock(dmcfreq->mdev_info); + rockchip_opp_dvfs_lock(opp_info); for (i = 0; i < dmcfreq->edev_count; i++) { ret = devfreq_event_get_event(dmcfreq->edev[i], &edata); if (ret < 0) { @@ -615,7 +627,7 @@ static int rockchip_dmcfreq_get_dev_status(struct device *dev, } out: - rockchip_monitor_volt_adjust_unlock(dmcfreq->mdev_info); + rockchip_opp_dvfs_unlock(opp_info); return ret; } @@ -635,9 +647,9 @@ static struct devfreq_dev_profile rockchip_devfreq_dmc_profile = { .target = rockchip_dmcfreq_target, .get_dev_status = rockchip_dmcfreq_get_dev_status, .get_cur_freq = rockchip_dmcfreq_get_cur_freq, + .is_cooling_device = true, }; - static inline void reset_last_status(struct devfreq *devfreq) { devfreq->last_status.total_time = 1; @@ -1296,9 +1308,9 @@ rockchip_dmcfreq_adjust_opp_table(struct rockchip_dmcfreq *dmcfreq) if (!opp->available) continue; - freq_table[i].freq = opp->rate; + freq_table[i].freq = opp->rates[0]; freq_table[i].supplies[0] = opp->supplies[0]; - if (dmcfreq->regulator_count > 1) + if (dmcfreq->opp_info.regulator_count > 1) freq_table[i].supplies[1] = opp->supplies[1]; i++; @@ -1316,9 +1328,9 @@ rockchip_dmcfreq_adjust_opp_table(struct rockchip_dmcfreq *dmcfreq) for (j = 0; j < count; j++) { if (dmcfreq->freq_info_rate[i] <= freq_table[j].freq) { - opp->rate = dmcfreq->freq_info_rate[i]; + opp->rates[0] = dmcfreq->freq_info_rate[i]; opp->supplies[0] = freq_table[j].supplies[0]; - if (dmcfreq->regulator_count > 1) + if (dmcfreq->opp_info.regulator_count > 1) opp->supplies[1] = freq_table[j].supplies[1]; break; @@ -1989,7 +2001,7 @@ static __maybe_unused int rk3588_dmc_init(struct platform_device *pdev, return PTR_ERR(opp); } dmcfreq->sleep_volt = opp->supplies[0].u_volt; - if (dmcfreq->regulator_count > 1) + if (dmcfreq->opp_info.regulator_count > 1) dmcfreq->sleep_mem_volt = opp->supplies[1].u_volt; dev_pm_opp_put(opp); @@ -2569,7 +2581,7 @@ static int rockchip_dmcfreq_panic_notifier(struct notifier_block *nb, container_of(nb, struct rockchip_dmcfreq, panic_nb); struct device *dev = dmcfreq->dev; - if (dmcfreq->regulator_count == 1) + if (dmcfreq->opp_info.regulator_count == 1) dev_info(dev, "cur_freq: %lu Hz, volt: %lu uV\n", dmcfreq->rate, dmcfreq->volt); else @@ -2934,66 +2946,6 @@ static int rockchip_dmcfreq_get_event(struct rockchip_dmcfreq *dmcfreq) return 0; } -static int rockchip_dmcfreq_power_control(struct rockchip_dmcfreq *dmcfreq) -{ - struct device *dev = dmcfreq->dev; - struct device_node *np = dev->of_node; - struct opp_table *opp_table = NULL, *reg_opp_table = NULL; - const char * const reg_names[] = {"center", "mem"}; - int ret = 0; - - if (of_find_property(np, "mem-supply", NULL)) - dmcfreq->regulator_count = 2; - else - dmcfreq->regulator_count = 1; - reg_opp_table = dev_pm_opp_set_regulators(dev, reg_names, - dmcfreq->regulator_count); - if (IS_ERR(reg_opp_table)) { - dev_err(dev, "failed to set regulators\n"); - return PTR_ERR(reg_opp_table); - } - opp_table = dev_pm_opp_register_set_opp_helper(dev, rockchip_dmcfreq_opp_helper); - if (IS_ERR(opp_table)) { - dev_err(dev, "failed to set opp helper\n"); - ret = PTR_ERR(opp_table); - goto reg_opp_table; - } - - dmcfreq->vdd_center = devm_regulator_get_optional(dev, "center"); - if (IS_ERR(dmcfreq->vdd_center)) { - dev_err(dev, "Cannot get the regulator \"center\"\n"); - ret = PTR_ERR(dmcfreq->vdd_center); - goto opp_table; - } - if (dmcfreq->regulator_count > 1) { - dmcfreq->mem_reg = devm_regulator_get_optional(dev, "mem"); - if (IS_ERR(dmcfreq->mem_reg)) { - dev_err(dev, "Cannot get the regulator \"mem\"\n"); - ret = PTR_ERR(dmcfreq->mem_reg); - goto opp_table; - } - } - - dmcfreq->dmc_clk = devm_clk_get(dev, "dmc_clk"); - if (IS_ERR(dmcfreq->dmc_clk)) { - dev_err(dev, "Cannot get the clk dmc_clk. If using SCMI, trusted firmware need update to V1.01 and above.\n"); - ret = PTR_ERR(dmcfreq->dmc_clk); - goto opp_table; - } - dmcfreq->rate = clk_get_rate(dmcfreq->dmc_clk); - - return 0; - -opp_table: - if (opp_table) - dev_pm_opp_unregister_set_opp_helper(opp_table); -reg_opp_table: - if (reg_opp_table) - dev_pm_opp_put_regulators(reg_opp_table); - - return ret; -} - static int rockchip_dmcfreq_dmc_init(struct platform_device *pdev, struct rockchip_dmcfreq *dmcfreq) { @@ -3067,8 +3019,10 @@ static int rockchip_dmcfreq_add_devfreq(struct rockchip_dmcfreq *dmcfreq) struct device *dev = dmcfreq->dev; struct dev_pm_opp *opp; struct devfreq *devfreq; - unsigned long opp_rate = dmcfreq->rate; + unsigned long opp_rate; + dmcfreq->rate = clk_get_rate(dmcfreq->opp_info.clk); + opp_rate = dmcfreq->rate; opp = devfreq_recommended_opp(dev, &opp_rate, 0); if (IS_ERR(opp)) { dev_err(dev, "Failed to find opp for %lu Hz\n", opp_rate); @@ -3117,12 +3071,14 @@ static void rockchip_dmcfreq_register_notifier(struct rockchip_dmcfreq *dmcfreq) dev_err(dmcfreq->dev, "failed to register panic nb\n"); dmc_mdevp.data = dmcfreq->info.devfreq; + dmc_mdevp.opp_info = &dmcfreq->opp_info; dmcfreq->mdev_info = rockchip_system_monitor_register(dmcfreq->dev, &dmc_mdevp); if (IS_ERR(dmcfreq->mdev_info)) { dev_dbg(dmcfreq->dev, "without without system monitor\n"); dmcfreq->mdev_info = NULL; } + dmcfreq->opp_info.is_rate_volt_checked = true; } static void rockchip_dmcfreq_add_interface(struct rockchip_dmcfreq *dmcfreq) @@ -3249,125 +3205,6 @@ static void rockchip_dmcfreq_boost_init(struct rockchip_dmcfreq *dmcfreq) dev_err(dmcfreq->dev, "failed to register input handler\n"); } -static unsigned long model_static_power(struct devfreq *devfreq, - unsigned long voltage) -{ - struct device *dev = devfreq->dev.parent; - struct rockchip_dmcfreq *dmcfreq = dev_get_drvdata(dev); - - int temperature; - unsigned long temp; - unsigned long temp_squared, temp_cubed, temp_scaling_factor; - const unsigned long voltage_cubed = (voltage * voltage * voltage) >> 10; - - if (!IS_ERR_OR_NULL(dmcfreq->ddr_tz) && dmcfreq->ddr_tz->ops->get_temp) { - int ret; - - ret = - dmcfreq->ddr_tz->ops->get_temp(dmcfreq->ddr_tz, - &temperature); - if (ret) { - dev_warn_ratelimited(dev, - "failed to read temp for ddr thermal zone: %d\n", - ret); - temperature = FALLBACK_STATIC_TEMPERATURE; - } - } else { - temperature = FALLBACK_STATIC_TEMPERATURE; - } - - /* - * Calculate the temperature scaling factor. To be applied to the - * voltage scaled power. - */ - temp = temperature / 1000; - temp_squared = temp * temp; - temp_cubed = temp_squared * temp; - temp_scaling_factor = (dmcfreq->ts[3] * temp_cubed) - + (dmcfreq->ts[2] * temp_squared) - + (dmcfreq->ts[1] * temp) - + dmcfreq->ts[0]; - - return (((dmcfreq->static_coefficient * voltage_cubed) >> 20) - * temp_scaling_factor) / 1000000; -} - -static struct devfreq_cooling_power ddr_cooling_power_data = { - .get_static_power = model_static_power, - .dyn_power_coeff = 120, -}; - -static int ddr_power_model_simple_init(struct rockchip_dmcfreq *dmcfreq) -{ - struct device_node *power_model_node; - const char *tz_name; - u32 temp; - - power_model_node = of_get_child_by_name(dmcfreq->dev->of_node, - "ddr_power_model"); - if (!power_model_node) { - dev_err(dmcfreq->dev, "could not find power_model node\n"); - return -ENODEV; - } - - if (of_property_read_string(power_model_node, "thermal-zone", &tz_name)) { - dev_err(dmcfreq->dev, "ts in power_model not available\n"); - return -EINVAL; - } - - dmcfreq->ddr_tz = thermal_zone_get_zone_by_name(tz_name); - if (IS_ERR(dmcfreq->ddr_tz)) { - pr_warn_ratelimited - ("Error getting ddr thermal zone (%ld), not yet ready?\n", - PTR_ERR(dmcfreq->ddr_tz)); - dmcfreq->ddr_tz = NULL; - - return -EPROBE_DEFER; - } - - if (of_property_read_u32(power_model_node, "static-power-coefficient", - &dmcfreq->static_coefficient)) { - dev_err(dmcfreq->dev, - "static-power-coefficient not available\n"); - return -EINVAL; - } - if (of_property_read_u32(power_model_node, "dynamic-power-coefficient", - &temp)) { - dev_err(dmcfreq->dev, - "dynamic-power-coefficient not available\n"); - return -EINVAL; - } - ddr_cooling_power_data.dyn_power_coeff = (unsigned long)temp; - - if (of_property_read_u32_array - (power_model_node, "ts", (u32 *)dmcfreq->ts, 4)) { - dev_err(dmcfreq->dev, "ts in power_model not available\n"); - return -EINVAL; - } - - return 0; -} - -static void -rockchip_dmcfreq_register_cooling_device(struct rockchip_dmcfreq *dmcfreq) -{ - int ret; - - ret = ddr_power_model_simple_init(dmcfreq); - if (ret) - return; - dmcfreq->devfreq_cooling = - of_devfreq_cooling_register_power(dmcfreq->dev->of_node, - dmcfreq->info.devfreq, - &ddr_cooling_power_data); - if (IS_ERR(dmcfreq->devfreq_cooling)) { - ret = PTR_ERR(dmcfreq->devfreq_cooling); - dev_err(dmcfreq->dev, - "Failed to register cooling device (%d)\n", - ret); - } -} - static int rockchip_dmcfreq_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -3387,11 +3224,7 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev) if (ret) return ret; - ret = rockchip_dmcfreq_power_control(data); - if (ret) - return ret; - - ret = rockchip_init_opp_table(dev, NULL, "ddr_leakage", "center"); + ret = rockchip_init_opp_table(dev, &data->opp_info, "dmc_clk", "center"); if (ret) return ret; @@ -3427,7 +3260,6 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev) rockchip_dmcfreq_add_interface(data); rockchip_dmcfreq_boost_init(data); rockchip_dmcfreq_vop_bandwidth_init(&data->info); - rockchip_dmcfreq_register_cooling_device(data); rockchip_set_system_status(SYS_STATUS_NORMAL); @@ -3437,6 +3269,9 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev) static __maybe_unused int rockchip_dmcfreq_suspend(struct device *dev) { struct rockchip_dmcfreq *dmcfreq = dev_get_drvdata(dev); + struct rockchip_opp_info *opp_info; + struct regulator *vdd_reg = NULL; + struct regulator *mem_reg = NULL; int ret = 0; if (!dmcfreq) @@ -3454,20 +3289,26 @@ static __maybe_unused int rockchip_dmcfreq_suspend(struct device *dev) } } + opp_info = &dmcfreq->opp_info; + if (!opp_info->regulators) + return 0; + vdd_reg = opp_info->regulators[0]; + if (opp_info->regulator_count > 1) + mem_reg = opp_info->regulators[1]; + /* set voltage to sleep_volt if need */ - if (dmcfreq->sleep_volt && dmcfreq->sleep_volt != dmcfreq->volt) { - ret = regulator_set_voltage(dmcfreq->vdd_center, - dmcfreq->sleep_volt, INT_MAX); + if (vdd_reg && dmcfreq->sleep_volt && + dmcfreq->sleep_volt != dmcfreq->volt) { + ret = regulator_set_voltage(vdd_reg, dmcfreq->sleep_volt, INT_MAX); if (ret) { dev_err(dev, "Cannot set vdd voltage %lu uV\n", dmcfreq->sleep_volt); return ret; } } - if (dmcfreq->sleep_mem_volt && + if (mem_reg && dmcfreq->sleep_mem_volt && dmcfreq->sleep_mem_volt != dmcfreq->mem_volt) { - ret = regulator_set_voltage(dmcfreq->mem_reg, - dmcfreq->sleep_mem_volt, INT_MAX); + ret = regulator_set_voltage(mem_reg, dmcfreq->sleep_mem_volt, INT_MAX); if (ret) { dev_err(dev, "Cannot set mem voltage %lu uV\n", dmcfreq->sleep_mem_volt); @@ -3481,29 +3322,40 @@ static __maybe_unused int rockchip_dmcfreq_suspend(struct device *dev) static __maybe_unused int rockchip_dmcfreq_resume(struct device *dev) { struct rockchip_dmcfreq *dmcfreq = dev_get_drvdata(dev); + struct rockchip_opp_info *opp_info; + struct regulator *vdd_reg = NULL; + struct regulator *mem_reg = NULL; int ret = 0; if (!dmcfreq) return 0; - /* restore voltage if it is sleep_volt */ - if (dmcfreq->sleep_volt && dmcfreq->sleep_volt != dmcfreq->volt) { - ret = regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt, - INT_MAX); - if (ret) { - dev_err(dev, "Cannot set vdd voltage %lu uV\n", - dmcfreq->volt); - return ret; + opp_info = &dmcfreq->opp_info; + if (opp_info->regulators) { + vdd_reg = opp_info->regulators[0]; + if (opp_info->regulator_count > 1) + mem_reg = opp_info->regulators[1]; + + /* restore voltage if it is sleep_volt */ + if (mem_reg && dmcfreq->sleep_volt && + dmcfreq->sleep_volt != dmcfreq->volt) { + ret = regulator_set_voltage(vdd_reg, dmcfreq->volt, + INT_MAX); + if (ret) { + dev_err(dev, "Cannot set vdd voltage %lu uV\n", + dmcfreq->volt); + return ret; + } } - } - if (dmcfreq->sleep_mem_volt && - dmcfreq->sleep_mem_volt != dmcfreq->mem_volt) { - ret = regulator_set_voltage(dmcfreq->mem_reg, dmcfreq->mem_volt, - INT_MAX); - if (ret) { - dev_err(dev, "Cannot set mem voltage %lu uV\n", - dmcfreq->mem_volt); - return ret; + if (vdd_reg && dmcfreq->sleep_mem_volt && + dmcfreq->sleep_mem_volt != dmcfreq->mem_volt) { + ret = regulator_set_voltage(mem_reg, dmcfreq->mem_volt, + INT_MAX); + if (ret) { + dev_err(dev, "Cannot set mem voltage %lu uV\n", + dmcfreq->mem_volt); + return ret; + } } }