Commit 5cf065f5 authored by Stephen Boyd's avatar Stephen Boyd

Merge branch 'clk-fixes' into clk-next

parents 306c342f aaa6d062
...@@ -211,8 +211,9 @@ static void __init imx6q_1588_init(void) ...@@ -211,8 +211,9 @@ static void __init imx6q_1588_init(void)
* set bit IOMUXC_GPR1[21]. Or the PTP clock must be from pad * set bit IOMUXC_GPR1[21]. Or the PTP clock must be from pad
* (external OSC), and we need to clear the bit. * (external OSC), and we need to clear the bit.
*/ */
clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP : clksel = clk_is_match(ptp_clk, enet_ref) ?
IMX6Q_GPR1_ENET_CLK_SEL_PAD; IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
IMX6Q_GPR1_ENET_CLK_SEL_PAD;
gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
if (!IS_ERR(gpr)) if (!IS_ERR(gpr))
regmap_update_bits(gpr, IOMUXC_GPR1, regmap_update_bits(gpr, IOMUXC_GPR1,
......
...@@ -144,12 +144,6 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, ...@@ -144,12 +144,6 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
divider->flags); divider->flags);
} }
/*
* The reverse of DIV_ROUND_UP: The maximum number which
* divided by m is r
*/
#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
static bool _is_valid_table_div(const struct clk_div_table *table, static bool _is_valid_table_div(const struct clk_div_table *table,
unsigned int div) unsigned int div)
{ {
...@@ -225,19 +219,24 @@ static int _div_round_closest(const struct clk_div_table *table, ...@@ -225,19 +219,24 @@ static int _div_round_closest(const struct clk_div_table *table,
unsigned long parent_rate, unsigned long rate, unsigned long parent_rate, unsigned long rate,
unsigned long flags) unsigned long flags)
{ {
int up, down, div; int up, down;
unsigned long up_rate, down_rate;
up = down = div = DIV_ROUND_CLOSEST(parent_rate, rate); up = DIV_ROUND_UP(parent_rate, rate);
down = parent_rate / rate;
if (flags & CLK_DIVIDER_POWER_OF_TWO) { if (flags & CLK_DIVIDER_POWER_OF_TWO) {
up = __roundup_pow_of_two(div); up = __roundup_pow_of_two(up);
down = __rounddown_pow_of_two(div); down = __rounddown_pow_of_two(down);
} else if (table) { } else if (table) {
up = _round_up_table(table, div); up = _round_up_table(table, up);
down = _round_down_table(table, div); down = _round_down_table(table, down);
} }
return (up - div) <= (div - down) ? up : down; up_rate = DIV_ROUND_UP(parent_rate, up);
down_rate = DIV_ROUND_UP(parent_rate, down);
return (rate - up_rate) <= (down_rate - rate) ? up : down;
} }
static int _div_round(const struct clk_div_table *table, static int _div_round(const struct clk_div_table *table,
...@@ -313,7 +312,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, ...@@ -313,7 +312,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
return i; return i;
} }
parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
MULT_ROUND_UP(rate, i)); rate * i);
now = DIV_ROUND_UP(parent_rate, i); now = DIV_ROUND_UP(parent_rate, i);
if (_is_best_div(rate, now, best, flags)) { if (_is_best_div(rate, now, best, flags)) {
bestdiv = i; bestdiv = i;
...@@ -353,7 +352,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, ...@@ -353,7 +352,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
bestdiv = readl(divider->reg) >> divider->shift; bestdiv = readl(divider->reg) >> divider->shift;
bestdiv &= div_mask(divider->width); bestdiv &= div_mask(divider->width);
bestdiv = _get_div(divider->table, bestdiv, divider->flags); bestdiv = _get_div(divider->table, bestdiv, divider->flags);
return bestdiv; return DIV_ROUND_UP(*prate, bestdiv);
} }
return divider_round_rate(hw, rate, prate, divider->table, return divider_round_rate(hw, rate, prate, divider->table,
......
...@@ -1382,7 +1382,6 @@ static unsigned long clk_core_get_rate(struct clk_core *clk) ...@@ -1382,7 +1382,6 @@ static unsigned long clk_core_get_rate(struct clk_core *clk)
return rate; return rate;
} }
EXPORT_SYMBOL_GPL(clk_core_get_rate);
/** /**
* clk_get_rate - return the rate of clk * clk_get_rate - return the rate of clk
...@@ -2216,6 +2215,32 @@ int clk_get_phase(struct clk *clk) ...@@ -2216,6 +2215,32 @@ int clk_get_phase(struct clk *clk)
return clk_core_get_phase(clk->core); return clk_core_get_phase(clk->core);
} }
/**
* clk_is_match - check if two clk's point to the same hardware clock
* @p: clk compared against q
* @q: clk compared against p
*
* Returns true if the two struct clk pointers both point to the same hardware
* clock node. Put differently, returns true if struct clk *p and struct clk *q
* share the same struct clk_core object.
*
* Returns false otherwise. Note that two NULL clks are treated as matching.
*/
bool clk_is_match(const struct clk *p, const struct clk *q)
{
/* trivial case: identical struct clk's or both NULL */
if (p == q)
return true;
/* true if clk->core pointers match. Avoid derefing garbage */
if (!IS_ERR_OR_NULL(p) && !IS_ERR_OR_NULL(q))
if (p->core == q->core)
return true;
return false;
}
EXPORT_SYMBOL_GPL(clk_is_match);
/** /**
* __clk_init - initialize the data structures in a struct clk * __clk_init - initialize the data structures in a struct clk
* @dev: device initializing this clk, placeholder for now * @dev: device initializing this clk, placeholder for now
......
...@@ -48,6 +48,17 @@ static struct clk_pll pll3 = { ...@@ -48,6 +48,17 @@ static struct clk_pll pll3 = {
}, },
}; };
static struct clk_regmap pll4_vote = {
.enable_reg = 0x34c0,
.enable_mask = BIT(4),
.hw.init = &(struct clk_init_data){
.name = "pll4_vote",
.parent_names = (const char *[]){ "pll4" },
.num_parents = 1,
.ops = &clk_pll_vote_ops,
},
};
static struct clk_pll pll8 = { static struct clk_pll pll8 = {
.l_reg = 0x3144, .l_reg = 0x3144,
.m_reg = 0x3148, .m_reg = 0x3148,
...@@ -3023,6 +3034,7 @@ static struct clk_branch rpm_msg_ram_h_clk = { ...@@ -3023,6 +3034,7 @@ static struct clk_branch rpm_msg_ram_h_clk = {
static struct clk_regmap *gcc_msm8960_clks[] = { static struct clk_regmap *gcc_msm8960_clks[] = {
[PLL3] = &pll3.clkr, [PLL3] = &pll3.clkr,
[PLL4_VOTE] = &pll4_vote,
[PLL8] = &pll8.clkr, [PLL8] = &pll8.clkr,
[PLL8_VOTE] = &pll8_vote, [PLL8_VOTE] = &pll8_vote,
[PLL14] = &pll14.clkr, [PLL14] = &pll14.clkr,
...@@ -3247,6 +3259,7 @@ static const struct qcom_reset_map gcc_msm8960_resets[] = { ...@@ -3247,6 +3259,7 @@ static const struct qcom_reset_map gcc_msm8960_resets[] = {
static struct clk_regmap *gcc_apq8064_clks[] = { static struct clk_regmap *gcc_apq8064_clks[] = {
[PLL3] = &pll3.clkr, [PLL3] = &pll3.clkr,
[PLL4_VOTE] = &pll4_vote,
[PLL8] = &pll8.clkr, [PLL8] = &pll8.clkr,
[PLL8_VOTE] = &pll8_vote, [PLL8_VOTE] = &pll8_vote,
[PLL14] = &pll14.clkr, [PLL14] = &pll14.clkr,
......
...@@ -461,7 +461,6 @@ static struct platform_driver lcc_ipq806x_driver = { ...@@ -461,7 +461,6 @@ static struct platform_driver lcc_ipq806x_driver = {
.remove = lcc_ipq806x_remove, .remove = lcc_ipq806x_remove,
.driver = { .driver = {
.name = "lcc-ipq806x", .name = "lcc-ipq806x",
.owner = THIS_MODULE,
.of_match_table = lcc_ipq806x_match_table, .of_match_table = lcc_ipq806x_match_table,
}, },
}; };
......
...@@ -417,8 +417,8 @@ static struct clk_rcg slimbus_src = { ...@@ -417,8 +417,8 @@ static struct clk_rcg slimbus_src = {
.mnctr_en_bit = 8, .mnctr_en_bit = 8,
.mnctr_reset_bit = 7, .mnctr_reset_bit = 7,
.mnctr_mode_shift = 5, .mnctr_mode_shift = 5,
.n_val_shift = 16, .n_val_shift = 24,
.m_val_shift = 16, .m_val_shift = 8,
.width = 8, .width = 8,
}, },
.p = { .p = {
...@@ -547,7 +547,7 @@ static int lcc_msm8960_probe(struct platform_device *pdev) ...@@ -547,7 +547,7 @@ static int lcc_msm8960_probe(struct platform_device *pdev)
return PTR_ERR(regmap); return PTR_ERR(regmap);
/* Use the correct frequency plan depending on speed of PLL4 */ /* Use the correct frequency plan depending on speed of PLL4 */
val = regmap_read(regmap, 0x4, &val); regmap_read(regmap, 0x4, &val);
if (val == 0x12) { if (val == 0x12) {
slimbus_src.freq_tbl = clk_tbl_aif_osr_492; slimbus_src.freq_tbl = clk_tbl_aif_osr_492;
mi2s_osr_src.freq_tbl = clk_tbl_aif_osr_492; mi2s_osr_src.freq_tbl = clk_tbl_aif_osr_492;
...@@ -574,7 +574,6 @@ static struct platform_driver lcc_msm8960_driver = { ...@@ -574,7 +574,6 @@ static struct platform_driver lcc_msm8960_driver = {
.remove = lcc_msm8960_remove, .remove = lcc_msm8960_remove,
.driver = { .driver = {
.name = "lcc-msm8960", .name = "lcc-msm8960",
.owner = THIS_MODULE,
.of_match_table = lcc_msm8960_match_table, .of_match_table = lcc_msm8960_match_table,
}, },
}; };
......
...@@ -84,7 +84,7 @@ static int ti_fapll_enable(struct clk_hw *hw) ...@@ -84,7 +84,7 @@ static int ti_fapll_enable(struct clk_hw *hw)
struct fapll_data *fd = to_fapll(hw); struct fapll_data *fd = to_fapll(hw);
u32 v = readl_relaxed(fd->base); u32 v = readl_relaxed(fd->base);
v |= (1 << FAPLL_MAIN_PLLEN); v |= FAPLL_MAIN_PLLEN;
writel_relaxed(v, fd->base); writel_relaxed(v, fd->base);
return 0; return 0;
...@@ -95,7 +95,7 @@ static void ti_fapll_disable(struct clk_hw *hw) ...@@ -95,7 +95,7 @@ static void ti_fapll_disable(struct clk_hw *hw)
struct fapll_data *fd = to_fapll(hw); struct fapll_data *fd = to_fapll(hw);
u32 v = readl_relaxed(fd->base); u32 v = readl_relaxed(fd->base);
v &= ~(1 << FAPLL_MAIN_PLLEN); v &= ~FAPLL_MAIN_PLLEN;
writel_relaxed(v, fd->base); writel_relaxed(v, fd->base);
} }
...@@ -104,7 +104,7 @@ static int ti_fapll_is_enabled(struct clk_hw *hw) ...@@ -104,7 +104,7 @@ static int ti_fapll_is_enabled(struct clk_hw *hw)
struct fapll_data *fd = to_fapll(hw); struct fapll_data *fd = to_fapll(hw);
u32 v = readl_relaxed(fd->base); u32 v = readl_relaxed(fd->base);
return v & (1 << FAPLL_MAIN_PLLEN); return v & FAPLL_MAIN_PLLEN;
} }
static unsigned long ti_fapll_recalc_rate(struct clk_hw *hw, static unsigned long ti_fapll_recalc_rate(struct clk_hw *hw,
......
...@@ -125,6 +125,19 @@ int clk_set_phase(struct clk *clk, int degrees); ...@@ -125,6 +125,19 @@ int clk_set_phase(struct clk *clk, int degrees);
*/ */
int clk_get_phase(struct clk *clk); int clk_get_phase(struct clk *clk);
/**
* clk_is_match - check if two clk's point to the same hardware clock
* @p: clk compared against q
* @q: clk compared against p
*
* Returns true if the two struct clk pointers both point to the same hardware
* clock node. Put differently, returns true if struct clk *p and struct clk *q
* share the same struct clk_core object.
*
* Returns false otherwise. Note that two NULL clks are treated as matching.
*/
bool clk_is_match(const struct clk *p, const struct clk *q);
#else #else
static inline long clk_get_accuracy(struct clk *clk) static inline long clk_get_accuracy(struct clk *clk)
...@@ -142,6 +155,11 @@ static inline long clk_get_phase(struct clk *clk) ...@@ -142,6 +155,11 @@ static inline long clk_get_phase(struct clk *clk)
return -ENOTSUPP; return -ENOTSUPP;
} }
static inline bool clk_is_match(const struct clk *p, const struct clk *q)
{
return p == q;
}
#endif #endif
/** /**
......
...@@ -1049,7 +1049,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv, ...@@ -1049,7 +1049,7 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
enum spdif_txrate index, bool round) enum spdif_txrate index, bool round)
{ {
const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 }; const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
bool is_sysclk = clk == spdif_priv->sysclk; bool is_sysclk = clk_is_match(clk, spdif_priv->sysclk);
u64 rate_ideal, rate_actual, sub; u64 rate_ideal, rate_actual, sub;
u32 sysclk_dfmin, sysclk_dfmax; u32 sysclk_dfmin, sysclk_dfmax;
u32 txclk_df, sysclk_df, arate; u32 txclk_df, sysclk_df, arate;
...@@ -1143,7 +1143,7 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv, ...@@ -1143,7 +1143,7 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
spdif_priv->txclk_src[index], rate[index]); spdif_priv->txclk_src[index], rate[index]);
dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n", dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n",
spdif_priv->txclk_df[index], rate[index]); spdif_priv->txclk_df[index], rate[index]);
if (spdif_priv->txclk[index] == spdif_priv->sysclk) if (clk_is_match(spdif_priv->txclk[index], spdif_priv->sysclk))
dev_dbg(&pdev->dev, "use sysclk df %d for %dHz sample rate\n", dev_dbg(&pdev->dev, "use sysclk df %d for %dHz sample rate\n",
spdif_priv->sysclk_df[index], rate[index]); spdif_priv->sysclk_df[index], rate[index]);
dev_dbg(&pdev->dev, "the best rate for %dHz sample rate is %dHz\n", dev_dbg(&pdev->dev, "the best rate for %dHz sample rate is %dHz\n",
......
...@@ -579,7 +579,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev) ...@@ -579,7 +579,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
if (PTR_ERR(priv->extclk) == -EPROBE_DEFER) if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
return -EPROBE_DEFER; return -EPROBE_DEFER;
} else { } else {
if (priv->extclk == priv->clk) { if (clk_is_match(priv->extclk, priv->clk)) {
devm_clk_put(&pdev->dev, priv->extclk); devm_clk_put(&pdev->dev, priv->extclk);
priv->extclk = ERR_PTR(-EINVAL); priv->extclk = ERR_PTR(-EINVAL);
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment