linux/arch/arm/mach-omap2/clock.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/mach-omap2/clock.c
   3 *
   4 *  Copyright (C) 2005-2008 Texas Instruments, Inc.
   5 *  Copyright (C) 2004-2010 Nokia Corporation
   6 *
   7 *  Contacts:
   8 *  Richard Woodruff <r-woodruff2@ti.com>
   9 *  Paul Walmsley
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License version 2 as
  13 * published by the Free Software Foundation.
  14 */
  15#undef DEBUG
  16
  17#include <linux/kernel.h>
  18#include <linux/export.h>
  19#include <linux/list.h>
  20#include <linux/errno.h>
  21#include <linux/err.h>
  22#include <linux/delay.h>
  23#include <linux/clk-provider.h>
  24#include <linux/io.h>
  25#include <linux/bitops.h>
  26#include <linux/clk-private.h>
  27#include <asm/cpu.h>
  28
  29
  30#include <trace/events/power.h>
  31
  32#include "soc.h"
  33#include "clockdomain.h"
  34#include "clock.h"
  35#include "cm.h"
  36#include "cm2xxx.h"
  37#include "cm3xxx.h"
  38#include "cm-regbits-24xx.h"
  39#include "cm-regbits-34xx.h"
  40#include "common.h"
  41
  42/*
  43 * MAX_MODULE_ENABLE_WAIT: maximum of number of microseconds to wait
  44 * for a module to indicate that it is no longer in idle
  45 */
  46#define MAX_MODULE_ENABLE_WAIT          100000
  47
  48u16 cpu_mask;
  49
  50/*
  51 * clkdm_control: if true, then when a clock is enabled in the
  52 * hardware, its clockdomain will first be enabled; and when a clock
  53 * is disabled in the hardware, its clockdomain will be disabled
  54 * afterwards.
  55 */
  56static bool clkdm_control = true;
  57
  58static LIST_HEAD(clk_hw_omap_clocks);
  59
  60/*
  61 * Used for clocks that have the same value as the parent clock,
  62 * divided by some factor
  63 */
  64unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
  65                unsigned long parent_rate)
  66{
  67        struct clk_hw_omap *oclk;
  68
  69        if (!hw) {
  70                pr_warn("%s: hw is NULL\n", __func__);
  71                return -EINVAL;
  72        }
  73
  74        oclk = to_clk_hw_omap(hw);
  75
  76        WARN_ON(!oclk->fixed_div);
  77
  78        return parent_rate / oclk->fixed_div;
  79}
  80
  81/*
  82 * OMAP2+ specific clock functions
  83 */
  84
  85/* Private functions */
  86
  87
  88/**
  89 * _wait_idlest_generic - wait for a module to leave the idle state
  90 * @reg: virtual address of module IDLEST register
  91 * @mask: value to mask against to determine if the module is active
  92 * @idlest: idle state indicator (0 or 1) for the clock
  93 * @name: name of the clock (for printk)
  94 *
  95 * Wait for a module to leave idle, where its idle-status register is
  96 * not inside the CM module.  Returns 1 if the module left idle
  97 * promptly, or 0 if the module did not leave idle before the timeout
  98 * elapsed.  XXX Deprecated - should be moved into drivers for the
  99 * individual IP block that the IDLEST register exists in.
 100 */
 101static int _wait_idlest_generic(void __iomem *reg, u32 mask, u8 idlest,
 102                                const char *name)
 103{
 104        int i = 0, ena = 0;
 105
 106        ena = (idlest) ? 0 : mask;
 107
 108        omap_test_timeout(((__raw_readl(reg) & mask) == ena),
 109                          MAX_MODULE_ENABLE_WAIT, i);
 110
 111        if (i < MAX_MODULE_ENABLE_WAIT)
 112                pr_debug("omap clock: module associated with clock %s ready after %d loops\n",
 113                         name, i);
 114        else
 115                pr_err("omap clock: module associated with clock %s didn't enable in %d tries\n",
 116                       name, MAX_MODULE_ENABLE_WAIT);
 117
 118        return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
 119};
 120
 121/**
 122 * _omap2_module_wait_ready - wait for an OMAP module to leave IDLE
 123 * @clk: struct clk * belonging to the module
 124 *
 125 * If the necessary clocks for the OMAP hardware IP block that
 126 * corresponds to clock @clk are enabled, then wait for the module to
 127 * indicate readiness (i.e., to leave IDLE).  This code does not
 128 * belong in the clock code and will be moved in the medium term to
 129 * module-dependent code.  No return value.
 130 */
 131static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
 132{
 133        void __iomem *companion_reg, *idlest_reg;
 134        u8 other_bit, idlest_bit, idlest_val, idlest_reg_id;
 135        s16 prcm_mod;
 136        int r;
 137
 138        /* Not all modules have multiple clocks that their IDLEST depends on */
 139        if (clk->ops->find_companion) {
 140                clk->ops->find_companion(clk, &companion_reg, &other_bit);
 141                if (!(__raw_readl(companion_reg) & (1 << other_bit)))
 142                        return;
 143        }
 144
 145        clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
 146        r = cm_split_idlest_reg(idlest_reg, &prcm_mod, &idlest_reg_id);
 147        if (r) {
 148                /* IDLEST register not in the CM module */
 149                _wait_idlest_generic(idlest_reg, (1 << idlest_bit), idlest_val,
 150                                     __clk_get_name(clk->hw.clk));
 151        } else {
 152                cm_wait_module_ready(prcm_mod, idlest_reg_id, idlest_bit);
 153        };
 154}
 155
 156/* Public functions */
 157
 158/**
 159 * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk
 160 * @clk: OMAP clock struct ptr to use
 161 *
 162 * Convert a clockdomain name stored in a struct clk 'clk' into a
 163 * clockdomain pointer, and save it into the struct clk.  Intended to be
 164 * called during clk_register().  No return value.
 165 */
 166void omap2_init_clk_clkdm(struct clk_hw *hw)
 167{
 168        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 169        struct clockdomain *clkdm;
 170        const char *clk_name;
 171
 172        if (!clk->clkdm_name)
 173                return;
 174
 175        clk_name = __clk_get_name(hw->clk);
 176
 177        clkdm = clkdm_lookup(clk->clkdm_name);
 178        if (clkdm) {
 179                pr_debug("clock: associated clk %s to clkdm %s\n",
 180                         clk_name, clk->clkdm_name);
 181                clk->clkdm = clkdm;
 182        } else {
 183                pr_debug("clock: could not associate clk %s to clkdm %s\n",
 184                         clk_name, clk->clkdm_name);
 185        }
 186}
 187
 188/**
 189 * omap2_clk_disable_clkdm_control - disable clkdm control on clk enable/disable
 190 *
 191 * Prevent the OMAP clock code from calling into the clockdomain code
 192 * when a hardware clock in that clockdomain is enabled or disabled.
 193 * Intended to be called at init time from omap*_clk_init().  No
 194 * return value.
 195 */
 196void __init omap2_clk_disable_clkdm_control(void)
 197{
 198        clkdm_control = false;
 199}
 200
 201/**
 202 * omap2_clk_dflt_find_companion - find companion clock to @clk
 203 * @clk: struct clk * to find the companion clock of
 204 * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
 205 * @other_bit: u8 ** to return the companion clock bit shift in
 206 *
 207 * Note: We don't need special code here for INVERT_ENABLE for the
 208 * time being since INVERT_ENABLE only applies to clocks enabled by
 209 * CM_CLKEN_PLL
 210 *
 211 * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes it's
 212 * just a matter of XORing the bits.
 213 *
 214 * Some clocks don't have companion clocks.  For example, modules with
 215 * only an interface clock (such as MAILBOXES) don't have a companion
 216 * clock.  Right now, this code relies on the hardware exporting a bit
 217 * in the correct companion register that indicates that the
 218 * nonexistent 'companion clock' is active.  Future patches will
 219 * associate this type of code with per-module data structures to
 220 * avoid this issue, and remove the casts.  No return value.
 221 */
 222void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
 223                        void __iomem **other_reg, u8 *other_bit)
 224{
 225        u32 r;
 226
 227        /*
 228         * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes
 229         * it's just a matter of XORing the bits.
 230         */
 231        r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN));
 232
 233        *other_reg = (__force void __iomem *)r;
 234        *other_bit = clk->enable_bit;
 235}
 236
 237/**
 238 * omap2_clk_dflt_find_idlest - find CM_IDLEST reg va, bit shift for @clk
 239 * @clk: struct clk * to find IDLEST info for
 240 * @idlest_reg: void __iomem ** to return the CM_IDLEST va in
 241 * @idlest_bit: u8 * to return the CM_IDLEST bit shift in
 242 * @idlest_val: u8 * to return the idle status indicator
 243 *
 244 * Return the CM_IDLEST register address and bit shift corresponding
 245 * to the module that "owns" this clock.  This default code assumes
 246 * that the CM_IDLEST bit shift is the CM_*CLKEN bit shift, and that
 247 * the IDLEST register address ID corresponds to the CM_*CLKEN
 248 * register address ID (e.g., that CM_FCLKEN2 corresponds to
 249 * CM_IDLEST2).  This is not true for all modules.  No return value.
 250 */
 251void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
 252                void __iomem **idlest_reg, u8 *idlest_bit, u8 *idlest_val)
 253{
 254        u32 r;
 255
 256        r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
 257        *idlest_reg = (__force void __iomem *)r;
 258        *idlest_bit = clk->enable_bit;
 259
 260        /*
 261         * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
 262         * 34xx reverses this, just to keep us on our toes
 263         * AM35xx uses both, depending on the module.
 264         */
 265        if (cpu_is_omap24xx())
 266                *idlest_val = OMAP24XX_CM_IDLEST_VAL;
 267        else if (cpu_is_omap34xx())
 268                *idlest_val = OMAP34XX_CM_IDLEST_VAL;
 269        else
 270                BUG();
 271
 272}
 273
 274/**
 275 * omap2_dflt_clk_enable - enable a clock in the hardware
 276 * @hw: struct clk_hw * of the clock to enable
 277 *
 278 * Enable the clock @hw in the hardware.  We first call into the OMAP
 279 * clockdomain code to "enable" the corresponding clockdomain if this
 280 * is the first enabled user of the clockdomain.  Then program the
 281 * hardware to enable the clock.  Then wait for the IP block that uses
 282 * this clock to leave idle (if applicable).  Returns the error value
 283 * from clkdm_clk_enable() if it terminated with an error, or -EINVAL
 284 * if @hw has a null clock enable_reg, or zero upon success.
 285 */
 286int omap2_dflt_clk_enable(struct clk_hw *hw)
 287{
 288        struct clk_hw_omap *clk;
 289        u32 v;
 290        int ret = 0;
 291
 292        clk = to_clk_hw_omap(hw);
 293
 294        if (clkdm_control && clk->clkdm) {
 295                ret = clkdm_clk_enable(clk->clkdm, hw->clk);
 296                if (ret) {
 297                        WARN(1, "%s: could not enable %s's clockdomain %s: %d\n",
 298                             __func__, __clk_get_name(hw->clk),
 299                             clk->clkdm->name, ret);
 300                        return ret;
 301                }
 302        }
 303
 304        if (unlikely(clk->enable_reg == NULL)) {
 305                pr_err("%s: %s missing enable_reg\n", __func__,
 306                       __clk_get_name(hw->clk));
 307                ret = -EINVAL;
 308                goto err;
 309        }
 310
 311        /* FIXME should not have INVERT_ENABLE bit here */
 312        v = __raw_readl(clk->enable_reg);
 313        if (clk->flags & INVERT_ENABLE)
 314                v &= ~(1 << clk->enable_bit);
 315        else
 316                v |= (1 << clk->enable_bit);
 317        __raw_writel(v, clk->enable_reg);
 318        v = __raw_readl(clk->enable_reg); /* OCP barrier */
 319
 320        if (clk->ops && clk->ops->find_idlest)
 321                _omap2_module_wait_ready(clk);
 322
 323        return 0;
 324
 325err:
 326        if (clkdm_control && clk->clkdm)
 327                clkdm_clk_disable(clk->clkdm, hw->clk);
 328        return ret;
 329}
 330
 331/**
 332 * omap2_dflt_clk_disable - disable a clock in the hardware
 333 * @hw: struct clk_hw * of the clock to disable
 334 *
 335 * Disable the clock @hw in the hardware, and call into the OMAP
 336 * clockdomain code to "disable" the corresponding clockdomain if all
 337 * clocks/hwmods in that clockdomain are now disabled.  No return
 338 * value.
 339 */
 340void omap2_dflt_clk_disable(struct clk_hw *hw)
 341{
 342        struct clk_hw_omap *clk;
 343        u32 v;
 344
 345        clk = to_clk_hw_omap(hw);
 346        if (!clk->enable_reg) {
 347                /*
 348                 * 'independent' here refers to a clock which is not
 349                 * controlled by its parent.
 350                 */
 351                pr_err("%s: independent clock %s has no enable_reg\n",
 352                       __func__, __clk_get_name(hw->clk));
 353                return;
 354        }
 355
 356        v = __raw_readl(clk->enable_reg);
 357        if (clk->flags & INVERT_ENABLE)
 358                v |= (1 << clk->enable_bit);
 359        else
 360                v &= ~(1 << clk->enable_bit);
 361        __raw_writel(v, clk->enable_reg);
 362        /* No OCP barrier needed here since it is a disable operation */
 363
 364        if (clkdm_control && clk->clkdm)
 365                clkdm_clk_disable(clk->clkdm, hw->clk);
 366}
 367
 368/**
 369 * omap2_clkops_enable_clkdm - increment usecount on clkdm of @hw
 370 * @hw: struct clk_hw * of the clock being enabled
 371 *
 372 * Increment the usecount of the clockdomain of the clock pointed to
 373 * by @hw; if the usecount is 1, the clockdomain will be "enabled."
 374 * Only needed for clocks that don't use omap2_dflt_clk_enable() as
 375 * their enable function pointer.  Passes along the return value of
 376 * clkdm_clk_enable(), -EINVAL if @hw is not associated with a
 377 * clockdomain, or 0 if clock framework-based clockdomain control is
 378 * not implemented.
 379 */
 380int omap2_clkops_enable_clkdm(struct clk_hw *hw)
 381{
 382        struct clk_hw_omap *clk;
 383        int ret = 0;
 384
 385        clk = to_clk_hw_omap(hw);
 386
 387        if (unlikely(!clk->clkdm)) {
 388                pr_err("%s: %s: no clkdm set ?!\n", __func__,
 389                       __clk_get_name(hw->clk));
 390                return -EINVAL;
 391        }
 392
 393        if (unlikely(clk->enable_reg))
 394                pr_err("%s: %s: should use dflt_clk_enable ?!\n", __func__,
 395                       __clk_get_name(hw->clk));
 396
 397        if (!clkdm_control) {
 398                pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
 399                       __func__, __clk_get_name(hw->clk));
 400                return 0;
 401        }
 402
 403        ret = clkdm_clk_enable(clk->clkdm, hw->clk);
 404        WARN(ret, "%s: could not enable %s's clockdomain %s: %d\n",
 405             __func__, __clk_get_name(hw->clk), clk->clkdm->name, ret);
 406
 407        return ret;
 408}
 409
 410/**
 411 * omap2_clkops_disable_clkdm - decrement usecount on clkdm of @hw
 412 * @hw: struct clk_hw * of the clock being disabled
 413 *
 414 * Decrement the usecount of the clockdomain of the clock pointed to
 415 * by @hw; if the usecount is 0, the clockdomain will be "disabled."
 416 * Only needed for clocks that don't use omap2_dflt_clk_disable() as their
 417 * disable function pointer.  No return value.
 418 */
 419void omap2_clkops_disable_clkdm(struct clk_hw *hw)
 420{
 421        struct clk_hw_omap *clk;
 422
 423        clk = to_clk_hw_omap(hw);
 424
 425        if (unlikely(!clk->clkdm)) {
 426                pr_err("%s: %s: no clkdm set ?!\n", __func__,
 427                       __clk_get_name(hw->clk));
 428                return;
 429        }
 430
 431        if (unlikely(clk->enable_reg))
 432                pr_err("%s: %s: should use dflt_clk_disable ?!\n", __func__,
 433                       __clk_get_name(hw->clk));
 434
 435        if (!clkdm_control) {
 436                pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
 437                       __func__, __clk_get_name(hw->clk));
 438                return;
 439        }
 440
 441        clkdm_clk_disable(clk->clkdm, hw->clk);
 442}
 443
 444/**
 445 * omap2_dflt_clk_is_enabled - is clock enabled in the hardware?
 446 * @hw: struct clk_hw * to check
 447 *
 448 * Return 1 if the clock represented by @hw is enabled in the
 449 * hardware, or 0 otherwise.  Intended for use in the struct
 450 * clk_ops.is_enabled function pointer.
 451 */
 452int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
 453{
 454        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 455        u32 v;
 456
 457        v = __raw_readl(clk->enable_reg);
 458
 459        if (clk->flags & INVERT_ENABLE)
 460                v ^= BIT(clk->enable_bit);
 461
 462        v &= BIT(clk->enable_bit);
 463
 464        return v ? 1 : 0;
 465}
 466
 467static int __initdata mpurate;
 468
 469/*
 470 * By default we use the rate set by the bootloader.
 471 * You can override this with mpurate= cmdline option.
 472 */
 473static int __init omap_clk_setup(char *str)
 474{
 475        get_option(&str, &mpurate);
 476
 477        if (!mpurate)
 478                return 1;
 479
 480        if (mpurate < 1000)
 481                mpurate *= 1000000;
 482
 483        return 1;
 484}
 485__setup("mpurate=", omap_clk_setup);
 486
 487/**
 488 * omap2_init_clk_hw_omap_clocks - initialize an OMAP clock
 489 * @clk: struct clk * to initialize
 490 *
 491 * Add an OMAP clock @clk to the internal list of OMAP clocks.  Used
 492 * temporarily for autoidle handling, until this support can be
 493 * integrated into the common clock framework code in some way.  No
 494 * return value.
 495 */
 496void omap2_init_clk_hw_omap_clocks(struct clk *clk)
 497{
 498        struct clk_hw_omap *c;
 499
 500        if (__clk_get_flags(clk) & CLK_IS_BASIC)
 501                return;
 502
 503        c = to_clk_hw_omap(__clk_get_hw(clk));
 504        list_add(&c->node, &clk_hw_omap_clocks);
 505}
 506
 507/**
 508 * omap2_clk_enable_autoidle_all - enable autoidle on all OMAP clocks that
 509 * support it
 510 *
 511 * Enable clock autoidle on all OMAP clocks that have allow_idle
 512 * function pointers associated with them.  This function is intended
 513 * to be temporary until support for this is added to the common clock
 514 * code.  Returns 0.
 515 */
 516int omap2_clk_enable_autoidle_all(void)
 517{
 518        struct clk_hw_omap *c;
 519
 520        list_for_each_entry(c, &clk_hw_omap_clocks, node)
 521                if (c->ops && c->ops->allow_idle)
 522                        c->ops->allow_idle(c);
 523        return 0;
 524}
 525
 526/**
 527 * omap2_clk_disable_autoidle_all - disable autoidle on all OMAP clocks that
 528 * support it
 529 *
 530 * Disable clock autoidle on all OMAP clocks that have allow_idle
 531 * function pointers associated with them.  This function is intended
 532 * to be temporary until support for this is added to the common clock
 533 * code.  Returns 0.
 534 */
 535int omap2_clk_disable_autoidle_all(void)
 536{
 537        struct clk_hw_omap *c;
 538
 539        list_for_each_entry(c, &clk_hw_omap_clocks, node)
 540                if (c->ops && c->ops->deny_idle)
 541                        c->ops->deny_idle(c);
 542        return 0;
 543}
 544
 545/**
 546 * omap2_clk_enable_init_clocks - prepare & enable a list of clocks
 547 * @clk_names: ptr to an array of strings of clock names to enable
 548 * @num_clocks: number of clock names in @clk_names
 549 *
 550 * Prepare and enable a list of clocks, named by @clk_names.  No
 551 * return value. XXX Deprecated; only needed until these clocks are
 552 * properly claimed and enabled by the drivers or core code that uses
 553 * them.  XXX What code disables & calls clk_put on these clocks?
 554 */
 555void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
 556{
 557        struct clk *init_clk;
 558        int i;
 559
 560        for (i = 0; i < num_clocks; i++) {
 561                init_clk = clk_get(NULL, clk_names[i]);
 562                clk_prepare_enable(init_clk);
 563        }
 564}
 565
 566const struct clk_hw_omap_ops clkhwops_wait = {
 567        .find_idlest    = omap2_clk_dflt_find_idlest,
 568        .find_companion = omap2_clk_dflt_find_companion,
 569};
 570
 571/**
 572 * omap_clocks_register - register an array of omap_clk
 573 * @ocs: pointer to an array of omap_clk to register
 574 */
 575void __init omap_clocks_register(struct omap_clk oclks[], int cnt)
 576{
 577        struct omap_clk *c;
 578
 579        for (c = oclks; c < oclks + cnt; c++) {
 580                clkdev_add(&c->lk);
 581                if (!__clk_init(NULL, c->lk.clk))
 582                        omap2_init_clk_hw_omap_clocks(c->lk.clk);
 583        }
 584}
 585
 586/**
 587 * omap2_clk_switch_mpurate_at_boot - switch ARM MPU rate by boot-time argument
 588 * @mpurate_ck_name: clk name of the clock to change rate
 589 *
 590 * Change the ARM MPU clock rate to the rate specified on the command
 591 * line, if one was specified.  @mpurate_ck_name should be
 592 * "virt_prcm_set" on OMAP2xxx and "dpll1_ck" on OMAP34xx/OMAP36xx.
 593 * XXX Does not handle voltage scaling - on OMAP2xxx this is currently
 594 * handled by the virt_prcm_set clock, but this should be handled by
 595 * the OPP layer.  XXX This is intended to be handled by the OPP layer
 596 * code in the near future and should be removed from the clock code.
 597 * Returns -EINVAL if 'mpurate' is zero or if clk_set_rate() rejects
 598 * the rate, -ENOENT if the struct clk referred to by @mpurate_ck_name
 599 * cannot be found, or 0 upon success.
 600 */
 601int __init omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name)
 602{
 603        struct clk *mpurate_ck;
 604        int r;
 605
 606        if (!mpurate)
 607                return -EINVAL;
 608
 609        mpurate_ck = clk_get(NULL, mpurate_ck_name);
 610        if (WARN(IS_ERR(mpurate_ck), "Failed to get %s.\n", mpurate_ck_name))
 611                return -ENOENT;
 612
 613        r = clk_set_rate(mpurate_ck, mpurate);
 614        if (r < 0) {
 615                WARN(1, "clock: %s: unable to set MPU rate to %d: %d\n",
 616                     mpurate_ck_name, mpurate, r);
 617                clk_put(mpurate_ck);
 618                return -EINVAL;
 619        }
 620
 621        calibrate_delay();
 622        clk_put(mpurate_ck);
 623
 624        return 0;
 625}
 626
 627/**
 628 * omap2_clk_print_new_rates - print summary of current clock tree rates
 629 * @hfclkin_ck_name: clk name for the off-chip HF oscillator
 630 * @core_ck_name: clk name for the on-chip CORE_CLK
 631 * @mpu_ck_name: clk name for the ARM MPU clock
 632 *
 633 * Prints a short message to the console with the HFCLKIN oscillator
 634 * rate, the rate of the CORE clock, and the rate of the ARM MPU clock.
 635 * Called by the boot-time MPU rate switching code.   XXX This is intended
 636 * to be handled by the OPP layer code in the near future and should be
 637 * removed from the clock code.  No return value.
 638 */
 639void __init omap2_clk_print_new_rates(const char *hfclkin_ck_name,
 640                                      const char *core_ck_name,
 641                                      const char *mpu_ck_name)
 642{
 643        struct clk *hfclkin_ck, *core_ck, *mpu_ck;
 644        unsigned long hfclkin_rate;
 645
 646        mpu_ck = clk_get(NULL, mpu_ck_name);
 647        if (WARN(IS_ERR(mpu_ck), "clock: failed to get %s.\n", mpu_ck_name))
 648                return;
 649
 650        core_ck = clk_get(NULL, core_ck_name);
 651        if (WARN(IS_ERR(core_ck), "clock: failed to get %s.\n", core_ck_name))
 652                return;
 653
 654        hfclkin_ck = clk_get(NULL, hfclkin_ck_name);
 655        if (WARN(IS_ERR(hfclkin_ck), "Failed to get %s.\n", hfclkin_ck_name))
 656                return;
 657
 658        hfclkin_rate = clk_get_rate(hfclkin_ck);
 659
 660        pr_info("Switched to new clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
 661                (hfclkin_rate / 1000000), ((hfclkin_rate / 100000) % 10),
 662                (clk_get_rate(core_ck) / 1000000),
 663                (clk_get_rate(mpu_ck) / 1000000));
 664}
 665