MT8196 uses a combination of set/clr registers to control the PLL
enable state, along with a FENC bit to check the preparation status.
Add new set of PLL clock operations with support for set/clr enable and
FENC status logic.
Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Laura Nao <laura.nao@collabora.com>
---
drivers/clk/mediatek/clk-pll.c | 42 +++++++++++++++++++++++++++++++++-
drivers/clk/mediatek/clk-pll.h | 5 ++++
2 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index 49ca25dd5418..8f46de77f42d 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -37,6 +37,13 @@ int mtk_pll_is_prepared(struct clk_hw *hw)
return (readl(pll->en_addr) & BIT(pll->data->pll_en_bit)) != 0;
}
+static int mtk_pll_fenc_is_prepared(struct clk_hw *hw)
+{
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+ return readl(pll->fenc_addr) & pll->fenc_mask;
+}
+
static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
u32 pcw, int postdiv)
{
@@ -274,6 +281,25 @@ void mtk_pll_unprepare(struct clk_hw *hw)
writel(r, pll->pwr_addr);
}
+static int mtk_pll_prepare_setclr(struct clk_hw *hw)
+{
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+ writel(BIT(pll->data->pll_en_bit), pll->en_set_addr);
+
+ /* Wait 20us after enable for the PLL to stabilize */
+ udelay(20);
+
+ return 0;
+}
+
+static void mtk_pll_unprepare_setclr(struct clk_hw *hw)
+{
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+ writel(BIT(pll->data->pll_en_bit), pll->en_clr_addr);
+}
+
const struct clk_ops mtk_pll_ops = {
.is_prepared = mtk_pll_is_prepared,
.prepare = mtk_pll_prepare,
@@ -283,6 +309,16 @@ const struct clk_ops mtk_pll_ops = {
.set_rate = mtk_pll_set_rate,
};
+const struct clk_ops mtk_pll_fenc_clr_set_ops = {
+ .is_prepared = mtk_pll_fenc_is_prepared,
+ .prepare = mtk_pll_prepare_setclr,
+ .unprepare = mtk_pll_unprepare_setclr,
+ .recalc_rate = mtk_pll_recalc_rate,
+ .round_rate = mtk_pll_round_rate,
+ .set_rate = mtk_pll_set_rate,
+};
+EXPORT_SYMBOL_GPL(mtk_pll_fenc_clr_set_ops);
+
struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll,
const struct mtk_pll_data *data,
void __iomem *base,
@@ -315,6 +351,9 @@ struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll,
pll->hw.init = &init;
pll->data = data;
+ pll->fenc_addr = base + data->fenc_sta_ofs;
+ pll->fenc_mask = BIT(data->fenc_sta_bit);
+
init.name = data->name;
init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0;
init.ops = pll_ops;
@@ -337,12 +376,13 @@ struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data,
{
struct mtk_clk_pll *pll;
struct clk_hw *hw;
+ const struct clk_ops *pll_ops = data->ops ? data->ops : &mtk_pll_ops;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
return ERR_PTR(-ENOMEM);
- hw = mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_ops);
+ hw = mtk_clk_register_pll_ops(pll, data, base, pll_ops);
if (IS_ERR(hw))
kfree(pll);
diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h
index c4d06bb11516..7fdc5267a2b5 100644
--- a/drivers/clk/mediatek/clk-pll.h
+++ b/drivers/clk/mediatek/clk-pll.h
@@ -29,6 +29,7 @@ struct mtk_pll_data {
u32 reg;
u32 pwr_reg;
u32 en_mask;
+ u32 fenc_sta_ofs;
u32 pd_reg;
u32 tuner_reg;
u32 tuner_en_reg;
@@ -51,6 +52,7 @@ struct mtk_pll_data {
u32 en_clr_reg;
u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */
u8 pcw_chg_bit;
+ u8 fenc_sta_bit;
};
/*
@@ -72,6 +74,8 @@ struct mtk_clk_pll {
void __iomem *en_addr;
void __iomem *en_set_addr;
void __iomem *en_clr_addr;
+ void __iomem *fenc_addr;
+ u32 fenc_mask;
const struct mtk_pll_data *data;
};
@@ -82,6 +86,7 @@ void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls,
struct clk_hw_onecell_data *clk_data);
extern const struct clk_ops mtk_pll_ops;
+extern const struct clk_ops mtk_pll_fenc_clr_set_ops;
static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
{
--
2.39.5
On Tue, Aug 5, 2025 at 10:55 PM Laura Nao <laura.nao@collabora.com> wrote: > > MT8196 uses a combination of set/clr registers to control the PLL > enable state, along with a FENC bit to check the preparation status. > Add new set of PLL clock operations with support for set/clr enable and > FENC status logic. > > Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com> > Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> > Signed-off-by: Laura Nao <laura.nao@collabora.com> > --- > drivers/clk/mediatek/clk-pll.c | 42 +++++++++++++++++++++++++++++++++- > drivers/clk/mediatek/clk-pll.h | 5 ++++ > 2 files changed, 46 insertions(+), 1 deletion(-) > > diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c > index 49ca25dd5418..8f46de77f42d 100644 > --- a/drivers/clk/mediatek/clk-pll.c > +++ b/drivers/clk/mediatek/clk-pll.c > @@ -37,6 +37,13 @@ int mtk_pll_is_prepared(struct clk_hw *hw) > return (readl(pll->en_addr) & BIT(pll->data->pll_en_bit)) != 0; > } > > +static int mtk_pll_fenc_is_prepared(struct clk_hw *hw) > +{ > + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); > + > + return readl(pll->fenc_addr) & pll->fenc_mask; Nits: I'd do a double-negate (!!) just to indicate that we only care about true or false. Also, why do we need to store fenc_mask instead of just shifting the bit here? Same goes for the register address. |pll| has the base address. Why do we need to pre-calculate it? The code is OK; it just seems a bit wasteful on memory. Either way, this is Reviewed-by: Chen-Yu Tsai <wenst@chromium.org> > +} > + > static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin, > u32 pcw, int postdiv) > { > @@ -274,6 +281,25 @@ void mtk_pll_unprepare(struct clk_hw *hw) > writel(r, pll->pwr_addr); > } > > +static int mtk_pll_prepare_setclr(struct clk_hw *hw) > +{ > + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); > + > + writel(BIT(pll->data->pll_en_bit), pll->en_set_addr); > + > + /* Wait 20us after enable for the PLL to stabilize */ > + udelay(20); > + > + return 0; > +} > + > +static void mtk_pll_unprepare_setclr(struct clk_hw *hw) > +{ > + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); > + > + writel(BIT(pll->data->pll_en_bit), pll->en_clr_addr); > +} > + > const struct clk_ops mtk_pll_ops = { > .is_prepared = mtk_pll_is_prepared, > .prepare = mtk_pll_prepare, > @@ -283,6 +309,16 @@ const struct clk_ops mtk_pll_ops = { > .set_rate = mtk_pll_set_rate, > }; > > +const struct clk_ops mtk_pll_fenc_clr_set_ops = { > + .is_prepared = mtk_pll_fenc_is_prepared, > + .prepare = mtk_pll_prepare_setclr, > + .unprepare = mtk_pll_unprepare_setclr, > + .recalc_rate = mtk_pll_recalc_rate, > + .round_rate = mtk_pll_round_rate, > + .set_rate = mtk_pll_set_rate, > +}; > +EXPORT_SYMBOL_GPL(mtk_pll_fenc_clr_set_ops); > + > struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll, > const struct mtk_pll_data *data, > void __iomem *base, > @@ -315,6 +351,9 @@ struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll, > pll->hw.init = &init; > pll->data = data; > > + pll->fenc_addr = base + data->fenc_sta_ofs; > + pll->fenc_mask = BIT(data->fenc_sta_bit); > + > init.name = data->name; > init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0; > init.ops = pll_ops; > @@ -337,12 +376,13 @@ struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data, > { > struct mtk_clk_pll *pll; > struct clk_hw *hw; > + const struct clk_ops *pll_ops = data->ops ? data->ops : &mtk_pll_ops; > > pll = kzalloc(sizeof(*pll), GFP_KERNEL); > if (!pll) > return ERR_PTR(-ENOMEM); > > - hw = mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_ops); > + hw = mtk_clk_register_pll_ops(pll, data, base, pll_ops); > if (IS_ERR(hw)) > kfree(pll); > > diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h > index c4d06bb11516..7fdc5267a2b5 100644 > --- a/drivers/clk/mediatek/clk-pll.h > +++ b/drivers/clk/mediatek/clk-pll.h > @@ -29,6 +29,7 @@ struct mtk_pll_data { > u32 reg; > u32 pwr_reg; > u32 en_mask; > + u32 fenc_sta_ofs; > u32 pd_reg; > u32 tuner_reg; > u32 tuner_en_reg; > @@ -51,6 +52,7 @@ struct mtk_pll_data { > u32 en_clr_reg; > u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */ > u8 pcw_chg_bit; > + u8 fenc_sta_bit; > }; > > /* > @@ -72,6 +74,8 @@ struct mtk_clk_pll { > void __iomem *en_addr; > void __iomem *en_set_addr; > void __iomem *en_clr_addr; > + void __iomem *fenc_addr; > + u32 fenc_mask; > const struct mtk_pll_data *data; > }; > > @@ -82,6 +86,7 @@ void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, > struct clk_hw_onecell_data *clk_data); > > extern const struct clk_ops mtk_pll_ops; > +extern const struct clk_ops mtk_pll_fenc_clr_set_ops; > > static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw) > { > -- > 2.39.5 >
Hi Chen-Yu, On 8/15/25 05:18, Chen-Yu Tsai wrote: > On Tue, Aug 5, 2025 at 10:55 PM Laura Nao <laura.nao@collabora.com> wrote: >> >> MT8196 uses a combination of set/clr registers to control the PLL >> enable state, along with a FENC bit to check the preparation status. >> Add new set of PLL clock operations with support for set/clr enable and >> FENC status logic. >> >> Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com> >> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> >> Signed-off-by: Laura Nao <laura.nao@collabora.com> >> --- >> drivers/clk/mediatek/clk-pll.c | 42 +++++++++++++++++++++++++++++++++- >> drivers/clk/mediatek/clk-pll.h | 5 ++++ >> 2 files changed, 46 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c >> index 49ca25dd5418..8f46de77f42d 100644 >> --- a/drivers/clk/mediatek/clk-pll.c >> +++ b/drivers/clk/mediatek/clk-pll.c >> @@ -37,6 +37,13 @@ int mtk_pll_is_prepared(struct clk_hw *hw) >> return (readl(pll->en_addr) & BIT(pll->data->pll_en_bit)) != 0; >> } >> >> +static int mtk_pll_fenc_is_prepared(struct clk_hw *hw) >> +{ >> + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); >> + >> + return readl(pll->fenc_addr) & pll->fenc_mask; > > Nits: > > I'd do a double-negate (!!) just to indicate that we only care about > true or false. > > Also, why do we need to store fenc_mask instead of just shifting the bit > here? Same goes for the register address. |pll| has the base address. > Why do we need to pre-calculate it? > > The code is OK; it just seems a bit wasteful on memory. > Thanks for the heads up - since these are only used here for now, I agree they’re not really adding value. I’ll drop fenc_mask and fenc_addr in the next revision. Best, Laura > Either way, this is > > Reviewed-by: Chen-Yu Tsai <wenst@chromium.org> > >> +} >> + >> static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin, >> u32 pcw, int postdiv) >> { >> @@ -274,6 +281,25 @@ void mtk_pll_unprepare(struct clk_hw *hw) >> writel(r, pll->pwr_addr); >> } >> >> +static int mtk_pll_prepare_setclr(struct clk_hw *hw) >> +{ >> + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); >> + >> + writel(BIT(pll->data->pll_en_bit), pll->en_set_addr); >> + >> + /* Wait 20us after enable for the PLL to stabilize */ >> + udelay(20); >> + >> + return 0; >> +} >> + >> +static void mtk_pll_unprepare_setclr(struct clk_hw *hw) >> +{ >> + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); >> + >> + writel(BIT(pll->data->pll_en_bit), pll->en_clr_addr); >> +} >> + >> const struct clk_ops mtk_pll_ops = { >> .is_prepared = mtk_pll_is_prepared, >> .prepare = mtk_pll_prepare, >> @@ -283,6 +309,16 @@ const struct clk_ops mtk_pll_ops = { >> .set_rate = mtk_pll_set_rate, >> }; >> >> +const struct clk_ops mtk_pll_fenc_clr_set_ops = { >> + .is_prepared = mtk_pll_fenc_is_prepared, >> + .prepare = mtk_pll_prepare_setclr, >> + .unprepare = mtk_pll_unprepare_setclr, >> + .recalc_rate = mtk_pll_recalc_rate, >> + .round_rate = mtk_pll_round_rate, >> + .set_rate = mtk_pll_set_rate, >> +}; >> +EXPORT_SYMBOL_GPL(mtk_pll_fenc_clr_set_ops); >> + >> struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll, >> const struct mtk_pll_data *data, >> void __iomem *base, >> @@ -315,6 +351,9 @@ struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll, >> pll->hw.init = &init; >> pll->data = data; >> >> + pll->fenc_addr = base + data->fenc_sta_ofs; >> + pll->fenc_mask = BIT(data->fenc_sta_bit); >> + >> init.name = data->name; >> init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0; >> init.ops = pll_ops; >> @@ -337,12 +376,13 @@ struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data, >> { >> struct mtk_clk_pll *pll; >> struct clk_hw *hw; >> + const struct clk_ops *pll_ops = data->ops ? data->ops : &mtk_pll_ops; >> >> pll = kzalloc(sizeof(*pll), GFP_KERNEL); >> if (!pll) >> return ERR_PTR(-ENOMEM); >> >> - hw = mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_ops); >> + hw = mtk_clk_register_pll_ops(pll, data, base, pll_ops); >> if (IS_ERR(hw)) >> kfree(pll); >> >> diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h >> index c4d06bb11516..7fdc5267a2b5 100644 >> --- a/drivers/clk/mediatek/clk-pll.h >> +++ b/drivers/clk/mediatek/clk-pll.h >> @@ -29,6 +29,7 @@ struct mtk_pll_data { >> u32 reg; >> u32 pwr_reg; >> u32 en_mask; >> + u32 fenc_sta_ofs; >> u32 pd_reg; >> u32 tuner_reg; >> u32 tuner_en_reg; >> @@ -51,6 +52,7 @@ struct mtk_pll_data { >> u32 en_clr_reg; >> u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */ >> u8 pcw_chg_bit; >> + u8 fenc_sta_bit; >> }; >> >> /* >> @@ -72,6 +74,8 @@ struct mtk_clk_pll { >> void __iomem *en_addr; >> void __iomem *en_set_addr; >> void __iomem *en_clr_addr; >> + void __iomem *fenc_addr; >> + u32 fenc_mask; >> const struct mtk_pll_data *data; >> }; >> >> @@ -82,6 +86,7 @@ void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, >> struct clk_hw_onecell_data *clk_data); >> >> extern const struct clk_ops mtk_pll_ops; >> +extern const struct clk_ops mtk_pll_fenc_clr_set_ops; >> >> static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw) >> { >> -- >> 2.39.5 >>
On 8/25/25 14:39, Laura Nao wrote: > Hi Chen-Yu, > > On 8/15/25 05:18, Chen-Yu Tsai wrote: >> On Tue, Aug 5, 2025 at 10:55 PM Laura Nao <laura.nao@collabora.com> wrote: >>> >>> MT8196 uses a combination of set/clr registers to control the PLL >>> enable state, along with a FENC bit to check the preparation status. >>> Add new set of PLL clock operations with support for set/clr enable and >>> FENC status logic. >>> >>> Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com> >>> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> >>> Signed-off-by: Laura Nao <laura.nao@collabora.com> >>> --- >>> drivers/clk/mediatek/clk-pll.c | 42 +++++++++++++++++++++++++++++++++- >>> drivers/clk/mediatek/clk-pll.h | 5 ++++ >>> 2 files changed, 46 insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c >>> index 49ca25dd5418..8f46de77f42d 100644 >>> --- a/drivers/clk/mediatek/clk-pll.c >>> +++ b/drivers/clk/mediatek/clk-pll.c >>> @@ -37,6 +37,13 @@ int mtk_pll_is_prepared(struct clk_hw *hw) >>> return (readl(pll->en_addr) & BIT(pll->data->pll_en_bit)) != 0; >>> } >>> >>> +static int mtk_pll_fenc_is_prepared(struct clk_hw *hw) >>> +{ >>> + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); >>> + >>> + return readl(pll->fenc_addr) & pll->fenc_mask; >> >> Nits: >> >> I'd do a double-negate (!!) just to indicate that we only care about >> true or false. >> >> Also, why do we need to store fenc_mask instead of just shifting the bit >> here? Same goes for the register address. |pll| has the base address. >> Why do we need to pre-calculate it? >> >> The code is OK; it just seems a bit wasteful on memory. >> > > Thanks for the heads up - since these are only used here for now, I > agree they’re not really adding value. I’ll drop fenc_mask and fenc_addr > in the next revision. > On second thought, since pll->base_addr is initialized as base + data->reg (i.e. at CON0 offset), and the FENC status register sits before that in the register map, it can’t be derived directly from pll->base_addr. So we need to keep fenc_addr, but I’ll drop fenc_mask and shift the bit inline instead. Laura > Best, > > Laura > >> Either way, this is >> >> Reviewed-by: Chen-Yu Tsai <wenst@chromium.org> >> >>> +} >>> + >>> static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin, >>> u32 pcw, int postdiv) >>> { >>> @@ -274,6 +281,25 @@ void mtk_pll_unprepare(struct clk_hw *hw) >>> writel(r, pll->pwr_addr); >>> } >>> >>> +static int mtk_pll_prepare_setclr(struct clk_hw *hw) >>> +{ >>> + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); >>> + >>> + writel(BIT(pll->data->pll_en_bit), pll->en_set_addr); >>> + >>> + /* Wait 20us after enable for the PLL to stabilize */ >>> + udelay(20); >>> + >>> + return 0; >>> +} >>> + >>> +static void mtk_pll_unprepare_setclr(struct clk_hw *hw) >>> +{ >>> + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); >>> + >>> + writel(BIT(pll->data->pll_en_bit), pll->en_clr_addr); >>> +} >>> + >>> const struct clk_ops mtk_pll_ops = { >>> .is_prepared = mtk_pll_is_prepared, >>> .prepare = mtk_pll_prepare, >>> @@ -283,6 +309,16 @@ const struct clk_ops mtk_pll_ops = { >>> .set_rate = mtk_pll_set_rate, >>> }; >>> >>> +const struct clk_ops mtk_pll_fenc_clr_set_ops = { >>> + .is_prepared = mtk_pll_fenc_is_prepared, >>> + .prepare = mtk_pll_prepare_setclr, >>> + .unprepare = mtk_pll_unprepare_setclr, >>> + .recalc_rate = mtk_pll_recalc_rate, >>> + .round_rate = mtk_pll_round_rate, >>> + .set_rate = mtk_pll_set_rate, >>> +}; >>> +EXPORT_SYMBOL_GPL(mtk_pll_fenc_clr_set_ops); >>> + >>> struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll, >>> const struct mtk_pll_data *data, >>> void __iomem *base, >>> @@ -315,6 +351,9 @@ struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll, >>> pll->hw.init = &init; >>> pll->data = data; >>> >>> + pll->fenc_addr = base + data->fenc_sta_ofs; >>> + pll->fenc_mask = BIT(data->fenc_sta_bit); >>> + >>> init.name = data->name; >>> init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0; >>> init.ops = pll_ops; >>> @@ -337,12 +376,13 @@ struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data, >>> { >>> struct mtk_clk_pll *pll; >>> struct clk_hw *hw; >>> + const struct clk_ops *pll_ops = data->ops ? data->ops : &mtk_pll_ops; >>> >>> pll = kzalloc(sizeof(*pll), GFP_KERNEL); >>> if (!pll) >>> return ERR_PTR(-ENOMEM); >>> >>> - hw = mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_ops); >>> + hw = mtk_clk_register_pll_ops(pll, data, base, pll_ops); >>> if (IS_ERR(hw)) >>> kfree(pll); >>> >>> diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h >>> index c4d06bb11516..7fdc5267a2b5 100644 >>> --- a/drivers/clk/mediatek/clk-pll.h >>> +++ b/drivers/clk/mediatek/clk-pll.h >>> @@ -29,6 +29,7 @@ struct mtk_pll_data { >>> u32 reg; >>> u32 pwr_reg; >>> u32 en_mask; >>> + u32 fenc_sta_ofs; >>> u32 pd_reg; >>> u32 tuner_reg; >>> u32 tuner_en_reg; >>> @@ -51,6 +52,7 @@ struct mtk_pll_data { >>> u32 en_clr_reg; >>> u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */ >>> u8 pcw_chg_bit; >>> + u8 fenc_sta_bit; >>> }; >>> >>> /* >>> @@ -72,6 +74,8 @@ struct mtk_clk_pll { >>> void __iomem *en_addr; >>> void __iomem *en_set_addr; >>> void __iomem *en_clr_addr; >>> + void __iomem *fenc_addr; >>> + u32 fenc_mask; >>> const struct mtk_pll_data *data; >>> }; >>> >>> @@ -82,6 +86,7 @@ void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, >>> struct clk_hw_onecell_data *clk_data); >>> >>> extern const struct clk_ops mtk_pll_ops; >>> +extern const struct clk_ops mtk_pll_fenc_clr_set_ops; >>> >>> static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw) >>> { >>> -- >>> 2.39.5 >>> >
© 2016 - 2025 Red Hat, Inc.