Clock rates are stored in an unsigned long field, but ->round_rate()
(which returns a rounded rate from a requested one) returns a long
value (errors are reported using negative error codes), which can lead
to long overflow if the clock rate exceed 2Ghz.

Change ->round_rate() prototype to return 0 or an error code, and pass the
requested rate as a pointer so that it can be adjusted depending on
hardware capabilities.

Signed-off-by: Boris Brezillon <boris.brezil...@free-electrons.com>
Tested-by: Heiko Stuebner <he...@sntech.de>
Tested-by: Mikko Perttunen <mikko.perttu...@kapsi.fi>
Reviewed-by: Heiko Stuebner <he...@sntech.de>
---
CC: Jonathan Corbet <cor...@lwn.net>
CC: Shawn Guo <shawn....@linaro.org>
CC: ascha Hauer <ker...@pengutronix.de>
CC: David Brown <dav...@codeaurora.org>
CC: Daniel Walker <dwal...@fifo99.com>
CC: Bryan Huntsman <bry...@codeaurora.org>
CC: Tony Lindgren <t...@atomide.com>
CC: Paul Walmsley <p...@pwsan.com>
CC: Liviu Dudau <liviu.du...@arm.com>
CC: Sudeep Holla <sudeep.ho...@arm.com>
CC: Lorenzo Pieralisi <lorenzo.pieral...@arm.com>
CC: Ralf Baechle <r...@linux-mips.org>
CC: Max Filippov <jcmvb...@gmail.com>
CC: Heiko Stuebner <he...@sntech.de>
CC: Sylwester Nawrocki <s.nawro...@samsung.com> 
CC: Tomasz Figa <tomasz.f...@gmail.com>
CC: Barry Song <bao...@kernel.org>
CC: Viresh Kumar <viresh.li...@gmail.com>
CC: "Emilio L??pez" <emi...@elopez.com.ar>
CC: Maxime Ripard <maxime.rip...@free-electrons.com>
CC: Peter De Schrijver <pdeschrij...@nvidia.com>
CC: Prashant Gaikwad <pgaik...@nvidia.com>
CC: Stephen Warren <swar...@wwwdotorg.org>
CC: Thierry Reding <thierry.red...@gmail.com>
CC: Alexandre Courbot <gnu...@gmail.com>
CC: Tero Kristo <t-kri...@ti.com>
CC: Ulf Hansson <ulf.hans...@linaro.org>
CC: Michal Simek <michal.si...@xilinx.com>
CC: Philipp Zabel <p.za...@pengutronix.de>
CC: linux-...@vger.kernel.org
CC: linux-kernel@vger.kernel.org
CC: linux-arm-ker...@lists.infradead.org
CC: linux-arm-...@vger.kernel.org
CC: linux-o...@vger.kernel.org
CC: linux-m...@linux-mips.org
CC: patc...@opensource.wolfsonmicro.com
CC: linux-rockc...@lists.infradead.org
CC: linux-samsung-...@vger.kernel.org
CC: spear-de...@list.st.com
CC: linux-te...@vger.kernel.org
CC: dri-de...@lists.freedesktop.org
CC: linux-me...@vger.kernel.org
CC: rtc-li...@googlegroups.com

 Documentation/clk.txt                        |  4 +-
 arch/arm/mach-imx/clk-busy.c                 |  2 +-
 arch/arm/mach-imx/clk-cpu.c                  | 12 +++-
 arch/arm/mach-imx/clk-fixup-div.c            |  2 +-
 arch/arm/mach-imx/clk-pfd.c                  | 11 ++--
 arch/arm/mach-imx/clk-pllv2.c                |  8 ++-
 arch/arm/mach-imx/clk-pllv3.c                | 46 +++++++------
 arch/arm/mach-msm/clock-pcom.c               |  4 +-
 arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c | 13 ++--
 arch/arm/mach-omap2/clkt_clksel.c            |  6 +-
 arch/arm/mach-omap2/clkt_dpll.c              | 21 +++---
 arch/arm/mach-omap2/clock.h                  |  4 +-
 arch/arm/mach-omap2/dpll3xxx.c               | 27 +++++---
 arch/arm/mach-omap2/dpll44xx.c               | 26 +++++---
 arch/arm/mach-vexpress/spc.c                 | 11 +++-
 arch/mips/alchemy/common/clock.c             | 13 ++--
 drivers/clk/at91/clk-h32mx.c                 | 24 ++++---
 drivers/clk/at91/clk-peripheral.c            | 31 +++++----
 drivers/clk/at91/clk-pll.c                   | 14 ++--
 drivers/clk/at91/clk-plldiv.c                | 22 ++++---
 drivers/clk/at91/clk-smd.c                   | 24 ++++---
 drivers/clk/at91/clk-usb.c                   | 16 +++--
 drivers/clk/clk-axi-clkgen.c                 |  5 +-
 drivers/clk/clk-cdce706.c                    | 46 ++++++-------
 drivers/clk/clk-composite.c                  | 23 ++++---
 drivers/clk/clk-divider.c                    | 16 +++--
 drivers/clk/clk-fixed-factor.c               |  7 +-
 drivers/clk/clk-fractional-divider.c         | 16 +++--
 drivers/clk/clk-highbank.c                   | 18 +++---
 drivers/clk/clk-si5351.c                     | 96 ++++++++++++++--------------
 drivers/clk/clk-si570.c                      | 14 ++--
 drivers/clk/clk-u300.c                       | 65 ++++++++++---------
 drivers/clk/clk-vt8500.c                     | 27 ++++----
 drivers/clk/clk-wm831x.c                     | 11 ++--
 drivers/clk/clk-xgene.c                      | 11 ++--
 drivers/clk/clk.c                            | 14 ++--
 drivers/clk/mmp/clk-frac.c                   | 14 ++--
 drivers/clk/mvebu/clk-corediv.c              |  7 +-
 drivers/clk/mvebu/clk-cpu.c                  |  9 +--
 drivers/clk/mxs/clk-div.c                    |  4 +-
 drivers/clk/mxs/clk-frac.c                   | 11 ++--
 drivers/clk/mxs/clk-ref.c                    | 11 ++--
 drivers/clk/qcom/clk-regmap-divider.c        |  4 +-
 drivers/clk/rockchip/clk-pll.c               | 13 ++--
 drivers/clk/samsung/clk-pll.c                | 13 ++--
 drivers/clk/shmobile/clk-div6.c              |  7 +-
 drivers/clk/shmobile/clk-rcar-gen2.c         |  9 +--
 drivers/clk/sirf/clk-common.c                | 18 +++---
 drivers/clk/spear/clk-aux-synth.c            | 10 ++-
 drivers/clk/spear/clk-frac-synth.c           | 10 ++-
 drivers/clk/spear/clk-gpt-synth.c            | 10 ++-
 drivers/clk/spear/clk-vco-pll.c              | 20 ++++--
 drivers/clk/st/clk-flexgen.c                 | 11 ++--
 drivers/clk/st/clkgen-fsyn.c                 | 21 +++---
 drivers/clk/st/clkgen-mux.c                  |  2 +-
 drivers/clk/sunxi/clk-factors.c              | 14 ++--
 drivers/clk/tegra/clk-audio-sync.c           |  8 +--
 drivers/clk/tegra/clk-divider.c              | 19 ++++--
 drivers/clk/tegra/clk-periph.c               |  4 +-
 drivers/clk/tegra/clk-pll.c                  | 39 ++++++-----
 drivers/clk/ti/clk-dra7-atl.c                |  9 +--
 drivers/clk/ti/composite.c                   |  4 +-
 drivers/clk/ti/divider.c                     |  9 +--
 drivers/clk/ux500/clk-prcmu.c                | 13 +++-
 drivers/clk/versatile/clk-icst.c             |  9 +--
 drivers/clk/versatile/clk-vexpress-osc.c     | 12 ++--
 drivers/clk/zynq/pll.c                       |  7 +-
 drivers/gpu/drm/imx/imx-tve.c                | 15 +++--
 drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c     |  7 +-
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_pll.c |  7 +-
 drivers/media/platform/omap3isp/isp.c        |  6 +-
 drivers/rtc/rtc-hym8563.c                    | 14 ++--
 include/linux/clk-provider.h                 |  6 +-
 include/linux/clk/ti.h                       | 12 ++--
 74 files changed, 659 insertions(+), 469 deletions(-)

diff --git a/Documentation/clk.txt b/Documentation/clk.txt
index 0e4f90a..fca8b7a 100644
--- a/Documentation/clk.txt
+++ b/Documentation/clk.txt
@@ -68,8 +68,8 @@ the operations defined in clk.h:
                int             (*is_enabled)(struct clk_hw *hw);
                unsigned long   (*recalc_rate)(struct clk_hw *hw,
                                                unsigned long parent_rate);
-               long            (*round_rate)(struct clk_hw *hw,
-                                               unsigned long rate,
+               int             (*round_rate)(struct clk_hw *hw,
+                                               unsigned long *rate,
                                                unsigned long *parent_rate);
                long            (*determine_rate)(struct clk_hw *hw,
                                                unsigned long rate,
diff --git a/arch/arm/mach-imx/clk-busy.c b/arch/arm/mach-imx/clk-busy.c
index 4bb1bc4..f8c67e9 100644
--- a/arch/arm/mach-imx/clk-busy.c
+++ b/arch/arm/mach-imx/clk-busy.c
@@ -51,7 +51,7 @@ static unsigned long clk_busy_divider_recalc_rate(struct 
clk_hw *hw,
        return busy->div_ops->recalc_rate(&busy->div.hw, parent_rate);
 }
 
-static long clk_busy_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_busy_divider_round_rate(struct clk_hw *hw, unsigned long *rate,
                                        unsigned long *prate)
 {
        struct clk_busy_divider *busy = to_clk_busy_divider(hw);
diff --git a/arch/arm/mach-imx/clk-cpu.c b/arch/arm/mach-imx/clk-cpu.c
index aa1c345..f6af2d8 100644
--- a/arch/arm/mach-imx/clk-cpu.c
+++ b/arch/arm/mach-imx/clk-cpu.c
@@ -34,12 +34,18 @@ static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw,
        return clk_get_rate(cpu->div);
 }
 
-static long clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
-                              unsigned long *prate)
+static int clk_cpu_round_rate(struct clk_hw *hw, unsigned long *rate,
+                             unsigned long *prate)
 {
        struct clk_cpu *cpu = to_clk_cpu(hw);
+       long ret;
 
-       return clk_round_rate(cpu->pll, rate);
+       ret = clk_round_rate(cpu->pll, *rate);
+       if (ret < 0)
+               return ret;
+
+       *rate = ret;
+       return 0;
 }
 
 static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/arch/arm/mach-imx/clk-fixup-div.c 
b/arch/arm/mach-imx/clk-fixup-div.c
index 21db020..c2f4f00 100644
--- a/arch/arm/mach-imx/clk-fixup-div.c
+++ b/arch/arm/mach-imx/clk-fixup-div.c
@@ -48,7 +48,7 @@ static unsigned long clk_fixup_div_recalc_rate(struct clk_hw 
*hw,
        return fixup_div->ops->recalc_rate(&fixup_div->divider.hw, parent_rate);
 }
 
-static long clk_fixup_div_round_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_fixup_div_round_rate(struct clk_hw *hw, unsigned long *rate,
                               unsigned long *prate)
 {
        struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw);
diff --git a/arch/arm/mach-imx/clk-pfd.c b/arch/arm/mach-imx/clk-pfd.c
index 0b0f6f6..449fb7a 100644
--- a/arch/arm/mach-imx/clk-pfd.c
+++ b/arch/arm/mach-imx/clk-pfd.c
@@ -68,14 +68,14 @@ static unsigned long clk_pfd_recalc_rate(struct clk_hw *hw,
        return tmp;
 }
 
-static long clk_pfd_round_rate(struct clk_hw *hw, unsigned long rate,
-                              unsigned long *prate)
+static int clk_pfd_round_rate(struct clk_hw *hw, unsigned long *rate,
+                             unsigned long *prate)
 {
        u64 tmp = *prate;
        u8 frac;
 
-       tmp = tmp * 18 + rate / 2;
-       do_div(tmp, rate);
+       tmp = tmp * 18 + *rate / 2;
+       do_div(tmp, *rate);
        frac = tmp;
        if (frac < 12)
                frac = 12;
@@ -85,7 +85,8 @@ static long clk_pfd_round_rate(struct clk_hw *hw, unsigned 
long rate,
        tmp *= 18;
        do_div(tmp, frac);
 
-       return tmp;
+       *rate = tmp;
+       return 0;
 }
 
 static int clk_pfd_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/arch/arm/mach-imx/clk-pllv2.c b/arch/arm/mach-imx/clk-pllv2.c
index 20889d5..6b48bf5 100644
--- a/arch/arm/mach-imx/clk-pllv2.c
+++ b/arch/arm/mach-imx/clk-pllv2.c
@@ -180,14 +180,16 @@ static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned 
long rate,
        return 0;
 }
 
-static long clk_pllv2_round_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_pllv2_round_rate(struct clk_hw *hw, unsigned long *rate,
                unsigned long *prate)
 {
        u32 dp_op, dp_mfd, dp_mfn;
 
-       __clk_pllv2_set_rate(rate, *prate, &dp_op, &dp_mfd, &dp_mfn);
-       return __clk_pllv2_recalc_rate(*prate, MXC_PLL_DP_CTL_DPDCK0_2_EN,
+       __clk_pllv2_set_rate(*rate, *prate, &dp_op, &dp_mfd, &dp_mfn);
+       *rate = __clk_pllv2_recalc_rate(*prate, MXC_PLL_DP_CTL_DPDCK0_2_EN,
                        dp_op, dp_mfd, dp_mfn);
+
+       return 0;
 }
 
 static int clk_pllv2_prepare(struct clk_hw *hw)
diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c
index 641ebc5..4d8f4eb 100644
--- a/arch/arm/mach-imx/clk-pllv3.c
+++ b/arch/arm/mach-imx/clk-pllv3.c
@@ -104,13 +104,15 @@ static unsigned long clk_pllv3_recalc_rate(struct clk_hw 
*hw,
        return (div == 1) ? parent_rate * 22 : parent_rate * 20;
 }
 
-static long clk_pllv3_round_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long *prate)
+static int clk_pllv3_round_rate(struct clk_hw *hw, unsigned long *rate,
+                               unsigned long *prate)
 {
        unsigned long parent_rate = *prate;
 
-       return (rate >= parent_rate * 22) ? parent_rate * 22 :
-                                           parent_rate * 20;
+       *rate = (*rate >= parent_rate * 22) ? parent_rate * 22 :
+                                             parent_rate * 20;
+
+       return 0;
 }
 
 static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -151,21 +153,23 @@ static unsigned long clk_pllv3_sys_recalc_rate(struct 
clk_hw *hw,
        return parent_rate * div / 2;
 }
 
-static long clk_pllv3_sys_round_rate(struct clk_hw *hw, unsigned long rate,
-                                    unsigned long *prate)
+static int clk_pllv3_sys_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                   unsigned long *prate)
 {
        unsigned long parent_rate = *prate;
        unsigned long min_rate = parent_rate * 54 / 2;
        unsigned long max_rate = parent_rate * 108 / 2;
        u32 div;
 
-       if (rate > max_rate)
-               rate = max_rate;
-       else if (rate < min_rate)
-               rate = min_rate;
-       div = rate * 2 / parent_rate;
+       if (*rate > max_rate)
+               *rate = max_rate;
+       else if (*rate < min_rate)
+               *rate = min_rate;
+       div = *rate * 2 / parent_rate;
 
-       return parent_rate * div / 2;
+       *rate = parent_rate * div / 2;
+
+       return 0;
 }
 
 static int clk_pllv3_sys_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -207,7 +211,7 @@ static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw 
*hw,
        return (parent_rate * div) + ((parent_rate / mfd) * mfn);
 }
 
-static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long *rate,
                                    unsigned long *prate)
 {
        unsigned long parent_rate = *prate;
@@ -217,18 +221,20 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, 
unsigned long rate,
        u32 mfn, mfd = 1000000;
        s64 temp64;
 
-       if (rate > max_rate)
-               rate = max_rate;
-       else if (rate < min_rate)
-               rate = min_rate;
+       if (*rate > max_rate)
+               *rate = max_rate;
+       else if (*rate < min_rate)
+               *rate = min_rate;
 
-       div = rate / parent_rate;
-       temp64 = (u64) (rate - div * parent_rate);
+       div = *rate / parent_rate;
+       temp64 = (u64) (*rate - div * parent_rate);
        temp64 *= mfd;
        do_div(temp64, parent_rate);
        mfn = temp64;
 
-       return parent_rate * div + parent_rate / mfd * mfn;
+       *rate = parent_rate * div + parent_rate / mfd * mfn;
+
+       return 0;
 }
 
 static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index f5b69d7..118c288 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -109,11 +109,11 @@ static int pc_clk_is_enabled(struct clk_hw *hw)
                return id;
 }
 
-static long pc_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+static int pc_clk_round_rate(struct clk_hw *hw, unsigned long *rate,
                              unsigned long *p_rate)
 {
        /* Not really supported; pc_clk_set_rate() does rounding on it's own. */
-       return rate;
+       return 0;
 }
 
 static struct clk_ops clk_ops_pcom = {
diff --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c 
b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
index 85e0b0c0..2829a6f 100644
--- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
+++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
@@ -71,8 +71,8 @@ unsigned long omap2_table_mpu_recalc(struct clk_hw *clk,
  * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
  * just uses the ARM rates.
  */
-long omap2_round_to_table_rate(struct clk_hw *hw, unsigned long rate,
-                              unsigned long *parent_rate)
+int omap2_round_to_table_rate(struct clk_hw *hw, unsigned long *rate,
+                             unsigned long *parent_rate)
 {
        const struct prcm_config *ptr;
        long highest_rate;
@@ -88,10 +88,15 @@ long omap2_round_to_table_rate(struct clk_hw *hw, unsigned 
long rate,
                highest_rate = ptr->mpu_speed;
 
                /* Can check only after xtal frequency check */
-               if (ptr->mpu_speed <= rate)
+               if (ptr->mpu_speed <= *rate)
                        break;
        }
-       return highest_rate;
+
+       if (highest_rate < 0)
+               return highest_rate;
+
+       *rate = highest_rate;
+       return 0;
 }
 
 /* Sets basic clocks based on the specified rate */
diff --git a/arch/arm/mach-omap2/clkt_clksel.c 
b/arch/arm/mach-omap2/clkt_clksel.c
index 7ee2610..b932276 100644
--- a/arch/arm/mach-omap2/clkt_clksel.c
+++ b/arch/arm/mach-omap2/clkt_clksel.c
@@ -385,13 +385,15 @@ unsigned long omap2_clksel_recalc(struct clk_hw *hw, 
unsigned long parent_rate)
  *
  * Returns the rounded clock rate or returns 0xffffffff on error.
  */
-long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
+int omap2_clksel_round_rate(struct clk_hw *hw, unsigned long *target_rate,
                        unsigned long *parent_rate)
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        u32 new_div;
 
-       return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
+       *target_rate = omap2_clksel_round_rate_div(clk, *target_rate,
+                                                  &new_div);
+       return 0;
 }
 
 /**
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
index f251a14..7dac6b3 100644
--- a/arch/arm/mach-omap2/clkt_dpll.c
+++ b/arch/arm/mach-omap2/clkt_dpll.c
@@ -280,7 +280,7 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
  * (expensive) function again.  Returns ~0 if the target rate cannot
  * be rounded, or the rounded rate upon success.
  */
-long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
+int omap2_dpll_round_rate(struct clk_hw *hw, unsigned long *target_rate,
                unsigned long *parent_rate)
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
@@ -295,16 +295,16 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned 
long target_rate,
        const char *clk_name;
 
        if (!clk || !clk->dpll_data)
-               return ~0;
+               return -EINVAL;
 
        dd = clk->dpll_data;
 
        ref_rate = __clk_get_rate(dd->clk_ref);
        clk_name = __clk_get_name(hw->clk);
        pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n",
-                clk_name, target_rate);
+                clk_name, *target_rate);
 
-       scaled_rt_rp = target_rate / (ref_rate / DPLL_SCALE_FACTOR);
+       scaled_rt_rp = *target_rate / (ref_rate / DPLL_SCALE_FACTOR);
        scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
 
        dd->last_rounded_rate = 0;
@@ -330,7 +330,7 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long 
target_rate,
                if (m > scaled_max_m)
                        break;
 
-               r = _dpll_test_mult(&m, n, &new_rate, target_rate,
+               r = _dpll_test_mult(&m, n, &new_rate, *target_rate,
                                    ref_rate);
 
                /* m can't be set low enough for this n - try with a larger n */
@@ -338,7 +338,7 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long 
target_rate,
                        continue;
 
                /* skip rates above our target rate */
-               delta = target_rate - new_rate;
+               delta = *target_rate - new_rate;
                if (delta < 0)
                        continue;
 
@@ -357,14 +357,15 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned 
long target_rate,
 
        if (prev_min_delta == LONG_MAX) {
                pr_debug("clock: %s: cannot round to rate %lu\n",
-                        clk_name, target_rate);
-               return ~0;
+                        clk_name, *target_rate);
+               return -EINVAL;
        }
 
        dd->last_rounded_m = min_delta_m;
        dd->last_rounded_n = min_delta_n;
-       dd->last_rounded_rate = target_rate - prev_min_delta;
+       dd->last_rounded_rate = *target_rate - prev_min_delta;
 
-       return dd->last_rounded_rate;
+       *target_rate = dd->last_rounded_rate;
+       return 0;
 }
 
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index a56742f..cfe41b7 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -194,8 +194,8 @@ u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
                                u32 *new_div);
 u8 omap2_clksel_find_parent_index(struct clk_hw *hw);
 unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long 
parent_rate);
-long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
-                               unsigned long *parent_rate);
+int omap2_clksel_round_rate(struct clk_hw *hw, unsigned long *target_rate,
+                           unsigned long *parent_rate);
 int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
                                unsigned long parent_rate);
 int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val);
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 44e57ec..7a6fb45 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -480,6 +480,7 @@ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, 
unsigned long rate,
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        struct dpll_data *dd;
+       int ret;
 
        if (!hw || !rate)
                return -EINVAL;
@@ -492,7 +493,10 @@ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, 
unsigned long rate,
            (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
                *best_parent_clk = __clk_get_hw(dd->clk_bypass);
        } else {
-               rate = omap2_dpll_round_rate(hw, rate, best_parent_rate);
+               ret = omap2_dpll_round_rate(hw, &rate, best_parent_rate);
+               if (ret)
+                       return ret;
+
                *best_parent_clk = __clk_get_hw(dd->clk_ref);
        }
 
@@ -768,27 +772,33 @@ int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned 
long rate,
        return 0;
 }
 
-long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
+int omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long *rate,
                unsigned long *prate)
 {
        const struct dpll_data *dd;
        u32 v;
        struct clk_hw_omap *pclk = NULL;
 
-       if (!*prate)
+       if (!*prate) {
+               *rate = 0;
                return 0;
+       }
 
        pclk = omap3_find_clkoutx2_dpll(hw);
 
-       if (!pclk)
+       if (!pclk) {
+               *rate = 0;
                return 0;
+       }
 
        dd = pclk->dpll_data;
 
        /* TYPE J does not have a clkoutx2 */
        if (dd->flags & DPLL_J_TYPE) {
-               *prate = __clk_round_rate(__clk_get_parent(pclk->hw.clk), rate);
-               return *prate;
+               *prate = __clk_round_rate(__clk_get_parent(pclk->hw.clk),
+                                         *rate);
+               *rate = *prate;
+               return 0;
        }
 
        WARN_ON(!dd->enable_mask);
@@ -803,12 +813,13 @@ long omap3_clkoutx2_round_rate(struct clk_hw *hw, 
unsigned long rate,
        if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
                unsigned long best_parent;
 
-               best_parent = (rate / 2);
+               best_parent = (*rate / 2);
                *prate = __clk_round_rate(__clk_get_parent(hw->clk),
                                best_parent);
        }
 
-       return *prate * 2;
+       *rate = *prate * 2;
+       return 0;
 }
 
 /* OMAP3/4 non-CORE DPLL clkops */
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index f231be0..afd3284 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -146,11 +146,12 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw 
*hw,
  * M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or
  * ~0 if an error occurred in omap2_dpll_round_rate().
  */
-long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
-                                   unsigned long target_rate,
-                                   unsigned long *parent_rate)
+int omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
+                                  unsigned long *target_rate,
+                                  unsigned long *parent_rate)
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       unsigned long rate = *target_rate;
        struct dpll_data *dd;
        long r;
 
@@ -166,7 +167,7 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
         * target rate without using the 4X multiplier.
         */
        r = omap2_dpll_round_rate(hw, target_rate, NULL);
-       if (r != ~0)
+       if (!r)
                goto out;
 
        /*
@@ -174,9 +175,9 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
         * this time see if using the 4X multiplier can help. Enabling the
         * 4X multiplier is equivalent to dividing the target rate by 4.
         */
-       r = omap2_dpll_round_rate(hw, target_rate / OMAP4430_REGM4XEN_MULT,
-                                 NULL);
-       if (r == ~0)
+       rate = *target_rate / OMAP4430_REGM4XEN_MULT;
+       r = omap2_dpll_round_rate(hw, &rate, NULL);
+       if (r)
                return r;
 
        dd->last_rounded_rate *= OMAP4430_REGM4XEN_MULT;
@@ -184,8 +185,9 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
 
 out:
        omap4_dpll_lpmode_recalc(dd);
+       *target_rate = dd->last_rounded_rate;
 
-       return dd->last_rounded_rate;
+       return 0;
 }
 
 /**
@@ -209,6 +211,7 @@ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, 
unsigned long rate,
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        struct dpll_data *dd;
+       int ret;
 
        if (!hw || !rate)
                return -EINVAL;
@@ -221,8 +224,11 @@ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, 
unsigned long rate,
            (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
                *best_parent_clk = __clk_get_hw(dd->clk_bypass);
        } else {
-               rate = omap4_dpll_regm4xen_round_rate(hw, rate,
-                                                     best_parent_rate);
+               ret = omap4_dpll_regm4xen_round_rate(hw, &rate,
+                                                    best_parent_rate);
+               if (ret)
+                       return ret;
+
                *best_parent_clk = __clk_get_hw(dd->clk_ref);
        }
 
diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c
index f61158c..774ac3b 100644
--- a/arch/arm/mach-vexpress/spc.c
+++ b/arch/arm/mach-vexpress/spc.c
@@ -507,12 +507,19 @@ static unsigned long spc_recalc_rate(struct clk_hw *hw,
        return freq * 1000;
 }
 
-static long spc_round_rate(struct clk_hw *hw, unsigned long drate,
+static int spc_round_rate(struct clk_hw *hw, unsigned long *drate,
                unsigned long *parent_rate)
 {
        struct clk_spc *spc = to_clk_spc(hw);
+       long ret;
 
-       return ve_spc_round_performance(spc->cluster, drate);
+       ret = ve_spc_round_performance(spc->cluster, *drate);
+       if (ret < 0)
+               return ret;
+
+       *drate = ret;
+
+       return 0;
 }
 
 static int spc_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c
index 6a98d2c..d697d8f 100644
--- a/arch/mips/alchemy/common/clock.c
+++ b/arch/mips/alchemy/common/clock.c
@@ -202,24 +202,27 @@ static int alchemy_clk_aux_setr(struct clk_hw *hw,
        return 0;
 }
 
-static long alchemy_clk_aux_roundr(struct clk_hw *hw,
-                                           unsigned long rate,
+static int alchemy_clk_aux_roundr(struct clk_hw *hw,
+                                           unsigned long *rate,
                                            unsigned long *parent_rate)
 {
        struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
        unsigned long mult;
 
-       if (!rate || !*parent_rate)
+       if (!*rate || !*parent_rate) {
+               *rate = 0;
                return 0;
+       }
 
-       mult = rate / (*parent_rate);
+       mult = *rate / (*parent_rate);
 
        if (mult && (mult < 7))
                mult = 7;
        if (mult > a->maxmult)
                mult = a->maxmult;
 
-       return (*parent_rate) * mult;
+       *rate = (*parent_rate) * mult;
+       return 0;
 }
 
 static struct clk_ops alchemy_clkops_aux = {
diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c
index 152dcb3..e48f31e 100644
--- a/drivers/clk/at91/clk-h32mx.c
+++ b/drivers/clk/at91/clk-h32mx.c
@@ -49,21 +49,25 @@ static unsigned long clk_sama5d4_h32mx_recalc_rate(struct 
clk_hw *hw,
        return parent_rate;
 }
 
-static long clk_sama5d4_h32mx_round_rate(struct clk_hw *hw, unsigned long rate,
-                                      unsigned long *parent_rate)
+static int clk_sama5d4_h32mx_round_rate(struct clk_hw *hw,
+                                       unsigned long *rate,
+                                       unsigned long *parent_rate)
 {
        unsigned long div;
 
-       if (rate > *parent_rate)
-               return *parent_rate;
-       div = *parent_rate / 2;
-       if (rate < div)
-               return div;
+       if (*rate > *parent_rate) {
+               *rate = *parent_rate;
+               return 0;
+       }
 
-       if (rate - div < *parent_rate - rate)
-               return div;
+       div = *parent_rate / 2;
+       if (*rate < div || (*rate - div) < (*parent_rate - *rate)) {
+               *rate = div;
+               return 0;
+       }
 
-       return *parent_rate;
+       *rate = *parent_rate;
+       return 0;
 }
 
 static int clk_sama5d4_h32mx_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/at91/clk-peripheral.c 
b/drivers/clk/at91/clk-peripheral.c
index 597fed4..d990ae0 100644
--- a/drivers/clk/at91/clk-peripheral.c
+++ b/drivers/clk/at91/clk-peripheral.c
@@ -227,9 +227,9 @@ clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw,
        return parent_rate >> periph->div;
 }
 
-static long clk_sam9x5_peripheral_round_rate(struct clk_hw *hw,
-                                            unsigned long rate,
-                                            unsigned long *parent_rate)
+static int clk_sam9x5_peripheral_round_rate(struct clk_hw *hw,
+                                           unsigned long *rate,
+                                           unsigned long *parent_rate)
 {
        int shift = 0;
        unsigned long best_rate;
@@ -238,8 +238,10 @@ static long clk_sam9x5_peripheral_round_rate(struct clk_hw 
*hw,
        unsigned long cur_diff;
        struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
 
-       if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max)
-               return *parent_rate;
+       if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) {
+               *rate = *parent_rate;
+               return 0;
+       }
 
        if (periph->range.max) {
                for (; shift < PERIPHERAL_MAX_SHIFT; shift++) {
@@ -249,28 +251,31 @@ static long clk_sam9x5_peripheral_round_rate(struct 
clk_hw *hw,
                }
        }
 
-       if (rate >= cur_rate)
-               return cur_rate;
+       if (*rate >= cur_rate) {
+               *rate = cur_rate;
+               return 0;
+       }
 
-       best_diff = cur_rate - rate;
+       best_diff = cur_rate - *rate;
        best_rate = cur_rate;
        for (; shift < PERIPHERAL_MAX_SHIFT; shift++) {
                cur_rate = *parent_rate >> shift;
-               if (cur_rate < rate)
-                       cur_diff = rate - cur_rate;
+               if (cur_rate < *rate)
+                       cur_diff = *rate - cur_rate;
                else
-                       cur_diff = cur_rate - rate;
+                       cur_diff = cur_rate - *rate;
 
                if (cur_diff < best_diff) {
                        best_diff = cur_diff;
                        best_rate = cur_rate;
                }
 
-               if (!best_diff || cur_rate < rate)
+               if (!best_diff || cur_rate < *rate)
                        break;
        }
 
-       return best_rate;
+       *rate = best_rate;
+       return 0;
 }
 
 static int clk_sam9x5_peripheral_set_rate(struct clk_hw *hw,
diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c
index 6ec79db..e7754eb 100644
--- a/drivers/clk/at91/clk-pll.c
+++ b/drivers/clk/at91/clk-pll.c
@@ -260,13 +260,19 @@ static long clk_pll_get_best_div_mul(struct clk_pll *pll, 
unsigned long rate,
        return bestrate;
 }
 
-static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long *parent_rate)
+static int clk_pll_round_rate(struct clk_hw *hw, unsigned long *rate,
+                             unsigned long *parent_rate)
 {
        struct clk_pll *pll = to_clk_pll(hw);
+       long ret;
 
-       return clk_pll_get_best_div_mul(pll, rate, *parent_rate,
-                                       NULL, NULL, NULL);
+       ret = clk_pll_get_best_div_mul(pll, *rate, *parent_rate,
+                                      NULL, NULL, NULL);
+       if (ret < 0)
+               return ret;
+
+       *rate = ret;
+       return 0;
 }
 
 static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/at91/clk-plldiv.c b/drivers/clk/at91/clk-plldiv.c
index ea22656..c267214 100644
--- a/drivers/clk/at91/clk-plldiv.c
+++ b/drivers/clk/at91/clk-plldiv.c
@@ -36,21 +36,23 @@ static unsigned long clk_plldiv_recalc_rate(struct clk_hw 
*hw,
        return parent_rate;
 }
 
-static long clk_plldiv_round_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long *parent_rate)
+static int clk_plldiv_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                unsigned long *parent_rate)
 {
        unsigned long div;
 
-       if (rate > *parent_rate)
-               return *parent_rate;
-       div = *parent_rate / 2;
-       if (rate < div)
-               return div;
+       if (*rate > *parent_rate) {
+               *rate = *parent_rate;
+               return 0;
+       }
 
-       if (rate - div < *parent_rate - rate)
-               return div;
+       div = *parent_rate / 2;
+       if (*rate < div || (*rate - div) < (*parent_rate - *rate))
+               *rate = div;
+       else
+               *rate = *parent_rate;
 
-       return *parent_rate;
+       return 0;
 }
 
 static int clk_plldiv_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c
index 144d47e..cd0f6d2 100644
--- a/drivers/clk/at91/clk-smd.c
+++ b/drivers/clk/at91/clk-smd.c
@@ -43,26 +43,32 @@ static unsigned long at91sam9x5_clk_smd_recalc_rate(struct 
clk_hw *hw,
        return parent_rate / (smddiv + 1);
 }
 
-static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long 
rate,
-                                         unsigned long *parent_rate)
+static int at91sam9x5_clk_smd_round_rate(struct clk_hw *hw,
+                                        unsigned long *rate,
+                                        unsigned long *parent_rate)
 {
        unsigned long div;
        unsigned long bestrate;
        unsigned long tmp;
 
-       if (rate >= *parent_rate)
-               return *parent_rate;
+       if (*rate >= *parent_rate) {
+               *rate = *parent_rate;
+               return 0;
+       }
 
-       div = *parent_rate / rate;
-       if (div > SMD_MAX_DIV)
-               return *parent_rate / (SMD_MAX_DIV + 1);
+       div = *parent_rate / *rate;
+       if (div > SMD_MAX_DIV) {
+               *rate = *parent_rate / (SMD_MAX_DIV + 1);
+               return 0;
+       }
 
        bestrate = *parent_rate / div;
        tmp = *parent_rate / (div + 1);
-       if (bestrate - rate > rate - tmp)
+       if (bestrate - *rate > *rate - tmp)
                bestrate = tmp;
 
-       return bestrate;
+       *rate = bestrate;
+       return 0;
 }
 
 static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index)
diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c
index 0b7c3e8..08a2ee2 100644
--- a/drivers/clk/at91/clk-usb.c
+++ b/drivers/clk/at91/clk-usb.c
@@ -269,8 +269,9 @@ static unsigned long at91rm9200_clk_usb_recalc_rate(struct 
clk_hw *hw,
        return 0;
 }
 
-static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long 
rate,
-                                         unsigned long *parent_rate)
+static int at91rm9200_clk_usb_round_rate(struct clk_hw *hw,
+                                        unsigned long *rate,
+                                        unsigned long *parent_rate)
 {
        struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
        struct clk *parent = __clk_get_parent(hw->clk);
@@ -286,13 +287,13 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw 
*hw, unsigned long rate,
                if (!usb->divisors[i])
                        continue;
 
-               tmp_parent_rate = rate * usb->divisors[i];
+               tmp_parent_rate = *rate * usb->divisors[i];
                tmp_parent_rate = __clk_round_rate(parent, tmp_parent_rate);
                tmprate = DIV_ROUND_CLOSEST(tmp_parent_rate, usb->divisors[i]);
-               if (tmprate < rate)
-                       tmpdiff = rate - tmprate;
+               if (tmprate < *rate)
+                       tmpdiff = *rate - tmprate;
                else
-                       tmpdiff = tmprate - rate;
+                       tmpdiff = tmprate - *rate;
 
                if (bestdiff < 0 || bestdiff > tmpdiff) {
                        bestrate = tmprate;
@@ -304,7 +305,8 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw 
*hw, unsigned long rate,
                        break;
        }
 
-       return bestrate;
+       *rate = bestrate;
+       return 0;
 }
 
 static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
index e619285..3509d50 100644
--- a/drivers/clk/clk-axi-clkgen.c
+++ b/drivers/clk/clk-axi-clkgen.c
@@ -405,7 +405,7 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
        return 0;
 }
 
-static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
+static int axi_clkgen_round_rate(struct clk_hw *hw, unsigned long *rate,
        unsigned long *parent_rate)
 {
        unsigned int d, m, dout;
@@ -415,7 +415,8 @@ static long axi_clkgen_round_rate(struct clk_hw *hw, 
unsigned long rate,
        if (d == 0 || dout == 0 || m == 0)
                return -EINVAL;
 
-       return *parent_rate / d * m / dout;
+       *rate = *parent_rate / d * m / dout;
+       return 0;
 }
 
 static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
diff --git a/drivers/clk/clk-cdce706.c b/drivers/clk/clk-cdce706.c
index b8e4f8a..ec9ba82 100644
--- a/drivers/clk/clk-cdce706.c
+++ b/drivers/clk/clk-cdce706.c
@@ -187,8 +187,8 @@ static unsigned long cdce706_pll_recalc_rate(struct clk_hw 
*hw,
        return 0;
 }
 
-static long cdce706_pll_round_rate(struct clk_hw *hw, unsigned long rate,
-                                  unsigned long *parent_rate)
+static int cdce706_pll_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                 unsigned long *parent_rate)
 {
        struct cdce706_hw_data *hwd = to_hw_data(hw);
        unsigned long mul, div;
@@ -196,9 +196,9 @@ static long cdce706_pll_round_rate(struct clk_hw *hw, 
unsigned long rate,
 
        dev_dbg(&hwd->dev_data->client->dev,
                "%s, rate: %lu, parent_rate: %lu\n",
-               __func__, rate, *parent_rate);
+               __func__, *rate, *parent_rate);
 
-       rational_best_approximation(rate, *parent_rate,
+       rational_best_approximation(*rate, *parent_rate,
                                    CDCE706_PLL_N_MAX, CDCE706_PLL_M_MAX,
                                    &mul, &div);
        hwd->mul = mul;
@@ -210,7 +210,8 @@ static long cdce706_pll_round_rate(struct clk_hw *hw, 
unsigned long rate,
 
        res = (u64)*parent_rate * hwd->mul;
        do_div(res, hwd->div);
-       return res;
+       *rate = res;
+       return 0;
 }
 
 static int cdce706_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -292,8 +293,8 @@ static unsigned long cdce706_divider_recalc_rate(struct 
clk_hw *hw,
        return 0;
 }
 
-static long cdce706_divider_round_rate(struct clk_hw *hw, unsigned long rate,
-                                      unsigned long *parent_rate)
+static int cdce706_divider_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                     unsigned long *parent_rate)
 {
        struct cdce706_hw_data *hwd = to_hw_data(hw);
        struct cdce706_dev_data *cdce = hwd->dev_data;
@@ -301,31 +302,31 @@ static long cdce706_divider_round_rate(struct clk_hw *hw, 
unsigned long rate,
 
        dev_dbg(&hwd->dev_data->client->dev,
                "%s, rate: %lu, parent_rate: %lu\n",
-               __func__, rate, *parent_rate);
+               __func__, *rate, *parent_rate);
 
-       rational_best_approximation(rate, *parent_rate,
+       rational_best_approximation(*rate, *parent_rate,
                                    1, CDCE706_DIVIDER_DIVIDER_MAX,
                                    &mul, &div);
        if (!mul)
                div = CDCE706_DIVIDER_DIVIDER_MAX;
 
        if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
-               unsigned long best_diff = rate;
+               unsigned long best_diff = *rate;
                unsigned long best_div = 0;
                struct clk *gp_clk = cdce->clkin_clk[cdce->clkin[0].parent];
                unsigned long gp_rate = gp_clk ? clk_get_rate(gp_clk) : 0;
 
-               for (div = CDCE706_PLL_FREQ_MIN / rate; best_diff &&
-                    div <= CDCE706_PLL_FREQ_MAX / rate; ++div) {
+               for (div = CDCE706_PLL_FREQ_MIN / *rate; best_diff &&
+                    div <= CDCE706_PLL_FREQ_MAX / *rate; ++div) {
                        unsigned long n, m;
                        unsigned long diff;
                        unsigned long div_rate;
                        u64 div_rate64;
 
-                       if (rate * div < CDCE706_PLL_FREQ_MIN)
+                       if (*rate * div < CDCE706_PLL_FREQ_MIN)
                                continue;
 
-                       rational_best_approximation(rate * div, gp_rate,
+                       rational_best_approximation(*rate * div, gp_rate,
                                                    CDCE706_PLL_N_MAX,
                                                    CDCE706_PLL_M_MAX,
                                                    &n, &m);
@@ -333,7 +334,7 @@ static long cdce706_divider_round_rate(struct clk_hw *hw, 
unsigned long rate,
                        do_div(div_rate64, m);
                        do_div(div_rate64, div);
                        div_rate = div_rate64;
-                       diff = max(div_rate, rate) - min(div_rate, rate);
+                       diff = max(div_rate, *rate) - min(div_rate, *rate);
 
                        if (diff < best_diff) {
                                best_diff = diff;
@@ -348,8 +349,8 @@ static long cdce706_divider_round_rate(struct clk_hw *hw, 
unsigned long rate,
 
                dev_dbg(&hwd->dev_data->client->dev,
                        "%s, altering parent rate: %lu -> %lu\n",
-                       __func__, *parent_rate, rate * div);
-               *parent_rate = rate * div;
+                       __func__, *parent_rate, *rate * div);
+               *parent_rate = *rate * div;
        }
        hwd->div = div;
 
@@ -357,7 +358,8 @@ static long cdce706_divider_round_rate(struct clk_hw *hw, 
unsigned long rate,
                "%s, divider: %d, div: %lu\n",
                __func__, hwd->idx, div);
 
-       return *parent_rate / div;
+       *rate = *parent_rate / div;
+       return 0;
 }
 
 static int cdce706_divider_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -425,11 +427,11 @@ static unsigned long cdce706_clkout_recalc_rate(struct 
clk_hw *hw,
        return parent_rate;
 }
 
-static long cdce706_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
-                                     unsigned long *parent_rate)
+static int cdce706_clkout_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                    unsigned long *parent_rate)
 {
-       *parent_rate = rate;
-       return rate;
+       *parent_rate = *rate;
+       return 0;
 }
 
 static int cdce706_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 956b7e5..f56a71d 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -68,10 +68,10 @@ static long clk_composite_determine_rate(struct clk_hw *hw, 
unsigned long rate,
        struct clk_hw *mux_hw = composite->mux_hw;
        struct clk *parent;
        unsigned long parent_rate;
-       long tmp_rate, best_rate = 0;
+       unsigned long tmp_rate, best_rate = 0;
        unsigned long rate_diff;
        unsigned long best_rate_diff = ULONG_MAX;
-       int i;
+       int ret, i;
 
        if (rate_hw && rate_ops && rate_ops->determine_rate) {
                __clk_hw_set_clk(rate_hw, hw);
@@ -88,8 +88,12 @@ static long clk_composite_determine_rate(struct clk_hw *hw, 
unsigned long rate,
                        *best_parent_p = __clk_get_hw(parent);
                        *best_parent_rate = __clk_get_rate(parent);
 
-                       return rate_ops->round_rate(rate_hw, rate,
-                                                   best_parent_rate);
+                       ret = rate_ops->round_rate(rate_hw, &rate,
+                                                  best_parent_rate);
+                       if (ret)
+                               return ret;
+
+                       return rate;
                }
 
                for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
@@ -99,9 +103,10 @@ static long clk_composite_determine_rate(struct clk_hw *hw, 
unsigned long rate,
 
                        parent_rate = __clk_get_rate(parent);
 
-                       tmp_rate = rate_ops->round_rate(rate_hw, rate,
-                                                       &parent_rate);
-                       if (tmp_rate < 0)
+                       tmp_rate = rate;
+                       ret = rate_ops->round_rate(rate_hw, &tmp_rate,
+                                                  &parent_rate);
+                       if (ret < 0)
                                continue;
 
                        rate_diff = abs(rate - tmp_rate);
@@ -130,8 +135,8 @@ static long clk_composite_determine_rate(struct clk_hw *hw, 
unsigned long rate,
        }
 }
 
-static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate,
-                                 unsigned long *prate)
+static int clk_composite_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                    unsigned long *prate)
 {
        struct clk_composite *composite = to_clk_composite(hw);
        const struct clk_ops *rate_ops = composite->rate_ops;
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 25006a8..f646a0c 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -329,19 +329,20 @@ static int clk_divider_bestdiv(struct clk_hw *hw, 
unsigned long rate,
        return bestdiv;
 }
 
-long divider_round_rate(struct clk_hw *hw, unsigned long rate,
-                       unsigned long *prate, const struct clk_div_table *table,
-                       u8 width, unsigned long flags)
+int divider_round_rate(struct clk_hw *hw, unsigned long *rate,
+                      unsigned long *prate, const struct clk_div_table *table,
+                      u8 width, unsigned long flags)
 {
        int div;
 
-       div = clk_divider_bestdiv(hw, rate, prate, table, width, flags);
+       div = clk_divider_bestdiv(hw, *rate, prate, table, width, flags);
 
-       return DIV_ROUND_UP(*prate, div);
+       *rate = DIV_ROUND_UP(*prate, div);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(divider_round_rate);
 
-static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_divider_round_rate(struct clk_hw *hw, unsigned long *rate,
                                unsigned long *prate)
 {
        struct clk_divider *divider = to_clk_divider(hw);
@@ -352,7 +353,8 @@ static long clk_divider_round_rate(struct clk_hw *hw, 
unsigned long rate,
                bestdiv = readl(divider->reg) >> divider->shift;
                bestdiv &= div_mask(divider->width);
                bestdiv = _get_div(divider->table, bestdiv, divider->flags);
-               return DIV_ROUND_UP(*prate, bestdiv);
+               *rate = DIV_ROUND_UP(*prate, bestdiv);
+               return 0;
        }
 
        return divider_round_rate(hw, rate, prate, divider->table,
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index d9e3f67..ff936d0 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -36,7 +36,7 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
        return (unsigned long)rate;
 }
 
-static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_factor_round_rate(struct clk_hw *hw, unsigned long *rate,
                                unsigned long *prate)
 {
        struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
@@ -44,12 +44,13 @@ static long clk_factor_round_rate(struct clk_hw *hw, 
unsigned long rate,
        if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
                unsigned long best_parent;
 
-               best_parent = (rate / fix->mult) * fix->div;
+               best_parent = (*rate / fix->mult) * fix->div;
                *prate = __clk_round_rate(__clk_get_parent(hw->clk),
                                best_parent);
        }
 
-       return (*prate / fix->div) * fix->mult;
+       *rate = (*prate / fix->div) * fix->mult;
+       return 0;
 }
 
 static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/clk-fractional-divider.c 
b/drivers/clk/clk-fractional-divider.c
index 6aa72d9..1f1ba3e 100644
--- a/drivers/clk/clk-fractional-divider.c
+++ b/drivers/clk/clk-fractional-divider.c
@@ -45,24 +45,26 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
        return ret;
 }
 
-static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
-                             unsigned long *prate)
+static int clk_fd_round_rate(struct clk_hw *hw, unsigned long *rate,
+                            unsigned long *prate)
 {
        struct clk_fractional_divider *fd = to_clk_fd(hw);
        unsigned maxn = (fd->nmask >> fd->nshift) + 1;
        unsigned div;
 
-       if (!rate || rate >= *prate)
-               return *prate;
+       if (!*rate || *rate >= *prate) {
+               *rate = *prate;
+               return 0;
+       }
 
-       div = gcd(*prate, rate);
+       div = gcd(*prate, *rate);
 
        while ((*prate / div) > maxn) {
                div <<= 1;
-               rate <<= 1;
+               *rate <<= 1;
        }
 
-       return rate;
+       return 0;
 }
 
 static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/clk-highbank.c b/drivers/clk/clk-highbank.c
index 2e7e9d9..f26d1b0 100644
--- a/drivers/clk/clk-highbank.c
+++ b/drivers/clk/clk-highbank.c
@@ -142,15 +142,16 @@ static void clk_pll_calc(unsigned long rate, unsigned 
long ref_freq,
        *pdivf = divf;
 }
 
-static long clk_pll_round_rate(struct clk_hw *hwclk, unsigned long rate,
-                              unsigned long *parent_rate)
+static int clk_pll_round_rate(struct clk_hw *hwclk, unsigned long *rate,
+                             unsigned long *parent_rate)
 {
        u32 divq, divf;
        unsigned long ref_freq = *parent_rate;
 
-       clk_pll_calc(rate, ref_freq, &divq, &divf);
+       clk_pll_calc(*rate, ref_freq, &divq, &divf);
 
-       return (ref_freq * (divf + 1)) / (1 << divq);
+       *rate = (ref_freq * (divf + 1)) / (1 << divq);
+       return 0;
 }
 
 static int clk_pll_set_rate(struct clk_hw *hwclk, unsigned long rate,
@@ -239,16 +240,17 @@ static unsigned long clk_periclk_recalc_rate(struct 
clk_hw *hwclk,
        return parent_rate / div;
 }
 
-static long clk_periclk_round_rate(struct clk_hw *hwclk, unsigned long rate,
-                                  unsigned long *parent_rate)
+static int clk_periclk_round_rate(struct clk_hw *hwclk, unsigned long *rate,
+                                 unsigned long *parent_rate)
 {
        u32 div;
 
-       div = *parent_rate / rate;
+       div = *parent_rate / *rate;
        div++;
        div &= ~0x1;
 
-       return *parent_rate / div;
+       *rate = *parent_rate / div;
+       return 0;
 }
 
 static int clk_periclk_set_rate(struct clk_hw *hwclk, unsigned long rate,
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c
index 44ea107..54b302e 100644
--- a/drivers/clk/clk-si5351.c
+++ b/drivers/clk/clk-si5351.c
@@ -446,30 +446,30 @@ static unsigned long si5351_pll_recalc_rate(struct clk_hw 
*hw,
        return (unsigned long)rate;
 }
 
-static long si5351_pll_round_rate(struct clk_hw *hw, unsigned long rate,
-                                 unsigned long *parent_rate)
+static int si5351_pll_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                unsigned long *parent_rate)
 {
        struct si5351_hw_data *hwdata =
                container_of(hw, struct si5351_hw_data, hw);
        unsigned long rfrac, denom, a, b, c;
        unsigned long long lltmp;
 
-       if (rate < SI5351_PLL_VCO_MIN)
-               rate = SI5351_PLL_VCO_MIN;
-       if (rate > SI5351_PLL_VCO_MAX)
-               rate = SI5351_PLL_VCO_MAX;
+       if (*rate < SI5351_PLL_VCO_MIN)
+               *rate = SI5351_PLL_VCO_MIN;
+       if (*rate > SI5351_PLL_VCO_MAX)
+               *rate = SI5351_PLL_VCO_MAX;
 
        /* determine integer part of feedback equation */
-       a = rate / *parent_rate;
+       a = *rate / *parent_rate;
 
        if (a < SI5351_PLL_A_MIN)
-               rate = *parent_rate * SI5351_PLL_A_MIN;
+               *rate = *parent_rate * SI5351_PLL_A_MIN;
        if (a > SI5351_PLL_A_MAX)
-               rate = *parent_rate * SI5351_PLL_A_MAX;
+               *rate = *parent_rate * SI5351_PLL_A_MAX;
 
        /* find best approximation for b/c = fVCO mod fIN */
        denom = 1000 * 1000;
-       lltmp = rate % (*parent_rate);
+       lltmp = *rate % (*parent_rate);
        lltmp *= denom;
        do_div(lltmp, *parent_rate);
        rfrac = (unsigned long)lltmp;
@@ -492,15 +492,15 @@ static long si5351_pll_round_rate(struct clk_hw *hw, 
unsigned long rate,
        lltmp *= b;
        do_div(lltmp, c);
 
-       rate  = (unsigned long)lltmp;
-       rate += *parent_rate * a;
+       *rate  = (unsigned long)lltmp;
+       *rate += *parent_rate * a;
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: a = %lu, b = %lu, c = %lu, parent_rate = %lu, rate = 
%lu\n",
                __func__, __clk_get_name(hwdata->hw.clk), a, b, c,
-               *parent_rate, rate);
+               *parent_rate, *rate);
 
-       return rate;
+       return 0;
 }
 
 static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -639,8 +639,8 @@ static unsigned long si5351_msynth_recalc_rate(struct 
clk_hw *hw,
        return (unsigned long)rate;
 }
 
-static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
-                                    unsigned long *parent_rate)
+static int si5351_msynth_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                   unsigned long *parent_rate)
 {
        struct si5351_hw_data *hwdata =
                container_of(hw, struct si5351_hw_data, hw);
@@ -649,17 +649,17 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, 
unsigned long rate,
        int divby4;
 
        /* multisync6-7 can only handle freqencies < 150MHz */
-       if (hwdata->num >= 6 && rate > SI5351_MULTISYNTH67_MAX_FREQ)
-               rate = SI5351_MULTISYNTH67_MAX_FREQ;
+       if (hwdata->num >= 6 && *rate > SI5351_MULTISYNTH67_MAX_FREQ)
+               *rate = SI5351_MULTISYNTH67_MAX_FREQ;
 
        /* multisync frequency is 1MHz .. 160MHz */
-       if (rate > SI5351_MULTISYNTH_MAX_FREQ)
-               rate = SI5351_MULTISYNTH_MAX_FREQ;
-       if (rate < SI5351_MULTISYNTH_MIN_FREQ)
-               rate = SI5351_MULTISYNTH_MIN_FREQ;
+       if (*rate > SI5351_MULTISYNTH_MAX_FREQ)
+               *rate = SI5351_MULTISYNTH_MAX_FREQ;
+       if (*rate < SI5351_MULTISYNTH_MIN_FREQ)
+               *rate = SI5351_MULTISYNTH_MIN_FREQ;
 
        divby4 = 0;
-       if (rate > SI5351_MULTISYNTH_DIVBY4_FREQ)
+       if (*rate > SI5351_MULTISYNTH_DIVBY4_FREQ)
                divby4 = 1;
 
        /* multisync can set pll */
@@ -670,7 +670,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, 
unsigned long rate,
                 */
                if (divby4 == 0) {
                        lltmp = SI5351_PLL_VCO_MAX;
-                       do_div(lltmp, rate);
+                       do_div(lltmp, *rate);
                        a = (unsigned long)lltmp;
                } else
                        a = 4;
@@ -678,18 +678,18 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, 
unsigned long rate,
                b = 0;
                c = 1;
 
-               *parent_rate = a * rate;
+               *parent_rate = a * *rate;
        } else {
                unsigned long rfrac, denom;
 
                /* disable divby4 */
                if (divby4) {
-                       rate = SI5351_MULTISYNTH_DIVBY4_FREQ;
+                       *rate = SI5351_MULTISYNTH_DIVBY4_FREQ;
                        divby4 = 0;
                }
 
                /* determine integer part of divider equation */
-               a = *parent_rate / rate;
+               a = *parent_rate / *rate;
                if (a < SI5351_MULTISYNTH_A_MIN)
                        a = SI5351_MULTISYNTH_A_MIN;
                if (hwdata->num >= 6 && a > SI5351_MULTISYNTH67_A_MAX)
@@ -699,9 +699,9 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, 
unsigned long rate,
 
                /* find best approximation for b/c = fVCO mod fOUT */
                denom = 1000 * 1000;
-               lltmp = (*parent_rate) % rate;
+               lltmp = (*parent_rate) % *rate;
                lltmp *= denom;
-               do_div(lltmp, rate);
+               do_div(lltmp, *rate);
                rfrac = (unsigned long)lltmp;
 
                b = 0;
@@ -716,7 +716,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, 
unsigned long rate,
        lltmp  = *parent_rate;
        lltmp *= c;
        do_div(lltmp, a * c + b);
-       rate  = (unsigned long)lltmp;
+       *rate  = (unsigned long)lltmp;
 
        /* calculate parameters */
        if (divby4) {
@@ -734,9 +734,9 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, 
unsigned long rate,
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: a = %lu, b = %lu, c = %lu, divby4 = %d, parent_rate = 
%lu, rate = %lu\n",
                __func__, __clk_get_name(hwdata->hw.clk), a, b, c, divby4,
-               *parent_rate, rate);
+               *parent_rate, *rate);
 
-       return rate;
+       return 0;
 }
 
 static int si5351_msynth_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -983,57 +983,57 @@ static unsigned long si5351_clkout_recalc_rate(struct 
clk_hw *hw,
        return parent_rate >> rdiv;
 }
 
-static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
-                                    unsigned long *parent_rate)
+static int si5351_clkout_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                   unsigned long *parent_rate)
 {
        struct si5351_hw_data *hwdata =
                container_of(hw, struct si5351_hw_data, hw);
        unsigned char rdiv;
 
        /* clkout6/7 can only handle output freqencies < 150MHz */
-       if (hwdata->num >= 6 && rate > SI5351_CLKOUT67_MAX_FREQ)
-               rate = SI5351_CLKOUT67_MAX_FREQ;
+       if (hwdata->num >= 6 && *rate > SI5351_CLKOUT67_MAX_FREQ)
+               *rate = SI5351_CLKOUT67_MAX_FREQ;
 
        /* clkout freqency is 8kHz - 160MHz */
-       if (rate > SI5351_CLKOUT_MAX_FREQ)
-               rate = SI5351_CLKOUT_MAX_FREQ;
-       if (rate < SI5351_CLKOUT_MIN_FREQ)
-               rate = SI5351_CLKOUT_MIN_FREQ;
+       if (*rate > SI5351_CLKOUT_MAX_FREQ)
+               *rate = SI5351_CLKOUT_MAX_FREQ;
+       if (*rate < SI5351_CLKOUT_MIN_FREQ)
+               *rate = SI5351_CLKOUT_MIN_FREQ;
 
        /* request frequency if multisync master */
        if (__clk_get_flags(hwdata->hw.clk) & CLK_SET_RATE_PARENT) {
                /* use r divider for frequencies below 1MHz */
                rdiv = SI5351_OUTPUT_CLK_DIV_1;
-               while (rate < SI5351_MULTISYNTH_MIN_FREQ &&
+               while (*rate < SI5351_MULTISYNTH_MIN_FREQ &&
                       rdiv < SI5351_OUTPUT_CLK_DIV_128) {
                        rdiv += 1;
-                       rate *= 2;
+                       *rate *= 2;
                }
-               *parent_rate = rate;
+               *parent_rate = *rate;
        } else {
                unsigned long new_rate, new_err, err;
 
                /* round to closed rdiv */
                rdiv = SI5351_OUTPUT_CLK_DIV_1;
                new_rate = *parent_rate;
-               err = abs(new_rate - rate);
+               err = abs(new_rate - *rate);
                do {
                        new_rate >>= 1;
-                       new_err = abs(new_rate - rate);
+                       new_err = abs(new_rate - *rate);
                        if (new_err > err || rdiv == SI5351_OUTPUT_CLK_DIV_128)
                                break;
                        rdiv++;
                        err = new_err;
                } while (1);
        }
-       rate = *parent_rate >> rdiv;
+       *rate = *parent_rate >> rdiv;
 
        dev_dbg(&hwdata->drvdata->client->dev,
                "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n",
                __func__, __clk_get_name(hwdata->hw.clk), (1 << rdiv),
-               *parent_rate, rate);
+               *parent_rate, *rate);
 
-       return rate;
+       return 0;
 }
 
 static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/clk-si570.c b/drivers/clk/clk-si570.c
index 20a5aec..e60a956 100644
--- a/drivers/clk/clk-si570.c
+++ b/drivers/clk/clk-si570.c
@@ -245,7 +245,7 @@ static unsigned long si570_recalc_rate(struct clk_hw *hw,
        return rate;
 }
 
-static long si570_round_rate(struct clk_hw *hw, unsigned long rate,
+static int si570_round_rate(struct clk_hw *hw, unsigned long *rate,
                unsigned long *parent_rate)
 {
        int err;
@@ -253,26 +253,26 @@ static long si570_round_rate(struct clk_hw *hw, unsigned 
long rate,
        unsigned int n1, hs_div;
        struct clk_si570 *data = to_clk_si570(hw);
 
-       if (!rate)
+       if (!*rate)
                return 0;
 
-       if (div64_u64(abs(rate - data->frequency) * 10000LL,
+       if (div64_u64(abs(*rate - data->frequency) * 10000LL,
                                data->frequency) < 35) {
-               rfreq = div64_u64((data->rfreq * rate) +
+               rfreq = div64_u64((data->rfreq * *rate) +
                                div64_u64(data->frequency, 2), data->frequency);
                n1 = data->n1;
                hs_div = data->hs_div;
 
        } else {
-               err = si570_calc_divs(rate, data, &rfreq, &n1, &hs_div);
+               err = si570_calc_divs(*rate, data, &rfreq, &n1, &hs_div);
                if (err) {
                        dev_err(&data->i2c_client->dev,
                                        "unable to round rate\n");
-                       return 0;
+                       *rate = 0;
                }
        }
 
-       return rate;
+       return 0;
 }
 
 /**
diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c
index 406bfc1..5e3163b 100644
--- a/drivers/clk/clk-u300.c
+++ b/drivers/clk/clk-u300.c
@@ -628,22 +628,27 @@ syscon_clk_recalc_rate(struct clk_hw *hw,
        }
 }
 
-static long
-syscon_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+static int
+syscon_clk_round_rate(struct clk_hw *hw, unsigned long *rate,
                      unsigned long *prate)
 {
        struct clk_syscon *sclk = to_syscon(hw);
 
-       if (sclk->clk_val != U300_SYSCON_SBCER_CPU_CLK_EN)
-               return *prate;
+       if (sclk->clk_val != U300_SYSCON_SBCER_CPU_CLK_EN) {
+               *rate = *prate;
+               return 0;
+       }
        /* We really only support setting the rate of the CPU clock */
-       if (rate <= 13000000)
-               return 13000000;
-       if (rate <= 52000000)
-               return 52000000;
-       if (rate <= 104000000)
-               return 104000000;
-       return 208000000;
+       if (*rate <= 13000000)
+               *rate = 13000000;
+       else if (*rate <= 52000000)
+               *rate = 52000000;
+       else if (*rate <= 104000000)
+               *rate = 104000000;
+       else
+               *rate = 208000000;
+
+       return 0;
 }
 
 static int syscon_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -1037,26 +1042,28 @@ mclk_clk_recalc_rate(struct clk_hw *hw,
        return parent_rate;
 }
 
-static long
-mclk_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+static int
+mclk_clk_round_rate(struct clk_hw *hw, unsigned long *rate,
                    unsigned long *prate)
 {
-       if (rate <= 18900000)
-               return 18900000;
-       if (rate <= 20800000)
-               return 20800000;
-       if (rate <= 23100000)
-               return 23100000;
-       if (rate <= 26000000)
-               return 26000000;
-       if (rate <= 29700000)
-               return 29700000;
-       if (rate <= 34700000)
-               return 34700000;
-       if (rate <= 41600000)
-               return 41600000;
-       /* Highest rate */
-       return 52000000;
+       if (*rate <= 18900000)
+               *rate = 18900000;
+       else if (*rate <= 20800000)
+               *rate = 20800000;
+       else if (*rate <= 23100000)
+               *rate = 23100000;
+       else if (*rate <= 26000000)
+               *rate = 26000000;
+       else if (*rate <= 29700000)
+               *rate = 29700000;
+       else if (*rate <= 34700000)
+               *rate = 34700000;
+       else if (*rate <= 41600000)
+               *rate = 41600000;
+       else
+               *rate = 52000000;
+
+       return 0;
 }
 
 static int mclk_clk_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c
index 37e9288..221eec3 100644
--- a/drivers/clk/clk-vt8500.c
+++ b/drivers/clk/clk-vt8500.c
@@ -137,19 +137,19 @@ static unsigned long vt8500_dclk_recalc_rate(struct 
clk_hw *hw,
        return parent_rate / div;
 }
 
-static long vt8500_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
+static int vt8500_dclk_round_rate(struct clk_hw *hw, unsigned long *rate,
                                unsigned long *prate)
 {
        struct clk_device *cdev = to_clk_device(hw);
        u32 divisor;
 
-       if (rate == 0)
+       if (*rate == 0)
                return 0;
 
-       divisor = *prate / rate;
+       divisor = *prate / *rate;
 
        /* If prate / rate would be decimal, incr the divisor */
-       if (rate * divisor < *prate)
+       if (*rate * divisor < *prate)
                divisor++;
 
        /*
@@ -160,7 +160,8 @@ static long vt8500_dclk_round_rate(struct clk_hw *hw, 
unsigned long rate,
                divisor = 64 * ((divisor / 64) + 1);
        }
 
-       return *prate / divisor;
+       *rate = *prate / divisor;
+       return 0;
 }
 
 static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -579,8 +580,8 @@ static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned 
long rate,
        return 0;
 }
 
-static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long *prate)
+static int vtwm_pll_round_rate(struct clk_hw *hw, unsigned long *rate,
+                              unsigned long *prate)
 {
        struct clk_pll *pll = to_clk_pll(hw);
        u32 filter, mul, div1, div2;
@@ -588,26 +589,28 @@ static long vtwm_pll_round_rate(struct clk_hw *hw, 
unsigned long rate,
 
        switch (pll->type) {
        case PLL_TYPE_VT8500:
-               vt8500_find_pll_bits(rate, *prate, &mul, &div1);
+               vt8500_find_pll_bits(*rate, *prate, &mul, &div1);
                round_rate = VT8500_BITS_TO_FREQ(*prate, mul, div1);
                break;
        case PLL_TYPE_WM8650:
-               wm8650_find_pll_bits(rate, *prate, &mul, &div1, &div2);
+               wm8650_find_pll_bits(*rate, *prate, &mul, &div1, &div2);
                round_rate = WM8650_BITS_TO_FREQ(*prate, mul, div1, div2);
                break;
        case PLL_TYPE_WM8750:
-               wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2);
+               wm8750_find_pll_bits(*rate, *prate, &filter, &mul, &div1,
+                                    &div2);
                round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2);
                break;
        case PLL_TYPE_WM8850:
-               wm8850_find_pll_bits(rate, *prate, &mul, &div1, &div2);
+               wm8850_find_pll_bits(*rate, *prate, &mul, &div1, &div2);
                round_rate = WM8850_BITS_TO_FREQ(*prate, mul, div1, div2);
                break;
        default:
                round_rate = 0;
        }
 
-       return round_rate;
+       *rate = round_rate;
+       return 0;
 }
 
 static unsigned long vtwm_pll_recalc_rate(struct clk_hw *hw,
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
index ef67719..23db1b5 100644
--- a/drivers/clk/clk-wm831x.c
+++ b/drivers/clk/clk-wm831x.c
@@ -142,18 +142,19 @@ static unsigned long wm831x_fll_recalc_rate(struct clk_hw 
*hw,
        return 0;
 }
 
-static long wm831x_fll_round_rate(struct clk_hw *hw, unsigned long rate,
-                                 unsigned long *unused)
+static int wm831x_fll_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                unsigned long *unused)
 {
        int best = 0;
        int i;
 
        for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
-               if (abs(wm831x_fll_auto_rates[i] - rate) <
-                   abs(wm831x_fll_auto_rates[best] - rate))
+               if (abs(wm831x_fll_auto_rates[i] - *rate) <
+                   abs(wm831x_fll_auto_rates[best] - *rate))
                        best = i;
 
-       return wm831x_fll_auto_rates[best];
+       *rate = wm831x_fll_auto_rates[best];
+       return 0;
 }
 
 static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c
index dd8a62d..27460e3 100644
--- a/drivers/clk/clk-xgene.c
+++ b/drivers/clk/clk-xgene.c
@@ -367,7 +367,7 @@ static int xgene_clk_set_rate(struct clk_hw *hw, unsigned 
long rate,
        return parent_rate / divider_save;
 }
 
-static long xgene_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+static int xgene_clk_round_rate(struct clk_hw *hw, unsigned long *rate,
                                unsigned long *prate)
 {
        struct xgene_clk *pclk = to_xgene_clk(hw);
@@ -376,14 +376,15 @@ static long xgene_clk_round_rate(struct clk_hw *hw, 
unsigned long rate,
 
        if (pclk->param.divider_reg) {
                /* Let's compute the divider */
-               if (rate > parent_rate)
-                       rate = parent_rate;
-               divider = parent_rate / rate;   /* Rounded down */
+               if (*rate > parent_rate)
+                       *rate = parent_rate;
+               divider = parent_rate / *rate;   /* Rounded down */
        } else {
                divider = 1;
        }
 
-       return parent_rate / divider;
+       *rate = parent_rate / divider;
+       return 0;
 }
 
 const struct clk_ops xgene_clk_ops = {
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 459ce9d..6039bd2 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1146,9 +1146,12 @@ static unsigned long clk_core_round_rate_nolock(struct 
clk_core *clk,
                return clk->ops->determine_rate(clk->hw, rate,
                                                min_rate, max_rate,
                                                &parent_rate, &parent_hw);
-       } else if (clk->ops->round_rate)
-               return clk->ops->round_rate(clk->hw, rate, &parent_rate);
-       else if (clk->flags & CLK_SET_RATE_PARENT)
+       } else if (clk->ops->round_rate) {
+               if (clk->ops->round_rate(clk->hw, &rate, &parent_rate))
+                       return 0;
+
+               return rate;
+       } else if (clk->flags & CLK_SET_RATE_PARENT)
                return clk_core_round_rate_nolock(clk->parent, rate, min_rate,
                                                  max_rate);
        else
@@ -1614,7 +1617,7 @@ static struct clk_core *clk_calc_new_rates(struct 
clk_core *clk,
        struct clk_core *old_parent, *parent;
        struct clk_hw *parent_hw;
        unsigned long best_parent_rate = 0;
-       unsigned long new_rate;
+       unsigned long new_rate = rate;
        unsigned long min_rate;
        unsigned long max_rate;
        int p_index = 0;
@@ -1645,12 +1648,11 @@ static struct clk_core *clk_calc_new_rates(struct 
clk_core *clk,
                new_rate = ret;
                parent = parent_hw ? parent_hw->core : NULL;
        } else if (clk->ops->round_rate) {
-               ret = clk->ops->round_rate(clk->hw, rate,
+               ret = clk->ops->round_rate(clk->hw, &new_rate,
                                           &best_parent_rate);
                if (ret < 0)
                        return NULL;
 
-               new_rate = ret;
                if (new_rate < min_rate || new_rate > max_rate)
                        return NULL;
        } else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 584a992..6652983 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -24,7 +24,7 @@
 
 #define to_clk_factor(hw) container_of(hw, struct mmp_clk_factor, hw)
 
-static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
+static int clk_factor_round_rate(struct clk_hw *hw, unsigned long *drate,
                unsigned long *prate)
 {
        struct mmp_clk_factor *factor = to_clk_factor(hw);
@@ -35,17 +35,19 @@ static long clk_factor_round_rate(struct clk_hw *hw, 
unsigned long drate,
                prev_rate = rate;
                rate = (((*prate / 10000) * factor->ftbl[i].den) /
                        (factor->ftbl[i].num * factor->masks->factor)) * 10000;
-               if (rate > drate)
+               if (rate > *drate)
                        break;
        }
        if ((i == 0) || (i == factor->ftbl_cnt)) {
-               return rate;
+               *drate = rate;
        } else {
-               if ((drate - prev_rate) > (rate - drate))
-                       return rate;
+               if ((*drate - prev_rate) > (rate - *drate))
+                       *drate = rate;
                else
-                       return prev_rate;
+                       *drate = prev_rate;
        }
+
+       return 0;
 }
 
 static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
diff --git a/drivers/clk/mvebu/clk-corediv.c b/drivers/clk/mvebu/clk-corediv.c
index d1e5863..c5aee2f 100644
--- a/drivers/clk/mvebu/clk-corediv.c
+++ b/drivers/clk/mvebu/clk-corediv.c
@@ -132,19 +132,20 @@ static unsigned long clk_corediv_recalc_rate(struct 
clk_hw *hwclk,
        return parent_rate / div;
 }
 
-static long clk_corediv_round_rate(struct clk_hw *hwclk, unsigned long rate,
+static int clk_corediv_round_rate(struct clk_hw *hwclk, unsigned long *rate,
                               unsigned long *parent_rate)
 {
        /* Valid ratio are 1:4, 1:5, 1:6 and 1:8 */
        u32 div;
 
-       div = *parent_rate / rate;
+       div = *parent_rate / *rate;
        if (div < 4)
                div = 4;
        else if (div > 6)
                div = 8;
 
-       return *parent_rate / div;
+       *rate = *parent_rate / div;
+       return 0;
 }
 
 static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate,
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
index 3821a88..0279b50 100644
--- a/drivers/clk/mvebu/clk-cpu.c
+++ b/drivers/clk/mvebu/clk-cpu.c
@@ -57,19 +57,20 @@ static unsigned long clk_cpu_recalc_rate(struct clk_hw 
*hwclk,
        return parent_rate / div;
 }
 
-static long clk_cpu_round_rate(struct clk_hw *hwclk, unsigned long rate,
-                              unsigned long *parent_rate)
+static int clk_cpu_round_rate(struct clk_hw *hwclk, unsigned long *rate,
+                             unsigned long *parent_rate)
 {
        /* Valid ratio are 1:1, 1:2 and 1:3 */
        u32 div;
 
-       div = *parent_rate / rate;
+       div = *parent_rate / *rate;
        if (div == 0)
                div = 1;
        else if (div > 3)
                div = 3;
 
-       return *parent_rate / div;
+       *rate = *parent_rate / div;
+       return 0;
 }
 
 static int clk_cpu_off_set_rate(struct clk_hw *hwclk, unsigned long rate,
diff --git a/drivers/clk/mxs/clk-div.c b/drivers/clk/mxs/clk-div.c
index 90e1da9..3677e51 100644
--- a/drivers/clk/mxs/clk-div.c
+++ b/drivers/clk/mxs/clk-div.c
@@ -47,8 +47,8 @@ static unsigned long clk_div_recalc_rate(struct clk_hw *hw,
        return div->ops->recalc_rate(&div->divider.hw, parent_rate);
 }
 
-static long clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
-                              unsigned long *prate)
+static int clk_div_round_rate(struct clk_hw *hw, unsigned long *rate,
+                             unsigned long *prate)
 {
        struct clk_div *div = to_clk_div(hw);
 
diff --git a/drivers/clk/mxs/clk-frac.c b/drivers/clk/mxs/clk-frac.c
index e6aa6b5..86fc3bb 100644
--- a/drivers/clk/mxs/clk-frac.c
+++ b/drivers/clk/mxs/clk-frac.c
@@ -49,18 +49,18 @@ static unsigned long clk_frac_recalc_rate(struct clk_hw *hw,
        return (parent_rate >> frac->width) * div;
 }
 
-static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
-                               unsigned long *prate)
+static int clk_frac_round_rate(struct clk_hw *hw, unsigned long *rate,
+                              unsigned long *prate)
 {
        struct clk_frac *frac = to_clk_frac(hw);
        unsigned long parent_rate = *prate;
        u32 div;
        u64 tmp;
 
-       if (rate > parent_rate)
+       if (*rate > parent_rate)
                return -EINVAL;
 
-       tmp = rate;
+       tmp = *rate;
        tmp <<= frac->width;
        do_div(tmp, parent_rate);
        div = tmp;
@@ -68,7 +68,8 @@ static long clk_frac_round_rate(struct clk_hw *hw, unsigned 
long rate,
        if (!div)
                return -EINVAL;
 
-       return (parent_rate >> frac->width) * div;
+       *rate = (parent_rate >> frac->width) * div;
+       return 0;
 }
 
 static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/mxs/clk-ref.c b/drivers/clk/mxs/clk-ref.c
index 4adeed6..e0d6529 100644
--- a/drivers/clk/mxs/clk-ref.c
+++ b/drivers/clk/mxs/clk-ref.c
@@ -64,15 +64,15 @@ static unsigned long clk_ref_recalc_rate(struct clk_hw *hw,
        return tmp;
 }
 
-static long clk_ref_round_rate(struct clk_hw *hw, unsigned long rate,
-                              unsigned long *prate)
+static int clk_ref_round_rate(struct clk_hw *hw, unsigned long *rate,
+                             unsigned long *prate)
 {
        unsigned long parent_rate = *prate;
        u64 tmp = parent_rate;
        u8 frac;
 
-       tmp = tmp * 18 + rate / 2;
-       do_div(tmp, rate);
+       tmp = tmp * 18 + *rate / 2;
+       do_div(tmp, *rate);
        frac = tmp;
 
        if (frac < 18)
@@ -83,8 +83,9 @@ static long clk_ref_round_rate(struct clk_hw *hw, unsigned 
long rate,
        tmp = parent_rate;
        tmp *= 18;
        do_div(tmp, frac);
+       *rate = tmp;
 
-       return tmp;
+       return 0;
 }
 
 static int clk_ref_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/qcom/clk-regmap-divider.c 
b/drivers/clk/qcom/clk-regmap-divider.c
index 5348491..1720da4 100644
--- a/drivers/clk/qcom/clk-regmap-divider.c
+++ b/drivers/clk/qcom/clk-regmap-divider.c
@@ -23,8 +23,8 @@ static inline struct clk_regmap_div *to_clk_regmap_div(struct 
clk_hw *hw)
        return container_of(to_clk_regmap(hw), struct clk_regmap_div, clkr);
 }
 
-static long div_round_rate(struct clk_hw *hw, unsigned long rate,
-                          unsigned long *prate)
+static int div_round_rate(struct clk_hw *hw, unsigned long *rate,
+                         unsigned long *prate)
 {
        struct clk_regmap_div *divider = to_clk_regmap_div(hw);
 
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index f8d3baf..bd408ef 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -63,8 +63,8 @@ static const struct rockchip_pll_rate_table 
*rockchip_get_pll_settings(
        return NULL;
 }
 
-static long rockchip_pll_round_rate(struct clk_hw *hw,
-                           unsigned long drate, unsigned long *prate)
+static int rockchip_pll_round_rate(struct clk_hw *hw,
+                           unsigned long *drate, unsigned long *prate)
 {
        struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
        const struct rockchip_pll_rate_table *rate_table = pll->rate_table;
@@ -72,12 +72,15 @@ static long rockchip_pll_round_rate(struct clk_hw *hw,
 
        /* Assumming rate_table is in descending order */
        for (i = 0; i < pll->rate_count; i++) {
-               if (drate >= rate_table[i].rate)
-                       return rate_table[i].rate;
+               if (*drate >= rate_table[i].rate) {
+                       *drate = rate_table[i].rate;
+                       return 0;
+               }
        }
 
        /* return minimum supported value */
-       return rate_table[i - 1].rate;
+       *drate = rate_table[i - 1].rate;
+       return 0;
 }
 
 /*
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 9d70e5c..0128de2 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -42,8 +42,8 @@ static const struct samsung_pll_rate_table 
*samsung_get_pll_settings(
        return NULL;
 }
 
-static long samsung_pll_round_rate(struct clk_hw *hw,
-                       unsigned long drate, unsigned long *prate)
+static int samsung_pll_round_rate(struct clk_hw *hw,
+                       unsigned long *drate, unsigned long *prate)
 {
        struct samsung_clk_pll *pll = to_clk_pll(hw);
        const struct samsung_pll_rate_table *rate_table = pll->rate_table;
@@ -51,12 +51,15 @@ static long samsung_pll_round_rate(struct clk_hw *hw,
 
        /* Assumming rate_table is in descending order */
        for (i = 0; i < pll->rate_count; i++) {
-               if (drate >= rate_table[i].rate)
-                       return rate_table[i].rate;
+               if (*drate >= rate_table[i].rate) {
+                       *drate = rate_table[i].rate;
+                       return 0;
+               }
        }
 
        /* return minimum supported value */
-       return rate_table[i - 1].rate;
+       *drate = rate_table[i - 1].rate;
+       return 0;
 }
 
 /*
diff --git a/drivers/clk/shmobile/clk-div6.c b/drivers/clk/shmobile/clk-div6.c
index 036a692..d31ae3d 100644
--- a/drivers/clk/shmobile/clk-div6.c
+++ b/drivers/clk/shmobile/clk-div6.c
@@ -97,12 +97,13 @@ static unsigned int cpg_div6_clock_calc_div(unsigned long 
rate,
        return clamp_t(unsigned int, div, 1, 64);
 }
 
-static long cpg_div6_clock_round_rate(struct clk_hw *hw, unsigned long rate,
+static int cpg_div6_clock_round_rate(struct clk_hw *hw, unsigned long *rate,
                                      unsigned long *parent_rate)
 {
-       unsigned int div = cpg_div6_clock_calc_div(rate, *parent_rate);
+       unsigned int div = cpg_div6_clock_calc_div(*rate, *parent_rate);
 
-       return *parent_rate / div;
+       *rate = *parent_rate / div;
+       return 0;
 }
 
 static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c 
b/drivers/clk/shmobile/clk-rcar-gen2.c
index acfb6d7..57581a9 100644
--- a/drivers/clk/shmobile/clk-rcar-gen2.c
+++ b/drivers/clk/shmobile/clk-rcar-gen2.c
@@ -68,8 +68,8 @@ static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
        return div_u64((u64)parent_rate * mult, 32);
 }
 
-static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long *parent_rate)
+static int cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long *rate,
+                               unsigned long *parent_rate)
 {
        unsigned long prate  = *parent_rate;
        unsigned int mult;
@@ -77,10 +77,11 @@ static long cpg_z_clk_round_rate(struct clk_hw *hw, 
unsigned long rate,
        if (!prate)
                prate = 1;
 
-       mult = div_u64((u64)rate * 32, prate);
+       mult = div_u64((u64)*rate * 32, prate);
        mult = clamp(mult, 1U, 32U);
 
-       return *parent_rate / 32 * mult;
+       *rate = *parent_rate / 32 * mult;
+       return 0;
 }
 
 static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/sirf/clk-common.c b/drivers/clk/sirf/clk-common.c
index 37af51c..68a7889 100644
--- a/drivers/clk/sirf/clk-common.c
+++ b/drivers/clk/sirf/clk-common.c
@@ -91,7 +91,7 @@ static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
        }
 }
 
-static long pll_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+static int pll_clk_round_rate(struct clk_hw *hw, unsigned long *rate,
        unsigned long *parent_rate)
 {
        unsigned long fin, nf, nr, od;
@@ -101,9 +101,9 @@ static long pll_clk_round_rate(struct clk_hw *hw, unsigned 
long rate,
         * fout = fin * nf / (nr * od);
         * set od = 1, nr = fin/MHz, so fout = nf * MHz
         */
-       rate = rate - rate % MHZ;
+       *rate = *rate - *rate % MHZ;
 
-       nf = rate / MHZ;
+       nf = *rate / MHZ;
        if (nf > BIT(13))
                nf = BIT(13);
        if (nf < 1)
@@ -119,7 +119,8 @@ static long pll_clk_round_rate(struct clk_hw *hw, unsigned 
long rate,
        dividend = (u64)fin * nf;
        do_div(dividend, nr * od);
 
-       return (long)dividend;
+       *rate = dividend;
+       return 0;
 }
 
 static int pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -158,7 +159,7 @@ static int pll_clk_set_rate(struct clk_hw *hw, unsigned 
long rate,
        return 0;
 }
 
-static long cpu_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+static int cpu_clk_round_rate(struct clk_hw *hw, unsigned long *rate,
        unsigned long *parent_rate)
 {
        /*
@@ -347,7 +348,7 @@ static unsigned long dmn_clk_recalc_rate(struct clk_hw *hw,
        }
 }
 
-static long dmn_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+static int dmn_clk_round_rate(struct clk_hw *hw, unsigned long *rate,
        unsigned long *parent_rate)
 {
        unsigned long fin;
@@ -355,7 +356,7 @@ static long dmn_clk_round_rate(struct clk_hw *hw, unsigned 
long rate,
        unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4;
 
        fin = *parent_rate;
-       ratio = fin / rate;
+       ratio = fin / *rate;
 
        if (ratio < 2)
                ratio = 2;
@@ -365,7 +366,8 @@ static long dmn_clk_round_rate(struct clk_hw *hw, unsigned 
long rate,
        wait = (ratio >> 1) - 1;
        hold = ratio - wait - 2;
 
-       return fin / (wait + hold + 2);
+       *rate = fin / (wait + hold + 2);
+       return 0;
 }
 
 static int dmn_clk_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/spear/clk-aux-synth.c 
b/drivers/clk/spear/clk-aux-synth.c
index bdfb442..1a93f6a 100644
--- a/drivers/clk/spear/clk-aux-synth.c
+++ b/drivers/clk/spear/clk-aux-synth.c
@@ -52,14 +52,20 @@ static unsigned long aux_calc_rate(struct clk_hw *hw, 
unsigned long prate,
                        (rtbl[index].yscale * eq)) * 10000;
 }
 
-static long clk_aux_round_rate(struct clk_hw *hw, unsigned long drate,
+static int clk_aux_round_rate(struct clk_hw *hw, unsigned long *drate,
                unsigned long *prate)
 {
        struct clk_aux *aux = to_clk_aux(hw);
        int unused;
+       long ret;
 
-       return clk_round_rate_index(hw, drate, *prate, aux_calc_rate,
+       ret = clk_round_rate_index(hw, *drate, *prate, aux_calc_rate,
                        aux->rtbl_cnt, &unused);
+       if (ret < 0)
+               return ret;
+
+       *drate = ret;
+       return 0;
 }
 
 static unsigned long clk_aux_recalc_rate(struct clk_hw *hw,
diff --git a/drivers/clk/spear/clk-frac-synth.c 
b/drivers/clk/spear/clk-frac-synth.c
index dffd4ce..d4098c8 100644
--- a/drivers/clk/spear/clk-frac-synth.c
+++ b/drivers/clk/spear/clk-frac-synth.c
@@ -55,14 +55,20 @@ static unsigned long frac_calc_rate(struct clk_hw *hw, 
unsigned long prate,
        return prate;
 }
 
-static long clk_frac_round_rate(struct clk_hw *hw, unsigned long drate,
+static int clk_frac_round_rate(struct clk_hw *hw, unsigned long *drate,
                unsigned long *prate)
 {
        struct clk_frac *frac = to_clk_frac(hw);
        int unused;
+       long ret;
 
-       return clk_round_rate_index(hw, drate, *prate, frac_calc_rate,
+       ret = clk_round_rate_index(hw, *drate, *prate, frac_calc_rate,
                        frac->rtbl_cnt, &unused);
+       if (ret < 0)
+               return ret;
+
+       *drate = ret;
+       return 0;
 }
 
 static unsigned long clk_frac_recalc_rate(struct clk_hw *hw,
diff --git a/drivers/clk/spear/clk-gpt-synth.c 
b/drivers/clk/spear/clk-gpt-synth.c
index 1afc18c..ea3328b 100644
--- a/drivers/clk/spear/clk-gpt-synth.c
+++ b/drivers/clk/spear/clk-gpt-synth.c
@@ -42,14 +42,20 @@ static unsigned long gpt_calc_rate(struct clk_hw *hw, 
unsigned long prate,
        return prate;
 }
 
-static long clk_gpt_round_rate(struct clk_hw *hw, unsigned long drate,
+static int clk_gpt_round_rate(struct clk_hw *hw, unsigned long *drate,
                unsigned long *prate)
 {
        struct clk_gpt *gpt = to_clk_gpt(hw);
        int unused;
+       long ret;
 
-       return clk_round_rate_index(hw, drate, *prate, gpt_calc_rate,
+       ret = clk_round_rate_index(hw, *drate, *prate, gpt_calc_rate,
                        gpt->rtbl_cnt, &unused);
+       if (ret < 0)
+               return ret;
+
+       *drate = ret;
+       return 0;
 }
 
 static unsigned long clk_gpt_recalc_rate(struct clk_hw *hw,
diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c
index 1b9b65b..08b1411 100644
--- a/drivers/clk/spear/clk-vco-pll.c
+++ b/drivers/clk/spear/clk-vco-pll.c
@@ -113,12 +113,18 @@ static long clk_pll_round_rate_index(struct clk_hw *hw, 
unsigned long drate,
        return rate;
 }
 
-static long clk_pll_round_rate(struct clk_hw *hw, unsigned long drate,
+static int clk_pll_round_rate(struct clk_hw *hw, unsigned long *drate,
                                unsigned long *prate)
 {
        int unused;
+       long ret;
 
-       return clk_pll_round_rate_index(hw, drate, prate, &unused);
+       ret = clk_pll_round_rate_index(hw, *drate, prate, &unused);
+       if (ret < 0)
+               return ret;
+
+       *drate = ret;
+       return 0;
 }
 
 static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long
@@ -179,14 +185,20 @@ static inline unsigned long vco_calc_rate(struct clk_hw 
*hw,
        return pll_calc_rate(vco->rtbl, prate, index, NULL);
 }
 
-static long clk_vco_round_rate(struct clk_hw *hw, unsigned long drate,
+static int clk_vco_round_rate(struct clk_hw *hw, unsigned long *drate,
                unsigned long *prate)
 {
        struct clk_vco *vco = to_clk_vco(hw);
        int unused;
+       long ret;
 
-       return clk_round_rate_index(hw, drate, *prate, vco_calc_rate,
+       ret = clk_round_rate_index(hw, *drate, *prate, vco_calc_rate,
                        vco->rtbl_cnt, &unused);
+       if (ret < 0)
+               return ret;
+
+       *drate = ret;
+       return 0;
 }
 
 static unsigned long clk_vco_recalc_rate(struct clk_hw *hw,
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index bf12a25..d04278b 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -100,20 +100,21 @@ clk_best_div(unsigned long parent_rate, unsigned long 
rate)
        return parent_rate / rate + ((rate > (2*(parent_rate % rate))) ? 0 : 1);
 }
 
-static long flexgen_round_rate(struct clk_hw *hw, unsigned long rate,
+static int flexgen_round_rate(struct clk_hw *hw, unsigned long *rate,
                                   unsigned long *prate)
 {
        unsigned long div;
 
        /* Round div according to exact prate and wished rate */
-       div = clk_best_div(*prate, rate);
+       div = clk_best_div(*prate, *rate);
 
        if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
-               *prate = rate * div;
-               return rate;
+               *prate = *rate * div;
+               return 0;
        }
 
-       return *prate / div;
+       *rate = *prate / div;
+       return 0;
 }
 
 unsigned long flexgen_recalc_rate(struct clk_hw *hw,
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
index a917c4c..f50d571 100644
--- a/drivers/clk/st/clkgen-fsyn.c
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -548,21 +548,22 @@ int clk_fs660c32_vco_get_params(unsigned long input,
        return 0;
 }
 
-static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw, unsigned long 
rate
-               , unsigned long *prate)
+static int quadfs_pll_fs660c32_round_rate(struct clk_hw *hw,
+                                         unsigned long *rate,
+                                         unsigned long *prate)
 {
        struct stm_fs params;
 
-       if (!clk_fs660c32_vco_get_params(*prate, rate, &params))
-               clk_fs660c32_vco_get_rate(*prate, &params, &rate);
+       if (!clk_fs660c32_vco_get_params(*prate, *rate, &params))
+               clk_fs660c32_vco_get_rate(*prate, &params, rate);
 
        pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
                 __func__, __clk_get_name(hw->clk),
-                rate, (unsigned int)params.sdiv,
+                *rate, (unsigned int)params.sdiv,
                 (unsigned int)params.mdiv,
                 (unsigned int)params.pe, (unsigned int)params.nsdiv);
 
-       return rate;
+       return 0;
 }
 
 static int quadfs_pll_fs660c32_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -953,19 +954,19 @@ static unsigned long quadfs_recalc_rate(struct clk_hw *hw,
        return rate;
 }
 
-static long quadfs_round_rate(struct clk_hw *hw, unsigned long rate,
+static int quadfs_round_rate(struct clk_hw *hw, unsigned long *rate,
                                     unsigned long *prate)
 {
        struct stm_fs params;
 
-       rate = quadfs_find_best_rate(hw, rate, *prate, &params);
+       *rate = quadfs_find_best_rate(hw, *rate, *prate, &params);
 
        pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
                 __func__, __clk_get_name(hw->clk),
-                rate, (unsigned int)params.sdiv, (unsigned int)params.mdiv,
+                *rate, (unsigned int)params.sdiv, (unsigned int)params.mdiv,
                         (unsigned int)params.pe, (unsigned int)params.nsdiv);
 
-       return rate;
+       return 0;
 }
 
 
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index fdcff10..7a42b6c 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -190,7 +190,7 @@ static int clkgena_divmux_set_rate(struct clk_hw *hw, 
unsigned long rate,
        return clk_divider_ops.set_rate(div_hw, rate, parent_rate);
 }
 
-static long clkgena_divmux_round_rate(struct clk_hw *hw, unsigned long rate,
+static int clkgena_divmux_round_rate(struct clk_hw *hw, unsigned long *rate,
                                   unsigned long *prate)
 {
        struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 8c20190..5865300 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -69,14 +69,17 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw 
*hw,
        return rate;
 }
 
-static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
-                                  unsigned long *parent_rate)
+static int clk_factors_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                 unsigned long *parent_rate)
 {
        struct clk_factors *factors = to_clk_factors(hw);
-       factors->get_factors((u32 *)&rate, (u32)*parent_rate,
+       u32 tmp_rate = *rate;
+
+       factors->get_factors(&tmp_rate, (u32)*parent_rate,
                             NULL, NULL, NULL, NULL);
 
-       return rate;
+       *rate = tmp_rate;
+       return 0;
 }
 
 static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
@@ -100,7 +103,8 @@ static long clk_factors_determine_rate(struct clk_hw *hw, 
unsigned long rate,
                else
                        parent_rate = __clk_get_rate(parent);
 
-               child_rate = clk_factors_round_rate(hw, rate, &parent_rate);
+               child_rate = rate;
+               clk_factors_round_rate(hw, &child_rate, &parent_rate);
 
                if (child_rate <= rate && child_rate > best_child_rate) {
                        best_parent = parent;
diff --git a/drivers/clk/tegra/clk-audio-sync.c 
b/drivers/clk/tegra/clk-audio-sync.c
index c0f7843..0224256 100644
--- a/drivers/clk/tegra/clk-audio-sync.c
+++ b/drivers/clk/tegra/clk-audio-sync.c
@@ -28,15 +28,15 @@ static unsigned long clk_sync_source_recalc_rate(struct 
clk_hw *hw,
        return sync->rate;
 }
 
-static long clk_sync_source_round_rate(struct clk_hw *hw, unsigned long rate,
-                                      unsigned long *prate)
+static int clk_sync_source_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                     unsigned long *prate)
 {
        struct tegra_clk_sync_source *sync = to_clk_sync_source(hw);
 
-       if (rate > sync->max_rate)
+       if (*rate > sync->max_rate)
                return -EINVAL;
        else
-               return rate;
+               return 0;
 }
 
 static int clk_sync_source_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c
index 59a5714..9e5ca82 100644
--- a/drivers/clk/tegra/clk-divider.c
+++ b/drivers/clk/tegra/clk-divider.c
@@ -85,23 +85,28 @@ static unsigned long clk_frac_div_recalc_rate(struct clk_hw 
*hw,
        return rate;
 }
 
-static long clk_frac_div_round_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_frac_div_round_rate(struct clk_hw *hw, unsigned long *rate,
                                   unsigned long *prate)
 {
        struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
        int div, mul;
        unsigned long output_rate = *prate;
 
-       if (!rate)
-               return output_rate;
+       if (!*rate) {
+               *rate = output_rate;
+               return 0;
+       }
 
-       div = get_div(divider, rate, output_rate);
-       if (div < 0)
-               return *prate;
+       div = get_div(divider, *rate, output_rate);
+       if (div < 0) {
+               *rate = *prate;
+               return 0;
+       }
 
        mul = get_mul(divider);
 
-       return DIV_ROUND_UP(output_rate * mul, div + mul);
+       *rate = DIV_ROUND_UP(output_rate * mul, div + mul);
+       return 0;
 }
 
 static int clk_frac_div_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index d84ae49..5a262f5 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -56,8 +56,8 @@ static unsigned long clk_periph_recalc_rate(struct clk_hw *hw,
        return div_ops->recalc_rate(div_hw, parent_rate);
 }
 
-static long clk_periph_round_rate(struct clk_hw *hw, unsigned long rate,
-                                 unsigned long *prate)
+static int clk_periph_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                unsigned long *prate)
 {
        struct tegra_clk_periph *periph = to_clk_periph(hw);
        const struct clk_ops *div_ops = periph->div_ops;
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 05c6d08..40ff3c5 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -623,24 +623,29 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned 
long rate,
        return ret;
 }
 
-static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_pll_round_rate(struct clk_hw *hw, unsigned long *rate,
                        unsigned long *prate)
 {
        struct tegra_clk_pll *pll = to_clk_pll(hw);
        struct tegra_clk_pll_freq_table cfg;
 
-       if (pll->params->flags & TEGRA_PLL_FIXED)
-               return pll->params->fixed_rate;
+       if (pll->params->flags & TEGRA_PLL_FIXED) {
+               *rate = pll->params->fixed_rate;
+               return 0;
+       }
 
        /* PLLM is used for memory; we do not change rate */
-       if (pll->params->flags & TEGRA_PLLM)
-               return __clk_get_rate(hw->clk);
+       if (pll->params->flags & TEGRA_PLLM) {
+               *rate = __clk_get_rate(hw->clk);
+               return 0;
+       }
 
-       if (_get_table_rate(hw, &cfg, rate, *prate) &&
-           _calc_rate(hw, &cfg, rate, *prate))
+       if (_get_table_rate(hw, &cfg, *rate, *prate) &&
+           _calc_rate(hw, &cfg, *rate, *prate))
                return -EINVAL;
 
-       return cfg.output_rate;
+       *rate = cfg.output_rate;
+       return 0;
 }
 
 static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
@@ -1001,25 +1006,28 @@ static int clk_pllxc_set_rate(struct clk_hw *hw, 
unsigned long rate,
        return ret;
 }
 
-static long clk_pll_ramp_round_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_pll_ramp_round_rate(struct clk_hw *hw, unsigned long *rate,
                                unsigned long *prate)
 {
        struct tegra_clk_pll_freq_table cfg;
        int ret, p_div;
        u64 output_rate = *prate;
 
-       ret = _pll_ramp_calc_pll(hw, &cfg, rate, *prate);
+       ret = _pll_ramp_calc_pll(hw, &cfg, *rate, *prate);
        if (ret < 0)
                return ret;
 
        p_div = _hw_to_p_div(hw, cfg.p);
-       if (p_div < 0)
-               return p_div;
+       if (p_div < 0) {
+               *rate = p_div;
+               return 0;
+       }
 
        output_rate *= cfg.n;
        do_div(output_rate, cfg.m * p_div);
 
-       return output_rate;
+       *rate = output_rate;
+       return 0;
 }
 
 static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -1273,12 +1281,13 @@ static unsigned long clk_pllre_recalc_rate(struct 
clk_hw *hw,
        return rate;
 }
 
-static long clk_pllre_round_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_pllre_round_rate(struct clk_hw *hw, unsigned long *rate,
                                 unsigned long *prate)
 {
        struct tegra_clk_pll *pll = to_clk_pll(hw);
 
-       return _pllre_calc_rate(pll, NULL, rate, *prate);
+       *rate = _pllre_calc_rate(pll, NULL, *rate, *prate);
+       return 0;
 }
 
 static int clk_plle_tegra114_enable(struct clk_hw *hw)
diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
index d86bc46..3264cc3 100644
--- a/drivers/clk/ti/clk-dra7-atl.c
+++ b/drivers/clk/ti/clk-dra7-atl.c
@@ -124,16 +124,17 @@ static unsigned long atl_clk_recalc_rate(struct clk_hw 
*hw,
        return parent_rate / cdesc->divider;
 }
 
-static long atl_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-                              unsigned long *parent_rate)
+static int atl_clk_round_rate(struct clk_hw *hw, unsigned long *rate,
+                             unsigned long *parent_rate)
 {
        unsigned divider;
 
-       divider = (*parent_rate + rate / 2) / rate;
+       divider = (*parent_rate + *rate / 2) / *rate;
        if (divider > DRA7_ATL_DIVIDER_MASK + 1)
                divider = DRA7_ATL_DIVIDER_MASK + 1;
 
-       return *parent_rate / divider;
+       *rate = *parent_rate / divider;
+       return 0;
 }
 
 static int atl_clk_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c
index 96f83ce..6900a45 100644
--- a/drivers/clk/ti/composite.c
+++ b/drivers/clk/ti/composite.c
@@ -36,8 +36,8 @@ static unsigned long ti_composite_recalc_rate(struct clk_hw 
*hw,
        return ti_clk_divider_ops.recalc_rate(hw, parent_rate);
 }
 
-static long ti_composite_round_rate(struct clk_hw *hw, unsigned long rate,
-                                   unsigned long *prate)
+static int ti_composite_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                  unsigned long *prate)
 {
        return -EINVAL;
 }
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index ff5f117..6044251 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -200,13 +200,14 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, 
unsigned long rate,
        return bestdiv;
 }
 
-static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
-                                     unsigned long *prate)
+static int ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                    unsigned long *prate)
 {
        int div;
-       div = ti_clk_divider_bestdiv(hw, rate, prate);
+       div = ti_clk_divider_bestdiv(hw, *rate, prate);
 
-       return DIV_ROUND_UP(*prate, div);
+       *rate = DIV_ROUND_UP(*prate, div);
+       return 0;
 }
 
 static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
index bf63c96..1e1aa2d 100644
--- a/drivers/clk/ux500/clk-prcmu.c
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -80,11 +80,18 @@ static unsigned long clk_prcmu_recalc_rate(struct clk_hw 
*hw,
        return prcmu_clock_rate(clk->cg_sel);
 }
 
-static long clk_prcmu_round_rate(struct clk_hw *hw, unsigned long rate,
-                                unsigned long *parent_rate)
+static int clk_prcmu_round_rate(struct clk_hw *hw, unsigned long *rate,
+                               unsigned long *parent_rate)
 {
        struct clk_prcmu *clk = to_clk_prcmu(hw);
-       return prcmu_round_clock_rate(clk->cg_sel, rate);
+       long ret;
+
+       ret = prcmu_round_clock_rate(clk->cg_sel, *rate);
+       if (ret < 0)
+               return ret;
+
+       *rate = ret;
+       return 0;
 }
 
 static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
index bc96f10..6404e61 100644
--- a/drivers/clk/versatile/clk-icst.c
+++ b/drivers/clk/versatile/clk-icst.c
@@ -91,14 +91,15 @@ static unsigned long icst_recalc_rate(struct clk_hw *hw,
        return icst->rate;
 }
 
-static long icst_round_rate(struct clk_hw *hw, unsigned long rate,
-                           unsigned long *prate)
+static int icst_round_rate(struct clk_hw *hw, unsigned long *rate,
+                          unsigned long *prate)
 {
        struct clk_icst *icst = to_icst(hw);
        struct icst_vco vco;
 
-       vco = icst_hz_to_vco(icst->params, rate);
-       return icst_hz(icst->params, vco);
+       vco = icst_hz_to_vco(icst->params, *rate);
+       *rate = icst_hz(icst->params, vco);
+       return 0;
 }
 
 static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c 
b/drivers/clk/versatile/clk-vexpress-osc.c
index 89c0609..36d74b5 100644
--- a/drivers/clk/versatile/clk-vexpress-osc.c
+++ b/drivers/clk/versatile/clk-vexpress-osc.c
@@ -39,18 +39,18 @@ static unsigned long vexpress_osc_recalc_rate(struct clk_hw 
*hw,
        return rate;
 }
 
-static long vexpress_osc_round_rate(struct clk_hw *hw, unsigned long rate,
+static int vexpress_osc_round_rate(struct clk_hw *hw, unsigned long *rate,
                unsigned long *parent_rate)
 {
        struct vexpress_osc *osc = to_vexpress_osc(hw);
 
-       if (WARN_ON(osc->rate_min && rate < osc->rate_min))
-               rate = osc->rate_min;
+       if (WARN_ON(osc->rate_min && *rate < osc->rate_min))
+               *rate = osc->rate_min;
 
-       if (WARN_ON(osc->rate_max && rate > osc->rate_max))
-               rate = osc->rate_max;
+       if (WARN_ON(osc->rate_max && *rate > osc->rate_max))
+               *rate = osc->rate_max;
 
-       return rate;
+       return 0;
 }
 
 static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/zynq/pll.c b/drivers/clk/zynq/pll.c
index 00d72fb..b62d298 100644
--- a/drivers/clk/zynq/pll.c
+++ b/drivers/clk/zynq/pll.c
@@ -60,18 +60,19 @@ struct zynq_pll {
  * @prate:     Clock frequency of parent clock
  * Returns frequency closest to @rate the hardware can generate.
  */
-static long zynq_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+static int zynq_pll_round_rate(struct clk_hw *hw, unsigned long *rate,
                unsigned long *prate)
 {
        u32 fbdiv;
 
-       fbdiv = DIV_ROUND_CLOSEST(rate, *prate);
+       fbdiv = DIV_ROUND_CLOSEST(*rate, *prate);
        if (fbdiv < PLL_FBDIV_MIN)
                fbdiv = PLL_FBDIV_MIN;
        else if (fbdiv > PLL_FBDIV_MAX)
                fbdiv = PLL_FBDIV_MAX;
 
-       return *prate * fbdiv;
+       *rate = *prate * fbdiv;
+       return 0;
 }
 
 /**
diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
index 4216e47..0695428 100644
--- a/drivers/gpu/drm/imx/imx-tve.c
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -423,17 +423,20 @@ static unsigned long clk_tve_di_recalc_rate(struct clk_hw 
*hw,
        return 0;
 }
 
-static long clk_tve_di_round_rate(struct clk_hw *hw, unsigned long rate,
-                                 unsigned long *prate)
+static int clk_tve_di_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                unsigned long *prate)
 {
        unsigned long div;
 
-       div = *prate / rate;
+       div = *prate / *rate;
        if (div >= 4)
-               return *prate / 4;
+               *rate = *prate / 4;
        else if (div >= 2)
-               return *prate / 2;
-       return *prate;
+               *rate = *prate / 2;
+       else
+               *rate = *prate;
+
+       return 0;
 }
 
 static int clk_tve_di_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c 
b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
index eeed006..97cdcb4 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
@@ -336,11 +336,12 @@ static unsigned long hdmi_pll_recalc_rate(struct clk_hw 
*hw,
        return phy_8960->pixclk;
 }
 
-static long hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+static int hdmi_pll_round_rate(struct clk_hw *hw, unsigned long *rate,
                unsigned long *parent_rate)
 {
-       const struct pll_rate *pll_rate = find_rate(rate);
-       return pll_rate->rate;
+       const struct pll_rate *pll_rate = find_rate(*rate);
+       *rate = pll_rate->rate;
+       return 0;
 }
 
 static int hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_pll.c 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_pll.c
index ce42459..c89b109 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_pll.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_pll.c
@@ -109,11 +109,12 @@ static unsigned long mpd4_lvds_pll_recalc_rate(struct 
clk_hw *hw,
        return lvds_pll->pixclk;
 }
 
-static long mpd4_lvds_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+static int mpd4_lvds_pll_round_rate(struct clk_hw *hw, unsigned long *rate,
                unsigned long *parent_rate)
 {
-       const struct pll_rate *pll_rate = find_rate(rate);
-       return pll_rate->rate;
+       const struct pll_rate *pll_rate = find_rate(*rate);
+       *rate = pll_rate->rate;
+       return 0;
 }
 
 static int mpd4_lvds_pll_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/media/platform/omap3isp/isp.c 
b/drivers/media/platform/omap3isp/isp.c
index deca809..4d5ba85 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -231,11 +231,11 @@ static u32 isp_xclk_calc_divider(unsigned long *rate, 
unsigned long parent_rate)
        return divider;
 }
 
-static long isp_xclk_round_rate(struct clk_hw *hw, unsigned long rate,
+static int isp_xclk_round_rate(struct clk_hw *hw, unsigned long *rate,
                                unsigned long *parent_rate)
 {
-       isp_xclk_calc_divider(&rate, *parent_rate);
-       return rate;
+       isp_xclk_calc_divider(rate, *parent_rate);
+       return 0;
 }
 
 static int isp_xclk_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
index b936bb4..5e6f5a5 100644
--- a/drivers/rtc/rtc-hym8563.c
+++ b/drivers/rtc/rtc-hym8563.c
@@ -316,15 +316,19 @@ static unsigned long hym8563_clkout_recalc_rate(struct 
clk_hw *hw,
        return clkout_rates[ret];
 }
 
-static long hym8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
-                                     unsigned long *prate)
+static int hym8563_clkout_round_rate(struct clk_hw *hw, unsigned long *rate,
+                                    unsigned long *prate)
 {
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
-               if (clkout_rates[i] <= rate)
-                       return clkout_rates[i];
+       for (i = 0; i < ARRAY_SIZE(clkout_rates); i++) {
+               if (clkout_rates[i] <= *rate) {
+                       *rate = clkout_rates[i];
+                       return 0;
+               }
+       }
 
+       *rate = 0;
        return 0;
 }
 
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index df69531..84047b1 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -173,8 +173,8 @@ struct clk_ops {
        void            (*disable_unused)(struct clk_hw *hw);
        unsigned long   (*recalc_rate)(struct clk_hw *hw,
                                        unsigned long parent_rate);
-       long            (*round_rate)(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long *parent_rate);
+       int             (*round_rate)(struct clk_hw *hw, unsigned long *rate,
+                                     unsigned long *parent_rate);
        long            (*determine_rate)(struct clk_hw *hw,
                                          unsigned long rate,
                                          unsigned long min_rate,
@@ -365,7 +365,7 @@ extern const struct clk_ops clk_divider_ops;
 unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate,
                unsigned int val, const struct clk_div_table *table,
                unsigned long flags);
-long divider_round_rate(struct clk_hw *hw, unsigned long rate,
+int divider_round_rate(struct clk_hw *hw, unsigned long *rate,
                unsigned long *prate, const struct clk_div_table *table,
                u8 width, unsigned long flags);
 int divider_get_val(unsigned long rate, unsigned long parent_rate,
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 6784400..3b2406c 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -277,9 +277,9 @@ long omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
                                       struct clk_hw **best_parent_clk);
 unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
                                         unsigned long parent_rate);
-long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
-                                   unsigned long target_rate,
-                                   unsigned long *parent_rate);
+int omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
+                                  unsigned long *target_rate,
+                                  unsigned long *parent_rate);
 long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
                                        unsigned long rate,
                                        unsigned long min_rate,
@@ -288,14 +288,14 @@ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
                                        struct clk_hw **best_parent_clk);
 u8 omap2_init_dpll_parent(struct clk_hw *hw);
 unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
-long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
-                          unsigned long *parent_rate);
+int omap2_dpll_round_rate(struct clk_hw *hw, unsigned long *target_rate,
+                         unsigned long *parent_rate);
 void omap2_init_clk_clkdm(struct clk_hw *clk);
 unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
                                    unsigned long parent_rate);
 int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
                                        unsigned long parent_rate);
-long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
+int omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long *rate,
                unsigned long *prate);
 int omap2_clkops_enable_clkdm(struct clk_hw *hw);
 void omap2_clkops_disable_clkdm(struct clk_hw *hw);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to