linux/arch/arm/mach-omap2/cm3xxx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * OMAP3xxx CM module functions
   4 *
   5 * Copyright (C) 2009 Nokia Corporation
   6 * Copyright (C) 2008-2010, 2012 Texas Instruments, Inc.
   7 * Paul Walmsley
   8 * Rajendra Nayak <rnayak@ti.com>
   9 */
  10
  11#include <linux/kernel.h>
  12#include <linux/types.h>
  13#include <linux/delay.h>
  14#include <linux/errno.h>
  15#include <linux/err.h>
  16#include <linux/io.h>
  17
  18#include "prm2xxx_3xxx.h"
  19#include "cm.h"
  20#include "cm3xxx.h"
  21#include "cm-regbits-34xx.h"
  22#include "clockdomain.h"
  23
  24static const u8 omap3xxx_cm_idlest_offs[] = {
  25        CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
  26};
  27
  28/*
  29 *
  30 */
  31
  32static void _write_clktrctrl(u8 c, s16 module, u32 mask)
  33{
  34        u32 v;
  35
  36        v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
  37        v &= ~mask;
  38        v |= c << __ffs(mask);
  39        omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
  40}
  41
  42static bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
  43{
  44        u32 v;
  45
  46        v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
  47        v &= mask;
  48        v >>= __ffs(mask);
  49
  50        return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
  51}
  52
  53static void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
  54{
  55        _write_clktrctrl(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
  56}
  57
  58static void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
  59{
  60        _write_clktrctrl(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
  61}
  62
  63static void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask)
  64{
  65        _write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, module, mask);
  66}
  67
  68static void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
  69{
  70        _write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
  71}
  72
  73/*
  74 *
  75 */
  76
  77/**
  78 * omap3xxx_cm_wait_module_ready - wait for a module to leave idle or standby
  79 * @part: PRCM partition, ignored for OMAP3
  80 * @prcm_mod: PRCM module offset
  81 * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
  82 * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
  83 *
  84 * Wait for the PRCM to indicate that the module identified by
  85 * (@prcm_mod, @idlest_id, @idlest_shift) is clocked.  Return 0 upon
  86 * success or -EBUSY if the module doesn't enable in time.
  87 */
  88static int omap3xxx_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_id,
  89                                         u8 idlest_shift)
  90{
  91        int ena = 0, i = 0;
  92        u8 cm_idlest_reg;
  93        u32 mask;
  94
  95        if (!idlest_id || (idlest_id > ARRAY_SIZE(omap3xxx_cm_idlest_offs)))
  96                return -EINVAL;
  97
  98        cm_idlest_reg = omap3xxx_cm_idlest_offs[idlest_id - 1];
  99
 100        mask = 1 << idlest_shift;
 101        ena = 0;
 102
 103        omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) &
 104                            mask) == ena), MAX_MODULE_READY_TIME, i);
 105
 106        return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
 107}
 108
 109/**
 110 * omap3xxx_cm_split_idlest_reg - split CM_IDLEST reg addr into its components
 111 * @idlest_reg: CM_IDLEST* virtual address
 112 * @prcm_inst: pointer to an s16 to return the PRCM instance offset
 113 * @idlest_reg_id: pointer to a u8 to return the CM_IDLESTx register ID
 114 *
 115 * XXX This function is only needed until absolute register addresses are
 116 * removed from the OMAP struct clk records.
 117 */
 118static int omap3xxx_cm_split_idlest_reg(struct clk_omap_reg *idlest_reg,
 119                                        s16 *prcm_inst,
 120                                        u8 *idlest_reg_id)
 121{
 122        unsigned long offs;
 123        u8 idlest_offs;
 124        int i;
 125
 126        idlest_offs = idlest_reg->offset & 0xff;
 127        for (i = 0; i < ARRAY_SIZE(omap3xxx_cm_idlest_offs); i++) {
 128                if (idlest_offs == omap3xxx_cm_idlest_offs[i]) {
 129                        *idlest_reg_id = i + 1;
 130                        break;
 131                }
 132        }
 133
 134        if (i == ARRAY_SIZE(omap3xxx_cm_idlest_offs))
 135                return -EINVAL;
 136
 137        offs = idlest_reg->offset;
 138        offs &= 0xff00;
 139        *prcm_inst = offs;
 140
 141        return 0;
 142}
 143
 144/* Clockdomain low-level operations */
 145
 146static int omap3xxx_clkdm_add_sleepdep(struct clockdomain *clkdm1,
 147                                       struct clockdomain *clkdm2)
 148{
 149        omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
 150                                  clkdm1->pwrdm.ptr->prcm_offs,
 151                                  OMAP3430_CM_SLEEPDEP);
 152        return 0;
 153}
 154
 155static int omap3xxx_clkdm_del_sleepdep(struct clockdomain *clkdm1,
 156                                       struct clockdomain *clkdm2)
 157{
 158        omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
 159                                    clkdm1->pwrdm.ptr->prcm_offs,
 160                                    OMAP3430_CM_SLEEPDEP);
 161        return 0;
 162}
 163
 164static int omap3xxx_clkdm_read_sleepdep(struct clockdomain *clkdm1,
 165                                        struct clockdomain *clkdm2)
 166{
 167        return omap2_cm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
 168                                            OMAP3430_CM_SLEEPDEP,
 169                                            (1 << clkdm2->dep_bit));
 170}
 171
 172static int omap3xxx_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
 173{
 174        struct clkdm_dep *cd;
 175        u32 mask = 0;
 176
 177        for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
 178                if (!cd->clkdm)
 179                        continue; /* only happens if data is erroneous */
 180
 181                mask |= 1 << cd->clkdm->dep_bit;
 182                cd->sleepdep_usecount = 0;
 183        }
 184        omap2_cm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
 185                                    OMAP3430_CM_SLEEPDEP);
 186        return 0;
 187}
 188
 189static int omap3xxx_clkdm_sleep(struct clockdomain *clkdm)
 190{
 191        omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
 192                                      clkdm->clktrctrl_mask);
 193        return 0;
 194}
 195
 196static int omap3xxx_clkdm_wakeup(struct clockdomain *clkdm)
 197{
 198        omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
 199                                       clkdm->clktrctrl_mask);
 200        return 0;
 201}
 202
 203static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm)
 204{
 205        if (clkdm->usecount > 0)
 206                clkdm_add_autodeps(clkdm);
 207
 208        omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 209                                       clkdm->clktrctrl_mask);
 210}
 211
 212static void omap3xxx_clkdm_deny_idle(struct clockdomain *clkdm)
 213{
 214        omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 215                                        clkdm->clktrctrl_mask);
 216
 217        if (clkdm->usecount > 0)
 218                clkdm_del_autodeps(clkdm);
 219}
 220
 221static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
 222{
 223        bool hwsup = false;
 224
 225        if (!clkdm->clktrctrl_mask)
 226                return 0;
 227
 228        /*
 229         * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
 230         * more details on the unpleasant problem this is working
 231         * around
 232         */
 233        if ((clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) &&
 234            (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
 235                omap3xxx_clkdm_wakeup(clkdm);
 236                return 0;
 237        }
 238
 239        hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 240                                              clkdm->clktrctrl_mask);
 241
 242        if (hwsup) {
 243                /* Disable HW transitions when we are changing deps */
 244                omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 245                                                clkdm->clktrctrl_mask);
 246                clkdm_add_autodeps(clkdm);
 247                omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 248                                               clkdm->clktrctrl_mask);
 249        } else {
 250                if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
 251                        omap3xxx_clkdm_wakeup(clkdm);
 252        }
 253
 254        return 0;
 255}
 256
 257static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
 258{
 259        bool hwsup = false;
 260
 261        if (!clkdm->clktrctrl_mask)
 262                return 0;
 263
 264        /*
 265         * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
 266         * more details on the unpleasant problem this is working
 267         * around
 268         */
 269        if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
 270            !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
 271                omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 272                                               clkdm->clktrctrl_mask);
 273                return 0;
 274        }
 275
 276        hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 277                                              clkdm->clktrctrl_mask);
 278
 279        if (hwsup) {
 280                /* Disable HW transitions when we are changing deps */
 281                omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 282                                                clkdm->clktrctrl_mask);
 283                clkdm_del_autodeps(clkdm);
 284                omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 285                                               clkdm->clktrctrl_mask);
 286        } else {
 287                if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
 288                        omap3xxx_clkdm_sleep(clkdm);
 289        }
 290
 291        return 0;
 292}
 293
 294struct clkdm_ops omap3_clkdm_operations = {
 295        .clkdm_add_wkdep        = omap2_clkdm_add_wkdep,
 296        .clkdm_del_wkdep        = omap2_clkdm_del_wkdep,
 297        .clkdm_read_wkdep       = omap2_clkdm_read_wkdep,
 298        .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps,
 299        .clkdm_add_sleepdep     = omap3xxx_clkdm_add_sleepdep,
 300        .clkdm_del_sleepdep     = omap3xxx_clkdm_del_sleepdep,
 301        .clkdm_read_sleepdep    = omap3xxx_clkdm_read_sleepdep,
 302        .clkdm_clear_all_sleepdeps      = omap3xxx_clkdm_clear_all_sleepdeps,
 303        .clkdm_sleep            = omap3xxx_clkdm_sleep,
 304        .clkdm_wakeup           = omap3xxx_clkdm_wakeup,
 305        .clkdm_allow_idle       = omap3xxx_clkdm_allow_idle,
 306        .clkdm_deny_idle        = omap3xxx_clkdm_deny_idle,
 307        .clkdm_clk_enable       = omap3xxx_clkdm_clk_enable,
 308        .clkdm_clk_disable      = omap3xxx_clkdm_clk_disable,
 309};
 310
 311/*
 312 * Context save/restore code - OMAP3 only
 313 */
 314struct omap3_cm_regs {
 315        u32 iva2_cm_clksel1;
 316        u32 iva2_cm_clksel2;
 317        u32 cm_sysconfig;
 318        u32 sgx_cm_clksel;
 319        u32 dss_cm_clksel;
 320        u32 cam_cm_clksel;
 321        u32 per_cm_clksel;
 322        u32 emu_cm_clksel;
 323        u32 emu_cm_clkstctrl;
 324        u32 pll_cm_autoidle;
 325        u32 pll_cm_autoidle2;
 326        u32 pll_cm_clksel4;
 327        u32 pll_cm_clksel5;
 328        u32 pll_cm_clken2;
 329        u32 cm_polctrl;
 330        u32 iva2_cm_fclken;
 331        u32 iva2_cm_clken_pll;
 332        u32 core_cm_fclken1;
 333        u32 core_cm_fclken3;
 334        u32 sgx_cm_fclken;
 335        u32 wkup_cm_fclken;
 336        u32 dss_cm_fclken;
 337        u32 cam_cm_fclken;
 338        u32 per_cm_fclken;
 339        u32 usbhost_cm_fclken;
 340        u32 core_cm_iclken1;
 341        u32 core_cm_iclken2;
 342        u32 core_cm_iclken3;
 343        u32 sgx_cm_iclken;
 344        u32 wkup_cm_iclken;
 345        u32 dss_cm_iclken;
 346        u32 cam_cm_iclken;
 347        u32 per_cm_iclken;
 348        u32 usbhost_cm_iclken;
 349        u32 iva2_cm_autoidle2;
 350        u32 mpu_cm_autoidle2;
 351        u32 iva2_cm_clkstctrl;
 352        u32 mpu_cm_clkstctrl;
 353        u32 core_cm_clkstctrl;
 354        u32 sgx_cm_clkstctrl;
 355        u32 dss_cm_clkstctrl;
 356        u32 cam_cm_clkstctrl;
 357        u32 per_cm_clkstctrl;
 358        u32 neon_cm_clkstctrl;
 359        u32 usbhost_cm_clkstctrl;
 360        u32 core_cm_autoidle1;
 361        u32 core_cm_autoidle2;
 362        u32 core_cm_autoidle3;
 363        u32 wkup_cm_autoidle;
 364        u32 dss_cm_autoidle;
 365        u32 cam_cm_autoidle;
 366        u32 per_cm_autoidle;
 367        u32 usbhost_cm_autoidle;
 368        u32 sgx_cm_sleepdep;
 369        u32 dss_cm_sleepdep;
 370        u32 cam_cm_sleepdep;
 371        u32 per_cm_sleepdep;
 372        u32 usbhost_cm_sleepdep;
 373        u32 cm_clkout_ctrl;
 374};
 375
 376static struct omap3_cm_regs cm_context;
 377
 378void omap3_cm_save_context(void)
 379{
 380        cm_context.iva2_cm_clksel1 =
 381                omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1);
 382        cm_context.iva2_cm_clksel2 =
 383                omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL2);
 384        cm_context.cm_sysconfig =
 385                omap2_cm_read_mod_reg(OCP_MOD, OMAP3430_CM_SYSCONFIG);
 386        cm_context.sgx_cm_clksel =
 387                omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL);
 388        cm_context.dss_cm_clksel =
 389                omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSEL);
 390        cm_context.cam_cm_clksel =
 391                omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_CLKSEL);
 392        cm_context.per_cm_clksel =
 393                omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_CLKSEL);
 394        cm_context.emu_cm_clksel =
 395                omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
 396        cm_context.emu_cm_clkstctrl =
 397                omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
 398        /*
 399         * As per erratum i671, ROM code does not respect the PER DPLL
 400         * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
 401         * In this case, even though this register has been saved in
 402         * scratchpad contents, we need to restore AUTO_PERIPH_DPLL
 403         * by ourselves. So, we need to save it anyway.
 404         */
 405        cm_context.pll_cm_autoidle =
 406                omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
 407        cm_context.pll_cm_autoidle2 =
 408                omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
 409        cm_context.pll_cm_clksel4 =
 410                omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
 411        cm_context.pll_cm_clksel5 =
 412                omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
 413        cm_context.pll_cm_clken2 =
 414                omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2);
 415        cm_context.cm_polctrl =
 416                omap2_cm_read_mod_reg(OCP_MOD, OMAP3430_CM_POLCTRL);
 417        cm_context.iva2_cm_fclken =
 418                omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN);
 419        cm_context.iva2_cm_clken_pll =
 420                omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL);
 421        cm_context.core_cm_fclken1 =
 422                omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
 423        cm_context.core_cm_fclken3 =
 424                omap2_cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
 425        cm_context.sgx_cm_fclken =
 426                omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_FCLKEN);
 427        cm_context.wkup_cm_fclken =
 428                omap2_cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
 429        cm_context.dss_cm_fclken =
 430                omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_FCLKEN);
 431        cm_context.cam_cm_fclken =
 432                omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_FCLKEN);
 433        cm_context.per_cm_fclken =
 434                omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
 435        cm_context.usbhost_cm_fclken =
 436                omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
 437        cm_context.core_cm_iclken1 =
 438                omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
 439        cm_context.core_cm_iclken2 =
 440                omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN2);
 441        cm_context.core_cm_iclken3 =
 442                omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
 443        cm_context.sgx_cm_iclken =
 444                omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_ICLKEN);
 445        cm_context.wkup_cm_iclken =
 446                omap2_cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
 447        cm_context.dss_cm_iclken =
 448                omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_ICLKEN);
 449        cm_context.cam_cm_iclken =
 450                omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_ICLKEN);
 451        cm_context.per_cm_iclken =
 452                omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
 453        cm_context.usbhost_cm_iclken =
 454                omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
 455        cm_context.iva2_cm_autoidle2 =
 456                omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
 457        cm_context.mpu_cm_autoidle2 =
 458                omap2_cm_read_mod_reg(MPU_MOD, CM_AUTOIDLE2);
 459        cm_context.iva2_cm_clkstctrl =
 460                omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL);
 461        cm_context.mpu_cm_clkstctrl =
 462                omap2_cm_read_mod_reg(MPU_MOD, OMAP2_CM_CLKSTCTRL);
 463        cm_context.core_cm_clkstctrl =
 464                omap2_cm_read_mod_reg(CORE_MOD, OMAP2_CM_CLKSTCTRL);
 465        cm_context.sgx_cm_clkstctrl =
 466                omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, OMAP2_CM_CLKSTCTRL);
 467        cm_context.dss_cm_clkstctrl =
 468                omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP2_CM_CLKSTCTRL);
 469        cm_context.cam_cm_clkstctrl =
 470                omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP2_CM_CLKSTCTRL);
 471        cm_context.per_cm_clkstctrl =
 472                omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP2_CM_CLKSTCTRL);
 473        cm_context.neon_cm_clkstctrl =
 474                omap2_cm_read_mod_reg(OMAP3430_NEON_MOD, OMAP2_CM_CLKSTCTRL);
 475        cm_context.usbhost_cm_clkstctrl =
 476                omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
 477                                      OMAP2_CM_CLKSTCTRL);
 478        cm_context.core_cm_autoidle1 =
 479                omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE1);
 480        cm_context.core_cm_autoidle2 =
 481                omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE2);
 482        cm_context.core_cm_autoidle3 =
 483                omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE3);
 484        cm_context.wkup_cm_autoidle =
 485                omap2_cm_read_mod_reg(WKUP_MOD, CM_AUTOIDLE);
 486        cm_context.dss_cm_autoidle =
 487                omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_AUTOIDLE);
 488        cm_context.cam_cm_autoidle =
 489                omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_AUTOIDLE);
 490        cm_context.per_cm_autoidle =
 491                omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
 492        cm_context.usbhost_cm_autoidle =
 493                omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
 494        cm_context.sgx_cm_sleepdep =
 495                omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
 496                                      OMAP3430_CM_SLEEPDEP);
 497        cm_context.dss_cm_sleepdep =
 498                omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP3430_CM_SLEEPDEP);
 499        cm_context.cam_cm_sleepdep =
 500                omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP3430_CM_SLEEPDEP);
 501        cm_context.per_cm_sleepdep =
 502                omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_CM_SLEEPDEP);
 503        cm_context.usbhost_cm_sleepdep =
 504                omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
 505                                      OMAP3430_CM_SLEEPDEP);
 506        cm_context.cm_clkout_ctrl =
 507                omap2_cm_read_mod_reg(OMAP3430_CCR_MOD,
 508                                      OMAP3_CM_CLKOUT_CTRL_OFFSET);
 509}
 510
 511void omap3_cm_restore_context(void)
 512{
 513        omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel1, OMAP3430_IVA2_MOD,
 514                               CM_CLKSEL1);
 515        omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel2, OMAP3430_IVA2_MOD,
 516                               CM_CLKSEL2);
 517        omap2_cm_write_mod_reg(cm_context.cm_sysconfig, OCP_MOD,
 518                               OMAP3430_CM_SYSCONFIG);
 519        omap2_cm_write_mod_reg(cm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD,
 520                               CM_CLKSEL);
 521        omap2_cm_write_mod_reg(cm_context.dss_cm_clksel, OMAP3430_DSS_MOD,
 522                               CM_CLKSEL);
 523        omap2_cm_write_mod_reg(cm_context.cam_cm_clksel, OMAP3430_CAM_MOD,
 524                               CM_CLKSEL);
 525        omap2_cm_write_mod_reg(cm_context.per_cm_clksel, OMAP3430_PER_MOD,
 526                               CM_CLKSEL);
 527        omap2_cm_write_mod_reg(cm_context.emu_cm_clksel, OMAP3430_EMU_MOD,
 528                               CM_CLKSEL1);
 529        omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
 530                               OMAP2_CM_CLKSTCTRL);
 531        /*
 532         * As per erratum i671, ROM code does not respect the PER DPLL
 533         * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
 534         * In this case, we need to restore AUTO_PERIPH_DPLL by ourselves.
 535         */
 536        omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle, PLL_MOD,
 537                               CM_AUTOIDLE);
 538        omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD,
 539                               CM_AUTOIDLE2);
 540        omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD,
 541                               OMAP3430ES2_CM_CLKSEL4);
 542        omap2_cm_write_mod_reg(cm_context.pll_cm_clksel5, PLL_MOD,
 543                               OMAP3430ES2_CM_CLKSEL5);
 544        omap2_cm_write_mod_reg(cm_context.pll_cm_clken2, PLL_MOD,
 545                               OMAP3430ES2_CM_CLKEN2);
 546        omap2_cm_write_mod_reg(cm_context.cm_polctrl, OCP_MOD,
 547                               OMAP3430_CM_POLCTRL);
 548        omap2_cm_write_mod_reg(cm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD,
 549                               CM_FCLKEN);
 550        omap2_cm_write_mod_reg(cm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD,
 551                               OMAP3430_CM_CLKEN_PLL);
 552        omap2_cm_write_mod_reg(cm_context.core_cm_fclken1, CORE_MOD,
 553                               CM_FCLKEN1);
 554        omap2_cm_write_mod_reg(cm_context.core_cm_fclken3, CORE_MOD,
 555                               OMAP3430ES2_CM_FCLKEN3);
 556        omap2_cm_write_mod_reg(cm_context.sgx_cm_fclken, OMAP3430ES2_SGX_MOD,
 557                               CM_FCLKEN);
 558        omap2_cm_write_mod_reg(cm_context.wkup_cm_fclken, WKUP_MOD, CM_FCLKEN);
 559        omap2_cm_write_mod_reg(cm_context.dss_cm_fclken, OMAP3430_DSS_MOD,
 560                               CM_FCLKEN);
 561        omap2_cm_write_mod_reg(cm_context.cam_cm_fclken, OMAP3430_CAM_MOD,
 562                               CM_FCLKEN);
 563        omap2_cm_write_mod_reg(cm_context.per_cm_fclken, OMAP3430_PER_MOD,
 564                               CM_FCLKEN);
 565        omap2_cm_write_mod_reg(cm_context.usbhost_cm_fclken,
 566                               OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
 567        omap2_cm_write_mod_reg(cm_context.core_cm_iclken1, CORE_MOD,
 568                               CM_ICLKEN1);
 569        omap2_cm_write_mod_reg(cm_context.core_cm_iclken2, CORE_MOD,
 570                               CM_ICLKEN2);
 571        omap2_cm_write_mod_reg(cm_context.core_cm_iclken3, CORE_MOD,
 572                               CM_ICLKEN3);
 573        omap2_cm_write_mod_reg(cm_context.sgx_cm_iclken, OMAP3430ES2_SGX_MOD,
 574                               CM_ICLKEN);
 575        omap2_cm_write_mod_reg(cm_context.wkup_cm_iclken, WKUP_MOD, CM_ICLKEN);
 576        omap2_cm_write_mod_reg(cm_context.dss_cm_iclken, OMAP3430_DSS_MOD,
 577                               CM_ICLKEN);
 578        omap2_cm_write_mod_reg(cm_context.cam_cm_iclken, OMAP3430_CAM_MOD,
 579                               CM_ICLKEN);
 580        omap2_cm_write_mod_reg(cm_context.per_cm_iclken, OMAP3430_PER_MOD,
 581                               CM_ICLKEN);
 582        omap2_cm_write_mod_reg(cm_context.usbhost_cm_iclken,
 583                               OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
 584        omap2_cm_write_mod_reg(cm_context.iva2_cm_autoidle2, OMAP3430_IVA2_MOD,
 585                               CM_AUTOIDLE2);
 586        omap2_cm_write_mod_reg(cm_context.mpu_cm_autoidle2, MPU_MOD,
 587                               CM_AUTOIDLE2);
 588        omap2_cm_write_mod_reg(cm_context.iva2_cm_clkstctrl, OMAP3430_IVA2_MOD,
 589                               OMAP2_CM_CLKSTCTRL);
 590        omap2_cm_write_mod_reg(cm_context.mpu_cm_clkstctrl, MPU_MOD,
 591                               OMAP2_CM_CLKSTCTRL);
 592        omap2_cm_write_mod_reg(cm_context.core_cm_clkstctrl, CORE_MOD,
 593                               OMAP2_CM_CLKSTCTRL);
 594        omap2_cm_write_mod_reg(cm_context.sgx_cm_clkstctrl, OMAP3430ES2_SGX_MOD,
 595                               OMAP2_CM_CLKSTCTRL);
 596        omap2_cm_write_mod_reg(cm_context.dss_cm_clkstctrl, OMAP3430_DSS_MOD,
 597                               OMAP2_CM_CLKSTCTRL);
 598        omap2_cm_write_mod_reg(cm_context.cam_cm_clkstctrl, OMAP3430_CAM_MOD,
 599                               OMAP2_CM_CLKSTCTRL);
 600        omap2_cm_write_mod_reg(cm_context.per_cm_clkstctrl, OMAP3430_PER_MOD,
 601                               OMAP2_CM_CLKSTCTRL);
 602        omap2_cm_write_mod_reg(cm_context.neon_cm_clkstctrl, OMAP3430_NEON_MOD,
 603                               OMAP2_CM_CLKSTCTRL);
 604        omap2_cm_write_mod_reg(cm_context.usbhost_cm_clkstctrl,
 605                               OMAP3430ES2_USBHOST_MOD, OMAP2_CM_CLKSTCTRL);
 606        omap2_cm_write_mod_reg(cm_context.core_cm_autoidle1, CORE_MOD,
 607                               CM_AUTOIDLE1);
 608        omap2_cm_write_mod_reg(cm_context.core_cm_autoidle2, CORE_MOD,
 609                               CM_AUTOIDLE2);
 610        omap2_cm_write_mod_reg(cm_context.core_cm_autoidle3, CORE_MOD,
 611                               CM_AUTOIDLE3);
 612        omap2_cm_write_mod_reg(cm_context.wkup_cm_autoidle, WKUP_MOD,
 613                               CM_AUTOIDLE);
 614        omap2_cm_write_mod_reg(cm_context.dss_cm_autoidle, OMAP3430_DSS_MOD,
 615                               CM_AUTOIDLE);
 616        omap2_cm_write_mod_reg(cm_context.cam_cm_autoidle, OMAP3430_CAM_MOD,
 617                               CM_AUTOIDLE);
 618        omap2_cm_write_mod_reg(cm_context.per_cm_autoidle, OMAP3430_PER_MOD,
 619                               CM_AUTOIDLE);
 620        omap2_cm_write_mod_reg(cm_context.usbhost_cm_autoidle,
 621                               OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
 622        omap2_cm_write_mod_reg(cm_context.sgx_cm_sleepdep, OMAP3430ES2_SGX_MOD,
 623                               OMAP3430_CM_SLEEPDEP);
 624        omap2_cm_write_mod_reg(cm_context.dss_cm_sleepdep, OMAP3430_DSS_MOD,
 625                               OMAP3430_CM_SLEEPDEP);
 626        omap2_cm_write_mod_reg(cm_context.cam_cm_sleepdep, OMAP3430_CAM_MOD,
 627                               OMAP3430_CM_SLEEPDEP);
 628        omap2_cm_write_mod_reg(cm_context.per_cm_sleepdep, OMAP3430_PER_MOD,
 629                               OMAP3430_CM_SLEEPDEP);
 630        omap2_cm_write_mod_reg(cm_context.usbhost_cm_sleepdep,
 631                               OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
 632        omap2_cm_write_mod_reg(cm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
 633                               OMAP3_CM_CLKOUT_CTRL_OFFSET);
 634}
 635
 636void omap3_cm_save_scratchpad_contents(u32 *ptr)
 637{
 638        *ptr++ = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL);
 639        *ptr++ = omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
 640        *ptr++ = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
 641
 642        /*
 643         * As per erratum i671, ROM code does not respect the PER DPLL
 644         * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
 645         * Then,  in any case, clear these bits to avoid extra latencies.
 646         */
 647        *ptr++ = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
 648                ~OMAP3430_AUTO_PERIPH_DPLL_MASK;
 649        *ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
 650        *ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL2_PLL);
 651        *ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL3);
 652        *ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKEN_PLL);
 653        *ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL);
 654        *ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL);
 655        *ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL);
 656}
 657
 658/*
 659 *
 660 */
 661
 662static const struct cm_ll_data omap3xxx_cm_ll_data = {
 663        .split_idlest_reg       = &omap3xxx_cm_split_idlest_reg,
 664        .wait_module_ready      = &omap3xxx_cm_wait_module_ready,
 665};
 666
 667int __init omap3xxx_cm_init(const struct omap_prcm_init_data *data)
 668{
 669        omap2_clk_legacy_provider_init(TI_CLKM_CM, cm_base.va +
 670                                       OMAP3430_IVA2_MOD);
 671        return cm_register(&omap3xxx_cm_ll_data);
 672}
 673
 674static void __exit omap3xxx_cm_exit(void)
 675{
 676        cm_unregister(&omap3xxx_cm_ll_data);
 677}
 678__exitcall(omap3xxx_cm_exit);
 679