mirror of https://github.com/torvalds/linux.git
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:
commit
112104e2b7
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = ÷r->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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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, ¶ms))
|
||||
return rate;
|
||||
if (clk_fs660c32_vco_get_params(req->best_parent_rate, req->rate, ¶ms))
|
||||
return 0;
|
||||
|
||||
clk_fs660c32_vco_get_rate(*prate, ¶ms, &rate);
|
||||
clk_fs660c32_vco_get_rate(req->best_parent_rate, ¶ms, &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, ¶ms);
|
||||
req->rate = quadfs_find_best_rate(hw, req->rate,
|
||||
req->best_parent_rate, ¶ms);
|
||||
|
||||
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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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, ¶ms))
|
||||
clk_pll3200c32_get_rate(*prate, ¶ms, &rate);
|
||||
if (!clk_pll3200c32_get_params(req->best_parent_rate, req->rate, ¶ms))
|
||||
clk_pll3200c32_get_rate(req->best_parent_rate, ¶ms,
|
||||
&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, ¶ms)) {
|
||||
clk_pll4600c28_get_rate(*prate, ¶ms, &rate);
|
||||
if (!clk_pll4600c28_get_params(req->best_parent_rate, req->rate, ¶ms)) {
|
||||
clk_pll4600c28_get_rate(req->best_parent_rate, ¶ms,
|
||||
&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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue