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