Commit | Line | Data |
---|---|---|
f327e07b RN |
1 | /* |
2 | * OMAP4 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> | |
4647ca57 | 18 | #include <linux/bug.h> |
6e01478a | 19 | |
72e06d08 | 20 | #include "powerdomain.h" |
f327e07b | 21 | #include <plat/prcm.h> |
59fb659b | 22 | #include "prm2xxx_3xxx.h" |
d198b514 | 23 | #include "prm44xx.h" |
a64bb9cd | 24 | #include "prminst44xx.h" |
f327e07b | 25 | #include "prm-regbits-44xx.h" |
f327e07b RN |
26 | |
27 | static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | |
28 | { | |
a64bb9cd PW |
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); | |
f327e07b RN |
33 | return 0; |
34 | } | |
35 | ||
36 | static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | |
37 | { | |
a64bb9cd PW |
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; | |
f327e07b RN |
46 | } |
47 | ||
48 | static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm) | |
49 | { | |
a64bb9cd PW |
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; | |
f327e07b RN |
58 | } |
59 | ||
60 | static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | |
61 | { | |
a64bb9cd PW |
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; | |
f327e07b RN |
70 | } |
71 | ||
9b7fc907 RN |
72 | static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) |
73 | { | |
a64bb9cd PW |
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); | |
9b7fc907 RN |
78 | return 0; |
79 | } | |
80 | ||
4b4f62c4 SS |
81 | static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) |
82 | { | |
a64bb9cd PW |
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); | |
4b4f62c4 SS |
87 | return 0; |
88 | } | |
89 | ||
12627578 RN |
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); | |
a64bb9cd PW |
95 | omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v, |
96 | pwrdm->prcm_partition, pwrdm->prcm_offs, | |
97 | OMAP4_PM_PWSTCTRL); | |
12627578 RN |
98 | |
99 | return 0; | |
100 | } | |
101 | ||
9b7fc907 | 102 | static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, |
a64bb9cd | 103 | u8 pwrst) |
9b7fc907 RN |
104 | { |
105 | u32 m; | |
106 | ||
107 | m = omap2_pwrdm_get_mem_bank_onstate_mask(bank); | |
108 | ||
a64bb9cd PW |
109 | omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)), |
110 | pwrdm->prcm_partition, pwrdm->prcm_offs, | |
111 | OMAP4_PM_PWSTCTRL); | |
9b7fc907 RN |
112 | |
113 | return 0; | |
114 | } | |
115 | ||
116 | static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, | |
a64bb9cd | 117 | u8 pwrst) |
9b7fc907 RN |
118 | { |
119 | u32 m; | |
120 | ||
121 | m = omap2_pwrdm_get_mem_bank_retst_mask(bank); | |
122 | ||
a64bb9cd PW |
123 | omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)), |
124 | pwrdm->prcm_partition, pwrdm->prcm_offs, | |
125 | OMAP4_PM_PWSTCTRL); | |
9b7fc907 RN |
126 | |
127 | return 0; | |
128 | } | |
129 | ||
12627578 RN |
130 | static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) |
131 | { | |
a64bb9cd PW |
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; | |
12627578 RN |
140 | } |
141 | ||
142 | static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm) | |
143 | { | |
a64bb9cd PW |
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; | |
12627578 RN |
152 | } |
153 | ||
9b7fc907 RN |
154 | static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) |
155 | { | |
a64bb9cd | 156 | u32 m, v; |
9b7fc907 RN |
157 | |
158 | m = omap2_pwrdm_get_mem_bank_stst_mask(bank); | |
159 | ||
a64bb9cd PW |
160 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, |
161 | OMAP4_PM_PWSTST); | |
162 | v &= m; | |
163 | v >>= __ffs(m); | |
164 | ||
165 | return v; | |
9b7fc907 RN |
166 | } |
167 | ||
168 | static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) | |
169 | { | |
a64bb9cd | 170 | u32 m, v; |
9b7fc907 RN |
171 | |
172 | m = omap2_pwrdm_get_mem_bank_retst_mask(bank); | |
173 | ||
a64bb9cd PW |
174 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, |
175 | OMAP4_PM_PWSTCTRL); | |
176 | v &= m; | |
177 | v >>= __ffs(m); | |
178 | ||
179 | return v; | |
9b7fc907 RN |
180 | } |
181 | ||
182 | static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm) | |
183 | { | |
184 | u32 c = 0; | |
185 | ||
186 | /* | |
187 | * REVISIT: pwrdm_wait_transition() may be better implemented | |
188 | * via a callback and a periodic timer check -- how long do we expect | |
189 | * powerdomain transitions to take? | |
190 | */ | |
191 | ||
192 | /* XXX Is this udelay() value meaningful? */ | |
a64bb9cd PW |
193 | while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition, |
194 | pwrdm->prcm_offs, | |
195 | OMAP4_PM_PWSTST) & | |
9b7fc907 | 196 | OMAP_INTRANSITION_MASK) && |
a64bb9cd PW |
197 | (c++ < PWRDM_TRANSITION_BAILOUT)) |
198 | udelay(1); | |
9b7fc907 RN |
199 | |
200 | if (c > PWRDM_TRANSITION_BAILOUT) { | |
201 | printk(KERN_ERR "powerdomain: waited too long for " | |
a64bb9cd | 202 | "powerdomain %s to complete transition\n", pwrdm->name); |
9b7fc907 RN |
203 | return -EAGAIN; |
204 | } | |
205 | ||
206 | pr_debug("powerdomain: completed transition in %d loops\n", c); | |
207 | ||
208 | return 0; | |
209 | } | |
210 | ||
f327e07b RN |
211 | struct pwrdm_ops omap4_pwrdm_operations = { |
212 | .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst, | |
213 | .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst, | |
214 | .pwrdm_read_pwrst = omap4_pwrdm_read_pwrst, | |
215 | .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst, | |
9b7fc907 | 216 | .pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange, |
4b4f62c4 | 217 | .pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst, |
12627578 RN |
218 | .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst, |
219 | .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst, | |
220 | .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst, | |
9b7fc907 RN |
221 | .pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst, |
222 | .pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst, | |
223 | .pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst, | |
224 | .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst, | |
225 | .pwrdm_wait_transition = omap4_pwrdm_wait_transition, | |
f327e07b | 226 | }; |