Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * OMAP4 CM instance functions
0004  *
0005  * Copyright (C) 2009 Nokia Corporation
0006  * Copyright (C) 2008-2011 Texas Instruments, Inc.
0007  * Paul Walmsley
0008  * Rajendra Nayak <rnayak@ti.com>
0009  *
0010  * This is needed since CM instances can be in the PRM, PRCM_MPU, CM1,
0011  * or CM2 hardware modules.  For example, the EMU_CM CM instance is in
0012  * the PRM hardware module.  What a mess...
0013  */
0014 
0015 #include <linux/kernel.h>
0016 #include <linux/types.h>
0017 #include <linux/errno.h>
0018 #include <linux/err.h>
0019 #include <linux/io.h>
0020 
0021 #include "clockdomain.h"
0022 #include "cm.h"
0023 #include "cm1_44xx.h"
0024 #include "cm2_44xx.h"
0025 #include "cm44xx.h"
0026 #include "cm-regbits-34xx.h"
0027 #include "prcm44xx.h"
0028 #include "prm44xx.h"
0029 #include "prcm_mpu44xx.h"
0030 #include "prcm-common.h"
0031 
0032 #define OMAP4430_IDLEST_SHIFT       16
0033 #define OMAP4430_IDLEST_MASK        (0x3 << 16)
0034 #define OMAP4430_CLKTRCTRL_SHIFT    0
0035 #define OMAP4430_CLKTRCTRL_MASK     (0x3 << 0)
0036 #define OMAP4430_MODULEMODE_SHIFT   0
0037 #define OMAP4430_MODULEMODE_MASK    (0x3 << 0)
0038 
0039 /*
0040  * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield:
0041  *
0042  *   0x0 func:     Module is fully functional, including OCP
0043  *   0x1 trans:    Module is performing transition: wakeup, or sleep, or sleep
0044  *                 abortion
0045  *   0x2 idle:     Module is in Idle mode (only OCP part). It is functional if
0046  *                 using separate functional clock
0047  *   0x3 disabled: Module is disabled and cannot be accessed
0048  *
0049  */
0050 #define CLKCTRL_IDLEST_FUNCTIONAL       0x0
0051 #define CLKCTRL_IDLEST_INTRANSITION     0x1
0052 #define CLKCTRL_IDLEST_INTERFACE_IDLE       0x2
0053 #define CLKCTRL_IDLEST_DISABLED         0x3
0054 
0055 static struct omap_domain_base _cm_bases[OMAP4_MAX_PRCM_PARTITIONS];
0056 
0057 /**
0058  * omap_cm_base_init - Populates the cm partitions
0059  *
0060  * Populates the base addresses of the _cm_bases
0061  * array used for read/write of cm module registers.
0062  */
0063 static void omap_cm_base_init(void)
0064 {
0065     memcpy(&_cm_bases[OMAP4430_PRM_PARTITION], &prm_base, sizeof(prm_base));
0066     memcpy(&_cm_bases[OMAP4430_CM1_PARTITION], &cm_base, sizeof(cm_base));
0067     memcpy(&_cm_bases[OMAP4430_CM2_PARTITION], &cm2_base, sizeof(cm2_base));
0068     memcpy(&_cm_bases[OMAP4430_PRCM_MPU_PARTITION], &prcm_mpu_base,
0069            sizeof(prcm_mpu_base));
0070 }
0071 
0072 /* Private functions */
0073 
0074 static u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx);
0075 
0076 /**
0077  * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield
0078  * @part: PRCM partition ID that the CM_CLKCTRL register exists in
0079  * @inst: CM instance register offset (*_INST macro)
0080  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
0081  *
0082  * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to
0083  * bit 0.
0084  */
0085 static u32 _clkctrl_idlest(u8 part, u16 inst, u16 clkctrl_offs)
0086 {
0087     u32 v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
0088     v &= OMAP4430_IDLEST_MASK;
0089     v >>= OMAP4430_IDLEST_SHIFT;
0090     return v;
0091 }
0092 
0093 /**
0094  * _is_module_ready - can module registers be accessed without causing an abort?
0095  * @part: PRCM partition ID that the CM_CLKCTRL register exists in
0096  * @inst: CM instance register offset (*_INST macro)
0097  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
0098  *
0099  * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either
0100  * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise.
0101  */
0102 static bool _is_module_ready(u8 part, u16 inst, u16 clkctrl_offs)
0103 {
0104     u32 v;
0105 
0106     v = _clkctrl_idlest(part, inst, clkctrl_offs);
0107 
0108     return (v == CLKCTRL_IDLEST_FUNCTIONAL ||
0109         v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false;
0110 }
0111 
0112 /* Read a register in a CM instance */
0113 static u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx)
0114 {
0115     BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
0116            part == OMAP4430_INVALID_PRCM_PARTITION ||
0117            !_cm_bases[part].va);
0118     return readl_relaxed(_cm_bases[part].va + inst + idx);
0119 }
0120 
0121 /* Write into a register in a CM instance */
0122 static void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx)
0123 {
0124     BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
0125            part == OMAP4430_INVALID_PRCM_PARTITION ||
0126            !_cm_bases[part].va);
0127     writel_relaxed(val, _cm_bases[part].va + inst + idx);
0128 }
0129 
0130 /* Read-modify-write a register in CM1. Caller must lock */
0131 static u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, u16 inst,
0132                       s16 idx)
0133 {
0134     u32 v;
0135 
0136     v = omap4_cminst_read_inst_reg(part, inst, idx);
0137     v &= ~mask;
0138     v |= bits;
0139     omap4_cminst_write_inst_reg(v, part, inst, idx);
0140 
0141     return v;
0142 }
0143 
0144 static u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, u16 inst, s16 idx)
0145 {
0146     return omap4_cminst_rmw_inst_reg_bits(bits, bits, part, inst, idx);
0147 }
0148 
0149 static u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, u16 inst,
0150                         s16 idx)
0151 {
0152     return omap4_cminst_rmw_inst_reg_bits(bits, 0x0, part, inst, idx);
0153 }
0154 
0155 static u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx, u32 mask)
0156 {
0157     u32 v;
0158 
0159     v = omap4_cminst_read_inst_reg(part, inst, idx);
0160     v &= mask;
0161     v >>= __ffs(mask);
0162 
0163     return v;
0164 }
0165 
0166 /*
0167  *
0168  */
0169 
0170 /**
0171  * _clktrctrl_write - write @c to a CM_CLKSTCTRL.CLKTRCTRL register bitfield
0172  * @c: CLKTRCTRL register bitfield (LSB = bit 0, i.e., unshifted)
0173  * @part: PRCM partition ID that the CM_CLKSTCTRL register exists in
0174  * @inst: CM instance register offset (*_INST macro)
0175  * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
0176  *
0177  * @c must be the unshifted value for CLKTRCTRL - i.e., this function
0178  * will handle the shift itself.
0179  */
0180 static void _clktrctrl_write(u8 c, u8 part, u16 inst, u16 cdoffs)
0181 {
0182     u32 v;
0183 
0184     v = omap4_cminst_read_inst_reg(part, inst, cdoffs + OMAP4_CM_CLKSTCTRL);
0185     v &= ~OMAP4430_CLKTRCTRL_MASK;
0186     v |= c << OMAP4430_CLKTRCTRL_SHIFT;
0187     omap4_cminst_write_inst_reg(v, part, inst, cdoffs + OMAP4_CM_CLKSTCTRL);
0188 }
0189 
0190 /**
0191  * omap4_cminst_is_clkdm_in_hwsup - is a clockdomain in hwsup idle mode?
0192  * @part: PRCM partition ID that the CM_CLKSTCTRL register exists in
0193  * @inst: CM instance register offset (*_INST macro)
0194  * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
0195  *
0196  * Returns true if the clockdomain referred to by (@part, @inst, @cdoffs)
0197  * is in hardware-supervised idle mode, or 0 otherwise.
0198  */
0199 static bool omap4_cminst_is_clkdm_in_hwsup(u8 part, u16 inst, u16 cdoffs)
0200 {
0201     u32 v;
0202 
0203     v = omap4_cminst_read_inst_reg(part, inst, cdoffs + OMAP4_CM_CLKSTCTRL);
0204     v &= OMAP4430_CLKTRCTRL_MASK;
0205     v >>= OMAP4430_CLKTRCTRL_SHIFT;
0206 
0207     return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? true : false;
0208 }
0209 
0210 /**
0211  * omap4_cminst_clkdm_enable_hwsup - put a clockdomain in hwsup-idle mode
0212  * @part: PRCM partition ID that the clockdomain registers exist in
0213  * @inst: CM instance register offset (*_INST macro)
0214  * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
0215  *
0216  * Put a clockdomain referred to by (@part, @inst, @cdoffs) into
0217  * hardware-supervised idle mode.  No return value.
0218  */
0219 static void omap4_cminst_clkdm_enable_hwsup(u8 part, u16 inst, u16 cdoffs)
0220 {
0221     _clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, part, inst, cdoffs);
0222 }
0223 
0224 /**
0225  * omap4_cminst_clkdm_disable_hwsup - put a clockdomain in swsup-idle mode
0226  * @part: PRCM partition ID that the clockdomain registers exist in
0227  * @inst: CM instance register offset (*_INST macro)
0228  * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
0229  *
0230  * Put a clockdomain referred to by (@part, @inst, @cdoffs) into
0231  * software-supervised idle mode, i.e., controlled manually by the
0232  * Linux OMAP clockdomain code.  No return value.
0233  */
0234 static void omap4_cminst_clkdm_disable_hwsup(u8 part, u16 inst, u16 cdoffs)
0235 {
0236     _clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, part, inst, cdoffs);
0237 }
0238 
0239 /**
0240  * omap4_cminst_clkdm_force_sleep - try to take a clockdomain out of idle
0241  * @part: PRCM partition ID that the clockdomain registers exist in
0242  * @inst: CM instance register offset (*_INST macro)
0243  * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
0244  *
0245  * Take a clockdomain referred to by (@part, @inst, @cdoffs) out of idle,
0246  * waking it up.  No return value.
0247  */
0248 static void omap4_cminst_clkdm_force_wakeup(u8 part, u16 inst, u16 cdoffs)
0249 {
0250     _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, part, inst, cdoffs);
0251 }
0252 
0253 /*
0254  *
0255  */
0256 
0257 static void omap4_cminst_clkdm_force_sleep(u8 part, u16 inst, u16 cdoffs)
0258 {
0259     _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, part, inst, cdoffs);
0260 }
0261 
0262 /**
0263  * omap4_cminst_wait_module_ready - wait for a module to be in 'func' state
0264  * @part: PRCM partition ID that the CM_CLKCTRL register exists in
0265  * @inst: CM instance register offset (*_INST macro)
0266  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
0267  * @bit_shift: bit shift for the register, ignored for OMAP4+
0268  *
0269  * Wait for the module IDLEST to be functional. If the idle state is in any
0270  * the non functional state (trans, idle or disabled), module and thus the
0271  * sysconfig cannot be accessed and will probably lead to an "imprecise
0272  * external abort"
0273  */
0274 static int omap4_cminst_wait_module_ready(u8 part, s16 inst, u16 clkctrl_offs,
0275                       u8 bit_shift)
0276 {
0277     int i = 0;
0278 
0279     omap_test_timeout(_is_module_ready(part, inst, clkctrl_offs),
0280               MAX_MODULE_READY_TIME, i);
0281 
0282     return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
0283 }
0284 
0285 /**
0286  * omap4_cminst_wait_module_idle - wait for a module to be in 'disabled'
0287  * state
0288  * @part: PRCM partition ID that the CM_CLKCTRL register exists in
0289  * @inst: CM instance register offset (*_INST macro)
0290  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
0291  * @bit_shift: Bit shift for the register, ignored for OMAP4+
0292  *
0293  * Wait for the module IDLEST to be disabled. Some PRCM transition,
0294  * like reset assertion or parent clock de-activation must wait the
0295  * module to be fully disabled.
0296  */
0297 static int omap4_cminst_wait_module_idle(u8 part, s16 inst, u16 clkctrl_offs,
0298                      u8 bit_shift)
0299 {
0300     int i = 0;
0301 
0302     omap_test_timeout((_clkctrl_idlest(part, inst, clkctrl_offs) ==
0303                CLKCTRL_IDLEST_DISABLED),
0304               MAX_MODULE_DISABLE_TIME, i);
0305 
0306     return (i < MAX_MODULE_DISABLE_TIME) ? 0 : -EBUSY;
0307 }
0308 
0309 /**
0310  * omap4_cminst_module_enable - Enable the modulemode inside CLKCTRL
0311  * @mode: Module mode (SW or HW)
0312  * @part: PRCM partition ID that the CM_CLKCTRL register exists in
0313  * @inst: CM instance register offset (*_INST macro)
0314  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
0315  *
0316  * No return value.
0317  */
0318 static void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst,
0319                        u16 clkctrl_offs)
0320 {
0321     u32 v;
0322 
0323     v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
0324     v &= ~OMAP4430_MODULEMODE_MASK;
0325     v |= mode << OMAP4430_MODULEMODE_SHIFT;
0326     omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
0327 }
0328 
0329 /**
0330  * omap4_cminst_module_disable - Disable the module inside CLKCTRL
0331  * @part: PRCM partition ID that the CM_CLKCTRL register exists in
0332  * @inst: CM instance register offset (*_INST macro)
0333  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
0334  *
0335  * No return value.
0336  */
0337 static void omap4_cminst_module_disable(u8 part, u16 inst, u16 clkctrl_offs)
0338 {
0339     u32 v;
0340 
0341     v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
0342     v &= ~OMAP4430_MODULEMODE_MASK;
0343     omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
0344 }
0345 
0346 /*
0347  * Clockdomain low-level functions
0348  */
0349 
0350 static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1,
0351                     struct clockdomain *clkdm2)
0352 {
0353     omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit),
0354                        clkdm1->prcm_partition,
0355                        clkdm1->cm_inst, clkdm1->clkdm_offs +
0356                        OMAP4_CM_STATICDEP);
0357     return 0;
0358 }
0359 
0360 static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1,
0361                     struct clockdomain *clkdm2)
0362 {
0363     omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit),
0364                      clkdm1->prcm_partition,
0365                      clkdm1->cm_inst, clkdm1->clkdm_offs +
0366                      OMAP4_CM_STATICDEP);
0367     return 0;
0368 }
0369 
0370 static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1,
0371                     struct clockdomain *clkdm2)
0372 {
0373     return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition,
0374                            clkdm1->cm_inst,
0375                            clkdm1->clkdm_offs +
0376                            OMAP4_CM_STATICDEP,
0377                            (1 << clkdm2->dep_bit));
0378 }
0379 
0380 static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
0381 {
0382     struct clkdm_dep *cd;
0383     u32 mask = 0;
0384 
0385     if (!clkdm->prcm_partition)
0386         return 0;
0387 
0388     for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
0389         if (!cd->clkdm)
0390             continue; /* only happens if data is erroneous */
0391 
0392         mask |= 1 << cd->clkdm->dep_bit;
0393         cd->wkdep_usecount = 0;
0394     }
0395 
0396     omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition,
0397                      clkdm->cm_inst, clkdm->clkdm_offs +
0398                      OMAP4_CM_STATICDEP);
0399     return 0;
0400 }
0401 
0402 static int omap4_clkdm_sleep(struct clockdomain *clkdm)
0403 {
0404     if (clkdm->flags & CLKDM_CAN_HWSUP)
0405         omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
0406                         clkdm->cm_inst,
0407                         clkdm->clkdm_offs);
0408     else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
0409         omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition,
0410                            clkdm->cm_inst,
0411                            clkdm->clkdm_offs);
0412     else
0413         return -EINVAL;
0414 
0415     return 0;
0416 }
0417 
0418 static int omap4_clkdm_wakeup(struct clockdomain *clkdm)
0419 {
0420     omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
0421                     clkdm->cm_inst, clkdm->clkdm_offs);
0422     return 0;
0423 }
0424 
0425 static void omap4_clkdm_allow_idle(struct clockdomain *clkdm)
0426 {
0427     omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
0428                     clkdm->cm_inst, clkdm->clkdm_offs);
0429 }
0430 
0431 static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
0432 {
0433     if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
0434         omap4_clkdm_wakeup(clkdm);
0435     else
0436         omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
0437                          clkdm->cm_inst,
0438                          clkdm->clkdm_offs);
0439 }
0440 
0441 static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
0442 {
0443     if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
0444         return omap4_clkdm_wakeup(clkdm);
0445 
0446     return 0;
0447 }
0448 
0449 static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
0450 {
0451     bool hwsup = false;
0452 
0453     if (!clkdm->prcm_partition)
0454         return 0;
0455 
0456     /*
0457      * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
0458      * more details on the unpleasant problem this is working
0459      * around
0460      */
0461     if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
0462         !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
0463         omap4_clkdm_allow_idle(clkdm);
0464         return 0;
0465     }
0466 
0467     hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
0468                     clkdm->cm_inst, clkdm->clkdm_offs);
0469 
0470     if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
0471         omap4_clkdm_sleep(clkdm);
0472 
0473     return 0;
0474 }
0475 
0476 static u32 omap4_cminst_xlate_clkctrl(u8 part, u16 inst, u16 offset)
0477 {
0478     return _cm_bases[part].pa + inst + offset;
0479 }
0480 
0481 /**
0482  * omap4_clkdm_save_context - Save the clockdomain modulemode context
0483  * @clkdm: The clockdomain pointer whose context needs to be saved
0484  *
0485  * Save the clockdomain modulemode context.
0486  */
0487 static int omap4_clkdm_save_context(struct clockdomain *clkdm)
0488 {
0489     clkdm->context = omap4_cminst_read_inst_reg(clkdm->prcm_partition,
0490                             clkdm->cm_inst,
0491                             clkdm->clkdm_offs +
0492                             OMAP4_CM_CLKSTCTRL);
0493     clkdm->context &= OMAP4430_MODULEMODE_MASK;
0494     return 0;
0495 }
0496 
0497 /**
0498  * omap4_clkdm_restore_context - Restore the clockdomain modulemode context
0499  * @clkdm: The clockdomain pointer whose context needs to be restored
0500  *
0501  * Restore the clockdomain modulemode context.
0502  */
0503 static int omap4_clkdm_restore_context(struct clockdomain *clkdm)
0504 {
0505     switch (clkdm->context) {
0506     case OMAP34XX_CLKSTCTRL_DISABLE_AUTO:
0507         omap4_clkdm_deny_idle(clkdm);
0508         break;
0509     case OMAP34XX_CLKSTCTRL_FORCE_SLEEP:
0510         omap4_clkdm_sleep(clkdm);
0511         break;
0512     case OMAP34XX_CLKSTCTRL_FORCE_WAKEUP:
0513         omap4_clkdm_wakeup(clkdm);
0514         break;
0515     case OMAP34XX_CLKSTCTRL_ENABLE_AUTO:
0516         omap4_clkdm_allow_idle(clkdm);
0517         break;
0518     }
0519     return 0;
0520 }
0521 
0522 struct clkdm_ops omap4_clkdm_operations = {
0523     .clkdm_add_wkdep    = omap4_clkdm_add_wkup_sleep_dep,
0524     .clkdm_del_wkdep    = omap4_clkdm_del_wkup_sleep_dep,
0525     .clkdm_read_wkdep   = omap4_clkdm_read_wkup_sleep_dep,
0526     .clkdm_clear_all_wkdeps = omap4_clkdm_clear_all_wkup_sleep_deps,
0527     .clkdm_add_sleepdep = omap4_clkdm_add_wkup_sleep_dep,
0528     .clkdm_del_sleepdep = omap4_clkdm_del_wkup_sleep_dep,
0529     .clkdm_read_sleepdep    = omap4_clkdm_read_wkup_sleep_dep,
0530     .clkdm_clear_all_sleepdeps  = omap4_clkdm_clear_all_wkup_sleep_deps,
0531     .clkdm_sleep        = omap4_clkdm_sleep,
0532     .clkdm_wakeup       = omap4_clkdm_wakeup,
0533     .clkdm_allow_idle   = omap4_clkdm_allow_idle,
0534     .clkdm_deny_idle    = omap4_clkdm_deny_idle,
0535     .clkdm_clk_enable   = omap4_clkdm_clk_enable,
0536     .clkdm_clk_disable  = omap4_clkdm_clk_disable,
0537     .clkdm_save_context = omap4_clkdm_save_context,
0538     .clkdm_restore_context  = omap4_clkdm_restore_context,
0539 };
0540 
0541 struct clkdm_ops am43xx_clkdm_operations = {
0542     .clkdm_sleep        = omap4_clkdm_sleep,
0543     .clkdm_wakeup       = omap4_clkdm_wakeup,
0544     .clkdm_allow_idle   = omap4_clkdm_allow_idle,
0545     .clkdm_deny_idle    = omap4_clkdm_deny_idle,
0546     .clkdm_clk_enable   = omap4_clkdm_clk_enable,
0547     .clkdm_clk_disable  = omap4_clkdm_clk_disable,
0548 };
0549 
0550 static const struct cm_ll_data omap4xxx_cm_ll_data = {
0551     .wait_module_ready  = &omap4_cminst_wait_module_ready,
0552     .wait_module_idle   = &omap4_cminst_wait_module_idle,
0553     .module_enable      = &omap4_cminst_module_enable,
0554     .module_disable     = &omap4_cminst_module_disable,
0555     .xlate_clkctrl      = &omap4_cminst_xlate_clkctrl,
0556 };
0557 
0558 int __init omap4_cm_init(const struct omap_prcm_init_data *data)
0559 {
0560     omap_cm_base_init();
0561 
0562     return cm_register(&omap4xxx_cm_ll_data);
0563 }
0564 
0565 static void __exit omap4_cm_exit(void)
0566 {
0567     cm_unregister(&omap4xxx_cm_ll_data);
0568 }
0569 __exitcall(omap4_cm_exit);