Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Spreadtrum pll clock driver
0004 //
0005 // Copyright (C) 2015~2017 Spreadtrum, Inc.
0006 // Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
0007 
0008 #include <linux/delay.h>
0009 #include <linux/err.h>
0010 #include <linux/regmap.h>
0011 #include <linux/slab.h>
0012 
0013 #include "pll.h"
0014 
0015 #define CLK_PLL_1M  1000000
0016 #define CLK_PLL_10M (CLK_PLL_1M * 10)
0017 
0018 #define pindex(pll, member)     \
0019     (pll->factors[member].shift / (8 * sizeof(pll->regs_num)))
0020 
0021 #define pshift(pll, member)     \
0022     (pll->factors[member].shift % (8 * sizeof(pll->regs_num)))
0023 
0024 #define pwidth(pll, member)     \
0025     pll->factors[member].width
0026 
0027 #define pmask(pll, member)                  \
0028     ((pwidth(pll, member)) ?                \
0029     GENMASK(pwidth(pll, member) + pshift(pll, member) - 1,  \
0030     pshift(pll, member)) : 0)
0031 
0032 #define pinternal(pll, cfg, member) \
0033     (cfg[pindex(pll, member)] & pmask(pll, member))
0034 
0035 #define pinternal_val(pll, cfg, member) \
0036     (pinternal(pll, cfg, member) >> pshift(pll, member))
0037 
0038 static inline unsigned int
0039 sprd_pll_read(const struct sprd_pll *pll, u8 index)
0040 {
0041     const struct sprd_clk_common *common = &pll->common;
0042     unsigned int val = 0;
0043 
0044     if (WARN_ON(index >= pll->regs_num))
0045         return 0;
0046 
0047     regmap_read(common->regmap, common->reg + index * 4, &val);
0048 
0049     return val;
0050 }
0051 
0052 static inline void
0053 sprd_pll_write(const struct sprd_pll *pll, u8 index,
0054                   u32 msk, u32 val)
0055 {
0056     const struct sprd_clk_common *common = &pll->common;
0057     unsigned int offset, reg;
0058     int ret = 0;
0059 
0060     if (WARN_ON(index >= pll->regs_num))
0061         return;
0062 
0063     offset = common->reg + index * 4;
0064     ret = regmap_read(common->regmap, offset, &reg);
0065     if (!ret)
0066         regmap_write(common->regmap, offset, (reg & ~msk) | val);
0067 }
0068 
0069 static unsigned long pll_get_refin(const struct sprd_pll *pll)
0070 {
0071     u32 shift, mask, index, refin_id = 3;
0072     const unsigned long refin[4] = { 2, 4, 13, 26 };
0073 
0074     if (pwidth(pll, PLL_REFIN)) {
0075         index = pindex(pll, PLL_REFIN);
0076         shift = pshift(pll, PLL_REFIN);
0077         mask = pmask(pll, PLL_REFIN);
0078         refin_id = (sprd_pll_read(pll, index) & mask) >> shift;
0079         if (refin_id > 3)
0080             refin_id = 3;
0081     }
0082 
0083     return refin[refin_id];
0084 }
0085 
0086 static u32 pll_get_ibias(u64 rate, const u64 *table)
0087 {
0088     u32 i, num = table[0];
0089 
0090     /* table[0] indicates the number of items in this table */
0091     for (i = 0; i < num; i++)
0092         if (rate <= table[i + 1])
0093             break;
0094 
0095     return i == num ? num - 1 : i;
0096 }
0097 
0098 static unsigned long _sprd_pll_recalc_rate(const struct sprd_pll *pll,
0099                        unsigned long parent_rate)
0100 {
0101     u32 *cfg;
0102     u32 i, mask, regs_num = pll->regs_num;
0103     unsigned long rate, nint, kint = 0;
0104     u64 refin;
0105     u16 k1, k2;
0106 
0107     cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL);
0108     if (!cfg)
0109         return parent_rate;
0110 
0111     for (i = 0; i < regs_num; i++)
0112         cfg[i] = sprd_pll_read(pll, i);
0113 
0114     refin = pll_get_refin(pll);
0115 
0116     if (pinternal(pll, cfg, PLL_PREDIV))
0117         refin = refin * 2;
0118 
0119     if (pwidth(pll, PLL_POSTDIV) &&
0120         ((pll->fflag == 1 && pinternal(pll, cfg, PLL_POSTDIV)) ||
0121          (!pll->fflag && !pinternal(pll, cfg, PLL_POSTDIV))))
0122         refin = refin / 2;
0123 
0124     if (!pinternal(pll, cfg, PLL_DIV_S)) {
0125         rate = refin * pinternal_val(pll, cfg, PLL_N) * CLK_PLL_10M;
0126     } else {
0127         nint = pinternal_val(pll, cfg, PLL_NINT);
0128         if (pinternal(pll, cfg, PLL_SDM_EN))
0129             kint = pinternal_val(pll, cfg, PLL_KINT);
0130 
0131         mask = pmask(pll, PLL_KINT);
0132 
0133         k1 = pll->k1;
0134         k2 = pll->k2;
0135         rate = DIV_ROUND_CLOSEST_ULL(refin * kint * k1,
0136                      ((mask >> __ffs(mask)) + 1)) *
0137                      k2 + refin * nint * CLK_PLL_1M;
0138     }
0139 
0140     kfree(cfg);
0141     return rate;
0142 }
0143 
0144 #define SPRD_PLL_WRITE_CHECK(pll, i, mask, val)     \
0145     (((sprd_pll_read(pll, i) & mask) == val) ? 0 : (-EFAULT))
0146 
0147 static int _sprd_pll_set_rate(const struct sprd_pll *pll,
0148                   unsigned long rate,
0149                   unsigned long parent_rate)
0150 {
0151     struct reg_cfg *cfg;
0152     int ret = 0;
0153     u32 mask, shift, width, ibias_val, index;
0154     u32 regs_num = pll->regs_num, i = 0;
0155     unsigned long kint, nint;
0156     u64 tmp, refin, fvco = rate;
0157 
0158     cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL);
0159     if (!cfg)
0160         return -ENOMEM;
0161 
0162     refin = pll_get_refin(pll);
0163 
0164     mask = pmask(pll, PLL_PREDIV);
0165     index = pindex(pll, PLL_PREDIV);
0166     width = pwidth(pll, PLL_PREDIV);
0167     if (width && (sprd_pll_read(pll, index) & mask))
0168         refin = refin * 2;
0169 
0170     mask = pmask(pll, PLL_POSTDIV);
0171     index = pindex(pll, PLL_POSTDIV);
0172     width = pwidth(pll, PLL_POSTDIV);
0173     cfg[index].msk = mask;
0174     if (width && ((pll->fflag == 1 && fvco <= pll->fvco) ||
0175               (pll->fflag == 0 && fvco > pll->fvco)))
0176         cfg[index].val |= mask;
0177 
0178     if (width && fvco <= pll->fvco)
0179         fvco = fvco * 2;
0180 
0181     mask = pmask(pll, PLL_DIV_S);
0182     index = pindex(pll, PLL_DIV_S);
0183     cfg[index].val |= mask;
0184     cfg[index].msk |= mask;
0185 
0186     mask = pmask(pll, PLL_SDM_EN);
0187     index = pindex(pll, PLL_SDM_EN);
0188     cfg[index].val |= mask;
0189     cfg[index].msk |= mask;
0190 
0191     nint = do_div(fvco, refin * CLK_PLL_1M);
0192     mask = pmask(pll, PLL_NINT);
0193     index = pindex(pll, PLL_NINT);
0194     shift = pshift(pll, PLL_NINT);
0195     cfg[index].val |= (nint << shift) & mask;
0196     cfg[index].msk |= mask;
0197 
0198     mask = pmask(pll, PLL_KINT);
0199     index = pindex(pll, PLL_KINT);
0200     width = pwidth(pll, PLL_KINT);
0201     shift = pshift(pll, PLL_KINT);
0202     tmp = fvco - refin * nint * CLK_PLL_1M;
0203     tmp = do_div(tmp, 10000) * ((mask >> shift) + 1);
0204     kint = DIV_ROUND_CLOSEST_ULL(tmp, refin * 100);
0205     cfg[index].val |= (kint << shift) & mask;
0206     cfg[index].msk |= mask;
0207 
0208     ibias_val = pll_get_ibias(fvco, pll->itable);
0209 
0210     mask = pmask(pll, PLL_IBIAS);
0211     index = pindex(pll, PLL_IBIAS);
0212     shift = pshift(pll, PLL_IBIAS);
0213     cfg[index].val |= ibias_val << shift & mask;
0214     cfg[index].msk |= mask;
0215 
0216     for (i = 0; i < regs_num; i++) {
0217         if (cfg[i].msk) {
0218             sprd_pll_write(pll, i, cfg[i].msk, cfg[i].val);
0219             ret |= SPRD_PLL_WRITE_CHECK(pll, i, cfg[i].msk,
0220                            cfg[i].val);
0221         }
0222     }
0223 
0224     if (!ret)
0225         udelay(pll->udelay);
0226 
0227     kfree(cfg);
0228     return ret;
0229 }
0230 
0231 static unsigned long sprd_pll_recalc_rate(struct clk_hw *hw,
0232                       unsigned long parent_rate)
0233 {
0234     struct sprd_pll *pll = hw_to_sprd_pll(hw);
0235 
0236     return _sprd_pll_recalc_rate(pll, parent_rate);
0237 }
0238 
0239 static int sprd_pll_set_rate(struct clk_hw *hw,
0240                  unsigned long rate,
0241                  unsigned long parent_rate)
0242 {
0243     struct sprd_pll *pll = hw_to_sprd_pll(hw);
0244 
0245     return _sprd_pll_set_rate(pll, rate, parent_rate);
0246 }
0247 
0248 static int sprd_pll_clk_prepare(struct clk_hw *hw)
0249 {
0250     struct sprd_pll *pll = hw_to_sprd_pll(hw);
0251 
0252     udelay(pll->udelay);
0253 
0254     return 0;
0255 }
0256 
0257 static long sprd_pll_round_rate(struct clk_hw *hw, unsigned long rate,
0258                 unsigned long *prate)
0259 {
0260     return rate;
0261 }
0262 
0263 const struct clk_ops sprd_pll_ops = {
0264     .prepare = sprd_pll_clk_prepare,
0265     .recalc_rate = sprd_pll_recalc_rate,
0266     .round_rate = sprd_pll_round_rate,
0267     .set_rate = sprd_pll_set_rate,
0268 };
0269 EXPORT_SYMBOL_GPL(sprd_pll_ops);