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> | |
6e01478a | 18 | |
72e06d08 | 19 | #include "powerdomain.h" |
f327e07b | 20 | #include <plat/prcm.h> |
59fb659b | 21 | #include "prm2xxx_3xxx.h" |
d198b514 | 22 | #include "prm44xx.h" |
a64bb9cd | 23 | #include "prminst44xx.h" |
f327e07b | 24 | #include "prm-regbits-44xx.h" |
f327e07b RN |
25 | |
26 | static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) | |
27 | { | |
a64bb9cd PW |
28 | omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK, |
29 | (pwrst << OMAP_POWERSTATE_SHIFT), | |
30 | pwrdm->prcm_partition, | |
31 | pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL); | |
f327e07b RN |
32 | return 0; |
33 | } | |
34 | ||
35 | static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm) | |
36 | { | |
a64bb9cd PW |
37 | u32 v; |
38 | ||
39 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | |
40 | OMAP4_PM_PWSTCTRL); | |
41 | v &= OMAP_POWERSTATE_MASK; | |
42 | v >>= OMAP_POWERSTATE_SHIFT; | |
43 | ||
44 | return v; | |
f327e07b RN |
45 | } |
46 | ||
47 | static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm) | |
48 | { | |
a64bb9cd PW |
49 | u32 v; |
50 | ||
51 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | |
52 | OMAP4_PM_PWSTST); | |
53 | v &= OMAP_POWERSTATEST_MASK; | |
54 | v >>= OMAP_POWERSTATEST_SHIFT; | |
55 | ||
56 | return v; | |
f327e07b RN |
57 | } |
58 | ||
59 | static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm) | |
60 | { | |
a64bb9cd PW |
61 | u32 v; |
62 | ||
63 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | |
64 | OMAP4_PM_PWSTST); | |
65 | v &= OMAP4430_LASTPOWERSTATEENTERED_MASK; | |
66 | v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT; | |
67 | ||
68 | return v; | |
f327e07b RN |
69 | } |
70 | ||
9b7fc907 RN |
71 | static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm) |
72 | { | |
a64bb9cd PW |
73 | omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK, |
74 | (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT), | |
75 | pwrdm->prcm_partition, | |
76 | pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL); | |
9b7fc907 RN |
77 | return 0; |
78 | } | |
79 | ||
4b4f62c4 SS |
80 | static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm) |
81 | { | |
a64bb9cd PW |
82 | omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK, |
83 | OMAP4430_LASTPOWERSTATEENTERED_MASK, | |
84 | pwrdm->prcm_partition, | |
85 | pwrdm->prcm_offs, OMAP4_PM_PWSTST); | |
4b4f62c4 SS |
86 | return 0; |
87 | } | |
88 | ||
12627578 RN |
89 | static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst) |
90 | { | |
91 | u32 v; | |
92 | ||
93 | v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK); | |
a64bb9cd PW |
94 | omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v, |
95 | pwrdm->prcm_partition, pwrdm->prcm_offs, | |
96 | OMAP4_PM_PWSTCTRL); | |
12627578 RN |
97 | |
98 | return 0; | |
99 | } | |
100 | ||
9b7fc907 | 101 | static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, |
a64bb9cd | 102 | u8 pwrst) |
9b7fc907 RN |
103 | { |
104 | u32 m; | |
105 | ||
106 | m = omap2_pwrdm_get_mem_bank_onstate_mask(bank); | |
107 | ||
a64bb9cd PW |
108 | omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)), |
109 | pwrdm->prcm_partition, pwrdm->prcm_offs, | |
110 | OMAP4_PM_PWSTCTRL); | |
9b7fc907 RN |
111 | |
112 | return 0; | |
113 | } | |
114 | ||
115 | static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, | |
a64bb9cd | 116 | u8 pwrst) |
9b7fc907 RN |
117 | { |
118 | u32 m; | |
119 | ||
120 | m = omap2_pwrdm_get_mem_bank_retst_mask(bank); | |
121 | ||
a64bb9cd PW |
122 | omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)), |
123 | pwrdm->prcm_partition, pwrdm->prcm_offs, | |
124 | OMAP4_PM_PWSTCTRL); | |
9b7fc907 RN |
125 | |
126 | return 0; | |
127 | } | |
128 | ||
12627578 RN |
129 | static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm) |
130 | { | |
a64bb9cd PW |
131 | u32 v; |
132 | ||
133 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | |
134 | OMAP4_PM_PWSTST); | |
135 | v &= OMAP4430_LOGICSTATEST_MASK; | |
136 | v >>= OMAP4430_LOGICSTATEST_SHIFT; | |
137 | ||
138 | return v; | |
12627578 RN |
139 | } |
140 | ||
141 | static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm) | |
142 | { | |
a64bb9cd PW |
143 | u32 v; |
144 | ||
145 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, | |
146 | OMAP4_PM_PWSTCTRL); | |
147 | v &= OMAP4430_LOGICRETSTATE_MASK; | |
148 | v >>= OMAP4430_LOGICRETSTATE_SHIFT; | |
149 | ||
150 | return v; | |
12627578 RN |
151 | } |
152 | ||
9b7fc907 RN |
153 | static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank) |
154 | { | |
a64bb9cd | 155 | u32 m, v; |
9b7fc907 RN |
156 | |
157 | m = omap2_pwrdm_get_mem_bank_stst_mask(bank); | |
158 | ||
a64bb9cd PW |
159 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, |
160 | OMAP4_PM_PWSTST); | |
161 | v &= m; | |
162 | v >>= __ffs(m); | |
163 | ||
164 | return v; | |
9b7fc907 RN |
165 | } |
166 | ||
167 | static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank) | |
168 | { | |
a64bb9cd | 169 | u32 m, v; |
9b7fc907 RN |
170 | |
171 | m = omap2_pwrdm_get_mem_bank_retst_mask(bank); | |
172 | ||
a64bb9cd PW |
173 | v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs, |
174 | OMAP4_PM_PWSTCTRL); | |
175 | v &= m; | |
176 | v >>= __ffs(m); | |
177 | ||
178 | return v; | |
9b7fc907 RN |
179 | } |
180 | ||
181 | static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm) | |
182 | { | |
183 | u32 c = 0; | |
184 | ||
185 | /* | |
186 | * REVISIT: pwrdm_wait_transition() may be better implemented | |
187 | * via a callback and a periodic timer check -- how long do we expect | |
188 | * powerdomain transitions to take? | |
189 | */ | |
190 | ||
191 | /* XXX Is this udelay() value meaningful? */ | |
a64bb9cd PW |
192 | while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition, |
193 | pwrdm->prcm_offs, | |
194 | OMAP4_PM_PWSTST) & | |
9b7fc907 | 195 | OMAP_INTRANSITION_MASK) && |
a64bb9cd PW |
196 | (c++ < PWRDM_TRANSITION_BAILOUT)) |
197 | udelay(1); | |
9b7fc907 RN |
198 | |
199 | if (c > PWRDM_TRANSITION_BAILOUT) { | |
200 | printk(KERN_ERR "powerdomain: waited too long for " | |
a64bb9cd | 201 | "powerdomain %s to complete transition\n", pwrdm->name); |
9b7fc907 RN |
202 | return -EAGAIN; |
203 | } | |
204 | ||
205 | pr_debug("powerdomain: completed transition in %d loops\n", c); | |
206 | ||
207 | return 0; | |
208 | } | |
209 | ||
f327e07b RN |
210 | struct pwrdm_ops omap4_pwrdm_operations = { |
211 | .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst, | |
212 | .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst, | |
213 | .pwrdm_read_pwrst = omap4_pwrdm_read_pwrst, | |
214 | .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst, | |
9b7fc907 | 215 | .pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange, |
4b4f62c4 | 216 | .pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst, |
12627578 RN |
217 | .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst, |
218 | .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst, | |
219 | .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst, | |
9b7fc907 RN |
220 | .pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst, |
221 | .pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst, | |
222 | .pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst, | |
223 | .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst, | |
224 | .pwrdm_wait_transition = omap4_pwrdm_wait_transition, | |
f327e07b | 225 | }; |