Merge branch 'for-38-rc2' of git://codeaurora.org/quic/kernel/davidb/linux-msm
[pandora-kernel.git] / arch / arm / mach-omap2 / powerdomain2xxx_3xxx.c
1 /*
2  * OMAP2 and OMAP3 powerdomain control
3  *
4  * Copyright (C) 2009-2010 Texas Instruments, Inc.
5  * Copyright (C) 2007-2009 Nokia Corporation
6  *
7  * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
8  * Rajendra Nayak <rnayak@ti.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  */
14
15 #include <linux/io.h>
16 #include <linux/errno.h>
17 #include <linux/delay.h>
18
19 #include <plat/prcm.h>
20
21 #include "powerdomain.h"
22 #include "prm-regbits-34xx.h"
23 #include "prm.h"
24 #include "prm-regbits-24xx.h"
25 #include "prm-regbits-34xx.h"
26
27
28 /* Common functions across OMAP2 and OMAP3 */
29 static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
30 {
31         omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
32                                 (pwrst << OMAP_POWERSTATE_SHIFT),
33                                 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
34         return 0;
35 }
36
37 static int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
38 {
39         return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
40                                              OMAP2_PM_PWSTCTRL,
41                                              OMAP_POWERSTATE_MASK);
42 }
43
44 static int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm)
45 {
46         return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
47                                              OMAP2_PM_PWSTST,
48                                              OMAP_POWERSTATEST_MASK);
49 }
50
51 static int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
52                                                                 u8 pwrst)
53 {
54         u32 m;
55
56         m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
57
58         omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
59                                    OMAP2_PM_PWSTCTRL);
60
61         return 0;
62 }
63
64 static int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
65                                                                 u8 pwrst)
66 {
67         u32 m;
68
69         m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
70
71         omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
72                                    OMAP2_PM_PWSTCTRL);
73
74         return 0;
75 }
76
77 static int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
78 {
79         u32 m;
80
81         m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
82
83         return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST,
84                                              m);
85 }
86
87 static int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
88 {
89         u32 m;
90
91         m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
92
93         return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
94                                              OMAP2_PM_PWSTCTRL, m);
95 }
96
97 static int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
98 {
99         u32 v;
100
101         v = pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE_MASK);
102         omap2_prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE_MASK, v,
103                                    pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
104
105         return 0;
106 }
107
108 static int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)
109 {
110         u32 c = 0;
111
112         /*
113          * REVISIT: pwrdm_wait_transition() may be better implemented
114          * via a callback and a periodic timer check -- how long do we expect
115          * powerdomain transitions to take?
116          */
117
118         /* XXX Is this udelay() value meaningful? */
119         while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) &
120                 OMAP_INTRANSITION_MASK) &&
121                 (c++ < PWRDM_TRANSITION_BAILOUT))
122                         udelay(1);
123
124         if (c > PWRDM_TRANSITION_BAILOUT) {
125                 printk(KERN_ERR "powerdomain: waited too long for "
126                         "powerdomain %s to complete transition\n", pwrdm->name);
127                 return -EAGAIN;
128         }
129
130         pr_debug("powerdomain: completed transition in %d loops\n", c);
131
132         return 0;
133 }
134
135 /* Applicable only for OMAP3. Not supported on OMAP2 */
136 static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
137 {
138         return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
139                                              OMAP3430_PM_PREPWSTST,
140                                              OMAP3430_LASTPOWERSTATEENTERED_MASK);
141 }
142
143 static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
144 {
145         return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
146                                              OMAP2_PM_PWSTST,
147                                              OMAP3430_LOGICSTATEST_MASK);
148 }
149
150 static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
151 {
152         return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
153                                              OMAP2_PM_PWSTCTRL,
154                                              OMAP3430_LOGICSTATEST_MASK);
155 }
156
157 static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
158 {
159         return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
160                                              OMAP3430_PM_PREPWSTST,
161                                              OMAP3430_LASTLOGICSTATEENTERED_MASK);
162 }
163
164 static int omap3_get_mem_bank_lastmemst_mask(u8 bank)
165 {
166         switch (bank) {
167         case 0:
168                 return OMAP3430_LASTMEM1STATEENTERED_MASK;
169         case 1:
170                 return OMAP3430_LASTMEM2STATEENTERED_MASK;
171         case 2:
172                 return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
173         case 3:
174                 return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
175         default:
176                 WARN_ON(1); /* should never happen */
177                 return -EEXIST;
178         }
179         return 0;
180 }
181
182 static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
183 {
184         u32 m;
185
186         m = omap3_get_mem_bank_lastmemst_mask(bank);
187
188         return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
189                                 OMAP3430_PM_PREPWSTST, m);
190 }
191
192 static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
193 {
194         omap2_prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
195         return 0;
196 }
197
198 static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
199 {
200         return omap2_prm_rmw_mod_reg_bits(0,
201                                           1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
202                                           pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
203 }
204
205 static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
206 {
207         return omap2_prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
208                                           0, pwrdm->prcm_offs,
209                                           OMAP2_PM_PWSTCTRL);
210 }
211
212 struct pwrdm_ops omap2_pwrdm_operations = {
213         .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
214         .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
215         .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
216         .pwrdm_set_logic_retst  = omap2_pwrdm_set_logic_retst,
217         .pwrdm_set_mem_onst     = omap2_pwrdm_set_mem_onst,
218         .pwrdm_set_mem_retst    = omap2_pwrdm_set_mem_retst,
219         .pwrdm_read_mem_pwrst   = omap2_pwrdm_read_mem_pwrst,
220         .pwrdm_read_mem_retst   = omap2_pwrdm_read_mem_retst,
221         .pwrdm_wait_transition  = omap2_pwrdm_wait_transition,
222 };
223
224 struct pwrdm_ops omap3_pwrdm_operations = {
225         .pwrdm_set_next_pwrst   = omap2_pwrdm_set_next_pwrst,
226         .pwrdm_read_next_pwrst  = omap2_pwrdm_read_next_pwrst,
227         .pwrdm_read_pwrst       = omap2_pwrdm_read_pwrst,
228         .pwrdm_read_prev_pwrst  = omap3_pwrdm_read_prev_pwrst,
229         .pwrdm_set_logic_retst  = omap2_pwrdm_set_logic_retst,
230         .pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst,
231         .pwrdm_read_logic_retst = omap3_pwrdm_read_logic_retst,
232         .pwrdm_read_prev_logic_pwrst    = omap3_pwrdm_read_prev_logic_pwrst,
233         .pwrdm_set_mem_onst     = omap2_pwrdm_set_mem_onst,
234         .pwrdm_set_mem_retst    = omap2_pwrdm_set_mem_retst,
235         .pwrdm_read_mem_pwrst   = omap2_pwrdm_read_mem_pwrst,
236         .pwrdm_read_mem_retst   = omap2_pwrdm_read_mem_retst,
237         .pwrdm_read_prev_mem_pwrst      = omap3_pwrdm_read_prev_mem_pwrst,
238         .pwrdm_clear_all_prev_pwrst     = omap3_pwrdm_clear_all_prev_pwrst,
239         .pwrdm_enable_hdwr_sar  = omap3_pwrdm_enable_hdwr_sar,
240         .pwrdm_disable_hdwr_sar = omap3_pwrdm_disable_hdwr_sar,
241         .pwrdm_wait_transition  = omap2_pwrdm_wait_transition,
242 };