]> Pileus Git - ~andy/linux/blob - arch/arm/mach-omap2/powerdomain44xx.c
Merge tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
[~andy/linux] / arch / arm / mach-omap2 / powerdomain44xx.c
1 /*
2  * OMAP4 powerdomain control
3  *
4  * Copyright (C) 2009-2010, 2012 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 #include <linux/bug.h>
19
20 #include "powerdomain.h"
21 #include <plat/prcm.h>
22 #include "prm2xxx_3xxx.h"
23 #include "prm44xx.h"
24 #include "prminst44xx.h"
25 #include "prm-regbits-44xx.h"
26
27 static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
28 {
29         omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK,
30                                         (pwrst << OMAP_POWERSTATE_SHIFT),
31                                         pwrdm->prcm_partition,
32                                         pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
33         return 0;
34 }
35
36 static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
37 {
38         u32 v;
39
40         v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
41                                         OMAP4_PM_PWSTCTRL);
42         v &= OMAP_POWERSTATE_MASK;
43         v >>= OMAP_POWERSTATE_SHIFT;
44
45         return v;
46 }
47
48 static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm)
49 {
50         u32 v;
51
52         v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
53                                         OMAP4_PM_PWSTST);
54         v &= OMAP_POWERSTATEST_MASK;
55         v >>= OMAP_POWERSTATEST_SHIFT;
56
57         return v;
58 }
59
60 static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
61 {
62         u32 v;
63
64         v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
65                                         OMAP4_PM_PWSTST);
66         v &= OMAP4430_LASTPOWERSTATEENTERED_MASK;
67         v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
68
69         return v;
70 }
71
72 static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
73 {
74         omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
75                                         (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
76                                         pwrdm->prcm_partition,
77                                         pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
78         return 0;
79 }
80
81 static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
82 {
83         omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK,
84                                         OMAP4430_LASTPOWERSTATEENTERED_MASK,
85                                         pwrdm->prcm_partition,
86                                         pwrdm->prcm_offs, OMAP4_PM_PWSTST);
87         return 0;
88 }
89
90 static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
91 {
92         u32 v;
93
94         v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK);
95         omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v,
96                                         pwrdm->prcm_partition, pwrdm->prcm_offs,
97                                         OMAP4_PM_PWSTCTRL);
98
99         return 0;
100 }
101
102 static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
103                                     u8 pwrst)
104 {
105         u32 m;
106
107         m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
108
109         omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
110                                         pwrdm->prcm_partition, pwrdm->prcm_offs,
111                                         OMAP4_PM_PWSTCTRL);
112
113         return 0;
114 }
115
116 static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
117                                      u8 pwrst)
118 {
119         u32 m;
120
121         m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
122
123         omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
124                                         pwrdm->prcm_partition, pwrdm->prcm_offs,
125                                         OMAP4_PM_PWSTCTRL);
126
127         return 0;
128 }
129
130 static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
131 {
132         u32 v;
133
134         v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
135                                         OMAP4_PM_PWSTST);
136         v &= OMAP4430_LOGICSTATEST_MASK;
137         v >>= OMAP4430_LOGICSTATEST_SHIFT;
138
139         return v;
140 }
141
142 static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
143 {
144         u32 v;
145
146         v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
147                                         OMAP4_PM_PWSTCTRL);
148         v &= OMAP4430_LOGICRETSTATE_MASK;
149         v >>= OMAP4430_LOGICRETSTATE_SHIFT;
150
151         return v;
152 }
153
154 /**
155  * omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate
156  * @pwrdm: struct powerdomain * to read the state for
157  *
158  * Reads the previous logic powerstate for a powerdomain. This
159  * function must determine the previous logic powerstate by first
160  * checking the previous powerstate for the domain. If that was OFF,
161  * then logic has been lost. If previous state was RETENTION, the
162  * function reads the setting for the next retention logic state to
163  * see the actual value.  In every other case, the logic is
164  * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
165  * depending whether the logic was retained or not.
166  */
167 static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
168 {
169         int state;
170
171         state = omap4_pwrdm_read_prev_pwrst(pwrdm);
172
173         if (state == PWRDM_POWER_OFF)
174                 return PWRDM_POWER_OFF;
175
176         if (state != PWRDM_POWER_RET)
177                 return PWRDM_POWER_RET;
178
179         return omap4_pwrdm_read_logic_retst(pwrdm);
180 }
181
182 static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
183 {
184         u32 m, v;
185
186         m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
187
188         v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
189                                         OMAP4_PM_PWSTST);
190         v &= m;
191         v >>= __ffs(m);
192
193         return v;
194 }
195
196 static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
197 {
198         u32 m, v;
199
200         m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
201
202         v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
203                                         OMAP4_PM_PWSTCTRL);
204         v &= m;
205         v >>= __ffs(m);
206
207         return v;
208 }
209
210 /**
211  * omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate
212  * @pwrdm: struct powerdomain * to read mem powerstate for
213  * @bank: memory bank index
214  *
215  * Reads the previous memory powerstate for a powerdomain. This
216  * function must determine the previous memory powerstate by first
217  * checking the previous powerstate for the domain. If that was OFF,
218  * then logic has been lost. If previous state was RETENTION, the
219  * function reads the setting for the next memory retention state to
220  * see the actual value.  In every other case, the logic is
221  * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
222  * depending whether logic was retained or not.
223  */
224 static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
225 {
226         int state;
227
228         state = omap4_pwrdm_read_prev_pwrst(pwrdm);
229
230         if (state == PWRDM_POWER_OFF)
231                 return PWRDM_POWER_OFF;
232
233         if (state != PWRDM_POWER_RET)
234                 return PWRDM_POWER_RET;
235
236         return omap4_pwrdm_read_mem_retst(pwrdm, bank);
237 }
238
239 static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
240 {
241         u32 c = 0;
242
243         /*
244          * REVISIT: pwrdm_wait_transition() may be better implemented
245          * via a callback and a periodic timer check -- how long do we expect
246          * powerdomain transitions to take?
247          */
248
249         /* XXX Is this udelay() value meaningful? */
250         while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
251                                             pwrdm->prcm_offs,
252                                             OMAP4_PM_PWSTST) &
253                 OMAP_INTRANSITION_MASK) &&
254                (c++ < PWRDM_TRANSITION_BAILOUT))
255                 udelay(1);
256
257         if (c > PWRDM_TRANSITION_BAILOUT) {
258                 pr_err("powerdomain: %s: waited too long to complete transition\n",
259                        pwrdm->name);
260                 return -EAGAIN;
261         }
262
263         pr_debug("powerdomain: completed transition in %d loops\n", c);
264
265         return 0;
266 }
267
268 struct pwrdm_ops omap4_pwrdm_operations = {
269         .pwrdm_set_next_pwrst   = omap4_pwrdm_set_next_pwrst,
270         .pwrdm_read_next_pwrst  = omap4_pwrdm_read_next_pwrst,
271         .pwrdm_read_pwrst       = omap4_pwrdm_read_pwrst,
272         .pwrdm_read_prev_pwrst  = omap4_pwrdm_read_prev_pwrst,
273         .pwrdm_set_lowpwrstchange       = omap4_pwrdm_set_lowpwrstchange,
274         .pwrdm_clear_all_prev_pwrst     = omap4_pwrdm_clear_all_prev_pwrst,
275         .pwrdm_set_logic_retst  = omap4_pwrdm_set_logic_retst,
276         .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst,
277         .pwrdm_read_prev_logic_pwrst    = omap4_pwrdm_read_prev_logic_pwrst,
278         .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst,
279         .pwrdm_read_mem_pwrst   = omap4_pwrdm_read_mem_pwrst,
280         .pwrdm_read_mem_retst   = omap4_pwrdm_read_mem_retst,
281         .pwrdm_read_prev_mem_pwrst      = omap4_pwrdm_read_prev_mem_pwrst,
282         .pwrdm_set_mem_onst     = omap4_pwrdm_set_mem_onst,
283         .pwrdm_set_mem_retst    = omap4_pwrdm_set_mem_retst,
284         .pwrdm_wait_transition  = omap4_pwrdm_wait_transition,
285 };