Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
powerdomain33xx.c
Go to the documentation of this file.
1 /*
2  * AM33XX Powerdomain control
3  *
4  * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
5  *
6  * Derived from mach-omap2/powerdomain44xx.c written by Rajendra Nayak
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation version 2.
12  *
13  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
14  * kind, whether express or implied; without even the implied warranty
15  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  */
18 
19 #include <linux/io.h>
20 #include <linux/errno.h>
21 #include <linux/delay.h>
22 
23 #include <plat/prcm.h>
24 
25 #include "powerdomain.h"
26 #include "prm33xx.h"
27 #include "prm-regbits-33xx.h"
28 
29 
30 static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
31 {
33  (pwrst << OMAP_POWERSTATE_SHIFT),
34  pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
35  return 0;
36 }
37 
38 static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
39 {
40  u32 v;
41 
42  v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
45 
46  return v;
47 }
48 
49 static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
50 {
51  u32 v;
52 
53  v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
56 
57  return v;
58 }
59 
60 static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
61 {
62  u32 v;
63 
64  v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
67 
68  return v;
69 }
70 
71 static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
72 {
75  pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
76  return 0;
77 }
78 
79 static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
80 {
83  pwrdm->prcm_offs, pwrdm->pwrstst_offs);
84  return 0;
85 }
86 
87 static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
88 {
89  u32 m;
90 
91  m = pwrdm->logicretstate_mask;
92  if (!m)
93  return -EINVAL;
94 
95  am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
96  pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
97 
98  return 0;
99 }
100 
101 static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
102 {
103  u32 v;
104 
105  v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
108 
109  return v;
110 }
111 
112 static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
113 {
114  u32 v, m;
115 
116  m = pwrdm->logicretstate_mask;
117  if (!m)
118  return -EINVAL;
119 
120  v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
121  v &= m;
122  v >>= __ffs(m);
123 
124  return v;
125 }
126 
127 static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
128  u8 pwrst)
129 {
130  u32 m;
131 
132  m = pwrdm->mem_on_mask[bank];
133  if (!m)
134  return -EINVAL;
135 
136  am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
137  pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
138 
139  return 0;
140 }
141 
142 static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
143  u8 pwrst)
144 {
145  u32 m;
146 
147  m = pwrdm->mem_ret_mask[bank];
148  if (!m)
149  return -EINVAL;
150 
151  am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
152  pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
153 
154  return 0;
155 }
156 
157 static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
158 {
159  u32 m, v;
160 
161  m = pwrdm->mem_pwrst_mask[bank];
162  if (!m)
163  return -EINVAL;
164 
165  v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
166  v &= m;
167  v >>= __ffs(m);
168 
169  return v;
170 }
171 
172 static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
173 {
174  u32 m, v;
175 
176  m = pwrdm->mem_retst_mask[bank];
177  if (!m)
178  return -EINVAL;
179 
180  v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
181  v &= m;
182  v >>= __ffs(m);
183 
184  return v;
185 }
186 
187 static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
188 {
189  u32 c = 0;
190 
191  /*
192  * REVISIT: pwrdm_wait_transition() may be better implemented
193  * via a callback and a periodic timer check -- how long do we expect
194  * powerdomain transitions to take?
195  */
196 
197  /* XXX Is this udelay() value meaningful? */
198  while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
200  (c++ < PWRDM_TRANSITION_BAILOUT))
201  udelay(1);
202 
203  if (c > PWRDM_TRANSITION_BAILOUT) {
204  pr_err("powerdomain: %s: waited too long to complete transition\n",
205  pwrdm->name);
206  return -EAGAIN;
207  }
208 
209  pr_debug("powerdomain: completed transition in %d loops\n", c);
210 
211  return 0;
212 }
213 
215  .pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst,
216  .pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst,
217  .pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst,
218  .pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst,
219  .pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst,
220  .pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst,
221  .pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst,
222  .pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst,
223  .pwrdm_set_lowpwrstchange = am33xx_pwrdm_set_lowpwrstchange,
224  .pwrdm_read_mem_pwrst = am33xx_pwrdm_read_mem_pwrst,
225  .pwrdm_read_mem_retst = am33xx_pwrdm_read_mem_retst,
226  .pwrdm_set_mem_onst = am33xx_pwrdm_set_mem_onst,
227  .pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst,
228  .pwrdm_wait_transition = am33xx_pwrdm_wait_transition,
229 };