On Mon, 2019-12-23 at 17:28 +0800, mingming lee wrote: > Update mtk common clock driver to support mt8512 > 1. add new set_clr_upd mux type and related operation > 2. add configurable pcw_chg_reg/ibits/fmin to mtk_pll > 3. fix mtk_clk_find_parent_rate data overflow.
I think these should be split into different patches. Also, Sam has sent a fixup for overflow problem > Signed-off-by: mingming lee <mingming....@mediatek.com> > --- > drivers/clk/mediatek/clk-mtk.c | 72 ++++++++++++++++++++++++---------- > drivers/clk/mediatek/clk-mtk.h | 26 ++++++++++++ > 2 files changed, 77 insertions(+), 21 deletions(-) > diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c > index 6c6b500d9b..5a2b77e4ae 100644 > --- a/drivers/clk/mediatek/clk-mtk.c > +++ b/drivers/clk/mediatek/clk-mtk.c > @@ -39,8 +39,8 @@ > * this function is recursively called to find the parent to calculate > * the accurate frequency. > */ > -static int mtk_clk_find_parent_rate(struct clk *clk, int id, > - const struct driver *drv) > +static ulong mtk_clk_find_parent_rate(struct clk *clk, int id, > + const struct driver *drv) > { > struct clk parent = { .id = id, }; > > @@ -67,12 +67,23 @@ static int mtk_clk_mux_set_parent(void __iomem *base, u32 > parent, > if (++index == mux->num_parents) > return -EINVAL; > > - /* switch mux to a select parent */ > - val = readl(base + mux->mux_reg); > - val &= ~(mux->mux_mask << mux->mux_shift); > + if (mux->flags & CLK_MUX_SETCLR_UPD) { > + val = (mux->mux_mask << mux->mux_shift); > + writel(val, base + mux->mux_clr_reg); > > - val |= index << mux->mux_shift; > - writel(val, base + mux->mux_reg); > + val = (index << mux->mux_shift); > + writel(val, base + mux->mux_set_reg); > + > + if (mux->upd_shift >= 0) > + writel(BIT(mux->upd_shift), base + mux->upd_reg); > + } else { > + /* switch mux to a select parent */ > + val = readl(base + mux->mux_reg); > + val &= ~(mux->mux_mask << mux->mux_shift); > + > + val |= index << mux->mux_shift; > + writel(val, base + mux->mux_reg); > + } > > return 0; > } > @@ -84,11 +95,13 @@ static unsigned long __mtk_pll_recalc_rate(const struct > mtk_pll_data *pll, > { > int pcwbits = pll->pcwbits; > int pcwfbits; > + int ibits; > u64 vco; > u8 c = 0; > > /* The fractional part of the PLL divider. */ > - pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0; > + ibits = pll->pcwibits ? pll->pcwibits : INTEGER_BITS; > + pcwfbits = pcwbits > ibits ? pcwbits - ibits : 0; > > vco = (u64)fin * pcw; > > @@ -113,7 +126,7 @@ static void mtk_pll_set_rate_regs(struct clk *clk, u32 > pcw, int postdiv) > { > struct mtk_clk_priv *priv = dev_get_priv(clk->dev); > const struct mtk_pll_data *pll = &priv->tree->plls[clk->id]; > - u32 val; > + u32 val, chg; > > /* set postdiv */ > val = readl(priv->base + pll->pd_reg); > @@ -129,11 +142,16 @@ static void mtk_pll_set_rate_regs(struct clk *clk, u32 > pcw, int postdiv) > /* set pcw */ > val &= ~GENMASK(pll->pcw_shift + pll->pcwbits - 1, pll->pcw_shift); > val |= pcw << pll->pcw_shift; > - val &= ~CON1_PCW_CHG; > - writel(val, priv->base + pll->pcw_reg); > > - val |= CON1_PCW_CHG; > - writel(val, priv->base + pll->pcw_reg); > + if (pll->pcw_chg_reg) { > + chg = readl(priv->base + pll->pcw_chg_reg); > + chg |= CON1_PCW_CHG; > + writel(val, priv->base + pll->pcw_reg); > + writel(chg, priv->base + pll->pcw_chg_reg); > + } else { > + val |= CON1_PCW_CHG; > + writel(val, priv->base + pll->pcw_reg); > + } > > udelay(20); > } > @@ -150,8 +168,9 @@ static void mtk_pll_calc_values(struct clk *clk, u32 > *pcw, u32 *postdiv, > { > struct mtk_clk_priv *priv = dev_get_priv(clk->dev); > const struct mtk_pll_data *pll = &priv->tree->plls[clk->id]; > - unsigned long fmin = 1000 * MHZ; > + unsigned long fmin = pll->fmin ? pll->fmin : 1000 * MHZ; > u64 _pcw; > + int ibits; > u32 val; > > if (freq > pll->fmax) > @@ -164,7 +183,8 @@ static void mtk_pll_calc_values(struct clk *clk, u32 > *pcw, u32 *postdiv, > } > > /* _pcw = freq * postdiv / xtal_rate * 2^pcwfbits */ > - _pcw = ((u64)freq << val) << (pll->pcwbits - INTEGER_BITS); > + ibits = pll->pcwibits ? pll->pcwibits : INTEGER_BITS; > + _pcw = ((u64)freq << val) << (pll->pcwbits - ibits); > do_div(_pcw, priv->tree->xtal2_rate); > > *pcw = (u32)_pcw; > @@ -332,9 +352,14 @@ static int mtk_topckgen_enable(struct clk *clk) > return 0; > > /* enable clock gate */ > - val = readl(priv->base + mux->gate_reg); > - val &= ~BIT(mux->gate_shift); > - writel(val, priv->base + mux->gate_reg); > + if (mux->flags & CLK_MUX_SETCLR_UPD) { > + val = BIT(mux->gate_shift); > + writel(val, priv->base + mux->mux_clr_reg); > + } else { > + val = readl(priv->base + mux->gate_reg); > + val &= ~BIT(mux->gate_shift); > + writel(val, priv->base + mux->gate_reg); > + } > > if (mux->flags & CLK_DOMAIN_SCPSYS) { > /* enable scpsys clock off control */ > @@ -360,9 +385,14 @@ static int mtk_topckgen_disable(struct clk *clk) > return 0; > > /* disable clock gate */ > - val = readl(priv->base + mux->gate_reg); > - val |= BIT(mux->gate_shift); > - writel(val, priv->base + mux->gate_reg); > + if (mux->flags & CLK_MUX_SETCLR_UPD) { > + val = BIT(mux->gate_shift); > + writel(val, priv->base + mux->mux_set_reg); > + } else { > + val = readl(priv->base + mux->gate_reg); > + val |= BIT(mux->gate_shift); > + writel(val, priv->base + mux->gate_reg); > + } > > return 0; > } > diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h > index dce93253ad..c7dc980861 100644 > --- a/drivers/clk/mediatek/clk-mtk.h > +++ b/drivers/clk/mediatek/clk-mtk.h > @@ -12,6 +12,7 @@ > > #define HAVE_RST_BAR BIT(0) > #define CLK_DOMAIN_SCPSYS BIT(0) > +#define CLK_MUX_SETCLR_UPD BIT(1) > > #define CLK_GATE_SETCLR BIT(0) > #define CLK_GATE_SETCLR_INV BIT(1) > @@ -36,9 +37,12 @@ struct mtk_pll_data { > u32 flags; > u32 rst_bar_mask; > u64 fmax; > + u64 fmin; > int pcwbits; > + int pcwibits; > u32 pcw_reg; > int pcw_shift; > + u32 pcw_chg_reg; > }; > > /** > @@ -102,9 +106,13 @@ struct mtk_composite { > const int id; > const int *parent; > u32 mux_reg; > + u32 mux_set_reg; > + u32 mux_clr_reg; > + u32 upd_reg; > u32 gate_reg; > u32 mux_mask; > signed char mux_shift; > + signed char upd_shift; > signed char gate_shift; > signed char num_parents; > u16 flags; > @@ -137,6 +145,24 @@ struct mtk_composite { > .flags = 0, \ > } > > +#define MUX_CLR_SET_UPD_FLAGS(_id, _parents, _mux_ofs, _mux_set_ofs,\ > + _mux_clr_ofs, _shift, _width, _gate, \ > + _upd_ofs, _upd, _flags) { \ > + .id = _id, \ > + .mux_reg = _mux_ofs, \ > + .mux_set_reg = _mux_set_ofs, \ > + .mux_clr_reg = _mux_clr_ofs, \ > + .upd_reg = _upd_ofs, \ > + .upd_shift = _upd, \ > + .mux_shift = _shift, \ > + .mux_mask = BIT(_width) - 1, \ > + .gate_reg = _mux_ofs, \ > + .gate_shift = _gate, \ > + .parent = _parents, \ > + .num_parents = ARRAY_SIZE(_parents), \ > + .flags = _flags, \ > + } > + > struct mtk_gate_regs { > u32 sta_ofs; > u32 clr_ofs;