Merge branch 'clk-determine-rate' into clk-next

* clk-determine-rate: (120 commits)
  clk: microchip: core: remove duplicate roclk_determine_rate()
  clk: nxp: Fix pll0 rate check condition in LPC18xx CGU driver
  clk: scmi: migrate round_rate() to determine_rate()
  clk: ti: fapll: convert from round_rate() to determine_rate()
  clk: ti: dra7-atl: convert from round_rate() to determine_rate()
  clk: ti: divider: convert from round_rate() to determine_rate()
  clk: ti: composite: convert from round_rate() to determine_rate()
  clk: ti: dpll: convert from round_rate() to determine_rate()
  clk: ti: dpll: change error return from ~0 to -EINVAL
  clk: ti: dpll: remove round_rate() in favor of determine_rate()
  clk: tegra: tegra210-emc: convert from round_rate() to determine_rate()
  clk: tegra: super: convert from round_rate() to determine_rate()
  clk: tegra: pll: convert from round_rate() to determine_rate()
  clk: tegra: periph: divider: convert from round_rate() to determine_rate()
  clk: tegra: divider: convert from round_rate() to determine_rate()
  clk: tegra: audio-sync: convert from round_rate() to determine_rate()
  clk: fixed-factor: drop round_rate() clk ops
  clk: divider: remove round_rate() in favor of determine_rate()
  clk: visconti: pll: convert from round_rate() to determine_rate()
  clk: versatile: vexpress-osc: convert from round_rate() to determine_rate()
  ...
This commit is contained in:
Stephen Boyd 2025-10-06 13:00:55 -05:00
commit 112104e2b7
No known key found for this signature in database
GPG Key ID: AD028897C6E49525
123 changed files with 1526 additions and 1200 deletions

View File

@ -122,13 +122,13 @@ static int owl_comp_fact_set_rate(struct clk_hw *hw, unsigned long rate,
rate, parent_rate);
}
static long owl_comp_fix_fact_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int owl_comp_fix_fact_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
struct clk_fixed_factor *fix_fact_hw = &comp->rate.fix_fact_hw;
return comp->fix_fact_ops->round_rate(&fix_fact_hw->hw, rate, parent_rate);
return comp->fix_fact_ops->determine_rate(&fix_fact_hw->hw, req);
}
static unsigned long owl_comp_fix_fact_recalc_rate(struct clk_hw *hw,
@ -193,7 +193,7 @@ const struct clk_ops owl_comp_fix_fact_ops = {
.is_enabled = owl_comp_is_enabled,
/* fix_fact_ops */
.round_rate = owl_comp_fix_fact_round_rate,
.determine_rate = owl_comp_fix_fact_determine_rate,
.recalc_rate = owl_comp_fix_fact_recalc_rate,
.set_rate = owl_comp_fix_fact_set_rate,
};

View File

@ -23,13 +23,16 @@ long owl_divider_helper_round_rate(struct owl_clk_common *common,
div_hw->div_flags);
}
static long owl_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int owl_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct owl_divider *div = hw_to_owl_divider(hw);
return owl_divider_helper_round_rate(&div->common, &div->div_hw,
rate, parent_rate);
req->rate = owl_divider_helper_round_rate(&div->common, &div->div_hw,
req->rate,
&req->best_parent_rate);
return 0;
}
unsigned long owl_divider_helper_recalc_rate(struct owl_clk_common *common,
@ -89,6 +92,6 @@ static int owl_divider_set_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops owl_divider_ops = {
.recalc_rate = owl_divider_recalc_rate,
.round_rate = owl_divider_round_rate,
.determine_rate = owl_divider_determine_rate,
.set_rate = owl_divider_set_rate,
};

View File

@ -130,14 +130,16 @@ long owl_factor_helper_round_rate(struct owl_clk_common *common,
return *parent_rate * mul / div;
}
static long owl_factor_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int owl_factor_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct owl_factor *factor = hw_to_owl_factor(hw);
struct owl_factor_hw *factor_hw = &factor->factor_hw;
return owl_factor_helper_round_rate(&factor->common, factor_hw,
rate, parent_rate);
req->rate = owl_factor_helper_round_rate(&factor->common, factor_hw,
req->rate, &req->best_parent_rate);
return 0;
}
unsigned long owl_factor_helper_recalc_rate(struct owl_clk_common *common,
@ -214,7 +216,7 @@ static int owl_factor_set_rate(struct clk_hw *hw, unsigned long rate,
}
const struct clk_ops owl_factor_ops = {
.round_rate = owl_factor_round_rate,
.determine_rate = owl_factor_determine_rate,
.recalc_rate = owl_factor_recalc_rate,
.set_rate = owl_factor_set_rate,
};

View File

@ -56,8 +56,8 @@ static const struct clk_pll_table *_get_pll_table(
return table;
}
static long owl_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int owl_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct owl_pll *pll = hw_to_owl_pll(hw);
struct owl_pll_hw *pll_hw = &pll->pll_hw;
@ -65,17 +65,24 @@ static long owl_pll_round_rate(struct clk_hw *hw, unsigned long rate,
u32 mul;
if (pll_hw->table) {
clkt = _get_pll_table(pll_hw->table, rate);
return clkt->rate;
clkt = _get_pll_table(pll_hw->table, req->rate);
req->rate = clkt->rate;
return 0;
}
/* fixed frequency */
if (pll_hw->width == 0)
return pll_hw->bfreq;
if (pll_hw->width == 0) {
req->rate = pll_hw->bfreq;
mul = owl_pll_calculate_mul(pll_hw, rate);
return 0;
}
return pll_hw->bfreq * mul;
mul = owl_pll_calculate_mul(pll_hw, req->rate);
req->rate = pll_hw->bfreq * mul;
return 0;
}
static unsigned long owl_pll_recalc_rate(struct clk_hw *hw,
@ -188,7 +195,7 @@ const struct clk_ops owl_pll_ops = {
.enable = owl_pll_enable,
.disable = owl_pll_disable,
.is_enabled = owl_pll_is_enabled,
.round_rate = owl_pll_round_rate,
.determine_rate = owl_pll_determine_rate,
.recalc_rate = owl_pll_recalc_rate,
.set_rate = owl_pll_set_rate,
};

View File

@ -270,8 +270,8 @@ static int clk_audio_pll_frac_determine_rate(struct clk_hw *hw,
return 0;
}
static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int clk_audio_pll_pad_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_hw *pclk = clk_hw_get_parent(hw);
long best_rate = -EINVAL;
@ -283,7 +283,7 @@ static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate,
int best_diff = -1;
pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__,
rate, *parent_rate);
req->rate, req->best_parent_rate);
/*
* Rate divisor is actually made of two different divisors, multiplied
@ -304,12 +304,12 @@ static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate,
continue;
best_parent_rate = clk_hw_round_rate(pclk,
rate * tmp_qd * div);
req->rate * tmp_qd * div);
tmp_rate = best_parent_rate / (div * tmp_qd);
tmp_diff = abs(rate - tmp_rate);
tmp_diff = abs(req->rate - tmp_rate);
if (best_diff < 0 || best_diff > tmp_diff) {
*parent_rate = best_parent_rate;
req->best_parent_rate = best_parent_rate;
best_rate = tmp_rate;
best_diff = tmp_diff;
}
@ -318,11 +318,13 @@ static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate,
pr_debug("A PLL/PAD: %s, best_rate = %ld, best_parent_rate = %lu\n",
__func__, best_rate, best_parent_rate);
return best_rate;
req->rate = best_rate;
return 0;
}
static long clk_audio_pll_pmc_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int clk_audio_pll_pmc_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_hw *pclk = clk_hw_get_parent(hw);
long best_rate = -EINVAL;
@ -333,20 +335,20 @@ static long clk_audio_pll_pmc_round_rate(struct clk_hw *hw, unsigned long rate,
int best_diff = -1;
pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n", __func__,
rate, *parent_rate);
req->rate, req->best_parent_rate);
if (!rate)
if (!req->rate)
return 0;
best_parent_rate = clk_round_rate(pclk->clk, 1);
div = max(best_parent_rate / rate, 1UL);
div = max(best_parent_rate / req->rate, 1UL);
for (; div <= AUDIO_PLL_QDPMC_MAX; div++) {
best_parent_rate = clk_round_rate(pclk->clk, rate * div);
best_parent_rate = clk_round_rate(pclk->clk, req->rate * div);
tmp_rate = best_parent_rate / div;
tmp_diff = abs(rate - tmp_rate);
tmp_diff = abs(req->rate - tmp_rate);
if (best_diff < 0 || best_diff > tmp_diff) {
*parent_rate = best_parent_rate;
req->best_parent_rate = best_parent_rate;
best_rate = tmp_rate;
best_diff = tmp_diff;
tmp_qd = div;
@ -356,9 +358,11 @@ static long clk_audio_pll_pmc_round_rate(struct clk_hw *hw, unsigned long rate,
}
pr_debug("A PLL/PMC: %s, best_rate = %ld, best_parent_rate = %lu (qd = %d)\n",
__func__, best_rate, *parent_rate, tmp_qd - 1);
__func__, best_rate, req->best_parent_rate, tmp_qd - 1);
return best_rate;
req->rate = best_rate;
return 0;
}
static int clk_audio_pll_frac_set_rate(struct clk_hw *hw, unsigned long rate,
@ -436,7 +440,7 @@ static const struct clk_ops audio_pll_pad_ops = {
.enable = clk_audio_pll_pad_enable,
.disable = clk_audio_pll_pad_disable,
.recalc_rate = clk_audio_pll_pad_recalc_rate,
.round_rate = clk_audio_pll_pad_round_rate,
.determine_rate = clk_audio_pll_pad_determine_rate,
.set_rate = clk_audio_pll_pad_set_rate,
};
@ -444,7 +448,7 @@ static const struct clk_ops audio_pll_pmc_ops = {
.enable = clk_audio_pll_pmc_enable,
.disable = clk_audio_pll_pmc_disable,
.recalc_rate = clk_audio_pll_pmc_recalc_rate,
.round_rate = clk_audio_pll_pmc_round_rate,
.determine_rate = clk_audio_pll_pmc_determine_rate,
.set_rate = clk_audio_pll_pmc_set_rate,
};

View File

@ -40,21 +40,32 @@ 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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned long div;
if (rate > *parent_rate)
return *parent_rate;
div = *parent_rate / 2;
if (rate < div)
return div;
if (req->rate > req->best_parent_rate) {
req->rate = req->best_parent_rate;
if (rate - div < *parent_rate - rate)
return div;
return 0;
}
div = req->best_parent_rate / 2;
if (req->rate < div) {
req->rate = div;
return *parent_rate;
return 0;
}
if (req->rate - div < req->best_parent_rate - req->rate) {
req->rate = div;
return 0;
}
req->rate = req->best_parent_rate;
return 0;
}
static int clk_sama5d4_h32mx_set_rate(struct clk_hw *hw, unsigned long rate,
@ -77,7 +88,7 @@ static int clk_sama5d4_h32mx_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops h32mx_ops = {
.recalc_rate = clk_sama5d4_h32mx_recalc_rate,
.round_rate = clk_sama5d4_h32mx_round_rate,
.determine_rate = clk_sama5d4_h32mx_determine_rate,
.set_rate = clk_sama5d4_h32mx_set_rate,
};

View File

@ -279,8 +279,11 @@ static int clk_sam9x5_peripheral_determine_rate(struct clk_hw *hw,
long best_diff = LONG_MIN;
u32 shift;
if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max)
return parent_rate;
if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) {
req->rate = parent_rate;
return 0;
}
/* Fist step: check the available dividers. */
for (shift = 0; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
@ -332,50 +335,57 @@ static int clk_sam9x5_peripheral_determine_rate(struct clk_hw *hw,
return 0;
}
static long clk_sam9x5_peripheral_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *parent_rate)
static int clk_sam9x5_peripheral_no_parent_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
int shift = 0;
unsigned long best_rate;
unsigned long best_diff;
unsigned long cur_rate = *parent_rate;
unsigned long cur_rate = req->best_parent_rate;
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) {
req->rate = req->best_parent_rate;
return 0;
}
if (periph->range.max) {
for (; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
cur_rate = *parent_rate >> shift;
cur_rate = req->best_parent_rate >> shift;
if (cur_rate <= periph->range.max)
break;
}
}
if (rate >= cur_rate)
return cur_rate;
if (req->rate >= cur_rate) {
req->rate = cur_rate;
best_diff = cur_rate - rate;
return 0;
}
best_diff = cur_rate - req->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;
cur_rate = req->best_parent_rate >> shift;
if (cur_rate < req->rate)
cur_diff = req->rate - cur_rate;
else
cur_diff = cur_rate - rate;
cur_diff = cur_rate - req->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 < req->rate)
break;
}
return best_rate;
req->rate = best_rate;
return 0;
}
static int clk_sam9x5_peripheral_set_rate(struct clk_hw *hw,
@ -427,7 +437,7 @@ static const struct clk_ops sam9x5_peripheral_ops = {
.disable = clk_sam9x5_peripheral_disable,
.is_enabled = clk_sam9x5_peripheral_is_enabled,
.recalc_rate = clk_sam9x5_peripheral_recalc_rate,
.round_rate = clk_sam9x5_peripheral_round_rate,
.determine_rate = clk_sam9x5_peripheral_no_parent_determine_rate,
.set_rate = clk_sam9x5_peripheral_set_rate,
.save_context = clk_sam9x5_peripheral_save_context,
.restore_context = clk_sam9x5_peripheral_restore_context,

View File

@ -231,13 +231,15 @@ 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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_pll *pll = to_clk_pll(hw);
return clk_pll_get_best_div_mul(pll, rate, *parent_rate,
NULL, NULL, NULL);
req->rate = clk_pll_get_best_div_mul(pll, req->rate, req->best_parent_rate,
NULL, NULL, NULL);
return 0;
}
static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@ -302,7 +304,7 @@ static const struct clk_ops pll_ops = {
.unprepare = clk_pll_unprepare,
.is_prepared = clk_pll_is_prepared,
.recalc_rate = clk_pll_recalc_rate,
.round_rate = clk_pll_round_rate,
.determine_rate = clk_pll_determine_rate,
.set_rate = clk_pll_set_rate,
.save_context = clk_pll_save_context,
.restore_context = clk_pll_restore_context,

View File

@ -33,21 +33,33 @@ 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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned long div;
if (rate > *parent_rate)
return *parent_rate;
div = *parent_rate / 2;
if (rate < div)
return div;
if (req->rate > req->best_parent_rate) {
req->rate = req->best_parent_rate;
if (rate - div < *parent_rate - rate)
return div;
return 0;
}
return *parent_rate;
div = req->best_parent_rate / 2;
if (req->rate < div) {
req->rate = div;
return 0;
}
if (req->rate - div < req->best_parent_rate - req->rate) {
req->rate = div;
return 0;
}
req->rate = req->best_parent_rate;
return 0;
}
static int clk_plldiv_set_rate(struct clk_hw *hw, unsigned long rate,
@ -66,7 +78,7 @@ static int clk_plldiv_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops plldiv_ops = {
.recalc_rate = clk_plldiv_recalc_rate,
.round_rate = clk_plldiv_round_rate,
.determine_rate = clk_plldiv_determine_rate,
.set_rate = clk_plldiv_set_rate,
};

View File

@ -227,12 +227,16 @@ static long sam9x60_frac_pll_compute_mul_frac(struct sam9x60_pll_core *core,
return tmprate;
}
static long sam9x60_frac_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int sam9x60_frac_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
return sam9x60_frac_pll_compute_mul_frac(core, rate, *parent_rate, false);
req->rate = sam9x60_frac_pll_compute_mul_frac(core, req->rate,
req->best_parent_rate,
false);
return 0;
}
static int sam9x60_frac_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@ -318,7 +322,7 @@ static const struct clk_ops sam9x60_frac_pll_ops = {
.unprepare = sam9x60_frac_pll_unprepare,
.is_prepared = sam9x60_frac_pll_is_prepared,
.recalc_rate = sam9x60_frac_pll_recalc_rate,
.round_rate = sam9x60_frac_pll_round_rate,
.determine_rate = sam9x60_frac_pll_determine_rate,
.set_rate = sam9x60_frac_pll_set_rate,
.save_context = sam9x60_frac_pll_save_context,
.restore_context = sam9x60_frac_pll_restore_context,
@ -329,7 +333,7 @@ static const struct clk_ops sam9x60_frac_pll_ops_chg = {
.unprepare = sam9x60_frac_pll_unprepare,
.is_prepared = sam9x60_frac_pll_is_prepared,
.recalc_rate = sam9x60_frac_pll_recalc_rate,
.round_rate = sam9x60_frac_pll_round_rate,
.determine_rate = sam9x60_frac_pll_determine_rate,
.set_rate = sam9x60_frac_pll_set_rate_chg,
.save_context = sam9x60_frac_pll_save_context,
.restore_context = sam9x60_frac_pll_restore_context,
@ -487,12 +491,15 @@ static long sam9x60_div_pll_compute_div(struct sam9x60_pll_core *core,
return best_rate;
}
static long sam9x60_div_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int sam9x60_div_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
return sam9x60_div_pll_compute_div(core, parent_rate, rate);
req->rate = sam9x60_div_pll_compute_div(core, &req->best_parent_rate,
req->rate);
return 0;
}
static int sam9x60_div_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@ -601,7 +608,7 @@ static const struct clk_ops sam9x60_div_pll_ops = {
.unprepare = sam9x60_div_pll_unprepare,
.is_prepared = sam9x60_div_pll_is_prepared,
.recalc_rate = sam9x60_div_pll_recalc_rate,
.round_rate = sam9x60_div_pll_round_rate,
.determine_rate = sam9x60_div_pll_determine_rate,
.set_rate = sam9x60_div_pll_set_rate,
.save_context = sam9x60_div_pll_save_context,
.restore_context = sam9x60_div_pll_restore_context,
@ -612,7 +619,7 @@ static const struct clk_ops sam9x60_div_pll_ops_chg = {
.unprepare = sam9x60_div_pll_unprepare,
.is_prepared = sam9x60_div_pll_is_prepared,
.recalc_rate = sam9x60_div_pll_recalc_rate,
.round_rate = sam9x60_div_pll_round_rate,
.determine_rate = sam9x60_div_pll_determine_rate,
.set_rate = sam9x60_div_pll_set_rate_chg,
.save_context = sam9x60_div_pll_save_context,
.restore_context = sam9x60_div_pll_restore_context,
@ -623,7 +630,7 @@ static const struct clk_ops sam9x60_fixed_div_pll_ops = {
.unprepare = sam9x60_div_pll_unprepare,
.is_prepared = sam9x60_div_pll_is_prepared,
.recalc_rate = sam9x60_fixed_div_pll_recalc_rate,
.round_rate = sam9x60_div_pll_round_rate,
.determine_rate = sam9x60_div_pll_determine_rate,
.save_context = sam9x60_div_pll_save_context,
.restore_context = sam9x60_div_pll_restore_context,
};

View File

@ -319,8 +319,8 @@ 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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
struct clk_hw *parent = clk_hw_get_parent(hw);
@ -336,25 +336,27 @@ 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 = req->rate * usb->divisors[i];
tmp_parent_rate = clk_hw_round_rate(parent, tmp_parent_rate);
tmprate = DIV_ROUND_CLOSEST(tmp_parent_rate, usb->divisors[i]);
if (tmprate < rate)
tmpdiff = rate - tmprate;
if (tmprate < req->rate)
tmpdiff = req->rate - tmprate;
else
tmpdiff = tmprate - rate;
tmpdiff = tmprate - req->rate;
if (bestdiff < 0 || bestdiff > tmpdiff) {
bestrate = tmprate;
bestdiff = tmpdiff;
*parent_rate = tmp_parent_rate;
req->best_parent_rate = tmp_parent_rate;
}
if (!bestdiff)
break;
}
return bestrate;
req->rate = bestrate;
return 0;
}
static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
@ -384,7 +386,7 @@ static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops at91rm9200_usb_ops = {
.recalc_rate = at91rm9200_clk_usb_recalc_rate,
.round_rate = at91rm9200_clk_usb_round_rate,
.determine_rate = at91rm9200_clk_usb_determine_rate,
.set_rate = at91rm9200_clk_usb_set_rate,
};

View File

@ -108,21 +108,21 @@ static unsigned long i2s_pll_recalc_rate(struct clk_hw *hw,
return ((parent_rate / idiv) * fbdiv) / odiv;
}
static long i2s_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int i2s_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct i2s_pll_clk *clk = to_i2s_pll_clk(hw);
const struct i2s_pll_cfg *pll_cfg = i2s_pll_get_cfg(*prate);
const struct i2s_pll_cfg *pll_cfg = i2s_pll_get_cfg(req->best_parent_rate);
int i;
if (!pll_cfg) {
dev_err(clk->dev, "invalid parent rate=%ld\n", *prate);
dev_err(clk->dev, "invalid parent rate=%ld\n", req->best_parent_rate);
return -EINVAL;
}
for (i = 0; pll_cfg[i].rate != 0; i++)
if (pll_cfg[i].rate == rate)
return rate;
if (pll_cfg[i].rate == req->rate)
return 0;
return -EINVAL;
}
@ -156,7 +156,7 @@ static int i2s_pll_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops i2s_pll_ops = {
.recalc_rate = i2s_pll_recalc_rate,
.round_rate = i2s_pll_round_rate,
.determine_rate = i2s_pll_determine_rate,
.set_rate = i2s_pll_set_rate,
};

View File

@ -149,8 +149,8 @@ static unsigned long axs10x_pll_recalc_rate(struct clk_hw *hw,
return rate;
}
static long axs10x_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int axs10x_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
int i;
long best_rate;
@ -163,11 +163,13 @@ static long axs10x_pll_round_rate(struct clk_hw *hw, unsigned long rate,
best_rate = pll_cfg[0].rate;
for (i = 1; pll_cfg[i].rate != 0; i++) {
if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate))
if (abs(req->rate - pll_cfg[i].rate) < abs(req->rate - best_rate))
best_rate = pll_cfg[i].rate;
}
return best_rate;
req->rate = best_rate;
return 0;
}
static int axs10x_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@ -208,7 +210,7 @@ static int axs10x_pll_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops axs10x_pll_ops = {
.recalc_rate = axs10x_pll_recalc_rate,
.round_rate = axs10x_pll_round_rate,
.determine_rate = axs10x_pll_determine_rate,
.set_rate = axs10x_pll_set_rate,
};

View File

@ -228,15 +228,18 @@ static inline unsigned long ccu_div_var_calc_divider(unsigned long rate,
CCU_DIV_CLKDIV_MAX(mask));
}
static long ccu_div_var_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int ccu_div_var_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct ccu_div *div = to_ccu_div(hw);
unsigned long divider;
divider = ccu_div_var_calc_divider(rate, *parent_rate, div->mask);
divider = ccu_div_var_calc_divider(req->rate, req->best_parent_rate,
div->mask);
return ccu_div_calc_freq(*parent_rate, divider);
req->rate = ccu_div_calc_freq(req->best_parent_rate, divider);
return 0;
}
/*
@ -308,12 +311,14 @@ static unsigned long ccu_div_fixed_recalc_rate(struct clk_hw *hw,
return ccu_div_calc_freq(parent_rate, div->divider);
}
static long ccu_div_fixed_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int ccu_div_fixed_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct ccu_div *div = to_ccu_div(hw);
return ccu_div_calc_freq(*parent_rate, div->divider);
req->rate = ccu_div_calc_freq(req->best_parent_rate, div->divider);
return 0;
}
static int ccu_div_fixed_set_rate(struct clk_hw *hw, unsigned long rate,
@ -534,14 +539,14 @@ static const struct clk_ops ccu_div_var_gate_to_set_ops = {
.disable = ccu_div_gate_disable,
.is_enabled = ccu_div_gate_is_enabled,
.recalc_rate = ccu_div_var_recalc_rate,
.round_rate = ccu_div_var_round_rate,
.determine_rate = ccu_div_var_determine_rate,
.set_rate = ccu_div_var_set_rate_fast,
.debug_init = ccu_div_var_debug_init
};
static const struct clk_ops ccu_div_var_nogate_ops = {
.recalc_rate = ccu_div_var_recalc_rate,
.round_rate = ccu_div_var_round_rate,
.determine_rate = ccu_div_var_determine_rate,
.set_rate = ccu_div_var_set_rate_slow,
.debug_init = ccu_div_var_debug_init
};
@ -551,7 +556,7 @@ static const struct clk_ops ccu_div_gate_ops = {
.disable = ccu_div_gate_disable,
.is_enabled = ccu_div_gate_is_enabled,
.recalc_rate = ccu_div_fixed_recalc_rate,
.round_rate = ccu_div_fixed_round_rate,
.determine_rate = ccu_div_fixed_determine_rate,
.set_rate = ccu_div_fixed_set_rate,
.debug_init = ccu_div_gate_debug_init
};
@ -565,7 +570,7 @@ static const struct clk_ops ccu_div_buf_ops = {
static const struct clk_ops ccu_div_fixed_ops = {
.recalc_rate = ccu_div_fixed_recalc_rate,
.round_rate = ccu_div_fixed_round_rate,
.determine_rate = ccu_div_fixed_determine_rate,
.set_rate = ccu_div_fixed_set_rate,
.debug_init = ccu_div_fixed_debug_init
};

View File

@ -228,14 +228,16 @@ static void ccu_pll_calc_factors(unsigned long rate, unsigned long parent_rate,
}
}
static long ccu_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int ccu_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned long nr = 1, nf = 1, od = 1;
ccu_pll_calc_factors(rate, *parent_rate, &nr, &nf, &od);
ccu_pll_calc_factors(req->rate, req->best_parent_rate, &nr, &nf, &od);
return ccu_pll_calc_freq(*parent_rate, nr, nf, od);
req->rate = ccu_pll_calc_freq(req->best_parent_rate, nr, nf, od);
return 0;
}
/*
@ -481,7 +483,7 @@ static const struct clk_ops ccu_pll_gate_to_set_ops = {
.disable = ccu_pll_disable,
.is_enabled = ccu_pll_is_enabled,
.recalc_rate = ccu_pll_recalc_rate,
.round_rate = ccu_pll_round_rate,
.determine_rate = ccu_pll_determine_rate,
.set_rate = ccu_pll_set_rate_norst,
.debug_init = ccu_pll_debug_init
};
@ -491,7 +493,7 @@ static const struct clk_ops ccu_pll_straight_set_ops = {
.disable = ccu_pll_disable,
.is_enabled = ccu_pll_is_enabled,
.recalc_rate = ccu_pll_recalc_rate,
.round_rate = ccu_pll_round_rate,
.determine_rate = ccu_pll_determine_rate,
.set_rate = ccu_pll_set_rate_reset,
.debug_init = ccu_pll_debug_init
};

View File

@ -98,22 +98,27 @@ static unsigned long iproc_asiu_clk_recalc_rate(struct clk_hw *hw,
return clk->rate;
}
static long iproc_asiu_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int iproc_asiu_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned int div;
if (rate == 0 || *parent_rate == 0)
if (req->rate == 0 || req->best_parent_rate == 0)
return -EINVAL;
if (rate == *parent_rate)
return *parent_rate;
if (req->rate == req->best_parent_rate)
return 0;
div = DIV_ROUND_CLOSEST(*parent_rate, rate);
if (div < 2)
return *parent_rate;
div = DIV_ROUND_CLOSEST(req->best_parent_rate, req->rate);
if (div < 2) {
req->rate = req->best_parent_rate;
return *parent_rate / div;
return 0;
}
req->rate = req->best_parent_rate / div;
return 0;
}
static int iproc_asiu_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@ -168,7 +173,7 @@ static const struct clk_ops iproc_asiu_ops = {
.enable = iproc_asiu_clk_enable,
.disable = iproc_asiu_clk_disable,
.recalc_rate = iproc_asiu_clk_recalc_rate,
.round_rate = iproc_asiu_clk_round_rate,
.determine_rate = iproc_asiu_clk_determine_rate,
.set_rate = iproc_asiu_clk_set_rate,
};

View File

@ -212,13 +212,15 @@ static unsigned long applnco_recalc_rate(struct clk_hw *hw,
((u64) div) * incbase + inc1);
}
static long applnco_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int applnco_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned long lo = *parent_rate / (COARSE_DIV_OFFSET + LFSR_TBLSIZE) + 1;
unsigned long hi = *parent_rate / COARSE_DIV_OFFSET;
unsigned long lo = req->best_parent_rate / (COARSE_DIV_OFFSET + LFSR_TBLSIZE) + 1;
unsigned long hi = req->best_parent_rate / COARSE_DIV_OFFSET;
return clamp(rate, lo, hi);
req->rate = clamp(req->rate, lo, hi);
return 0;
}
static int applnco_enable(struct clk_hw *hw)
@ -246,7 +248,7 @@ static void applnco_disable(struct clk_hw *hw)
static const struct clk_ops applnco_ops = {
.set_rate = applnco_set_rate,
.recalc_rate = applnco_recalc_rate,
.round_rate = applnco_round_rate,
.determine_rate = applnco_determine_rate,
.enable = applnco_enable,
.disable = applnco_disable,
.is_enabled = applnco_is_enabled,

View File

@ -608,8 +608,8 @@ static unsigned long bm1880_clk_div_recalc_rate(struct clk_hw *hw,
return rate;
}
static long bm1880_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int bm1880_clk_div_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct bm1880_div_hw_clock *div_hw = to_bm1880_div_clk(hw);
struct bm1880_div_clock *div = &div_hw->div;
@ -621,13 +621,18 @@ static long bm1880_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
val = readl(reg_addr) >> div->shift;
val &= clk_div_mask(div->width);
return divider_ro_round_rate(hw, rate, prate, div->table,
div->width, div->flags,
val);
req->rate = divider_ro_round_rate(hw, req->rate,
&req->best_parent_rate,
div->table,
div->width, div->flags, val);
return 0;
}
return divider_round_rate(hw, rate, prate, div->table,
div->width, div->flags);
req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
div->table, div->width, div->flags);
return 0;
}
static int bm1880_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
@ -665,7 +670,7 @@ static int bm1880_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops bm1880_clk_div_ops = {
.recalc_rate = bm1880_clk_div_recalc_rate,
.round_rate = bm1880_clk_div_round_rate,
.determine_rate = bm1880_clk_div_determine_rate,
.set_rate = bm1880_clk_div_set_rate,
};

View File

@ -183,8 +183,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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct cdce706_hw_data *hwd = to_hw_data(hw);
unsigned long mul, div;
@ -192,9 +192,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__, req->rate, req->best_parent_rate);
rational_best_approximation(rate, *parent_rate,
rational_best_approximation(req->rate, req->best_parent_rate,
CDCE706_PLL_N_MAX, CDCE706_PLL_M_MAX,
&mul, &div);
hwd->mul = mul;
@ -204,9 +204,11 @@ static long cdce706_pll_round_rate(struct clk_hw *hw, unsigned long rate,
"%s, pll: %d, mul: %lu, div: %lu\n",
__func__, hwd->idx, mul, div);
res = (u64)*parent_rate * hwd->mul;
res = (u64)req->best_parent_rate * hwd->mul;
do_div(res, hwd->div);
return res;
req->rate = res;
return 0;
}
static int cdce706_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@ -251,7 +253,7 @@ static int cdce706_pll_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops cdce706_pll_ops = {
.recalc_rate = cdce706_pll_recalc_rate,
.round_rate = cdce706_pll_round_rate,
.determine_rate = cdce706_pll_determine_rate,
.set_rate = cdce706_pll_set_rate,
};

View File

@ -128,13 +128,15 @@ static void cdce925_pll_find_rate(unsigned long rate,
}
}
static long cdce925_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int cdce925_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
u16 n, m;
cdce925_pll_find_rate(rate, *parent_rate, &n, &m);
return (long)cdce925_pll_calculate_rate(*parent_rate, n, m);
cdce925_pll_find_rate(req->rate, req->best_parent_rate, &n, &m);
req->rate = (long)cdce925_pll_calculate_rate(req->best_parent_rate, n, m);
return 0;
}
static int cdce925_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@ -266,7 +268,7 @@ static const struct clk_ops cdce925_pll_ops = {
.prepare = cdce925_pll_prepare,
.unprepare = cdce925_pll_unprepare,
.recalc_rate = cdce925_pll_recalc_rate,
.round_rate = cdce925_pll_round_rate,
.determine_rate = cdce925_pll_determine_rate,
.set_rate = cdce925_pll_set_rate,
};
@ -420,20 +422,23 @@ static unsigned long cdce925_clk_best_parent_rate(
return rate * pdiv_best;
}
static long cdce925_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int cdce925_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned long l_parent_rate = *parent_rate;
u16 divider = cdce925_calc_divider(rate, l_parent_rate);
unsigned long l_parent_rate = req->best_parent_rate;
u16 divider = cdce925_calc_divider(req->rate, l_parent_rate);
if (l_parent_rate / divider != rate) {
l_parent_rate = cdce925_clk_best_parent_rate(hw, rate);
divider = cdce925_calc_divider(rate, l_parent_rate);
*parent_rate = l_parent_rate;
if (l_parent_rate / divider != req->rate) {
l_parent_rate = cdce925_clk_best_parent_rate(hw, req->rate);
divider = cdce925_calc_divider(req->rate, l_parent_rate);
req->best_parent_rate = l_parent_rate;
}
if (divider)
return (long)(l_parent_rate / divider);
req->rate = (long)(l_parent_rate / divider);
else
req->rate = 0;
return 0;
}
@ -451,7 +456,7 @@ static const struct clk_ops cdce925_clk_ops = {
.prepare = cdce925_clk_prepare,
.unprepare = cdce925_clk_unprepare,
.recalc_rate = cdce925_clk_recalc_rate,
.round_rate = cdce925_clk_round_rate,
.determine_rate = cdce925_clk_determine_rate,
.set_rate = cdce925_clk_set_rate,
};
@ -473,14 +478,17 @@ static u16 cdce925_y1_calc_divider(unsigned long rate,
return (u16)divider;
}
static long cdce925_clk_y1_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int cdce925_clk_y1_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned long l_parent_rate = *parent_rate;
u16 divider = cdce925_y1_calc_divider(rate, l_parent_rate);
unsigned long l_parent_rate = req->best_parent_rate;
u16 divider = cdce925_y1_calc_divider(req->rate, l_parent_rate);
if (divider)
return (long)(l_parent_rate / divider);
req->rate = (long)(l_parent_rate / divider);
else
req->rate = 0;
return 0;
}
@ -498,7 +506,7 @@ static const struct clk_ops cdce925_clk_y1_ops = {
.prepare = cdce925_clk_prepare,
.unprepare = cdce925_clk_unprepare,
.recalc_rate = cdce925_clk_recalc_rate,
.round_rate = cdce925_clk_y1_round_rate,
.determine_rate = cdce925_clk_y1_determine_rate,
.set_rate = cdce925_clk_y1_set_rate,
};

View File

@ -305,15 +305,19 @@ static unsigned long cs2000_recalc_rate(struct clk_hw *hw,
return cs2000_ratio_to_rate(ratio, parent_rate, priv->lf_ratio);
}
static long cs2000_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int cs2000_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct cs2000_priv *priv = hw_to_priv(hw);
u32 ratio;
ratio = cs2000_rate_to_ratio(*parent_rate, rate, priv->lf_ratio);
ratio = cs2000_rate_to_ratio(req->best_parent_rate, req->rate,
priv->lf_ratio);
return cs2000_ratio_to_rate(ratio, *parent_rate, priv->lf_ratio);
req->rate = cs2000_ratio_to_rate(ratio, req->best_parent_rate,
priv->lf_ratio);
return 0;
}
static int cs2000_select_ratio_mode(struct cs2000_priv *priv,
@ -430,7 +434,7 @@ static u8 cs2000_get_parent(struct clk_hw *hw)
static const struct clk_ops cs2000_ops = {
.get_parent = cs2000_get_parent,
.recalc_rate = cs2000_recalc_rate,
.round_rate = cs2000_round_rate,
.determine_rate = cs2000_determine_rate,
.set_rate = cs2000_set_rate,
.prepare = cs2000_enable,
.unprepare = cs2000_disable,

View File

@ -431,27 +431,6 @@ long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
}
EXPORT_SYMBOL_GPL(divider_ro_round_rate_parent);
static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_divider *divider = to_clk_divider(hw);
/* if read only, just return current value */
if (divider->flags & CLK_DIVIDER_READ_ONLY) {
u32 val;
val = clk_div_readl(divider) >> divider->shift;
val &= clk_div_mask(divider->width);
return divider_ro_round_rate(hw, rate, prate, divider->table,
divider->width, divider->flags,
val);
}
return divider_round_rate(hw, rate, prate, divider->table,
divider->width, divider->flags);
}
static int clk_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
@ -527,7 +506,6 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops clk_divider_ops = {
.recalc_rate = clk_divider_recalc_rate,
.round_rate = clk_divider_round_rate,
.determine_rate = clk_divider_determine_rate,
.set_rate = clk_divider_set_rate,
};
@ -535,7 +513,6 @@ EXPORT_SYMBOL_GPL(clk_divider_ops);
const struct clk_ops clk_divider_ro_ops = {
.recalc_rate = clk_divider_recalc_rate,
.round_rate = clk_divider_round_rate,
.determine_rate = clk_divider_determine_rate,
};
EXPORT_SYMBOL_GPL(clk_divider_ro_ops);

View File

@ -389,23 +389,25 @@ static unsigned long ep93xx_div_recalc_rate(struct clk_hw *hw,
return DIV_ROUND_CLOSEST(parent_rate, clk->div[index]);
}
static long ep93xx_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int ep93xx_div_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct ep93xx_clk *clk = ep93xx_clk_from(hw);
unsigned long best = 0, now;
unsigned int i;
for (i = 0; i < clk->num_div; i++) {
if ((rate * clk->div[i]) == *parent_rate)
return rate;
if (req->rate * clk->div[i] == req->best_parent_rate)
return 0;
now = DIV_ROUND_CLOSEST(*parent_rate, clk->div[i]);
if (!best || is_best(rate, now, best))
now = DIV_ROUND_CLOSEST(req->best_parent_rate, clk->div[i]);
if (!best || is_best(req->rate, now, best))
best = now;
}
return best;
req->rate = best;
return 0;
}
static int ep93xx_div_set_rate(struct clk_hw *hw, unsigned long rate,
@ -437,7 +439,7 @@ static const struct clk_ops ep93xx_div_ops = {
.disable = ep93xx_clk_disable,
.is_enabled = ep93xx_clk_is_enabled,
.recalc_rate = ep93xx_div_recalc_rate,
.round_rate = ep93xx_div_round_rate,
.determine_rate = ep93xx_div_determine_rate,
.set_rate = ep93xx_div_set_rate,
};

View File

@ -30,19 +30,21 @@ 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,
unsigned long *prate)
static int clk_factor_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
unsigned long best_parent;
best_parent = (rate / fix->mult) * fix->div;
*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
best_parent = (req->rate / fix->mult) * fix->div;
req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
}
return (*prate / fix->div) * fix->mult;
req->rate = (req->best_parent_rate / fix->div) * fix->mult;
return 0;
}
static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate,
@ -50,7 +52,7 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate,
{
/*
* We must report success but we can do so unconditionally because
* clk_factor_round_rate returns values that ensure this call is a
* clk_factor_determine_rate returns values that ensure this call is a
* nop.
*/
@ -69,7 +71,7 @@ static unsigned long clk_factor_recalc_accuracy(struct clk_hw *hw,
}
const struct clk_ops clk_fixed_factor_ops = {
.round_rate = clk_factor_round_rate,
.determine_rate = clk_factor_determine_rate,
.set_rate = clk_factor_set_rate,
.recalc_rate = clk_factor_recalc_rate,
.recalc_accuracy = clk_factor_recalc_accuracy,

View File

@ -151,25 +151,32 @@ void clk_fractional_divider_general_approximation(struct clk_hw *hw,
}
EXPORT_SYMBOL_GPL(clk_fractional_divider_general_approximation);
static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int clk_fd_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
unsigned long m, n;
u64 ret;
if (!rate || (!clk_hw_can_set_rate_parent(hw) && rate >= *parent_rate))
return *parent_rate;
if (!req->rate || (!clk_hw_can_set_rate_parent(hw) && req->rate >= req->best_parent_rate)) {
req->rate = req->best_parent_rate;
return 0;
}
if (fd->approximation)
fd->approximation(hw, rate, parent_rate, &m, &n);
fd->approximation(hw, req->rate, &req->best_parent_rate, &m, &n);
else
clk_fractional_divider_general_approximation(hw, rate, parent_rate, &m, &n);
clk_fractional_divider_general_approximation(hw, req->rate,
&req->best_parent_rate,
&m, &n);
ret = (u64)*parent_rate * m;
ret = (u64)req->best_parent_rate * m;
do_div(ret, n);
return ret;
req->rate = ret;
return 0;
}
static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
@ -250,7 +257,7 @@ static void clk_fd_debug_init(struct clk_hw *hw, struct dentry *dentry)
const struct clk_ops clk_fractional_divider_ops = {
.recalc_rate = clk_fd_recalc_rate,
.round_rate = clk_fd_round_rate,
.determine_rate = clk_fd_determine_rate,
.set_rate = clk_fd_set_rate,
#ifdef CONFIG_DEBUG_FS
.debug_init = clk_fd_debug_init,

View File

@ -126,13 +126,16 @@ static unsigned long gemini_pci_recalc_rate(struct clk_hw *hw,
return 33000000;
}
static long gemini_pci_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int gemini_pci_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
/* We support 33 and 66 MHz */
if (rate < 48000000)
return 33000000;
return 66000000;
if (req->rate < 48000000)
req->rate = 33000000;
else
req->rate = 66000000;
return 0;
}
static int gemini_pci_set_rate(struct clk_hw *hw, unsigned long rate,
@ -179,7 +182,7 @@ static int gemini_pci_is_enabled(struct clk_hw *hw)
static const struct clk_ops gemini_pci_clk_ops = {
.recalc_rate = gemini_pci_recalc_rate,
.round_rate = gemini_pci_round_rate,
.determine_rate = gemini_pci_determine_rate,
.set_rate = gemini_pci_set_rate,
.enable = gemini_pci_enable,
.disable = gemini_pci_disable,

View File

@ -130,15 +130,17 @@ 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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
u32 divq, divf;
unsigned long ref_freq = *parent_rate;
unsigned long ref_freq = req->best_parent_rate;
clk_pll_calc(rate, ref_freq, &divq, &divf);
clk_pll_calc(req->rate, ref_freq, &divq, &divf);
return (ref_freq * (divf + 1)) / (1 << divq);
req->rate = (ref_freq * (divf + 1)) / (1 << divq);
return 0;
}
static int clk_pll_set_rate(struct clk_hw *hwclk, unsigned long rate,
@ -185,7 +187,7 @@ static const struct clk_ops clk_pll_ops = {
.enable = clk_pll_enable,
.disable = clk_pll_disable,
.recalc_rate = clk_pll_recalc_rate,
.round_rate = clk_pll_round_rate,
.determine_rate = clk_pll_determine_rate,
.set_rate = clk_pll_set_rate,
};
@ -227,16 +229,18 @@ 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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
u32 div;
div = *parent_rate / rate;
div = req->best_parent_rate / req->rate;
div++;
div &= ~0x1;
return *parent_rate / div;
req->rate = req->best_parent_rate / div;
return 0;
}
static int clk_periclk_set_rate(struct clk_hw *hwclk, unsigned long rate,
@ -255,7 +259,7 @@ static int clk_periclk_set_rate(struct clk_hw *hwclk, unsigned long rate,
static const struct clk_ops periclk_ops = {
.recalc_rate = clk_periclk_recalc_rate,
.round_rate = clk_periclk_round_rate,
.determine_rate = clk_periclk_determine_rate,
.set_rate = clk_periclk_set_rate,
};

View File

@ -197,8 +197,8 @@ static unsigned long hsdk_pll_recalc_rate(struct clk_hw *hw,
return rate;
}
static long hsdk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int hsdk_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
int i;
unsigned long best_rate;
@ -211,13 +211,15 @@ static long hsdk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
best_rate = pll_cfg[0].rate;
for (i = 1; pll_cfg[i].rate != 0; i++) {
if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate))
if (abs(req->rate - pll_cfg[i].rate) < abs(req->rate - best_rate))
best_rate = pll_cfg[i].rate;
}
dev_dbg(clk->dev, "chosen best rate: %lu\n", best_rate);
return best_rate;
req->rate = best_rate;
return 0;
}
static int hsdk_pll_comm_update_rate(struct hsdk_pll_clk *clk,
@ -296,7 +298,7 @@ static int hsdk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops hsdk_pll_ops = {
.recalc_rate = hsdk_pll_recalc_rate,
.round_rate = hsdk_pll_round_rate,
.determine_rate = hsdk_pll_determine_rate,
.set_rate = hsdk_pll_set_rate,
};

View File

@ -491,28 +491,33 @@ static long lmk04832_calc_pll2_params(unsigned long prate, unsigned long rate,
return DIV_ROUND_CLOSEST(prate * 2 * pll2_p * pll2_n, pll2_r);
}
static long lmk04832_vco_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int lmk04832_vco_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco);
unsigned int n, p, r;
long vco_rate;
int ret;
ret = lmk04832_check_vco_ranges(lmk, rate);
ret = lmk04832_check_vco_ranges(lmk, req->rate);
if (ret < 0)
return ret;
vco_rate = lmk04832_calc_pll2_params(*prate, rate, &n, &p, &r);
vco_rate = lmk04832_calc_pll2_params(req->best_parent_rate, req->rate,
&n, &p, &r);
if (vco_rate < 0) {
dev_err(lmk->dev, "PLL2 parameters out of range\n");
return vco_rate;
req->rate = vco_rate;
return 0;
}
if (rate != vco_rate)
if (req->rate != vco_rate)
return -EINVAL;
return vco_rate;
req->rate = vco_rate;
return 0;
}
static int lmk04832_vco_set_rate(struct clk_hw *hw, unsigned long rate,
@ -579,7 +584,7 @@ static const struct clk_ops lmk04832_vco_ops = {
.prepare = lmk04832_vco_prepare,
.unprepare = lmk04832_vco_unprepare,
.recalc_rate = lmk04832_vco_recalc_rate,
.round_rate = lmk04832_vco_round_rate,
.determine_rate = lmk04832_vco_determine_rate,
.set_rate = lmk04832_vco_set_rate,
};
@ -888,25 +893,27 @@ static unsigned long lmk04832_sclk_recalc_rate(struct clk_hw *hw,
return DIV_ROUND_CLOSEST(prate, sysref_div);
}
static long lmk04832_sclk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int lmk04832_sclk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk);
unsigned long sclk_rate;
unsigned int sysref_div;
sysref_div = DIV_ROUND_CLOSEST(*prate, rate);
sclk_rate = DIV_ROUND_CLOSEST(*prate, sysref_div);
sysref_div = DIV_ROUND_CLOSEST(req->best_parent_rate, req->rate);
sclk_rate = DIV_ROUND_CLOSEST(req->best_parent_rate, sysref_div);
if (sysref_div < 0x07 || sysref_div > 0x1fff) {
dev_err(lmk->dev, "SYSREF divider out of range\n");
return -EINVAL;
}
if (rate != sclk_rate)
if (req->rate != sclk_rate)
return -EINVAL;
return sclk_rate;
req->rate = sclk_rate;
return 0;
}
static int lmk04832_sclk_set_rate(struct clk_hw *hw, unsigned long rate,
@ -945,7 +952,7 @@ static const struct clk_ops lmk04832_sclk_ops = {
.prepare = lmk04832_sclk_prepare,
.unprepare = lmk04832_sclk_unprepare,
.recalc_rate = lmk04832_sclk_recalc_rate,
.round_rate = lmk04832_sclk_round_rate,
.determine_rate = lmk04832_sclk_determine_rate,
.set_rate = lmk04832_sclk_set_rate,
};
@ -1069,26 +1076,28 @@ static unsigned long lmk04832_dclk_recalc_rate(struct clk_hw *hw,
return rate;
}
static long lmk04832_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int lmk04832_dclk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw);
struct lmk04832 *lmk = dclk->lmk;
unsigned long dclk_rate;
unsigned int dclk_div;
dclk_div = DIV_ROUND_CLOSEST(*prate, rate);
dclk_rate = DIV_ROUND_CLOSEST(*prate, dclk_div);
dclk_div = DIV_ROUND_CLOSEST(req->best_parent_rate, req->rate);
dclk_rate = DIV_ROUND_CLOSEST(req->best_parent_rate, dclk_div);
if (dclk_div < 1 || dclk_div > 0x3ff) {
dev_err(lmk->dev, "%s_div out of range\n", clk_hw_get_name(hw));
return -EINVAL;
}
if (rate != dclk_rate)
if (req->rate != dclk_rate)
return -EINVAL;
return dclk_rate;
req->rate = dclk_rate;
return 0;
}
static int lmk04832_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
@ -1158,7 +1167,7 @@ static const struct clk_ops lmk04832_dclk_ops = {
.prepare = lmk04832_dclk_prepare,
.unprepare = lmk04832_dclk_unprepare,
.recalc_rate = lmk04832_dclk_recalc_rate,
.round_rate = lmk04832_dclk_round_rate,
.determine_rate = lmk04832_dclk_determine_rate,
.set_rate = lmk04832_dclk_set_rate,
};

View File

@ -93,14 +93,16 @@ static unsigned long ls1x_divider_recalc_rate(struct clk_hw *hw,
d->flags, d->width);
}
static long ls1x_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int ls1x_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct ls1x_clk *ls1x_clk = to_ls1x_clk(hw);
const struct ls1x_clk_div_data *d = ls1x_clk->data;
return divider_round_rate(hw, rate, prate, d->table,
d->width, d->flags);
req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
d->table, d->width, d->flags);
return 0;
}
static int ls1x_divider_set_rate(struct clk_hw *hw, unsigned long rate,
@ -146,7 +148,7 @@ static int ls1x_divider_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops ls1x_clk_divider_ops = {
.recalc_rate = ls1x_divider_recalc_rate,
.round_rate = ls1x_divider_round_rate,
.determine_rate = ls1x_divider_determine_rate,
.set_rate = ls1x_divider_set_rate,
};

View File

@ -159,29 +159,32 @@ static unsigned long max9485_clkout_recalc_rate(struct clk_hw *hw,
return 0;
}
static long max9485_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int max9485_clkout_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
const struct max9485_rate *curr, *prev = NULL;
for (curr = max9485_rates; curr->out != 0; curr++) {
/* Exact matches */
if (curr->out == rate)
return rate;
if (curr->out == req->rate)
return 0;
/*
* Find the first entry that has a frequency higher than the
* requested one.
*/
if (curr->out > rate) {
if (curr->out > req->rate) {
unsigned int mid;
/*
* If this is the first entry, clamp the value to the
* lowest possible frequency.
*/
if (!prev)
return curr->out;
if (!prev) {
req->rate = curr->out;
return 0;
}
/*
* Otherwise, determine whether the previous entry or
@ -189,14 +192,18 @@ static long max9485_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
*/
mid = prev->out + ((curr->out - prev->out) / 2);
return (mid > rate) ? prev->out : curr->out;
req->rate = mid > req->rate ? prev->out : curr->out;
return 0;
}
prev = curr;
}
/* If the last entry was still too high, clamp the value */
return prev->out;
req->rate = prev->out;
return 0;
}
struct max9485_clk {
@ -221,7 +228,7 @@ static const struct max9485_clk max9485_clks[MAX9485_NUM_CLKS] = {
.parent_index = -1,
.ops = {
.set_rate = max9485_clkout_set_rate,
.round_rate = max9485_clkout_round_rate,
.determine_rate = max9485_clkout_determine_rate,
.recalc_rate = max9485_clkout_recalc_rate,
},
},

View File

@ -386,8 +386,8 @@ static unsigned long m10v_clk_divider_recalc_rate(struct clk_hw *hw,
divider->flags, divider->width);
}
static long m10v_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int m10v_clk_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct m10v_clk_divider *divider = to_m10v_div(hw);
@ -398,13 +398,19 @@ static long m10v_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
val = readl(divider->reg) >> divider->shift;
val &= clk_div_mask(divider->width);
return divider_ro_round_rate(hw, rate, prate, divider->table,
divider->width, divider->flags,
val);
req->rate = divider_ro_round_rate(hw, req->rate,
&req->best_parent_rate,
divider->table,
divider->width,
divider->flags, val);
return 0;
}
return divider_round_rate(hw, rate, prate, divider->table,
divider->width, divider->flags);
req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
divider->table, divider->width, divider->flags);
return 0;
}
static int m10v_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
@ -450,7 +456,7 @@ static int m10v_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops m10v_clk_divider_ops = {
.recalc_rate = m10v_clk_divider_recalc_rate,
.round_rate = m10v_clk_divider_round_rate,
.determine_rate = m10v_clk_divider_determine_rate,
.set_rate = m10v_clk_divider_set_rate,
};

View File

@ -112,14 +112,16 @@ static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
return bestmult;
}
static long clk_multiplier_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int clk_multiplier_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_multiplier *mult = to_clk_multiplier(hw);
unsigned long factor = __bestmult(hw, rate, parent_rate,
unsigned long factor = __bestmult(hw, req->rate, &req->best_parent_rate,
mult->width, mult->flags);
return *parent_rate * factor;
req->rate = req->best_parent_rate * factor;
return 0;
}
static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate,
@ -150,7 +152,7 @@ static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops clk_multiplier_ops = {
.recalc_rate = clk_multiplier_recalc_rate,
.round_rate = clk_multiplier_round_rate,
.determine_rate = clk_multiplier_determine_rate,
.set_rate = clk_multiplier_set_rate,
};
EXPORT_SYMBOL_GPL(clk_multiplier_ops);

View File

@ -54,8 +54,8 @@ static unsigned long scmi_clk_recalc_rate(struct clk_hw *hw,
return rate;
}
static long scmi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int scmi_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
u64 fmin, fmax, ftmp;
struct scmi_clk *clk = to_scmi_clk(hw);
@ -67,20 +67,27 @@ static long scmi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
* running at then.
*/
if (clk->info->rate_discrete)
return rate;
return 0;
fmin = clk->info->range.min_rate;
fmax = clk->info->range.max_rate;
if (rate <= fmin)
return fmin;
else if (rate >= fmax)
return fmax;
if (req->rate <= fmin) {
req->rate = fmin;
ftmp = rate - fmin;
return 0;
} else if (req->rate >= fmax) {
req->rate = fmax;
return 0;
}
ftmp = req->rate - fmin;
ftmp += clk->info->range.step_size - 1; /* to round up */
do_div(ftmp, clk->info->range.step_size);
return ftmp * clk->info->range.step_size + fmin;
req->rate = ftmp * clk->info->range.step_size + fmin;
return 0;
}
static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@ -119,15 +126,6 @@ static u8 scmi_clk_get_parent(struct clk_hw *hw)
return p_idx;
}
static int scmi_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
/*
* Suppose all the requested rates are supported, and let firmware
* to handle the left work.
*/
return 0;
}
static int scmi_clk_enable(struct clk_hw *hw)
{
struct scmi_clk *clk = to_scmi_clk(hw);
@ -300,7 +298,6 @@ scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key)
/* Rate ops */
ops->recalc_rate = scmi_clk_recalc_rate;
ops->round_rate = scmi_clk_round_rate;
ops->determine_rate = scmi_clk_determine_rate;
if (feats_key & BIT(SCMI_CLK_RATE_CTRL_SUPPORTED))
ops->set_rate = scmi_clk_set_rate;

View File

@ -32,8 +32,8 @@ static unsigned long scpi_clk_recalc_rate(struct clk_hw *hw,
return clk->scpi_ops->clk_get_val(clk->id);
}
static long scpi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int scpi_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
/*
* We can't figure out what rate it will be, so just return the
@ -41,7 +41,7 @@ static long scpi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
* after the rate is set and we'll know what rate the clock is
* running at then.
*/
return rate;
return 0;
}
static int scpi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@ -54,7 +54,7 @@ static int scpi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops scpi_clk_ops = {
.recalc_rate = scpi_clk_recalc_rate,
.round_rate = scpi_clk_round_rate,
.determine_rate = scpi_clk_determine_rate,
.set_rate = scpi_clk_set_rate,
};
@ -92,12 +92,14 @@ static unsigned long scpi_dvfs_recalc_rate(struct clk_hw *hw,
return opp->freq;
}
static long scpi_dvfs_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int scpi_dvfs_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct scpi_clk *clk = to_scpi_clk(hw);
return __scpi_dvfs_round_rate(clk, rate);
req->rate = __scpi_dvfs_round_rate(clk, req->rate);
return 0;
}
static int __scpi_find_dvfs_index(struct scpi_clk *clk, unsigned long rate)
@ -124,7 +126,7 @@ static int scpi_dvfs_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops scpi_dvfs_ops = {
.recalc_rate = scpi_dvfs_recalc_rate,
.round_rate = scpi_dvfs_round_rate,
.determine_rate = scpi_dvfs_determine_rate,
.set_rate = scpi_dvfs_set_rate,
};

View File

@ -227,20 +227,28 @@ static unsigned long si514_recalc_rate(struct clk_hw *hw,
return si514_calc_rate(&settings);
}
static long si514_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int si514_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_si514_muldiv settings;
int err;
if (!rate)
if (!req->rate) {
req->rate = 0;
return 0;
}
err = si514_calc_muldiv(&settings, rate);
if (err)
return err;
err = si514_calc_muldiv(&settings, req->rate);
if (err) {
req->rate = err;
return si514_calc_rate(&settings);
return 0;
}
req->rate = si514_calc_rate(&settings);
return 0;
}
/*
@ -289,7 +297,7 @@ static const struct clk_ops si514_clk_ops = {
.unprepare = si514_unprepare,
.is_prepared = si514_is_prepared,
.recalc_rate = si514_recalc_rate,
.round_rate = si514_round_rate,
.determine_rate = si514_determine_rate,
.set_rate = si514_set_rate,
};

View File

@ -164,15 +164,17 @@ static unsigned long si521xx_diff_recalc_rate(struct clk_hw *hw,
return (unsigned long)rate;
}
static long si521xx_diff_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int si521xx_diff_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned long best_parent;
best_parent = (rate / SI521XX_DIFF_MULT) * SI521XX_DIFF_DIV;
*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
best_parent = (req->rate / SI521XX_DIFF_MULT) * SI521XX_DIFF_DIV;
req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
return (*prate / SI521XX_DIFF_DIV) * SI521XX_DIFF_MULT;
req->rate = (req->best_parent_rate / SI521XX_DIFF_DIV) * SI521XX_DIFF_MULT;
return 0;
}
static int si521xx_diff_set_rate(struct clk_hw *hw, unsigned long rate,
@ -208,7 +210,7 @@ static void si521xx_diff_unprepare(struct clk_hw *hw)
}
static const struct clk_ops si521xx_diff_clk_ops = {
.round_rate = si521xx_diff_round_rate,
.determine_rate = si521xx_diff_determine_rate,
.set_rate = si521xx_diff_set_rate,
.recalc_rate = si521xx_diff_recalc_rate,
.prepare = si521xx_diff_prepare,

View File

@ -663,8 +663,8 @@ static unsigned long si5341_synth_clk_recalc_rate(struct clk_hw *hw,
return f;
}
static long si5341_synth_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int si5341_synth_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_si5341_synth *synth = to_clk_si5341_synth(hw);
u64 f;
@ -672,15 +672,21 @@ static long si5341_synth_clk_round_rate(struct clk_hw *hw, unsigned long rate,
/* The synthesizer accuracy is such that anything in range will work */
f = synth->data->freq_vco;
do_div(f, SI5341_SYNTH_N_MAX);
if (rate < f)
return f;
if (req->rate < f) {
req->rate = f;
return 0;
}
f = synth->data->freq_vco;
do_div(f, SI5341_SYNTH_N_MIN);
if (rate > f)
return f;
if (req->rate > f) {
req->rate = f;
return rate;
return 0;
}
return 0;
}
static int si5341_synth_program(struct clk_si5341_synth *synth,
@ -741,7 +747,7 @@ static const struct clk_ops si5341_synth_clk_ops = {
.prepare = si5341_synth_clk_prepare,
.unprepare = si5341_synth_clk_unprepare,
.recalc_rate = si5341_synth_clk_recalc_rate,
.round_rate = si5341_synth_clk_round_rate,
.determine_rate = si5341_synth_clk_determine_rate,
.set_rate = si5341_synth_clk_set_rate,
};

View File

@ -307,16 +307,16 @@ static unsigned long si544_recalc_rate(struct clk_hw *hw,
return si544_calc_rate(&settings);
}
static long si544_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int si544_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_si544 *data = to_clk_si544(hw);
if (!is_valid_frequency(data, rate))
if (!is_valid_frequency(data, req->rate))
return -EINVAL;
/* The accuracy is less than 1 Hz, so any rate is possible */
return rate;
return 0;
}
/* Calculates the maximum "small" change, 950 * rate / 1000000 */
@ -408,7 +408,7 @@ static const struct clk_ops si544_clk_ops = {
.unprepare = si544_unprepare,
.is_prepared = si544_is_prepared,
.recalc_rate = si544_recalc_rate,
.round_rate = si544_round_rate,
.determine_rate = si544_determine_rate,
.set_rate = si544_set_rate,
};

View File

@ -246,34 +246,40 @@ static unsigned long si570_recalc_rate(struct clk_hw *hw,
return rate;
}
static long si570_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int si570_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
int err;
u64 rfreq;
unsigned int n1, hs_div;
struct clk_si570 *data = to_clk_si570(hw);
if (!rate)
return 0;
if (!req->rate) {
req->rate = 0;
if (div64_u64(abs(rate - data->frequency) * 10000LL,
return 0;
}
if (div64_u64(abs(req->rate - data->frequency) * 10000LL,
data->frequency) < 35) {
rfreq = div64_u64((data->rfreq * rate) +
div64_u64(data->frequency, 2), data->frequency);
rfreq = div64_u64((data->rfreq * req->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(req->rate, data, &rfreq, &n1, &hs_div);
if (err) {
dev_err(&data->i2c_client->dev,
"unable to round rate\n");
req->rate = 0;
return 0;
}
}
return rate;
return 0;
}
/**
@ -368,7 +374,7 @@ static int si570_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops si570_clk_ops = {
.recalc_rate = si570_recalc_rate,
.round_rate = si570_round_rate,
.determine_rate = si570_determine_rate,
.set_rate = si570_set_rate,
};

View File

@ -412,25 +412,27 @@ static long sp_pll_calc_div(struct sp_pll *clk, unsigned long rate)
return fbdiv;
}
static long sp_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int sp_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct sp_pll *clk = to_sp_pll(hw);
long ret;
if (rate == *prate) {
ret = *prate; /* bypass */
if (req->rate == req->best_parent_rate) {
ret = req->best_parent_rate; /* bypass */
} else if (clk->div_width == DIV_A) {
ret = plla_round_rate(clk, rate);
ret = plla_round_rate(clk, req->rate);
} else if (clk->div_width == DIV_TV) {
ret = plltv_div(clk, rate);
ret = plltv_div(clk, req->rate);
if (ret < 0)
ret = *prate;
ret = req->best_parent_rate;
} else {
ret = sp_pll_calc_div(clk, rate) * clk->brate;
ret = sp_pll_calc_div(clk, req->rate) * clk->brate;
}
return ret;
req->rate = ret;
return 0;
}
static unsigned long sp_pll_recalc_rate(struct clk_hw *hw,
@ -535,7 +537,7 @@ static const struct clk_ops sp_pll_ops = {
.enable = sp_pll_enable,
.disable = sp_pll_disable,
.is_enabled = sp_pll_is_enabled,
.round_rate = sp_pll_round_rate,
.determine_rate = sp_pll_determine_rate,
.recalc_rate = sp_pll_recalc_rate,
.set_rate = sp_pll_set_rate
};

View File

@ -213,19 +213,21 @@ static unsigned long s5_pll_recalc_rate(struct clk_hw *hw,
return conf.freq;
}
static long s5_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int s5_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct s5_pll_conf conf;
return s5_calc_params(rate, *parent_rate, &conf);
req->rate = s5_calc_params(req->rate, req->best_parent_rate, &conf);
return 0;
}
static const struct clk_ops s5_pll_ops = {
.enable = s5_pll_enable,
.disable = s5_pll_disable,
.set_rate = s5_pll_set_rate,
.round_rate = s5_pll_round_rate,
.determine_rate = s5_pll_determine_rate,
.recalc_rate = s5_pll_recalc_rate,
};

View File

@ -443,8 +443,8 @@ static unsigned long clk_apb_mul_recalc_rate(struct clk_hw *hw,
return parent_rate;
}
static long clk_apb_mul_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int clk_apb_mul_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_apb_mul *am = to_clk_apb_mul(hw);
unsigned long mult = 1;
@ -453,12 +453,14 @@ static long clk_apb_mul_round_rate(struct clk_hw *hw, unsigned long rate,
mult = 2;
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
unsigned long best_parent = rate / mult;
unsigned long best_parent = req->rate / mult;
*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
}
return *prate * mult;
req->rate = req->best_parent_rate * mult;
return 0;
}
static int clk_apb_mul_set_rate(struct clk_hw *hw, unsigned long rate,
@ -474,7 +476,7 @@ static int clk_apb_mul_set_rate(struct clk_hw *hw, unsigned long rate,
}
static const struct clk_ops clk_apb_mul_factor_ops = {
.round_rate = clk_apb_mul_round_rate,
.determine_rate = clk_apb_mul_determine_rate,
.set_rate = clk_apb_mul_set_rate,
.recalc_rate = clk_apb_mul_recalc_rate,
};
@ -670,21 +672,23 @@ static unsigned long stm32f4_pll_recalc(struct clk_hw *hw,
return parent_rate * n;
}
static long stm32f4_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int stm32f4_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_gate *gate = to_clk_gate(hw);
struct stm32f4_pll *pll = to_stm32f4_pll(gate);
unsigned long n;
n = rate / *prate;
n = req->rate / req->best_parent_rate;
if (n < pll->n_start)
n = pll->n_start;
else if (n > 432)
n = 432;
return *prate * n;
req->rate = req->best_parent_rate * n;
return 0;
}
static void stm32f4_pll_set_ssc(struct clk_hw *hw, unsigned long parent_rate,
@ -749,7 +753,7 @@ static const struct clk_ops stm32f4_pll_gate_ops = {
.disable = stm32f4_pll_disable,
.is_enabled = stm32f4_pll_is_enabled,
.recalc_rate = stm32f4_pll_recalc,
.round_rate = stm32f4_pll_round_rate,
.determine_rate = stm32f4_pll_determine_rate,
.set_rate = stm32f4_pll_set_rate,
};

View File

@ -146,12 +146,14 @@ static unsigned int tps68470_clk_cfg_lookup(unsigned long rate)
return best_idx;
}
static long tps68470_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int tps68470_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned int idx = tps68470_clk_cfg_lookup(rate);
unsigned int idx = tps68470_clk_cfg_lookup(req->rate);
return clk_freqs[idx].freq;
req->rate = clk_freqs[idx].freq;
return 0;
}
static int tps68470_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@ -186,7 +188,7 @@ static const struct clk_ops tps68470_clk_ops = {
.prepare = tps68470_clk_prepare,
.unprepare = tps68470_clk_unprepare,
.recalc_rate = tps68470_clk_recalc_rate,
.round_rate = tps68470_clk_round_rate,
.determine_rate = tps68470_clk_determine_rate,
.set_rate = tps68470_clk_set_rate,
};

View File

@ -289,22 +289,25 @@ static unsigned long vc3_pfd_recalc_rate(struct clk_hw *hw,
return rate;
}
static long vc3_pfd_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int vc3_pfd_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
const struct vc3_pfd_data *pfd = vc3->data;
unsigned long idiv;
/* PLL cannot operate with input clock above 50 MHz. */
if (rate > 50000000)
if (req->rate > 50000000)
return -EINVAL;
/* CLKIN within range of PLL input, feed directly to PLL. */
if (*parent_rate <= 50000000)
return *parent_rate;
if (req->best_parent_rate <= 50000000) {
req->rate = req->best_parent_rate;
idiv = DIV_ROUND_UP(*parent_rate, rate);
return 0;
}
idiv = DIV_ROUND_UP(req->best_parent_rate, req->rate);
if (pfd->num == VC3_PFD1 || pfd->num == VC3_PFD3) {
if (idiv > 63)
return -EINVAL;
@ -313,7 +316,9 @@ static long vc3_pfd_round_rate(struct clk_hw *hw, unsigned long rate,
return -EINVAL;
}
return *parent_rate / idiv;
req->rate = req->best_parent_rate / idiv;
return 0;
}
static int vc3_pfd_set_rate(struct clk_hw *hw, unsigned long rate,
@ -354,7 +359,7 @@ static int vc3_pfd_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops vc3_pfd_ops = {
.recalc_rate = vc3_pfd_recalc_rate,
.round_rate = vc3_pfd_round_rate,
.determine_rate = vc3_pfd_determine_rate,
.set_rate = vc3_pfd_set_rate,
};
@ -385,36 +390,38 @@ static unsigned long vc3_pll_recalc_rate(struct clk_hw *hw,
return rate;
}
static long vc3_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int vc3_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
const struct vc3_pll_data *pll = vc3->data;
u64 div_frc;
if (rate < pll->vco.min)
rate = pll->vco.min;
if (rate > pll->vco.max)
rate = pll->vco.max;
if (req->rate < pll->vco.min)
req->rate = pll->vco.min;
if (req->rate > pll->vco.max)
req->rate = pll->vco.max;
vc3->div_int = rate / *parent_rate;
vc3->div_int = req->rate / req->best_parent_rate;
if (pll->num == VC3_PLL2) {
if (vc3->div_int > 0x7ff)
rate = *parent_rate * 0x7ff;
req->rate = req->best_parent_rate * 0x7ff;
/* Determine best fractional part, which is 16 bit wide */
div_frc = rate % *parent_rate;
div_frc = req->rate % req->best_parent_rate;
div_frc *= BIT(16) - 1;
vc3->div_frc = min_t(u64, div64_ul(div_frc, *parent_rate), U16_MAX);
rate = (*parent_rate *
(vc3->div_int * VC3_2_POW_16 + vc3->div_frc) / VC3_2_POW_16);
vc3->div_frc = min_t(u64,
div64_ul(div_frc, req->best_parent_rate),
U16_MAX);
req->rate = (req->best_parent_rate *
(vc3->div_int * VC3_2_POW_16 + vc3->div_frc) / VC3_2_POW_16);
} else {
rate = *parent_rate * vc3->div_int;
req->rate = req->best_parent_rate * vc3->div_int;
}
return rate;
return 0;
}
static int vc3_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@ -441,7 +448,7 @@ static int vc3_pll_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops vc3_pll_ops = {
.recalc_rate = vc3_pll_recalc_rate,
.round_rate = vc3_pll_round_rate,
.determine_rate = vc3_pll_determine_rate,
.set_rate = vc3_pll_set_rate,
};
@ -498,8 +505,8 @@ static unsigned long vc3_div_recalc_rate(struct clk_hw *hw,
div_data->flags, div_data->width);
}
static long vc3_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int vc3_div_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
const struct vc3_div_data *div_data = vc3->data;
@ -511,11 +518,16 @@ static long vc3_div_round_rate(struct clk_hw *hw, unsigned long rate,
bestdiv >>= div_data->shift;
bestdiv &= VC3_DIV_MASK(div_data->width);
bestdiv = vc3_get_div(div_data->table, bestdiv, div_data->flags);
return DIV_ROUND_UP(*parent_rate, bestdiv);
req->rate = DIV_ROUND_UP(req->best_parent_rate, bestdiv);
return 0;
}
return divider_round_rate(hw, rate, parent_rate, div_data->table,
div_data->width, div_data->flags);
req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
div_data->table,
div_data->width, div_data->flags);
return 0;
}
static int vc3_div_set_rate(struct clk_hw *hw, unsigned long rate,
@ -534,7 +546,7 @@ static int vc3_div_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops vc3_div_ops = {
.recalc_rate = vc3_div_recalc_rate,
.round_rate = vc3_div_round_rate,
.determine_rate = vc3_div_determine_rate,
.set_rate = vc3_div_set_rate,
};

View File

@ -304,11 +304,11 @@ static unsigned long vc5_dbl_recalc_rate(struct clk_hw *hw,
return parent_rate;
}
static long vc5_dbl_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int vc5_dbl_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
if ((*parent_rate == rate) || ((*parent_rate * 2) == rate))
return rate;
if ((req->best_parent_rate == req->rate) || ((req->best_parent_rate * 2) == req->rate))
return 0;
else
return -EINVAL;
}
@ -332,7 +332,7 @@ static int vc5_dbl_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops vc5_dbl_ops = {
.recalc_rate = vc5_dbl_recalc_rate,
.round_rate = vc5_dbl_round_rate,
.determine_rate = vc5_dbl_determine_rate,
.set_rate = vc5_dbl_set_rate,
};
@ -363,24 +363,29 @@ static unsigned long vc5_pfd_recalc_rate(struct clk_hw *hw,
return parent_rate / VC5_REF_DIVIDER_REF_DIV(div);
}
static long vc5_pfd_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int vc5_pfd_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned long idiv;
/* PLL cannot operate with input clock above 50 MHz. */
if (rate > 50000000)
if (req->rate > 50000000)
return -EINVAL;
/* CLKIN within range of PLL input, feed directly to PLL. */
if (*parent_rate <= 50000000)
return *parent_rate;
if (req->best_parent_rate <= 50000000) {
req->rate = req->best_parent_rate;
idiv = DIV_ROUND_UP(*parent_rate, rate);
return 0;
}
idiv = DIV_ROUND_UP(req->best_parent_rate, req->rate);
if (idiv > 127)
return -EINVAL;
return *parent_rate / idiv;
req->rate = req->best_parent_rate / idiv;
return 0;
}
static int vc5_pfd_set_rate(struct clk_hw *hw, unsigned long rate,
@ -420,7 +425,7 @@ static int vc5_pfd_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops vc5_pfd_ops = {
.recalc_rate = vc5_pfd_recalc_rate,
.round_rate = vc5_pfd_round_rate,
.determine_rate = vc5_pfd_determine_rate,
.set_rate = vc5_pfd_set_rate,
};
@ -444,30 +449,32 @@ static unsigned long vc5_pll_recalc_rate(struct clk_hw *hw,
return (parent_rate * div_int) + ((parent_rate * div_frc) >> 24);
}
static long vc5_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int vc5_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw);
struct vc5_driver_data *vc5 = hwdata->vc5;
u32 div_int;
u64 div_frc;
rate = clamp(rate, VC5_PLL_VCO_MIN, vc5->chip_info->vco_max);
req->rate = clamp(req->rate, VC5_PLL_VCO_MIN, vc5->chip_info->vco_max);
/* Determine integer part, which is 12 bit wide */
div_int = rate / *parent_rate;
div_int = req->rate / req->best_parent_rate;
if (div_int > 0xfff)
rate = *parent_rate * 0xfff;
req->rate = req->best_parent_rate * 0xfff;
/* Determine best fractional part, which is 24 bit wide */
div_frc = rate % *parent_rate;
div_frc = req->rate % req->best_parent_rate;
div_frc *= BIT(24) - 1;
do_div(div_frc, *parent_rate);
do_div(div_frc, req->best_parent_rate);
hwdata->div_int = div_int;
hwdata->div_frc = (u32)div_frc;
return (*parent_rate * div_int) + ((*parent_rate * div_frc) >> 24);
req->rate = (req->best_parent_rate * div_int) + ((req->best_parent_rate * div_frc) >> 24);
return 0;
}
static int vc5_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@ -488,7 +495,7 @@ static int vc5_pll_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops vc5_pll_ops = {
.recalc_rate = vc5_pll_recalc_rate,
.round_rate = vc5_pll_round_rate,
.determine_rate = vc5_pll_determine_rate,
.set_rate = vc5_pll_set_rate,
};
@ -520,17 +527,17 @@ static unsigned long vc5_fod_recalc_rate(struct clk_hw *hw,
return div64_u64((u64)f_in << 24ULL, ((u64)div_int << 24ULL) + div_frc);
}
static long vc5_fod_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int vc5_fod_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw);
/* VCO frequency is divided by two before entering FOD */
u32 f_in = *parent_rate / 2;
u32 f_in = req->best_parent_rate / 2;
u32 div_int;
u64 div_frc;
/* Determine integer part, which is 12 bit wide */
div_int = f_in / rate;
div_int = f_in / req->rate;
/*
* WARNING: The clock chip does not output signal if the integer part
* of the divider is 0xfff and fractional part is non-zero.
@ -538,18 +545,20 @@ static long vc5_fod_round_rate(struct clk_hw *hw, unsigned long rate,
*/
if (div_int > 0xffe) {
div_int = 0xffe;
rate = f_in / div_int;
req->rate = f_in / div_int;
}
/* Determine best fractional part, which is 30 bit wide */
div_frc = f_in % rate;
div_frc = f_in % req->rate;
div_frc <<= 24;
do_div(div_frc, rate);
do_div(div_frc, req->rate);
hwdata->div_int = div_int;
hwdata->div_frc = (u32)div_frc;
return div64_u64((u64)f_in << 24ULL, ((u64)div_int << 24ULL) + div_frc);
req->rate = div64_u64((u64)f_in << 24ULL, ((u64)div_int << 24ULL) + div_frc);
return 0;
}
static int vc5_fod_set_rate(struct clk_hw *hw, unsigned long rate,
@ -589,7 +598,7 @@ static int vc5_fod_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops vc5_fod_ops = {
.recalc_rate = vc5_fod_recalc_rate,
.round_rate = vc5_fod_round_rate,
.determine_rate = vc5_fod_determine_rate,
.set_rate = vc5_fod_set_rate,
};

View File

@ -900,17 +900,18 @@ static unsigned long vc7_fod_recalc_rate(struct clk_hw *hw, unsigned long parent
return fod_rate;
}
static long vc7_fod_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate)
static int vc7_fod_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct vc7_fod_data *fod = container_of(hw, struct vc7_fod_data, hw);
unsigned long fod_rate;
pr_debug("%s - %s: requested rate: %lu, parent_rate: %lu\n",
__func__, clk_hw_get_name(hw), rate, *parent_rate);
__func__, clk_hw_get_name(hw), req->rate, req->best_parent_rate);
vc7_calc_fod_divider(rate, *parent_rate,
vc7_calc_fod_divider(req->rate, req->best_parent_rate,
&fod->fod_1st_int, &fod->fod_2nd_int, &fod->fod_frac);
fod_rate = vc7_calc_fod_2nd_stage_rate(*parent_rate, fod->fod_1st_int,
fod_rate = vc7_calc_fod_2nd_stage_rate(req->best_parent_rate, fod->fod_1st_int,
fod->fod_2nd_int, fod->fod_frac);
pr_debug("%s - %s: fod_1st_int: %u, fod_2nd_int: %u, fod_frac: %llu\n",
@ -918,7 +919,9 @@ static long vc7_fod_round_rate(struct clk_hw *hw, unsigned long rate, unsigned l
fod->fod_1st_int, fod->fod_2nd_int, fod->fod_frac);
pr_debug("%s - %s rate: %lu\n", __func__, clk_hw_get_name(hw), fod_rate);
return fod_rate;
req->rate = fod_rate;
return 0;
}
static int vc7_fod_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
@ -952,7 +955,7 @@ static int vc7_fod_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long
static const struct clk_ops vc7_fod_ops = {
.recalc_rate = vc7_fod_recalc_rate,
.round_rate = vc7_fod_round_rate,
.determine_rate = vc7_fod_determine_rate,
.set_rate = vc7_fod_set_rate,
};
@ -978,21 +981,24 @@ static unsigned long vc7_iod_recalc_rate(struct clk_hw *hw, unsigned long parent
return iod_rate;
}
static long vc7_iod_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate)
static int vc7_iod_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct vc7_iod_data *iod = container_of(hw, struct vc7_iod_data, hw);
unsigned long iod_rate;
pr_debug("%s - %s: requested rate: %lu, parent_rate: %lu\n",
__func__, clk_hw_get_name(hw), rate, *parent_rate);
__func__, clk_hw_get_name(hw), req->rate, req->best_parent_rate);
vc7_calc_iod_divider(rate, *parent_rate, &iod->iod_int);
iod_rate = div64_u64(*parent_rate, iod->iod_int);
vc7_calc_iod_divider(req->rate, req->best_parent_rate, &iod->iod_int);
iod_rate = div64_u64(req->best_parent_rate, iod->iod_int);
pr_debug("%s - %s: iod_int: %u\n", __func__, clk_hw_get_name(hw), iod->iod_int);
pr_debug("%s - %s rate: %ld\n", __func__, clk_hw_get_name(hw), iod_rate);
return iod_rate;
req->rate = iod_rate;
return 0;
}
static int vc7_iod_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
@ -1023,7 +1029,7 @@ static int vc7_iod_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long
static const struct clk_ops vc7_iod_ops = {
.recalc_rate = vc7_iod_recalc_rate,
.round_rate = vc7_iod_round_rate,
.determine_rate = vc7_iod_determine_rate,
.set_rate = vc7_iod_set_rate,
};

View File

@ -128,30 +128,31 @@ 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,
unsigned long *prate)
static int vt8500_dclk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_device *cdev = to_clk_device(hw);
u32 divisor;
if (rate == 0)
if (req->rate == 0)
return 0;
divisor = *prate / rate;
divisor = req->best_parent_rate / req->rate;
/* If prate / rate would be decimal, incr the divisor */
if (rate * divisor < *prate)
if (req->rate * divisor < req->best_parent_rate)
divisor++;
/*
* If this is a request for SDMMC we have to adjust the divisor
* when >31 to use the fixed predivisor
*/
if ((cdev->div_mask == 0x3F) && (divisor > 31)) {
if ((cdev->div_mask == 0x3F) && (divisor > 31))
divisor = 64 * ((divisor / 64) + 1);
}
return *prate / divisor;
req->rate = req->best_parent_rate / divisor;
return 0;
}
static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
@ -202,7 +203,7 @@ static const struct clk_ops vt8500_gated_clk_ops = {
};
static const struct clk_ops vt8500_divisor_clk_ops = {
.round_rate = vt8500_dclk_round_rate,
.determine_rate = vt8500_dclk_determine_rate,
.set_rate = vt8500_dclk_set_rate,
.recalc_rate = vt8500_dclk_recalc_rate,
};
@ -211,7 +212,7 @@ static const struct clk_ops vt8500_gated_divisor_clk_ops = {
.enable = vt8500_dclk_enable,
.disable = vt8500_dclk_disable,
.is_enabled = vt8500_dclk_is_enabled,
.round_rate = vt8500_dclk_round_rate,
.determine_rate = vt8500_dclk_determine_rate,
.set_rate = vt8500_dclk_set_rate,
.recalc_rate = vt8500_dclk_recalc_rate,
};
@ -594,8 +595,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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_pll *pll = to_clk_pll(hw);
u32 filter, mul, div1, div2;
@ -604,33 +605,43 @@ static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate,
switch (pll->type) {
case PLL_TYPE_VT8500:
ret = vt8500_find_pll_bits(rate, *prate, &mul, &div1);
ret = vt8500_find_pll_bits(req->rate, req->best_parent_rate,
&mul, &div1);
if (!ret)
round_rate = VT8500_BITS_TO_FREQ(*prate, mul, div1);
round_rate = VT8500_BITS_TO_FREQ(req->best_parent_rate,
mul, div1);
break;
case PLL_TYPE_WM8650:
ret = wm8650_find_pll_bits(rate, *prate, &mul, &div1, &div2);
ret = wm8650_find_pll_bits(req->rate, req->best_parent_rate,
&mul, &div1, &div2);
if (!ret)
round_rate = WM8650_BITS_TO_FREQ(*prate, mul, div1, div2);
round_rate = WM8650_BITS_TO_FREQ(req->best_parent_rate,
mul, div1, div2);
break;
case PLL_TYPE_WM8750:
ret = wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2);
ret = wm8750_find_pll_bits(req->rate, req->best_parent_rate,
&filter, &mul, &div1, &div2);
if (!ret)
round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2);
round_rate = WM8750_BITS_TO_FREQ(req->best_parent_rate,
mul, div1, div2);
break;
case PLL_TYPE_WM8850:
ret = wm8850_find_pll_bits(rate, *prate, &mul, &div1, &div2);
ret = wm8850_find_pll_bits(req->rate, req->best_parent_rate,
&mul, &div1, &div2);
if (!ret)
round_rate = WM8850_BITS_TO_FREQ(*prate, mul, div1, div2);
round_rate = WM8850_BITS_TO_FREQ(req->best_parent_rate,
mul, div1, div2);
break;
default:
ret = -EINVAL;
return -EINVAL;
}
if (ret)
return ret;
req->rate = ret;
else
req->rate = round_rate;
return round_rate;
return 0;
}
static unsigned long vtwm_pll_recalc_rate(struct clk_hw *hw,
@ -665,7 +676,7 @@ static unsigned long vtwm_pll_recalc_rate(struct clk_hw *hw,
}
static const struct clk_ops vtwm_pll_ops = {
.round_rate = vtwm_pll_round_rate,
.determine_rate = vtwm_pll_determine_rate,
.set_rate = vtwm_pll_set_rate,
.recalc_rate = vtwm_pll_recalc_rate,
};

View File

@ -133,18 +133,20 @@ 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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
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] - req->rate) <
abs(wm831x_fll_auto_rates[best] - req->rate))
best = i;
return wm831x_fll_auto_rates[best];
req->rate = wm831x_fll_auto_rates[best];
return 0;
}
static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate,
@ -214,7 +216,7 @@ static const struct clk_ops wm831x_fll_ops = {
.is_prepared = wm831x_fll_is_prepared,
.prepare = wm831x_fll_prepare,
.unprepare = wm831x_fll_unprepare,
.round_rate = wm831x_fll_round_rate,
.determine_rate = wm831x_fll_determine_rate,
.recalc_rate = wm831x_fll_recalc_rate,
.set_rate = wm831x_fll_set_rate,
.get_parent = wm831x_fll_get_parent,

View File

@ -271,23 +271,28 @@ static unsigned long xgene_clk_pmd_recalc_rate(struct clk_hw *hw,
return ret;
}
static long xgene_clk_pmd_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int xgene_clk_pmd_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct xgene_clk_pmd *fd = to_xgene_clk_pmd(hw);
u64 ret, scale;
if (!rate || rate >= *parent_rate)
return *parent_rate;
if (!req->rate || req->rate >= req->best_parent_rate) {
req->rate = req->best_parent_rate;
return 0;
}
/* freq = parent_rate * scaler / denom */
ret = rate * fd->denom;
scale = DIV_ROUND_UP_ULL(ret, *parent_rate);
ret = req->rate * fd->denom;
scale = DIV_ROUND_UP_ULL(ret, req->best_parent_rate);
ret = (u64)*parent_rate * scale;
ret = (u64)req->best_parent_rate * scale;
do_div(ret, fd->denom);
return ret;
req->rate = ret;
return 0;
}
static int xgene_clk_pmd_set_rate(struct clk_hw *hw, unsigned long rate,
@ -333,7 +338,7 @@ static int xgene_clk_pmd_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops xgene_clk_pmd_ops = {
.recalc_rate = xgene_clk_pmd_recalc_rate,
.round_rate = xgene_clk_pmd_round_rate,
.determine_rate = xgene_clk_pmd_determine_rate,
.set_rate = xgene_clk_pmd_set_rate,
};
@ -593,23 +598,25 @@ 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,
unsigned long *prate)
static int xgene_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct xgene_clk *pclk = to_xgene_clk(hw);
unsigned long parent_rate = *prate;
unsigned long parent_rate = req->best_parent_rate;
u32 divider;
if (pclk->param.divider_reg) {
/* Let's compute the divider */
if (rate > parent_rate)
rate = parent_rate;
divider = parent_rate / rate; /* Rounded down */
if (req->rate > parent_rate)
req->rate = parent_rate;
divider = parent_rate / req->rate; /* Rounded down */
} else {
divider = 1;
}
return parent_rate / divider;
req->rate = parent_rate / divider;
return 0;
}
static const struct clk_ops xgene_clk_ops = {
@ -618,7 +625,7 @@ static const struct clk_ops xgene_clk_ops = {
.is_enabled = xgene_clk_is_enabled,
.recalc_rate = xgene_clk_recalc_rate,
.set_rate = xgene_clk_set_rate,
.round_rate = xgene_clk_round_rate,
.determine_rate = xgene_clk_determine_rate,
};
static struct clk *xgene_register_clk(struct device *dev,

View File

@ -34,7 +34,7 @@
.num_parents = 0, \
.flags = CLK_GET_RATE_NOCACHE, \
}, \
},
}
#define to_stub_clk(_hw) container_of(_hw, struct hi3660_stub_clk, hw)
@ -67,14 +67,14 @@ static unsigned long hi3660_stub_clk_recalc_rate(struct clk_hw *hw,
return stub_clk->rate;
}
static long hi3660_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int hi3660_stub_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
/*
* LPM3 handles rate rounding so just return whatever
* rate is requested.
*/
return rate;
return 0;
}
static int hi3660_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@ -97,15 +97,15 @@ static int hi3660_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops hi3660_stub_clk_ops = {
.recalc_rate = hi3660_stub_clk_recalc_rate,
.round_rate = hi3660_stub_clk_round_rate,
.determine_rate = hi3660_stub_clk_determine_rate,
.set_rate = hi3660_stub_clk_set_rate,
};
static struct hi3660_stub_clk hi3660_stub_clks[HI3660_CLK_STUB_NUM] = {
DEFINE_CLK_STUB(HI3660_CLK_STUB_CLUSTER0, 0x0001030A, "cpu-cluster.0")
DEFINE_CLK_STUB(HI3660_CLK_STUB_CLUSTER1, 0x0002030A, "cpu-cluster.1")
DEFINE_CLK_STUB(HI3660_CLK_STUB_GPU, 0x0003030A, "clk-g3d")
DEFINE_CLK_STUB(HI3660_CLK_STUB_DDR, 0x00040309, "clk-ddrc")
DEFINE_CLK_STUB(HI3660_CLK_STUB_CLUSTER0, 0x0001030A, "cpu-cluster.0"),
DEFINE_CLK_STUB(HI3660_CLK_STUB_CLUSTER1, 0x0002030A, "cpu-cluster.1"),
DEFINE_CLK_STUB(HI3660_CLK_STUB_GPU, 0x0003030A, "clk-g3d"),
DEFINE_CLK_STUB(HI3660_CLK_STUB_DDR, 0x00040309, "clk-ddrc"),
};
static struct clk_hw *hi3660_stub_clk_hw_get(struct of_phandle_args *clkspec,

View File

@ -161,11 +161,11 @@ static int hi6220_stub_clk_set_rate(struct clk_hw *hw, unsigned long rate,
return ret;
}
static long hi6220_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int hi6220_stub_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct hi6220_stub_clk *stub_clk = to_stub_clk(hw);
unsigned long new_rate = rate / 1000; /* kHz */
unsigned long new_rate = req->rate / 1000; /* kHz */
switch (stub_clk->id) {
case HI6220_STUB_ACPU0:
@ -181,12 +181,14 @@ static long hi6220_stub_clk_round_rate(struct clk_hw *hw, unsigned long rate,
break;
}
return new_rate;
req->rate = new_rate;
return 0;
}
static const struct clk_ops hi6220_stub_clk_ops = {
.recalc_rate = hi6220_stub_clk_recalc_rate,
.round_rate = hi6220_stub_clk_round_rate,
.determine_rate = hi6220_stub_clk_determine_rate,
.set_rate = hi6220_stub_clk_set_rate,
};

View File

@ -55,13 +55,15 @@ static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
CLK_DIVIDER_ROUND_CLOSEST, dclk->width);
}
static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int hi6220_clkdiv_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
return divider_round_rate(hw, rate, prate, dclk->table,
dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, dclk->table,
dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
return 0;
}
static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
@ -93,7 +95,7 @@ static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops hi6220_clkdiv_ops = {
.recalc_rate = hi6220_clkdiv_recalc_rate,
.round_rate = hi6220_clkdiv_round_rate,
.determine_rate = hi6220_clkdiv_determine_rate,
.set_rate = hi6220_clkdiv_set_rate,
};

View File

@ -174,14 +174,16 @@ ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
n * od);
}
static long
ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
unsigned long *prate)
static int ingenic_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL);
req->rate = ingenic_pll_calc(clk_info, req->rate, req->best_parent_rate,
NULL, NULL, NULL);
return 0;
}
static inline int ingenic_pll_check_stable(struct ingenic_cgu *cgu,
@ -317,7 +319,7 @@ static int ingenic_pll_is_enabled(struct clk_hw *hw)
static const struct clk_ops ingenic_pll_ops = {
.recalc_rate = ingenic_pll_recalc_rate,
.round_rate = ingenic_pll_round_rate,
.determine_rate = ingenic_pll_determine_rate,
.set_rate = ingenic_pll_set_rate,
.enable = ingenic_pll_enable,

View File

@ -128,19 +128,19 @@ static unsigned long jz4780_otg_phy_recalc_rate(struct clk_hw *hw,
return parent_rate;
}
static long jz4780_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate,
unsigned long *parent_rate)
static int jz4780_otg_phy_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
if (req_rate < 15600000)
return 12000000;
if (req->rate < 15600000)
req->rate = 12000000;
else if (req->rate < 21600000)
req->rate = 19200000;
else if (req->rate < 36000000)
req->rate = 24000000;
else
req->rate = 48000000;
if (req_rate < 21600000)
return 19200000;
if (req_rate < 36000000)
return 24000000;
return 48000000;
return 0;
}
static int jz4780_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
@ -212,7 +212,7 @@ static int jz4780_otg_phy_is_enabled(struct clk_hw *hw)
static const struct clk_ops jz4780_otg_phy_ops = {
.recalc_rate = jz4780_otg_phy_recalc_rate,
.round_rate = jz4780_otg_phy_round_rate,
.determine_rate = jz4780_otg_phy_determine_rate,
.set_rate = jz4780_otg_phy_set_rate,
.enable = jz4780_otg_phy_enable,

View File

@ -84,16 +84,17 @@ static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,
return parent_rate;
}
static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate,
unsigned long *parent_rate)
static int x1000_otg_phy_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
if (req_rate < 18000000)
return 12000000;
if (req->rate < 18000000)
req->rate = 12000000;
else if (req->rate < 36000000)
req->rate = 24000000;
else
req->rate = 48000000;
if (req_rate < 36000000)
return 24000000;
return 48000000;
return 0;
}
static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
@ -161,7 +162,7 @@ static int x1000_usb_phy_is_enabled(struct clk_hw *hw)
static const struct clk_ops x1000_otg_phy_ops = {
.recalc_rate = x1000_otg_phy_recalc_rate,
.round_rate = x1000_otg_phy_round_rate,
.determine_rate = x1000_otg_phy_determine_rate,
.set_rate = x1000_otg_phy_set_rate,
.enable = x1000_usb_phy_enable,

View File

@ -207,16 +207,19 @@ unsigned long mtk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv);
}
long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
int mtk_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
u32 pcw = 0;
int postdiv;
mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate);
mtk_pll_calc_values(pll, &pcw, &postdiv, req->rate,
req->best_parent_rate);
return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv);
req->rate = __mtk_pll_recalc_rate(pll, req->best_parent_rate, pcw,
postdiv);
return 0;
}
int mtk_pll_prepare(struct clk_hw *hw)
@ -305,7 +308,7 @@ const struct clk_ops mtk_pll_ops = {
.prepare = mtk_pll_prepare,
.unprepare = mtk_pll_unprepare,
.recalc_rate = mtk_pll_recalc_rate,
.round_rate = mtk_pll_round_rate,
.determine_rate = mtk_pll_determine_rate,
.set_rate = mtk_pll_set_rate,
};
@ -314,7 +317,7 @@ const struct clk_ops mtk_pll_fenc_clr_set_ops = {
.prepare = mtk_pll_prepare_setclr,
.unprepare = mtk_pll_unprepare_setclr,
.recalc_rate = mtk_pll_recalc_rate,
.round_rate = mtk_pll_round_rate,
.determine_rate = mtk_pll_determine_rate,
.set_rate = mtk_pll_set_rate,
};
EXPORT_SYMBOL_GPL(mtk_pll_fenc_clr_set_ops);

View File

@ -104,8 +104,7 @@ void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
u32 freq, u32 fin);
int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate);
long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate);
int mtk_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req);
struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll,
const struct mtk_pll_data *data,

View File

@ -42,7 +42,7 @@ static const struct clk_ops mtk_pllfh_ops = {
.prepare = mtk_pll_prepare,
.unprepare = mtk_pll_unprepare,
.recalc_rate = mtk_pll_recalc_rate,
.round_rate = mtk_pll_round_rate,
.determine_rate = mtk_pll_determine_rate,
.set_rate = mtk_fhctl_set_rate,
};

View File

@ -155,11 +155,13 @@ static unsigned long pbclk_recalc_rate(struct clk_hw *hw,
return parent_rate / pbclk_read_pbdiv(pb);
}
static long pbclk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int pbclk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return calc_best_divided_rate(rate, *parent_rate,
PB_DIV_MAX, PB_DIV_MIN);
req->rate = calc_best_divided_rate(req->rate, req->best_parent_rate,
PB_DIV_MAX, PB_DIV_MIN);
return 0;
}
static int pbclk_set_rate(struct clk_hw *hw, unsigned long rate,
@ -207,7 +209,7 @@ const struct clk_ops pic32_pbclk_ops = {
.disable = pbclk_disable,
.is_enabled = pbclk_is_enabled,
.recalc_rate = pbclk_recalc_rate,
.round_rate = pbclk_round_rate,
.determine_rate = pbclk_determine_rate,
.set_rate = pbclk_set_rate,
};
@ -372,18 +374,6 @@ static unsigned long roclk_recalc_rate(struct clk_hw *hw,
return roclk_calc_rate(parent_rate, rodiv, rotrim);
}
static long roclk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
u32 rotrim, rodiv;
/* calculate dividers for new rate */
roclk_calc_div_trim(rate, *parent_rate, &rodiv, &rotrim);
/* caclulate new rate (rounding) based on new rodiv & rotrim */
return roclk_calc_rate(*parent_rate, rodiv, rotrim);
}
static int roclk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
@ -394,6 +384,8 @@ static int roclk_determine_rate(struct clk_hw *hw,
/* find a parent which can generate nearest clkrate >= rate */
for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
u32 rotrim, rodiv;
/* get parent */
parent_clk = clk_hw_get_parent_by_index(hw, i);
if (!parent_clk)
@ -404,7 +396,12 @@ static int roclk_determine_rate(struct clk_hw *hw,
if (req->rate > parent_rate)
continue;
nearest_rate = roclk_round_rate(hw, req->rate, &parent_rate);
/* calculate dividers for new rate */
roclk_calc_div_trim(req->rate, req->best_parent_rate, &rodiv, &rotrim);
/* caclulate new rate (rounding) based on new rodiv & rotrim */
nearest_rate = roclk_calc_rate(req->best_parent_rate, rodiv, rotrim);
delta = abs(nearest_rate - req->rate);
if ((nearest_rate >= req->rate) && (delta < best_delta)) {
best_parent_clk = parent_clk;
@ -665,12 +662,15 @@ static unsigned long spll_clk_recalc_rate(struct clk_hw *hw,
return rate64;
}
static long spll_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int spll_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct pic32_sys_pll *pll = clkhw_to_spll(hw);
return spll_calc_mult_div(pll, rate, *parent_rate, NULL, NULL);
req->rate = spll_calc_mult_div(pll, req->rate, req->best_parent_rate,
NULL, NULL);
return 0;
}
static int spll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@ -725,7 +725,7 @@ static int spll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
/* SPLL clock operation */
const struct clk_ops pic32_spll_ops = {
.recalc_rate = spll_clk_recalc_rate,
.round_rate = spll_clk_round_rate,
.determine_rate = spll_clk_determine_rate,
.set_rate = spll_clk_set_rate,
};
@ -780,10 +780,13 @@ static unsigned long sclk_get_rate(struct clk_hw *hw, unsigned long parent_rate)
return parent_rate / div;
}
static long sclk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int sclk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return calc_best_divided_rate(rate, *parent_rate, SLEW_SYSDIV, 1);
req->rate = calc_best_divided_rate(req->rate, req->best_parent_rate,
SLEW_SYSDIV, 1);
return 0;
}
static int sclk_set_rate(struct clk_hw *hw,
@ -909,7 +912,7 @@ static int sclk_init(struct clk_hw *hw)
const struct clk_ops pic32_sclk_ops = {
.get_parent = sclk_get_parent,
.set_parent = sclk_set_parent,
.round_rate = sclk_round_rate,
.determine_rate = sclk_determine_rate,
.set_rate = sclk_set_rate,
.recalc_rate = sclk_get_rate,
.init = sclk_init,

View File

@ -164,23 +164,23 @@ static unsigned long audio_pll_recalc_rate(struct clk_hw *hw,
return 0;
}
static long audio_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int audio_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned int prediv;
unsigned int postdiv;
long rounded = 0;
for (prediv = 0; prediv < ARRAY_SIZE(predivs); prediv++) {
if (predivs[prediv].parent_rate != *parent_rate)
if (predivs[prediv].parent_rate != req->best_parent_rate)
continue;
for (postdiv = 0; postdiv < ARRAY_SIZE(postdivs); postdiv++) {
long freq = predivs[prediv].freq_vco;
freq /= postdivs[postdiv].divisor;
if (freq == rate)
return rate;
if (freq < rate)
if (freq == req->rate)
return 0;
if (freq < req->rate)
continue;
if (rounded && freq > rounded)
continue;
@ -188,7 +188,9 @@ static long audio_pll_round_rate(struct clk_hw *hw, unsigned long rate,
}
}
return rounded;
req->rate = rounded;
return 0;
}
static int audio_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@ -228,7 +230,7 @@ static int audio_pll_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops audio_pll_ops = {
.recalc_rate = audio_pll_recalc_rate,
.round_rate = audio_pll_round_rate,
.determine_rate = audio_pll_determine_rate,
.set_rate = audio_pll_set_rate,
};

View File

@ -21,8 +21,8 @@
#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;
@ -33,19 +33,20 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
d = &factor->ftbl[i];
prev_rate = rate;
rate = (u64)(*prate) * d->denominator;
rate = (u64)(req->best_parent_rate) * d->denominator;
do_div(rate, d->numerator * factor->masks->factor);
if (rate > drate)
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,
@ -160,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,
};

View File

@ -140,20 +140,22 @@ static unsigned long msc313_cpupll_recalc_rate(struct clk_hw *hw, unsigned long
parent_rate);
}
static long msc313_cpupll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int msc313_cpupll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
u32 reg = msc313_cpupll_regforfrequecy(rate, *parent_rate);
long rounded = msc313_cpupll_frequencyforreg(reg, *parent_rate);
u32 reg = msc313_cpupll_regforfrequecy(req->rate, req->best_parent_rate);
long rounded = msc313_cpupll_frequencyforreg(reg, req->best_parent_rate);
/*
* This is my poor attempt at making sure the resulting
* rate doesn't overshoot the requested rate.
*/
for (; rounded >= rate && reg > 0; reg--)
rounded = msc313_cpupll_frequencyforreg(reg, *parent_rate);
for (; rounded >= req->rate && reg > 0; reg--)
rounded = msc313_cpupll_frequencyforreg(reg, req->best_parent_rate);
return rounded;
req->rate = rounded;
return 0;
}
static int msc313_cpupll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
@ -168,7 +170,7 @@ static int msc313_cpupll_set_rate(struct clk_hw *hw, unsigned long rate, unsigne
static const struct clk_ops msc313_cpupll_ops = {
.recalc_rate = msc313_cpupll_recalc_rate,
.round_rate = msc313_cpupll_round_rate,
.determine_rate = msc313_cpupll_determine_rate,
.set_rate = msc313_cpupll_set_rate,
};

View File

@ -210,19 +210,21 @@ static int ap_cpu_clk_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
static long ap_cpu_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int ap_cpu_clk_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
int divider = *parent_rate / rate;
int divider = req->best_parent_rate / req->rate;
divider = min(divider, APN806_MAX_DIVIDER);
return *parent_rate / divider;
req->rate = req->best_parent_rate / divider;
return 0;
}
static const struct clk_ops ap_cpu_clk_ops = {
.recalc_rate = ap_cpu_clk_recalc_rate,
.round_rate = ap_cpu_clk_round_rate,
.determine_rate = ap_cpu_clk_determine_rate,
.set_rate = ap_cpu_clk_set_rate,
};

View File

@ -454,12 +454,12 @@ static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
return DIV_ROUND_UP_ULL((u64)parent_rate, div);
}
static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int clk_pm_cpu_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
struct regmap *base = pm_cpu->nb_pm_base;
unsigned int div = *parent_rate / rate;
unsigned int div = req->best_parent_rate / req->rate;
unsigned int load_level;
/* only available when DVFS is enabled */
if (!armada_3700_pm_dvfs_is_enabled(base))
@ -474,13 +474,16 @@ static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
val >>= offset;
val &= ARMADA_37XX_NB_TBG_DIV_MASK;
if (val == div)
if (val == div) {
/*
* We found a load level matching the target
* divider, switch to this load level and
* return.
*/
return *parent_rate / div;
req->rate = req->best_parent_rate / div;
return 0;
}
}
/* We didn't find any valid divider */
@ -600,7 +603,7 @@ static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops clk_pm_cpu_ops = {
.get_parent = clk_pm_cpu_get_parent,
.round_rate = clk_pm_cpu_round_rate,
.determine_rate = clk_pm_cpu_determine_rate,
.set_rate = clk_pm_cpu_set_rate,
.recalc_rate = clk_pm_cpu_recalc_rate,
};

View File

@ -135,19 +135,21 @@ 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,
unsigned long *parent_rate)
static int clk_corediv_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
/* Valid ratio are 1:4, 1:5, 1:6 and 1:8 */
u32 div;
div = *parent_rate / rate;
div = req->best_parent_rate / req->rate;
if (div < 4)
div = 4;
else if (div > 6)
div = 8;
return *parent_rate / div;
req->rate = req->best_parent_rate / div;
return 0;
}
static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate,
@ -199,7 +201,7 @@ static const struct clk_corediv_soc_desc armada370_corediv_soc = {
.disable = clk_corediv_disable,
.is_enabled = clk_corediv_is_enabled,
.recalc_rate = clk_corediv_recalc_rate,
.round_rate = clk_corediv_round_rate,
.determine_rate = clk_corediv_determine_rate,
.set_rate = clk_corediv_set_rate,
},
.ratio_reload = BIT(8),
@ -215,7 +217,7 @@ static const struct clk_corediv_soc_desc armada380_corediv_soc = {
.disable = clk_corediv_disable,
.is_enabled = clk_corediv_is_enabled,
.recalc_rate = clk_corediv_recalc_rate,
.round_rate = clk_corediv_round_rate,
.determine_rate = clk_corediv_determine_rate,
.set_rate = clk_corediv_set_rate,
},
.ratio_reload = BIT(8),
@ -228,7 +230,7 @@ static const struct clk_corediv_soc_desc armada375_corediv_soc = {
.ndescs = ARRAY_SIZE(mvebu_corediv_desc),
.ops = {
.recalc_rate = clk_corediv_recalc_rate,
.round_rate = clk_corediv_round_rate,
.determine_rate = clk_corediv_determine_rate,
.set_rate = clk_corediv_set_rate,
},
.ratio_reload = BIT(8),
@ -240,7 +242,7 @@ static const struct clk_corediv_soc_desc mv98dx3236_corediv_soc = {
.ndescs = ARRAY_SIZE(mv98dx3236_corediv_desc),
.ops = {
.recalc_rate = clk_corediv_recalc_rate,
.round_rate = clk_corediv_round_rate,
.determine_rate = clk_corediv_determine_rate,
.set_rate = clk_corediv_set_rate,
},
.ratio_reload = BIT(10),

View File

@ -56,19 +56,21 @@ 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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
/* Valid ratio are 1:1, 1:2 and 1:3 */
u32 div;
div = *parent_rate / rate;
div = req->best_parent_rate / req->rate;
if (div == 0)
div = 1;
else if (div > 3)
div = 3;
return *parent_rate / div;
req->rate = req->best_parent_rate / div;
return 0;
}
static int clk_cpu_off_set_rate(struct clk_hw *hwclk, unsigned long rate,
@ -159,7 +161,7 @@ static int clk_cpu_set_rate(struct clk_hw *hwclk, unsigned long rate,
static const struct clk_ops cpu_ops = {
.recalc_rate = clk_cpu_recalc_rate,
.round_rate = clk_cpu_round_rate,
.determine_rate = clk_cpu_determine_rate,
.set_rate = clk_cpu_set_rate,
};

View File

@ -108,23 +108,23 @@ static unsigned long dove_recalc_rate(struct clk_hw *hw, unsigned long parent)
return rate;
}
static long dove_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent)
static int dove_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct dove_clk *dc = to_dove_clk(hw);
unsigned long parent_rate = *parent;
unsigned long parent_rate = req->best_parent_rate;
int divider;
divider = dove_calc_divider(dc, rate, parent_rate, false);
divider = dove_calc_divider(dc, req->rate, parent_rate, false);
if (divider < 0)
return divider;
rate = DIV_ROUND_CLOSEST(parent_rate, divider);
req->rate = DIV_ROUND_CLOSEST(parent_rate, divider);
pr_debug("%s(): %s divider=%u parent=%lu rate=%lu\n",
__func__, dc->name, divider, parent_rate, rate);
__func__, dc->name, divider, parent_rate, req->rate);
return rate;
return 0;
}
static int dove_set_clock(struct clk_hw *hw, unsigned long rate,
@ -154,7 +154,7 @@ static int dove_set_clock(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops dove_divider_ops = {
.set_rate = dove_set_clock,
.round_rate = dove_round_rate,
.determine_rate = dove_determine_rate,
.recalc_rate = dove_recalc_rate,
};

View File

@ -40,12 +40,12 @@ 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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_div *div = to_clk_div(hw);
return div->ops->round_rate(&div->divider.hw, rate, prate);
return div->ops->determine_rate(&div->divider.hw, req);
}
static int clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
@ -63,7 +63,7 @@ static int clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops clk_div_ops = {
.recalc_rate = clk_div_recalc_rate,
.round_rate = clk_div_round_rate,
.determine_rate = clk_div_determine_rate,
.set_rate = clk_div_set_rate,
};

View File

@ -44,18 +44,18 @@ static unsigned long clk_frac_recalc_rate(struct clk_hw *hw,
return tmp_rate >> frac->width;
}
static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int clk_frac_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_frac *frac = to_clk_frac(hw);
unsigned long parent_rate = *prate;
unsigned long parent_rate = req->best_parent_rate;
u32 div;
u64 tmp, tmp_rate, result;
if (rate > parent_rate)
if (req->rate > parent_rate)
return -EINVAL;
tmp = rate;
tmp = req->rate;
tmp <<= frac->width;
do_div(tmp, parent_rate);
div = tmp;
@ -67,7 +67,9 @@ static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
result = tmp_rate >> frac->width;
if ((result << frac->width) < tmp_rate)
result += 1;
return result;
req->rate = result;
return 0;
}
static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate,
@ -103,7 +105,7 @@ static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops clk_frac_ops = {
.recalc_rate = clk_frac_recalc_rate,
.round_rate = clk_frac_round_rate,
.determine_rate = clk_frac_determine_rate,
.set_rate = clk_frac_set_rate,
};

View File

@ -57,22 +57,24 @@ 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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned long parent_rate = *prate;
unsigned long parent_rate = req->best_parent_rate;
u64 tmp = parent_rate;
u8 frac;
tmp = tmp * 18 + rate / 2;
do_div(tmp, rate);
tmp = tmp * 18 + req->rate / 2;
do_div(tmp, req->rate);
frac = clamp(tmp, 18, 35);
tmp = parent_rate;
tmp *= 18;
do_div(tmp, frac);
return tmp;
req->rate = tmp;
return 0;
}
static int clk_ref_set_rate(struct clk_hw *hw, unsigned long rate,
@ -104,7 +106,7 @@ static const struct clk_ops clk_ref_ops = {
.enable = clk_ref_enable,
.disable = clk_ref_disable,
.recalc_rate = clk_ref_recalc_rate,
.round_rate = clk_ref_round_rate,
.determine_rate = clk_ref_determine_rate,
.set_rate = clk_ref_set_rate,
};

View File

@ -39,12 +39,16 @@ static unsigned long ma35d1_clkdiv_recalc_rate(struct clk_hw *hw, unsigned long
CLK_DIVIDER_ROUND_CLOSEST, dclk->width);
}
static long ma35d1_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate)
static int ma35d1_clkdiv_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct ma35d1_adc_clk_div *dclk = to_ma35d1_adc_clk_div(hw);
return divider_round_rate(hw, rate, prate, dclk->table,
dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
dclk->table, dclk->width,
CLK_DIVIDER_ROUND_CLOSEST);
return 0;
}
static int ma35d1_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
@ -71,7 +75,7 @@ static int ma35d1_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate, unsigne
static const struct clk_ops ma35d1_adc_clkdiv_ops = {
.recalc_rate = ma35d1_clkdiv_recalc_rate,
.round_rate = ma35d1_clkdiv_round_rate,
.determine_rate = ma35d1_clkdiv_determine_rate,
.set_rate = ma35d1_clkdiv_set_rate,
};

View File

@ -244,35 +244,43 @@ static unsigned long ma35d1_clk_pll_recalc_rate(struct clk_hw *hw, unsigned long
return 0;
}
static long ma35d1_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int ma35d1_clk_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw);
u32 reg_ctl[3] = { 0 };
unsigned long pll_freq;
long ret;
if (*parent_rate < PLL_FREF_MIN_FREQ || *parent_rate > PLL_FREF_MAX_FREQ)
if (req->best_parent_rate < PLL_FREF_MIN_FREQ || req->best_parent_rate > PLL_FREF_MAX_FREQ)
return -EINVAL;
ret = ma35d1_pll_find_closest(pll, rate, *parent_rate, reg_ctl, &pll_freq);
ret = ma35d1_pll_find_closest(pll, req->rate, req->best_parent_rate,
reg_ctl, &pll_freq);
if (ret < 0)
return ret;
switch (pll->id) {
case CAPLL:
reg_ctl[0] = readl_relaxed(pll->ctl0_base);
pll_freq = ma35d1_calc_smic_pll_freq(reg_ctl[0], *parent_rate);
return pll_freq;
pll_freq = ma35d1_calc_smic_pll_freq(reg_ctl[0], req->best_parent_rate);
req->rate = pll_freq;
return 0;
case DDRPLL:
case APLL:
case EPLL:
case VPLL:
reg_ctl[0] = readl_relaxed(pll->ctl0_base);
reg_ctl[1] = readl_relaxed(pll->ctl1_base);
pll_freq = ma35d1_calc_pll_freq(pll->mode, reg_ctl, *parent_rate);
return pll_freq;
pll_freq = ma35d1_calc_pll_freq(pll->mode, reg_ctl, req->best_parent_rate);
req->rate = pll_freq;
return 0;
}
req->rate = 0;
return 0;
}
@ -311,12 +319,12 @@ static const struct clk_ops ma35d1_clk_pll_ops = {
.unprepare = ma35d1_clk_pll_unprepare,
.set_rate = ma35d1_clk_pll_set_rate,
.recalc_rate = ma35d1_clk_pll_recalc_rate,
.round_rate = ma35d1_clk_pll_round_rate,
.determine_rate = ma35d1_clk_pll_determine_rate,
};
static const struct clk_ops ma35d1_clk_fixed_pll_ops = {
.recalc_rate = ma35d1_clk_pll_recalc_rate,
.round_rate = ma35d1_clk_pll_round_rate,
.determine_rate = ma35d1_clk_pll_determine_rate,
};
struct clk_hw *ma35d1_reg_clk_pll(struct device *dev, u32 id, u8 u8mode, const char *name,

View File

@ -370,23 +370,25 @@ static unsigned long lpc18xx_pll0_recalc_rate(struct clk_hw *hw,
return 0;
}
static long lpc18xx_pll0_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int lpc18xx_pll0_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned long m;
if (*prate < rate) {
if (req->best_parent_rate < req->rate) {
pr_warn("%s: pll dividers not supported\n", __func__);
return -EINVAL;
}
m = DIV_ROUND_UP_ULL(*prate, rate * 2);
if (m <= 0 && m > LPC18XX_PLL0_MSEL_MAX) {
pr_warn("%s: unable to support rate %lu\n", __func__, rate);
m = DIV_ROUND_UP_ULL(req->best_parent_rate, req->rate * 2);
if (m == 0 || m > LPC18XX_PLL0_MSEL_MAX) {
pr_warn("%s: unable to support rate %lu\n", __func__, req->rate);
return -EINVAL;
}
return 2 * *prate * m;
req->rate = 2 * req->best_parent_rate * m;
return 0;
}
static int lpc18xx_pll0_set_rate(struct clk_hw *hw, unsigned long rate,
@ -402,7 +404,7 @@ static int lpc18xx_pll0_set_rate(struct clk_hw *hw, unsigned long rate,
}
m = DIV_ROUND_UP_ULL(parent_rate, rate * 2);
if (m <= 0 && m > LPC18XX_PLL0_MSEL_MAX) {
if (m == 0 || m > LPC18XX_PLL0_MSEL_MAX) {
pr_warn("%s: unable to support rate %lu\n", __func__, rate);
return -EINVAL;
}
@ -443,7 +445,7 @@ static int lpc18xx_pll0_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops lpc18xx_pll0_ops = {
.recalc_rate = lpc18xx_pll0_recalc_rate,
.round_rate = lpc18xx_pll0_round_rate,
.determine_rate = lpc18xx_pll0_determine_rate,
.set_rate = lpc18xx_pll0_set_rate,
};

View File

@ -578,17 +578,17 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
return regmap_update_bits(clk_regmap, clk->reg, 0x1FFFF, val);
}
static long clk_hclk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int clk_hclk_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw);
u64 m_i, o = rate, i = *parent_rate, d = (u64)rate << 6;
u64 m_i, o = req->rate, i = req->best_parent_rate, d = (u64)req->rate << 6;
u64 m = 0, n = 0, p = 0;
int p_i, n_i;
pr_debug("%s: %lu/%lu\n", clk_hw_get_name(hw), *parent_rate, rate);
pr_debug("%s: %lu/%lu\n", clk_hw_get_name(hw), req->best_parent_rate, req->rate);
if (rate > 266500000)
if (req->rate > 266500000)
return -EINVAL;
/* Have to check all 20 possibilities to find the minimal M */
@ -613,9 +613,9 @@ static long clk_hclk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
}
}
if (d == (u64)rate << 6) {
if (d == (u64)req->rate << 6) {
pr_err("%s: %lu: no valid PLL parameters are found\n",
clk_hw_get_name(hw), rate);
clk_hw_get_name(hw), req->rate);
return -EINVAL;
}
@ -633,22 +633,25 @@ static long clk_hclk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
if (!d)
pr_debug("%s: %lu: found exact match: %llu/%llu/%llu\n",
clk_hw_get_name(hw), rate, m, n, p);
clk_hw_get_name(hw), req->rate, m, n, p);
else
pr_debug("%s: %lu: found closest: %llu/%llu/%llu - %llu\n",
clk_hw_get_name(hw), rate, m, n, p, o);
clk_hw_get_name(hw), req->rate, m, n, p, o);
return o;
req->rate = o;
return 0;
}
static long clk_usb_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int clk_usb_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct lpc32xx_pll_clk *clk = to_lpc32xx_pll_clk(hw);
struct clk_hw *usb_div_hw, *osc_hw;
u64 d_i, n_i, m, o;
pr_debug("%s: %lu/%lu\n", clk_hw_get_name(hw), *parent_rate, rate);
pr_debug("%s: %lu/%lu\n", clk_hw_get_name(hw), req->best_parent_rate,
req->rate);
/*
* The only supported USB clock is 48MHz, with PLL internal constraints
@ -656,7 +659,7 @@ static long clk_usb_pll_round_rate(struct clk_hw *hw, unsigned long rate,
* and post-divider must be 4, this slightly simplifies calculation of
* USB divider, USB PLL N and M parameters.
*/
if (rate != 48000000)
if (req->rate != 48000000)
return -EINVAL;
/* USB divider clock */
@ -684,30 +687,30 @@ static long clk_usb_pll_round_rate(struct clk_hw *hw, unsigned long rate,
clk->m_div = m;
clk->p_div = 2;
clk->mode = PLL_NON_INTEGER;
*parent_rate = div64_u64(o, d_i);
req->best_parent_rate = div64_u64(o, d_i);
return rate;
return 0;
}
}
return -EINVAL;
}
#define LPC32XX_DEFINE_PLL_OPS(_name, _rc, _sr, _rr) \
#define LPC32XX_DEFINE_PLL_OPS(_name, _rc, _sr, _dr) \
static const struct clk_ops clk_ ##_name ## _ops = { \
.enable = clk_pll_enable, \
.disable = clk_pll_disable, \
.is_enabled = clk_pll_is_enabled, \
.recalc_rate = _rc, \
.set_rate = _sr, \
.round_rate = _rr, \
.determine_rate = _dr, \
}
LPC32XX_DEFINE_PLL_OPS(pll_397x, clk_pll_397x_recalc_rate, NULL, NULL);
LPC32XX_DEFINE_PLL_OPS(hclk_pll, clk_pll_recalc_rate,
clk_pll_set_rate, clk_hclk_pll_round_rate);
clk_pll_set_rate, clk_hclk_pll_determine_rate);
LPC32XX_DEFINE_PLL_OPS(usb_pll, clk_pll_recalc_rate,
clk_pll_set_rate, clk_usb_pll_round_rate);
clk_pll_set_rate, clk_usb_pll_determine_rate);
static int clk_ddram_is_enabled(struct clk_hw *hw)
{
@ -954,8 +957,8 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
divider->flags, divider->width);
}
static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int clk_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct lpc32xx_clk_div *divider = to_lpc32xx_div(hw);
unsigned int bestdiv;
@ -967,11 +970,15 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
bestdiv &= div_mask(divider->width);
bestdiv = _get_div(divider->table, bestdiv, divider->flags,
divider->width);
return DIV_ROUND_UP(*prate, bestdiv);
req->rate = DIV_ROUND_UP(req->best_parent_rate, bestdiv);
return 0;
}
return divider_round_rate(hw, rate, prate, divider->table,
divider->width, divider->flags);
req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
divider->table, divider->width, divider->flags);
return 0;
}
static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
@ -990,7 +997,7 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops lpc32xx_clk_divider_ops = {
.recalc_rate = clk_divider_recalc_rate,
.round_rate = clk_divider_round_rate,
.determine_rate = clk_divider_determine_rate,
.set_rate = clk_divider_set_rate,
};

View File

@ -139,19 +139,23 @@ pll_get_params(struct pistachio_clk_pll *pll, unsigned long fref,
return NULL;
}
static long pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
unsigned int i;
for (i = 0; i < pll->nr_rates; i++) {
if (i > 0 && pll->rates[i].fref == *parent_rate &&
pll->rates[i].fout <= rate)
return pll->rates[i - 1].fout;
if (i > 0 && pll->rates[i].fref == req->best_parent_rate &&
pll->rates[i].fout <= req->rate) {
req->rate = pll->rates[i - 1].fout;
return 0;
}
}
return pll->rates[0].fout;
req->rate = pll->rates[0].fout;
return 0;
}
static int pll_gf40lp_frac_enable(struct clk_hw *hw)
@ -300,7 +304,7 @@ static const struct clk_ops pll_gf40lp_frac_ops = {
.disable = pll_gf40lp_frac_disable,
.is_enabled = pll_gf40lp_frac_is_enabled,
.recalc_rate = pll_gf40lp_frac_recalc_rate,
.round_rate = pll_round_rate,
.determine_rate = pll_determine_rate,
.set_rate = pll_gf40lp_frac_set_rate,
};
@ -432,7 +436,7 @@ static const struct clk_ops pll_gf40lp_laint_ops = {
.disable = pll_gf40lp_laint_disable,
.is_enabled = pll_gf40lp_laint_is_enabled,
.recalc_rate = pll_gf40lp_laint_recalc_rate,
.round_rate = pll_round_rate,
.determine_rate = pll_determine_rate,
.set_rate = pll_gf40lp_laint_set_rate,
};

View File

@ -15,8 +15,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_ro_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int div_ro_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_regmap_div *divider = to_clk_regmap_div(hw);
struct clk_regmap *clkr = &divider->clkr;
@ -26,17 +26,24 @@ static long div_round_ro_rate(struct clk_hw *hw, unsigned long rate,
val >>= divider->shift;
val &= BIT(divider->width) - 1;
return divider_ro_round_rate(hw, rate, prate, NULL, divider->width,
CLK_DIVIDER_ROUND_CLOSEST, val);
req->rate = divider_ro_round_rate(hw, req->rate,
&req->best_parent_rate, NULL,
divider->width,
CLK_DIVIDER_ROUND_CLOSEST, val);
return 0;
}
static long div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int div_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
struct clk_regmap_div *divider = to_clk_regmap_div(hw);
return divider_round_rate(hw, rate, prate, NULL, divider->width,
CLK_DIVIDER_ROUND_CLOSEST);
req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate,
NULL,
divider->width,
CLK_DIVIDER_ROUND_CLOSEST);
return 0;
}
static int div_set_rate(struct clk_hw *hw, unsigned long rate,
@ -70,14 +77,14 @@ static unsigned long div_recalc_rate(struct clk_hw *hw,
}
const struct clk_ops clk_regmap_div_ops = {
.round_rate = div_round_rate,
.determine_rate = div_determine_rate,
.set_rate = div_set_rate,
.recalc_rate = div_recalc_rate,
};
EXPORT_SYMBOL_GPL(clk_regmap_div_ops);
const struct clk_ops clk_regmap_div_ro_ops = {
.round_rate = div_round_ro_rate,
.determine_rate = div_ro_determine_rate,
.recalc_rate = div_recalc_rate,
};
EXPORT_SYMBOL_GPL(clk_regmap_div_ro_ops);

View File

@ -55,17 +55,18 @@ rockchip_ddrclk_sip_recalc_rate(struct clk_hw *hw,
return res.a0;
}
static long rockchip_ddrclk_sip_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *prate)
static int rockchip_ddrclk_sip_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct arm_smccc_res res;
arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, rate, 0,
arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, req->rate, 0,
ROCKCHIP_SIP_CONFIG_DRAM_ROUND_RATE,
0, 0, 0, 0, &res);
return res.a0;
req->rate = res.a0;
return 0;
}
static u8 rockchip_ddrclk_get_parent(struct clk_hw *hw)
@ -83,7 +84,7 @@ static u8 rockchip_ddrclk_get_parent(struct clk_hw *hw)
static const struct clk_ops rockchip_ddrclk_sip_ops = {
.recalc_rate = rockchip_ddrclk_sip_recalc_rate,
.set_rate = rockchip_ddrclk_sip_set_rate,
.round_rate = rockchip_ddrclk_sip_round_rate,
.determine_rate = rockchip_ddrclk_sip_determine_rate,
.get_parent = rockchip_ddrclk_get_parent,
};

View File

@ -92,17 +92,19 @@ static int clk_half_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
return bestdiv;
}
static long clk_half_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int clk_half_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_divider *divider = to_clk_divider(hw);
int div;
div = clk_half_divider_bestdiv(hw, rate, prate,
div = clk_half_divider_bestdiv(hw, req->rate, &req->best_parent_rate,
divider->width,
divider->flags);
return DIV_ROUND_UP_ULL(((u64)*prate * 2), div * 2 + 3);
req->rate = DIV_ROUND_UP_ULL(((u64)req->best_parent_rate * 2), div * 2 + 3);
return 0;
}
static int clk_half_divider_set_rate(struct clk_hw *hw, unsigned long rate,
@ -141,7 +143,7 @@ static int clk_half_divider_set_rate(struct clk_hw *hw, unsigned long rate,
static const struct clk_ops clk_half_divider_ops = {
.recalc_rate = clk_half_divider_recalc_rate,
.round_rate = clk_half_divider_round_rate,
.determine_rate = clk_half_divider_determine_rate,
.set_rate = clk_half_divider_set_rate,
};

View File

@ -61,8 +61,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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
const struct rockchip_pll_rate_table *rate_table = pll->rate_table;
@ -70,12 +70,17 @@ static long rockchip_pll_round_rate(struct clk_hw *hw,
/* Assuming 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 (req->rate >= rate_table[i].rate) {
req->rate = rate_table[i].rate;
return 0;
}
}
/* return minimum supported value */
return rate_table[i - 1].rate;
req->rate = rate_table[i - 1].rate;
return 0;
}
/*
@ -352,7 +357,7 @@ static const struct clk_ops rockchip_rk3036_pll_clk_norate_ops = {
static const struct clk_ops rockchip_rk3036_pll_clk_ops = {
.recalc_rate = rockchip_rk3036_pll_recalc_rate,
.round_rate = rockchip_pll_round_rate,
.determine_rate = rockchip_pll_determine_rate,
.set_rate = rockchip_rk3036_pll_set_rate,
.enable = rockchip_rk3036_pll_enable,
.disable = rockchip_rk3036_pll_disable,
@ -571,7 +576,7 @@ static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = {
static const struct clk_ops rockchip_rk3066_pll_clk_ops = {
.recalc_rate = rockchip_rk3066_pll_recalc_rate,
.round_rate = rockchip_pll_round_rate,
.determine_rate = rockchip_pll_determine_rate,
.set_rate = rockchip_rk3066_pll_set_rate,
.enable = rockchip_rk3066_pll_enable,
.disable = rockchip_rk3066_pll_disable,
@ -836,7 +841,7 @@ static const struct clk_ops rockchip_rk3399_pll_clk_norate_ops = {
static const struct clk_ops rockchip_rk3399_pll_clk_ops = {
.recalc_rate = rockchip_rk3399_pll_recalc_rate,
.round_rate = rockchip_pll_round_rate,
.determine_rate = rockchip_pll_determine_rate,
.set_rate = rockchip_rk3399_pll_set_rate,
.enable = rockchip_rk3399_pll_enable,
.disable = rockchip_rk3399_pll_disable,
@ -1036,7 +1041,7 @@ static const struct clk_ops rockchip_rk3588_pll_clk_norate_ops = {
static const struct clk_ops rockchip_rk3588_pll_clk_ops = {
.recalc_rate = rockchip_rk3588_pll_recalc_rate,
.round_rate = rockchip_pll_round_rate,
.determine_rate = rockchip_pll_determine_rate,
.set_rate = rockchip_rk3588_pll_set_rate,
.enable = rockchip_rk3588_pll_enable,
.disable = rockchip_rk3588_pll_disable,

View File

@ -49,7 +49,7 @@ static struct __prci_wrpll_data sifive_fu540_prci_gemgxlpll_data = {
static const struct clk_ops sifive_fu540_prci_wrpll_clk_ops = {
.set_rate = sifive_prci_wrpll_set_rate,
.round_rate = sifive_prci_wrpll_round_rate,
.determine_rate = sifive_prci_wrpll_determine_rate,
.recalc_rate = sifive_prci_wrpll_recalc_rate,
.enable = sifive_prci_clock_enable,
.disable = sifive_prci_clock_disable,

View File

@ -55,7 +55,7 @@ static struct __prci_wrpll_data sifive_fu740_prci_cltxpll_data = {
static const struct clk_ops sifive_fu740_prci_wrpll_clk_ops = {
.set_rate = sifive_prci_wrpll_set_rate,
.round_rate = sifive_prci_wrpll_round_rate,
.determine_rate = sifive_prci_wrpll_determine_rate,
.recalc_rate = sifive_prci_wrpll_recalc_rate,
.enable = sifive_prci_clock_enable,
.disable = sifive_prci_clock_disable,

View File

@ -183,9 +183,8 @@ unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw,
return wrpll_calc_output_rate(&pwd->c, parent_rate);
}
long sifive_prci_wrpll_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *parent_rate)
int sifive_prci_wrpll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
struct __prci_wrpll_data *pwd = pc->pwd;
@ -193,9 +192,11 @@ long sifive_prci_wrpll_round_rate(struct clk_hw *hw,
memcpy(&c, &pwd->c, sizeof(c));
wrpll_configure_for_rate(&c, rate, *parent_rate);
wrpll_configure_for_rate(&c, req->rate, req->best_parent_rate);
return wrpll_calc_output_rate(&c, *parent_rate);
req->rate = wrpll_calc_output_rate(&c, req->best_parent_rate);
return 0;
}
int sifive_prci_wrpll_set_rate(struct clk_hw *hw,

View File

@ -291,8 +291,8 @@ void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd);
void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd);
/* Linux clock framework integration */
long sifive_prci_wrpll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate);
int sifive_prci_wrpll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req);
int sifive_prci_wrpll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate);
int sifive_clk_is_enabled(struct clk_hw *hw);

View File

@ -45,10 +45,12 @@ static unsigned long gate_recalc_rate(struct clk_hw *hw,
return parent_rate;
}
static long gate_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int gate_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return *parent_rate;
req->rate = req->best_parent_rate;
return 0;
}
static int gate_set_rate(struct clk_hw *hw, unsigned long rate,
@ -63,7 +65,7 @@ const struct clk_ops cv1800_clk_gate_ops = {
.is_enabled = gate_is_enabled,
.recalc_rate = gate_recalc_rate,
.round_rate = gate_round_rate,
.determine_rate = gate_determine_rate,
.set_rate = gate_set_rate,
};

View File

@ -176,9 +176,8 @@ static unsigned long sg2042_clk_divider_recalc_rate(struct clk_hw *hw,
return ret_rate;
}
static long sg2042_clk_divider_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *prate)
static int sg2042_clk_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
unsigned long ret_rate;
@ -192,15 +191,17 @@ static long sg2042_clk_divider_round_rate(struct clk_hw *hw,
bestdiv = readl(divider->reg) >> divider->shift;
bestdiv &= clk_div_mask(divider->width);
}
ret_rate = DIV_ROUND_UP_ULL((u64)*prate, bestdiv);
ret_rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, bestdiv);
} else {
ret_rate = divider_round_rate(hw, rate, prate, NULL,
ret_rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, NULL,
divider->width, divider->div_flags);
}
pr_debug("--> %s: divider_round_rate: val = %ld\n",
clk_hw_get_name(hw), ret_rate);
return ret_rate;
req->rate = ret_rate;
return 0;
}
static int sg2042_clk_divider_set_rate(struct clk_hw *hw,
@ -258,13 +259,13 @@ static int sg2042_clk_divider_set_rate(struct clk_hw *hw,
static const struct clk_ops sg2042_clk_divider_ops = {
.recalc_rate = sg2042_clk_divider_recalc_rate,
.round_rate = sg2042_clk_divider_round_rate,
.determine_rate = sg2042_clk_divider_determine_rate,
.set_rate = sg2042_clk_divider_set_rate,
};
static const struct clk_ops sg2042_clk_divider_ro_ops = {
.recalc_rate = sg2042_clk_divider_recalc_rate,
.round_rate = sg2042_clk_divider_round_rate,
.determine_rate = sg2042_clk_divider_determine_rate,
};
/*

View File

@ -346,37 +346,30 @@ static unsigned long sg2042_clk_pll_recalc_rate(struct clk_hw *hw,
return rate;
}
static long sg2042_clk_pll_round_rate(struct clk_hw *hw,
unsigned long req_rate,
unsigned long *prate)
static int sg2042_clk_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct sg2042_pll_ctrl pctrl_table;
unsigned int value;
long proper_rate;
int ret;
ret = sg2042_get_pll_ctl_setting(&pctrl_table, req_rate, *prate);
ret = sg2042_get_pll_ctl_setting(&pctrl_table,
min(req->rate, req->max_rate),
req->best_parent_rate);
if (ret) {
proper_rate = 0;
goto out;
}
value = sg2042_pll_ctrl_encode(&pctrl_table);
proper_rate = (long)sg2042_pll_recalc_rate(value, *prate);
proper_rate = (long)sg2042_pll_recalc_rate(value, req->best_parent_rate);
out:
pr_debug("--> %s: pll_round_rate: val = %ld\n",
clk_hw_get_name(hw), proper_rate);
return proper_rate;
}
static int sg2042_clk_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
req->rate = sg2042_clk_pll_round_rate(hw, min(req->rate, req->max_rate),
&req->best_parent_rate);
pr_debug("--> %s: pll_determine_rate: val = %ld\n",
clk_hw_get_name(hw), req->rate);
clk_hw_get_name(hw), proper_rate);
req->rate = proper_rate;
return 0;
}
@ -417,14 +410,13 @@ static int sg2042_clk_pll_set_rate(struct clk_hw *hw,
static const struct clk_ops sg2042_clk_pll_ops = {
.recalc_rate = sg2042_clk_pll_recalc_rate,
.round_rate = sg2042_clk_pll_round_rate,
.determine_rate = sg2042_clk_pll_determine_rate,
.set_rate = sg2042_clk_pll_set_rate,
};
static const struct clk_ops sg2042_clk_pll_ro_ops = {
.recalc_rate = sg2042_clk_pll_recalc_rate,
.round_rate = sg2042_clk_pll_round_rate,
.determine_rate = sg2042_clk_pll_determine_rate,
};
/*

View File

@ -49,14 +49,16 @@ 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,
unsigned long *prate)
static int clk_aux_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_aux *aux = to_clk_aux(hw);
int unused;
return clk_round_rate_index(hw, drate, *prate, aux_calc_rate,
aux->rtbl_cnt, &unused);
req->rate = clk_round_rate_index(hw, req->rate, req->best_parent_rate,
aux_calc_rate, aux->rtbl_cnt, &unused);
return 0;
}
static unsigned long clk_aux_recalc_rate(struct clk_hw *hw,
@ -127,7 +129,7 @@ static int clk_aux_set_rate(struct clk_hw *hw, unsigned long drate,
static const struct clk_ops clk_aux_ops = {
.recalc_rate = clk_aux_recalc_rate,
.round_rate = clk_aux_round_rate,
.determine_rate = clk_aux_determine_rate,
.set_rate = clk_aux_set_rate,
};

View File

@ -52,14 +52,16 @@ 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,
unsigned long *prate)
static int clk_frac_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_frac *frac = to_clk_frac(hw);
int unused;
return clk_round_rate_index(hw, drate, *prate, frac_calc_rate,
frac->rtbl_cnt, &unused);
req->rate = clk_round_rate_index(hw, req->rate, req->best_parent_rate,
frac_calc_rate, frac->rtbl_cnt, &unused);
return 0;
}
static unsigned long clk_frac_recalc_rate(struct clk_hw *hw,
@ -115,7 +117,7 @@ static int clk_frac_set_rate(struct clk_hw *hw, unsigned long drate,
static const struct clk_ops clk_frac_ops = {
.recalc_rate = clk_frac_recalc_rate,
.round_rate = clk_frac_round_rate,
.determine_rate = clk_frac_determine_rate,
.set_rate = clk_frac_set_rate,
};

View File

@ -39,14 +39,16 @@ 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,
unsigned long *prate)
static int clk_gpt_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_gpt *gpt = to_clk_gpt(hw);
int unused;
return clk_round_rate_index(hw, drate, *prate, gpt_calc_rate,
gpt->rtbl_cnt, &unused);
req->rate = clk_round_rate_index(hw, req->rate, req->best_parent_rate,
gpt_calc_rate, gpt->rtbl_cnt, &unused);
return 0;
}
static unsigned long clk_gpt_recalc_rate(struct clk_hw *hw,
@ -104,7 +106,7 @@ static int clk_gpt_set_rate(struct clk_hw *hw, unsigned long drate,
static const struct clk_ops clk_gpt_ops = {
.recalc_rate = clk_gpt_recalc_rate,
.round_rate = clk_gpt_round_rate,
.determine_rate = clk_gpt_determine_rate,
.set_rate = clk_gpt_set_rate,
};

View File

@ -110,12 +110,15 @@ 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,
unsigned long *prate)
static int clk_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
int unused;
return clk_pll_round_rate_index(hw, drate, prate, &unused);
req->rate = clk_pll_round_rate_index(hw, req->rate,
&req->best_parent_rate, &unused);
return 0;
}
static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long
@ -164,7 +167,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate,
static const struct clk_ops clk_pll_ops = {
.recalc_rate = clk_pll_recalc_rate,
.round_rate = clk_pll_round_rate,
.determine_rate = clk_pll_determine_rate,
.set_rate = clk_pll_set_rate,
};
@ -176,14 +179,16 @@ 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,
unsigned long *prate)
static int clk_vco_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_vco *vco = to_clk_vco(hw);
int unused;
return clk_round_rate_index(hw, drate, *prate, vco_calc_rate,
vco->rtbl_cnt, &unused);
req->rate = clk_round_rate_index(hw, req->rate, req->best_parent_rate,
vco_calc_rate, vco->rtbl_cnt, &unused);
return 0;
}
static unsigned long clk_vco_recalc_rate(struct clk_hw *hw,
@ -265,7 +270,7 @@ static int clk_vco_set_rate(struct clk_hw *hw, unsigned long drate,
static const struct clk_ops clk_vco_ops = {
.recalc_rate = clk_vco_recalc_rate,
.round_rate = clk_vco_round_rate,
.determine_rate = clk_vco_determine_rate,
.set_rate = clk_vco_set_rate,
};

View File

@ -9,13 +9,16 @@
#include "div.h"
static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int sprd_div_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct sprd_div *cd = hw_to_sprd_div(hw);
return divider_round_rate(&cd->common.hw, rate, parent_rate, NULL,
cd->div.width, 0);
req->rate = divider_round_rate(&cd->common.hw, req->rate,
&req->best_parent_rate,
NULL, cd->div.width, 0);
return 0;
}
unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
@ -75,7 +78,7 @@ static int sprd_div_set_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops sprd_div_ops = {
.recalc_rate = sprd_div_recalc_rate,
.round_rate = sprd_div_round_rate,
.determine_rate = sprd_div_determine_rate,
.set_rate = sprd_div_set_rate,
};
EXPORT_SYMBOL_GPL(sprd_div_ops);

View File

@ -254,16 +254,16 @@ static int sprd_pll_clk_prepare(struct clk_hw *hw)
return 0;
}
static long sprd_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int sprd_pll_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
return rate;
return 0;
}
const struct clk_ops sprd_pll_ops = {
.prepare = sprd_pll_clk_prepare,
.recalc_rate = sprd_pll_recalc_rate,
.round_rate = sprd_pll_round_rate,
.determine_rate = sprd_pll_determine_rate,
.set_rate = sprd_pll_set_rate,
};
EXPORT_SYMBOL_GPL(sprd_pll_ops);

View File

@ -375,22 +375,21 @@ static 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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct stm_fs params;
if (clk_fs660c32_vco_get_params(*prate, rate, &params))
return rate;
if (clk_fs660c32_vco_get_params(req->best_parent_rate, req->rate, &params))
return 0;
clk_fs660c32_vco_get_rate(*prate, &params, &rate);
clk_fs660c32_vco_get_rate(req->best_parent_rate, &params, &req->rate);
pr_debug("%s: %s new rate %ld [ndiv=%u]\n",
__func__, clk_hw_get_name(hw),
rate, (unsigned int)params.ndiv);
req->rate, (unsigned int)params.ndiv);
return rate;
return 0;
}
static int quadfs_pll_fs660c32_set_rate(struct clk_hw *hw, unsigned long rate,
@ -436,7 +435,7 @@ static const struct clk_ops st_quadfs_pll_c32_ops = {
.disable = quadfs_pll_disable,
.is_enabled = quadfs_pll_is_enabled,
.recalc_rate = quadfs_pll_fs660c32_recalc_rate,
.round_rate = quadfs_pll_fs660c32_round_rate,
.determine_rate = quadfs_pll_fs660c32_determine_rate,
.set_rate = quadfs_pll_fs660c32_set_rate,
};
@ -814,19 +813,21 @@ static unsigned long quadfs_recalc_rate(struct clk_hw *hw,
return rate;
}
static long quadfs_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int quadfs_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct stm_fs params;
rate = quadfs_find_best_rate(hw, rate, *prate, &params);
req->rate = quadfs_find_best_rate(hw, req->rate,
req->best_parent_rate, &params);
pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
__func__, clk_hw_get_name(hw),
rate, (unsigned int)params.sdiv, (unsigned int)params.mdiv,
(unsigned int)params.pe, (unsigned int)params.nsdiv);
req->rate, (unsigned int)params.sdiv,
(unsigned int)params.mdiv,
(unsigned int)params.pe, (unsigned int)params.nsdiv);
return rate;
return 0;
}
@ -873,7 +874,7 @@ static const struct clk_ops st_quadfs_ops = {
.enable = quadfs_fsynth_enable,
.disable = quadfs_fsynth_disable,
.is_enabled = quadfs_fsynth_is_enabled,
.round_rate = quadfs_round_rate,
.determine_rate = quadfs_determine_rate,
.set_rate = quadfs_set_rate,
.recalc_rate = quadfs_recalc_rate,
};

View File

@ -395,25 +395,28 @@ static unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
return rate;
}
static long round_rate_stm_pll3200c32(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int stm_pll3200c32_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct stm_pll params;
if (!clk_pll3200c32_get_params(*prate, rate, &params))
clk_pll3200c32_get_rate(*prate, &params, &rate);
if (!clk_pll3200c32_get_params(req->best_parent_rate, req->rate, &params))
clk_pll3200c32_get_rate(req->best_parent_rate, &params,
&req->rate);
else {
pr_debug("%s: %s rate %ld Invalid\n", __func__,
__clk_get_name(hw->clk), rate);
__clk_get_name(hw->clk), req->rate);
req->rate = 0;
return 0;
}
pr_debug("%s: %s new rate %ld [ndiv=%u] [idf=%u]\n",
__func__, __clk_get_name(hw->clk),
rate, (unsigned int)params.ndiv,
req->rate, (unsigned int)params.ndiv,
(unsigned int)params.idf);
return rate;
return 0;
}
static int set_rate_stm_pll3200c32(struct clk_hw *hw, unsigned long rate,
@ -549,25 +552,28 @@ static unsigned long recalc_stm_pll4600c28(struct clk_hw *hw,
return rate;
}
static long round_rate_stm_pll4600c28(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int stm_pll4600c28_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct stm_pll params;
if (!clk_pll4600c28_get_params(*prate, rate, &params)) {
clk_pll4600c28_get_rate(*prate, &params, &rate);
if (!clk_pll4600c28_get_params(req->best_parent_rate, req->rate, &params)) {
clk_pll4600c28_get_rate(req->best_parent_rate, &params,
&req->rate);
} else {
pr_debug("%s: %s rate %ld Invalid\n", __func__,
__clk_get_name(hw->clk), rate);
__clk_get_name(hw->clk), req->rate);
req->rate = 0;
return 0;
}
pr_debug("%s: %s new rate %ld [ndiv=%u] [idf=%u]\n",
__func__, __clk_get_name(hw->clk),
rate, (unsigned int)params.ndiv,
req->rate, (unsigned int)params.ndiv,
(unsigned int)params.idf);
return rate;
return 0;
}
static int set_rate_stm_pll4600c28(struct clk_hw *hw, unsigned long rate,
@ -628,7 +634,7 @@ static const struct clk_ops stm_pll3200c32_a9_ops = {
.disable = clkgen_pll_disable,
.is_enabled = clkgen_pll_is_enabled,
.recalc_rate = recalc_stm_pll3200c32,
.round_rate = round_rate_stm_pll3200c32,
.determine_rate = stm_pll3200c32_determine_rate,
.set_rate = set_rate_stm_pll3200c32,
};
@ -637,7 +643,7 @@ static const struct clk_ops stm_pll4600c28_ops = {
.disable = clkgen_pll_disable,
.is_enabled = clkgen_pll_is_enabled,
.recalc_rate = recalc_stm_pll4600c28,
.round_rate = round_rate_stm_pll4600c28,
.determine_rate = stm_pll4600c28_determine_rate,
.set_rate = set_rate_stm_pll4600c28,
};

View File

@ -351,14 +351,14 @@ static int clk_stm32_divider_set_rate(struct clk_hw *hw, unsigned long rate,
return ret;
}
static long clk_stm32_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
static int clk_stm32_divider_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_stm32_div *div = to_clk_stm32_divider(hw);
const struct stm32_div_cfg *divider;
if (div->div_id == NO_STM32_DIV)
return rate;
return 0;
divider = &div->clock_data->dividers[div->div_id];
@ -369,14 +369,22 @@ static long clk_stm32_divider_round_rate(struct clk_hw *hw, unsigned long rate,
val = readl(div->base + divider->offset) >> divider->shift;
val &= clk_div_mask(divider->width);
return divider_ro_round_rate(hw, rate, prate, divider->table,
divider->width, divider->flags,
val);
req->rate = divider_ro_round_rate(hw, req->rate,
&req->best_parent_rate,
divider->table,
divider->width,
divider->flags, val);
return 0;
}
return divider_round_rate_parent(hw, clk_hw_get_parent(hw),
rate, prate, divider->table,
divider->width, divider->flags);
req->rate = divider_round_rate_parent(hw, clk_hw_get_parent(hw),
req->rate,
&req->best_parent_rate,
divider->table,
divider->width, divider->flags);
return 0;
}
static unsigned long clk_stm32_divider_recalc_rate(struct clk_hw *hw,
@ -392,7 +400,7 @@ static unsigned long clk_stm32_divider_recalc_rate(struct clk_hw *hw,
const struct clk_ops clk_stm32_divider_ops = {
.recalc_rate = clk_stm32_divider_recalc_rate,
.round_rate = clk_stm32_divider_round_rate,
.determine_rate = clk_stm32_divider_determine_rate,
.set_rate = clk_stm32_divider_set_rate,
};

View File

@ -970,12 +970,15 @@ static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
return mult;
}
static long timer_ker_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
static int timer_ker_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
unsigned long factor = __bestmult(hw, rate, *parent_rate);
unsigned long factor = __bestmult(hw, req->rate,
req->best_parent_rate);
return *parent_rate * factor;
req->rate = req->best_parent_rate * factor;
return 0;
}
static int timer_ker_set_rate(struct clk_hw *hw, unsigned long rate,
@ -1026,7 +1029,7 @@ static unsigned long timer_ker_recalc_rate(struct clk_hw *hw,
static const struct clk_ops timer_ker_ops = {
.recalc_rate = timer_ker_recalc_rate,
.round_rate = timer_ker_round_rate,
.determine_rate = timer_ker_determine_rate,
.set_rate = timer_ker_set_rate,
};

View File

@ -17,15 +17,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_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct tegra_clk_sync_source *sync = to_clk_sync_source(hw);
if (rate > sync->max_rate)
if (req->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,
@ -38,7 +38,7 @@ static int clk_sync_source_set_rate(struct clk_hw *hw, unsigned long rate,
}
const struct clk_ops tegra_clk_sync_source_ops = {
.round_rate = clk_sync_source_round_rate,
.determine_rate = clk_sync_source_determine_rate,
.set_rate = clk_sync_source_set_rate,
.recalc_rate = clk_sync_source_recalc_rate,
};

View File

@ -58,23 +58,31 @@ 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,
unsigned long *prate)
static int clk_frac_div_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
int div, mul;
unsigned long output_rate = *prate;
unsigned long output_rate = req->best_parent_rate;
if (!rate)
return output_rate;
if (!req->rate) {
req->rate = output_rate;
div = get_div(divider, rate, output_rate);
if (div < 0)
return *prate;
return 0;
}
div = get_div(divider, req->rate, output_rate);
if (div < 0) {
req->rate = req->best_parent_rate;
return 0;
}
mul = get_mul(divider);
return DIV_ROUND_UP(output_rate * mul, div + mul);
req->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,
@ -127,7 +135,7 @@ static void clk_divider_restore_context(struct clk_hw *hw)
const struct clk_ops tegra_clk_frac_div_ops = {
.recalc_rate = clk_frac_div_recalc_rate,
.set_rate = clk_frac_div_set_rate,
.round_rate = clk_frac_div_round_rate,
.determine_rate = clk_frac_div_determine_rate,
.restore_context = clk_divider_restore_context,
};

View File

@ -51,16 +51,10 @@ static int clk_periph_determine_rate(struct clk_hw *hw,
struct tegra_clk_periph *periph = to_clk_periph(hw);
const struct clk_ops *div_ops = periph->div_ops;
struct clk_hw *div_hw = &periph->divider.hw;
long rate;
__clk_hw_set_clk(div_hw, hw);
rate = div_ops->round_rate(div_hw, req->rate, &req->best_parent_rate);
if (rate < 0)
return rate;
req->rate = (unsigned long)rate;
return 0;
return div_ops->determine_rate(div_hw, req);
}
static int clk_periph_set_rate(struct clk_hw *hw, unsigned long rate,

Some files were not shown because too many files have changed in this diff Show More