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