summaryrefslogtreecommitdiff
path: root/drivers/clk/mmp/clk-frac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/mmp/clk-frac.c')
-rw-r--r--drivers/clk/mmp/clk-frac.c87
1 files changed, 42 insertions, 45 deletions
diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 48f592bd633d..0b1bb01346f0 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* mmp factor clock operation source file
*
* Copyright (C) 2012 Marvell
* Chao Xie <xiechao.mail@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
*/
#include <linux/clk-provider.h>
@@ -24,30 +21,32 @@
#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,
- unsigned long *prate)
+static int clk_factor_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
struct mmp_clk_factor *factor = to_clk_factor(hw);
u64 rate = 0, prev_rate;
+ struct u32_fract *d;
int i;
for (i = 0; i < factor->ftbl_cnt; i++) {
- prev_rate = rate;
- rate = *prate;
- rate *= factor->ftbl[i].den;
- do_div(rate, factor->ftbl[i].num * factor->masks->factor);
+ d = &factor->ftbl[i];
- if (rate > drate)
+ prev_rate = rate;
+ rate = (u64)(req->best_parent_rate) * d->denominator;
+ do_div(rate, d->numerator * factor->masks->factor);
+ if (rate > req->rate)
break;
}
- if ((i == 0) || (i == factor->ftbl_cnt)) {
- return rate;
- } else {
- if ((drate - prev_rate) > (rate - drate))
- return rate;
- else
- return prev_rate;
- }
+
+ if ((i == 0) || (i == factor->ftbl_cnt))
+ req->rate = rate;
+ else if ((req->rate - prev_rate) > (rate - req->rate))
+ req->rate = rate;
+ else
+ req->rate = prev_rate;
+
+ return 0;
}
static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
@@ -55,23 +54,22 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
{
struct mmp_clk_factor *factor = to_clk_factor(hw);
struct mmp_clk_factor_masks *masks = factor->masks;
- unsigned int val, num, den;
+ struct u32_fract d;
+ unsigned int val;
u64 rate;
val = readl_relaxed(factor->base);
/* calculate numerator */
- num = (val >> masks->num_shift) & masks->num_mask;
+ d.numerator = (val >> masks->num_shift) & masks->num_mask;
/* calculate denominator */
- den = (val >> masks->den_shift) & masks->den_mask;
-
- if (!den)
+ d.denominator = (val >> masks->den_shift) & masks->den_mask;
+ if (!d.denominator)
return 0;
- rate = parent_rate;
- rate *= den;
- do_div(rate, num * factor->masks->factor);
+ rate = (u64)parent_rate * d.denominator;
+ do_div(rate, d.numerator * factor->masks->factor);
return rate;
}
@@ -85,18 +83,18 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
int i;
unsigned long val;
unsigned long flags = 0;
+ struct u32_fract *d;
u64 rate = 0;
for (i = 0; i < factor->ftbl_cnt; i++) {
- rate = prate;
- rate *= factor->ftbl[i].den;
- do_div(rate, factor->ftbl[i].num * factor->masks->factor);
+ d = &factor->ftbl[i];
+ rate = (u64)prate * d->denominator;
+ do_div(rate, d->numerator * factor->masks->factor);
if (rate > drate)
break;
}
- if (i > 0)
- i--;
+ d = i ? &factor->ftbl[i - 1] : &factor->ftbl[0];
if (factor->lock)
spin_lock_irqsave(factor->lock, flags);
@@ -104,10 +102,10 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
val = readl_relaxed(factor->base);
val &= ~(masks->num_mask << masks->num_shift);
- val |= (factor->ftbl[i].num & masks->num_mask) << masks->num_shift;
+ val |= (d->numerator & masks->num_mask) << masks->num_shift;
val &= ~(masks->den_mask << masks->den_shift);
- val |= (factor->ftbl[i].den & masks->den_mask) << masks->den_shift;
+ val |= (d->denominator & masks->den_mask) << masks->den_shift;
writel_relaxed(val, factor->base);
@@ -121,7 +119,8 @@ static int clk_factor_init(struct clk_hw *hw)
{
struct mmp_clk_factor *factor = to_clk_factor(hw);
struct mmp_clk_factor_masks *masks = factor->masks;
- u32 val, num, den;
+ struct u32_fract d;
+ u32 val;
int i;
unsigned long flags = 0;
@@ -131,23 +130,22 @@ static int clk_factor_init(struct clk_hw *hw)
val = readl(factor->base);
/* calculate numerator */
- num = (val >> masks->num_shift) & masks->num_mask;
+ d.numerator = (val >> masks->num_shift) & masks->num_mask;
/* calculate denominator */
- den = (val >> masks->den_shift) & masks->den_mask;
+ d.denominator = (val >> masks->den_shift) & masks->den_mask;
for (i = 0; i < factor->ftbl_cnt; i++)
- if (den == factor->ftbl[i].den && num == factor->ftbl[i].num)
+ if (d.denominator == factor->ftbl[i].denominator &&
+ d.numerator == factor->ftbl[i].numerator)
break;
if (i >= factor->ftbl_cnt) {
val &= ~(masks->num_mask << masks->num_shift);
- val |= (factor->ftbl[0].num & masks->num_mask) <<
- masks->num_shift;
+ val |= (factor->ftbl[0].numerator & masks->num_mask) << masks->num_shift;
val &= ~(masks->den_mask << masks->den_shift);
- val |= (factor->ftbl[0].den & masks->den_mask) <<
- masks->den_shift;
+ val |= (factor->ftbl[0].denominator & masks->den_mask) << masks->den_shift;
}
if (!(val & masks->enable_mask) || i >= factor->ftbl_cnt) {
@@ -163,7 +161,7 @@ static int clk_factor_init(struct clk_hw *hw)
static const struct clk_ops clk_factor_ops = {
.recalc_rate = clk_factor_recalc_rate,
- .round_rate = clk_factor_round_rate,
+ .determine_rate = clk_factor_determine_rate,
.set_rate = clk_factor_set_rate,
.init = clk_factor_init,
};
@@ -171,8 +169,7 @@ static const struct clk_ops clk_factor_ops = {
struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
unsigned long flags, void __iomem *base,
struct mmp_clk_factor_masks *masks,
- struct mmp_clk_factor_tbl *ftbl,
- unsigned int ftbl_cnt, spinlock_t *lock)
+ struct u32_fract *ftbl, unsigned int ftbl_cnt, spinlock_t *lock)
{
struct mmp_clk_factor *factor;
struct clk_init_data init;