linux/drivers/gpu/drm/omapdrm/dss/pll.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2014 Texas Instruments Incorporated
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms of the GNU General Public License version 2 as published by
   6 * the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful, but WITHOUT
   9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  11 * more details.
  12 *
  13 * You should have received a copy of the GNU General Public License along with
  14 * this program.  If not, see <http://www.gnu.org/licenses/>.
  15 */
  16
  17#define DSS_SUBSYS_NAME "PLL"
  18
  19#include <linux/clk.h>
  20#include <linux/io.h>
  21#include <linux/kernel.h>
  22#include <linux/regulator/consumer.h>
  23#include <linux/sched.h>
  24
  25#include "omapdss.h"
  26#include "dss.h"
  27
  28#define PLL_CONTROL                     0x0000
  29#define PLL_STATUS                      0x0004
  30#define PLL_GO                          0x0008
  31#define PLL_CONFIGURATION1              0x000C
  32#define PLL_CONFIGURATION2              0x0010
  33#define PLL_CONFIGURATION3              0x0014
  34#define PLL_SSC_CONFIGURATION1          0x0018
  35#define PLL_SSC_CONFIGURATION2          0x001C
  36#define PLL_CONFIGURATION4              0x0020
  37
  38static struct dss_pll *dss_plls[4];
  39
  40int dss_pll_register(struct dss_pll *pll)
  41{
  42        int i;
  43
  44        for (i = 0; i < ARRAY_SIZE(dss_plls); ++i) {
  45                if (!dss_plls[i]) {
  46                        dss_plls[i] = pll;
  47                        return 0;
  48                }
  49        }
  50
  51        return -EBUSY;
  52}
  53
  54void dss_pll_unregister(struct dss_pll *pll)
  55{
  56        int i;
  57
  58        for (i = 0; i < ARRAY_SIZE(dss_plls); ++i) {
  59                if (dss_plls[i] == pll) {
  60                        dss_plls[i] = NULL;
  61                        return;
  62                }
  63        }
  64}
  65
  66struct dss_pll *dss_pll_find(const char *name)
  67{
  68        int i;
  69
  70        for (i = 0; i < ARRAY_SIZE(dss_plls); ++i) {
  71                if (dss_plls[i] && strcmp(dss_plls[i]->name, name) == 0)
  72                        return dss_plls[i];
  73        }
  74
  75        return NULL;
  76}
  77
  78struct dss_pll *dss_pll_find_by_src(enum dss_clk_source src)
  79{
  80        struct dss_pll *pll;
  81
  82        switch (src) {
  83        default:
  84        case DSS_CLK_SRC_FCK:
  85                return NULL;
  86
  87        case DSS_CLK_SRC_HDMI_PLL:
  88                return dss_pll_find("hdmi");
  89
  90        case DSS_CLK_SRC_PLL1_1:
  91        case DSS_CLK_SRC_PLL1_2:
  92        case DSS_CLK_SRC_PLL1_3:
  93                pll = dss_pll_find("dsi0");
  94                if (!pll)
  95                        pll = dss_pll_find("video0");
  96                return pll;
  97
  98        case DSS_CLK_SRC_PLL2_1:
  99        case DSS_CLK_SRC_PLL2_2:
 100        case DSS_CLK_SRC_PLL2_3:
 101                pll = dss_pll_find("dsi1");
 102                if (!pll)
 103                        pll = dss_pll_find("video1");
 104                return pll;
 105        }
 106}
 107
 108unsigned dss_pll_get_clkout_idx_for_src(enum dss_clk_source src)
 109{
 110        switch (src) {
 111        case DSS_CLK_SRC_HDMI_PLL:
 112                return 0;
 113
 114        case DSS_CLK_SRC_PLL1_1:
 115        case DSS_CLK_SRC_PLL2_1:
 116                return 0;
 117
 118        case DSS_CLK_SRC_PLL1_2:
 119        case DSS_CLK_SRC_PLL2_2:
 120                return 1;
 121
 122        case DSS_CLK_SRC_PLL1_3:
 123        case DSS_CLK_SRC_PLL2_3:
 124                return 2;
 125
 126        default:
 127                return 0;
 128        }
 129}
 130
 131int dss_pll_enable(struct dss_pll *pll)
 132{
 133        int r;
 134
 135        r = clk_prepare_enable(pll->clkin);
 136        if (r)
 137                return r;
 138
 139        if (pll->regulator) {
 140                r = regulator_enable(pll->regulator);
 141                if (r)
 142                        goto err_reg;
 143        }
 144
 145        r = pll->ops->enable(pll);
 146        if (r)
 147                goto err_enable;
 148
 149        return 0;
 150
 151err_enable:
 152        if (pll->regulator)
 153                regulator_disable(pll->regulator);
 154err_reg:
 155        clk_disable_unprepare(pll->clkin);
 156        return r;
 157}
 158
 159void dss_pll_disable(struct dss_pll *pll)
 160{
 161        pll->ops->disable(pll);
 162
 163        if (pll->regulator)
 164                regulator_disable(pll->regulator);
 165
 166        clk_disable_unprepare(pll->clkin);
 167
 168        memset(&pll->cinfo, 0, sizeof(pll->cinfo));
 169}
 170
 171int dss_pll_set_config(struct dss_pll *pll, const struct dss_pll_clock_info *cinfo)
 172{
 173        int r;
 174
 175        r = pll->ops->set_config(pll, cinfo);
 176        if (r)
 177                return r;
 178
 179        pll->cinfo = *cinfo;
 180
 181        return 0;
 182}
 183
 184bool dss_pll_hsdiv_calc_a(const struct dss_pll *pll, unsigned long clkdco,
 185                unsigned long out_min, unsigned long out_max,
 186                dss_hsdiv_calc_func func, void *data)
 187{
 188        const struct dss_pll_hw *hw = pll->hw;
 189        int m, m_start, m_stop;
 190        unsigned long out;
 191
 192        out_min = out_min ? out_min : 1;
 193        out_max = out_max ? out_max : ULONG_MAX;
 194
 195        m_start = max(DIV_ROUND_UP(clkdco, out_max), 1ul);
 196
 197        m_stop = min((unsigned)(clkdco / out_min), hw->mX_max);
 198
 199        for (m = m_start; m <= m_stop; ++m) {
 200                out = clkdco / m;
 201
 202                if (func(m, out, data))
 203                        return true;
 204        }
 205
 206        return false;
 207}
 208
 209/*
 210 * clkdco = clkin / n * m * 2
 211 * clkoutX = clkdco / mX
 212 */
 213bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
 214                unsigned long pll_min, unsigned long pll_max,
 215                dss_pll_calc_func func, void *data)
 216{
 217        const struct dss_pll_hw *hw = pll->hw;
 218        int n, n_start, n_stop;
 219        int m, m_start, m_stop;
 220        unsigned long fint, clkdco;
 221        unsigned long pll_hw_max;
 222        unsigned long fint_hw_min, fint_hw_max;
 223
 224        pll_hw_max = hw->clkdco_max;
 225
 226        fint_hw_min = hw->fint_min;
 227        fint_hw_max = hw->fint_max;
 228
 229        n_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
 230        n_stop = min((unsigned)(clkin / fint_hw_min), hw->n_max);
 231
 232        pll_max = pll_max ? pll_max : ULONG_MAX;
 233
 234        for (n = n_start; n <= n_stop; ++n) {
 235                fint = clkin / n;
 236
 237                m_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
 238                                1ul);
 239                m_stop = min3((unsigned)(pll_max / fint / 2),
 240                                (unsigned)(pll_hw_max / fint / 2),
 241                                hw->m_max);
 242
 243                for (m = m_start; m <= m_stop; ++m) {
 244                        clkdco = 2 * m * fint;
 245
 246                        if (func(n, m, fint, clkdco, data))
 247                                return true;
 248                }
 249        }
 250
 251        return false;
 252}
 253
 254/*
 255 * This calculates a PLL config that will provide the target_clkout rate
 256 * for clkout. Additionally clkdco rate will be the same as clkout rate
 257 * when clkout rate is >= min_clkdco.
 258 *
 259 * clkdco = clkin / n * m + clkin / n * mf / 262144
 260 * clkout = clkdco / m2
 261 */
 262bool dss_pll_calc_b(const struct dss_pll *pll, unsigned long clkin,
 263        unsigned long target_clkout, struct dss_pll_clock_info *cinfo)
 264{
 265        unsigned long fint, clkdco, clkout;
 266        unsigned long target_clkdco;
 267        unsigned long min_dco;
 268        unsigned n, m, mf, m2, sd;
 269        const struct dss_pll_hw *hw = pll->hw;
 270
 271        DSSDBG("clkin %lu, target clkout %lu\n", clkin, target_clkout);
 272
 273        /* Fint */
 274        n = DIV_ROUND_UP(clkin, hw->fint_max);
 275        fint = clkin / n;
 276
 277        /* adjust m2 so that the clkdco will be high enough */
 278        min_dco = roundup(hw->clkdco_min, fint);
 279        m2 = DIV_ROUND_UP(min_dco, target_clkout);
 280        if (m2 == 0)
 281                m2 = 1;
 282
 283        target_clkdco = target_clkout * m2;
 284        m = target_clkdco / fint;
 285
 286        clkdco = fint * m;
 287
 288        /* adjust clkdco with fractional mf */
 289        if (WARN_ON(target_clkdco - clkdco > fint))
 290                mf = 0;
 291        else
 292                mf = (u32)div_u64(262144ull * (target_clkdco - clkdco), fint);
 293
 294        if (mf > 0)
 295                clkdco += (u32)div_u64((u64)mf * fint, 262144);
 296
 297        clkout = clkdco / m2;
 298
 299        /* sigma-delta */
 300        sd = DIV_ROUND_UP(fint * m, 250000000);
 301
 302        DSSDBG("N = %u, M = %u, M.f = %u, M2 = %u, SD = %u\n",
 303                n, m, mf, m2, sd);
 304        DSSDBG("Fint %lu, clkdco %lu, clkout %lu\n", fint, clkdco, clkout);
 305
 306        cinfo->n = n;
 307        cinfo->m = m;
 308        cinfo->mf = mf;
 309        cinfo->mX[0] = m2;
 310        cinfo->sd = sd;
 311
 312        cinfo->fint = fint;
 313        cinfo->clkdco = clkdco;
 314        cinfo->clkout[0] = clkout;
 315
 316        return true;
 317}
 318
 319static int wait_for_bit_change(void __iomem *reg, int bitnum, int value)
 320{
 321        unsigned long timeout;
 322        ktime_t wait;
 323        int t;
 324
 325        /* first busyloop to see if the bit changes right away */
 326        t = 100;
 327        while (t-- > 0) {
 328                if (FLD_GET(readl_relaxed(reg), bitnum, bitnum) == value)
 329                        return value;
 330        }
 331
 332        /* then loop for 500ms, sleeping for 1ms in between */
 333        timeout = jiffies + msecs_to_jiffies(500);
 334        while (time_before(jiffies, timeout)) {
 335                if (FLD_GET(readl_relaxed(reg), bitnum, bitnum) == value)
 336                        return value;
 337
 338                wait = ns_to_ktime(1000 * 1000);
 339                set_current_state(TASK_UNINTERRUPTIBLE);
 340                schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
 341        }
 342
 343        return !value;
 344}
 345
 346int dss_pll_wait_reset_done(struct dss_pll *pll)
 347{
 348        void __iomem *base = pll->base;
 349
 350        if (wait_for_bit_change(base + PLL_STATUS, 0, 1) != 1)
 351                return -ETIMEDOUT;
 352        else
 353                return 0;
 354}
 355
 356static int dss_wait_hsdiv_ack(struct dss_pll *pll, u32 hsdiv_ack_mask)
 357{
 358        int t = 100;
 359
 360        while (t-- > 0) {
 361                u32 v = readl_relaxed(pll->base + PLL_STATUS);
 362                v &= hsdiv_ack_mask;
 363                if (v == hsdiv_ack_mask)
 364                        return 0;
 365        }
 366
 367        return -ETIMEDOUT;
 368}
 369
 370int dss_pll_write_config_type_a(struct dss_pll *pll,
 371                const struct dss_pll_clock_info *cinfo)
 372{
 373        const struct dss_pll_hw *hw = pll->hw;
 374        void __iomem *base = pll->base;
 375        int r = 0;
 376        u32 l;
 377
 378        l = 0;
 379        if (hw->has_stopmode)
 380                l = FLD_MOD(l, 1, 0, 0);                /* PLL_STOPMODE */
 381        l = FLD_MOD(l, cinfo->n - 1, hw->n_msb, hw->n_lsb);     /* PLL_REGN */
 382        l = FLD_MOD(l, cinfo->m, hw->m_msb, hw->m_lsb);         /* PLL_REGM */
 383        /* M4 */
 384        l = FLD_MOD(l, cinfo->mX[0] ? cinfo->mX[0] - 1 : 0,
 385                        hw->mX_msb[0], hw->mX_lsb[0]);
 386        /* M5 */
 387        l = FLD_MOD(l, cinfo->mX[1] ? cinfo->mX[1] - 1 : 0,
 388                        hw->mX_msb[1], hw->mX_lsb[1]);
 389        writel_relaxed(l, base + PLL_CONFIGURATION1);
 390
 391        l = 0;
 392        /* M6 */
 393        l = FLD_MOD(l, cinfo->mX[2] ? cinfo->mX[2] - 1 : 0,
 394                        hw->mX_msb[2], hw->mX_lsb[2]);
 395        /* M7 */
 396        l = FLD_MOD(l, cinfo->mX[3] ? cinfo->mX[3] - 1 : 0,
 397                        hw->mX_msb[3], hw->mX_lsb[3]);
 398        writel_relaxed(l, base + PLL_CONFIGURATION3);
 399
 400        l = readl_relaxed(base + PLL_CONFIGURATION2);
 401        if (hw->has_freqsel) {
 402                u32 f = cinfo->fint < 1000000 ? 0x3 :
 403                        cinfo->fint < 1250000 ? 0x4 :
 404                        cinfo->fint < 1500000 ? 0x5 :
 405                        cinfo->fint < 1750000 ? 0x6 :
 406                        0x7;
 407
 408                l = FLD_MOD(l, f, 4, 1);        /* PLL_FREQSEL */
 409        } else if (hw->has_selfreqdco) {
 410                u32 f = cinfo->clkdco < hw->clkdco_low ? 0x2 : 0x4;
 411
 412                l = FLD_MOD(l, f, 3, 1);        /* PLL_SELFREQDCO */
 413        }
 414        l = FLD_MOD(l, 1, 13, 13);              /* PLL_REFEN */
 415        l = FLD_MOD(l, 0, 14, 14);              /* PHY_CLKINEN */
 416        l = FLD_MOD(l, 0, 16, 16);              /* M4_CLOCK_EN */
 417        l = FLD_MOD(l, 0, 18, 18);              /* M5_CLOCK_EN */
 418        l = FLD_MOD(l, 1, 20, 20);              /* HSDIVBYPASS */
 419        if (hw->has_refsel)
 420                l = FLD_MOD(l, 3, 22, 21);      /* REFSEL = sysclk */
 421        l = FLD_MOD(l, 0, 23, 23);              /* M6_CLOCK_EN */
 422        l = FLD_MOD(l, 0, 25, 25);              /* M7_CLOCK_EN */
 423        writel_relaxed(l, base + PLL_CONFIGURATION2);
 424
 425        writel_relaxed(1, base + PLL_GO);       /* PLL_GO */
 426
 427        if (wait_for_bit_change(base + PLL_GO, 0, 0) != 0) {
 428                DSSERR("DSS DPLL GO bit not going down.\n");
 429                r = -EIO;
 430                goto err;
 431        }
 432
 433        if (wait_for_bit_change(base + PLL_STATUS, 1, 1) != 1) {
 434                DSSERR("cannot lock DSS DPLL\n");
 435                r = -EIO;
 436                goto err;
 437        }
 438
 439        l = readl_relaxed(base + PLL_CONFIGURATION2);
 440        l = FLD_MOD(l, 1, 14, 14);                      /* PHY_CLKINEN */
 441        l = FLD_MOD(l, cinfo->mX[0] ? 1 : 0, 16, 16);   /* M4_CLOCK_EN */
 442        l = FLD_MOD(l, cinfo->mX[1] ? 1 : 0, 18, 18);   /* M5_CLOCK_EN */
 443        l = FLD_MOD(l, 0, 20, 20);                      /* HSDIVBYPASS */
 444        l = FLD_MOD(l, cinfo->mX[2] ? 1 : 0, 23, 23);   /* M6_CLOCK_EN */
 445        l = FLD_MOD(l, cinfo->mX[3] ? 1 : 0, 25, 25);   /* M7_CLOCK_EN */
 446        writel_relaxed(l, base + PLL_CONFIGURATION2);
 447
 448        r = dss_wait_hsdiv_ack(pll,
 449                (cinfo->mX[0] ? BIT(7) : 0) |
 450                (cinfo->mX[1] ? BIT(8) : 0) |
 451                (cinfo->mX[2] ? BIT(10) : 0) |
 452                (cinfo->mX[3] ? BIT(11) : 0));
 453        if (r) {
 454                DSSERR("failed to enable HSDIV clocks\n");
 455                goto err;
 456        }
 457
 458err:
 459        return r;
 460}
 461
 462int dss_pll_write_config_type_b(struct dss_pll *pll,
 463                const struct dss_pll_clock_info *cinfo)
 464{
 465        const struct dss_pll_hw *hw = pll->hw;
 466        void __iomem *base = pll->base;
 467        u32 l;
 468
 469        l = 0;
 470        l = FLD_MOD(l, cinfo->m, 20, 9);        /* PLL_REGM */
 471        l = FLD_MOD(l, cinfo->n - 1, 8, 1);     /* PLL_REGN */
 472        writel_relaxed(l, base + PLL_CONFIGURATION1);
 473
 474        l = readl_relaxed(base + PLL_CONFIGURATION2);
 475        l = FLD_MOD(l, 0x0, 12, 12);    /* PLL_HIGHFREQ divide by 2 */
 476        l = FLD_MOD(l, 0x1, 13, 13);    /* PLL_REFEN */
 477        l = FLD_MOD(l, 0x0, 14, 14);    /* PHY_CLKINEN */
 478        if (hw->has_refsel)
 479                l = FLD_MOD(l, 0x3, 22, 21);    /* REFSEL = SYSCLK */
 480
 481        /* PLL_SELFREQDCO */
 482        if (cinfo->clkdco > hw->clkdco_low)
 483                l = FLD_MOD(l, 0x4, 3, 1);
 484        else
 485                l = FLD_MOD(l, 0x2, 3, 1);
 486        writel_relaxed(l, base + PLL_CONFIGURATION2);
 487
 488        l = readl_relaxed(base + PLL_CONFIGURATION3);
 489        l = FLD_MOD(l, cinfo->sd, 17, 10);      /* PLL_REGSD */
 490        writel_relaxed(l, base + PLL_CONFIGURATION3);
 491
 492        l = readl_relaxed(base + PLL_CONFIGURATION4);
 493        l = FLD_MOD(l, cinfo->mX[0], 24, 18);   /* PLL_REGM2 */
 494        l = FLD_MOD(l, cinfo->mf, 17, 0);       /* PLL_REGM_F */
 495        writel_relaxed(l, base + PLL_CONFIGURATION4);
 496
 497        writel_relaxed(1, base + PLL_GO);       /* PLL_GO */
 498
 499        if (wait_for_bit_change(base + PLL_GO, 0, 0) != 0) {
 500                DSSERR("DSS DPLL GO bit not going down.\n");
 501                return -EIO;
 502        }
 503
 504        if (wait_for_bit_change(base + PLL_STATUS, 1, 1) != 1) {
 505                DSSERR("cannot lock DSS DPLL\n");
 506                return -ETIMEDOUT;
 507        }
 508
 509        return 0;
 510}
 511