Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cm33xx.c
Go to the documentation of this file.
1 /*
2  * AM33XX CM functions
3  *
4  * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
5  * Vaibhav Hiremath <[email protected]>
6  *
7  * Reference taken from from OMAP4 cminst44xx.c
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation version 2.
12  *
13  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
14  * kind, whether express or implied; without even the implied warranty
15  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  */
18 
19 #include <linux/kernel.h>
20 #include <linux/types.h>
21 #include <linux/errno.h>
22 #include <linux/err.h>
23 #include <linux/io.h>
24 
25 #include <plat/common.h>
26 
27 #include "cm.h"
28 #include "cm33xx.h"
29 #include "cm-regbits-34xx.h"
30 #include "cm-regbits-33xx.h"
31 #include "prm33xx.h"
32 
33 /*
34  * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield:
35  *
36  * 0x0 func: Module is fully functional, including OCP
37  * 0x1 trans: Module is performing transition: wakeup, or sleep, or sleep
38  * abortion
39  * 0x2 idle: Module is in Idle mode (only OCP part). It is functional if
40  * using separate functional clock
41  * 0x3 disabled: Module is disabled and cannot be accessed
42  *
43  */
44 #define CLKCTRL_IDLEST_FUNCTIONAL 0x0
45 #define CLKCTRL_IDLEST_INTRANSITION 0x1
46 #define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2
47 #define CLKCTRL_IDLEST_DISABLED 0x3
48 
49 /* Private functions */
50 
51 /* Read a register in a CM instance */
52 static inline u32 am33xx_cm_read_reg(s16 inst, u16 idx)
53 {
54  return __raw_readl(cm_base + inst + idx);
55 }
56 
57 /* Write into a register in a CM */
58 static inline void am33xx_cm_write_reg(u32 val, s16 inst, u16 idx)
59 {
60  __raw_writel(val, cm_base + inst + idx);
61 }
62 
63 /* Read-modify-write a register in CM */
64 static inline u32 am33xx_cm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx)
65 {
66  u32 v;
67 
68  v = am33xx_cm_read_reg(inst, idx);
69  v &= ~mask;
70  v |= bits;
71  am33xx_cm_write_reg(v, inst, idx);
72 
73  return v;
74 }
75 
76 static inline u32 am33xx_cm_set_reg_bits(u32 bits, s16 inst, s16 idx)
77 {
78  return am33xx_cm_rmw_reg_bits(bits, bits, inst, idx);
79 }
80 
81 static inline u32 am33xx_cm_clear_reg_bits(u32 bits, s16 inst, s16 idx)
82 {
83  return am33xx_cm_rmw_reg_bits(bits, 0x0, inst, idx);
84 }
85 
86 static inline u32 am33xx_cm_read_reg_bits(u16 inst, s16 idx, u32 mask)
87 {
88  u32 v;
89 
90  v = am33xx_cm_read_reg(inst, idx);
91  v &= mask;
92  v >>= __ffs(mask);
93 
94  return v;
95 }
96 
106 static u32 _clkctrl_idlest(u16 inst, s16 cdoffs, u16 clkctrl_offs)
107 {
108  u32 v = am33xx_cm_read_reg(inst, clkctrl_offs);
109  v &= AM33XX_IDLEST_MASK;
110  v >>= AM33XX_IDLEST_SHIFT;
111  return v;
112 }
113 
123 static bool _is_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs)
124 {
125  u32 v;
126 
127  v = _clkctrl_idlest(inst, cdoffs, clkctrl_offs);
128 
129  return (v == CLKCTRL_IDLEST_FUNCTIONAL ||
130  v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false;
131 }
132 
142 static void _clktrctrl_write(u8 c, s16 inst, u16 cdoffs)
143 {
144  u32 v;
145 
146  v = am33xx_cm_read_reg(inst, cdoffs);
147  v &= ~AM33XX_CLKTRCTRL_MASK;
148  v |= c << AM33XX_CLKTRCTRL_SHIFT;
149  am33xx_cm_write_reg(v, inst, cdoffs);
150 }
151 
152 /* Public functions */
153 
163 {
164  u32 v;
165 
166  v = am33xx_cm_read_reg(inst, cdoffs);
169 
170  return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? true : false;
171 }
172 
182 {
183  _clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, inst, cdoffs);
184 }
185 
196 {
197  _clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, inst, cdoffs);
198 }
199 
209 {
210  _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, inst, cdoffs);
211 }
212 
222 {
223  _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, inst, cdoffs);
224 }
225 
226 /*
227  *
228  */
229 
241 int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs)
242 {
243  int i = 0;
244 
245  if (!clkctrl_offs)
246  return 0;
247 
248  omap_test_timeout(_is_module_ready(inst, cdoffs, clkctrl_offs),
250 
251  return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
252 }
253 
265 int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs, u16 clkctrl_offs)
266 {
267  int i = 0;
268 
269  if (!clkctrl_offs)
270  return 0;
271 
272  omap_test_timeout((_clkctrl_idlest(inst, cdoffs, clkctrl_offs) ==
275 
276  return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
277 }
278 
288 void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs, u16 clkctrl_offs)
289 {
290  u32 v;
291 
292  v = am33xx_cm_read_reg(inst, clkctrl_offs);
294  v |= mode << AM33XX_MODULEMODE_SHIFT;
295  am33xx_cm_write_reg(v, inst, clkctrl_offs);
296 }
297 
306 void am33xx_cm_module_disable(u16 inst, s16 cdoffs, u16 clkctrl_offs)
307 {
308  u32 v;
309 
310  v = am33xx_cm_read_reg(inst, clkctrl_offs);
312  am33xx_cm_write_reg(v, inst, clkctrl_offs);
313 }