cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cm3xxx.c (22314B)


      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);