From b8a2dcfd13b0a41e40f232b24eb7b1d7dae35df2 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 28 Nov 2016 10:07:06 +0800 Subject: [PATCH] devfreq: rockchip: avoid DDR voltage domain keeping the initial voltage If there is only one opp whose frequency is equal to the initial value in opp table list, the DDR voltage domain will keep the initial voltage, it may be too large. Change-Id: I9e75d54bdc7d909baa72667821ff30beb4d62e27 Signed-off-by: Finley Xiao --- drivers/devfreq/rk3399_dmc.c | 47 +++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c index 59f4e4b09761..c178b808ca80 100644 --- a/drivers/devfreq/rk3399_dmc.c +++ b/drivers/devfreq/rk3399_dmc.c @@ -81,7 +81,6 @@ struct rk3399_dmcfreq { struct regulator *vdd_center; unsigned long rate, target_rate; unsigned long volt, target_volt; - struct dev_pm_opp *curr_opp; }; static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, @@ -90,7 +89,7 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(dev); struct dev_pm_opp *opp; unsigned long old_clk_rate = dmcfreq->rate; - unsigned long target_volt, target_rate; + unsigned long temp_rate, target_volt, target_rate; int err; rcu_read_lock(); @@ -100,16 +99,26 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, return PTR_ERR(opp); } - target_rate = dev_pm_opp_get_freq(opp); + temp_rate = dev_pm_opp_get_freq(opp); + target_rate = clk_round_rate(dmcfreq->dmc_clk, temp_rate); + if ((long)target_rate <= 0) + target_rate = temp_rate; target_volt = dev_pm_opp_get_voltage(opp); - dmcfreq->rate = dev_pm_opp_get_freq(dmcfreq->curr_opp); - dmcfreq->volt = dev_pm_opp_get_voltage(dmcfreq->curr_opp); - rcu_read_unlock(); - if (dmcfreq->rate == target_rate) - return 0; + if (dmcfreq->rate == target_rate) { + if (dmcfreq->volt == target_volt) + return 0; + err = regulator_set_voltage(dmcfreq->vdd_center, target_volt, + target_volt); + if (err) { + dev_err(dev, "Cannot to set voltage %lu uV\n", + target_volt); + goto out; + } + } + mutex_lock(&dmcfreq->lock); @@ -151,13 +160,16 @@ static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq, regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt, dmcfreq->volt); goto out; - } else if (old_clk_rate > target_rate) + } else if (old_clk_rate > target_rate) { err = regulator_set_voltage(dmcfreq->vdd_center, target_volt, target_volt); - if (err) - dev_err(dev, "Cannot to set vol %lu uV\n", target_volt); + if (err) { + dev_err(dev, "Cannot to set vol %lu uV\n", target_volt); + goto out; + } + } - dmcfreq->curr_opp = opp; + dmcfreq->volt = target_volt; out: mutex_unlock(&dmcfreq->lock); return err; @@ -372,7 +384,6 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev) struct rk3399_dmcfreq *data; int ret, index, size; uint32_t *timing; - struct dev_pm_opp *opp; struct devfreq_dev_profile *devp = &rk3399_devfreq_dmc_profile; data = devm_kzalloc(dev, sizeof(struct rk3399_dmcfreq), GFP_KERNEL); @@ -447,16 +458,8 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev) &data->ondemand_data.downdifferential); data->rate = clk_get_rate(data->dmc_clk); + data->volt = regulator_get_voltage(data->vdd_center); - rcu_read_lock(); - opp = devfreq_recommended_opp(dev, &data->rate, 0); - if (IS_ERR(opp)) { - rcu_read_unlock(); - return PTR_ERR(opp); - } - rcu_read_unlock(); - - data->curr_opp = opp; devp->initial_freq = data->rate; data->devfreq = devfreq_add_device(dev, devp, "simple_ondemand", -- 2.34.1