Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cminst44xx.c
Go to the documentation of this file.
1 /*
2  * OMAP4 CM instance functions
3  *
4  * Copyright (C) 2009 Nokia Corporation
5  * Copyright (C) 2011 Texas Instruments, Inc.
6  * Paul Walmsley
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * This is needed since CM instances can be in the PRM, PRCM_MPU, CM1,
13  * or CM2 hardware modules. For example, the EMU_CM CM instance is in
14  * the PRM hardware module. What a mess...
15  */
16 
17 #include <linux/kernel.h>
18 #include <linux/types.h>
19 #include <linux/errno.h>
20 #include <linux/err.h>
21 #include <linux/io.h>
22 
23 #include "iomap.h"
24 #include "common.h"
25 #include "cm.h"
26 #include "cm1_44xx.h"
27 #include "cm2_44xx.h"
28 #include "cm44xx.h"
29 #include "cminst44xx.h"
30 #include "cm-regbits-34xx.h"
31 #include "cm-regbits-44xx.h"
32 #include "prcm44xx.h"
33 #include "prm44xx.h"
34 #include "prcm_mpu44xx.h"
35 #include "prcm-common.h"
36 
37 /*
38  * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield:
39  *
40  * 0x0 func: Module is fully functional, including OCP
41  * 0x1 trans: Module is performing transition: wakeup, or sleep, or sleep
42  * abortion
43  * 0x2 idle: Module is in Idle mode (only OCP part). It is functional if
44  * using separate functional clock
45  * 0x3 disabled: Module is disabled and cannot be accessed
46  *
47  */
48 #define CLKCTRL_IDLEST_FUNCTIONAL 0x0
49 #define CLKCTRL_IDLEST_INTRANSITION 0x1
50 #define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2
51 #define CLKCTRL_IDLEST_DISABLED 0x3
52 
53 static void __iomem *_cm_bases[OMAP4_MAX_PRCM_PARTITIONS];
54 
62 {
63  _cm_bases[OMAP4430_PRM_PARTITION] = prm_base;
64  _cm_bases[OMAP4430_CM1_PARTITION] = cm_base;
65  _cm_bases[OMAP4430_CM2_PARTITION] = cm2_base;
67 }
68 
69 /* Private functions */
70 
81 static u32 _clkctrl_idlest(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
82 {
83  u32 v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
86  return v;
87 }
88 
99 static bool _is_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
100 {
101  u32 v;
102 
103  v = _clkctrl_idlest(part, inst, cdoffs, clkctrl_offs);
104 
105  return (v == CLKCTRL_IDLEST_FUNCTIONAL ||
106  v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false;
107 }
108 
109 /* Public functions */
110 
111 /* Read a register in a CM instance */
113 {
116  !_cm_bases[part]);
117  return __raw_readl(_cm_bases[part] + inst + idx);
118 }
119 
120 /* Write into a register in a CM instance */
122 {
125  !_cm_bases[part]);
126  __raw_writel(val, _cm_bases[part] + inst + idx);
127 }
128 
129 /* Read-modify-write a register in CM1. Caller must lock */
131  s16 idx)
132 {
133  u32 v;
134 
135  v = omap4_cminst_read_inst_reg(part, inst, idx);
136  v &= ~mask;
137  v |= bits;
138  omap4_cminst_write_inst_reg(v, part, inst, idx);
139 
140  return v;
141 }
142 
144 {
145  return omap4_cminst_rmw_inst_reg_bits(bits, bits, part, inst, idx);
146 }
147 
149 {
150  return omap4_cminst_rmw_inst_reg_bits(bits, 0x0, part, inst, idx);
151 }
152 
154 {
155  u32 v;
156 
157  v = omap4_cminst_read_inst_reg(part, inst, idx);
158  v &= mask;
159  v >>= __ffs(mask);
160 
161  return v;
162 }
163 
164 /*
165  *
166  */
167 
178 static void _clktrctrl_write(u8 c, u8 part, s16 inst, u16 cdoffs)
179 {
180  u32 v;
181 
182  v = omap4_cminst_read_inst_reg(part, inst, cdoffs + OMAP4_CM_CLKSTCTRL);
184  v |= c << OMAP4430_CLKTRCTRL_SHIFT;
185  omap4_cminst_write_inst_reg(v, part, inst, cdoffs + OMAP4_CM_CLKSTCTRL);
186 }
187 
197 bool omap4_cminst_is_clkdm_in_hwsup(u8 part, s16 inst, u16 cdoffs)
198 {
199  u32 v;
200 
201  v = omap4_cminst_read_inst_reg(part, inst, cdoffs + OMAP4_CM_CLKSTCTRL);
204 
205  return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? true : false;
206 }
207 
217 void omap4_cminst_clkdm_enable_hwsup(u8 part, s16 inst, u16 cdoffs)
218 {
219  _clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, part, inst, cdoffs);
220 }
221 
232 void omap4_cminst_clkdm_disable_hwsup(u8 part, s16 inst, u16 cdoffs)
233 {
234  _clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, part, inst, cdoffs);
235 }
236 
246 void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs)
247 {
248  _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, part, inst, cdoffs);
249 }
250 
251 /*
252  *
253  */
254 
267 int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs,
268  u16 clkctrl_offs)
269 {
270  int i = 0;
271 
272  if (!clkctrl_offs)
273  return 0;
274 
275  omap_test_timeout(_is_module_ready(part, inst, cdoffs, clkctrl_offs),
277 
278  return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
279 }
280 
293 int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
294 {
295  int i = 0;
296 
297  if (!clkctrl_offs)
298  return 0;
299 
300  omap_test_timeout((_clkctrl_idlest(part, inst, cdoffs, clkctrl_offs) ==
303 
304  return (i < MAX_MODULE_DISABLE_TIME) ? 0 : -EBUSY;
305 }
306 
317 void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs,
318  u16 clkctrl_offs)
319 {
320  u32 v;
321 
322  v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
324  v |= mode << OMAP4430_MODULEMODE_SHIFT;
325  omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
326 }
327 
337 void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
338  u16 clkctrl_offs)
339 {
340  u32 v;
341 
342  v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
344  omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
345 }