xref: /openbmc/linux/arch/arm/mach-omap2/cm3xxx.c (revision 90129336)
1ff4ae5d9SPaul Walmsley /*
24bd5259eSPaul Walmsley  * OMAP3xxx CM module functions
3ff4ae5d9SPaul Walmsley  *
4ff4ae5d9SPaul Walmsley  * Copyright (C) 2009 Nokia Corporation
54bd5259eSPaul Walmsley  * Copyright (C) 2008-2010, 2012 Texas Instruments, Inc.
6ff4ae5d9SPaul Walmsley  * Paul Walmsley
74bd5259eSPaul Walmsley  * Rajendra Nayak <rnayak@ti.com>
8ff4ae5d9SPaul Walmsley  *
9ff4ae5d9SPaul Walmsley  * This program is free software; you can redistribute it and/or modify
10ff4ae5d9SPaul Walmsley  * it under the terms of the GNU General Public License version 2 as
11ff4ae5d9SPaul Walmsley  * published by the Free Software Foundation.
12ff4ae5d9SPaul Walmsley  */
13ff4ae5d9SPaul Walmsley 
14ff4ae5d9SPaul Walmsley #include <linux/kernel.h>
15ff4ae5d9SPaul Walmsley #include <linux/types.h>
16ff4ae5d9SPaul Walmsley #include <linux/delay.h>
17ff4ae5d9SPaul Walmsley #include <linux/errno.h>
18ff4ae5d9SPaul Walmsley #include <linux/err.h>
19ff4ae5d9SPaul Walmsley #include <linux/io.h>
20ff4ae5d9SPaul Walmsley 
214bd5259eSPaul Walmsley #include "prm2xxx_3xxx.h"
22ff4ae5d9SPaul Walmsley #include "cm.h"
23ff4ae5d9SPaul Walmsley #include "cm3xxx.h"
24ff4ae5d9SPaul Walmsley #include "cm-regbits-34xx.h"
254bd5259eSPaul Walmsley #include "clockdomain.h"
26ff4ae5d9SPaul Walmsley 
27ff4ae5d9SPaul Walmsley static const u8 omap3xxx_cm_idlest_offs[] = {
28ff4ae5d9SPaul Walmsley 	CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
29ff4ae5d9SPaul Walmsley };
30ff4ae5d9SPaul Walmsley 
31ff4ae5d9SPaul Walmsley /*
32ff4ae5d9SPaul Walmsley  *
33ff4ae5d9SPaul Walmsley  */
34ff4ae5d9SPaul Walmsley 
35ff4ae5d9SPaul Walmsley static void _write_clktrctrl(u8 c, s16 module, u32 mask)
36ff4ae5d9SPaul Walmsley {
37ff4ae5d9SPaul Walmsley 	u32 v;
38ff4ae5d9SPaul Walmsley 
39ff4ae5d9SPaul Walmsley 	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
40ff4ae5d9SPaul Walmsley 	v &= ~mask;
41ff4ae5d9SPaul Walmsley 	v |= c << __ffs(mask);
42ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
43ff4ae5d9SPaul Walmsley }
44ff4ae5d9SPaul Walmsley 
45f2650d6eSTero Kristo static bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
46ff4ae5d9SPaul Walmsley {
47ff4ae5d9SPaul Walmsley 	u32 v;
48ff4ae5d9SPaul Walmsley 
49ff4ae5d9SPaul Walmsley 	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
50ff4ae5d9SPaul Walmsley 	v &= mask;
51ff4ae5d9SPaul Walmsley 	v >>= __ffs(mask);
52ff4ae5d9SPaul Walmsley 
53ff4ae5d9SPaul Walmsley 	return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
54ff4ae5d9SPaul Walmsley }
55ff4ae5d9SPaul Walmsley 
56f2650d6eSTero Kristo static void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
57ff4ae5d9SPaul Walmsley {
58ff4ae5d9SPaul Walmsley 	_write_clktrctrl(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
59ff4ae5d9SPaul Walmsley }
60ff4ae5d9SPaul Walmsley 
61f2650d6eSTero Kristo static void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
62ff4ae5d9SPaul Walmsley {
63ff4ae5d9SPaul Walmsley 	_write_clktrctrl(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
64ff4ae5d9SPaul Walmsley }
65ff4ae5d9SPaul Walmsley 
66f2650d6eSTero Kristo static void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask)
67ff4ae5d9SPaul Walmsley {
68ff4ae5d9SPaul Walmsley 	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, module, mask);
69ff4ae5d9SPaul Walmsley }
70ff4ae5d9SPaul Walmsley 
71f2650d6eSTero Kristo static void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
72ff4ae5d9SPaul Walmsley {
73ff4ae5d9SPaul Walmsley 	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
74ff4ae5d9SPaul Walmsley }
75ff4ae5d9SPaul Walmsley 
76ff4ae5d9SPaul Walmsley /*
77ff4ae5d9SPaul Walmsley  *
78ff4ae5d9SPaul Walmsley  */
79ff4ae5d9SPaul Walmsley 
80ff4ae5d9SPaul Walmsley /**
81ff4ae5d9SPaul Walmsley  * omap3xxx_cm_wait_module_ready - wait for a module to leave idle or standby
82021b6ff0STero Kristo  * @part: PRCM partition, ignored for OMAP3
83ff4ae5d9SPaul Walmsley  * @prcm_mod: PRCM module offset
84ff4ae5d9SPaul Walmsley  * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
85ff4ae5d9SPaul Walmsley  * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
86ff4ae5d9SPaul Walmsley  *
87ff4ae5d9SPaul Walmsley  * Wait for the PRCM to indicate that the module identified by
88ff4ae5d9SPaul Walmsley  * (@prcm_mod, @idlest_id, @idlest_shift) is clocked.  Return 0 upon
89ff4ae5d9SPaul Walmsley  * success or -EBUSY if the module doesn't enable in time.
90ff4ae5d9SPaul Walmsley  */
91021b6ff0STero Kristo static int omap3xxx_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_id,
92021b6ff0STero Kristo 					 u8 idlest_shift)
93ff4ae5d9SPaul Walmsley {
94ff4ae5d9SPaul Walmsley 	int ena = 0, i = 0;
95ff4ae5d9SPaul Walmsley 	u8 cm_idlest_reg;
96ff4ae5d9SPaul Walmsley 	u32 mask;
97ff4ae5d9SPaul Walmsley 
98ff4ae5d9SPaul Walmsley 	if (!idlest_id || (idlest_id > ARRAY_SIZE(omap3xxx_cm_idlest_offs)))
99ff4ae5d9SPaul Walmsley 		return -EINVAL;
100ff4ae5d9SPaul Walmsley 
101ff4ae5d9SPaul Walmsley 	cm_idlest_reg = omap3xxx_cm_idlest_offs[idlest_id - 1];
102ff4ae5d9SPaul Walmsley 
103ff4ae5d9SPaul Walmsley 	mask = 1 << idlest_shift;
104ff4ae5d9SPaul Walmsley 	ena = 0;
105ff4ae5d9SPaul Walmsley 
106ff4ae5d9SPaul Walmsley 	omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) &
107ff4ae5d9SPaul Walmsley 			    mask) == ena), MAX_MODULE_READY_TIME, i);
108ff4ae5d9SPaul Walmsley 
109ff4ae5d9SPaul Walmsley 	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
110ff4ae5d9SPaul Walmsley }
111ff4ae5d9SPaul Walmsley 
112c4ceedcbSPaul Walmsley /**
113c4ceedcbSPaul Walmsley  * omap3xxx_cm_split_idlest_reg - split CM_IDLEST reg addr into its components
114c4ceedcbSPaul Walmsley  * @idlest_reg: CM_IDLEST* virtual address
115c4ceedcbSPaul Walmsley  * @prcm_inst: pointer to an s16 to return the PRCM instance offset
116c4ceedcbSPaul Walmsley  * @idlest_reg_id: pointer to a u8 to return the CM_IDLESTx register ID
117c4ceedcbSPaul Walmsley  *
118c4ceedcbSPaul Walmsley  * XXX This function is only needed until absolute register addresses are
119c4ceedcbSPaul Walmsley  * removed from the OMAP struct clk records.
120c4ceedcbSPaul Walmsley  */
1216c0afb50STero Kristo static int omap3xxx_cm_split_idlest_reg(struct clk_omap_reg *idlest_reg,
1222196a9b8STero Kristo 					s16 *prcm_inst,
123c4ceedcbSPaul Walmsley 					u8 *idlest_reg_id)
124c4ceedcbSPaul Walmsley {
125c4ceedcbSPaul Walmsley 	unsigned long offs;
126c4ceedcbSPaul Walmsley 	u8 idlest_offs;
127c4ceedcbSPaul Walmsley 	int i;
128c4ceedcbSPaul Walmsley 
1296c0afb50STero Kristo 	idlest_offs = idlest_reg->offset & 0xff;
130c4ceedcbSPaul Walmsley 	for (i = 0; i < ARRAY_SIZE(omap3xxx_cm_idlest_offs); i++) {
131c4ceedcbSPaul Walmsley 		if (idlest_offs == omap3xxx_cm_idlest_offs[i]) {
132c4ceedcbSPaul Walmsley 			*idlest_reg_id = i + 1;
133c4ceedcbSPaul Walmsley 			break;
134c4ceedcbSPaul Walmsley 		}
135c4ceedcbSPaul Walmsley 	}
136c4ceedcbSPaul Walmsley 
137c4ceedcbSPaul Walmsley 	if (i == ARRAY_SIZE(omap3xxx_cm_idlest_offs))
138c4ceedcbSPaul Walmsley 		return -EINVAL;
139c4ceedcbSPaul Walmsley 
1406c0afb50STero Kristo 	offs = idlest_reg->offset;
141c4ceedcbSPaul Walmsley 	offs &= 0xff00;
142c4ceedcbSPaul Walmsley 	*prcm_inst = offs;
143c4ceedcbSPaul Walmsley 
144c4ceedcbSPaul Walmsley 	return 0;
145c4ceedcbSPaul Walmsley }
146c4ceedcbSPaul Walmsley 
1474bd5259eSPaul Walmsley /* Clockdomain low-level operations */
1484bd5259eSPaul Walmsley 
1494bd5259eSPaul Walmsley static int omap3xxx_clkdm_add_sleepdep(struct clockdomain *clkdm1,
1504bd5259eSPaul Walmsley 				       struct clockdomain *clkdm2)
1514bd5259eSPaul Walmsley {
1524bd5259eSPaul Walmsley 	omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
1534bd5259eSPaul Walmsley 				  clkdm1->pwrdm.ptr->prcm_offs,
1544bd5259eSPaul Walmsley 				  OMAP3430_CM_SLEEPDEP);
1554bd5259eSPaul Walmsley 	return 0;
1564bd5259eSPaul Walmsley }
1574bd5259eSPaul Walmsley 
1584bd5259eSPaul Walmsley static int omap3xxx_clkdm_del_sleepdep(struct clockdomain *clkdm1,
1594bd5259eSPaul Walmsley 				       struct clockdomain *clkdm2)
1604bd5259eSPaul Walmsley {
1614bd5259eSPaul Walmsley 	omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
1624bd5259eSPaul Walmsley 				    clkdm1->pwrdm.ptr->prcm_offs,
1634bd5259eSPaul Walmsley 				    OMAP3430_CM_SLEEPDEP);
1644bd5259eSPaul Walmsley 	return 0;
1654bd5259eSPaul Walmsley }
1664bd5259eSPaul Walmsley 
1674bd5259eSPaul Walmsley static int omap3xxx_clkdm_read_sleepdep(struct clockdomain *clkdm1,
1684bd5259eSPaul Walmsley 					struct clockdomain *clkdm2)
1694bd5259eSPaul Walmsley {
1704bd5259eSPaul Walmsley 	return omap2_cm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
1714bd5259eSPaul Walmsley 					    OMAP3430_CM_SLEEPDEP,
1724bd5259eSPaul Walmsley 					    (1 << clkdm2->dep_bit));
1734bd5259eSPaul Walmsley }
1744bd5259eSPaul Walmsley 
1754bd5259eSPaul Walmsley static int omap3xxx_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
1764bd5259eSPaul Walmsley {
1774bd5259eSPaul Walmsley 	struct clkdm_dep *cd;
1784bd5259eSPaul Walmsley 	u32 mask = 0;
1794bd5259eSPaul Walmsley 
1804bd5259eSPaul Walmsley 	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
1814bd5259eSPaul Walmsley 		if (!cd->clkdm)
1824bd5259eSPaul Walmsley 			continue; /* only happens if data is erroneous */
1834bd5259eSPaul Walmsley 
1844bd5259eSPaul Walmsley 		mask |= 1 << cd->clkdm->dep_bit;
18592493870SPaul Walmsley 		cd->sleepdep_usecount = 0;
1864bd5259eSPaul Walmsley 	}
1874bd5259eSPaul Walmsley 	omap2_cm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
1884bd5259eSPaul Walmsley 				    OMAP3430_CM_SLEEPDEP);
1894bd5259eSPaul Walmsley 	return 0;
1904bd5259eSPaul Walmsley }
1914bd5259eSPaul Walmsley 
1924bd5259eSPaul Walmsley static int omap3xxx_clkdm_sleep(struct clockdomain *clkdm)
1934bd5259eSPaul Walmsley {
1944bd5259eSPaul Walmsley 	omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
1954bd5259eSPaul Walmsley 				      clkdm->clktrctrl_mask);
1964bd5259eSPaul Walmsley 	return 0;
1974bd5259eSPaul Walmsley }
1984bd5259eSPaul Walmsley 
1994bd5259eSPaul Walmsley static int omap3xxx_clkdm_wakeup(struct clockdomain *clkdm)
2004bd5259eSPaul Walmsley {
2014bd5259eSPaul Walmsley 	omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
2024bd5259eSPaul Walmsley 				       clkdm->clktrctrl_mask);
2034bd5259eSPaul Walmsley 	return 0;
2044bd5259eSPaul Walmsley }
2054bd5259eSPaul Walmsley 
2064bd5259eSPaul Walmsley static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm)
2074bd5259eSPaul Walmsley {
20892493870SPaul Walmsley 	if (clkdm->usecount > 0)
20965958fb6SPaul Walmsley 		clkdm_add_autodeps(clkdm);
2104bd5259eSPaul Walmsley 
2114bd5259eSPaul Walmsley 	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
2124bd5259eSPaul Walmsley 				       clkdm->clktrctrl_mask);
2134bd5259eSPaul Walmsley }
2144bd5259eSPaul Walmsley 
2154bd5259eSPaul Walmsley static void omap3xxx_clkdm_deny_idle(struct clockdomain *clkdm)
2164bd5259eSPaul Walmsley {
2174bd5259eSPaul Walmsley 	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
2184bd5259eSPaul Walmsley 					clkdm->clktrctrl_mask);
2194bd5259eSPaul Walmsley 
22092493870SPaul Walmsley 	if (clkdm->usecount > 0)
22165958fb6SPaul Walmsley 		clkdm_del_autodeps(clkdm);
2224bd5259eSPaul Walmsley }
2234bd5259eSPaul Walmsley 
2244bd5259eSPaul Walmsley static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
2254bd5259eSPaul Walmsley {
2264bd5259eSPaul Walmsley 	bool hwsup = false;
2274bd5259eSPaul Walmsley 
2284bd5259eSPaul Walmsley 	if (!clkdm->clktrctrl_mask)
2294bd5259eSPaul Walmsley 		return 0;
2304bd5259eSPaul Walmsley 
2314bd5259eSPaul Walmsley 	/*
2324bd5259eSPaul Walmsley 	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
2334bd5259eSPaul Walmsley 	 * more details on the unpleasant problem this is working
2344bd5259eSPaul Walmsley 	 * around
2354bd5259eSPaul Walmsley 	 */
2364bd5259eSPaul Walmsley 	if ((clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) &&
2374bd5259eSPaul Walmsley 	    (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
2384bd5259eSPaul Walmsley 		omap3xxx_clkdm_wakeup(clkdm);
2394bd5259eSPaul Walmsley 		return 0;
2404bd5259eSPaul Walmsley 	}
2414bd5259eSPaul Walmsley 
2424bd5259eSPaul Walmsley 	hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
2434bd5259eSPaul Walmsley 					      clkdm->clktrctrl_mask);
2444bd5259eSPaul Walmsley 
2454bd5259eSPaul Walmsley 	if (hwsup) {
2464bd5259eSPaul Walmsley 		/* Disable HW transitions when we are changing deps */
2474bd5259eSPaul Walmsley 		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
2484bd5259eSPaul Walmsley 						clkdm->clktrctrl_mask);
24965958fb6SPaul Walmsley 		clkdm_add_autodeps(clkdm);
2504bd5259eSPaul Walmsley 		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
2514bd5259eSPaul Walmsley 					       clkdm->clktrctrl_mask);
2524bd5259eSPaul Walmsley 	} else {
2534bd5259eSPaul Walmsley 		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
2544bd5259eSPaul Walmsley 			omap3xxx_clkdm_wakeup(clkdm);
2554bd5259eSPaul Walmsley 	}
2564bd5259eSPaul Walmsley 
2574bd5259eSPaul Walmsley 	return 0;
2584bd5259eSPaul Walmsley }
2594bd5259eSPaul Walmsley 
2604bd5259eSPaul Walmsley static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
2614bd5259eSPaul Walmsley {
2624bd5259eSPaul Walmsley 	bool hwsup = false;
2634bd5259eSPaul Walmsley 
2644bd5259eSPaul Walmsley 	if (!clkdm->clktrctrl_mask)
2654bd5259eSPaul Walmsley 		return 0;
2664bd5259eSPaul Walmsley 
2674bd5259eSPaul Walmsley 	/*
2684bd5259eSPaul Walmsley 	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
2694bd5259eSPaul Walmsley 	 * more details on the unpleasant problem this is working
2704bd5259eSPaul Walmsley 	 * around
2714bd5259eSPaul Walmsley 	 */
2724bd5259eSPaul Walmsley 	if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
2734bd5259eSPaul Walmsley 	    !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
2744bd5259eSPaul Walmsley 		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
2754bd5259eSPaul Walmsley 					       clkdm->clktrctrl_mask);
2764bd5259eSPaul Walmsley 		return 0;
2774bd5259eSPaul Walmsley 	}
2784bd5259eSPaul Walmsley 
2794bd5259eSPaul Walmsley 	hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
2804bd5259eSPaul Walmsley 					      clkdm->clktrctrl_mask);
2814bd5259eSPaul Walmsley 
2824bd5259eSPaul Walmsley 	if (hwsup) {
2834bd5259eSPaul Walmsley 		/* Disable HW transitions when we are changing deps */
2844bd5259eSPaul Walmsley 		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
2854bd5259eSPaul Walmsley 						clkdm->clktrctrl_mask);
28665958fb6SPaul Walmsley 		clkdm_del_autodeps(clkdm);
2874bd5259eSPaul Walmsley 		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
2884bd5259eSPaul Walmsley 					       clkdm->clktrctrl_mask);
2894bd5259eSPaul Walmsley 	} else {
2904bd5259eSPaul Walmsley 		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
2914bd5259eSPaul Walmsley 			omap3xxx_clkdm_sleep(clkdm);
2924bd5259eSPaul Walmsley 	}
2934bd5259eSPaul Walmsley 
2944bd5259eSPaul Walmsley 	return 0;
2954bd5259eSPaul Walmsley }
2964bd5259eSPaul Walmsley 
2974bd5259eSPaul Walmsley struct clkdm_ops omap3_clkdm_operations = {
2984bd5259eSPaul Walmsley 	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
2994bd5259eSPaul Walmsley 	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
3004bd5259eSPaul Walmsley 	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
3014bd5259eSPaul Walmsley 	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
3024bd5259eSPaul Walmsley 	.clkdm_add_sleepdep	= omap3xxx_clkdm_add_sleepdep,
3034bd5259eSPaul Walmsley 	.clkdm_del_sleepdep	= omap3xxx_clkdm_del_sleepdep,
3044bd5259eSPaul Walmsley 	.clkdm_read_sleepdep	= omap3xxx_clkdm_read_sleepdep,
3054bd5259eSPaul Walmsley 	.clkdm_clear_all_sleepdeps	= omap3xxx_clkdm_clear_all_sleepdeps,
3064bd5259eSPaul Walmsley 	.clkdm_sleep		= omap3xxx_clkdm_sleep,
3074bd5259eSPaul Walmsley 	.clkdm_wakeup		= omap3xxx_clkdm_wakeup,
3084bd5259eSPaul Walmsley 	.clkdm_allow_idle	= omap3xxx_clkdm_allow_idle,
3094bd5259eSPaul Walmsley 	.clkdm_deny_idle	= omap3xxx_clkdm_deny_idle,
3104bd5259eSPaul Walmsley 	.clkdm_clk_enable	= omap3xxx_clkdm_clk_enable,
3114bd5259eSPaul Walmsley 	.clkdm_clk_disable	= omap3xxx_clkdm_clk_disable,
3124bd5259eSPaul Walmsley };
3134bd5259eSPaul Walmsley 
314ff4ae5d9SPaul Walmsley /*
315ff4ae5d9SPaul Walmsley  * Context save/restore code - OMAP3 only
316ff4ae5d9SPaul Walmsley  */
317ff4ae5d9SPaul Walmsley struct omap3_cm_regs {
318ff4ae5d9SPaul Walmsley 	u32 iva2_cm_clksel1;
319ff4ae5d9SPaul Walmsley 	u32 iva2_cm_clksel2;
320ff4ae5d9SPaul Walmsley 	u32 cm_sysconfig;
321ff4ae5d9SPaul Walmsley 	u32 sgx_cm_clksel;
322ff4ae5d9SPaul Walmsley 	u32 dss_cm_clksel;
323ff4ae5d9SPaul Walmsley 	u32 cam_cm_clksel;
324ff4ae5d9SPaul Walmsley 	u32 per_cm_clksel;
325ff4ae5d9SPaul Walmsley 	u32 emu_cm_clksel;
326ff4ae5d9SPaul Walmsley 	u32 emu_cm_clkstctrl;
327ff4ae5d9SPaul Walmsley 	u32 pll_cm_autoidle;
328ff4ae5d9SPaul Walmsley 	u32 pll_cm_autoidle2;
329ff4ae5d9SPaul Walmsley 	u32 pll_cm_clksel4;
330ff4ae5d9SPaul Walmsley 	u32 pll_cm_clksel5;
331ff4ae5d9SPaul Walmsley 	u32 pll_cm_clken2;
332ff4ae5d9SPaul Walmsley 	u32 cm_polctrl;
333ff4ae5d9SPaul Walmsley 	u32 iva2_cm_fclken;
334ff4ae5d9SPaul Walmsley 	u32 iva2_cm_clken_pll;
335ff4ae5d9SPaul Walmsley 	u32 core_cm_fclken1;
336ff4ae5d9SPaul Walmsley 	u32 core_cm_fclken3;
337ff4ae5d9SPaul Walmsley 	u32 sgx_cm_fclken;
338ff4ae5d9SPaul Walmsley 	u32 wkup_cm_fclken;
339ff4ae5d9SPaul Walmsley 	u32 dss_cm_fclken;
340ff4ae5d9SPaul Walmsley 	u32 cam_cm_fclken;
341ff4ae5d9SPaul Walmsley 	u32 per_cm_fclken;
342ff4ae5d9SPaul Walmsley 	u32 usbhost_cm_fclken;
343ff4ae5d9SPaul Walmsley 	u32 core_cm_iclken1;
344ff4ae5d9SPaul Walmsley 	u32 core_cm_iclken2;
345ff4ae5d9SPaul Walmsley 	u32 core_cm_iclken3;
346ff4ae5d9SPaul Walmsley 	u32 sgx_cm_iclken;
347ff4ae5d9SPaul Walmsley 	u32 wkup_cm_iclken;
348ff4ae5d9SPaul Walmsley 	u32 dss_cm_iclken;
349ff4ae5d9SPaul Walmsley 	u32 cam_cm_iclken;
350ff4ae5d9SPaul Walmsley 	u32 per_cm_iclken;
351ff4ae5d9SPaul Walmsley 	u32 usbhost_cm_iclken;
352ff4ae5d9SPaul Walmsley 	u32 iva2_cm_autoidle2;
353ff4ae5d9SPaul Walmsley 	u32 mpu_cm_autoidle2;
354ff4ae5d9SPaul Walmsley 	u32 iva2_cm_clkstctrl;
355ff4ae5d9SPaul Walmsley 	u32 mpu_cm_clkstctrl;
356ff4ae5d9SPaul Walmsley 	u32 core_cm_clkstctrl;
357ff4ae5d9SPaul Walmsley 	u32 sgx_cm_clkstctrl;
358ff4ae5d9SPaul Walmsley 	u32 dss_cm_clkstctrl;
359ff4ae5d9SPaul Walmsley 	u32 cam_cm_clkstctrl;
360ff4ae5d9SPaul Walmsley 	u32 per_cm_clkstctrl;
361ff4ae5d9SPaul Walmsley 	u32 neon_cm_clkstctrl;
362ff4ae5d9SPaul Walmsley 	u32 usbhost_cm_clkstctrl;
363ff4ae5d9SPaul Walmsley 	u32 core_cm_autoidle1;
364ff4ae5d9SPaul Walmsley 	u32 core_cm_autoidle2;
365ff4ae5d9SPaul Walmsley 	u32 core_cm_autoidle3;
366ff4ae5d9SPaul Walmsley 	u32 wkup_cm_autoidle;
367ff4ae5d9SPaul Walmsley 	u32 dss_cm_autoidle;
368ff4ae5d9SPaul Walmsley 	u32 cam_cm_autoidle;
369ff4ae5d9SPaul Walmsley 	u32 per_cm_autoidle;
370ff4ae5d9SPaul Walmsley 	u32 usbhost_cm_autoidle;
371ff4ae5d9SPaul Walmsley 	u32 sgx_cm_sleepdep;
372ff4ae5d9SPaul Walmsley 	u32 dss_cm_sleepdep;
373ff4ae5d9SPaul Walmsley 	u32 cam_cm_sleepdep;
374ff4ae5d9SPaul Walmsley 	u32 per_cm_sleepdep;
375ff4ae5d9SPaul Walmsley 	u32 usbhost_cm_sleepdep;
376ff4ae5d9SPaul Walmsley 	u32 cm_clkout_ctrl;
377ff4ae5d9SPaul Walmsley };
378ff4ae5d9SPaul Walmsley 
379ff4ae5d9SPaul Walmsley static struct omap3_cm_regs cm_context;
380ff4ae5d9SPaul Walmsley 
381ff4ae5d9SPaul Walmsley void omap3_cm_save_context(void)
382ff4ae5d9SPaul Walmsley {
383ff4ae5d9SPaul Walmsley 	cm_context.iva2_cm_clksel1 =
384ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1);
385ff4ae5d9SPaul Walmsley 	cm_context.iva2_cm_clksel2 =
386ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL2);
387b21be7bcSTero Kristo 	cm_context.cm_sysconfig =
388b21be7bcSTero Kristo 		omap2_cm_read_mod_reg(OCP_MOD, OMAP3430_CM_SYSCONFIG);
389ff4ae5d9SPaul Walmsley 	cm_context.sgx_cm_clksel =
390ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL);
391ff4ae5d9SPaul Walmsley 	cm_context.dss_cm_clksel =
392ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSEL);
393ff4ae5d9SPaul Walmsley 	cm_context.cam_cm_clksel =
394ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_CLKSEL);
395ff4ae5d9SPaul Walmsley 	cm_context.per_cm_clksel =
396ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_CLKSEL);
397ff4ae5d9SPaul Walmsley 	cm_context.emu_cm_clksel =
398ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
399ff4ae5d9SPaul Walmsley 	cm_context.emu_cm_clkstctrl =
400ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
401ff4ae5d9SPaul Walmsley 	/*
402ff4ae5d9SPaul Walmsley 	 * As per erratum i671, ROM code does not respect the PER DPLL
403ff4ae5d9SPaul Walmsley 	 * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
404ff4ae5d9SPaul Walmsley 	 * In this case, even though this register has been saved in
405ff4ae5d9SPaul Walmsley 	 * scratchpad contents, we need to restore AUTO_PERIPH_DPLL
406ff4ae5d9SPaul Walmsley 	 * by ourselves. So, we need to save it anyway.
407ff4ae5d9SPaul Walmsley 	 */
408ff4ae5d9SPaul Walmsley 	cm_context.pll_cm_autoidle =
409ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
410ff4ae5d9SPaul Walmsley 	cm_context.pll_cm_autoidle2 =
411ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
412ff4ae5d9SPaul Walmsley 	cm_context.pll_cm_clksel4 =
413ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
414ff4ae5d9SPaul Walmsley 	cm_context.pll_cm_clksel5 =
415ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
416ff4ae5d9SPaul Walmsley 	cm_context.pll_cm_clken2 =
417ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2);
418b21be7bcSTero Kristo 	cm_context.cm_polctrl =
419b21be7bcSTero Kristo 		omap2_cm_read_mod_reg(OCP_MOD, OMAP3430_CM_POLCTRL);
420ff4ae5d9SPaul Walmsley 	cm_context.iva2_cm_fclken =
421ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN);
422ff4ae5d9SPaul Walmsley 	cm_context.iva2_cm_clken_pll =
423ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL);
424ff4ae5d9SPaul Walmsley 	cm_context.core_cm_fclken1 =
425ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
426ff4ae5d9SPaul Walmsley 	cm_context.core_cm_fclken3 =
427ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
428ff4ae5d9SPaul Walmsley 	cm_context.sgx_cm_fclken =
429ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_FCLKEN);
430ff4ae5d9SPaul Walmsley 	cm_context.wkup_cm_fclken =
431ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
432ff4ae5d9SPaul Walmsley 	cm_context.dss_cm_fclken =
433ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_FCLKEN);
434ff4ae5d9SPaul Walmsley 	cm_context.cam_cm_fclken =
435ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_FCLKEN);
436ff4ae5d9SPaul Walmsley 	cm_context.per_cm_fclken =
437ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
438ff4ae5d9SPaul Walmsley 	cm_context.usbhost_cm_fclken =
439ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
440ff4ae5d9SPaul Walmsley 	cm_context.core_cm_iclken1 =
441ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
442ff4ae5d9SPaul Walmsley 	cm_context.core_cm_iclken2 =
443ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN2);
444ff4ae5d9SPaul Walmsley 	cm_context.core_cm_iclken3 =
445ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
446ff4ae5d9SPaul Walmsley 	cm_context.sgx_cm_iclken =
447ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_ICLKEN);
448ff4ae5d9SPaul Walmsley 	cm_context.wkup_cm_iclken =
449ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
450ff4ae5d9SPaul Walmsley 	cm_context.dss_cm_iclken =
451ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_ICLKEN);
452ff4ae5d9SPaul Walmsley 	cm_context.cam_cm_iclken =
453ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_ICLKEN);
454ff4ae5d9SPaul Walmsley 	cm_context.per_cm_iclken =
455ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
456ff4ae5d9SPaul Walmsley 	cm_context.usbhost_cm_iclken =
457ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
458ff4ae5d9SPaul Walmsley 	cm_context.iva2_cm_autoidle2 =
459ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
460ff4ae5d9SPaul Walmsley 	cm_context.mpu_cm_autoidle2 =
461ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(MPU_MOD, CM_AUTOIDLE2);
462ff4ae5d9SPaul Walmsley 	cm_context.iva2_cm_clkstctrl =
463ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL);
464ff4ae5d9SPaul Walmsley 	cm_context.mpu_cm_clkstctrl =
465ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(MPU_MOD, OMAP2_CM_CLKSTCTRL);
466ff4ae5d9SPaul Walmsley 	cm_context.core_cm_clkstctrl =
467ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(CORE_MOD, OMAP2_CM_CLKSTCTRL);
468ff4ae5d9SPaul Walmsley 	cm_context.sgx_cm_clkstctrl =
469ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, OMAP2_CM_CLKSTCTRL);
470ff4ae5d9SPaul Walmsley 	cm_context.dss_cm_clkstctrl =
471ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP2_CM_CLKSTCTRL);
472ff4ae5d9SPaul Walmsley 	cm_context.cam_cm_clkstctrl =
473ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP2_CM_CLKSTCTRL);
474ff4ae5d9SPaul Walmsley 	cm_context.per_cm_clkstctrl =
475ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP2_CM_CLKSTCTRL);
476ff4ae5d9SPaul Walmsley 	cm_context.neon_cm_clkstctrl =
477ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_NEON_MOD, OMAP2_CM_CLKSTCTRL);
478ff4ae5d9SPaul Walmsley 	cm_context.usbhost_cm_clkstctrl =
479ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
480ff4ae5d9SPaul Walmsley 				      OMAP2_CM_CLKSTCTRL);
481ff4ae5d9SPaul Walmsley 	cm_context.core_cm_autoidle1 =
482ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE1);
483ff4ae5d9SPaul Walmsley 	cm_context.core_cm_autoidle2 =
484ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE2);
485ff4ae5d9SPaul Walmsley 	cm_context.core_cm_autoidle3 =
486ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE3);
487ff4ae5d9SPaul Walmsley 	cm_context.wkup_cm_autoidle =
488ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(WKUP_MOD, CM_AUTOIDLE);
489ff4ae5d9SPaul Walmsley 	cm_context.dss_cm_autoidle =
490ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_AUTOIDLE);
491ff4ae5d9SPaul Walmsley 	cm_context.cam_cm_autoidle =
492ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_AUTOIDLE);
493ff4ae5d9SPaul Walmsley 	cm_context.per_cm_autoidle =
494ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
495ff4ae5d9SPaul Walmsley 	cm_context.usbhost_cm_autoidle =
496ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
497ff4ae5d9SPaul Walmsley 	cm_context.sgx_cm_sleepdep =
498ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
499ff4ae5d9SPaul Walmsley 				      OMAP3430_CM_SLEEPDEP);
500ff4ae5d9SPaul Walmsley 	cm_context.dss_cm_sleepdep =
501ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP3430_CM_SLEEPDEP);
502ff4ae5d9SPaul Walmsley 	cm_context.cam_cm_sleepdep =
503ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP3430_CM_SLEEPDEP);
504ff4ae5d9SPaul Walmsley 	cm_context.per_cm_sleepdep =
505ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_CM_SLEEPDEP);
506ff4ae5d9SPaul Walmsley 	cm_context.usbhost_cm_sleepdep =
507ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
508ff4ae5d9SPaul Walmsley 				      OMAP3430_CM_SLEEPDEP);
509ff4ae5d9SPaul Walmsley 	cm_context.cm_clkout_ctrl =
510ff4ae5d9SPaul Walmsley 		omap2_cm_read_mod_reg(OMAP3430_CCR_MOD,
511ff4ae5d9SPaul Walmsley 				      OMAP3_CM_CLKOUT_CTRL_OFFSET);
512ff4ae5d9SPaul Walmsley }
513ff4ae5d9SPaul Walmsley 
514ff4ae5d9SPaul Walmsley void omap3_cm_restore_context(void)
515ff4ae5d9SPaul Walmsley {
516ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel1, OMAP3430_IVA2_MOD,
517ff4ae5d9SPaul Walmsley 			       CM_CLKSEL1);
518ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel2, OMAP3430_IVA2_MOD,
519ff4ae5d9SPaul Walmsley 			       CM_CLKSEL2);
520b21be7bcSTero Kristo 	omap2_cm_write_mod_reg(cm_context.cm_sysconfig, OCP_MOD,
521b21be7bcSTero Kristo 			       OMAP3430_CM_SYSCONFIG);
522ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD,
523ff4ae5d9SPaul Walmsley 			       CM_CLKSEL);
524ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.dss_cm_clksel, OMAP3430_DSS_MOD,
525ff4ae5d9SPaul Walmsley 			       CM_CLKSEL);
526ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.cam_cm_clksel, OMAP3430_CAM_MOD,
527ff4ae5d9SPaul Walmsley 			       CM_CLKSEL);
528ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.per_cm_clksel, OMAP3430_PER_MOD,
529ff4ae5d9SPaul Walmsley 			       CM_CLKSEL);
530ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.emu_cm_clksel, OMAP3430_EMU_MOD,
531ff4ae5d9SPaul Walmsley 			       CM_CLKSEL1);
532ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
533ff4ae5d9SPaul Walmsley 			       OMAP2_CM_CLKSTCTRL);
534ff4ae5d9SPaul Walmsley 	/*
535ff4ae5d9SPaul Walmsley 	 * As per erratum i671, ROM code does not respect the PER DPLL
536ff4ae5d9SPaul Walmsley 	 * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
537ff4ae5d9SPaul Walmsley 	 * In this case, we need to restore AUTO_PERIPH_DPLL by ourselves.
538ff4ae5d9SPaul Walmsley 	 */
539ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle, PLL_MOD,
540ff4ae5d9SPaul Walmsley 			       CM_AUTOIDLE);
541ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD,
542ff4ae5d9SPaul Walmsley 			       CM_AUTOIDLE2);
543ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD,
544ff4ae5d9SPaul Walmsley 			       OMAP3430ES2_CM_CLKSEL4);
545ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.pll_cm_clksel5, PLL_MOD,
546ff4ae5d9SPaul Walmsley 			       OMAP3430ES2_CM_CLKSEL5);
547ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.pll_cm_clken2, PLL_MOD,
548ff4ae5d9SPaul Walmsley 			       OMAP3430ES2_CM_CLKEN2);
549b21be7bcSTero Kristo 	omap2_cm_write_mod_reg(cm_context.cm_polctrl, OCP_MOD,
550b21be7bcSTero Kristo 			       OMAP3430_CM_POLCTRL);
551ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD,
552ff4ae5d9SPaul Walmsley 			       CM_FCLKEN);
553ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD,
554ff4ae5d9SPaul Walmsley 			       OMAP3430_CM_CLKEN_PLL);
555ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.core_cm_fclken1, CORE_MOD,
556ff4ae5d9SPaul Walmsley 			       CM_FCLKEN1);
557ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.core_cm_fclken3, CORE_MOD,
558ff4ae5d9SPaul Walmsley 			       OMAP3430ES2_CM_FCLKEN3);
559ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.sgx_cm_fclken, OMAP3430ES2_SGX_MOD,
560ff4ae5d9SPaul Walmsley 			       CM_FCLKEN);
561ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.wkup_cm_fclken, WKUP_MOD, CM_FCLKEN);
562ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.dss_cm_fclken, OMAP3430_DSS_MOD,
563ff4ae5d9SPaul Walmsley 			       CM_FCLKEN);
564ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.cam_cm_fclken, OMAP3430_CAM_MOD,
565ff4ae5d9SPaul Walmsley 			       CM_FCLKEN);
566ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.per_cm_fclken, OMAP3430_PER_MOD,
567ff4ae5d9SPaul Walmsley 			       CM_FCLKEN);
568ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.usbhost_cm_fclken,
569ff4ae5d9SPaul Walmsley 			       OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
570ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.core_cm_iclken1, CORE_MOD,
571ff4ae5d9SPaul Walmsley 			       CM_ICLKEN1);
572ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.core_cm_iclken2, CORE_MOD,
573ff4ae5d9SPaul Walmsley 			       CM_ICLKEN2);
574ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.core_cm_iclken3, CORE_MOD,
575ff4ae5d9SPaul Walmsley 			       CM_ICLKEN3);
576ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.sgx_cm_iclken, OMAP3430ES2_SGX_MOD,
577ff4ae5d9SPaul Walmsley 			       CM_ICLKEN);
578ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.wkup_cm_iclken, WKUP_MOD, CM_ICLKEN);
579ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.dss_cm_iclken, OMAP3430_DSS_MOD,
580ff4ae5d9SPaul Walmsley 			       CM_ICLKEN);
581ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.cam_cm_iclken, OMAP3430_CAM_MOD,
582ff4ae5d9SPaul Walmsley 			       CM_ICLKEN);
583ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.per_cm_iclken, OMAP3430_PER_MOD,
584ff4ae5d9SPaul Walmsley 			       CM_ICLKEN);
585ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.usbhost_cm_iclken,
586ff4ae5d9SPaul Walmsley 			       OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
587ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.iva2_cm_autoidle2, OMAP3430_IVA2_MOD,
588ff4ae5d9SPaul Walmsley 			       CM_AUTOIDLE2);
589ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.mpu_cm_autoidle2, MPU_MOD,
590ff4ae5d9SPaul Walmsley 			       CM_AUTOIDLE2);
591ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.iva2_cm_clkstctrl, OMAP3430_IVA2_MOD,
592ff4ae5d9SPaul Walmsley 			       OMAP2_CM_CLKSTCTRL);
593ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.mpu_cm_clkstctrl, MPU_MOD,
594ff4ae5d9SPaul Walmsley 			       OMAP2_CM_CLKSTCTRL);
595ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.core_cm_clkstctrl, CORE_MOD,
596ff4ae5d9SPaul Walmsley 			       OMAP2_CM_CLKSTCTRL);
597ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.sgx_cm_clkstctrl, OMAP3430ES2_SGX_MOD,
598ff4ae5d9SPaul Walmsley 			       OMAP2_CM_CLKSTCTRL);
599ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.dss_cm_clkstctrl, OMAP3430_DSS_MOD,
600ff4ae5d9SPaul Walmsley 			       OMAP2_CM_CLKSTCTRL);
601ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.cam_cm_clkstctrl, OMAP3430_CAM_MOD,
602ff4ae5d9SPaul Walmsley 			       OMAP2_CM_CLKSTCTRL);
603ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.per_cm_clkstctrl, OMAP3430_PER_MOD,
604ff4ae5d9SPaul Walmsley 			       OMAP2_CM_CLKSTCTRL);
605ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.neon_cm_clkstctrl, OMAP3430_NEON_MOD,
606ff4ae5d9SPaul Walmsley 			       OMAP2_CM_CLKSTCTRL);
607ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.usbhost_cm_clkstctrl,
608ff4ae5d9SPaul Walmsley 			       OMAP3430ES2_USBHOST_MOD, OMAP2_CM_CLKSTCTRL);
609ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle1, CORE_MOD,
610ff4ae5d9SPaul Walmsley 			       CM_AUTOIDLE1);
611ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle2, CORE_MOD,
612ff4ae5d9SPaul Walmsley 			       CM_AUTOIDLE2);
613ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle3, CORE_MOD,
614ff4ae5d9SPaul Walmsley 			       CM_AUTOIDLE3);
615ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.wkup_cm_autoidle, WKUP_MOD,
616ff4ae5d9SPaul Walmsley 			       CM_AUTOIDLE);
617ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.dss_cm_autoidle, OMAP3430_DSS_MOD,
618ff4ae5d9SPaul Walmsley 			       CM_AUTOIDLE);
619ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.cam_cm_autoidle, OMAP3430_CAM_MOD,
620ff4ae5d9SPaul Walmsley 			       CM_AUTOIDLE);
621ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.per_cm_autoidle, OMAP3430_PER_MOD,
622ff4ae5d9SPaul Walmsley 			       CM_AUTOIDLE);
623ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.usbhost_cm_autoidle,
624ff4ae5d9SPaul Walmsley 			       OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
625ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.sgx_cm_sleepdep, OMAP3430ES2_SGX_MOD,
626ff4ae5d9SPaul Walmsley 			       OMAP3430_CM_SLEEPDEP);
627ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.dss_cm_sleepdep, OMAP3430_DSS_MOD,
628ff4ae5d9SPaul Walmsley 			       OMAP3430_CM_SLEEPDEP);
629ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.cam_cm_sleepdep, OMAP3430_CAM_MOD,
630ff4ae5d9SPaul Walmsley 			       OMAP3430_CM_SLEEPDEP);
631ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.per_cm_sleepdep, OMAP3430_PER_MOD,
632ff4ae5d9SPaul Walmsley 			       OMAP3430_CM_SLEEPDEP);
633ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.usbhost_cm_sleepdep,
634ff4ae5d9SPaul Walmsley 			       OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
635ff4ae5d9SPaul Walmsley 	omap2_cm_write_mod_reg(cm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
636ff4ae5d9SPaul Walmsley 			       OMAP3_CM_CLKOUT_CTRL_OFFSET);
637ff4ae5d9SPaul Walmsley }
638c4ceedcbSPaul Walmsley 
639c6a2d839STero Kristo void omap3_cm_save_scratchpad_contents(u32 *ptr)
640c6a2d839STero Kristo {
641c6a2d839STero Kristo 	*ptr++ = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL);
642c6a2d839STero Kristo 	*ptr++ = omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
643c6a2d839STero Kristo 	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
644c6a2d839STero Kristo 
645c6a2d839STero Kristo 	/*
646c6a2d839STero Kristo 	 * As per erratum i671, ROM code does not respect the PER DPLL
647c6a2d839STero Kristo 	 * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
648c6a2d839STero Kristo 	 * Then,  in any case, clear these bits to avoid extra latencies.
649c6a2d839STero Kristo 	 */
650c6a2d839STero Kristo 	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
651c6a2d839STero Kristo 		~OMAP3430_AUTO_PERIPH_DPLL_MASK;
652c6a2d839STero Kristo 	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
653c6a2d839STero Kristo 	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL2_PLL);
654c6a2d839STero Kristo 	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL3);
655c6a2d839STero Kristo 	*ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKEN_PLL);
656c6a2d839STero Kristo 	*ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL);
657c6a2d839STero Kristo 	*ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL);
658c6a2d839STero Kristo 	*ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL);
659c6a2d839STero Kristo }
660c6a2d839STero Kristo 
661c4ceedcbSPaul Walmsley /*
662c4ceedcbSPaul Walmsley  *
663c4ceedcbSPaul Walmsley  */
664c4ceedcbSPaul Walmsley 
665c4ceedcbSPaul Walmsley static struct cm_ll_data omap3xxx_cm_ll_data = {
666c4ceedcbSPaul Walmsley 	.split_idlest_reg	= &omap3xxx_cm_split_idlest_reg,
667c4ceedcbSPaul Walmsley 	.wait_module_ready	= &omap3xxx_cm_wait_module_ready,
668c4ceedcbSPaul Walmsley };
669c4ceedcbSPaul Walmsley 
670425dc8b2STero Kristo int __init omap3xxx_cm_init(const struct omap_prcm_init_data *data)
671c4ceedcbSPaul Walmsley {
67290129336STero Kristo 	omap2_clk_legacy_provider_init(TI_CLKM_CM, cm_base.va +
67390129336STero Kristo 				       OMAP3430_IVA2_MOD);
674c4ceedcbSPaul Walmsley 	return cm_register(&omap3xxx_cm_ll_data);
675c4ceedcbSPaul Walmsley }
676c4ceedcbSPaul Walmsley 
677c4ceedcbSPaul Walmsley static void __exit omap3xxx_cm_exit(void)
678c4ceedcbSPaul Walmsley {
6797af13637STero Kristo 	cm_unregister(&omap3xxx_cm_ll_data);
680c4ceedcbSPaul Walmsley }
681c4ceedcbSPaul Walmsley __exitcall(omap3xxx_cm_exit);
682