1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * OMAP3xxx CM module functions
4 *
5 * Copyright (C) 2009 Nokia Corporation
6 * Copyright (C) 2008-2010, 2012 Texas Instruments, Inc.
7 * Paul Walmsley
8 * Rajendra Nayak <rnayak@ti.com>
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <linux/delay.h>
14#include <linux/errno.h>
15#include <linux/err.h>
16#include <linux/io.h>
17
18#include "prm2xxx_3xxx.h"
19#include "cm.h"
20#include "cm3xxx.h"
21#include "cm-regbits-34xx.h"
22#include "clockdomain.h"
23
24static const u8 omap3xxx_cm_idlest_offs[] = {
25	CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
26};
27
28/*
29 *
30 */
31
32static void _write_clktrctrl(u8 c, s16 module, u32 mask)
33{
34	u32 v;
35
36	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
37	v &= ~mask;
38	v |= c << __ffs(mask);
39	omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
40}
41
42static bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
43{
44	u32 v;
45
46	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
47	v &= mask;
48	v >>= __ffs(mask);
49
50	return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
51}
52
53static void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
54{
55	_write_clktrctrl(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
56}
57
58static void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
59{
60	_write_clktrctrl(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
61}
62
63static void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask)
64{
65	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, module, mask);
66}
67
68static void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
69{
70	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
71}
72
73/*
74 *
75 */
76
77/**
78 * omap3xxx_cm_wait_module_ready - wait for a module to leave idle or standby
79 * @part: PRCM partition, ignored for OMAP3
80 * @prcm_mod: PRCM module offset
81 * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
82 * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
83 *
84 * Wait for the PRCM to indicate that the module identified by
85 * (@prcm_mod, @idlest_id, @idlest_shift) is clocked.  Return 0 upon
86 * success or -EBUSY if the module doesn't enable in time.
87 */
88static int omap3xxx_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_id,
89					 u8 idlest_shift)
90{
91	int ena = 0, i = 0;
92	u8 cm_idlest_reg;
93	u32 mask;
94
95	if (!idlest_id || (idlest_id > ARRAY_SIZE(omap3xxx_cm_idlest_offs)))
96		return -EINVAL;
97
98	cm_idlest_reg = omap3xxx_cm_idlest_offs[idlest_id - 1];
99
100	mask = 1 << idlest_shift;
101	ena = 0;
102
103	omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) &
104			    mask) == ena), MAX_MODULE_READY_TIME, i);
105
106	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
107}
108
109/**
110 * omap3xxx_cm_split_idlest_reg - split CM_IDLEST reg addr into its components
111 * @idlest_reg: CM_IDLEST* virtual address
112 * @prcm_inst: pointer to an s16 to return the PRCM instance offset
113 * @idlest_reg_id: pointer to a u8 to return the CM_IDLESTx register ID
114 *
115 * XXX This function is only needed until absolute register addresses are
116 * removed from the OMAP struct clk records.
117 */
118static int omap3xxx_cm_split_idlest_reg(struct clk_omap_reg *idlest_reg,
119					s16 *prcm_inst,
120					u8 *idlest_reg_id)
121{
122	unsigned long offs;
123	u8 idlest_offs;
124	int i;
125
126	idlest_offs = idlest_reg->offset & 0xff;
127	for (i = 0; i < ARRAY_SIZE(omap3xxx_cm_idlest_offs); i++) {
128		if (idlest_offs == omap3xxx_cm_idlest_offs[i]) {
129			*idlest_reg_id = i + 1;
130			break;
131		}
132	}
133
134	if (i == ARRAY_SIZE(omap3xxx_cm_idlest_offs))
135		return -EINVAL;
136
137	offs = idlest_reg->offset;
138	offs &= 0xff00;
139	*prcm_inst = offs;
140
141	return 0;
142}
143
144/* Clockdomain low-level operations */
145
146static int omap3xxx_clkdm_add_sleepdep(struct clockdomain *clkdm1,
147				       struct clockdomain *clkdm2)
148{
149	omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
150				  clkdm1->pwrdm.ptr->prcm_offs,
151				  OMAP3430_CM_SLEEPDEP);
152	return 0;
153}
154
155static int omap3xxx_clkdm_del_sleepdep(struct clockdomain *clkdm1,
156				       struct clockdomain *clkdm2)
157{
158	omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
159				    clkdm1->pwrdm.ptr->prcm_offs,
160				    OMAP3430_CM_SLEEPDEP);
161	return 0;
162}
163
164static int omap3xxx_clkdm_read_sleepdep(struct clockdomain *clkdm1,
165					struct clockdomain *clkdm2)
166{
167	return omap2_cm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
168					    OMAP3430_CM_SLEEPDEP,
169					    (1 << clkdm2->dep_bit));
170}
171
172static int omap3xxx_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
173{
174	struct clkdm_dep *cd;
175	u32 mask = 0;
176
177	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
178		if (!cd->clkdm)
179			continue; /* only happens if data is erroneous */
180
181		mask |= 1 << cd->clkdm->dep_bit;
182		cd->sleepdep_usecount = 0;
183	}
184	omap2_cm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
185				    OMAP3430_CM_SLEEPDEP);
186	return 0;
187}
188
189static int omap3xxx_clkdm_sleep(struct clockdomain *clkdm)
190{
191	omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
192				      clkdm->clktrctrl_mask);
193	return 0;
194}
195
196static int omap3xxx_clkdm_wakeup(struct clockdomain *clkdm)
197{
198	omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
199				       clkdm->clktrctrl_mask);
200	return 0;
201}
202
203static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm)
204{
205	if (clkdm->usecount > 0)
206		clkdm_add_autodeps(clkdm);
207
208	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
209				       clkdm->clktrctrl_mask);
210}
211
212static void omap3xxx_clkdm_deny_idle(struct clockdomain *clkdm)
213{
214	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
215					clkdm->clktrctrl_mask);
216
217	if (clkdm->usecount > 0)
218		clkdm_del_autodeps(clkdm);
219}
220
221static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
222{
223	bool hwsup = false;
224
225	if (!clkdm->clktrctrl_mask)
226		return 0;
227
228	/*
229	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
230	 * more details on the unpleasant problem this is working
231	 * around
232	 */
233	if ((clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) &&
234	    (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
235		omap3xxx_clkdm_wakeup(clkdm);
236		return 0;
237	}
238
239	hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
240					      clkdm->clktrctrl_mask);
241
242	if (hwsup) {
243		/* Disable HW transitions when we are changing deps */
244		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
245						clkdm->clktrctrl_mask);
246		clkdm_add_autodeps(clkdm);
247		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
248					       clkdm->clktrctrl_mask);
249	} else {
250		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
251			omap3xxx_clkdm_wakeup(clkdm);
252	}
253
254	return 0;
255}
256
257static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
258{
259	bool hwsup = false;
260
261	if (!clkdm->clktrctrl_mask)
262		return 0;
263
264	/*
265	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
266	 * more details on the unpleasant problem this is working
267	 * around
268	 */
269	if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
270	    !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
271		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
272					       clkdm->clktrctrl_mask);
273		return 0;
274	}
275
276	hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
277					      clkdm->clktrctrl_mask);
278
279	if (hwsup) {
280		/* Disable HW transitions when we are changing deps */
281		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
282						clkdm->clktrctrl_mask);
283		clkdm_del_autodeps(clkdm);
284		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
285					       clkdm->clktrctrl_mask);
286	} else {
287		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
288			omap3xxx_clkdm_sleep(clkdm);
289	}
290
291	return 0;
292}
293
294struct clkdm_ops omap3_clkdm_operations = {
295	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
296	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
297	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
298	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
299	.clkdm_add_sleepdep	= omap3xxx_clkdm_add_sleepdep,
300	.clkdm_del_sleepdep	= omap3xxx_clkdm_del_sleepdep,
301	.clkdm_read_sleepdep	= omap3xxx_clkdm_read_sleepdep,
302	.clkdm_clear_all_sleepdeps	= omap3xxx_clkdm_clear_all_sleepdeps,
303	.clkdm_sleep		= omap3xxx_clkdm_sleep,
304	.clkdm_wakeup		= omap3xxx_clkdm_wakeup,
305	.clkdm_allow_idle	= omap3xxx_clkdm_allow_idle,
306	.clkdm_deny_idle	= omap3xxx_clkdm_deny_idle,
307	.clkdm_clk_enable	= omap3xxx_clkdm_clk_enable,
308	.clkdm_clk_disable	= omap3xxx_clkdm_clk_disable,
309};
310
311/*
312 * Context save/restore code - OMAP3 only
313 */
314struct omap3_cm_regs {
315	u32 iva2_cm_clksel1;
316	u32 iva2_cm_clksel2;
317	u32 cm_sysconfig;
318	u32 sgx_cm_clksel;
319	u32 dss_cm_clksel;
320	u32 cam_cm_clksel;
321	u32 per_cm_clksel;
322	u32 emu_cm_clksel;
323	u32 emu_cm_clkstctrl;
324	u32 pll_cm_autoidle;
325	u32 pll_cm_autoidle2;
326	u32 pll_cm_clksel4;
327	u32 pll_cm_clksel5;
328	u32 pll_cm_clken2;
329	u32 cm_polctrl;
330	u32 iva2_cm_fclken;
331	u32 iva2_cm_clken_pll;
332	u32 core_cm_fclken1;
333	u32 core_cm_fclken3;
334	u32 sgx_cm_fclken;
335	u32 wkup_cm_fclken;
336	u32 dss_cm_fclken;
337	u32 cam_cm_fclken;
338	u32 per_cm_fclken;
339	u32 usbhost_cm_fclken;
340	u32 core_cm_iclken1;
341	u32 core_cm_iclken2;
342	u32 core_cm_iclken3;
343	u32 sgx_cm_iclken;
344	u32 wkup_cm_iclken;
345	u32 dss_cm_iclken;
346	u32 cam_cm_iclken;
347	u32 per_cm_iclken;
348	u32 usbhost_cm_iclken;
349	u32 iva2_cm_autoidle2;
350	u32 mpu_cm_autoidle2;
351	u32 iva2_cm_clkstctrl;
352	u32 mpu_cm_clkstctrl;
353	u32 core_cm_clkstctrl;
354	u32 sgx_cm_clkstctrl;
355	u32 dss_cm_clkstctrl;
356	u32 cam_cm_clkstctrl;
357	u32 per_cm_clkstctrl;
358	u32 neon_cm_clkstctrl;
359	u32 usbhost_cm_clkstctrl;
360	u32 core_cm_autoidle1;
361	u32 core_cm_autoidle2;
362	u32 core_cm_autoidle3;
363	u32 wkup_cm_autoidle;
364	u32 dss_cm_autoidle;
365	u32 cam_cm_autoidle;
366	u32 per_cm_autoidle;
367	u32 usbhost_cm_autoidle;
368	u32 sgx_cm_sleepdep;
369	u32 dss_cm_sleepdep;
370	u32 cam_cm_sleepdep;
371	u32 per_cm_sleepdep;
372	u32 usbhost_cm_sleepdep;
373	u32 cm_clkout_ctrl;
374};
375
376static struct omap3_cm_regs cm_context;
377
378void omap3_cm_save_context(void)
379{
380	cm_context.iva2_cm_clksel1 =
381		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL1);
382	cm_context.iva2_cm_clksel2 =
383		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSEL2);
384	cm_context.cm_sysconfig =
385		omap2_cm_read_mod_reg(OCP_MOD, OMAP3430_CM_SYSCONFIG);
386	cm_context.sgx_cm_clksel =
387		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSEL);
388	cm_context.dss_cm_clksel =
389		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSEL);
390	cm_context.cam_cm_clksel =
391		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_CLKSEL);
392	cm_context.per_cm_clksel =
393		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_CLKSEL);
394	cm_context.emu_cm_clksel =
395		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
396	cm_context.emu_cm_clkstctrl =
397		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
398	/*
399	 * As per erratum i671, ROM code does not respect the PER DPLL
400	 * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
401	 * In this case, even though this register has been saved in
402	 * scratchpad contents, we need to restore AUTO_PERIPH_DPLL
403	 * by ourselves. So, we need to save it anyway.
404	 */
405	cm_context.pll_cm_autoidle =
406		omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
407	cm_context.pll_cm_autoidle2 =
408		omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
409	cm_context.pll_cm_clksel4 =
410		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL4);
411	cm_context.pll_cm_clksel5 =
412		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKSEL5);
413	cm_context.pll_cm_clken2 =
414		omap2_cm_read_mod_reg(PLL_MOD, OMAP3430ES2_CM_CLKEN2);
415	cm_context.cm_polctrl =
416		omap2_cm_read_mod_reg(OCP_MOD, OMAP3430_CM_POLCTRL);
417	cm_context.iva2_cm_fclken =
418		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN);
419	cm_context.iva2_cm_clken_pll =
420		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL);
421	cm_context.core_cm_fclken1 =
422		omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
423	cm_context.core_cm_fclken3 =
424		omap2_cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3);
425	cm_context.sgx_cm_fclken =
426		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_FCLKEN);
427	cm_context.wkup_cm_fclken =
428		omap2_cm_read_mod_reg(WKUP_MOD, CM_FCLKEN);
429	cm_context.dss_cm_fclken =
430		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_FCLKEN);
431	cm_context.cam_cm_fclken =
432		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_FCLKEN);
433	cm_context.per_cm_fclken =
434		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN);
435	cm_context.usbhost_cm_fclken =
436		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
437	cm_context.core_cm_iclken1 =
438		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN1);
439	cm_context.core_cm_iclken2 =
440		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN2);
441	cm_context.core_cm_iclken3 =
442		omap2_cm_read_mod_reg(CORE_MOD, CM_ICLKEN3);
443	cm_context.sgx_cm_iclken =
444		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_ICLKEN);
445	cm_context.wkup_cm_iclken =
446		omap2_cm_read_mod_reg(WKUP_MOD, CM_ICLKEN);
447	cm_context.dss_cm_iclken =
448		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_ICLKEN);
449	cm_context.cam_cm_iclken =
450		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_ICLKEN);
451	cm_context.per_cm_iclken =
452		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN);
453	cm_context.usbhost_cm_iclken =
454		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
455	cm_context.iva2_cm_autoidle2 =
456		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
457	cm_context.mpu_cm_autoidle2 =
458		omap2_cm_read_mod_reg(MPU_MOD, CM_AUTOIDLE2);
459	cm_context.iva2_cm_clkstctrl =
460		omap2_cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL);
461	cm_context.mpu_cm_clkstctrl =
462		omap2_cm_read_mod_reg(MPU_MOD, OMAP2_CM_CLKSTCTRL);
463	cm_context.core_cm_clkstctrl =
464		omap2_cm_read_mod_reg(CORE_MOD, OMAP2_CM_CLKSTCTRL);
465	cm_context.sgx_cm_clkstctrl =
466		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD, OMAP2_CM_CLKSTCTRL);
467	cm_context.dss_cm_clkstctrl =
468		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP2_CM_CLKSTCTRL);
469	cm_context.cam_cm_clkstctrl =
470		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP2_CM_CLKSTCTRL);
471	cm_context.per_cm_clkstctrl =
472		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP2_CM_CLKSTCTRL);
473	cm_context.neon_cm_clkstctrl =
474		omap2_cm_read_mod_reg(OMAP3430_NEON_MOD, OMAP2_CM_CLKSTCTRL);
475	cm_context.usbhost_cm_clkstctrl =
476		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
477				      OMAP2_CM_CLKSTCTRL);
478	cm_context.core_cm_autoidle1 =
479		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE1);
480	cm_context.core_cm_autoidle2 =
481		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE2);
482	cm_context.core_cm_autoidle3 =
483		omap2_cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE3);
484	cm_context.wkup_cm_autoidle =
485		omap2_cm_read_mod_reg(WKUP_MOD, CM_AUTOIDLE);
486	cm_context.dss_cm_autoidle =
487		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, CM_AUTOIDLE);
488	cm_context.cam_cm_autoidle =
489		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, CM_AUTOIDLE);
490	cm_context.per_cm_autoidle =
491		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
492	cm_context.usbhost_cm_autoidle =
493		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
494	cm_context.sgx_cm_sleepdep =
495		omap2_cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
496				      OMAP3430_CM_SLEEPDEP);
497	cm_context.dss_cm_sleepdep =
498		omap2_cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP3430_CM_SLEEPDEP);
499	cm_context.cam_cm_sleepdep =
500		omap2_cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP3430_CM_SLEEPDEP);
501	cm_context.per_cm_sleepdep =
502		omap2_cm_read_mod_reg(OMAP3430_PER_MOD, OMAP3430_CM_SLEEPDEP);
503	cm_context.usbhost_cm_sleepdep =
504		omap2_cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
505				      OMAP3430_CM_SLEEPDEP);
506	cm_context.cm_clkout_ctrl =
507		omap2_cm_read_mod_reg(OMAP3430_CCR_MOD,
508				      OMAP3_CM_CLKOUT_CTRL_OFFSET);
509}
510
511void omap3_cm_restore_context(void)
512{
513	omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel1, OMAP3430_IVA2_MOD,
514			       CM_CLKSEL1);
515	omap2_cm_write_mod_reg(cm_context.iva2_cm_clksel2, OMAP3430_IVA2_MOD,
516			       CM_CLKSEL2);
517	omap2_cm_write_mod_reg(cm_context.cm_sysconfig, OCP_MOD,
518			       OMAP3430_CM_SYSCONFIG);
519	omap2_cm_write_mod_reg(cm_context.sgx_cm_clksel, OMAP3430ES2_SGX_MOD,
520			       CM_CLKSEL);
521	omap2_cm_write_mod_reg(cm_context.dss_cm_clksel, OMAP3430_DSS_MOD,
522			       CM_CLKSEL);
523	omap2_cm_write_mod_reg(cm_context.cam_cm_clksel, OMAP3430_CAM_MOD,
524			       CM_CLKSEL);
525	omap2_cm_write_mod_reg(cm_context.per_cm_clksel, OMAP3430_PER_MOD,
526			       CM_CLKSEL);
527	omap2_cm_write_mod_reg(cm_context.emu_cm_clksel, OMAP3430_EMU_MOD,
528			       CM_CLKSEL1);
529	omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
530			       OMAP2_CM_CLKSTCTRL);
531	/*
532	 * As per erratum i671, ROM code does not respect the PER DPLL
533	 * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
534	 * In this case, we need to restore AUTO_PERIPH_DPLL by ourselves.
535	 */
536	omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle, PLL_MOD,
537			       CM_AUTOIDLE);
538	omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD,
539			       CM_AUTOIDLE2);
540	omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD,
541			       OMAP3430ES2_CM_CLKSEL4);
542	omap2_cm_write_mod_reg(cm_context.pll_cm_clksel5, PLL_MOD,
543			       OMAP3430ES2_CM_CLKSEL5);
544	omap2_cm_write_mod_reg(cm_context.pll_cm_clken2, PLL_MOD,
545			       OMAP3430ES2_CM_CLKEN2);
546	omap2_cm_write_mod_reg(cm_context.cm_polctrl, OCP_MOD,
547			       OMAP3430_CM_POLCTRL);
548	omap2_cm_write_mod_reg(cm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD,
549			       CM_FCLKEN);
550	omap2_cm_write_mod_reg(cm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD,
551			       OMAP3430_CM_CLKEN_PLL);
552	omap2_cm_write_mod_reg(cm_context.core_cm_fclken1, CORE_MOD,
553			       CM_FCLKEN1);
554	omap2_cm_write_mod_reg(cm_context.core_cm_fclken3, CORE_MOD,
555			       OMAP3430ES2_CM_FCLKEN3);
556	omap2_cm_write_mod_reg(cm_context.sgx_cm_fclken, OMAP3430ES2_SGX_MOD,
557			       CM_FCLKEN);
558	omap2_cm_write_mod_reg(cm_context.wkup_cm_fclken, WKUP_MOD, CM_FCLKEN);
559	omap2_cm_write_mod_reg(cm_context.dss_cm_fclken, OMAP3430_DSS_MOD,
560			       CM_FCLKEN);
561	omap2_cm_write_mod_reg(cm_context.cam_cm_fclken, OMAP3430_CAM_MOD,
562			       CM_FCLKEN);
563	omap2_cm_write_mod_reg(cm_context.per_cm_fclken, OMAP3430_PER_MOD,
564			       CM_FCLKEN);
565	omap2_cm_write_mod_reg(cm_context.usbhost_cm_fclken,
566			       OMAP3430ES2_USBHOST_MOD, CM_FCLKEN);
567	omap2_cm_write_mod_reg(cm_context.core_cm_iclken1, CORE_MOD,
568			       CM_ICLKEN1);
569	omap2_cm_write_mod_reg(cm_context.core_cm_iclken2, CORE_MOD,
570			       CM_ICLKEN2);
571	omap2_cm_write_mod_reg(cm_context.core_cm_iclken3, CORE_MOD,
572			       CM_ICLKEN3);
573	omap2_cm_write_mod_reg(cm_context.sgx_cm_iclken, OMAP3430ES2_SGX_MOD,
574			       CM_ICLKEN);
575	omap2_cm_write_mod_reg(cm_context.wkup_cm_iclken, WKUP_MOD, CM_ICLKEN);
576	omap2_cm_write_mod_reg(cm_context.dss_cm_iclken, OMAP3430_DSS_MOD,
577			       CM_ICLKEN);
578	omap2_cm_write_mod_reg(cm_context.cam_cm_iclken, OMAP3430_CAM_MOD,
579			       CM_ICLKEN);
580	omap2_cm_write_mod_reg(cm_context.per_cm_iclken, OMAP3430_PER_MOD,
581			       CM_ICLKEN);
582	omap2_cm_write_mod_reg(cm_context.usbhost_cm_iclken,
583			       OMAP3430ES2_USBHOST_MOD, CM_ICLKEN);
584	omap2_cm_write_mod_reg(cm_context.iva2_cm_autoidle2, OMAP3430_IVA2_MOD,
585			       CM_AUTOIDLE2);
586	omap2_cm_write_mod_reg(cm_context.mpu_cm_autoidle2, MPU_MOD,
587			       CM_AUTOIDLE2);
588	omap2_cm_write_mod_reg(cm_context.iva2_cm_clkstctrl, OMAP3430_IVA2_MOD,
589			       OMAP2_CM_CLKSTCTRL);
590	omap2_cm_write_mod_reg(cm_context.mpu_cm_clkstctrl, MPU_MOD,
591			       OMAP2_CM_CLKSTCTRL);
592	omap2_cm_write_mod_reg(cm_context.core_cm_clkstctrl, CORE_MOD,
593			       OMAP2_CM_CLKSTCTRL);
594	omap2_cm_write_mod_reg(cm_context.sgx_cm_clkstctrl, OMAP3430ES2_SGX_MOD,
595			       OMAP2_CM_CLKSTCTRL);
596	omap2_cm_write_mod_reg(cm_context.dss_cm_clkstctrl, OMAP3430_DSS_MOD,
597			       OMAP2_CM_CLKSTCTRL);
598	omap2_cm_write_mod_reg(cm_context.cam_cm_clkstctrl, OMAP3430_CAM_MOD,
599			       OMAP2_CM_CLKSTCTRL);
600	omap2_cm_write_mod_reg(cm_context.per_cm_clkstctrl, OMAP3430_PER_MOD,
601			       OMAP2_CM_CLKSTCTRL);
602	omap2_cm_write_mod_reg(cm_context.neon_cm_clkstctrl, OMAP3430_NEON_MOD,
603			       OMAP2_CM_CLKSTCTRL);
604	omap2_cm_write_mod_reg(cm_context.usbhost_cm_clkstctrl,
605			       OMAP3430ES2_USBHOST_MOD, OMAP2_CM_CLKSTCTRL);
606	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle1, CORE_MOD,
607			       CM_AUTOIDLE1);
608	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle2, CORE_MOD,
609			       CM_AUTOIDLE2);
610	omap2_cm_write_mod_reg(cm_context.core_cm_autoidle3, CORE_MOD,
611			       CM_AUTOIDLE3);
612	omap2_cm_write_mod_reg(cm_context.wkup_cm_autoidle, WKUP_MOD,
613			       CM_AUTOIDLE);
614	omap2_cm_write_mod_reg(cm_context.dss_cm_autoidle, OMAP3430_DSS_MOD,
615			       CM_AUTOIDLE);
616	omap2_cm_write_mod_reg(cm_context.cam_cm_autoidle, OMAP3430_CAM_MOD,
617			       CM_AUTOIDLE);
618	omap2_cm_write_mod_reg(cm_context.per_cm_autoidle, OMAP3430_PER_MOD,
619			       CM_AUTOIDLE);
620	omap2_cm_write_mod_reg(cm_context.usbhost_cm_autoidle,
621			       OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE);
622	omap2_cm_write_mod_reg(cm_context.sgx_cm_sleepdep, OMAP3430ES2_SGX_MOD,
623			       OMAP3430_CM_SLEEPDEP);
624	omap2_cm_write_mod_reg(cm_context.dss_cm_sleepdep, OMAP3430_DSS_MOD,
625			       OMAP3430_CM_SLEEPDEP);
626	omap2_cm_write_mod_reg(cm_context.cam_cm_sleepdep, OMAP3430_CAM_MOD,
627			       OMAP3430_CM_SLEEPDEP);
628	omap2_cm_write_mod_reg(cm_context.per_cm_sleepdep, OMAP3430_PER_MOD,
629			       OMAP3430_CM_SLEEPDEP);
630	omap2_cm_write_mod_reg(cm_context.usbhost_cm_sleepdep,
631			       OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP);
632	omap2_cm_write_mod_reg(cm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
633			       OMAP3_CM_CLKOUT_CTRL_OFFSET);
634}
635
636void omap3_cm_save_scratchpad_contents(u32 *ptr)
637{
638	*ptr++ = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL);
639	*ptr++ = omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
640	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
641
642	/*
643	 * As per erratum i671, ROM code does not respect the PER DPLL
644	 * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
645	 * Then,  in any case, clear these bits to avoid extra latencies.
646	 */
647	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
648		~OMAP3430_AUTO_PERIPH_DPLL_MASK;
649	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
650	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL2_PLL);
651	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL3);
652	*ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKEN_PLL);
653	*ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL);
654	*ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL);
655	*ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL);
656}
657
658/*
659 *
660 */
661
662static const struct cm_ll_data omap3xxx_cm_ll_data = {
663	.split_idlest_reg	= &omap3xxx_cm_split_idlest_reg,
664	.wait_module_ready	= &omap3xxx_cm_wait_module_ready,
665};
666
667int __init omap3xxx_cm_init(const struct omap_prcm_init_data *data)
668{
669	omap2_clk_legacy_provider_init(TI_CLKM_CM, cm_base.va +
670				       OMAP3430_IVA2_MOD);
671	return cm_register(&omap3xxx_cm_ll_data);
672}
673
674static void __exit omap3xxx_cm_exit(void)
675{
676	cm_unregister(&omap3xxx_cm_ll_data);
677}
678__exitcall(omap3xxx_cm_exit);
679