Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
powerdomain44xx.c
Go to the documentation of this file.
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 <[email protected]>
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 {
30  (pwrst << OMAP_POWERSTATE_SHIFT),
31  pwrdm->prcm_partition,
33  return 0;
34 }
35 
36 static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
37 {
38  u32 v;
39 
44 
45  return v;
46 }
47 
48 static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm)
49 {
50  u32 v;
51 
56 
57  return v;
58 }
59 
60 static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
61 {
62  u32 v;
63 
68 
69  return v;
70 }
71 
72 static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
73 {
76  pwrdm->prcm_partition,
78  return 0;
79 }
80 
81 static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
82 {
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);
96  pwrdm->prcm_partition, pwrdm->prcm_offs,
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 
108 
109  omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
110  pwrdm->prcm_partition, pwrdm->prcm_offs,
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 
122 
123  omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
124  pwrdm->prcm_partition, pwrdm->prcm_offs,
126 
127  return 0;
128 }
129 
130 static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
131 {
132  u32 v;
133 
138 
139  return v;
140 }
141 
142 static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
143 {
144  u32 v;
145 
150 
151  return v;
152 }
153 
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 
187 
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 
201 
204  v &= m;
205  v >>= __ffs(m);
206 
207  return v;
208 }
209 
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? */
251  pwrdm->prcm_offs,
252  OMAP4_PM_PWSTST) &
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 
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 };