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