* [PATCH 1/2] clk: change clk_ops' ->round_rate() prototype
[not found] <1429255769-13639-1-git-send-email-boris.brezillon@free-electrons.com>
@ 2015-04-17 7:29 ` Boris Brezillon
2015-04-19 12:13 ` Heiko Stübner
2015-04-28 15:11 ` Mikko Perttunen
2015-04-17 7:29 ` [PATCH 2/2] clk: change clk_ops' ->determine_rate() prototype Boris Brezillon
1 sibling, 2 replies; 5+ messages in thread
From: Boris Brezillon @ 2015-04-17 7:29 UTC (permalink / raw)
To: linux-arm-kernel
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.brezillon@free-electrons.com>
---
CC: Jonathan Corbet <corbet@lwn.net>
CC: Shawn Guo <shawn.guo@linaro.org>
CC: ascha Hauer <kernel@pengutronix.de>
CC: David Brown <davidb@codeaurora.org>
CC: Daniel Walker <dwalker@fifo99.com>
CC: Bryan Huntsman <bryanh@codeaurora.org>
CC: Tony Lindgren <tony@atomide.com>
CC: Paul Walmsley <paul@pwsan.com>
CC: Liviu Dudau <liviu.dudau@arm.com>
CC: Sudeep Holla <sudeep.holla@arm.com>
CC: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
CC: Ralf Baechle <ralf@linux-mips.org>
CC: Max Filippov <jcmvbkbc@gmail.com>
CC: Heiko Stuebner <heiko@sntech.de>
CC: Sylwester Nawrocki <s.nawrocki@samsung.com>
CC: Tomasz Figa <tomasz.figa@gmail.com>
CC: Barry Song <baohua@kernel.org>
CC: Viresh Kumar <viresh.linux@gmail.com>
CC: "Emilio L?pez" <emilio@elopez.com.ar>
CC: Maxime Ripard <maxime.ripard@free-electrons.com>
CC: Peter De Schrijver <pdeschrijver@nvidia.com>
CC: Prashant Gaikwad <pgaikwad@nvidia.com>
CC: Stephen Warren <swarren@wwwdotorg.org>
CC: Thierry Reding <thierry.reding@gmail.com>
CC: Alexandre Courbot <gnurou@gmail.com>
CC: Tero Kristo <t-kristo@ti.com>
CC: Ulf Hansson <ulf.hansson@linaro.org>
CC: Michal Simek <michal.simek@xilinx.com>
CC: Philipp Zabel <p.zabel@pengutronix.de>
CC: linux-doc at vger.kernel.org
CC: linux-kernel at vger.kernel.org
CC: linux-arm-kernel at lists.infradead.org
CC: linux-arm-msm at vger.kernel.org
CC: linux-omap at vger.kernel.org
CC: linux-mips at linux-mips.org
CC: patches at opensource.wolfsonmicro.com
CC: linux-rockchip at lists.infradead.org
CC: linux-samsung-soc at vger.kernel.org
CC: spear-devel at list.st.com
CC: linux-tegra at vger.kernel.org
CC: dri-devel at lists.freedesktop.org
CC: linux-media at vger.kernel.org
CC: rtc-linux at 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 | 34 ++++++----
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 | 15 +++--
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, 672 insertions(+), 475 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 a23ac0c..02599e6 100644
--- a/drivers/clk/at91/clk-usb.c
+++ b/drivers/clk/at91/clk-usb.c
@@ -56,22 +56,26 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
}
-static long at91sam9x5_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int at91sam9x5_clk_usb_round_rate(struct clk_hw *hw,
+ unsigned long *rate,
+ unsigned long *parent_rate)
{
unsigned long div;
- if (!rate)
+ if (!*rate)
return -EINVAL;
- if (rate >= *parent_rate)
- return *parent_rate;
+ if (*rate >= *parent_rate) {
+ *rate = *parent_rate;
+ return 0;
+ }
- div = DIV_ROUND_CLOSEST(*parent_rate, rate);
+ div = DIV_ROUND_CLOSEST(*parent_rate, *rate);
if (div > SAM9X5_USB_MAX_DIV + 1)
div = SAM9X5_USB_MAX_DIV + 1;
- return DIV_ROUND_CLOSEST(*parent_rate, div);
+ *rate = DIV_ROUND_CLOSEST(*parent_rate, div);
+ return 0;
}
static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
@@ -235,8 +239,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);
@@ -252,13 +257,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;
@@ -270,7 +275,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 c386ad2..f110959 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 3b2a66f..8fad555 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 fc167b3..0680863 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 fa5a00e..1462ddc 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
@@ -1640,8 +1643,10 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
&parent_hw);
parent = parent_hw ? parent_hw->core : NULL;
} else if (clk->ops->round_rate) {
- new_rate = clk->ops->round_rate(clk->hw, rate,
- &best_parent_rate);
+ if (clk->ops->round_rate(clk->hw, &new_rate,
+ &best_parent_rate))
+ return NULL;
+
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 af94ed8..7c70049 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, ¶ms))
- clk_fs660c32_vco_get_rate(*prate, ¶ms, &rate);
+ if (!clk_fs660c32_vco_get_params(*prate, *rate, ¶ms))
+ clk_fs660c32_vco_get_rate(*prate, ¶ms, 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, ¶ms);
+ *rate = quadfs_find_best_rate(hw, *rate, *prate, ¶ms);
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 9a15ec3..2bbcb7b 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 bfef9ab..a73bdb3 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 = 0, 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,
@@ -1272,12 +1280,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 59bb4b3..cdf1d17 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 3654f61..eddad41 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 765f1e0..b507758 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 5591ea7..1213b0b 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
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] clk: change clk_ops' ->determine_rate() prototype
[not found] <1429255769-13639-1-git-send-email-boris.brezillon@free-electrons.com>
2015-04-17 7:29 ` [PATCH 1/2] clk: change clk_ops' ->round_rate() prototype Boris Brezillon
@ 2015-04-17 7:29 ` Boris Brezillon
1 sibling, 0 replies; 5+ messages in thread
From: Boris Brezillon @ 2015-04-17 7:29 UTC (permalink / raw)
To: linux-arm-kernel
Clock rates are stored in an unsigned long field, but ->determine_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 ->determine_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.brezillon@free-electrons.com>
---
CC: Jonathan Corbet <corbet@lwn.net>
CC: Tony Lindgren <tony@atomide.com>
CC: Ralf Baechle <ralf@linux-mips.org>
CC: "Emilio L?pez" <emilio@elopez.com.ar>
CC: Maxime Ripard <maxime.ripard@free-electrons.com>
CC: Tero Kristo <t-kristo@ti.com>
CC: linux-doc at vger.kernel.org
CC: linux-kernel at vger.kernel.org
CC: linux-arm-kernel at lists.infradead.org
CC: linux-omap at vger.kernel.org
CC: linux-mips at linux-mips.org
Documentation/clk.txt | 4 +--
arch/arm/mach-omap2/dpll3xxx.c | 20 +++++------
arch/arm/mach-omap2/dpll44xx.c | 20 +++++------
arch/mips/alchemy/common/clock.c | 63 +++++++++++++++++++++-----------
drivers/clk/at91/clk-programmable.c | 28 +++++++++------
drivers/clk/bcm/clk-kona.c | 24 ++++++++-----
drivers/clk/clk-composite.c | 22 ++++++------
drivers/clk/clk.c | 72 +++++++++++++++++++++----------------
drivers/clk/hisilicon/clk-hi3620.c | 22 ++++++------
drivers/clk/mmp/clk-mix.c | 17 ++++-----
drivers/clk/qcom/clk-pll.c | 12 ++++---
drivers/clk/qcom/clk-rcg.c | 32 +++++++++--------
drivers/clk/qcom/clk-rcg2.c | 55 +++++++++++++++-------------
drivers/clk/sunxi/clk-factors.c | 19 +++++-----
drivers/clk/sunxi/clk-sun6i-ar100.c | 18 ++++++----
drivers/clk/sunxi/clk-sunxi.c | 19 +++++-----
include/linux/clk-provider.h | 24 ++++++-------
include/linux/clk/ti.h | 24 ++++++-------
18 files changed, 278 insertions(+), 217 deletions(-)
diff --git a/Documentation/clk.txt b/Documentation/clk.txt
index fca8b7a..f5cae13 100644
--- a/Documentation/clk.txt
+++ b/Documentation/clk.txt
@@ -71,8 +71,8 @@ the operations defined in clk.h:
int (*round_rate)(struct clk_hw *hw,
unsigned long *rate,
unsigned long *parent_rate);
- long (*determine_rate)(struct clk_hw *hw,
- unsigned long rate,
+ int (*determine_rate)(struct clk_hw *hw,
+ unsigned long *rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 7a6fb45..cfa24fd 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -472,37 +472,37 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
* Returns a positive clock rate with success, negative error value
* in failure.
*/
-long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk)
+int omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_clk)
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
struct dpll_data *dd;
int ret;
- if (!hw || !rate)
+ if (!hw || !*rate)
return -EINVAL;
dd = clk->dpll_data;
if (!dd)
return -EINVAL;
- if (__clk_get_rate(dd->clk_bypass) == rate &&
+ if (__clk_get_rate(dd->clk_bypass) == *rate &&
(dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
*best_parent_clk = __clk_get_hw(dd->clk_bypass);
} else {
- ret = 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);
}
- *best_parent_rate = rate;
+ *best_parent_rate = *rate;
- return rate;
+ return 0;
}
/**
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index afd3284..1571d41 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -203,28 +203,28 @@ out:
* Returns a positive clock rate with success, negative error value
* in failure.
*/
-long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk)
+int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_clk)
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
struct dpll_data *dd;
int ret;
- if (!hw || !rate)
+ if (!hw || !*rate)
return -EINVAL;
dd = clk->dpll_data;
if (!dd)
return -EINVAL;
- if (__clk_get_rate(dd->clk_bypass) == rate &&
+ if (__clk_get_rate(dd->clk_bypass) == *rate &&
(dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
*best_parent_clk = __clk_get_hw(dd->clk_bypass);
} else {
- ret = omap4_dpll_regm4xen_round_rate(hw, &rate,
+ ret = omap4_dpll_regm4xen_round_rate(hw, rate,
best_parent_rate);
if (ret)
return ret;
@@ -232,7 +232,7 @@ long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
*best_parent_clk = __clk_get_hw(dd->clk_ref);
}
- *best_parent_rate = rate;
+ *best_parent_rate = *rate;
- return rate;
+ return 0;
}
diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c
index d697d8f..0abcfc6 100644
--- a/arch/mips/alchemy/common/clock.c
+++ b/arch/mips/alchemy/common/clock.c
@@ -565,14 +565,22 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
return parent_rate / v;
}
-static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk)
+static int alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_clk)
{
- return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
- best_parent_clk, 2, 512);
+ long ret;
+
+ ret = alchemy_clk_fgcs_detr(hw, *rate, best_parent_rate,
+ best_parent_clk, 2, 512);
+ if (ret < 0)
+ return ret;
+
+ *rate = ret;
+
+ return 0;
}
/* Au1000, Au1100, Au15x0, Au12x0 */
@@ -699,14 +707,15 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
return t;
}
-static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk)
+static int alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_clk)
{
struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
int scale, maxdiv;
+ long ret;
if (alchemy_rdsys(c->reg) & (1 << 30)) {
scale = 1;
@@ -716,8 +725,13 @@ static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
maxdiv = 512;
}
- return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
- best_parent_clk, scale, maxdiv);
+ ret = alchemy_clk_fgcs_detr(hw, *rate, best_parent_rate,
+ best_parent_clk, scale, maxdiv);
+ if (ret < 0)
+ return ret;
+
+ *rate = ret;
+ return 0;
}
/* Au1300 larger input mux, no separate disable bit, flexible divider */
@@ -920,17 +934,24 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
return 0;
}
-static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk)
+static int alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_clk)
{
struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
+ long ret;
- return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
- best_parent_clk, scale, 4);
+ ret = alchemy_clk_fgcs_detr(hw, *rate, best_parent_rate,
+ best_parent_clk, scale, 4);
+ if (ret < 0)
+ return ret;
+
+ *rate = ret;
+
+ return 0;
}
static struct clk_ops alchemy_clkops_csrc = {
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index 86c8a07..5f9570d 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -54,17 +54,18 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
return parent_rate >> pres;
}
-static long clk_programmable_determine_rate(struct clk_hw *hw,
- unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_hw)
+static int clk_programmable_determine_rate(struct clk_hw *hw,
+ unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_hw)
{
struct clk *parent = NULL;
- long best_rate = -EINVAL;
unsigned long parent_rate;
+ unsigned long best_rate;
unsigned long tmp_rate;
+ int ret = -EINVAL;
int shift;
int i;
@@ -76,24 +77,29 @@ static long clk_programmable_determine_rate(struct clk_hw *hw,
parent_rate = __clk_get_rate(parent);
for (shift = 0; shift < PROG_PRES_MASK; shift++) {
tmp_rate = parent_rate >> shift;
- if (tmp_rate <= rate)
+ if (tmp_rate <= *rate)
break;
}
- if (tmp_rate > rate)
+ if (tmp_rate > *rate)
continue;
- if (best_rate < 0 || (rate - tmp_rate) < (rate - best_rate)) {
+ if (best_rate < 0 || (*rate - tmp_rate) < (*rate - best_rate)) {
best_rate = tmp_rate;
*best_parent_rate = parent_rate;
*best_parent_hw = __clk_get_hw(parent);
+ ret = 0;
}
if (!best_rate)
break;
}
- return best_rate;
+ if (ret)
+ return ret;
+
+ *rate = best_rate;
+ return 0;
}
static int clk_programmable_set_parent(struct clk_hw *hw, u8 index)
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c
index 05abae8..4a2a66b 100644
--- a/drivers/clk/bcm/clk-kona.c
+++ b/drivers/clk/bcm/clk-kona.c
@@ -1031,7 +1031,7 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
rate ? rate : 1, *parent_rate, NULL);
}
-static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+static int kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate, struct clk_hw **best_parent)
@@ -1044,6 +1044,7 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long best_rate;
u32 parent_count;
u32 which;
+ long ret;
/*
* If there is no other parent to choose, use the current one.
@@ -1051,14 +1052,20 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
*/
WARN_ON_ONCE(bcm_clk->init_data.flags & CLK_SET_RATE_NO_REPARENT);
parent_count = (u32)bcm_clk->init_data.num_parents;
- if (parent_count < 2)
- return kona_peri_clk_round_rate(hw, rate, best_parent_rate);
+ if (parent_count < 2) {
+ ret = kona_peri_clk_round_rate(hw, *rate, best_parent_rate);
+ if (ret < 0)
+ return ret;
+
+ *rate = ret;
+ return 0;
+ }
/* Unless we can do better, stick with current parent */
current_parent = clk_get_parent(clk);
parent_rate = __clk_get_rate(current_parent);
- best_rate = kona_peri_clk_round_rate(hw, rate, &parent_rate);
- best_delta = abs(best_rate - rate);
+ best_rate = kona_peri_clk_round_rate(hw, *rate, &parent_rate);
+ best_delta = abs(best_rate - *rate);
/* Check whether any other parent clock can produce a better result */
for (which = 0; which < parent_count; which++) {
@@ -1072,8 +1079,8 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
/* We don't support CLK_SET_RATE_PARENT */
parent_rate = __clk_get_rate(parent);
- other_rate = kona_peri_clk_round_rate(hw, rate, &parent_rate);
- delta = abs(other_rate - rate);
+ other_rate = kona_peri_clk_round_rate(hw, *rate, &parent_rate);
+ delta = abs(other_rate - *rate);
if (delta < best_delta) {
best_delta = delta;
best_rate = other_rate;
@@ -1082,7 +1089,8 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
}
}
- return best_rate;
+ *rate = best_rate;
+ return 0;
}
static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index f56a71d..45c2b51 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -55,7 +55,7 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
return rate_ops->recalc_rate(rate_hw, parent_rate);
}
-static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_composite_determine_rate(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
@@ -88,12 +88,8 @@ 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);
- ret = rate_ops->round_rate(rate_hw, &rate,
- best_parent_rate);
- if (ret)
- return ret;
-
- return rate;
+ return rate_ops->round_rate(rate_hw, rate,
+ best_parent_rate);
}
for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
@@ -103,13 +99,13 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
parent_rate = __clk_get_rate(parent);
- tmp_rate = rate;
+ tmp_rate = *rate;
ret = rate_ops->round_rate(rate_hw, &tmp_rate,
&parent_rate);
if (ret < 0)
continue;
- rate_diff = abs(rate - tmp_rate);
+ rate_diff = abs(*rate - tmp_rate);
if (!rate_diff || !*best_parent_p
|| best_rate_diff > rate_diff) {
@@ -120,10 +116,10 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
}
if (!rate_diff)
- return rate;
+ break;
}
- return best_rate;
+ *rate = best_rate;
} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
__clk_hw_set_clk(mux_hw, hw);
return mux_ops->determine_rate(mux_hw, rate, min_rate,
@@ -131,8 +127,10 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
best_parent_p);
} else {
pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
- return 0;
+ *rate = 0;
}
+
+ return 0;
}
static int clk_composite_round_rate(struct clk_hw *hw, unsigned long *rate,
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 1462ddc..f42a639 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -795,8 +795,8 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now,
return now <= rate && now > best;
}
-static long
-clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
+static int
+clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
@@ -804,15 +804,15 @@ clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
unsigned long flags)
{
struct clk_core *core = hw->core, *parent, *best_parent = NULL;
- int i, num_parents;
- unsigned long parent_rate, best = 0;
+ int i, num_parents, ret = 0;
+ unsigned long parent_rate = *rate, best = *rate;
/* if NO_REPARENT flag set, pass through to current parent */
if (core->flags & CLK_SET_RATE_NO_REPARENT) {
parent = core->parent;
if (core->flags & CLK_SET_RATE_PARENT)
- best = __clk_determine_rate(parent ? parent->hw : NULL,
- rate, min_rate, max_rate);
+ ret = __clk_determine_rate(parent ? parent->hw : NULL,
+ &best, min_rate, max_rate);
else if (parent)
best = clk_core_get_rate_nolock(parent);
else
@@ -827,23 +827,28 @@ clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
if (!parent)
continue;
if (core->flags & CLK_SET_RATE_PARENT)
- parent_rate = __clk_determine_rate(parent->hw, rate,
- min_rate,
- max_rate);
+ ret = __clk_determine_rate(parent->hw, &parent_rate,
+ min_rate,
+ max_rate);
else
parent_rate = clk_core_get_rate_nolock(parent);
- if (mux_is_better_rate(rate, parent_rate, best, flags)) {
+ if (!ret &&
+ mux_is_better_rate(*rate, parent_rate, best, flags)) {
best_parent = parent;
best = parent_rate;
}
}
out:
+ if (ret)
+ return ret;
+
if (best_parent)
*best_parent_p = best_parent->hw;
*best_parent_rate = best;
+ *rate = best;
- return best;
+ return 0;
}
struct clk *__clk_lookup(const char *name)
@@ -874,11 +879,11 @@ static void clk_core_get_boundaries(struct clk_core *clk,
* directly as a determine_rate callback (e.g. for a mux), or from a more
* complex clock that may combine a mux with other operations.
*/
-long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_p)
+int __clk_mux_determine_rate(struct clk_hw *hw, unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_p)
{
return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate,
best_parent_rate,
@@ -886,7 +891,7 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
}
EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
-long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
+int __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
@@ -1143,9 +1148,12 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
if (clk->ops->determine_rate) {
parent_hw = parent ? parent->hw : NULL;
- return clk->ops->determine_rate(clk->hw, rate,
- min_rate, max_rate,
- &parent_rate, &parent_hw);
+ if (clk->ops->determine_rate(clk->hw, &rate,
+ min_rate, max_rate,
+ &parent_rate, &parent_hw))
+ return 0;
+
+ return rate;
} else if (clk->ops->round_rate) {
if (clk->ops->round_rate(clk->hw, &rate, &parent_rate))
return 0;
@@ -1168,15 +1176,13 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
* Caller must hold prepare_lock. Useful for clk_ops such as .set_rate and
* .determine_rate.
*/
-unsigned long __clk_determine_rate(struct clk_hw *hw,
- unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate)
+int __clk_determine_rate(struct clk_hw *hw, unsigned long *rate,
+ unsigned long min_rate, unsigned long max_rate)
{
if (!hw)
return 0;
- return clk_core_round_rate_nolock(hw->core, rate, min_rate, max_rate);
+ return clk_core_round_rate_nolock(hw->core, *rate, min_rate, max_rate);
}
EXPORT_SYMBOL_GPL(__clk_determine_rate);
@@ -1617,10 +1623,11 @@ 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;
+ int ret;
/* sanity */
if (IS_ERR_OR_NULL(clk))
@@ -1636,11 +1643,14 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
/* find the closest rate and parent clk/rate */
if (clk->ops->determine_rate) {
parent_hw = parent ? parent->hw : NULL;
- new_rate = clk->ops->determine_rate(clk->hw, rate,
- min_rate,
- max_rate,
- &best_parent_rate,
- &parent_hw);
+ ret = clk->ops->determine_rate(clk->hw, &new_rate,
+ min_rate,
+ max_rate,
+ &best_parent_rate,
+ &parent_hw);
+ if (ret)
+ return NULL;
+
parent = parent_hw ? parent_hw->core : NULL;
} else if (clk->ops->round_rate) {
if (clk->ops->round_rate(clk->hw, &new_rate,
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index 2e4f6d4..f22885a 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -294,7 +294,7 @@ static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
}
}
-static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+static int mmc_clk_determine_rate(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
@@ -303,25 +303,25 @@ static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
struct clk_mmc *mclk = to_mmc(hw);
unsigned long best = 0;
- if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
- rate = 13000000;
+ if ((*rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
+ *rate = 13000000;
best = 26000000;
- } else if (rate <= 26000000) {
- rate = 25000000;
+ } else if (*rate <= 26000000) {
+ *rate = 25000000;
best = 180000000;
- } else if (rate <= 52000000) {
- rate = 50000000;
+ } else if (*rate <= 52000000) {
+ *rate = 50000000;
best = 360000000;
- } else if (rate <= 100000000) {
- rate = 100000000;
+ } else if (*rate <= 100000000) {
+ *rate = 100000000;
best = 720000000;
} else {
/* max is 180M */
- rate = 180000000;
+ *rate = 180000000;
best = 1440000000;
}
*best_parent_rate = best;
- return rate;
+ return 0;
}
static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c
index de6a873..e15bb57 100644
--- a/drivers/clk/mmp/clk-mix.c
+++ b/drivers/clk/mmp/clk-mix.c
@@ -201,11 +201,11 @@ error:
return ret;
}
-static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk)
+static int mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_clk)
{
struct mmp_clk_mix *mix = to_clk_mix(hw);
struct mmp_clk_mix_clk_table *item;
@@ -233,7 +233,7 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
item->parent_index);
parent_rate = __clk_get_rate(parent);
mix_rate = parent_rate / item->divisor;
- gap = abs(mix_rate - rate);
+ gap = abs(mix_rate - *rate);
if (parent_best == NULL || gap < gap_best) {
parent_best = parent;
parent_rate_best = parent_rate;
@@ -251,7 +251,7 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
for (j = 0; j < div_val_max; j++) {
div = _get_div(mix, j);
mix_rate = parent_rate / div;
- gap = abs(mix_rate - rate);
+ gap = abs(mix_rate - *rate);
if (parent_best == NULL || gap < gap_best) {
parent_best = parent;
parent_rate_best = parent_rate;
@@ -267,8 +267,9 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
found:
*best_parent_rate = parent_rate_best;
*best_parent_clk = __clk_get_hw(parent_best);
+ *rate = mix_rate_best;
- return mix_rate_best;
+ return 0;
}
static int mmp_clk_mix_set_rate_and_parent(struct clk_hw *hw,
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
index b4325f6..2588952 100644
--- a/drivers/clk/qcom/clk-pll.c
+++ b/drivers/clk/qcom/clk-pll.c
@@ -139,19 +139,21 @@ struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
return NULL;
}
-static long
-clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate,
+static int
+clk_pll_determine_rate(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p)
{
struct clk_pll *pll = to_clk_pll(hw);
const struct pll_freq_tbl *f;
- f = find_freq(pll->freq_tbl, rate);
+ f = find_freq(pll->freq_tbl, *rate);
if (!f)
- return clk_pll_recalc_rate(hw, *p_rate);
+ *rate = clk_pll_recalc_rate(hw, *p_rate);
+ else
+ *rate = f->freq;
- return f->freq;
+ return 0;
}
static int
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c
index 8f2f480..727012f 100644
--- a/drivers/clk/qcom/clk-rcg.c
+++ b/drivers/clk/qcom/clk-rcg.c
@@ -404,38 +404,39 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
return calc_rate(parent_rate, m, n, mode, pre_div);
}
-static long _freq_tbl_determine_rate(struct clk_hw *hw,
- const struct freq_tbl *f, unsigned long rate,
+static int _freq_tbl_determine_rate(struct clk_hw *hw,
+ const struct freq_tbl *f, unsigned long *rate,
unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p_hw)
{
- unsigned long clk_flags;
+ unsigned long clk_flags, parent_rate;
struct clk *p;
- f = qcom_find_freq(f, rate);
+ f = qcom_find_freq(f, *rate);
if (!f)
return -EINVAL;
clk_flags = __clk_get_flags(hw->clk);
p = clk_get_parent_by_index(hw->clk, f->src);
if (clk_flags & CLK_SET_RATE_PARENT) {
- rate = rate * f->pre_div;
+ parent_rate = *rate * f->pre_div;
if (f->n) {
- u64 tmp = rate;
+ u64 tmp = parent_rate;
tmp = tmp * f->n;
do_div(tmp, f->m);
- rate = tmp;
+ parent_rate = tmp;
}
} else {
- rate = __clk_get_rate(p);
+ parent_rate = __clk_get_rate(p);
}
*p_hw = __clk_get_hw(p);
- *p_rate = rate;
+ *p_rate = parent_rate;
+ *rate = f->freq;
- return f->freq;
+ return 0;
}
-static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_rcg_determine_rate(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p)
{
@@ -445,7 +446,7 @@ static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
max_rate, p_rate, p);
}
-static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p)
{
@@ -455,7 +456,7 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
max_rate, p_rate, p);
}
-static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p_hw)
{
@@ -465,9 +466,10 @@ static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
p = clk_get_parent_by_index(hw->clk, f->src);
*p_hw = __clk_get_hw(p);
- *p_rate = __clk_round_rate(p, rate);
+ *p_rate = __clk_round_rate(p, *rate);
+ *rate = *p_rate;
- return *p_rate;
+ return 0;
}
static int __clk_rcg_set_rate(struct clk_rcg *rcg, const struct freq_tbl *f)
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 416becc..38ef3f2 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -176,14 +176,14 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
return calc_rate(parent_rate, m, n, mode, hid_div);
}
-static long _freq_tbl_determine_rate(struct clk_hw *hw,
- const struct freq_tbl *f, unsigned long rate,
+static int _freq_tbl_determine_rate(struct clk_hw *hw,
+ const struct freq_tbl *f, unsigned long *rate,
unsigned long *p_rate, struct clk_hw **p_hw)
{
- unsigned long clk_flags;
+ unsigned long clk_flags, parent_rate = *rate;
struct clk *p;
- f = qcom_find_freq(f, rate);
+ f = qcom_find_freq(f, *rate);
if (!f)
return -EINVAL;
@@ -191,26 +191,27 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
p = clk_get_parent_by_index(hw->clk, f->src);
if (clk_flags & CLK_SET_RATE_PARENT) {
if (f->pre_div) {
- rate /= 2;
- rate *= f->pre_div + 1;
+ parent_rate /= 2;
+ parent_rate *= f->pre_div + 1;
}
if (f->n) {
- u64 tmp = rate;
+ u64 tmp = parent_rate;
tmp = tmp * f->n;
do_div(tmp, f->m);
- rate = tmp;
+ parent_rate = tmp;
}
} else {
- rate = __clk_get_rate(p);
+ parent_rate = __clk_get_rate(p);
}
*p_hw = __clk_get_hw(p);
- *p_rate = rate;
+ *p_rate = parent_rate;
+ *rate = f->freq;
- return f->freq;
+ return 0;
}
-static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p)
{
@@ -368,7 +369,7 @@ static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw,
return clk_edp_pixel_set_rate(hw, rate, parent_rate);
}
-static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p)
@@ -391,7 +392,7 @@ static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
frac = frac_table_675m;
for (; frac->num; frac++) {
- request = rate;
+ request = *rate;
request *= frac->den;
request = div_s64(request, frac->num);
if ((src_rate < (request - delta)) ||
@@ -403,8 +404,10 @@ static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
hid_div >>= CFG_SRC_DIV_SHIFT;
hid_div &= mask;
- return calc_rate(src_rate, frac->num, frac->den, !!frac->den,
- hid_div);
+ *rate = calc_rate(src_rate, frac->num, frac->den, !!frac->den,
+ hid_div);
+
+ return 0;
}
return -EINVAL;
@@ -421,7 +424,7 @@ const struct clk_ops clk_edp_pixel_ops = {
};
EXPORT_SYMBOL_GPL(clk_edp_pixel_ops);
-static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_byte_determine_rate(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate, unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p_hw)
{
@@ -431,17 +434,19 @@ static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
u32 mask = BIT(rcg->hid_width) - 1;
struct clk *p;
- if (rate == 0)
+ if (*rate == 0)
return -EINVAL;
p = clk_get_parent_by_index(hw->clk, f->src);
*p_hw = __clk_get_hw(p);
- *p_rate = parent_rate = __clk_round_rate(p, rate);
+ *p_rate = parent_rate = __clk_round_rate(p, *rate);
- div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
+ div = DIV_ROUND_UP((2 * parent_rate), *rate) - 1;
div = min_t(u32, div, mask);
- return calc_rate(parent_rate, 0, 0, 0, div);
+ *rate = calc_rate(parent_rate, 0, 0, 0, div);
+
+ return 0;
}
static int clk_byte_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -486,7 +491,7 @@ static const struct frac_entry frac_table_pixel[] = {
{ }
};
-static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
+static int clk_pixel_determine_rate(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *p_rate, struct clk_hw **p)
@@ -501,7 +506,7 @@ static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
*p = __clk_get_hw(parent);
for (; frac->num; frac++) {
- request = (rate * frac->den) / frac->num;
+ request = (*rate * frac->den) / frac->num;
src_rate = __clk_round_rate(parent, request);
if ((src_rate < (request - delta)) ||
@@ -509,7 +514,9 @@ static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
continue;
*p_rate = src_rate;
- return (src_rate * frac->num) / frac->den;
+ *rate = (src_rate * frac->num) / frac->den;
+
+ return 0;
}
return -EINVAL;
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 5865300..1cef6a5 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -82,11 +82,11 @@ static int clk_factors_round_rate(struct clk_hw *hw, unsigned long *rate,
return 0;
}
-static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_p)
+static int clk_factors_determine_rate(struct clk_hw *hw, unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_p)
{
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
int i, num_parents;
@@ -99,14 +99,14 @@ static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
if (!parent)
continue;
if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
- parent_rate = __clk_round_rate(parent, rate);
+ parent_rate = __clk_round_rate(parent, *rate);
else
parent_rate = __clk_get_rate(parent);
- child_rate = rate;
+ child_rate = *rate;
clk_factors_round_rate(hw, &child_rate, &parent_rate);
- if (child_rate <= rate && child_rate > best_child_rate) {
+ if (child_rate <= *rate && child_rate > best_child_rate) {
best_parent = parent;
best = parent_rate;
best_child_rate = child_rate;
@@ -116,8 +116,9 @@ static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
if (best_parent)
*best_parent_p = __clk_get_hw(best_parent);
*best_parent_rate = best;
+ *rate = best_child_rate;
- return best_child_rate;
+ return 0;
}
static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c
index 63cf149..f398190 100644
--- a/drivers/clk/sunxi/clk-sun6i-ar100.c
+++ b/drivers/clk/sunxi/clk-sun6i-ar100.c
@@ -44,11 +44,11 @@ static unsigned long ar100_recalc_rate(struct clk_hw *hw,
return (parent_rate >> shift) / (div + 1);
}
-static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk)
+static int ar100_determine_rate(struct clk_hw *hw, unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_clk)
{
int nparents = __clk_get_num_parents(hw->clk);
long best_rate = -EINVAL;
@@ -65,7 +65,7 @@ static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
parent = clk_get_parent_by_index(hw->clk, i);
parent_rate = __clk_get_rate(parent);
- div = DIV_ROUND_UP(parent_rate, rate);
+ div = DIV_ROUND_UP(parent_rate, *rate);
/*
* The AR100 clk contains 2 divisors:
@@ -108,7 +108,11 @@ static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
}
}
- return best_rate;
+ if (best_rate < 0)
+ return best_rate;
+
+ *rate = best_rate;
+ return 0;
}
static int ar100_set_parent(struct clk_hw *hw, u8 index)
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 7e1e2bd..3f2420f 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -118,11 +118,11 @@ static long sun6i_ahb1_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp,
return (parent_rate / calcm) >> calcp;
}
-static long sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk)
+static int sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_clk)
{
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
int i, num_parents;
@@ -135,14 +135,14 @@ static long sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
if (!parent)
continue;
if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
- parent_rate = __clk_round_rate(parent, rate);
+ parent_rate = __clk_round_rate(parent, *rate);
else
parent_rate = __clk_get_rate(parent);
- child_rate = sun6i_ahb1_clk_round(rate, NULL, NULL, i,
+ child_rate = sun6i_ahb1_clk_round(*rate, NULL, NULL, i,
parent_rate);
- if (child_rate <= rate && child_rate > best_child_rate) {
+ if (child_rate <= *rate && child_rate > best_child_rate) {
best_parent = parent;
best = parent_rate;
best_child_rate = child_rate;
@@ -152,8 +152,9 @@ static long sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
if (best_parent)
*best_parent_clk = __clk_get_hw(best_parent);
*best_parent_rate = best;
+ *rate = best_child_rate;
- return best_child_rate;
+ return 0;
}
static int sun6i_ahb1_clk_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1213b0b..51d67de 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -175,8 +175,8 @@ struct clk_ops {
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,
+ int (*determine_rate)(struct clk_hw *hw,
+ unsigned long *rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
@@ -575,16 +575,16 @@ unsigned long __clk_get_flags(struct clk *clk);
bool __clk_is_prepared(struct clk *clk);
bool __clk_is_enabled(struct clk *clk);
struct clk *__clk_lookup(const char *name);
-long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_p);
-unsigned long __clk_determine_rate(struct clk_hw *core,
- unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate);
-long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
+int __clk_mux_determine_rate(struct clk_hw *hw, unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_p);
+int __clk_determine_rate(struct clk_hw *core,
+ unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate);
+int __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long *rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 3b2406c..1df140f 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -269,23 +269,23 @@ int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate,
u8 index);
-long omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
- unsigned long rate,
- unsigned long min_rate,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk);
+int omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
+ unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ struct clk_hw **best_parent_clk);
unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
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,
- unsigned long max_rate,
- unsigned long *best_parent_rate,
- struct clk_hw **best_parent_clk);
+int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
+ unsigned long *rate,
+ unsigned long min_rate,
+ unsigned long max_rate,
+ unsigned long *best_parent_rate,
+ 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);
int omap2_dpll_round_rate(struct clk_hw *hw, unsigned long *target_rate,
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 1/2] clk: change clk_ops' ->round_rate() prototype
2015-04-17 7:29 ` [PATCH 1/2] clk: change clk_ops' ->round_rate() prototype Boris Brezillon
@ 2015-04-19 12:13 ` Heiko Stübner
2015-04-19 15:30 ` Boris Brezillon
2015-04-28 15:11 ` Mikko Perttunen
1 sibling, 1 reply; 5+ messages in thread
From: Heiko Stübner @ 2015-04-19 12:13 UTC (permalink / raw)
To: linux-arm-kernel
Hi Boris,
Am Freitag, 17. April 2015, 09:29:28 schrieb Boris Brezillon:
> 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.brezillon@free-electrons.com>
> ---
On a rk3288-veyron-pinky with the fix described below:
Tested-by: Heiko Stuebner <heiko@sntech.de>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index fa5a00e..1462ddc 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1640,8 +1643,10 @@ static struct clk_core *clk_calc_new_rates(struct
> clk_core *clk, &parent_hw);
> parent = parent_hw ? parent_hw->core : NULL;
> } else if (clk->ops->round_rate) {
> - new_rate = clk->ops->round_rate(clk->hw, rate,
> - &best_parent_rate);
> + if (clk->ops->round_rate(clk->hw, &new_rate,
> + &best_parent_rate))
> + return NULL;
> +
> if (new_rate < min_rate || new_rate > max_rate)
> return NULL;
> } else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
This is using new_rate uninitialized when calling into the round_rate
callback. Which in turn pushed my PLLs up to 2.2GHz :-)
I guess you'll need something like the following:
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index db4e4b2..afc7733 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1605,6 +1605,7 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
&parent_hw);
parent = parent_hw ? parent_hw->core : NULL;
} else if (clk->ops->round_rate) {
+ new_rate = rate;
if (clk->ops->round_rate(clk->hw, &new_rate,
&best_parent_rate))
return NULL;
> 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;
> }
>
> /*
The rockchip-part:
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
And as I've stumbled onto this recently too, the clock-maintainership has
expanded to Stephen Boyd and linux-clk at vger.kernel.org .
Heiko
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 1/2] clk: change clk_ops' ->round_rate() prototype
2015-04-19 12:13 ` Heiko Stübner
@ 2015-04-19 15:30 ` Boris Brezillon
0 siblings, 0 replies; 5+ messages in thread
From: Boris Brezillon @ 2015-04-19 15:30 UTC (permalink / raw)
To: linux-arm-kernel
Hi Heiko,
On Sun, 19 Apr 2015 14:13:04 +0200
Heiko St?bner <heiko@sntech.de> wrote:
> Hi Boris,
>
> Am Freitag, 17. April 2015, 09:29:28 schrieb Boris Brezillon:
> > 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.brezillon@free-electrons.com>
> > ---
>
> On a rk3288-veyron-pinky with the fix described below:
> Tested-by: Heiko Stuebner <heiko@sntech.de>
>
>
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index fa5a00e..1462ddc 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -1640,8 +1643,10 @@ static struct clk_core *clk_calc_new_rates(struct
> > clk_core *clk, &parent_hw);
> > parent = parent_hw ? parent_hw->core : NULL;
> > } else if (clk->ops->round_rate) {
> > - new_rate = clk->ops->round_rate(clk->hw, rate,
> > - &best_parent_rate);
> > + if (clk->ops->round_rate(clk->hw, &new_rate,
> > + &best_parent_rate))
> > + return NULL;
> > +
> > if (new_rate < min_rate || new_rate > max_rate)
> > return NULL;
> > } else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
>
> This is using new_rate uninitialized when calling into the round_rate
> callback. Which in turn pushed my PLLs up to 2.2GHz :-)
Indeed, thanks for the fix.
[...]
>
>
> And as I've stumbled onto this recently too, the clock-maintainership has
> expanded to Stephen Boyd and linux-clk at vger.kernel.org .
Noted. I'll add Stephen and the new linux-clk ML in the recipient list
next time.
Best Regards,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] clk: change clk_ops' ->round_rate() prototype
2015-04-17 7:29 ` [PATCH 1/2] clk: change clk_ops' ->round_rate() prototype Boris Brezillon
2015-04-19 12:13 ` Heiko Stübner
@ 2015-04-28 15:11 ` Mikko Perttunen
1 sibling, 0 replies; 5+ messages in thread
From: Mikko Perttunen @ 2015-04-28 15:11 UTC (permalink / raw)
To: linux-arm-kernel
The series
Tested-by: Mikko Perttunen <mikko.perttunen@kapsi.fi>
on Jetson-TK1.
I rebased my cpufreq series on top of this and everything's working well
now. :)
Thanks,
Mikko.
On 04/17/2015 10:29 AM, Boris Brezillon wrote:
> ...
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-04-28 15:11 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1429255769-13639-1-git-send-email-boris.brezillon@free-electrons.com>
2015-04-17 7:29 ` [PATCH 1/2] clk: change clk_ops' ->round_rate() prototype Boris Brezillon
2015-04-19 12:13 ` Heiko Stübner
2015-04-19 15:30 ` Boris Brezillon
2015-04-28 15:11 ` Mikko Perttunen
2015-04-17 7:29 ` [PATCH 2/2] clk: change clk_ops' ->determine_rate() prototype Boris Brezillon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).