Skip to content

Commit 56b8d0b

Browse files
MrVanabelvesa
authored andcommitted
clk: imx: fracn-gppll: support integer pll
The fracn gppll could be configured in FRAC or INTEGER mode during hardware design. The current driver only support FRAC mode, while this patch introduces INTEGER support. When the PLL is INTEGER pll, there is no mfn, mfd, the calculation is as below: Fvco_clk = (Fref / DIV[RDIV] ) * DIV[MFI] Fclko_odiv = Fvco_clk / DIV[ODIV] In this patch, we reuse the FRAC pll logic with some condition check to simplify the driver Signed-off-by: Peng Fan <[email protected]> Reviewed-by: Abel Vesa <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Abel Vesa <[email protected]>
1 parent 4435467 commit 56b8d0b

File tree

2 files changed

+68
-7
lines changed

2 files changed

+68
-7
lines changed

drivers/clk/imx/clk-fracn-gppll.c

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,22 @@
5353
.odiv = (_odiv), \
5454
}
5555

56+
#define PLL_FRACN_GP_INTEGER(_rate, _mfi, _rdiv, _odiv) \
57+
{ \
58+
.rate = (_rate), \
59+
.mfi = (_mfi), \
60+
.mfn = 0, \
61+
.mfd = 0, \
62+
.rdiv = (_rdiv), \
63+
.odiv = (_odiv), \
64+
}
65+
5666
struct clk_fracn_gppll {
5767
struct clk_hw hw;
5868
void __iomem *base;
5969
const struct imx_fracn_gppll_rate_table *rate_table;
6070
int rate_count;
71+
u32 flags;
6172
};
6273

6374
/*
@@ -83,6 +94,24 @@ struct imx_fracn_gppll_clk imx_fracn_gppll = {
8394
};
8495
EXPORT_SYMBOL_GPL(imx_fracn_gppll);
8596

97+
/*
98+
* Fvco = (Fref / rdiv) * MFI
99+
* Fout = Fvco / odiv
100+
* The (Fref / rdiv) should be in range 20MHz to 40MHz
101+
* The Fvco should be in range 2.5Ghz to 5Ghz
102+
*/
103+
static const struct imx_fracn_gppll_rate_table int_tbl[] = {
104+
PLL_FRACN_GP_INTEGER(1700000000U, 141, 1, 2),
105+
PLL_FRACN_GP_INTEGER(1400000000U, 175, 1, 3),
106+
PLL_FRACN_GP_INTEGER(900000000U, 150, 1, 4),
107+
};
108+
109+
struct imx_fracn_gppll_clk imx_fracn_gppll_integer = {
110+
.rate_table = int_tbl,
111+
.rate_count = ARRAY_SIZE(int_tbl),
112+
};
113+
EXPORT_SYMBOL_GPL(imx_fracn_gppll_integer);
114+
86115
static inline struct clk_fracn_gppll *to_clk_fracn_gppll(struct clk_hw *hw)
87116
{
88117
return container_of(hw, struct clk_fracn_gppll, hw);
@@ -169,9 +198,15 @@ static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned lon
169198
break;
170199
}
171200

172-
/* Fvco = Fref * (MFI + MFN / MFD) */
173-
fvco = fvco * mfi * mfd + fvco * mfn;
174-
do_div(fvco, mfd * rdiv * odiv);
201+
if (pll->flags & CLK_FRACN_GPPLL_INTEGER) {
202+
/* Fvco = (Fref / rdiv) * MFI */
203+
fvco = fvco * mfi;
204+
do_div(fvco, rdiv * odiv);
205+
} else {
206+
/* Fvco = (Fref / rdiv) * (MFI + MFN / MFD) */
207+
fvco = fvco * mfi * mfd + fvco * mfn;
208+
do_div(fvco, mfd * rdiv * odiv);
209+
}
175210

176211
return (unsigned long)fvco;
177212
}
@@ -215,8 +250,10 @@ static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
215250
pll_div = FIELD_PREP(PLL_RDIV_MASK, rate->rdiv) | rate->odiv |
216251
FIELD_PREP(PLL_MFI_MASK, rate->mfi);
217252
writel_relaxed(pll_div, pll->base + PLL_DIV);
218-
writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR);
219-
writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR);
253+
if (pll->flags & CLK_FRACN_GPPLL_FRACN) {
254+
writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR);
255+
writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR);
256+
}
220257

221258
/* Wait for 5us according to fracn mode pll doc */
222259
udelay(5);
@@ -300,8 +337,10 @@ static const struct clk_ops clk_fracn_gppll_ops = {
300337
.set_rate = clk_fracn_gppll_set_rate,
301338
};
302339

303-
struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
304-
const struct imx_fracn_gppll_clk *pll_clk)
340+
static struct clk_hw *_imx_clk_fracn_gppll(const char *name, const char *parent_name,
341+
void __iomem *base,
342+
const struct imx_fracn_gppll_clk *pll_clk,
343+
u32 pll_flags)
305344
{
306345
struct clk_fracn_gppll *pll;
307346
struct clk_hw *hw;
@@ -322,6 +361,7 @@ struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, vo
322361
pll->hw.init = &init;
323362
pll->rate_table = pll_clk->rate_table;
324363
pll->rate_count = pll_clk->rate_count;
364+
pll->flags = pll_flags;
325365

326366
hw = &pll->hw;
327367

@@ -334,4 +374,18 @@ struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, vo
334374

335375
return hw;
336376
}
377+
378+
struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
379+
const struct imx_fracn_gppll_clk *pll_clk)
380+
{
381+
return _imx_clk_fracn_gppll(name, parent_name, base, pll_clk, CLK_FRACN_GPPLL_FRACN);
382+
}
337383
EXPORT_SYMBOL_GPL(imx_clk_fracn_gppll);
384+
385+
struct clk_hw *imx_clk_fracn_gppll_integer(const char *name, const char *parent_name,
386+
void __iomem *base,
387+
const struct imx_fracn_gppll_clk *pll_clk)
388+
{
389+
return _imx_clk_fracn_gppll(name, parent_name, base, pll_clk, CLK_FRACN_GPPLL_INTEGER);
390+
}
391+
EXPORT_SYMBOL_GPL(imx_clk_fracn_gppll_integer);

drivers/clk/imx/clk.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ extern struct imx_pll14xx_clk imx_1416x_pll;
7373
extern struct imx_pll14xx_clk imx_1443x_pll;
7474
extern struct imx_pll14xx_clk imx_1443x_dram_pll;
7575

76+
#define CLK_FRACN_GPPLL_INTEGER BIT(0)
77+
#define CLK_FRACN_GPPLL_FRACN BIT(1)
78+
7679
/* NOTE: Rate table should be kept sorted in descending order. */
7780
struct imx_fracn_gppll_rate_table {
7881
unsigned int rate;
@@ -91,8 +94,12 @@ struct imx_fracn_gppll_clk {
9194

9295
struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
9396
const struct imx_fracn_gppll_clk *pll_clk);
97+
struct clk_hw *imx_clk_fracn_gppll_integer(const char *name, const char *parent_name,
98+
void __iomem *base,
99+
const struct imx_fracn_gppll_clk *pll_clk);
94100

95101
extern struct imx_fracn_gppll_clk imx_fracn_gppll;
102+
extern struct imx_fracn_gppll_clk imx_fracn_gppll_integer;
96103

97104
#define imx_clk_cpu(name, parent_name, div, mux, pll, step) \
98105
to_clk(imx_clk_hw_cpu(name, parent_name, div, mux, pll, step))

0 commit comments

Comments
 (0)