@@ -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,
@@ -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);
@@ -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,
@@ -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);
@@ -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,
@@ -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)
@@ -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,
@@ -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 = {
@@ -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 */
@@ -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;
}
/**
@@ -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;
}
@@ -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);
@@ -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 */
@@ -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);
}
@@ -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,
@@ -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 = {
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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)
@@ -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,
@@ -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,
@@ -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,
@@ -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;
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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;
}
/**
@@ -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,
@@ -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,
@@ -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,
@@ -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 = {
@@ -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)) {
@@ -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,
@@ -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,
@@ -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,
@@ -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);
@@ -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,
@@ -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,
@@ -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);
@@ -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;
}
/*
@@ -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;
}
/*
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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;
}
@@ -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);
@@ -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;
@@ -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,
@@ -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,
@@ -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;
@@ -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)
@@ -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,
@@ -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;
}
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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;
}
/**
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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;
}
@@ -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,
@@ -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);
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@vger.kernel.org CC: linux-kernel@vger.kernel.org CC: linux-arm-kernel@lists.infradead.org CC: linux-arm-msm@vger.kernel.org CC: linux-omap@vger.kernel.org CC: linux-mips@linux-mips.org CC: patches@opensource.wolfsonmicro.com CC: linux-rockchip@lists.infradead.org CC: linux-samsung-soc@vger.kernel.org CC: spear-devel@list.st.com CC: linux-tegra@vger.kernel.org CC: dri-devel@lists.freedesktop.org CC: linux-media@vger.kernel.org CC: rtc-linux@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(-)