aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2012-10-21 03:01:10 -0400
committerPaul Walmsley <paul@pwsan.com>2012-10-21 03:01:10 -0400
commit498153995b9ff41279be54fc56facb92f5cad793 (patch)
tree82736e204351bcd198d5dcec3c41deeab1b6779f
parent139563ad27e7baad7935b8113940f0d804cf513b (diff)
ARM: OMAP2+: powerdomain/PRM: move the low-level powerdomain functions into PRM
Move the low-level SoC-specific powerdomain control functions into prm*.c. For example, OMAP2xxx low-level powerdomain functions go into prm2xxx.c. Then remove the unnecessary powerdomain*xxx*.c files. The objective is to centralize low-level PRM register accesses into the prm*.[ch] files, and then to export an OMAP SoC-independent API to higher-level OMAP power management code. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Rajendra Nayak <rnayak@ti.com> Cc: Vaibhav Hiremath <hvaibhav@ti.com> Acked-by: Rajendra Nayak <rnayak@ti.com> Reviewed-by: Russ Dill <Russ.Dill@ti.com> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
-rw-r--r--arch/arm/mach-omap2/Makefile1
-rw-r--r--arch/arm/mach-omap2/powerdomain2xxx_3xxx.c242
-rw-r--r--arch/arm/mach-omap2/powerdomain33xx.c229
-rw-r--r--arch/arm/mach-omap2/powerdomain44xx.c285
-rw-r--r--arch/arm/mach-omap2/prm2xxx.c41
-rw-r--r--arch/arm/mach-omap2/prm2xxx_3xxx.c112
-rw-r--r--arch/arm/mach-omap2/prm2xxx_3xxx.h13
-rw-r--r--arch/arm/mach-omap2/prm33xx.c202
-rw-r--r--arch/arm/mach-omap2/prm3xxx.c107
-rw-r--r--arch/arm/mach-omap2/prm44xx.c265
10 files changed, 739 insertions, 758 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 20849604be94..7404e3d48cea 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -95,6 +95,7 @@ endif
95# PRCM 95# PRCM
96obj-y += prcm.o prm_common.o 96obj-y += prcm.o prm_common.o
97obj-$(CONFIG_ARCH_OMAP2) += cm2xxx_3xxx.o prm2xxx_3xxx.o 97obj-$(CONFIG_ARCH_OMAP2) += cm2xxx_3xxx.o prm2xxx_3xxx.o
98obj-$(CONFIG_ARCH_OMAP2) += prm2xxx.o
98obj-$(CONFIG_ARCH_OMAP3) += cm2xxx_3xxx.o prm2xxx_3xxx.o 99obj-$(CONFIG_ARCH_OMAP3) += cm2xxx_3xxx.o prm2xxx_3xxx.o
99obj-$(CONFIG_ARCH_OMAP3) += prm3xxx.o 100obj-$(CONFIG_ARCH_OMAP3) += prm3xxx.o
100obj-$(CONFIG_ARCH_OMAP3) += vc3xxx_data.o vp3xxx_data.o 101obj-$(CONFIG_ARCH_OMAP3) += vc3xxx_data.o vp3xxx_data.o
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
deleted file mode 100644
index 3950ccfe5f4a..000000000000
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ /dev/null
@@ -1,242 +0,0 @@
1/*
2 * OMAP2 and OMAP3 powerdomain control
3 *
4 * Copyright (C) 2009-2011 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 <plat/prcm.h>
21
22#include "powerdomain.h"
23#include "prm.h"
24#include "prm-regbits-24xx.h"
25#include "prm-regbits-34xx.h"
26
27
28/* Common functions across OMAP2 and OMAP3 */
29static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
30{
31 omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
32 (pwrst << OMAP_POWERSTATE_SHIFT),
33 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
34 return 0;
35}
36
37static int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
38{
39 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
40 OMAP2_PM_PWSTCTRL,
41 OMAP_POWERSTATE_MASK);
42}
43
44static int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm)
45{
46 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
47 OMAP2_PM_PWSTST,
48 OMAP_POWERSTATEST_MASK);
49}
50
51static int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
52 u8 pwrst)
53{
54 u32 m;
55
56 m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
57
58 omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
59 OMAP2_PM_PWSTCTRL);
60
61 return 0;
62}
63
64static int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
65 u8 pwrst)
66{
67 u32 m;
68
69 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
70
71 omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
72 OMAP2_PM_PWSTCTRL);
73
74 return 0;
75}
76
77static int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
78{
79 u32 m;
80
81 m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
82
83 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST,
84 m);
85}
86
87static int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
88{
89 u32 m;
90
91 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
92
93 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
94 OMAP2_PM_PWSTCTRL, m);
95}
96
97static int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
98{
99 u32 v;
100
101 v = pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE_MASK);
102 omap2_prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE_MASK, v,
103 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
104
105 return 0;
106}
107
108static int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)
109{
110 u32 c = 0;
111
112 /*
113 * REVISIT: pwrdm_wait_transition() may be better implemented
114 * via a callback and a periodic timer check -- how long do we expect
115 * powerdomain transitions to take?
116 */
117
118 /* XXX Is this udelay() value meaningful? */
119 while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) &
120 OMAP_INTRANSITION_MASK) &&
121 (c++ < PWRDM_TRANSITION_BAILOUT))
122 udelay(1);
123
124 if (c > PWRDM_TRANSITION_BAILOUT) {
125 pr_err("powerdomain: %s: waited too long to complete transition\n",
126 pwrdm->name);
127 return -EAGAIN;
128 }
129
130 pr_debug("powerdomain: completed transition in %d loops\n", c);
131
132 return 0;
133}
134
135/* Applicable only for OMAP3. Not supported on OMAP2 */
136static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
137{
138 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
139 OMAP3430_PM_PREPWSTST,
140 OMAP3430_LASTPOWERSTATEENTERED_MASK);
141}
142
143static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
144{
145 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
146 OMAP2_PM_PWSTST,
147 OMAP3430_LOGICSTATEST_MASK);
148}
149
150static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
151{
152 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
153 OMAP2_PM_PWSTCTRL,
154 OMAP3430_LOGICSTATEST_MASK);
155}
156
157static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
158{
159 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
160 OMAP3430_PM_PREPWSTST,
161 OMAP3430_LASTLOGICSTATEENTERED_MASK);
162}
163
164static int omap3_get_mem_bank_lastmemst_mask(u8 bank)
165{
166 switch (bank) {
167 case 0:
168 return OMAP3430_LASTMEM1STATEENTERED_MASK;
169 case 1:
170 return OMAP3430_LASTMEM2STATEENTERED_MASK;
171 case 2:
172 return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
173 case 3:
174 return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
175 default:
176 WARN_ON(1); /* should never happen */
177 return -EEXIST;
178 }
179 return 0;
180}
181
182static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
183{
184 u32 m;
185
186 m = omap3_get_mem_bank_lastmemst_mask(bank);
187
188 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
189 OMAP3430_PM_PREPWSTST, m);
190}
191
192static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
193{
194 omap2_prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
195 return 0;
196}
197
198static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
199{
200 return omap2_prm_rmw_mod_reg_bits(0,
201 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
202 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
203}
204
205static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
206{
207 return omap2_prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
208 0, pwrdm->prcm_offs,
209 OMAP2_PM_PWSTCTRL);
210}
211
212struct pwrdm_ops omap2_pwrdm_operations = {
213 .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst,
214 .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst,
215 .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst,
216 .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
217 .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
218 .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
219 .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
220 .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
221 .pwrdm_wait_transition = omap2_pwrdm_wait_transition,
222};
223
224struct pwrdm_ops omap3_pwrdm_operations = {
225 .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst,
226 .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst,
227 .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst,
228 .pwrdm_read_prev_pwrst = omap3_pwrdm_read_prev_pwrst,
229 .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
230 .pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst,
231 .pwrdm_read_logic_retst = omap3_pwrdm_read_logic_retst,
232 .pwrdm_read_prev_logic_pwrst = omap3_pwrdm_read_prev_logic_pwrst,
233 .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
234 .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
235 .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
236 .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
237 .pwrdm_read_prev_mem_pwrst = omap3_pwrdm_read_prev_mem_pwrst,
238 .pwrdm_clear_all_prev_pwrst = omap3_pwrdm_clear_all_prev_pwrst,
239 .pwrdm_enable_hdwr_sar = omap3_pwrdm_enable_hdwr_sar,
240 .pwrdm_disable_hdwr_sar = omap3_pwrdm_disable_hdwr_sar,
241 .pwrdm_wait_transition = omap2_pwrdm_wait_transition,
242};
diff --git a/arch/arm/mach-omap2/powerdomain33xx.c b/arch/arm/mach-omap2/powerdomain33xx.c
deleted file mode 100644
index 67c5663899b6..000000000000
--- a/arch/arm/mach-omap2/powerdomain33xx.c
+++ /dev/null
@@ -1,229 +0,0 @@
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
30static 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
38static 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
49static 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
60static 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
71static 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
79static 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
87static 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
101static 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
112static 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
127static 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
142static 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
157static 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
172static 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
187static 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
214struct 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};
diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
deleted file mode 100644
index aceb4f464c9b..000000000000
--- a/arch/arm/mach-omap2/powerdomain44xx.c
+++ /dev/null
@@ -1,285 +0,0 @@
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 <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
27static 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
36static 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
48static 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
60static 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
72static 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
81static 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
90static 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
102static 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
116static 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
130static 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
142static 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/**
155 * omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate
156 * @pwrdm: struct powerdomain * to read the state for
157 *
158 * Reads the previous logic powerstate for a powerdomain. This
159 * function must determine the previous logic powerstate by first
160 * checking the previous powerstate for the domain. If that was OFF,
161 * then logic has been lost. If previous state was RETENTION, the
162 * function reads the setting for the next retention logic state to
163 * see the actual value. In every other case, the logic is
164 * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
165 * depending whether the logic was retained or not.
166 */
167static 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
182static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
183{
184 u32 m, v;
185
186 m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
187
188 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
189 OMAP4_PM_PWSTST);
190 v &= m;
191 v >>= __ffs(m);
192
193 return v;
194}
195
196static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
197{
198 u32 m, v;
199
200 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
201
202 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
203 OMAP4_PM_PWSTCTRL);
204 v &= m;
205 v >>= __ffs(m);
206
207 return v;
208}
209
210/**
211 * omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate
212 * @pwrdm: struct powerdomain * to read mem powerstate for
213 * @bank: memory bank index
214 *
215 * Reads the previous memory powerstate for a powerdomain. This
216 * function must determine the previous memory powerstate by first
217 * checking the previous powerstate for the domain. If that was OFF,
218 * then logic has been lost. If previous state was RETENTION, the
219 * function reads the setting for the next memory retention state to
220 * see the actual value. In every other case, the logic is
221 * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
222 * depending whether logic was retained or not.
223 */
224static 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
239static 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? */
250 while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
251 pwrdm->prcm_offs,
252 OMAP4_PM_PWSTST) &
253 OMAP_INTRANSITION_MASK) &&
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
268struct pwrdm_ops omap4_pwrdm_operations = {
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};
diff --git a/arch/arm/mach-omap2/prm2xxx.c b/arch/arm/mach-omap2/prm2xxx.c
new file mode 100644
index 000000000000..218ef6a1f11e
--- /dev/null
+++ b/arch/arm/mach-omap2/prm2xxx.c
@@ -0,0 +1,41 @@
1/*
2 * OMAP2xxx PRM module functions
3 *
4 * Copyright (C) 2010-2012 Texas Instruments, Inc.
5 * Copyright (C) 2010 Nokia Corporation
6 * Benoît Cousson
7 * 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/kernel.h>
16#include <linux/errno.h>
17#include <linux/err.h>
18#include <linux/io.h>
19#include <linux/irq.h>
20
21#include "common.h"
22#include <plat/cpu.h>
23#include <plat/prcm.h>
24
25#include "vp.h"
26#include "powerdomain.h"
27#include "prm2xxx.h"
28#include "cm2xxx_3xxx.h"
29#include "prm-regbits-24xx.h"
30
31struct pwrdm_ops omap2_pwrdm_operations = {
32 .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst,
33 .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst,
34 .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst,
35 .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
36 .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
37 .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
38 .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
39 .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
40 .pwrdm_wait_transition = omap2_pwrdm_wait_transition,
41};
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
index 0d6cc543987d..bdddf5ca67c4 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c
@@ -17,7 +17,7 @@
17#include <linux/io.h> 17#include <linux/io.h>
18 18
19#include "common.h" 19#include "common.h"
20 20#include "powerdomain.h"
21#include "prm2xxx_3xxx.h" 21#include "prm2xxx_3xxx.h"
22#include "prm-regbits-24xx.h" 22#include "prm-regbits-24xx.h"
23 23
@@ -98,3 +98,113 @@ int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
98 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; 98 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
99} 99}
100 100
101
102/* Powerdomain low-level functions */
103
104/* Common functions across OMAP2 and OMAP3 */
105int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
106{
107 omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
108 (pwrst << OMAP_POWERSTATE_SHIFT),
109 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
110 return 0;
111}
112
113int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
114{
115 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
116 OMAP2_PM_PWSTCTRL,
117 OMAP_POWERSTATE_MASK);
118}
119
120int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm)
121{
122 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
123 OMAP2_PM_PWSTST,
124 OMAP_POWERSTATEST_MASK);
125}
126
127int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
128 u8 pwrst)
129{
130 u32 m;
131
132 m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
133
134 omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
135 OMAP2_PM_PWSTCTRL);
136
137 return 0;
138}
139
140int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
141 u8 pwrst)
142{
143 u32 m;
144
145 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
146
147 omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
148 OMAP2_PM_PWSTCTRL);
149
150 return 0;
151}
152
153int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
154{
155 u32 m;
156
157 m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
158
159 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST,
160 m);
161}
162
163int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
164{
165 u32 m;
166
167 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
168
169 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
170 OMAP2_PM_PWSTCTRL, m);
171}
172
173int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
174{
175 u32 v;
176
177 v = pwrst << __ffs(OMAP_LOGICRETSTATE_MASK);
178 omap2_prm_rmw_mod_reg_bits(OMAP_LOGICRETSTATE_MASK, v, pwrdm->prcm_offs,
179 OMAP2_PM_PWSTCTRL);
180
181 return 0;
182}
183
184int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)
185{
186 u32 c = 0;
187
188 /*
189 * REVISIT: pwrdm_wait_transition() may be better implemented
190 * via a callback and a periodic timer check -- how long do we expect
191 * powerdomain transitions to take?
192 */
193
194 /* XXX Is this udelay() value meaningful? */
195 while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) &
196 OMAP_INTRANSITION_MASK) &&
197 (c++ < PWRDM_TRANSITION_BAILOUT))
198 udelay(1);
199
200 if (c > PWRDM_TRANSITION_BAILOUT) {
201 pr_err("powerdomain: %s: waited too long to complete transition\n",
202 pwrdm->name);
203 return -EAGAIN;
204 }
205
206 pr_debug("powerdomain: completed transition in %d loops\n", c);
207
208 return 0;
209}
210
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h
index 8d09a1ac9311..706b0262f3f0 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h
@@ -50,6 +50,7 @@
50#ifndef __ASSEMBLER__ 50#ifndef __ASSEMBLER__
51 51
52#include <linux/io.h> 52#include <linux/io.h>
53#include "powerdomain.h"
53 54
54/* Power/reset management domain register get/set */ 55/* Power/reset management domain register get/set */
55static inline u32 omap2_prm_read_mod_reg(s16 module, u16 idx) 56static inline u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
@@ -103,6 +104,18 @@ extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
103extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift); 104extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
104extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift); 105extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
105 106
107extern int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
108extern int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
109extern int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm);
110extern int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
111 u8 pwrst);
112extern int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
113 u8 pwrst);
114extern int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
115extern int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank);
116extern int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
117extern int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm);
118
106#endif /* __ASSEMBLER */ 119#endif /* __ASSEMBLER */
107 120
108/* 121/*
diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c
index e7dbb6cf1255..3417dd3a7c37 100644
--- a/arch/arm/mach-omap2/prm33xx.c
+++ b/arch/arm/mach-omap2/prm33xx.c
@@ -22,6 +22,7 @@
22#include <plat/common.h> 22#include <plat/common.h>
23 23
24#include "common.h" 24#include "common.h"
25#include "powerdomain.h"
25#include "prm33xx.h" 26#include "prm33xx.h"
26#include "prm-regbits-33xx.h" 27#include "prm-regbits-33xx.h"
27 28
@@ -133,3 +134,204 @@ int am33xx_prm_deassert_hardreset(u8 shift, s16 inst,
133 134
134 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0; 135 return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
135} 136}
137
138static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
139{
140 am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
141 (pwrst << OMAP_POWERSTATE_SHIFT),
142 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
143 return 0;
144}
145
146static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
147{
148 u32 v;
149
150 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
151 v &= OMAP_POWERSTATE_MASK;
152 v >>= OMAP_POWERSTATE_SHIFT;
153
154 return v;
155}
156
157static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
158{
159 u32 v;
160
161 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
162 v &= OMAP_POWERSTATEST_MASK;
163 v >>= OMAP_POWERSTATEST_SHIFT;
164
165 return v;
166}
167
168static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
169{
170 u32 v;
171
172 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
173 v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
174 v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;
175
176 return v;
177}
178
179static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
180{
181 am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
182 (1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
183 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
184 return 0;
185}
186
187static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
188{
189 am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
190 AM33XX_LASTPOWERSTATEENTERED_MASK,
191 pwrdm->prcm_offs, pwrdm->pwrstst_offs);
192 return 0;
193}
194
195static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
196{
197 u32 m;
198
199 m = pwrdm->logicretstate_mask;
200 if (!m)
201 return -EINVAL;
202
203 am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
204 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
205
206 return 0;
207}
208
209static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
210{
211 u32 v;
212
213 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
214 v &= AM33XX_LOGICSTATEST_MASK;
215 v >>= AM33XX_LOGICSTATEST_SHIFT;
216
217 return v;
218}
219
220static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
221{
222 u32 v, m;
223
224 m = pwrdm->logicretstate_mask;
225 if (!m)
226 return -EINVAL;
227
228 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
229 v &= m;
230 v >>= __ffs(m);
231
232 return v;
233}
234
235static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
236 u8 pwrst)
237{
238 u32 m;
239
240 m = pwrdm->mem_on_mask[bank];
241 if (!m)
242 return -EINVAL;
243
244 am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
245 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
246
247 return 0;
248}
249
250static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
251 u8 pwrst)
252{
253 u32 m;
254
255 m = pwrdm->mem_ret_mask[bank];
256 if (!m)
257 return -EINVAL;
258
259 am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
260 pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
261
262 return 0;
263}
264
265static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
266{
267 u32 m, v;
268
269 m = pwrdm->mem_pwrst_mask[bank];
270 if (!m)
271 return -EINVAL;
272
273 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
274 v &= m;
275 v >>= __ffs(m);
276
277 return v;
278}
279
280static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
281{
282 u32 m, v;
283
284 m = pwrdm->mem_retst_mask[bank];
285 if (!m)
286 return -EINVAL;
287
288 v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
289 v &= m;
290 v >>= __ffs(m);
291
292 return v;
293}
294
295static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
296{
297 u32 c = 0;
298
299 /*
300 * REVISIT: pwrdm_wait_transition() may be better implemented
301 * via a callback and a periodic timer check -- how long do we expect
302 * powerdomain transitions to take?
303 */
304
305 /* XXX Is this udelay() value meaningful? */
306 while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
307 & OMAP_INTRANSITION_MASK) &&
308 (c++ < PWRDM_TRANSITION_BAILOUT))
309 udelay(1);
310
311 if (c > PWRDM_TRANSITION_BAILOUT) {
312 pr_err("powerdomain: %s: waited too long to complete transition\n",
313 pwrdm->name);
314 return -EAGAIN;
315 }
316
317 pr_debug("powerdomain: completed transition in %d loops\n", c);
318
319 return 0;
320}
321
322struct pwrdm_ops am33xx_pwrdm_operations = {
323 .pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst,
324 .pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst,
325 .pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst,
326 .pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst,
327 .pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst,
328 .pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst,
329 .pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst,
330 .pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst,
331 .pwrdm_set_lowpwrstchange = am33xx_pwrdm_set_lowpwrstchange,
332 .pwrdm_read_mem_pwrst = am33xx_pwrdm_read_mem_pwrst,
333 .pwrdm_read_mem_retst = am33xx_pwrdm_read_mem_retst,
334 .pwrdm_set_mem_onst = am33xx_pwrdm_set_mem_onst,
335 .pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst,
336 .pwrdm_wait_transition = am33xx_pwrdm_wait_transition,
337};
diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c
index 88f7d8de7da9..e276ff270ac5 100644
--- a/arch/arm/mach-omap2/prm3xxx.c
+++ b/arch/arm/mach-omap2/prm3xxx.c
@@ -5,6 +5,7 @@
5 * Copyright (C) 2010 Nokia Corporation 5 * Copyright (C) 2010 Nokia Corporation
6 * Benoît Cousson 6 * Benoît Cousson
7 * Paul Walmsley 7 * Paul Walmsley
8 * Rajendra Nayak <rnayak@ti.com>
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
@@ -22,8 +23,9 @@
22#include <plat/prcm.h> 23#include <plat/prcm.h>
23 24
24#include "vp.h" 25#include "vp.h"
25 26#include "powerdomain.h"
26#include "prm3xxx.h" 27#include "prm3xxx.h"
28#include "prm2xxx_3xxx.h"
27#include "cm2xxx_3xxx.h" 29#include "cm2xxx_3xxx.h"
28#include "prm-regbits-34xx.h" 30#include "prm-regbits-34xx.h"
29 31
@@ -215,6 +217,109 @@ static void __init omap3xxx_prm_enable_io_wakeup(void)
215 PM_WKEN); 217 PM_WKEN);
216} 218}
217 219
220/* Powerdomain low-level functions */
221
222/* Applicable only for OMAP3. Not supported on OMAP2 */
223static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
224{
225 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
226 OMAP3430_PM_PREPWSTST,
227 OMAP3430_LASTPOWERSTATEENTERED_MASK);
228}
229
230static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
231{
232 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
233 OMAP2_PM_PWSTST,
234 OMAP3430_LOGICSTATEST_MASK);
235}
236
237static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
238{
239 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
240 OMAP2_PM_PWSTCTRL,
241 OMAP3430_LOGICSTATEST_MASK);
242}
243
244static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
245{
246 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
247 OMAP3430_PM_PREPWSTST,
248 OMAP3430_LASTLOGICSTATEENTERED_MASK);
249}
250
251static int omap3_get_mem_bank_lastmemst_mask(u8 bank)
252{
253 switch (bank) {
254 case 0:
255 return OMAP3430_LASTMEM1STATEENTERED_MASK;
256 case 1:
257 return OMAP3430_LASTMEM2STATEENTERED_MASK;
258 case 2:
259 return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
260 case 3:
261 return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
262 default:
263 WARN_ON(1); /* should never happen */
264 return -EEXIST;
265 }
266 return 0;
267}
268
269static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
270{
271 u32 m;
272
273 m = omap3_get_mem_bank_lastmemst_mask(bank);
274
275 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
276 OMAP3430_PM_PREPWSTST, m);
277}
278
279static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
280{
281 omap2_prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
282 return 0;
283}
284
285static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
286{
287 return omap2_prm_rmw_mod_reg_bits(0,
288 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
289 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
290}
291
292static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
293{
294 return omap2_prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
295 0, pwrdm->prcm_offs,
296 OMAP2_PM_PWSTCTRL);
297}
298
299struct pwrdm_ops omap3_pwrdm_operations = {
300 .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst,
301 .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst,
302 .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst,
303 .pwrdm_read_prev_pwrst = omap3_pwrdm_read_prev_pwrst,
304 .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
305 .pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst,
306 .pwrdm_read_logic_retst = omap3_pwrdm_read_logic_retst,
307 .pwrdm_read_prev_logic_pwrst = omap3_pwrdm_read_prev_logic_pwrst,
308 .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
309 .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
310 .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
311 .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
312 .pwrdm_read_prev_mem_pwrst = omap3_pwrdm_read_prev_mem_pwrst,
313 .pwrdm_clear_all_prev_pwrst = omap3_pwrdm_clear_all_prev_pwrst,
314 .pwrdm_enable_hdwr_sar = omap3_pwrdm_enable_hdwr_sar,
315 .pwrdm_disable_hdwr_sar = omap3_pwrdm_disable_hdwr_sar,
316 .pwrdm_wait_transition = omap2_pwrdm_wait_transition,
317};
318
319/*
320 *
321 */
322
218static int __init omap3xxx_prm_init(void) 323static int __init omap3xxx_prm_init(void)
219{ 324{
220 int ret; 325 int ret;
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index 06bb67910a31..48d91930796d 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -5,6 +5,7 @@
5 * Copyright (C) 2010 Nokia Corporation 5 * Copyright (C) 2010 Nokia Corporation
6 * Benoît Cousson 6 * Benoît Cousson
7 * Paul Walmsley 7 * Paul Walmsley
8 * Rajendra Nayak <rnayak@ti.com>
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
@@ -27,6 +28,7 @@
27#include "prm-regbits-44xx.h" 28#include "prm-regbits-44xx.h"
28#include "prcm44xx.h" 29#include "prcm44xx.h"
29#include "prminst44xx.h" 30#include "prminst44xx.h"
31#include "powerdomain.h"
30 32
31static const struct omap_prcm_irq omap4_prcm_irqs[] = { 33static const struct omap_prcm_irq omap4_prcm_irqs[] = {
32 OMAP_PRCM_IRQ("wkup", 0, 0), 34 OMAP_PRCM_IRQ("wkup", 0, 0),
@@ -291,6 +293,269 @@ static void __init omap44xx_prm_enable_io_wakeup(void)
291 OMAP4_PRM_IO_PMCTRL_OFFSET); 293 OMAP4_PRM_IO_PMCTRL_OFFSET);
292} 294}
293 295
296/* Powerdomain low-level functions */
297
298static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
299{
300 omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK,
301 (pwrst << OMAP_POWERSTATE_SHIFT),
302 pwrdm->prcm_partition,
303 pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
304 return 0;
305}
306
307static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
308{
309 u32 v;
310
311 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
312 OMAP4_PM_PWSTCTRL);
313 v &= OMAP_POWERSTATE_MASK;
314 v >>= OMAP_POWERSTATE_SHIFT;
315
316 return v;
317}
318
319static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm)
320{
321 u32 v;
322
323 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
324 OMAP4_PM_PWSTST);
325 v &= OMAP_POWERSTATEST_MASK;
326 v >>= OMAP_POWERSTATEST_SHIFT;
327
328 return v;
329}
330
331static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
332{
333 u32 v;
334
335 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
336 OMAP4_PM_PWSTST);
337 v &= OMAP4430_LASTPOWERSTATEENTERED_MASK;
338 v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
339
340 return v;
341}
342
343static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
344{
345 omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
346 (1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
347 pwrdm->prcm_partition,
348 pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
349 return 0;
350}
351
352static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
353{
354 omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK,
355 OMAP4430_LASTPOWERSTATEENTERED_MASK,
356 pwrdm->prcm_partition,
357 pwrdm->prcm_offs, OMAP4_PM_PWSTST);
358 return 0;
359}
360
361static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
362{
363 u32 v;
364
365 v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK);
366 omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v,
367 pwrdm->prcm_partition, pwrdm->prcm_offs,
368 OMAP4_PM_PWSTCTRL);
369
370 return 0;
371}
372
373static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
374 u8 pwrst)
375{
376 u32 m;
377
378 m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
379
380 omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
381 pwrdm->prcm_partition, pwrdm->prcm_offs,
382 OMAP4_PM_PWSTCTRL);
383
384 return 0;
385}
386
387static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
388 u8 pwrst)
389{
390 u32 m;
391
392 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
393
394 omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
395 pwrdm->prcm_partition, pwrdm->prcm_offs,
396 OMAP4_PM_PWSTCTRL);
397
398 return 0;
399}
400
401static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
402{
403 u32 v;
404
405 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
406 OMAP4_PM_PWSTST);
407 v &= OMAP4430_LOGICSTATEST_MASK;
408 v >>= OMAP4430_LOGICSTATEST_SHIFT;
409
410 return v;
411}
412
413static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
414{
415 u32 v;
416
417 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
418 OMAP4_PM_PWSTCTRL);
419 v &= OMAP4430_LOGICRETSTATE_MASK;
420 v >>= OMAP4430_LOGICRETSTATE_SHIFT;
421
422 return v;
423}
424
425/**
426 * omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate
427 * @pwrdm: struct powerdomain * to read the state for
428 *
429 * Reads the previous logic powerstate for a powerdomain. This
430 * function must determine the previous logic powerstate by first
431 * checking the previous powerstate for the domain. If that was OFF,
432 * then logic has been lost. If previous state was RETENTION, the
433 * function reads the setting for the next retention logic state to
434 * see the actual value. In every other case, the logic is
435 * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
436 * depending whether the logic was retained or not.
437 */
438static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
439{
440 int state;
441
442 state = omap4_pwrdm_read_prev_pwrst(pwrdm);
443
444 if (state == PWRDM_POWER_OFF)
445 return PWRDM_POWER_OFF;
446
447 if (state != PWRDM_POWER_RET)
448 return PWRDM_POWER_RET;
449
450 return omap4_pwrdm_read_logic_retst(pwrdm);
451}
452
453static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
454{
455 u32 m, v;
456
457 m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
458
459 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
460 OMAP4_PM_PWSTST);
461 v &= m;
462 v >>= __ffs(m);
463
464 return v;
465}
466
467static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
468{
469 u32 m, v;
470
471 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
472
473 v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
474 OMAP4_PM_PWSTCTRL);
475 v &= m;
476 v >>= __ffs(m);
477
478 return v;
479}
480
481/**
482 * omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate
483 * @pwrdm: struct powerdomain * to read mem powerstate for
484 * @bank: memory bank index
485 *
486 * Reads the previous memory powerstate for a powerdomain. This
487 * function must determine the previous memory powerstate by first
488 * checking the previous powerstate for the domain. If that was OFF,
489 * then logic has been lost. If previous state was RETENTION, the
490 * function reads the setting for the next memory retention state to
491 * see the actual value. In every other case, the logic is
492 * retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
493 * depending whether logic was retained or not.
494 */
495static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
496{
497 int state;
498
499 state = omap4_pwrdm_read_prev_pwrst(pwrdm);
500
501 if (state == PWRDM_POWER_OFF)
502 return PWRDM_POWER_OFF;
503
504 if (state != PWRDM_POWER_RET)
505 return PWRDM_POWER_RET;
506
507 return omap4_pwrdm_read_mem_retst(pwrdm, bank);
508}
509
510static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
511{
512 u32 c = 0;
513
514 /*
515 * REVISIT: pwrdm_wait_transition() may be better implemented
516 * via a callback and a periodic timer check -- how long do we expect
517 * powerdomain transitions to take?
518 */
519
520 /* XXX Is this udelay() value meaningful? */
521 while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
522 pwrdm->prcm_offs,
523 OMAP4_PM_PWSTST) &
524 OMAP_INTRANSITION_MASK) &&
525 (c++ < PWRDM_TRANSITION_BAILOUT))
526 udelay(1);
527
528 if (c > PWRDM_TRANSITION_BAILOUT) {
529 pr_err("powerdomain: %s: waited too long to complete transition\n",
530 pwrdm->name);
531 return -EAGAIN;
532 }
533
534 pr_debug("powerdomain: completed transition in %d loops\n", c);
535
536 return 0;
537}
538
539struct pwrdm_ops omap4_pwrdm_operations = {
540 .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst,
541 .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst,
542 .pwrdm_read_pwrst = omap4_pwrdm_read_pwrst,
543 .pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst,
544 .pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange,
545 .pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst,
546 .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst,
547 .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst,
548 .pwrdm_read_prev_logic_pwrst = omap4_pwrdm_read_prev_logic_pwrst,
549 .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst,
550 .pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst,
551 .pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst,
552 .pwrdm_read_prev_mem_pwrst = omap4_pwrdm_read_prev_mem_pwrst,
553 .pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst,
554 .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst,
555 .pwrdm_wait_transition = omap4_pwrdm_wait_transition,
556};
557
558
294static int __init omap4xxx_prm_init(void) 559static int __init omap4xxx_prm_init(void)
295{ 560{
296 if (!cpu_is_omap44xx()) 561 if (!cpu_is_omap44xx())