]> Pileus Git - ~andy/linux/blob - arch/arm/mach-omap2/powerdomain44xx.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
[~andy/linux] / arch / arm / mach-omap2 / powerdomain44xx.c
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>
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 static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
155 {
156         u32 m, v;
157
158         m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
159
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;
166 }
167
168 static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
169 {
170         u32 m, v;
171
172         m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
173
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;
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? */
193         while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
194                                             pwrdm->prcm_offs,
195                                             OMAP4_PM_PWSTST) &
196                 OMAP_INTRANSITION_MASK) &&
197                (c++ < PWRDM_TRANSITION_BAILOUT))
198                 udelay(1);
199
200         if (c > PWRDM_TRANSITION_BAILOUT) {
201                 printk(KERN_ERR "powerdomain: waited too long for "
202                        "powerdomain %s to complete transition\n", pwrdm->name);
203                 return -EAGAIN;
204         }
205
206         pr_debug("powerdomain: completed transition in %d loops\n", c);
207
208         return 0;
209 }
210
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,
216         .pwrdm_set_lowpwrstchange       = omap4_pwrdm_set_lowpwrstchange,
217         .pwrdm_clear_all_prev_pwrst     = omap4_pwrdm_clear_all_prev_pwrst,
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,
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,
226 };