blob: 6cdf67860cb37af0e80ab9c802a9d74a7bc3a903 [file] [log] [blame]
Rajendra Nayakf327e072010-12-21 20:01:18 -07001/*
2 * OMAP2 and OMAP3 powerdomain control
3 *
4 * Copyright (C) 2009-2010 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 <plat/prcm.h>
19#include "prm.h"
20#include "prm-regbits-34xx.h"
21#include "powerdomains.h"
22
23/* Common functions across OMAP2 and OMAP3 */
24static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
25{
26 prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
27 (pwrst << OMAP_POWERSTATE_SHIFT),
28 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
29 return 0;
30}
31
32static int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
33{
34 return prm_read_mod_bits_shift(pwrdm->prcm_offs,
35 OMAP2_PM_PWSTCTRL, OMAP_POWERSTATE_MASK);
36}
37
38static int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm)
39{
40 return prm_read_mod_bits_shift(pwrdm->prcm_offs,
41 OMAP2_PM_PWSTST, OMAP_POWERSTATEST_MASK);
42}
43
Rajendra Nayak9b7fc902010-12-21 20:01:19 -070044static int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
45 u8 pwrst)
46{
47 u32 m;
48
49 m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
50
51 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
52 OMAP2_PM_PWSTCTRL);
53
54 return 0;
55}
56
57static int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
58 u8 pwrst)
59{
60 u32 m;
61
62 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
63
64 prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
65 OMAP2_PM_PWSTCTRL);
66
67 return 0;
68}
69
70static int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
71{
72 u32 m;
73
74 m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
75
76 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST, m);
77}
78
79static int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
80{
81 u32 m;
82
83 m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
84
85 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL, m);
86}
87
Rajendra Nayak12627572010-12-21 20:01:18 -070088static int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
89{
90 u32 v;
91
92 v = pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE_MASK);
93 prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE_MASK, v,
94 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
95
96 return 0;
97}
98
Rajendra Nayak9b7fc902010-12-21 20:01:19 -070099static int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)
100{
101 u32 c = 0;
102
103 /*
104 * REVISIT: pwrdm_wait_transition() may be better implemented
105 * via a callback and a periodic timer check -- how long do we expect
106 * powerdomain transitions to take?
107 */
108
109 /* XXX Is this udelay() value meaningful? */
110 while ((prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) &
111 OMAP_INTRANSITION_MASK) &&
112 (c++ < PWRDM_TRANSITION_BAILOUT))
113 udelay(1);
114
115 if (c > PWRDM_TRANSITION_BAILOUT) {
116 printk(KERN_ERR "powerdomain: waited too long for "
117 "powerdomain %s to complete transition\n", pwrdm->name);
118 return -EAGAIN;
119 }
120
121 pr_debug("powerdomain: completed transition in %d loops\n", c);
122
123 return 0;
124}
125
Rajendra Nayakf327e072010-12-21 20:01:18 -0700126/* Applicable only for OMAP3. Not supported on OMAP2 */
127static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
128{
129 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
130 OMAP3430_LASTPOWERSTATEENTERED_MASK);
131}
132
Rajendra Nayak12627572010-12-21 20:01:18 -0700133static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
134{
135 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST,
136 OMAP3430_LOGICSTATEST_MASK);
137}
138
139static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
140{
141 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL,
142 OMAP3430_LOGICSTATEST_MASK);
143}
144
145static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
146{
147 return prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST,
148 OMAP3430_LASTLOGICSTATEENTERED_MASK);
149}
150
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700151static int omap3_get_mem_bank_lastmemst_mask(u8 bank)
152{
153 switch (bank) {
154 case 0:
155 return OMAP3430_LASTMEM1STATEENTERED_MASK;
156 case 1:
157 return OMAP3430_LASTMEM2STATEENTERED_MASK;
158 case 2:
159 return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
160 case 3:
161 return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
162 default:
163 WARN_ON(1); /* should never happen */
164 return -EEXIST;
165 }
166 return 0;
167}
168
169static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
170{
171 u32 m;
172
173 m = omap3_get_mem_bank_lastmemst_mask(bank);
174
175 return prm_read_mod_bits_shift(pwrdm->prcm_offs,
176 OMAP3430_PM_PREPWSTST, m);
177}
178
179static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
180{
181 prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
182 return 0;
183}
184
185static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
186{
187 return prm_rmw_mod_reg_bits(0, 1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
188 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
189}
190
191static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
192{
193 return prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT, 0,
194 pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
195}
196
Rajendra Nayakf327e072010-12-21 20:01:18 -0700197struct pwrdm_ops omap2_pwrdm_operations = {
198 .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst,
199 .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst,
200 .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst,
Rajendra Nayak12627572010-12-21 20:01:18 -0700201 .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700202 .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
203 .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
204 .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
205 .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
206 .pwrdm_wait_transition = omap2_pwrdm_wait_transition,
Rajendra Nayakf327e072010-12-21 20:01:18 -0700207};
208
209struct pwrdm_ops omap3_pwrdm_operations = {
210 .pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst,
211 .pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst,
212 .pwrdm_read_pwrst = omap2_pwrdm_read_pwrst,
213 .pwrdm_read_prev_pwrst = omap3_pwrdm_read_prev_pwrst,
Rajendra Nayak12627572010-12-21 20:01:18 -0700214 .pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
215 .pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst,
216 .pwrdm_read_logic_retst = omap3_pwrdm_read_logic_retst,
217 .pwrdm_read_prev_logic_pwrst = omap3_pwrdm_read_prev_logic_pwrst,
Rajendra Nayak9b7fc902010-12-21 20:01:19 -0700218 .pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
219 .pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
220 .pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
221 .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
222 .pwrdm_read_prev_mem_pwrst = omap3_pwrdm_read_prev_mem_pwrst,
223 .pwrdm_clear_all_prev_pwrst = omap3_pwrdm_clear_all_prev_pwrst,
224 .pwrdm_enable_hdwr_sar = omap3_pwrdm_enable_hdwr_sar,
225 .pwrdm_disable_hdwr_sar = omap3_pwrdm_disable_hdwr_sar,
226 .pwrdm_wait_transition = omap2_pwrdm_wait_transition,
Rajendra Nayakf327e072010-12-21 20:01:18 -0700227};