1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * OMAP4 CM instance functions |
4 | * |
5 | * Copyright (C) 2009 Nokia Corporation |
6 | * Copyright (C) 2008-2011 Texas Instruments, Inc. |
7 | * Paul Walmsley |
8 | * Rajendra Nayak <rnayak@ti.com> |
9 | * |
10 | * This is needed since CM instances can be in the PRM, PRCM_MPU, CM1, |
11 | * or CM2 hardware modules. For example, the EMU_CM CM instance is in |
12 | * the PRM hardware module. What a mess... |
13 | */ |
14 | |
15 | #include <linux/kernel.h> |
16 | #include <linux/types.h> |
17 | #include <linux/errno.h> |
18 | #include <linux/err.h> |
19 | #include <linux/io.h> |
20 | |
21 | #include "clockdomain.h" |
22 | #include "cm.h" |
23 | #include "cm1_44xx.h" |
24 | #include "cm2_44xx.h" |
25 | #include "cm44xx.h" |
26 | #include "cm-regbits-34xx.h" |
27 | #include "prcm44xx.h" |
28 | #include "prm44xx.h" |
29 | #include "prcm_mpu44xx.h" |
30 | #include "prcm-common.h" |
31 | |
32 | #define OMAP4430_IDLEST_SHIFT 16 |
33 | #define OMAP4430_IDLEST_MASK (0x3 << 16) |
34 | #define OMAP4430_CLKTRCTRL_SHIFT 0 |
35 | #define OMAP4430_CLKTRCTRL_MASK (0x3 << 0) |
36 | #define OMAP4430_MODULEMODE_SHIFT 0 |
37 | #define OMAP4430_MODULEMODE_MASK (0x3 << 0) |
38 | |
39 | /* |
40 | * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield: |
41 | * |
42 | * 0x0 func: Module is fully functional, including OCP |
43 | * 0x1 trans: Module is performing transition: wakeup, or sleep, or sleep |
44 | * abortion |
45 | * 0x2 idle: Module is in Idle mode (only OCP part). It is functional if |
46 | * using separate functional clock |
47 | * 0x3 disabled: Module is disabled and cannot be accessed |
48 | * |
49 | */ |
50 | #define CLKCTRL_IDLEST_FUNCTIONAL 0x0 |
51 | #define CLKCTRL_IDLEST_INTRANSITION 0x1 |
52 | #define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2 |
53 | #define CLKCTRL_IDLEST_DISABLED 0x3 |
54 | |
55 | static struct omap_domain_base _cm_bases[OMAP4_MAX_PRCM_PARTITIONS]; |
56 | |
57 | /** |
58 | * omap_cm_base_init - Populates the cm partitions |
59 | * |
60 | * Populates the base addresses of the _cm_bases |
61 | * array used for read/write of cm module registers. |
62 | */ |
63 | static void omap_cm_base_init(void) |
64 | { |
65 | memcpy(&_cm_bases[OMAP4430_PRM_PARTITION], &prm_base, sizeof(prm_base)); |
66 | memcpy(&_cm_bases[OMAP4430_CM1_PARTITION], &cm_base, sizeof(cm_base)); |
67 | memcpy(&_cm_bases[OMAP4430_CM2_PARTITION], &cm2_base, sizeof(cm2_base)); |
68 | memcpy(&_cm_bases[OMAP4430_PRCM_MPU_PARTITION], &prcm_mpu_base, |
69 | sizeof(prcm_mpu_base)); |
70 | } |
71 | |
72 | /* Private functions */ |
73 | |
74 | static u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx); |
75 | |
76 | /** |
77 | * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield |
78 | * @part: PRCM partition ID that the CM_CLKCTRL register exists in |
79 | * @inst: CM instance register offset (*_INST macro) |
80 | * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) |
81 | * |
82 | * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to |
83 | * bit 0. |
84 | */ |
85 | static u32 _clkctrl_idlest(u8 part, u16 inst, u16 clkctrl_offs) |
86 | { |
87 | u32 v = omap4_cminst_read_inst_reg(part, inst, idx: clkctrl_offs); |
88 | v &= OMAP4430_IDLEST_MASK; |
89 | v >>= OMAP4430_IDLEST_SHIFT; |
90 | return v; |
91 | } |
92 | |
93 | /** |
94 | * _is_module_ready - can module registers be accessed without causing an abort? |
95 | * @part: PRCM partition ID that the CM_CLKCTRL register exists in |
96 | * @inst: CM instance register offset (*_INST macro) |
97 | * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) |
98 | * |
99 | * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either |
100 | * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise. |
101 | */ |
102 | static bool _is_module_ready(u8 part, u16 inst, u16 clkctrl_offs) |
103 | { |
104 | u32 v; |
105 | |
106 | v = _clkctrl_idlest(part, inst, clkctrl_offs); |
107 | |
108 | return (v == CLKCTRL_IDLEST_FUNCTIONAL || |
109 | v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false; |
110 | } |
111 | |
112 | /* Read a register in a CM instance */ |
113 | static u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx) |
114 | { |
115 | BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS || |
116 | part == OMAP4430_INVALID_PRCM_PARTITION || |
117 | !_cm_bases[part].va); |
118 | return readl_relaxed(_cm_bases[part].va + inst + idx); |
119 | } |
120 | |
121 | /* Write into a register in a CM instance */ |
122 | static void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx) |
123 | { |
124 | BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS || |
125 | part == OMAP4430_INVALID_PRCM_PARTITION || |
126 | !_cm_bases[part].va); |
127 | writel_relaxed(val, _cm_bases[part].va + inst + idx); |
128 | } |
129 | |
130 | /* Read-modify-write a register in CM1. Caller must lock */ |
131 | static u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, u16 inst, |
132 | s16 idx) |
133 | { |
134 | u32 v; |
135 | |
136 | v = omap4_cminst_read_inst_reg(part, inst, idx); |
137 | v &= ~mask; |
138 | v |= bits; |
139 | omap4_cminst_write_inst_reg(val: v, part, inst, idx); |
140 | |
141 | return v; |
142 | } |
143 | |
144 | static u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, u16 inst, s16 idx) |
145 | { |
146 | return omap4_cminst_rmw_inst_reg_bits(mask: bits, bits, part, inst, idx); |
147 | } |
148 | |
149 | static u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, u16 inst, |
150 | s16 idx) |
151 | { |
152 | return omap4_cminst_rmw_inst_reg_bits(mask: bits, bits: 0x0, part, inst, idx); |
153 | } |
154 | |
155 | static u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx, u32 mask) |
156 | { |
157 | u32 v; |
158 | |
159 | v = omap4_cminst_read_inst_reg(part, inst, idx); |
160 | v &= mask; |
161 | v >>= __ffs(mask); |
162 | |
163 | return v; |
164 | } |
165 | |
166 | /* |
167 | * |
168 | */ |
169 | |
170 | /** |
171 | * _clktrctrl_write - write @c to a CM_CLKSTCTRL.CLKTRCTRL register bitfield |
172 | * @c: CLKTRCTRL register bitfield (LSB = bit 0, i.e., unshifted) |
173 | * @part: PRCM partition ID that the CM_CLKSTCTRL register exists in |
174 | * @inst: CM instance register offset (*_INST macro) |
175 | * @cdoffs: Clockdomain register offset (*_CDOFFS macro) |
176 | * |
177 | * @c must be the unshifted value for CLKTRCTRL - i.e., this function |
178 | * will handle the shift itself. |
179 | */ |
180 | static void _clktrctrl_write(u8 c, u8 part, u16 inst, u16 cdoffs) |
181 | { |
182 | u32 v; |
183 | |
184 | v = omap4_cminst_read_inst_reg(part, inst, idx: cdoffs + OMAP4_CM_CLKSTCTRL); |
185 | v &= ~OMAP4430_CLKTRCTRL_MASK; |
186 | v |= c << OMAP4430_CLKTRCTRL_SHIFT; |
187 | omap4_cminst_write_inst_reg(val: v, part, inst, idx: cdoffs + OMAP4_CM_CLKSTCTRL); |
188 | } |
189 | |
190 | /** |
191 | * omap4_cminst_is_clkdm_in_hwsup - is a clockdomain in hwsup idle mode? |
192 | * @part: PRCM partition ID that the CM_CLKSTCTRL register exists in |
193 | * @inst: CM instance register offset (*_INST macro) |
194 | * @cdoffs: Clockdomain register offset (*_CDOFFS macro) |
195 | * |
196 | * Returns true if the clockdomain referred to by (@part, @inst, @cdoffs) |
197 | * is in hardware-supervised idle mode, or 0 otherwise. |
198 | */ |
199 | static bool omap4_cminst_is_clkdm_in_hwsup(u8 part, u16 inst, u16 cdoffs) |
200 | { |
201 | u32 v; |
202 | |
203 | v = omap4_cminst_read_inst_reg(part, inst, idx: cdoffs + OMAP4_CM_CLKSTCTRL); |
204 | v &= OMAP4430_CLKTRCTRL_MASK; |
205 | v >>= OMAP4430_CLKTRCTRL_SHIFT; |
206 | |
207 | return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? true : false; |
208 | } |
209 | |
210 | /** |
211 | * omap4_cminst_clkdm_enable_hwsup - put a clockdomain in hwsup-idle mode |
212 | * @part: PRCM partition ID that the clockdomain registers exist in |
213 | * @inst: CM instance register offset (*_INST macro) |
214 | * @cdoffs: Clockdomain register offset (*_CDOFFS macro) |
215 | * |
216 | * Put a clockdomain referred to by (@part, @inst, @cdoffs) into |
217 | * hardware-supervised idle mode. No return value. |
218 | */ |
219 | static void omap4_cminst_clkdm_enable_hwsup(u8 part, u16 inst, u16 cdoffs) |
220 | { |
221 | _clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, part, inst, cdoffs); |
222 | } |
223 | |
224 | /** |
225 | * omap4_cminst_clkdm_disable_hwsup - put a clockdomain in swsup-idle mode |
226 | * @part: PRCM partition ID that the clockdomain registers exist in |
227 | * @inst: CM instance register offset (*_INST macro) |
228 | * @cdoffs: Clockdomain register offset (*_CDOFFS macro) |
229 | * |
230 | * Put a clockdomain referred to by (@part, @inst, @cdoffs) into |
231 | * software-supervised idle mode, i.e., controlled manually by the |
232 | * Linux OMAP clockdomain code. No return value. |
233 | */ |
234 | static void omap4_cminst_clkdm_disable_hwsup(u8 part, u16 inst, u16 cdoffs) |
235 | { |
236 | _clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, part, inst, cdoffs); |
237 | } |
238 | |
239 | /** |
240 | * omap4_cminst_clkdm_force_sleep - try to take a clockdomain out of idle |
241 | * @part: PRCM partition ID that the clockdomain registers exist in |
242 | * @inst: CM instance register offset (*_INST macro) |
243 | * @cdoffs: Clockdomain register offset (*_CDOFFS macro) |
244 | * |
245 | * Take a clockdomain referred to by (@part, @inst, @cdoffs) out of idle, |
246 | * waking it up. No return value. |
247 | */ |
248 | static void omap4_cminst_clkdm_force_wakeup(u8 part, u16 inst, u16 cdoffs) |
249 | { |
250 | _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, part, inst, cdoffs); |
251 | } |
252 | |
253 | /* |
254 | * |
255 | */ |
256 | |
257 | static void omap4_cminst_clkdm_force_sleep(u8 part, u16 inst, u16 cdoffs) |
258 | { |
259 | _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, part, inst, cdoffs); |
260 | } |
261 | |
262 | /** |
263 | * omap4_cminst_wait_module_ready - wait for a module to be in 'func' state |
264 | * @part: PRCM partition ID that the CM_CLKCTRL register exists in |
265 | * @inst: CM instance register offset (*_INST macro) |
266 | * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) |
267 | * @bit_shift: bit shift for the register, ignored for OMAP4+ |
268 | * |
269 | * Wait for the module IDLEST to be functional. If the idle state is in any |
270 | * the non functional state (trans, idle or disabled), module and thus the |
271 | * sysconfig cannot be accessed and will probably lead to an "imprecise |
272 | * external abort" |
273 | */ |
274 | static int omap4_cminst_wait_module_ready(u8 part, s16 inst, u16 clkctrl_offs, |
275 | u8 bit_shift) |
276 | { |
277 | int i = 0; |
278 | |
279 | omap_test_timeout(_is_module_ready(part, inst, clkctrl_offs), |
280 | MAX_MODULE_READY_TIME, i); |
281 | |
282 | return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; |
283 | } |
284 | |
285 | /** |
286 | * omap4_cminst_wait_module_idle - wait for a module to be in 'disabled' |
287 | * state |
288 | * @part: PRCM partition ID that the CM_CLKCTRL register exists in |
289 | * @inst: CM instance register offset (*_INST macro) |
290 | * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) |
291 | * @bit_shift: Bit shift for the register, ignored for OMAP4+ |
292 | * |
293 | * Wait for the module IDLEST to be disabled. Some PRCM transition, |
294 | * like reset assertion or parent clock de-activation must wait the |
295 | * module to be fully disabled. |
296 | */ |
297 | static int omap4_cminst_wait_module_idle(u8 part, s16 inst, u16 clkctrl_offs, |
298 | u8 bit_shift) |
299 | { |
300 | int i = 0; |
301 | |
302 | omap_test_timeout((_clkctrl_idlest(part, inst, clkctrl_offs) == |
303 | CLKCTRL_IDLEST_DISABLED), |
304 | MAX_MODULE_DISABLE_TIME, i); |
305 | |
306 | return (i < MAX_MODULE_DISABLE_TIME) ? 0 : -EBUSY; |
307 | } |
308 | |
309 | /** |
310 | * omap4_cminst_module_enable - Enable the modulemode inside CLKCTRL |
311 | * @mode: Module mode (SW or HW) |
312 | * @part: PRCM partition ID that the CM_CLKCTRL register exists in |
313 | * @inst: CM instance register offset (*_INST macro) |
314 | * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) |
315 | * |
316 | * No return value. |
317 | */ |
318 | static void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, |
319 | u16 clkctrl_offs) |
320 | { |
321 | u32 v; |
322 | |
323 | v = omap4_cminst_read_inst_reg(part, inst, idx: clkctrl_offs); |
324 | v &= ~OMAP4430_MODULEMODE_MASK; |
325 | v |= mode << OMAP4430_MODULEMODE_SHIFT; |
326 | omap4_cminst_write_inst_reg(val: v, part, inst, idx: clkctrl_offs); |
327 | } |
328 | |
329 | /** |
330 | * omap4_cminst_module_disable - Disable the module inside CLKCTRL |
331 | * @part: PRCM partition ID that the CM_CLKCTRL register exists in |
332 | * @inst: CM instance register offset (*_INST macro) |
333 | * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) |
334 | * |
335 | * No return value. |
336 | */ |
337 | static void omap4_cminst_module_disable(u8 part, u16 inst, u16 clkctrl_offs) |
338 | { |
339 | u32 v; |
340 | |
341 | v = omap4_cminst_read_inst_reg(part, inst, idx: clkctrl_offs); |
342 | v &= ~OMAP4430_MODULEMODE_MASK; |
343 | omap4_cminst_write_inst_reg(val: v, part, inst, idx: clkctrl_offs); |
344 | } |
345 | |
346 | /* |
347 | * Clockdomain low-level functions |
348 | */ |
349 | |
350 | static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1, |
351 | struct clockdomain *clkdm2) |
352 | { |
353 | omap4_cminst_set_inst_reg_bits(bits: (1 << clkdm2->dep_bit), |
354 | part: clkdm1->prcm_partition, |
355 | inst: clkdm1->cm_inst, idx: clkdm1->clkdm_offs + |
356 | OMAP4_CM_STATICDEP); |
357 | return 0; |
358 | } |
359 | |
360 | static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1, |
361 | struct clockdomain *clkdm2) |
362 | { |
363 | omap4_cminst_clear_inst_reg_bits(bits: (1 << clkdm2->dep_bit), |
364 | part: clkdm1->prcm_partition, |
365 | inst: clkdm1->cm_inst, idx: clkdm1->clkdm_offs + |
366 | OMAP4_CM_STATICDEP); |
367 | return 0; |
368 | } |
369 | |
370 | static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1, |
371 | struct clockdomain *clkdm2) |
372 | { |
373 | return omap4_cminst_read_inst_reg_bits(part: clkdm1->prcm_partition, |
374 | inst: clkdm1->cm_inst, |
375 | idx: clkdm1->clkdm_offs + |
376 | OMAP4_CM_STATICDEP, |
377 | mask: (1 << clkdm2->dep_bit)); |
378 | } |
379 | |
380 | static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm) |
381 | { |
382 | struct clkdm_dep *cd; |
383 | u32 mask = 0; |
384 | |
385 | if (!clkdm->prcm_partition) |
386 | return 0; |
387 | |
388 | for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { |
389 | if (!cd->clkdm) |
390 | continue; /* only happens if data is erroneous */ |
391 | |
392 | mask |= 1 << cd->clkdm->dep_bit; |
393 | cd->wkdep_usecount = 0; |
394 | } |
395 | |
396 | omap4_cminst_clear_inst_reg_bits(bits: mask, part: clkdm->prcm_partition, |
397 | inst: clkdm->cm_inst, idx: clkdm->clkdm_offs + |
398 | OMAP4_CM_STATICDEP); |
399 | return 0; |
400 | } |
401 | |
402 | static int omap4_clkdm_sleep(struct clockdomain *clkdm) |
403 | { |
404 | if (clkdm->flags & CLKDM_CAN_HWSUP) |
405 | omap4_cminst_clkdm_enable_hwsup(part: clkdm->prcm_partition, |
406 | inst: clkdm->cm_inst, |
407 | cdoffs: clkdm->clkdm_offs); |
408 | else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP) |
409 | omap4_cminst_clkdm_force_sleep(part: clkdm->prcm_partition, |
410 | inst: clkdm->cm_inst, |
411 | cdoffs: clkdm->clkdm_offs); |
412 | else |
413 | return -EINVAL; |
414 | |
415 | return 0; |
416 | } |
417 | |
418 | static int omap4_clkdm_wakeup(struct clockdomain *clkdm) |
419 | { |
420 | omap4_cminst_clkdm_force_wakeup(part: clkdm->prcm_partition, |
421 | inst: clkdm->cm_inst, cdoffs: clkdm->clkdm_offs); |
422 | return 0; |
423 | } |
424 | |
425 | static void omap4_clkdm_allow_idle(struct clockdomain *clkdm) |
426 | { |
427 | omap4_cminst_clkdm_enable_hwsup(part: clkdm->prcm_partition, |
428 | inst: clkdm->cm_inst, cdoffs: clkdm->clkdm_offs); |
429 | } |
430 | |
431 | static void omap4_clkdm_deny_idle(struct clockdomain *clkdm) |
432 | { |
433 | if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) |
434 | omap4_clkdm_wakeup(clkdm); |
435 | else |
436 | omap4_cminst_clkdm_disable_hwsup(part: clkdm->prcm_partition, |
437 | inst: clkdm->cm_inst, |
438 | cdoffs: clkdm->clkdm_offs); |
439 | } |
440 | |
441 | static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) |
442 | { |
443 | if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) |
444 | return omap4_clkdm_wakeup(clkdm); |
445 | |
446 | return 0; |
447 | } |
448 | |
449 | static int omap4_clkdm_clk_disable(struct clockdomain *clkdm) |
450 | { |
451 | bool hwsup = false; |
452 | |
453 | if (!clkdm->prcm_partition) |
454 | return 0; |
455 | |
456 | /* |
457 | * The CLKDM_MISSING_IDLE_REPORTING flag documentation has |
458 | * more details on the unpleasant problem this is working |
459 | * around |
460 | */ |
461 | if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING && |
462 | !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) { |
463 | omap4_clkdm_allow_idle(clkdm); |
464 | return 0; |
465 | } |
466 | |
467 | hwsup = omap4_cminst_is_clkdm_in_hwsup(part: clkdm->prcm_partition, |
468 | inst: clkdm->cm_inst, cdoffs: clkdm->clkdm_offs); |
469 | |
470 | if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) |
471 | omap4_clkdm_sleep(clkdm); |
472 | |
473 | return 0; |
474 | } |
475 | |
476 | static u32 omap4_cminst_xlate_clkctrl(u8 part, u16 inst, u16 offset) |
477 | { |
478 | return _cm_bases[part].pa + inst + offset; |
479 | } |
480 | |
481 | /** |
482 | * omap4_clkdm_save_context - Save the clockdomain modulemode context |
483 | * @clkdm: The clockdomain pointer whose context needs to be saved |
484 | * |
485 | * Save the clockdomain modulemode context. |
486 | */ |
487 | static int omap4_clkdm_save_context(struct clockdomain *clkdm) |
488 | { |
489 | clkdm->context = omap4_cminst_read_inst_reg(part: clkdm->prcm_partition, |
490 | inst: clkdm->cm_inst, |
491 | idx: clkdm->clkdm_offs + |
492 | OMAP4_CM_CLKSTCTRL); |
493 | clkdm->context &= OMAP4430_MODULEMODE_MASK; |
494 | return 0; |
495 | } |
496 | |
497 | /** |
498 | * omap4_clkdm_restore_context - Restore the clockdomain modulemode context |
499 | * @clkdm: The clockdomain pointer whose context needs to be restored |
500 | * |
501 | * Restore the clockdomain modulemode context. |
502 | */ |
503 | static int omap4_clkdm_restore_context(struct clockdomain *clkdm) |
504 | { |
505 | switch (clkdm->context) { |
506 | case OMAP34XX_CLKSTCTRL_DISABLE_AUTO: |
507 | omap4_clkdm_deny_idle(clkdm); |
508 | break; |
509 | case OMAP34XX_CLKSTCTRL_FORCE_SLEEP: |
510 | omap4_clkdm_sleep(clkdm); |
511 | break; |
512 | case OMAP34XX_CLKSTCTRL_FORCE_WAKEUP: |
513 | omap4_clkdm_wakeup(clkdm); |
514 | break; |
515 | case OMAP34XX_CLKSTCTRL_ENABLE_AUTO: |
516 | omap4_clkdm_allow_idle(clkdm); |
517 | break; |
518 | } |
519 | return 0; |
520 | } |
521 | |
522 | struct clkdm_ops omap4_clkdm_operations = { |
523 | .clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep, |
524 | .clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep, |
525 | .clkdm_read_wkdep = omap4_clkdm_read_wkup_sleep_dep, |
526 | .clkdm_clear_all_wkdeps = omap4_clkdm_clear_all_wkup_sleep_deps, |
527 | .clkdm_add_sleepdep = omap4_clkdm_add_wkup_sleep_dep, |
528 | .clkdm_del_sleepdep = omap4_clkdm_del_wkup_sleep_dep, |
529 | .clkdm_read_sleepdep = omap4_clkdm_read_wkup_sleep_dep, |
530 | .clkdm_clear_all_sleepdeps = omap4_clkdm_clear_all_wkup_sleep_deps, |
531 | .clkdm_sleep = omap4_clkdm_sleep, |
532 | .clkdm_wakeup = omap4_clkdm_wakeup, |
533 | .clkdm_allow_idle = omap4_clkdm_allow_idle, |
534 | .clkdm_deny_idle = omap4_clkdm_deny_idle, |
535 | .clkdm_clk_enable = omap4_clkdm_clk_enable, |
536 | .clkdm_clk_disable = omap4_clkdm_clk_disable, |
537 | .clkdm_save_context = omap4_clkdm_save_context, |
538 | .clkdm_restore_context = omap4_clkdm_restore_context, |
539 | }; |
540 | |
541 | struct clkdm_ops am43xx_clkdm_operations = { |
542 | .clkdm_sleep = omap4_clkdm_sleep, |
543 | .clkdm_wakeup = omap4_clkdm_wakeup, |
544 | .clkdm_allow_idle = omap4_clkdm_allow_idle, |
545 | .clkdm_deny_idle = omap4_clkdm_deny_idle, |
546 | .clkdm_clk_enable = omap4_clkdm_clk_enable, |
547 | .clkdm_clk_disable = omap4_clkdm_clk_disable, |
548 | }; |
549 | |
550 | static const struct cm_ll_data omap4xxx_cm_ll_data = { |
551 | .wait_module_ready = &omap4_cminst_wait_module_ready, |
552 | .wait_module_idle = &omap4_cminst_wait_module_idle, |
553 | .module_enable = &omap4_cminst_module_enable, |
554 | .module_disable = &omap4_cminst_module_disable, |
555 | .xlate_clkctrl = &omap4_cminst_xlate_clkctrl, |
556 | }; |
557 | |
558 | int __init omap4_cm_init(const struct omap_prcm_init_data *data) |
559 | { |
560 | omap_cm_base_init(); |
561 | |
562 | return cm_register(cld: &omap4xxx_cm_ll_data); |
563 | } |
564 | |
565 | static void __exit omap4_cm_exit(void) |
566 | { |
567 | cm_unregister(cld: &omap4xxx_cm_ll_data); |
568 | } |
569 | __exitcall(omap4_cm_exit); |
570 | |