• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * OMAP4 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 <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 
omap4_pwrdm_set_next_pwrst(struct powerdomain * pwrdm,u8 pwrst)27 static 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 
omap4_pwrdm_read_next_pwrst(struct powerdomain * pwrdm)36 static 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 
omap4_pwrdm_read_pwrst(struct powerdomain * pwrdm)48 static 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 
omap4_pwrdm_read_prev_pwrst(struct powerdomain * pwrdm)60 static 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 
omap4_pwrdm_set_lowpwrstchange(struct powerdomain * pwrdm)72 static 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 
omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain * pwrdm)81 static 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 
omap4_pwrdm_set_logic_retst(struct powerdomain * pwrdm,u8 pwrst)90 static 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 
omap4_pwrdm_set_mem_onst(struct powerdomain * pwrdm,u8 bank,u8 pwrst)102 static 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 
omap4_pwrdm_set_mem_retst(struct powerdomain * pwrdm,u8 bank,u8 pwrst)116 static 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 
omap4_pwrdm_read_logic_pwrst(struct powerdomain * pwrdm)130 static 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 
omap4_pwrdm_read_logic_retst(struct powerdomain * pwrdm)142 static 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 
omap4_pwrdm_read_mem_pwrst(struct powerdomain * pwrdm,u8 bank)154 static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
155 {
156 	u32 m, v;
157 
158 	m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
159 
160 	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
161 					OMAP4_PM_PWSTST);
162 	v &= m;
163 	v >>= __ffs(m);
164 
165 	return v;
166 }
167 
omap4_pwrdm_read_mem_retst(struct powerdomain * pwrdm,u8 bank)168 static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
169 {
170 	u32 m, v;
171 
172 	m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
173 
174 	v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
175 					OMAP4_PM_PWSTCTRL);
176 	v &= m;
177 	v >>= __ffs(m);
178 
179 	return v;
180 }
181 
omap4_pwrdm_wait_transition(struct powerdomain * pwrdm)182 static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
183 {
184 	u32 c = 0;
185 
186 	/*
187 	 * REVISIT: pwrdm_wait_transition() may be better implemented
188 	 * via a callback and a periodic timer check -- how long do we expect
189 	 * powerdomain transitions to take?
190 	 */
191 
192 	/* XXX Is this udelay() value meaningful? */
193 	while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
194 					    pwrdm->prcm_offs,
195 					    OMAP4_PM_PWSTST) &
196 		OMAP_INTRANSITION_MASK) &&
197 	       (c++ < PWRDM_TRANSITION_BAILOUT))
198 		udelay(1);
199 
200 	if (c > PWRDM_TRANSITION_BAILOUT) {
201 		printk(KERN_ERR "powerdomain: waited too long for "
202 		       "powerdomain %s to complete transition\n", pwrdm->name);
203 		return -EAGAIN;
204 	}
205 
206 	pr_debug("powerdomain: completed transition in %d loops\n", c);
207 
208 	return 0;
209 }
210 
211 struct pwrdm_ops omap4_pwrdm_operations = {
212 	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
213 	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
214 	.pwrdm_read_pwrst	= omap4_pwrdm_read_pwrst,
215 	.pwrdm_read_prev_pwrst	= omap4_pwrdm_read_prev_pwrst,
216 	.pwrdm_set_lowpwrstchange	= omap4_pwrdm_set_lowpwrstchange,
217 	.pwrdm_clear_all_prev_pwrst	= omap4_pwrdm_clear_all_prev_pwrst,
218 	.pwrdm_set_logic_retst	= omap4_pwrdm_set_logic_retst,
219 	.pwrdm_read_logic_pwrst	= omap4_pwrdm_read_logic_pwrst,
220 	.pwrdm_read_logic_retst	= omap4_pwrdm_read_logic_retst,
221 	.pwrdm_read_mem_pwrst	= omap4_pwrdm_read_mem_pwrst,
222 	.pwrdm_read_mem_retst	= omap4_pwrdm_read_mem_retst,
223 	.pwrdm_set_mem_onst	= omap4_pwrdm_set_mem_onst,
224 	.pwrdm_set_mem_retst	= omap4_pwrdm_set_mem_retst,
225 	.pwrdm_wait_transition	= omap4_pwrdm_wait_transition,
226 };
227