Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arm/mach-omap2/cm3xxx.c
26292 views
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 <[email protected]>
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
24
static const u8 omap3xxx_cm_idlest_offs[] = {
25
CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
26
};
27
28
/*
29
*
30
*/
31
32
static 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
42
static 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
53
static void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
54
{
55
_write_clktrctrl(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
56
}
57
58
static void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
59
{
60
_write_clktrctrl(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
61
}
62
63
static void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask)
64
{
65
_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, module, mask);
66
}
67
68
static 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
*/
88
static 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
*/
118
static 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
146
static 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
155
static 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
164
static 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
172
static 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
189
static 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
196
static 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
203
static 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
212
static 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
221
static 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
257
static 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
294
struct 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
*/
314
struct 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
376
static struct omap3_cm_regs cm_context;
377
378
void 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
511
void 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
636
void 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
662
static 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
667
int __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
674
static void __exit omap3xxx_cm_exit(void)
675
{
676
cm_unregister(&omap3xxx_cm_ll_data);
677
}
678
__exitcall(omap3xxx_cm_exit);
679
680