root/drivers/clk/sprd/pll.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sprd_pll_read
  2. sprd_pll_write
  3. pll_get_refin
  4. pll_get_ibias
  5. _sprd_pll_recalc_rate
  6. _sprd_pll_set_rate
  7. sprd_pll_recalc_rate
  8. sprd_pll_set_rate
  9. sprd_pll_clk_prepare
  10. sprd_pll_round_rate

   1 // SPDX-License-Identifier: GPL-2.0
   2 //
   3 // Spreadtrum pll clock driver
   4 //
   5 // Copyright (C) 2015~2017 Spreadtrum, Inc.
   6 // Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
   7 
   8 #include <linux/delay.h>
   9 #include <linux/err.h>
  10 #include <linux/regmap.h>
  11 #include <linux/slab.h>
  12 
  13 #include "pll.h"
  14 
  15 #define CLK_PLL_1M      1000000
  16 #define CLK_PLL_10M     (CLK_PLL_1M * 10)
  17 
  18 #define pindex(pll, member)             \
  19         (pll->factors[member].shift / (8 * sizeof(pll->regs_num)))
  20 
  21 #define pshift(pll, member)             \
  22         (pll->factors[member].shift % (8 * sizeof(pll->regs_num)))
  23 
  24 #define pwidth(pll, member)             \
  25         pll->factors[member].width
  26 
  27 #define pmask(pll, member)                                      \
  28         ((pwidth(pll, member)) ?                                \
  29         GENMASK(pwidth(pll, member) + pshift(pll, member) - 1,  \
  30         pshift(pll, member)) : 0)
  31 
  32 #define pinternal(pll, cfg, member)     \
  33         (cfg[pindex(pll, member)] & pmask(pll, member))
  34 
  35 #define pinternal_val(pll, cfg, member) \
  36         (pinternal(pll, cfg, member) >> pshift(pll, member))
  37 
  38 static inline unsigned int
  39 sprd_pll_read(const struct sprd_pll *pll, u8 index)
  40 {
  41         const struct sprd_clk_common *common = &pll->common;
  42         unsigned int val = 0;
  43 
  44         if (WARN_ON(index >= pll->regs_num))
  45                 return 0;
  46 
  47         regmap_read(common->regmap, common->reg + index * 4, &val);
  48 
  49         return val;
  50 }
  51 
  52 static inline void
  53 sprd_pll_write(const struct sprd_pll *pll, u8 index,
  54                                   u32 msk, u32 val)
  55 {
  56         const struct sprd_clk_common *common = &pll->common;
  57         unsigned int offset, reg;
  58         int ret = 0;
  59 
  60         if (WARN_ON(index >= pll->regs_num))
  61                 return;
  62 
  63         offset = common->reg + index * 4;
  64         ret = regmap_read(common->regmap, offset, &reg);
  65         if (!ret)
  66                 regmap_write(common->regmap, offset, (reg & ~msk) | val);
  67 }
  68 
  69 static unsigned long pll_get_refin(const struct sprd_pll *pll)
  70 {
  71         u32 shift, mask, index, refin_id = 3;
  72         const unsigned long refin[4] = { 2, 4, 13, 26 };
  73 
  74         if (pwidth(pll, PLL_REFIN)) {
  75                 index = pindex(pll, PLL_REFIN);
  76                 shift = pshift(pll, PLL_REFIN);
  77                 mask = pmask(pll, PLL_REFIN);
  78                 refin_id = (sprd_pll_read(pll, index) & mask) >> shift;
  79                 if (refin_id > 3)
  80                         refin_id = 3;
  81         }
  82 
  83         return refin[refin_id];
  84 }
  85 
  86 static u32 pll_get_ibias(u64 rate, const u64 *table)
  87 {
  88         u32 i, num = table[0];
  89 
  90         for (i = 1; i < num + 1; i++)
  91                 if (rate <= table[i])
  92                         break;
  93 
  94         return (i == num + 1) ? num : i;
  95 }
  96 
  97 static unsigned long _sprd_pll_recalc_rate(const struct sprd_pll *pll,
  98                                            unsigned long parent_rate)
  99 {
 100         u32 *cfg;
 101         u32 i, mask, regs_num = pll->regs_num;
 102         unsigned long rate, nint, kint = 0;
 103         u64 refin;
 104         u16 k1, k2;
 105 
 106         cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL);
 107         if (!cfg)
 108                 return -ENOMEM;
 109 
 110         for (i = 0; i < regs_num; i++)
 111                 cfg[i] = sprd_pll_read(pll, i);
 112 
 113         refin = pll_get_refin(pll);
 114 
 115         if (pinternal(pll, cfg, PLL_PREDIV))
 116                 refin = refin * 2;
 117 
 118         if (pwidth(pll, PLL_POSTDIV) &&
 119             ((pll->fflag == 1 && pinternal(pll, cfg, PLL_POSTDIV)) ||
 120              (!pll->fflag && !pinternal(pll, cfg, PLL_POSTDIV))))
 121                 refin = refin / 2;
 122 
 123         if (!pinternal(pll, cfg, PLL_DIV_S)) {
 124                 rate = refin * pinternal_val(pll, cfg, PLL_N) * CLK_PLL_10M;
 125         } else {
 126                 nint = pinternal_val(pll, cfg, PLL_NINT);
 127                 if (pinternal(pll, cfg, PLL_SDM_EN))
 128                         kint = pinternal_val(pll, cfg, PLL_KINT);
 129 
 130                 mask = pmask(pll, PLL_KINT);
 131 
 132                 k1 = pll->k1;
 133                 k2 = pll->k2;
 134                 rate = DIV_ROUND_CLOSEST_ULL(refin * kint * k1,
 135                                          ((mask >> __ffs(mask)) + 1)) *
 136                                          k2 + refin * nint * CLK_PLL_1M;
 137         }
 138 
 139         kfree(cfg);
 140         return rate;
 141 }
 142 
 143 #define SPRD_PLL_WRITE_CHECK(pll, i, mask, val)         \
 144         (((sprd_pll_read(pll, i) & mask) == val) ? 0 : (-EFAULT))
 145 
 146 static int _sprd_pll_set_rate(const struct sprd_pll *pll,
 147                               unsigned long rate,
 148                               unsigned long parent_rate)
 149 {
 150         struct reg_cfg *cfg;
 151         int ret = 0;
 152         u32 mask, shift, width, ibias_val, index;
 153         u32 regs_num = pll->regs_num, i = 0;
 154         unsigned long kint, nint;
 155         u64 tmp, refin, fvco = rate;
 156 
 157         cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL);
 158         if (!cfg)
 159                 return -ENOMEM;
 160 
 161         refin = pll_get_refin(pll);
 162 
 163         mask = pmask(pll, PLL_PREDIV);
 164         index = pindex(pll, PLL_PREDIV);
 165         width = pwidth(pll, PLL_PREDIV);
 166         if (width && (sprd_pll_read(pll, index) & mask))
 167                 refin = refin * 2;
 168 
 169         mask = pmask(pll, PLL_POSTDIV);
 170         index = pindex(pll, PLL_POSTDIV);
 171         width = pwidth(pll, PLL_POSTDIV);
 172         cfg[index].msk = mask;
 173         if (width && ((pll->fflag == 1 && fvco <= pll->fvco) ||
 174                       (pll->fflag == 0 && fvco > pll->fvco)))
 175                 cfg[index].val |= mask;
 176 
 177         if (width && fvco <= pll->fvco)
 178                 fvco = fvco * 2;
 179 
 180         mask = pmask(pll, PLL_DIV_S);
 181         index = pindex(pll, PLL_DIV_S);
 182         cfg[index].val |= mask;
 183         cfg[index].msk |= mask;
 184 
 185         mask = pmask(pll, PLL_SDM_EN);
 186         index = pindex(pll, PLL_SDM_EN);
 187         cfg[index].val |= mask;
 188         cfg[index].msk |= mask;
 189 
 190         nint = do_div(fvco, refin * CLK_PLL_1M);
 191         mask = pmask(pll, PLL_NINT);
 192         index = pindex(pll, PLL_NINT);
 193         shift = pshift(pll, PLL_NINT);
 194         cfg[index].val |= (nint << shift) & mask;
 195         cfg[index].msk |= mask;
 196 
 197         mask = pmask(pll, PLL_KINT);
 198         index = pindex(pll, PLL_KINT);
 199         width = pwidth(pll, PLL_KINT);
 200         shift = pshift(pll, PLL_KINT);
 201         tmp = fvco - refin * nint * CLK_PLL_1M;
 202         tmp = do_div(tmp, 10000) * ((mask >> shift) + 1);
 203         kint = DIV_ROUND_CLOSEST_ULL(tmp, refin * 100);
 204         cfg[index].val |= (kint << shift) & mask;
 205         cfg[index].msk |= mask;
 206 
 207         ibias_val = pll_get_ibias(fvco, pll->itable);
 208 
 209         mask = pmask(pll, PLL_IBIAS);
 210         index = pindex(pll, PLL_IBIAS);
 211         shift = pshift(pll, PLL_IBIAS);
 212         cfg[index].val |= ibias_val << shift & mask;
 213         cfg[index].msk |= mask;
 214 
 215         for (i = 0; i < regs_num; i++) {
 216                 if (cfg[i].msk) {
 217                         sprd_pll_write(pll, i, cfg[i].msk, cfg[i].val);
 218                         ret |= SPRD_PLL_WRITE_CHECK(pll, i, cfg[i].msk,
 219                                                    cfg[i].val);
 220                 }
 221         }
 222 
 223         if (!ret)
 224                 udelay(pll->udelay);
 225 
 226         kfree(cfg);
 227         return ret;
 228 }
 229 
 230 static unsigned long sprd_pll_recalc_rate(struct clk_hw *hw,
 231                                           unsigned long parent_rate)
 232 {
 233         struct sprd_pll *pll = hw_to_sprd_pll(hw);
 234 
 235         return _sprd_pll_recalc_rate(pll, parent_rate);
 236 }
 237 
 238 static int sprd_pll_set_rate(struct clk_hw *hw,
 239                              unsigned long rate,
 240                              unsigned long parent_rate)
 241 {
 242         struct sprd_pll *pll = hw_to_sprd_pll(hw);
 243 
 244         return _sprd_pll_set_rate(pll, rate, parent_rate);
 245 }
 246 
 247 static int sprd_pll_clk_prepare(struct clk_hw *hw)
 248 {
 249         struct sprd_pll *pll = hw_to_sprd_pll(hw);
 250 
 251         udelay(pll->udelay);
 252 
 253         return 0;
 254 }
 255 
 256 static long sprd_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 257                                 unsigned long *prate)
 258 {
 259         return rate;
 260 }
 261 
 262 const struct clk_ops sprd_pll_ops = {
 263         .prepare = sprd_pll_clk_prepare,
 264         .recalc_rate = sprd_pll_recalc_rate,
 265         .round_rate = sprd_pll_round_rate,
 266         .set_rate = sprd_pll_set_rate,
 267 };
 268 EXPORT_SYMBOL_GPL(sprd_pll_ops);

/* [<][>][^][v][top][bottom][index][help] */