root/drivers/video/fbdev/omap2/omapfb/dss/pll.c

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

DEFINITIONS

This source file includes following definitions.
  1. dss_pll_register
  2. dss_pll_unregister
  3. dss_pll_find
  4. dss_pll_enable
  5. dss_pll_disable
  6. dss_pll_set_config
  7. dss_pll_hsdiv_calc
  8. dss_pll_calc
  9. wait_for_bit_change
  10. dss_pll_wait_reset_done
  11. dss_wait_hsdiv_ack
  12. dss_pll_write_config_type_a
  13. dss_pll_write_config_type_b

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2014 Texas Instruments Incorporated
   4  */
   5 
   6 #define DSS_SUBSYS_NAME "PLL"
   7 
   8 #include <linux/clk.h>
   9 #include <linux/io.h>
  10 #include <linux/kernel.h>
  11 #include <linux/regulator/consumer.h>
  12 #include <linux/sched.h>
  13 
  14 #include <video/omapfb_dss.h>
  15 
  16 #include "dss.h"
  17 
  18 #define PLL_CONTROL                     0x0000
  19 #define PLL_STATUS                      0x0004
  20 #define PLL_GO                          0x0008
  21 #define PLL_CONFIGURATION1              0x000C
  22 #define PLL_CONFIGURATION2              0x0010
  23 #define PLL_CONFIGURATION3              0x0014
  24 #define PLL_SSC_CONFIGURATION1          0x0018
  25 #define PLL_SSC_CONFIGURATION2          0x001C
  26 #define PLL_CONFIGURATION4              0x0020
  27 
  28 static struct dss_pll *dss_plls[4];
  29 
  30 int dss_pll_register(struct dss_pll *pll)
  31 {
  32         int i;
  33 
  34         for (i = 0; i < ARRAY_SIZE(dss_plls); ++i) {
  35                 if (!dss_plls[i]) {
  36                         dss_plls[i] = pll;
  37                         return 0;
  38                 }
  39         }
  40 
  41         return -EBUSY;
  42 }
  43 
  44 void dss_pll_unregister(struct dss_pll *pll)
  45 {
  46         int i;
  47 
  48         for (i = 0; i < ARRAY_SIZE(dss_plls); ++i) {
  49                 if (dss_plls[i] == pll) {
  50                         dss_plls[i] = NULL;
  51                         return;
  52                 }
  53         }
  54 }
  55 
  56 struct dss_pll *dss_pll_find(const char *name)
  57 {
  58         int i;
  59 
  60         for (i = 0; i < ARRAY_SIZE(dss_plls); ++i) {
  61                 if (dss_plls[i] && strcmp(dss_plls[i]->name, name) == 0)
  62                         return dss_plls[i];
  63         }
  64 
  65         return NULL;
  66 }
  67 
  68 int dss_pll_enable(struct dss_pll *pll)
  69 {
  70         int r;
  71 
  72         r = clk_prepare_enable(pll->clkin);
  73         if (r)
  74                 return r;
  75 
  76         if (pll->regulator) {
  77                 r = regulator_enable(pll->regulator);
  78                 if (r)
  79                         goto err_reg;
  80         }
  81 
  82         r = pll->ops->enable(pll);
  83         if (r)
  84                 goto err_enable;
  85 
  86         return 0;
  87 
  88 err_enable:
  89         if (pll->regulator)
  90                 regulator_disable(pll->regulator);
  91 err_reg:
  92         clk_disable_unprepare(pll->clkin);
  93         return r;
  94 }
  95 
  96 void dss_pll_disable(struct dss_pll *pll)
  97 {
  98         pll->ops->disable(pll);
  99 
 100         if (pll->regulator)
 101                 regulator_disable(pll->regulator);
 102 
 103         clk_disable_unprepare(pll->clkin);
 104 
 105         memset(&pll->cinfo, 0, sizeof(pll->cinfo));
 106 }
 107 
 108 int dss_pll_set_config(struct dss_pll *pll, const struct dss_pll_clock_info *cinfo)
 109 {
 110         int r;
 111 
 112         r = pll->ops->set_config(pll, cinfo);
 113         if (r)
 114                 return r;
 115 
 116         pll->cinfo = *cinfo;
 117 
 118         return 0;
 119 }
 120 
 121 bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco,
 122                 unsigned long out_min, unsigned long out_max,
 123                 dss_hsdiv_calc_func func, void *data)
 124 {
 125         const struct dss_pll_hw *hw = pll->hw;
 126         int m, m_start, m_stop;
 127         unsigned long out;
 128 
 129         out_min = out_min ? out_min : 1;
 130         out_max = out_max ? out_max : ULONG_MAX;
 131 
 132         m_start = max(DIV_ROUND_UP(clkdco, out_max), 1ul);
 133 
 134         m_stop = min((unsigned)(clkdco / out_min), hw->mX_max);
 135 
 136         for (m = m_start; m <= m_stop; ++m) {
 137                 out = clkdco / m;
 138 
 139                 if (func(m, out, data))
 140                         return true;
 141         }
 142 
 143         return false;
 144 }
 145 
 146 bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin,
 147                 unsigned long pll_min, unsigned long pll_max,
 148                 dss_pll_calc_func func, void *data)
 149 {
 150         const struct dss_pll_hw *hw = pll->hw;
 151         int n, n_start, n_stop;
 152         int m, m_start, m_stop;
 153         unsigned long fint, clkdco;
 154         unsigned long pll_hw_max;
 155         unsigned long fint_hw_min, fint_hw_max;
 156 
 157         pll_hw_max = hw->clkdco_max;
 158 
 159         fint_hw_min = hw->fint_min;
 160         fint_hw_max = hw->fint_max;
 161 
 162         n_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
 163         n_stop = min((unsigned)(clkin / fint_hw_min), hw->n_max);
 164 
 165         pll_max = pll_max ? pll_max : ULONG_MAX;
 166 
 167         for (n = n_start; n <= n_stop; ++n) {
 168                 fint = clkin / n;
 169 
 170                 m_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
 171                                 1ul);
 172                 m_stop = min3((unsigned)(pll_max / fint / 2),
 173                                 (unsigned)(pll_hw_max / fint / 2),
 174                                 hw->m_max);
 175 
 176                 for (m = m_start; m <= m_stop; ++m) {
 177                         clkdco = 2 * m * fint;
 178 
 179                         if (func(n, m, fint, clkdco, data))
 180                                 return true;
 181                 }
 182         }
 183 
 184         return false;
 185 }
 186 
 187 static int wait_for_bit_change(void __iomem *reg, int bitnum, int value)
 188 {
 189         unsigned long timeout;
 190         ktime_t wait;
 191         int t;
 192 
 193         /* first busyloop to see if the bit changes right away */
 194         t = 100;
 195         while (t-- > 0) {
 196                 if (FLD_GET(readl_relaxed(reg), bitnum, bitnum) == value)
 197                         return value;
 198         }
 199 
 200         /* then loop for 500ms, sleeping for 1ms in between */
 201         timeout = jiffies + msecs_to_jiffies(500);
 202         while (time_before(jiffies, timeout)) {
 203                 if (FLD_GET(readl_relaxed(reg), bitnum, bitnum) == value)
 204                         return value;
 205 
 206                 wait = ns_to_ktime(1000 * 1000);
 207                 set_current_state(TASK_UNINTERRUPTIBLE);
 208                 schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
 209         }
 210 
 211         return !value;
 212 }
 213 
 214 int dss_pll_wait_reset_done(struct dss_pll *pll)
 215 {
 216         void __iomem *base = pll->base;
 217 
 218         if (wait_for_bit_change(base + PLL_STATUS, 0, 1) != 1)
 219                 return -ETIMEDOUT;
 220         else
 221                 return 0;
 222 }
 223 
 224 static int dss_wait_hsdiv_ack(struct dss_pll *pll, u32 hsdiv_ack_mask)
 225 {
 226         int t = 100;
 227 
 228         while (t-- > 0) {
 229                 u32 v = readl_relaxed(pll->base + PLL_STATUS);
 230                 v &= hsdiv_ack_mask;
 231                 if (v == hsdiv_ack_mask)
 232                         return 0;
 233         }
 234 
 235         return -ETIMEDOUT;
 236 }
 237 
 238 int dss_pll_write_config_type_a(struct dss_pll *pll,
 239                 const struct dss_pll_clock_info *cinfo)
 240 {
 241         const struct dss_pll_hw *hw = pll->hw;
 242         void __iomem *base = pll->base;
 243         int r = 0;
 244         u32 l;
 245 
 246         l = 0;
 247         if (hw->has_stopmode)
 248                 l = FLD_MOD(l, 1, 0, 0);                /* PLL_STOPMODE */
 249         l = FLD_MOD(l, cinfo->n - 1, hw->n_msb, hw->n_lsb);     /* PLL_REGN */
 250         l = FLD_MOD(l, cinfo->m, hw->m_msb, hw->m_lsb);         /* PLL_REGM */
 251         /* M4 */
 252         l = FLD_MOD(l, cinfo->mX[0] ? cinfo->mX[0] - 1 : 0,
 253                         hw->mX_msb[0], hw->mX_lsb[0]);
 254         /* M5 */
 255         l = FLD_MOD(l, cinfo->mX[1] ? cinfo->mX[1] - 1 : 0,
 256                         hw->mX_msb[1], hw->mX_lsb[1]);
 257         writel_relaxed(l, base + PLL_CONFIGURATION1);
 258 
 259         l = 0;
 260         /* M6 */
 261         l = FLD_MOD(l, cinfo->mX[2] ? cinfo->mX[2] - 1 : 0,
 262                         hw->mX_msb[2], hw->mX_lsb[2]);
 263         /* M7 */
 264         l = FLD_MOD(l, cinfo->mX[3] ? cinfo->mX[3] - 1 : 0,
 265                         hw->mX_msb[3], hw->mX_lsb[3]);
 266         writel_relaxed(l, base + PLL_CONFIGURATION3);
 267 
 268         l = readl_relaxed(base + PLL_CONFIGURATION2);
 269         if (hw->has_freqsel) {
 270                 u32 f = cinfo->fint < 1000000 ? 0x3 :
 271                         cinfo->fint < 1250000 ? 0x4 :
 272                         cinfo->fint < 1500000 ? 0x5 :
 273                         cinfo->fint < 1750000 ? 0x6 :
 274                         0x7;
 275 
 276                 l = FLD_MOD(l, f, 4, 1);        /* PLL_FREQSEL */
 277         } else if (hw->has_selfreqdco) {
 278                 u32 f = cinfo->clkdco < hw->clkdco_low ? 0x2 : 0x4;
 279 
 280                 l = FLD_MOD(l, f, 3, 1);        /* PLL_SELFREQDCO */
 281         }
 282         l = FLD_MOD(l, 1, 13, 13);              /* PLL_REFEN */
 283         l = FLD_MOD(l, 0, 14, 14);              /* PHY_CLKINEN */
 284         l = FLD_MOD(l, 0, 16, 16);              /* M4_CLOCK_EN */
 285         l = FLD_MOD(l, 0, 18, 18);              /* M5_CLOCK_EN */
 286         l = FLD_MOD(l, 1, 20, 20);              /* HSDIVBYPASS */
 287         if (hw->has_refsel)
 288                 l = FLD_MOD(l, 3, 22, 21);      /* REFSEL = sysclk */
 289         l = FLD_MOD(l, 0, 23, 23);              /* M6_CLOCK_EN */
 290         l = FLD_MOD(l, 0, 25, 25);              /* M7_CLOCK_EN */
 291         writel_relaxed(l, base + PLL_CONFIGURATION2);
 292 
 293         writel_relaxed(1, base + PLL_GO);       /* PLL_GO */
 294 
 295         if (wait_for_bit_change(base + PLL_GO, 0, 0) != 0) {
 296                 DSSERR("DSS DPLL GO bit not going down.\n");
 297                 r = -EIO;
 298                 goto err;
 299         }
 300 
 301         if (wait_for_bit_change(base + PLL_STATUS, 1, 1) != 1) {
 302                 DSSERR("cannot lock DSS DPLL\n");
 303                 r = -EIO;
 304                 goto err;
 305         }
 306 
 307         l = readl_relaxed(base + PLL_CONFIGURATION2);
 308         l = FLD_MOD(l, 1, 14, 14);                      /* PHY_CLKINEN */
 309         l = FLD_MOD(l, cinfo->mX[0] ? 1 : 0, 16, 16);   /* M4_CLOCK_EN */
 310         l = FLD_MOD(l, cinfo->mX[1] ? 1 : 0, 18, 18);   /* M5_CLOCK_EN */
 311         l = FLD_MOD(l, 0, 20, 20);                      /* HSDIVBYPASS */
 312         l = FLD_MOD(l, cinfo->mX[2] ? 1 : 0, 23, 23);   /* M6_CLOCK_EN */
 313         l = FLD_MOD(l, cinfo->mX[3] ? 1 : 0, 25, 25);   /* M7_CLOCK_EN */
 314         writel_relaxed(l, base + PLL_CONFIGURATION2);
 315 
 316         r = dss_wait_hsdiv_ack(pll,
 317                 (cinfo->mX[0] ? BIT(7) : 0) |
 318                 (cinfo->mX[1] ? BIT(8) : 0) |
 319                 (cinfo->mX[2] ? BIT(10) : 0) |
 320                 (cinfo->mX[3] ? BIT(11) : 0));
 321         if (r) {
 322                 DSSERR("failed to enable HSDIV clocks\n");
 323                 goto err;
 324         }
 325 
 326 err:
 327         return r;
 328 }
 329 
 330 int dss_pll_write_config_type_b(struct dss_pll *pll,
 331                 const struct dss_pll_clock_info *cinfo)
 332 {
 333         const struct dss_pll_hw *hw = pll->hw;
 334         void __iomem *base = pll->base;
 335         u32 l;
 336 
 337         l = 0;
 338         l = FLD_MOD(l, cinfo->m, 20, 9);        /* PLL_REGM */
 339         l = FLD_MOD(l, cinfo->n - 1, 8, 1);     /* PLL_REGN */
 340         writel_relaxed(l, base + PLL_CONFIGURATION1);
 341 
 342         l = readl_relaxed(base + PLL_CONFIGURATION2);
 343         l = FLD_MOD(l, 0x0, 12, 12);    /* PLL_HIGHFREQ divide by 2 */
 344         l = FLD_MOD(l, 0x1, 13, 13);    /* PLL_REFEN */
 345         l = FLD_MOD(l, 0x0, 14, 14);    /* PHY_CLKINEN */
 346         if (hw->has_refsel)
 347                 l = FLD_MOD(l, 0x3, 22, 21);    /* REFSEL = SYSCLK */
 348 
 349         /* PLL_SELFREQDCO */
 350         if (cinfo->clkdco > hw->clkdco_low)
 351                 l = FLD_MOD(l, 0x4, 3, 1);
 352         else
 353                 l = FLD_MOD(l, 0x2, 3, 1);
 354         writel_relaxed(l, base + PLL_CONFIGURATION2);
 355 
 356         l = readl_relaxed(base + PLL_CONFIGURATION3);
 357         l = FLD_MOD(l, cinfo->sd, 17, 10);      /* PLL_REGSD */
 358         writel_relaxed(l, base + PLL_CONFIGURATION3);
 359 
 360         l = readl_relaxed(base + PLL_CONFIGURATION4);
 361         l = FLD_MOD(l, cinfo->mX[0], 24, 18);   /* PLL_REGM2 */
 362         l = FLD_MOD(l, cinfo->mf, 17, 0);       /* PLL_REGM_F */
 363         writel_relaxed(l, base + PLL_CONFIGURATION4);
 364 
 365         writel_relaxed(1, base + PLL_GO);       /* PLL_GO */
 366 
 367         if (wait_for_bit_change(base + PLL_GO, 0, 0) != 0) {
 368                 DSSERR("DSS DPLL GO bit not going down.\n");
 369                 return -EIO;
 370         }
 371 
 372         if (wait_for_bit_change(base + PLL_STATUS, 1, 1) != 1) {
 373                 DSSERR("cannot lock DSS DPLL\n");
 374                 return -ETIMEDOUT;
 375         }
 376 
 377         return 0;
 378 }

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