blob: 3950ccfe5f4a94a85bb39fcb286e4a582c47de22 [file] [log] [blame]
Rajendra Nayakf327e072010-12-21 20:01:18 -07001/*
2 * OMAP2 and OMAP3 powerdomain control
3 *
Kevin Hilmanaae030f2011-03-23 16:09:41 -07004 * Copyright (C) 2009-2011 Texas Instruments, Inc.
Rajendra Nayakf327e072010-12-21 20:01:18 -07005 * 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>
Tony Lindgrend9a5f4d2012-03-07 17:28:01 -080018#include <linux/bug.h>
Paul Walmsley6e014782010-12-21 20:01:20 -070019
Rajendra Nayakf327e072010-12-21 20:01:18 -070020#include <plat/prcm.h>
Paul Walmsley6e014782010-12-21 20:01:20 -070021
Paul Walmsley72e06d02010-12-21 21:05:16 -070022#include "powerdomain.h"
Paul Walmsley6e014782010-12-21 20:01:20 -070023#include "prm.h"
24#include "prm-regbits-24xx.h"
25#include "prm-regbits-34xx.h"
26
Rajendra Nayakf327e072010-12-21 20:01:18 -070027
28/* Common functions across OMAP2 and OMAP3 */
29static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
30{
Paul Walmsleyc4d7e582010-12-21 21:05:14 -070031 omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
Rajendra Nayakf327e072010-12-21 20:01:18 -070032 (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{
Paul Walmsleyc4d7e582010-12-21 21:05:14 -070039 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
40 OMAP2_PM_PWSTCTRL,
41 OMAP_POWERSTATE_MASK);
Rajendra Nayakf327e072010-12-21 20:01:18 -070042}
43
44static int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm)
45{
Paul Walmsleyc4d7e582010-12-21 21:05:14 -070046 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
47 OMAP2_PM_PWSTST,
48 OMAP_POWERSTATEST_MASK);
Rajendra Nayakf327e072010-12-21 20:01:18 -070049}
50
Rajendra Nayak9b7fc902010-12-21 20:01:19 -070051static 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
Paul Walmsleyc4d7e582010-12-21 21:05:14 -070058 omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
59 OMAP2_PM_PWSTCTRL);
Rajendra Nayak9b7fc902010-12-21 20:01:19 -070060
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
Paul Walmsleyc4d7e582010-12-21 21:05:14 -070071 omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
72 OMAP2_PM_PWSTCTRL);
Rajendra Nayak9b7fc902010-12-21 20:01:19 -070073
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
Paul Walmsleyc4d7e582010-12-21 21:05:14 -070083 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST,
84 m);
Rajendra Nayak9b7fc902010-12-21 20:01:19 -070085}
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
Paul Walmsleyc4d7e582010-12-21 21:05:14 -070093 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
94 OMAP2_PM_PWSTCTRL, m);
Rajendra Nayak9b7fc902010-12-21 20:01:19 -070095}
96
Rajendra Nayak12627572010-12-21 20:01:18 -070097static int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
98{
99 u32 v;
100
101 v = pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE_MASK);
Paul Walmsleyc4d7e582010-12-21 21:05:14 -0700102 omap2_prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE_MASK, v,
103 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
Rajendra Nayak12627572010-12-21 20:01:18 -0700104
105 return 0;
106}
107
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700108static 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? */
Paul Walmsleyc4d7e582010-12-21 21:05:14 -0700119 while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) &
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700120 OMAP_INTRANSITION_MASK) &&
121 (c++ < PWRDM_TRANSITION_BAILOUT))
122 udelay(1);
123
124 if (c > PWRDM_TRANSITION_BAILOUT) {
Paul Walmsley7852ec02012-07-26 00:54:26 -0600125 pr_err("powerdomain: %s: waited too long to complete transition\n",
126 pwrdm->name);
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700127 return -EAGAIN;
128 }
129
130 pr_debug("powerdomain: completed transition in %d loops\n", c);
131
132 return 0;
133}
134
Rajendra Nayakf327e072010-12-21 20:01:18 -0700135/* Applicable only for OMAP3. Not supported on OMAP2 */
136static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
137{
Paul Walmsleyc4d7e582010-12-21 21:05:14 -0700138 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
139 OMAP3430_PM_PREPWSTST,
140 OMAP3430_LASTPOWERSTATEENTERED_MASK);
Rajendra Nayakf327e072010-12-21 20:01:18 -0700141}
142
Rajendra Nayak12627572010-12-21 20:01:18 -0700143static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
144{
Paul Walmsleyc4d7e582010-12-21 21:05:14 -0700145 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
146 OMAP2_PM_PWSTST,
147 OMAP3430_LOGICSTATEST_MASK);
Rajendra Nayak12627572010-12-21 20:01:18 -0700148}
149
150static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
151{
Paul Walmsleyc4d7e582010-12-21 21:05:14 -0700152 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
153 OMAP2_PM_PWSTCTRL,
154 OMAP3430_LOGICSTATEST_MASK);
Rajendra Nayak12627572010-12-21 20:01:18 -0700155}
156
157static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
158{
Paul Walmsleyc4d7e582010-12-21 21:05:14 -0700159 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
160 OMAP3430_PM_PREPWSTST,
161 OMAP3430_LASTLOGICSTATEENTERED_MASK);
Rajendra Nayak12627572010-12-21 20:01:18 -0700162}
163
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700164static 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
Paul Walmsleyc4d7e582010-12-21 21:05:14 -0700188 return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700189 OMAP3430_PM_PREPWSTST, m);
190}
191
192static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
193{
Paul Walmsleyc4d7e582010-12-21 21:05:14 -0700194 omap2_prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700195 return 0;
196}
197
198static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
199{
Paul Walmsleyc4d7e582010-12-21 21:05:14 -0700200 return omap2_prm_rmw_mod_reg_bits(0,
201 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
202 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700203}
204
205static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
206{
Paul Walmsleyc4d7e582010-12-21 21:05:14 -0700207 return omap2_prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
208 0, pwrdm->prcm_offs,
209 OMAP2_PM_PWSTCTRL);
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700210}
211
Rajendra Nayakf327e072010-12-21 20:01:18 -0700212struct 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,
Rajendra Nayak12627572010-12-21 20:01:18 -0700216 .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700217 .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,
Rajendra Nayakf327e072010-12-21 20:01:18 -0700222};
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,
Rajendra Nayak12627572010-12-21 20:01:18 -0700229 .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,
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700233 .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,
Rajendra Nayakf327e072010-12-21 20:01:18 -0700242};