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