diff options
Diffstat (limited to 'arch/arm/mach-omap2/cminst44xx.c')
-rw-r--r-- | arch/arm/mach-omap2/cminst44xx.c | 150 |
1 files changed, 133 insertions, 17 deletions
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index a482bfa0a954..eb2a472bbf46 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * OMAP4 CM instance functions | 2 | * OMAP4 CM instance functions |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Nokia Corporation | 4 | * Copyright (C) 2009 Nokia Corporation |
5 | * Copyright (C) 2011 Texas Instruments, Inc. | ||
5 | * Paul Walmsley | 6 | * Paul Walmsley |
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
@@ -32,6 +33,22 @@ | |||
32 | #include "prm44xx.h" | 33 | #include "prm44xx.h" |
33 | #include "prcm_mpu44xx.h" | 34 | #include "prcm_mpu44xx.h" |
34 | 35 | ||
36 | /* | ||
37 | * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield: | ||
38 | * | ||
39 | * 0x0 func: Module is fully functional, including OCP | ||
40 | * 0x1 trans: Module is performing transition: wakeup, or sleep, or sleep | ||
41 | * abortion | ||
42 | * 0x2 idle: Module is in Idle mode (only OCP part). It is functional if | ||
43 | * using separate functional clock | ||
44 | * 0x3 disabled: Module is disabled and cannot be accessed | ||
45 | * | ||
46 | */ | ||
47 | #define CLKCTRL_IDLEST_FUNCTIONAL 0x0 | ||
48 | #define CLKCTRL_IDLEST_INTRANSITION 0x1 | ||
49 | #define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2 | ||
50 | #define CLKCTRL_IDLEST_DISABLED 0x3 | ||
51 | |||
35 | static u32 _cm_bases[OMAP4_MAX_PRCM_PARTITIONS] = { | 52 | static u32 _cm_bases[OMAP4_MAX_PRCM_PARTITIONS] = { |
36 | [OMAP4430_INVALID_PRCM_PARTITION] = 0, | 53 | [OMAP4430_INVALID_PRCM_PARTITION] = 0, |
37 | [OMAP4430_PRM_PARTITION] = OMAP4430_PRM_BASE, | 54 | [OMAP4430_PRM_PARTITION] = OMAP4430_PRM_BASE, |
@@ -41,6 +58,48 @@ static u32 _cm_bases[OMAP4_MAX_PRCM_PARTITIONS] = { | |||
41 | [OMAP4430_PRCM_MPU_PARTITION] = OMAP4430_PRCM_MPU_BASE, | 58 | [OMAP4430_PRCM_MPU_PARTITION] = OMAP4430_PRCM_MPU_BASE, |
42 | }; | 59 | }; |
43 | 60 | ||
61 | /* Private functions */ | ||
62 | |||
63 | /** | ||
64 | * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield | ||
65 | * @part: PRCM partition ID that the CM_CLKCTRL register exists in | ||
66 | * @inst: CM instance register offset (*_INST macro) | ||
67 | * @cdoffs: Clockdomain register offset (*_CDOFFS macro) | ||
68 | * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) | ||
69 | * | ||
70 | * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to | ||
71 | * bit 0. | ||
72 | */ | ||
73 | static u32 _clkctrl_idlest(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs) | ||
74 | { | ||
75 | u32 v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs); | ||
76 | v &= OMAP4430_IDLEST_MASK; | ||
77 | v >>= OMAP4430_IDLEST_SHIFT; | ||
78 | return v; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * _is_module_ready - can module registers be accessed without causing an abort? | ||
83 | * @part: PRCM partition ID that the CM_CLKCTRL register exists in | ||
84 | * @inst: CM instance register offset (*_INST macro) | ||
85 | * @cdoffs: Clockdomain register offset (*_CDOFFS macro) | ||
86 | * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) | ||
87 | * | ||
88 | * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either | ||
89 | * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise. | ||
90 | */ | ||
91 | static bool _is_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs) | ||
92 | { | ||
93 | u32 v; | ||
94 | |||
95 | v = _clkctrl_idlest(part, inst, cdoffs, clkctrl_offs); | ||
96 | |||
97 | return (v == CLKCTRL_IDLEST_FUNCTIONAL || | ||
98 | v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false; | ||
99 | } | ||
100 | |||
101 | /* Public functions */ | ||
102 | |||
44 | /* Read a register in a CM instance */ | 103 | /* Read a register in a CM instance */ |
45 | u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx) | 104 | u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx) |
46 | { | 105 | { |
@@ -200,36 +259,93 @@ void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs) | |||
200 | */ | 259 | */ |
201 | 260 | ||
202 | /** | 261 | /** |
203 | * omap4_cm_wait_module_ready - wait for a module to be in 'func' state | 262 | * omap4_cminst_wait_module_ready - wait for a module to be in 'func' state |
204 | * @clkctrl_reg: CLKCTRL module address | 263 | * @part: PRCM partition ID that the CM_CLKCTRL register exists in |
264 | * @inst: CM instance register offset (*_INST macro) | ||
265 | * @cdoffs: Clockdomain register offset (*_CDOFFS macro) | ||
266 | * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) | ||
205 | * | 267 | * |
206 | * Wait for the module IDLEST to be functional. If the idle state is in any | 268 | * Wait for the module IDLEST to be functional. If the idle state is in any |
207 | * the non functional state (trans, idle or disabled), module and thus the | 269 | * the non functional state (trans, idle or disabled), module and thus the |
208 | * sysconfig cannot be accessed and will probably lead to an "imprecise | 270 | * sysconfig cannot be accessed and will probably lead to an "imprecise |
209 | * external abort" | 271 | * external abort" |
272 | */ | ||
273 | int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs, | ||
274 | u16 clkctrl_offs) | ||
275 | { | ||
276 | int i = 0; | ||
277 | |||
278 | if (!clkctrl_offs) | ||
279 | return 0; | ||
280 | |||
281 | omap_test_timeout(_is_module_ready(part, inst, cdoffs, clkctrl_offs), | ||
282 | MAX_MODULE_READY_TIME, i); | ||
283 | |||
284 | return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; | ||
285 | } | ||
286 | |||
287 | /** | ||
288 | * omap4_cminst_wait_module_idle - wait for a module to be in 'disabled' | ||
289 | * state | ||
290 | * @part: PRCM partition ID that the CM_CLKCTRL register exists in | ||
291 | * @inst: CM instance register offset (*_INST macro) | ||
292 | * @cdoffs: Clockdomain register offset (*_CDOFFS macro) | ||
293 | * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) | ||
210 | * | 294 | * |
211 | * Module idle state: | 295 | * Wait for the module IDLEST to be disabled. Some PRCM transition, |
212 | * 0x0 func: Module is fully functional, including OCP | 296 | * like reset assertion or parent clock de-activation must wait the |
213 | * 0x1 trans: Module is performing transition: wakeup, or sleep, or sleep | 297 | * module to be fully disabled. |
214 | * abortion | ||
215 | * 0x2 idle: Module is in Idle mode (only OCP part). It is functional if | ||
216 | * using separate functional clock | ||
217 | * 0x3 disabled: Module is disabled and cannot be accessed | ||
218 | * | ||
219 | */ | 298 | */ |
220 | int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg) | 299 | int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs) |
221 | { | 300 | { |
222 | int i = 0; | 301 | int i = 0; |
223 | 302 | ||
224 | if (!clkctrl_reg) | 303 | if (!clkctrl_offs) |
225 | return 0; | 304 | return 0; |
226 | 305 | ||
227 | omap_test_timeout(( | 306 | omap_test_timeout((_clkctrl_idlest(part, inst, cdoffs, clkctrl_offs) == |
228 | ((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) == 0) || | 307 | CLKCTRL_IDLEST_DISABLED), |
229 | (((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) >> | 308 | MAX_MODULE_READY_TIME, i); |
230 | OMAP4430_IDLEST_SHIFT) == 0x2)), | ||
231 | MAX_MODULE_READY_TIME, i); | ||
232 | 309 | ||
233 | return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; | 310 | return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; |
234 | } | 311 | } |
235 | 312 | ||
313 | /** | ||
314 | * omap4_cminst_module_enable - Enable the modulemode inside CLKCTRL | ||
315 | * @mode: Module mode (SW or HW) | ||
316 | * @part: PRCM partition ID that the CM_CLKCTRL register exists in | ||
317 | * @inst: CM instance register offset (*_INST macro) | ||
318 | * @cdoffs: Clockdomain register offset (*_CDOFFS macro) | ||
319 | * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) | ||
320 | * | ||
321 | * No return value. | ||
322 | */ | ||
323 | void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs, | ||
324 | u16 clkctrl_offs) | ||
325 | { | ||
326 | u32 v; | ||
327 | |||
328 | v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs); | ||
329 | v &= ~OMAP4430_MODULEMODE_MASK; | ||
330 | v |= mode << OMAP4430_MODULEMODE_SHIFT; | ||
331 | omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs); | ||
332 | } | ||
333 | |||
334 | /** | ||
335 | * omap4_cminst_module_disable - Disable the module inside CLKCTRL | ||
336 | * @part: PRCM partition ID that the CM_CLKCTRL register exists in | ||
337 | * @inst: CM instance register offset (*_INST macro) | ||
338 | * @cdoffs: Clockdomain register offset (*_CDOFFS macro) | ||
339 | * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro) | ||
340 | * | ||
341 | * No return value. | ||
342 | */ | ||
343 | void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs, | ||
344 | u16 clkctrl_offs) | ||
345 | { | ||
346 | u32 v; | ||
347 | |||
348 | v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs); | ||
349 | v &= ~OMAP4430_MODULEMODE_MASK; | ||
350 | omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs); | ||
351 | } | ||