linux/drivers/clk/ti/dpll3xxx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * OMAP3/4 - specific DPLL control functions
   4 *
   5 * Copyright (C) 2009-2010 Texas Instruments, Inc.
   6 * Copyright (C) 2009-2010 Nokia Corporation
   7 *
   8 * Written by Paul Walmsley
   9 * Testing and integration fixes by Jouni H\xC3\xB6gander
  10 *
  11 * 36xx support added by Vishwanath BS, Richard Woodruff, and Nishanth
  12 * Menon
  13 *
  14 * Parts of this code are based on code written by
  15 * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
  16 */
  17
  18#include <linux/kernel.h>
  19#include <linux/device.h>
  20#include <linux/list.h>
  21#include <linux/errno.h>
  22#include <linux/delay.h>
  23#include <linux/clk.h>
  24#include <linux/io.h>
  25#include <linux/bitops.h>
  26#include <linux/clkdev.h>
  27#include <linux/clk/ti.h>
  28
  29#include "clock.h"
  30
  31/* CM_AUTOIDLE_PLL*.AUTO_* bit values */
  32#define DPLL_AUTOIDLE_DISABLE                   0x0
  33#define DPLL_AUTOIDLE_LOW_POWER_STOP            0x1
  34
  35#define MAX_DPLL_WAIT_TRIES             1000000
  36
  37#define OMAP3XXX_EN_DPLL_LOCKED         0x7
  38
  39/* Forward declarations */
  40static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
  41static void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
  42static void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
  43
  44/* Private functions */
  45
  46/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
  47static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
  48{
  49        const struct dpll_data *dd;
  50        u32 v;
  51
  52        dd = clk->dpll_data;
  53
  54        v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
  55        v &= ~dd->enable_mask;
  56        v |= clken_bits << __ffs(dd->enable_mask);
  57        ti_clk_ll_ops->clk_writel(v, &dd->control_reg);
  58}
  59
  60/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
  61static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
  62{
  63        const struct dpll_data *dd;
  64        int i = 0;
  65        int ret = -EINVAL;
  66        const char *clk_name;
  67
  68        dd = clk->dpll_data;
  69        clk_name = clk_hw_get_name(&clk->hw);
  70
  71        state <<= __ffs(dd->idlest_mask);
  72
  73        while (((ti_clk_ll_ops->clk_readl(&dd->idlest_reg) & dd->idlest_mask)
  74                != state) && i < MAX_DPLL_WAIT_TRIES) {
  75                i++;
  76                udelay(1);
  77        }
  78
  79        if (i == MAX_DPLL_WAIT_TRIES) {
  80                pr_err("clock: %s failed transition to '%s'\n",
  81                       clk_name, (state) ? "locked" : "bypassed");
  82        } else {
  83                pr_debug("clock: %s transition to '%s' in %d loops\n",
  84                         clk_name, (state) ? "locked" : "bypassed", i);
  85
  86                ret = 0;
  87        }
  88
  89        return ret;
  90}
  91
  92/* From 3430 TRM ES2 4.7.6.2 */
  93static u16 _omap3_dpll_compute_freqsel(struct clk_hw_omap *clk, u8 n)
  94{
  95        unsigned long fint;
  96        u16 f = 0;
  97
  98        fint = clk_hw_get_rate(clk->dpll_data->clk_ref) / n;
  99
 100        pr_debug("clock: fint is %lu\n", fint);
 101
 102        if (fint >= 750000 && fint <= 1000000)
 103                f = 0x3;
 104        else if (fint > 1000000 && fint <= 1250000)
 105                f = 0x4;
 106        else if (fint > 1250000 && fint <= 1500000)
 107                f = 0x5;
 108        else if (fint > 1500000 && fint <= 1750000)
 109                f = 0x6;
 110        else if (fint > 1750000 && fint <= 2100000)
 111                f = 0x7;
 112        else if (fint > 7500000 && fint <= 10000000)
 113                f = 0xB;
 114        else if (fint > 10000000 && fint <= 12500000)
 115                f = 0xC;
 116        else if (fint > 12500000 && fint <= 15000000)
 117                f = 0xD;
 118        else if (fint > 15000000 && fint <= 17500000)
 119                f = 0xE;
 120        else if (fint > 17500000 && fint <= 21000000)
 121                f = 0xF;
 122        else
 123                pr_debug("clock: unknown freqsel setting for %d\n", n);
 124
 125        return f;
 126}
 127
 128/**
 129 * _omap3_noncore_dpll_lock - instruct a DPLL to lock and wait for readiness
 130 * @clk: pointer to a DPLL struct clk
 131 *
 132 * Instructs a non-CORE DPLL to lock.  Waits for the DPLL to report
 133 * readiness before returning.  Will save and restore the DPLL's
 134 * autoidle state across the enable, per the CDP code.  If the DPLL
 135 * locked successfully, return 0; if the DPLL did not lock in the time
 136 * allotted, or DPLL3 was passed in, return -EINVAL.
 137 */
 138static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
 139{
 140        const struct dpll_data *dd;
 141        u8 ai;
 142        u8 state = 1;
 143        int r = 0;
 144
 145        pr_debug("clock: locking DPLL %s\n", clk_hw_get_name(&clk->hw));
 146
 147        dd = clk->dpll_data;
 148        state <<= __ffs(dd->idlest_mask);
 149
 150        /* Check if already locked */
 151        if ((ti_clk_ll_ops->clk_readl(&dd->idlest_reg) & dd->idlest_mask) ==
 152            state)
 153                goto done;
 154
 155        ai = omap3_dpll_autoidle_read(clk);
 156
 157        if (ai)
 158                omap3_dpll_deny_idle(clk);
 159
 160        _omap3_dpll_write_clken(clk, DPLL_LOCKED);
 161
 162        r = _omap3_wait_dpll_status(clk, 1);
 163
 164        if (ai)
 165                omap3_dpll_allow_idle(clk);
 166
 167done:
 168        return r;
 169}
 170
 171/**
 172 * _omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness
 173 * @clk: pointer to a DPLL struct clk
 174 *
 175 * Instructs a non-CORE DPLL to enter low-power bypass mode.  In
 176 * bypass mode, the DPLL's rate is set equal to its parent clock's
 177 * rate.  Waits for the DPLL to report readiness before returning.
 178 * Will save and restore the DPLL's autoidle state across the enable,
 179 * per the CDP code.  If the DPLL entered bypass mode successfully,
 180 * return 0; if the DPLL did not enter bypass in the time allotted, or
 181 * DPLL3 was passed in, or the DPLL does not support low-power bypass,
 182 * return -EINVAL.
 183 */
 184static int _omap3_noncore_dpll_bypass(struct clk_hw_omap *clk)
 185{
 186        int r;
 187        u8 ai;
 188
 189        if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS)))
 190                return -EINVAL;
 191
 192        pr_debug("clock: configuring DPLL %s for low-power bypass\n",
 193                 clk_hw_get_name(&clk->hw));
 194
 195        ai = omap3_dpll_autoidle_read(clk);
 196
 197        _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_BYPASS);
 198
 199        r = _omap3_wait_dpll_status(clk, 0);
 200
 201        if (ai)
 202                omap3_dpll_allow_idle(clk);
 203
 204        return r;
 205}
 206
 207/**
 208 * _omap3_noncore_dpll_stop - instruct a DPLL to stop
 209 * @clk: pointer to a DPLL struct clk
 210 *
 211 * Instructs a non-CORE DPLL to enter low-power stop. Will save and
 212 * restore the DPLL's autoidle state across the stop, per the CDP
 213 * code.  If DPLL3 was passed in, or the DPLL does not support
 214 * low-power stop, return -EINVAL; otherwise, return 0.
 215 */
 216static int _omap3_noncore_dpll_stop(struct clk_hw_omap *clk)
 217{
 218        u8 ai;
 219
 220        if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
 221                return -EINVAL;
 222
 223        pr_debug("clock: stopping DPLL %s\n", clk_hw_get_name(&clk->hw));
 224
 225        ai = omap3_dpll_autoidle_read(clk);
 226
 227        _omap3_dpll_write_clken(clk, DPLL_LOW_POWER_STOP);
 228
 229        if (ai)
 230                omap3_dpll_allow_idle(clk);
 231
 232        return 0;
 233}
 234
 235/**
 236 * _lookup_dco - Lookup DCO used by j-type DPLL
 237 * @clk: pointer to a DPLL struct clk
 238 * @dco: digital control oscillator selector
 239 * @m: DPLL multiplier to set
 240 * @n: DPLL divider to set
 241 *
 242 * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
 243 *
 244 * XXX This code is not needed for 3430/AM35xx; can it be optimized
 245 * out in non-multi-OMAP builds for those chips?
 246 */
 247static void _lookup_dco(struct clk_hw_omap *clk, u8 *dco, u16 m, u8 n)
 248{
 249        unsigned long fint, clkinp; /* watch out for overflow */
 250
 251        clkinp = clk_hw_get_rate(clk_hw_get_parent(&clk->hw));
 252        fint = (clkinp / n) * m;
 253
 254        if (fint < 1000000000)
 255                *dco = 2;
 256        else
 257                *dco = 4;
 258}
 259
 260/**
 261 * _lookup_sddiv - Calculate sigma delta divider for j-type DPLL
 262 * @clk: pointer to a DPLL struct clk
 263 * @sd_div: target sigma-delta divider
 264 * @m: DPLL multiplier to set
 265 * @n: DPLL divider to set
 266 *
 267 * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
 268 *
 269 * XXX This code is not needed for 3430/AM35xx; can it be optimized
 270 * out in non-multi-OMAP builds for those chips?
 271 */
 272static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n)
 273{
 274        unsigned long clkinp, sd; /* watch out for overflow */
 275        int mod1, mod2;
 276
 277        clkinp = clk_hw_get_rate(clk_hw_get_parent(&clk->hw));
 278
 279        /*
 280         * target sigma-delta to near 250MHz
 281         * sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)]
 282         */
 283        clkinp /= 100000; /* shift from MHz to 10*Hz for 38.4 and 19.2 */
 284        mod1 = (clkinp * m) % (250 * n);
 285        sd = (clkinp * m) / (250 * n);
 286        mod2 = sd % 10;
 287        sd /= 10;
 288
 289        if (mod1 || mod2)
 290                sd++;
 291        *sd_div = sd;
 292}
 293
 294/**
 295 * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly
 296 * @clk:        struct clk * of DPLL to set
 297 * @freqsel:    FREQSEL value to set
 298 *
 299 * Program the DPLL with the last M, N values calculated, and wait for
 300 * the DPLL to lock. Returns -EINVAL upon error, or 0 upon success.
 301 */
 302static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
 303{
 304        struct dpll_data *dd = clk->dpll_data;
 305        u8 dco, sd_div, ai = 0;
 306        u32 v;
 307        bool errata_i810;
 308
 309        /* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
 310        _omap3_noncore_dpll_bypass(clk);
 311
 312        /*
 313         * Set jitter correction. Jitter correction applicable for OMAP343X
 314         * only since freqsel field is no longer present on other devices.
 315         */
 316        if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) {
 317                v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
 318                v &= ~dd->freqsel_mask;
 319                v |= freqsel << __ffs(dd->freqsel_mask);
 320                ti_clk_ll_ops->clk_writel(v, &dd->control_reg);
 321        }
 322
 323        /* Set DPLL multiplier, divider */
 324        v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
 325
 326        /* Handle Duty Cycle Correction */
 327        if (dd->dcc_mask) {
 328                if (dd->last_rounded_rate >= dd->dcc_rate)
 329                        v |= dd->dcc_mask; /* Enable DCC */
 330                else
 331                        v &= ~dd->dcc_mask; /* Disable DCC */
 332        }
 333
 334        v &= ~(dd->mult_mask | dd->div1_mask);
 335        v |= dd->last_rounded_m << __ffs(dd->mult_mask);
 336        v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
 337
 338        /* Configure dco and sd_div for dplls that have these fields */
 339        if (dd->dco_mask) {
 340                _lookup_dco(clk, &dco, dd->last_rounded_m, dd->last_rounded_n);
 341                v &= ~(dd->dco_mask);
 342                v |= dco << __ffs(dd->dco_mask);
 343        }
 344        if (dd->sddiv_mask) {
 345                _lookup_sddiv(clk, &sd_div, dd->last_rounded_m,
 346                              dd->last_rounded_n);
 347                v &= ~(dd->sddiv_mask);
 348                v |= sd_div << __ffs(dd->sddiv_mask);
 349        }
 350
 351        /*
 352         * Errata i810 - DPLL controller can get stuck while transitioning
 353         * to a power saving state. Software must ensure the DPLL can not
 354         * transition to a low power state while changing M/N values.
 355         * Easiest way to accomplish this is to prevent DPLL autoidle
 356         * before doing the M/N re-program.
 357         */
 358        errata_i810 = ti_clk_get_features()->flags & TI_CLK_ERRATA_I810;
 359
 360        if (errata_i810) {
 361                ai = omap3_dpll_autoidle_read(clk);
 362                if (ai) {
 363                        omap3_dpll_deny_idle(clk);
 364
 365                        /* OCP barrier */
 366                        omap3_dpll_autoidle_read(clk);
 367                }
 368        }
 369
 370        ti_clk_ll_ops->clk_writel(v, &dd->mult_div1_reg);
 371
 372        /* Set 4X multiplier and low-power mode */
 373        if (dd->m4xen_mask || dd->lpmode_mask) {
 374                v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
 375
 376                if (dd->m4xen_mask) {
 377                        if (dd->last_rounded_m4xen)
 378                                v |= dd->m4xen_mask;
 379                        else
 380                                v &= ~dd->m4xen_mask;
 381                }
 382
 383                if (dd->lpmode_mask) {
 384                        if (dd->last_rounded_lpmode)
 385                                v |= dd->lpmode_mask;
 386                        else
 387                                v &= ~dd->lpmode_mask;
 388                }
 389
 390                ti_clk_ll_ops->clk_writel(v, &dd->control_reg);
 391        }
 392
 393        /* We let the clock framework set the other output dividers later */
 394
 395        /* REVISIT: Set ramp-up delay? */
 396
 397        _omap3_noncore_dpll_lock(clk);
 398
 399        if (errata_i810 && ai)
 400                omap3_dpll_allow_idle(clk);
 401
 402        return 0;
 403}
 404
 405/* Public functions */
 406
 407/**
 408 * omap3_dpll_recalc - recalculate DPLL rate
 409 * @hw: struct clk_hw containing the DPLL struct clk
 410 * @parent_rate: clock rate of the DPLL parent
 411 *
 412 * Recalculate and propagate the DPLL rate.
 413 */
 414unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate)
 415{
 416        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 417
 418        return omap2_get_dpll_rate(clk);
 419}
 420
 421/* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */
 422
 423/**
 424 * omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
 425 * @hw: struct clk_hw containing then pointer to a DPLL struct clk
 426 *
 427 * Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock.
 428 * The choice of modes depends on the DPLL's programmed rate: if it is
 429 * the same as the DPLL's parent clock, it will enter bypass;
 430 * otherwise, it will enter lock.  This code will wait for the DPLL to
 431 * indicate readiness before returning, unless the DPLL takes too long
 432 * to enter the target state.  Intended to be used as the struct clk's
 433 * enable function.  If DPLL3 was passed in, or the DPLL does not
 434 * support low-power stop, or if the DPLL took too long to enter
 435 * bypass or lock, return -EINVAL; otherwise, return 0.
 436 */
 437int omap3_noncore_dpll_enable(struct clk_hw *hw)
 438{
 439        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 440        int r;
 441        struct dpll_data *dd;
 442        struct clk_hw *parent;
 443
 444        dd = clk->dpll_data;
 445        if (!dd)
 446                return -EINVAL;
 447
 448        if (clk->clkdm) {
 449                r = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
 450                if (r) {
 451                        WARN(1,
 452                             "%s: could not enable %s's clockdomain %s: %d\n",
 453                             __func__, clk_hw_get_name(hw),
 454                             clk->clkdm_name, r);
 455                        return r;
 456                }
 457        }
 458
 459        parent = clk_hw_get_parent(hw);
 460
 461        if (clk_hw_get_rate(hw) == clk_hw_get_rate(dd->clk_bypass)) {
 462                WARN_ON(parent != dd->clk_bypass);
 463                r = _omap3_noncore_dpll_bypass(clk);
 464        } else {
 465                WARN_ON(parent != dd->clk_ref);
 466                r = _omap3_noncore_dpll_lock(clk);
 467        }
 468
 469        return r;
 470}
 471
 472/**
 473 * omap3_noncore_dpll_disable - instruct a DPLL to enter low-power stop
 474 * @hw: struct clk_hw containing then pointer to a DPLL struct clk
 475 *
 476 * Instructs a non-CORE DPLL to enter low-power stop.  This function is
 477 * intended for use in struct clkops.  No return value.
 478 */
 479void omap3_noncore_dpll_disable(struct clk_hw *hw)
 480{
 481        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 482
 483        _omap3_noncore_dpll_stop(clk);
 484        if (clk->clkdm)
 485                ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
 486}
 487
 488/* Non-CORE DPLL rate set code */
 489
 490/**
 491 * omap3_noncore_dpll_determine_rate - determine rate for a DPLL
 492 * @hw: pointer to the clock to determine rate for
 493 * @req: target rate request
 494 *
 495 * Determines which DPLL mode to use for reaching a desired target rate.
 496 * Checks whether the DPLL shall be in bypass or locked mode, and if
 497 * locked, calculates the M,N values for the DPLL via round-rate.
 498 * Returns a 0 on success, negative error value in failure.
 499 */
 500int omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
 501                                      struct clk_rate_request *req)
 502{
 503        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 504        struct dpll_data *dd;
 505
 506        if (!req->rate)
 507                return -EINVAL;
 508
 509        dd = clk->dpll_data;
 510        if (!dd)
 511                return -EINVAL;
 512
 513        if (clk_hw_get_rate(dd->clk_bypass) == req->rate &&
 514            (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
 515                req->best_parent_hw = dd->clk_bypass;
 516        } else {
 517                req->rate = omap2_dpll_round_rate(hw, req->rate,
 518                                          &req->best_parent_rate);
 519                req->best_parent_hw = dd->clk_ref;
 520        }
 521
 522        req->best_parent_rate = req->rate;
 523
 524        return 0;
 525}
 526
 527/**
 528 * omap3_noncore_dpll_set_parent - set parent for a DPLL clock
 529 * @hw: pointer to the clock to set parent for
 530 * @index: parent index to select
 531 *
 532 * Sets parent for a DPLL clock. This sets the DPLL into bypass or
 533 * locked mode. Returns 0 with success, negative error value otherwise.
 534 */
 535int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index)
 536{
 537        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 538        int ret;
 539
 540        if (!hw)
 541                return -EINVAL;
 542
 543        if (index)
 544                ret = _omap3_noncore_dpll_bypass(clk);
 545        else
 546                ret = _omap3_noncore_dpll_lock(clk);
 547
 548        return ret;
 549}
 550
 551/**
 552 * omap3_noncore_dpll_set_rate - set rate for a DPLL clock
 553 * @hw: pointer to the clock to set parent for
 554 * @rate: target rate for the clock
 555 * @parent_rate: rate of the parent clock
 556 *
 557 * Sets rate for a DPLL clock. First checks if the clock parent is
 558 * reference clock (in bypass mode, the rate of the clock can't be
 559 * changed) and proceeds with the rate change operation. Returns 0
 560 * with success, negative error value otherwise.
 561 */
 562int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
 563                                unsigned long parent_rate)
 564{
 565        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 566        struct dpll_data *dd;
 567        u16 freqsel = 0;
 568        int ret;
 569
 570        if (!hw || !rate)
 571                return -EINVAL;
 572
 573        dd = clk->dpll_data;
 574        if (!dd)
 575                return -EINVAL;
 576
 577        if (clk_hw_get_parent(hw) != dd->clk_ref)
 578                return -EINVAL;
 579
 580        if (dd->last_rounded_rate == 0)
 581                return -EINVAL;
 582
 583        /* Freqsel is available only on OMAP343X devices */
 584        if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) {
 585                freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
 586                WARN_ON(!freqsel);
 587        }
 588
 589        pr_debug("%s: %s: set rate: locking rate to %lu.\n", __func__,
 590                 clk_hw_get_name(hw), rate);
 591
 592        ret = omap3_noncore_dpll_program(clk, freqsel);
 593
 594        return ret;
 595}
 596
 597/**
 598 * omap3_noncore_dpll_set_rate_and_parent - set rate and parent for a DPLL clock
 599 * @hw: pointer to the clock to set rate and parent for
 600 * @rate: target rate for the DPLL
 601 * @parent_rate: clock rate of the DPLL parent
 602 * @index: new parent index for the DPLL, 0 - reference, 1 - bypass
 603 *
 604 * Sets rate and parent for a DPLL clock. If new parent is the bypass
 605 * clock, only selects the parent. Otherwise proceeds with a rate
 606 * change, as this will effectively also change the parent as the
 607 * DPLL is put into locked mode. Returns 0 with success, negative error
 608 * value otherwise.
 609 */
 610int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
 611                                           unsigned long rate,
 612                                           unsigned long parent_rate,
 613                                           u8 index)
 614{
 615        int ret;
 616
 617        if (!hw || !rate)
 618                return -EINVAL;
 619
 620        /*
 621         * clk-ref at index[0], in which case we only need to set rate,
 622         * the parent will be changed automatically with the lock sequence.
 623         * With clk-bypass case we only need to change parent.
 624         */
 625        if (index)
 626                ret = omap3_noncore_dpll_set_parent(hw, index);
 627        else
 628                ret = omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
 629
 630        return ret;
 631}
 632
 633/* DPLL autoidle read/set code */
 634
 635/**
 636 * omap3_dpll_autoidle_read - read a DPLL's autoidle bits
 637 * @clk: struct clk * of the DPLL to read
 638 *
 639 * Return the DPLL's autoidle bits, shifted down to bit 0.  Returns
 640 * -EINVAL if passed a null pointer or if the struct clk does not
 641 * appear to refer to a DPLL.
 642 */
 643static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
 644{
 645        const struct dpll_data *dd;
 646        u32 v;
 647
 648        if (!clk || !clk->dpll_data)
 649                return -EINVAL;
 650
 651        dd = clk->dpll_data;
 652
 653        if (!dd->autoidle_mask)
 654                return -EINVAL;
 655
 656        v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg);
 657        v &= dd->autoidle_mask;
 658        v >>= __ffs(dd->autoidle_mask);
 659
 660        return v;
 661}
 662
 663/**
 664 * omap3_dpll_allow_idle - enable DPLL autoidle bits
 665 * @clk: struct clk * of the DPLL to operate on
 666 *
 667 * Enable DPLL automatic idle control.  This automatic idle mode
 668 * switching takes effect only when the DPLL is locked, at least on
 669 * OMAP3430.  The DPLL will enter low-power stop when its downstream
 670 * clocks are gated.  No return value.
 671 */
 672static void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
 673{
 674        const struct dpll_data *dd;
 675        u32 v;
 676
 677        if (!clk || !clk->dpll_data)
 678                return;
 679
 680        dd = clk->dpll_data;
 681
 682        if (!dd->autoidle_mask)
 683                return;
 684
 685        /*
 686         * REVISIT: CORE DPLL can optionally enter low-power bypass
 687         * by writing 0x5 instead of 0x1.  Add some mechanism to
 688         * optionally enter this mode.
 689         */
 690        v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg);
 691        v &= ~dd->autoidle_mask;
 692        v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
 693        ti_clk_ll_ops->clk_writel(v, &dd->autoidle_reg);
 694}
 695
 696/**
 697 * omap3_dpll_deny_idle - prevent DPLL from automatically idling
 698 * @clk: struct clk * of the DPLL to operate on
 699 *
 700 * Disable DPLL automatic idle control.  No return value.
 701 */
 702static void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
 703{
 704        const struct dpll_data *dd;
 705        u32 v;
 706
 707        if (!clk || !clk->dpll_data)
 708                return;
 709
 710        dd = clk->dpll_data;
 711
 712        if (!dd->autoidle_mask)
 713                return;
 714
 715        v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg);
 716        v &= ~dd->autoidle_mask;
 717        v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
 718        ti_clk_ll_ops->clk_writel(v, &dd->autoidle_reg);
 719}
 720
 721/* Clock control for DPLL outputs */
 722
 723/* Find the parent DPLL for the given clkoutx2 clock */
 724static struct clk_hw_omap *omap3_find_clkoutx2_dpll(struct clk_hw *hw)
 725{
 726        struct clk_hw_omap *pclk = NULL;
 727
 728        /* Walk up the parents of clk, looking for a DPLL */
 729        do {
 730                do {
 731                        hw = clk_hw_get_parent(hw);
 732                } while (hw && (!omap2_clk_is_hw_omap(hw)));
 733                if (!hw)
 734                        break;
 735                pclk = to_clk_hw_omap(hw);
 736        } while (pclk && !pclk->dpll_data);
 737
 738        /* clk does not have a DPLL as a parent?  error in the clock data */
 739        if (!pclk) {
 740                WARN_ON(1);
 741                return NULL;
 742        }
 743
 744        return pclk;
 745}
 746
 747/**
 748 * omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
 749 * @hw: pointer  struct clk_hw
 750 * @parent_rate: clock rate of the DPLL parent
 751 *
 752 * Using parent clock DPLL data, look up DPLL state.  If locked, set our
 753 * rate to the dpll_clk * 2; otherwise, just use dpll_clk.
 754 */
 755unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 756                                    unsigned long parent_rate)
 757{
 758        const struct dpll_data *dd;
 759        unsigned long rate;
 760        u32 v;
 761        struct clk_hw_omap *pclk = NULL;
 762
 763        if (!parent_rate)
 764                return 0;
 765
 766        pclk = omap3_find_clkoutx2_dpll(hw);
 767
 768        if (!pclk)
 769                return 0;
 770
 771        dd = pclk->dpll_data;
 772
 773        WARN_ON(!dd->enable_mask);
 774
 775        v = ti_clk_ll_ops->clk_readl(&dd->control_reg) & dd->enable_mask;
 776        v >>= __ffs(dd->enable_mask);
 777        if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
 778                rate = parent_rate;
 779        else
 780                rate = parent_rate * 2;
 781        return rate;
 782}
 783
 784/**
 785 * omap3_core_dpll_save_context - Save the m and n values of the divider
 786 * @hw: pointer  struct clk_hw
 787 *
 788 * Before the dpll registers are lost save the last rounded rate m and n
 789 * and the enable mask.
 790 */
 791int omap3_core_dpll_save_context(struct clk_hw *hw)
 792{
 793        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 794        struct dpll_data *dd;
 795        u32 v;
 796
 797        dd = clk->dpll_data;
 798
 799        v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
 800        clk->context = (v & dd->enable_mask) >> __ffs(dd->enable_mask);
 801
 802        if (clk->context == DPLL_LOCKED) {
 803                v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
 804                dd->last_rounded_m = (v & dd->mult_mask) >>
 805                                                __ffs(dd->mult_mask);
 806                dd->last_rounded_n = ((v & dd->div1_mask) >>
 807                                                __ffs(dd->div1_mask)) + 1;
 808        }
 809
 810        return 0;
 811}
 812
 813/**
 814 * omap3_core_dpll_restore_context - restore the m and n values of the divider
 815 * @hw: pointer  struct clk_hw
 816 *
 817 * Restore the last rounded rate m and n
 818 * and the enable mask.
 819 */
 820void omap3_core_dpll_restore_context(struct clk_hw *hw)
 821{
 822        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 823        const struct dpll_data *dd;
 824        u32 v;
 825
 826        dd = clk->dpll_data;
 827
 828        if (clk->context == DPLL_LOCKED) {
 829                _omap3_dpll_write_clken(clk, 0x4);
 830                _omap3_wait_dpll_status(clk, 0);
 831
 832                v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
 833                v &= ~(dd->mult_mask | dd->div1_mask);
 834                v |= dd->last_rounded_m << __ffs(dd->mult_mask);
 835                v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
 836                ti_clk_ll_ops->clk_writel(v, &dd->mult_div1_reg);
 837
 838                _omap3_dpll_write_clken(clk, DPLL_LOCKED);
 839                _omap3_wait_dpll_status(clk, 1);
 840        } else {
 841                _omap3_dpll_write_clken(clk, clk->context);
 842        }
 843}
 844
 845/**
 846 * omap3_non_core_dpll_save_context - Save the m and n values of the divider
 847 * @hw: pointer  struct clk_hw
 848 *
 849 * Before the dpll registers are lost save the last rounded rate m and n
 850 * and the enable mask.
 851 */
 852int omap3_noncore_dpll_save_context(struct clk_hw *hw)
 853{
 854        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 855        struct dpll_data *dd;
 856        u32 v;
 857
 858        dd = clk->dpll_data;
 859
 860        v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
 861        clk->context = (v & dd->enable_mask) >> __ffs(dd->enable_mask);
 862
 863        if (clk->context == DPLL_LOCKED) {
 864                v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
 865                dd->last_rounded_m = (v & dd->mult_mask) >>
 866                                                __ffs(dd->mult_mask);
 867                dd->last_rounded_n = ((v & dd->div1_mask) >>
 868                                                __ffs(dd->div1_mask)) + 1;
 869        }
 870
 871        return 0;
 872}
 873
 874/**
 875 * omap3_core_dpll_restore_context - restore the m and n values of the divider
 876 * @hw: pointer  struct clk_hw
 877 *
 878 * Restore the last rounded rate m and n
 879 * and the enable mask.
 880 */
 881void omap3_noncore_dpll_restore_context(struct clk_hw *hw)
 882{
 883        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 884        const struct dpll_data *dd;
 885        u32 ctrl, mult_div1;
 886
 887        dd = clk->dpll_data;
 888
 889        ctrl = ti_clk_ll_ops->clk_readl(&dd->control_reg);
 890        mult_div1 = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
 891
 892        if (clk->context == ((ctrl & dd->enable_mask) >>
 893                             __ffs(dd->enable_mask)) &&
 894            dd->last_rounded_m == ((mult_div1 & dd->mult_mask) >>
 895                                   __ffs(dd->mult_mask)) &&
 896            dd->last_rounded_n == ((mult_div1 & dd->div1_mask) >>
 897                                   __ffs(dd->div1_mask)) + 1) {
 898                /* nothing to be done */
 899                return;
 900        }
 901
 902        if (clk->context == DPLL_LOCKED)
 903                omap3_noncore_dpll_program(clk, 0);
 904        else
 905                _omap3_dpll_write_clken(clk, clk->context);
 906}
 907
 908/* OMAP3/4 non-CORE DPLL clkops */
 909const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
 910        .allow_idle     = omap3_dpll_allow_idle,
 911        .deny_idle      = omap3_dpll_deny_idle,
 912};
 913
 914/**
 915 * omap3_dpll4_set_rate - set rate for omap3 per-dpll
 916 * @hw: clock to change
 917 * @rate: target rate for clock
 918 * @parent_rate: clock rate of the DPLL parent
 919 *
 920 * Check if the current SoC supports the per-dpll reprogram operation
 921 * or not, and then do the rate change if supported. Returns -EINVAL
 922 * if not supported, 0 for success, and potential error codes from the
 923 * clock rate change.
 924 */
 925int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
 926                         unsigned long parent_rate)
 927{
 928        /*
 929         * According to the 12-5 CDP code from TI, "Limitation 2.5"
 930         * on 3430ES1 prevents us from changing DPLL multipliers or dividers
 931         * on DPLL4.
 932         */
 933        if (ti_clk_get_features()->flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
 934                pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
 935                return -EINVAL;
 936        }
 937
 938        return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
 939}
 940
 941/**
 942 * omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
 943 * @hw: clock to change
 944 * @rate: target rate for clock
 945 * @parent_rate: rate of the parent clock
 946 * @index: parent index, 0 - reference clock, 1 - bypass clock
 947 *
 948 * Check if the current SoC support the per-dpll reprogram operation
 949 * or not, and then do the rate + parent change if supported. Returns
 950 * -EINVAL if not supported, 0 for success, and potential error codes
 951 * from the clock rate change.
 952 */
 953int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
 954                                    unsigned long parent_rate, u8 index)
 955{
 956        if (ti_clk_get_features()->flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
 957                pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
 958                return -EINVAL;
 959        }
 960
 961        return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
 962                                                      index);
 963}
 964
 965/* Apply DM3730 errata sprz319 advisory 2.1. */
 966static bool omap3_dpll5_apply_errata(struct clk_hw *hw,
 967                                     unsigned long parent_rate)
 968{
 969        struct omap3_dpll5_settings {
 970                unsigned int rate, m, n;
 971        };
 972
 973        static const struct omap3_dpll5_settings precomputed[] = {
 974                /*
 975                 * From DM3730 errata advisory 2.1, table 35 and 36.
 976                 * The N value is increased by 1 compared to the tables as the
 977                 * errata lists register values while last_rounded_field is the
 978                 * real divider value.
 979                 */
 980                { 12000000,  80,  0 + 1 },
 981                { 13000000, 443,  5 + 1 },
 982                { 19200000,  50,  0 + 1 },
 983                { 26000000, 443, 11 + 1 },
 984                { 38400000,  25,  0 + 1 }
 985        };
 986
 987        const struct omap3_dpll5_settings *d;
 988        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 989        struct dpll_data *dd;
 990        unsigned int i;
 991
 992        for (i = 0; i < ARRAY_SIZE(precomputed); ++i) {
 993                if (parent_rate == precomputed[i].rate)
 994                        break;
 995        }
 996
 997        if (i == ARRAY_SIZE(precomputed))
 998                return false;
 999
1000        d = &precomputed[i];
1001
1002        /* Update the M, N and rounded rate values and program the DPLL. */
1003        dd = clk->dpll_data;
1004        dd->last_rounded_m = d->m;
1005        dd->last_rounded_n = d->n;
1006        dd->last_rounded_rate = div_u64((u64)parent_rate * d->m, d->n);
1007        omap3_noncore_dpll_program(clk, 0);
1008
1009        return true;
1010}
1011
1012/**
1013 * omap3_dpll5_set_rate - set rate for omap3 dpll5
1014 * @hw: clock to change
1015 * @rate: target rate for clock
1016 * @parent_rate: rate of the parent clock
1017 *
1018 * Set rate for the DPLL5 clock. Apply the sprz319 advisory 2.1 on OMAP36xx if
1019 * the DPLL is used for USB host (detected through the requested rate).
1020 */
1021int omap3_dpll5_set_rate(struct clk_hw *hw, unsigned long rate,
1022                         unsigned long parent_rate)
1023{
1024        if (rate == OMAP3_DPLL5_FREQ_FOR_USBHOST * 8) {
1025                if (omap3_dpll5_apply_errata(hw, parent_rate))
1026                        return 0;
1027        }
1028
1029        return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
1030}
1031