Commit | Line | Data |
---|---|---|
f327e07b RN |
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> | |
6e01478a | 18 | |
f327e07b | 19 | #include <plat/prcm.h> |
6e01478a | 20 | |
72e06d08 | 21 | #include "powerdomain.h" |
6e01478a PW |
22 | #include "prm.h" |
23 | #include "prm-regbits-24xx.h" | |
24 | #include "prm-regbits-34xx.h" | |
25 | ||
f327e07b RN |
26 | |
27 | /* Common functions across OMAP2 and OMAP3 */ | |
28 | static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | |
29 | { | |
c4d7e58f | 30 | omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, |
f327e07b RN |
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 | { | |
c4d7e58f PW |
38 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, |
39 | OMAP2_PM_PWSTCTRL, | |
40 | OMAP_POWERSTATE_MASK); | |
f327e07b RN |
41 | } |
42 | ||
43 | static int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm) | |
44 | { | |
c4d7e58f PW |
45 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, |
46 | OMAP2_PM_PWSTST, | |
47 | OMAP_POWERSTATEST_MASK); | |
f327e07b RN |
48 | } |
49 | ||
9b7fc907 RN |
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 | ||
c4d7e58f PW |
57 | omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs, |
58 | OMAP2_PM_PWSTCTRL); | |
9b7fc907 RN |
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 | ||
c4d7e58f PW |
70 | omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs, |
71 | OMAP2_PM_PWSTCTRL); | |
9b7fc907 RN |
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 | ||
c4d7e58f PW |
82 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST, |
83 | m); | |
9b7fc907 RN |
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 | ||
c4d7e58f PW |
92 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, |
93 | OMAP2_PM_PWSTCTRL, m); | |
9b7fc907 RN |
94 | } |
95 | ||
12627578 RN |
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); | |
c4d7e58f PW |
101 | omap2_prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE_MASK, v, |
102 | pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); | |
12627578 RN |
103 | |
104 | return 0; | |
105 | } | |
106 | ||
9b7fc907 RN |
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? */ | |
c4d7e58f | 118 | while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) & |
9b7fc907 RN |
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 | ||
f327e07b RN |
134 | /* Applicable only for OMAP3. Not supported on OMAP2 */ |
135 | static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | |
136 | { | |
c4d7e58f PW |
137 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, |
138 | OMAP3430_PM_PREPWSTST, | |
139 | OMAP3430_LASTPOWERSTATEENTERED_MASK); | |
f327e07b RN |
140 | } |
141 | ||
12627578 RN |
142 | static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) |
143 | { | |
c4d7e58f PW |
144 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, |
145 | OMAP2_PM_PWSTST, | |
146 | OMAP3430_LOGICSTATEST_MASK); | |
12627578 RN |
147 | } |
148 | ||
149 | static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm) | |
150 | { | |
c4d7e58f PW |
151 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, |
152 | OMAP2_PM_PWSTCTRL, | |
153 | OMAP3430_LOGICSTATEST_MASK); | |
12627578 RN |
154 | } |
155 | ||
156 | static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm) | |
157 | { | |
c4d7e58f PW |
158 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, |
159 | OMAP3430_PM_PREPWSTST, | |
160 | OMAP3430_LASTLOGICSTATEENTERED_MASK); | |
12627578 RN |
161 | } |
162 | ||
9b7fc907 RN |
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 | ||
c4d7e58f | 187 | return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, |
9b7fc907 RN |
188 | OMAP3430_PM_PREPWSTST, m); |
189 | } | |
190 | ||
191 | static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) | |
192 | { | |
c4d7e58f | 193 | omap2_prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST); |
9b7fc907 RN |
194 | return 0; |
195 | } | |
196 | ||
197 | static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm) | |
198 | { | |
c4d7e58f PW |
199 | return omap2_prm_rmw_mod_reg_bits(0, |
200 | 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, | |
201 | pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); | |
9b7fc907 RN |
202 | } |
203 | ||
204 | static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm) | |
205 | { | |
c4d7e58f PW |
206 | return omap2_prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, |
207 | 0, pwrdm->prcm_offs, | |
208 | OMAP2_PM_PWSTCTRL); | |
9b7fc907 RN |
209 | } |
210 | ||
f327e07b RN |
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, | |
12627578 | 215 | .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst, |
9b7fc907 RN |
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, | |
f327e07b RN |
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, | |
12627578 RN |
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, | |
9b7fc907 RN |
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, | |
f327e07b | 241 | }; |