]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/blob - arch/arm/mach-omap2/powerdomain33xx.c
ARM: zynq: add clk binding support to the ttc
[can-eth-gw-linux.git] / arch / arm / mach-omap2 / powerdomain33xx.c
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
7  * <rnayak@ti.com>
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 {
32         am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
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);
43         v &= OMAP_POWERSTATE_MASK;
44         v >>= OMAP_POWERSTATE_SHIFT;
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);
54         v &= OMAP_POWERSTATEST_MASK;
55         v >>= OMAP_POWERSTATEST_SHIFT;
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);
65         v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
66         v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;
67
68         return v;
69 }
70
71 static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
72 {
73         am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
74                                 (1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
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 {
81         am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
82                                 AM33XX_LASTPOWERSTATEENTERED_MASK,
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);
106         v &= AM33XX_LOGICSTATEST_MASK;
107         v >>= AM33XX_LOGICSTATEST_SHIFT;
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)
199                         & OMAP_INTRANSITION_MASK) &&
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
214 struct pwrdm_ops am33xx_pwrdm_operations = {
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 };