1 // SPDX-License-Identifier: GPL-2.0
6 #include <linux/bitfield.h>
7 #include <linux/clk-provider.h>
9 #include <linux/export.h>
11 #include <linux/iopoll.h>
12 #include <linux/slab.h>
13 #include <asm/div64.h>
18 #define CLKMUX_BYPASS BIT(2)
19 #define CLKMUX_EN BIT(1)
20 #define POWERUP_MASK BIT(0)
22 #define PLL_ANA_PRG 0x10
23 #define PLL_SPREAD_SPECTRUM 0x30
25 #define PLL_NUMERATOR 0x40
26 #define PLL_MFN_MASK GENMASK(31, 2)
28 #define PLL_DENOMINATOR 0x50
29 #define PLL_MFD_MASK GENMASK(29, 0)
32 #define PLL_MFI_MASK GENMASK(24, 16)
33 #define PLL_RDIV_MASK GENMASK(15, 13)
34 #define PLL_ODIV_MASK GENMASK(7, 0)
36 #define PLL_DFS_CTRL(x) (0x70 + (x) * 0x10)
38 #define PLL_STATUS 0xF0
39 #define LOCK_STATUS BIT(0)
41 #define DFS_STATUS 0xF4
43 #define LOCK_TIMEOUT_US 200
45 #define PLL_FRACN_GP(_rate, _mfi, _mfn, _mfd, _rdiv, _odiv) \
55 struct clk_fracn_gppll {
58 const struct imx_fracn_gppll_rate_table *rate_table;
63 * Fvco = Fref * (MFI + MFN / MFD)
64 * Fout = Fvco / (rdiv * odiv)
66 static const struct imx_fracn_gppll_rate_table fracn_tbl[] = {
67 PLL_FRACN_GP(650000000U, 81, 0, 0, 0, 3),
68 PLL_FRACN_GP(594000000U, 198, 0, 0, 0, 8),
69 PLL_FRACN_GP(560000000U, 70, 0, 0, 0, 3),
70 PLL_FRACN_GP(400000000U, 50, 0, 0, 0, 3),
71 PLL_FRACN_GP(393216000U, 81, 92, 100, 0, 5)
74 struct imx_fracn_gppll_clk imx_fracn_gppll = {
75 .rate_table = fracn_tbl,
76 .rate_count = ARRAY_SIZE(fracn_tbl),
78 EXPORT_SYMBOL_GPL(imx_fracn_gppll);
80 static inline struct clk_fracn_gppll *to_clk_fracn_gppll(struct clk_hw *hw)
82 return container_of(hw, struct clk_fracn_gppll, hw);
85 static const struct imx_fracn_gppll_rate_table *
86 imx_get_pll_settings(struct clk_fracn_gppll *pll, unsigned long rate)
88 const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
91 for (i = 0; i < pll->rate_count; i++)
92 if (rate == rate_table[i].rate)
93 return &rate_table[i];
98 static long clk_fracn_gppll_round_rate(struct clk_hw *hw, unsigned long rate,
101 struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
102 const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
105 /* Assuming rate_table is in descending order */
106 for (i = 0; i < pll->rate_count; i++)
107 if (rate >= rate_table[i].rate)
108 return rate_table[i].rate;
110 /* return minimum supported value */
111 return rate_table[pll->rate_count - 1].rate;
114 static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
116 struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
117 const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
118 u32 pll_numerator, pll_denominator, pll_div;
119 u32 mfi, mfn, mfd, rdiv, odiv;
120 u64 fvco = parent_rate;
124 pll_numerator = readl_relaxed(pll->base + PLL_NUMERATOR);
125 mfn = FIELD_GET(PLL_MFN_MASK, pll_numerator);
127 pll_denominator = readl_relaxed(pll->base + PLL_DENOMINATOR);
128 mfd = FIELD_GET(PLL_MFD_MASK, pll_denominator);
130 pll_div = readl_relaxed(pll->base + PLL_DIV);
131 mfi = FIELD_GET(PLL_MFI_MASK, pll_div);
133 rdiv = FIELD_GET(PLL_RDIV_MASK, pll_div);
135 odiv = FIELD_GET(PLL_ODIV_MASK, pll_div);
148 * Sometimes, the recalculated rate has deviation due to
149 * the frac part. So find the accurate pll rate from the table
150 * first, if no match rate in the table, use the rate calculated
151 * from the equation below.
153 for (i = 0; i < pll->rate_count; i++) {
154 if (rate_table[i].mfn == mfn && rate_table[i].mfi == mfi &&
155 rate_table[i].mfd == mfd && rate_table[i].rdiv == rdiv &&
156 rate_table[i].odiv == odiv)
157 rate = rate_table[i].rate;
161 return (unsigned long)rate;
163 /* Fvco = Fref * (MFI + MFN / MFD) */
164 fvco = fvco * mfi * mfd + fvco * mfn;
165 do_div(fvco, mfd * rdiv * odiv);
167 return (unsigned long)fvco;
170 static int clk_fracn_gppll_wait_lock(struct clk_fracn_gppll *pll)
174 return readl_poll_timeout(pll->base + PLL_STATUS, val,
175 val & LOCK_STATUS, 0, LOCK_TIMEOUT_US);
178 static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
181 struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
182 const struct imx_fracn_gppll_rate_table *rate;
183 u32 tmp, pll_div, ana_mfn;
186 rate = imx_get_pll_settings(pll, drate);
189 tmp = readl_relaxed(pll->base + PLL_CTRL);
191 writel_relaxed(tmp, pll->base + PLL_CTRL);
194 tmp &= ~POWERUP_MASK;
195 writel_relaxed(tmp, pll->base + PLL_CTRL);
198 tmp &= ~CLKMUX_BYPASS;
199 writel_relaxed(tmp, pll->base + PLL_CTRL);
201 pll_div = FIELD_PREP(PLL_RDIV_MASK, rate->rdiv) | rate->odiv |
202 FIELD_PREP(PLL_MFI_MASK, rate->mfi);
203 writel_relaxed(pll_div, pll->base + PLL_DIV);
204 writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR);
205 writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR);
207 /* Wait for 5us according to fracn mode pll doc */
212 writel_relaxed(tmp, pll->base + PLL_CTRL);
215 ret = clk_fracn_gppll_wait_lock(pll);
221 writel_relaxed(tmp, pll->base + PLL_CTRL);
223 ana_mfn = readl_relaxed(pll->base + PLL_STATUS);
224 ana_mfn = FIELD_GET(PLL_MFN_MASK, ana_mfn);
226 WARN(ana_mfn != rate->mfn, "ana_mfn != rate->mfn\n");
231 static int clk_fracn_gppll_prepare(struct clk_hw *hw)
233 struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
237 val = readl_relaxed(pll->base + PLL_CTRL);
238 if (val & POWERUP_MASK)
241 val |= CLKMUX_BYPASS;
242 writel_relaxed(val, pll->base + PLL_CTRL);
245 writel_relaxed(val, pll->base + PLL_CTRL);
248 writel_relaxed(val, pll->base + PLL_CTRL);
250 ret = clk_fracn_gppll_wait_lock(pll);
254 val &= ~CLKMUX_BYPASS;
255 writel_relaxed(val, pll->base + PLL_CTRL);
260 static int clk_fracn_gppll_is_prepared(struct clk_hw *hw)
262 struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
265 val = readl_relaxed(pll->base + PLL_CTRL);
267 return (val & POWERUP_MASK) ? 1 : 0;
270 static void clk_fracn_gppll_unprepare(struct clk_hw *hw)
272 struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
275 val = readl_relaxed(pll->base + PLL_CTRL);
276 val &= ~POWERUP_MASK;
277 writel_relaxed(val, pll->base + PLL_CTRL);
280 static const struct clk_ops clk_fracn_gppll_ops = {
281 .prepare = clk_fracn_gppll_prepare,
282 .unprepare = clk_fracn_gppll_unprepare,
283 .is_prepared = clk_fracn_gppll_is_prepared,
284 .recalc_rate = clk_fracn_gppll_recalc_rate,
285 .round_rate = clk_fracn_gppll_round_rate,
286 .set_rate = clk_fracn_gppll_set_rate,
289 struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
290 const struct imx_fracn_gppll_clk *pll_clk)
292 struct clk_fracn_gppll *pll;
294 struct clk_init_data init;
297 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
299 return ERR_PTR(-ENOMEM);
302 init.flags = pll_clk->flags;
303 init.parent_names = &parent_name;
304 init.num_parents = 1;
305 init.ops = &clk_fracn_gppll_ops;
308 pll->hw.init = &init;
309 pll->rate_table = pll_clk->rate_table;
310 pll->rate_count = pll_clk->rate_count;
314 ret = clk_hw_register(NULL, hw);
316 pr_err("%s: failed to register pll %s %d\n", __func__, name, ret);
323 EXPORT_SYMBOL_GPL(imx_clk_fracn_gppll);