Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright 2021 NXP
0004  */
0005 
0006 #include <linux/bitfield.h>
0007 #include <linux/clk-provider.h>
0008 #include <linux/err.h>
0009 #include <linux/export.h>
0010 #include <linux/io.h>
0011 #include <linux/iopoll.h>
0012 #include <linux/slab.h>
0013 #include <asm/div64.h>
0014 
0015 #include "clk.h"
0016 
0017 #define PLL_CTRL        0x0
0018 #define CLKMUX_BYPASS       BIT(2)
0019 #define CLKMUX_EN       BIT(1)
0020 #define POWERUP_MASK        BIT(0)
0021 
0022 #define PLL_ANA_PRG     0x10
0023 #define PLL_SPREAD_SPECTRUM 0x30
0024 
0025 #define PLL_NUMERATOR       0x40
0026 #define PLL_MFN_MASK        GENMASK(31, 2)
0027 
0028 #define PLL_DENOMINATOR     0x50
0029 #define PLL_MFD_MASK        GENMASK(29, 0)
0030 
0031 #define PLL_DIV         0x60
0032 #define PLL_MFI_MASK        GENMASK(24, 16)
0033 #define PLL_RDIV_MASK       GENMASK(15, 13)
0034 #define PLL_ODIV_MASK       GENMASK(7, 0)
0035 
0036 #define PLL_DFS_CTRL(x)     (0x70 + (x) * 0x10)
0037 
0038 #define PLL_STATUS      0xF0
0039 #define LOCK_STATUS     BIT(0)
0040 
0041 #define DFS_STATUS      0xF4
0042 
0043 #define LOCK_TIMEOUT_US     200
0044 
0045 #define PLL_FRACN_GP(_rate, _mfi, _mfn, _mfd, _rdiv, _odiv) \
0046     {                           \
0047         .rate   =   (_rate),            \
0048         .mfi    =   (_mfi),             \
0049         .mfn    =   (_mfn),             \
0050         .mfd    =   (_mfd),             \
0051         .rdiv   =   (_rdiv),            \
0052         .odiv   =   (_odiv),            \
0053     }
0054 
0055 struct clk_fracn_gppll {
0056     struct clk_hw           hw;
0057     void __iomem            *base;
0058     const struct imx_fracn_gppll_rate_table *rate_table;
0059     int rate_count;
0060 };
0061 
0062 /*
0063  * Fvco = Fref * (MFI + MFN / MFD)
0064  * Fout = Fvco / (rdiv * odiv)
0065  */
0066 static const struct imx_fracn_gppll_rate_table fracn_tbl[] = {
0067     PLL_FRACN_GP(650000000U, 81, 0, 1, 0, 3),
0068     PLL_FRACN_GP(594000000U, 198, 0, 1, 0, 8),
0069     PLL_FRACN_GP(560000000U, 70, 0, 1, 0, 3),
0070     PLL_FRACN_GP(498000000U, 83, 0, 1, 0, 4),
0071     PLL_FRACN_GP(484000000U, 121, 0, 1, 0, 6),
0072     PLL_FRACN_GP(445333333U, 167, 0, 1, 0, 9),
0073     PLL_FRACN_GP(400000000U, 50, 0, 1, 0, 3),
0074     PLL_FRACN_GP(393216000U, 81, 92, 100, 0, 5)
0075 };
0076 
0077 struct imx_fracn_gppll_clk imx_fracn_gppll = {
0078     .rate_table = fracn_tbl,
0079     .rate_count = ARRAY_SIZE(fracn_tbl),
0080 };
0081 EXPORT_SYMBOL_GPL(imx_fracn_gppll);
0082 
0083 static inline struct clk_fracn_gppll *to_clk_fracn_gppll(struct clk_hw *hw)
0084 {
0085     return container_of(hw, struct clk_fracn_gppll, hw);
0086 }
0087 
0088 static const struct imx_fracn_gppll_rate_table *
0089 imx_get_pll_settings(struct clk_fracn_gppll *pll, unsigned long rate)
0090 {
0091     const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
0092     int i;
0093 
0094     for (i = 0; i < pll->rate_count; i++)
0095         if (rate == rate_table[i].rate)
0096             return &rate_table[i];
0097 
0098     return NULL;
0099 }
0100 
0101 static long clk_fracn_gppll_round_rate(struct clk_hw *hw, unsigned long rate,
0102                        unsigned long *prate)
0103 {
0104     struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
0105     const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
0106     int i;
0107 
0108     /* Assuming rate_table is in descending order */
0109     for (i = 0; i < pll->rate_count; i++)
0110         if (rate >= rate_table[i].rate)
0111             return rate_table[i].rate;
0112 
0113     /* return minimum supported value */
0114     return rate_table[pll->rate_count - 1].rate;
0115 }
0116 
0117 static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
0118 {
0119     struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
0120     const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
0121     u32 pll_numerator, pll_denominator, pll_div;
0122     u32 mfi, mfn, mfd, rdiv, odiv;
0123     u64 fvco = parent_rate;
0124     long rate = 0;
0125     int i;
0126 
0127     pll_numerator = readl_relaxed(pll->base + PLL_NUMERATOR);
0128     mfn = FIELD_GET(PLL_MFN_MASK, pll_numerator);
0129 
0130     pll_denominator = readl_relaxed(pll->base + PLL_DENOMINATOR);
0131     mfd = FIELD_GET(PLL_MFD_MASK, pll_denominator);
0132 
0133     pll_div = readl_relaxed(pll->base + PLL_DIV);
0134     mfi = FIELD_GET(PLL_MFI_MASK, pll_div);
0135 
0136     rdiv = FIELD_GET(PLL_RDIV_MASK, pll_div);
0137     odiv = FIELD_GET(PLL_ODIV_MASK, pll_div);
0138 
0139     /*
0140      * Sometimes, the recalculated rate has deviation due to
0141      * the frac part. So find the accurate pll rate from the table
0142      * first, if no match rate in the table, use the rate calculated
0143      * from the equation below.
0144      */
0145     for (i = 0; i < pll->rate_count; i++) {
0146         if (rate_table[i].mfn == mfn && rate_table[i].mfi == mfi &&
0147             rate_table[i].mfd == mfd && rate_table[i].rdiv == rdiv &&
0148             rate_table[i].odiv == odiv)
0149             rate = rate_table[i].rate;
0150     }
0151 
0152     if (rate)
0153         return (unsigned long)rate;
0154 
0155     if (!rdiv)
0156         rdiv = rdiv + 1;
0157 
0158     switch (odiv) {
0159     case 0:
0160         odiv = 2;
0161         break;
0162     case 1:
0163         odiv = 3;
0164         break;
0165     default:
0166         break;
0167     }
0168 
0169     /* Fvco = Fref * (MFI + MFN / MFD) */
0170     fvco = fvco * mfi * mfd + fvco * mfn;
0171     do_div(fvco, mfd * rdiv * odiv);
0172 
0173     return (unsigned long)fvco;
0174 }
0175 
0176 static int clk_fracn_gppll_wait_lock(struct clk_fracn_gppll *pll)
0177 {
0178     u32 val;
0179 
0180     return readl_poll_timeout(pll->base + PLL_STATUS, val,
0181                   val & LOCK_STATUS, 0, LOCK_TIMEOUT_US);
0182 }
0183 
0184 static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
0185                     unsigned long prate)
0186 {
0187     struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
0188     const struct imx_fracn_gppll_rate_table *rate;
0189     u32 tmp, pll_div, ana_mfn;
0190     int ret;
0191 
0192     rate = imx_get_pll_settings(pll, drate);
0193 
0194     /* Disable output */
0195     tmp = readl_relaxed(pll->base + PLL_CTRL);
0196     tmp &= ~CLKMUX_EN;
0197     writel_relaxed(tmp, pll->base + PLL_CTRL);
0198 
0199     /* Power Down */
0200     tmp &= ~POWERUP_MASK;
0201     writel_relaxed(tmp, pll->base + PLL_CTRL);
0202 
0203     /* Disable BYPASS */
0204     tmp &= ~CLKMUX_BYPASS;
0205     writel_relaxed(tmp, pll->base + PLL_CTRL);
0206 
0207     pll_div = FIELD_PREP(PLL_RDIV_MASK, rate->rdiv) | rate->odiv |
0208         FIELD_PREP(PLL_MFI_MASK, rate->mfi);
0209     writel_relaxed(pll_div, pll->base + PLL_DIV);
0210     writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR);
0211     writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR);
0212 
0213     /* Wait for 5us according to fracn mode pll doc */
0214     udelay(5);
0215 
0216     /* Enable Powerup */
0217     tmp |= POWERUP_MASK;
0218     writel_relaxed(tmp, pll->base + PLL_CTRL);
0219 
0220     /* Wait Lock */
0221     ret = clk_fracn_gppll_wait_lock(pll);
0222     if (ret)
0223         return ret;
0224 
0225     /* Enable output */
0226     tmp |= CLKMUX_EN;
0227     writel_relaxed(tmp, pll->base + PLL_CTRL);
0228 
0229     ana_mfn = readl_relaxed(pll->base + PLL_STATUS);
0230     ana_mfn = FIELD_GET(PLL_MFN_MASK, ana_mfn);
0231 
0232     WARN(ana_mfn != rate->mfn, "ana_mfn != rate->mfn\n");
0233 
0234     return 0;
0235 }
0236 
0237 static int clk_fracn_gppll_prepare(struct clk_hw *hw)
0238 {
0239     struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
0240     u32 val;
0241     int ret;
0242 
0243     val = readl_relaxed(pll->base + PLL_CTRL);
0244     if (val & POWERUP_MASK)
0245         return 0;
0246 
0247     val |= CLKMUX_BYPASS;
0248     writel_relaxed(val, pll->base + PLL_CTRL);
0249 
0250     val |= POWERUP_MASK;
0251     writel_relaxed(val, pll->base + PLL_CTRL);
0252 
0253     val |= CLKMUX_EN;
0254     writel_relaxed(val, pll->base + PLL_CTRL);
0255 
0256     ret = clk_fracn_gppll_wait_lock(pll);
0257     if (ret)
0258         return ret;
0259 
0260     val &= ~CLKMUX_BYPASS;
0261     writel_relaxed(val, pll->base + PLL_CTRL);
0262 
0263     return 0;
0264 }
0265 
0266 static int clk_fracn_gppll_is_prepared(struct clk_hw *hw)
0267 {
0268     struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
0269     u32 val;
0270 
0271     val = readl_relaxed(pll->base + PLL_CTRL);
0272 
0273     return (val & POWERUP_MASK) ? 1 : 0;
0274 }
0275 
0276 static void clk_fracn_gppll_unprepare(struct clk_hw *hw)
0277 {
0278     struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
0279     u32 val;
0280 
0281     val = readl_relaxed(pll->base + PLL_CTRL);
0282     val &= ~POWERUP_MASK;
0283     writel_relaxed(val, pll->base + PLL_CTRL);
0284 }
0285 
0286 static const struct clk_ops clk_fracn_gppll_ops = {
0287     .prepare    = clk_fracn_gppll_prepare,
0288     .unprepare  = clk_fracn_gppll_unprepare,
0289     .is_prepared    = clk_fracn_gppll_is_prepared,
0290     .recalc_rate    = clk_fracn_gppll_recalc_rate,
0291     .round_rate = clk_fracn_gppll_round_rate,
0292     .set_rate   = clk_fracn_gppll_set_rate,
0293 };
0294 
0295 struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
0296                    const struct imx_fracn_gppll_clk *pll_clk)
0297 {
0298     struct clk_fracn_gppll *pll;
0299     struct clk_hw *hw;
0300     struct clk_init_data init;
0301     int ret;
0302 
0303     pll = kzalloc(sizeof(*pll), GFP_KERNEL);
0304     if (!pll)
0305         return ERR_PTR(-ENOMEM);
0306 
0307     init.name = name;
0308     init.flags = pll_clk->flags;
0309     init.parent_names = &parent_name;
0310     init.num_parents = 1;
0311     init.ops = &clk_fracn_gppll_ops;
0312 
0313     pll->base = base;
0314     pll->hw.init = &init;
0315     pll->rate_table = pll_clk->rate_table;
0316     pll->rate_count = pll_clk->rate_count;
0317 
0318     hw = &pll->hw;
0319 
0320     ret = clk_hw_register(NULL, hw);
0321     if (ret) {
0322         pr_err("%s: failed to register pll %s %d\n", __func__, name, ret);
0323         kfree(pll);
0324         return ERR_PTR(ret);
0325     }
0326 
0327     return hw;
0328 }
0329 EXPORT_SYMBOL_GPL(imx_clk_fracn_gppll);