PM / OPP: Update voltage in case freq == old_freq

commit c5c2a97b upstream.

This commit fixes a rare but possible case when the clk rate is updated
without update of the regulator voltage.

At boot up, CPUfreq checks if the system is running at the right freq. This
is a sanity check in case a bootloader set clk rate that is outside of freq
table present with cpufreq core. In such cases system can be unstable so
better to change it to a freq that is preset in freq-table.

The CPUfreq takes next freq that is >= policy->cur and this is our
target_freq that needs to be set now.

dev_pm_opp_set_rate(dev, target_freq) checks the target_freq and the
old_freq (a current rate). If these are equal it returns early. If not,
it searches for OPP (old_opp) that fits best to old_freq (not listed in
the table) and updates old_freq (!).

Here, we can end up with old_freq = old_opp.rate = target_freq, which
is not handled in _generic_set_opp_regulator(). It's supposed to update
voltage only when freq > old_freq  || freq > old_freq.

if (freq > old_freq) {
		ret = _set_opp_voltage(dev, reg, new_supply);
[...]
if (freq < old_freq) {
		ret = _set_opp_voltage(dev, reg, new_supply);
		if (ret)

It results in, no voltage update while clk rate is updated.

Example:
freq-table = {
	1000MHz   1.15V
	 666MHZ   1.10V
	 333MHz   1.05V
}
boot-up-freq        = 800MHz   # not listed in freq-table
freq = target_freq  = 1GHz
old_freq            = 800Mhz
old_opp = _find_freq_ceil(opp_table, &old_freq);  #(old_freq is modified!)
old_freq            = 1GHz

Fixes: 6a0712f6 ("PM / OPP: Add dev_pm_opp_set_rate()")
Cc: 4.6+ <stable@vger.kernel.org> # v4.6+
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@gmail.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Chen-Yu Tsai (Moxa) <wens@csie.org>
Signed-off-by: Nobuhiro Iwamatsu (CIP) <nobuhiro1.iwamatsu@toshiba.co.jp>
23 jobs for ci/iwamatsu/linux-4.4.y-cip-rc in 172 minutes and 11 seconds (queued for 4 seconds)
Status Name Job ID Coverage
  Build
passed build:arm_cip_bbb_defconfig #630285260

00:09:30

passed build:arm_hitachi_omap_defconfig #630285261

00:11:42

passed build:arm_moxa_mxc_defconfig #630285262

00:12:26

passed build:arm_renesas_shmobile_defconfig #630285263

00:07:24

passed build:arm_siemens_am335x-axm2_defconfig #630285264

00:09:33

passed build:arm_siemens_am335x-draco_defconfig #630285265

00:09:54

passed build:arm_siemens_am335x-dxr2_defconfig #630285266

00:08:34

passed build:arm_siemens_am335x-etamin_defconfig #630285267

00:09:29

passed build:arm_siemens_am57xx-pxm3.config #630285268

00:08:37

passed build:arm_siemens_dcu2.config #630285270

00:09:02

passed build:arm_siemens_imx6_defconfig #630285271

00:09:21

passed build:arm_toshiba_tegra_defconfig #630285273

00:06:04

passed build:arm_toshiba_zynq_defconfig #630285275

00:08:26

passed build:x86_cip_qemu_defconfig #630285277

00:09:46

passed build:x86_plathome_obsvx1.config #630285278

00:11:26

passed build:x86_siemens_iot2000.config #630285279

00:09:30

passed build:x86_siemens_server_defconfig #630285280

00:07:54

passed build:x86_toshiba_defconfig #630285281

00:06:59

 
  Test
passed test:arm_renesas_shmobile_defconfig #630285282
small

00:10:02

passed test:arm_renesas_shmobile_defconfig_release #630524345
small

01:49:15

passed test:x86_cip_qemu_defconfig #630285283
small

00:08:18

passed test:x86_cip_qemu_defconfig_release #630285285
small

00:52:54

failed test:arm_renesas_shmobile_defconfig_release #630285284
small

03:01:10