diff options
author | Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> | 2009-03-13 12:19:16 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2009-11-11 17:42:49 -0500 |
commit | 06d8f065b3bac1673825be744d22742ad72f9c2a (patch) | |
tree | 02ab11a51a0c0ed63e111b153f69f6e9220639ac /arch | |
parent | 0343371e22dcfec9291193ad3e771dbce3a93670 (diff) |
OMAP3: PM: CPUidle: Add new lower-latency C1 state
This patch introduces a new C state which allows MPU to go to WFI but keeps
the core domain active. This offers a much better wakeup latency (3us vs
10s of us for the current C1) at the cost of a higher power consumption.
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-omap2/cpuidle34xx.c | 125 |
1 files changed, 81 insertions, 44 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index ad3af11f8f6e..c11377ddc189 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c | |||
@@ -25,8 +25,9 @@ | |||
25 | #include <linux/cpuidle.h> | 25 | #include <linux/cpuidle.h> |
26 | 26 | ||
27 | #include <plat/prcm.h> | 27 | #include <plat/prcm.h> |
28 | #include <plat/powerdomain.h> | ||
29 | #include <plat/irqs.h> | 28 | #include <plat/irqs.h> |
29 | #include <plat/powerdomain.h> | ||
30 | #include <plat/clockdomain.h> | ||
30 | #include <plat/control.h> | 31 | #include <plat/control.h> |
31 | #include <plat/serial.h> | 32 | #include <plat/serial.h> |
32 | 33 | ||
@@ -34,13 +35,14 @@ | |||
34 | 35 | ||
35 | #ifdef CONFIG_CPU_IDLE | 36 | #ifdef CONFIG_CPU_IDLE |
36 | 37 | ||
37 | #define OMAP3_MAX_STATES 7 | 38 | #define OMAP3_MAX_STATES 8 |
38 | #define OMAP3_STATE_C1 1 /* C1 - MPU WFI + Core active */ | 39 | #define OMAP3_STATE_C1 1 /* C1 - MPU WFI + Core active */ |
39 | #define OMAP3_STATE_C2 2 /* C2 - MPU CSWR + Core active */ | 40 | #define OMAP3_STATE_C2 2 /* C2 - MPU WFI + Core inactive */ |
40 | #define OMAP3_STATE_C3 3 /* C3 - MPU OFF + Core active */ | 41 | #define OMAP3_STATE_C3 3 /* C3 - MPU CSWR + Core inactive */ |
41 | #define OMAP3_STATE_C4 4 /* C4 - MPU RET + Core RET */ | 42 | #define OMAP3_STATE_C4 4 /* C4 - MPU OFF + Core iactive */ |
42 | #define OMAP3_STATE_C5 5 /* C5 - MPU OFF + Core RET */ | 43 | #define OMAP3_STATE_C5 5 /* C5 - MPU RET + Core RET */ |
43 | #define OMAP3_STATE_C6 6 /* C6 - MPU OFF + Core OFF */ | 44 | #define OMAP3_STATE_C6 6 /* C6 - MPU OFF + Core RET */ |
45 | #define OMAP3_STATE_C7 7 /* C7 - MPU OFF + Core OFF */ | ||
44 | 46 | ||
45 | struct omap3_processor_cx { | 47 | struct omap3_processor_cx { |
46 | u8 valid; | 48 | u8 valid; |
@@ -64,6 +66,20 @@ static int omap3_idle_bm_check(void) | |||
64 | return 0; | 66 | return 0; |
65 | } | 67 | } |
66 | 68 | ||
69 | static int _cpuidle_allow_idle(struct powerdomain *pwrdm, | ||
70 | struct clockdomain *clkdm) | ||
71 | { | ||
72 | omap2_clkdm_allow_idle(clkdm); | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int _cpuidle_deny_idle(struct powerdomain *pwrdm, | ||
77 | struct clockdomain *clkdm) | ||
78 | { | ||
79 | omap2_clkdm_deny_idle(clkdm); | ||
80 | return 0; | ||
81 | } | ||
82 | |||
67 | /** | 83 | /** |
68 | * omap3_enter_idle - Programs OMAP3 to enter the specified state | 84 | * omap3_enter_idle - Programs OMAP3 to enter the specified state |
69 | * @dev: cpuidle device | 85 | * @dev: cpuidle device |
@@ -100,9 +116,19 @@ static int omap3_enter_idle(struct cpuidle_device *dev, | |||
100 | if (omap_irq_pending()) | 116 | if (omap_irq_pending()) |
101 | goto return_sleep_time; | 117 | goto return_sleep_time; |
102 | 118 | ||
119 | if (cx->type == OMAP3_STATE_C1) { | ||
120 | pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); | ||
121 | pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); | ||
122 | } | ||
123 | |||
103 | /* Execute ARM wfi */ | 124 | /* Execute ARM wfi */ |
104 | omap_sram_idle(); | 125 | omap_sram_idle(); |
105 | 126 | ||
127 | if (cx->type == OMAP3_STATE_C1) { | ||
128 | pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); | ||
129 | pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); | ||
130 | } | ||
131 | |||
106 | return_sleep_time: | 132 | return_sleep_time: |
107 | getnstimeofday(&ts_postidle); | 133 | getnstimeofday(&ts_postidle); |
108 | ts_idle = timespec_sub(ts_postidle, ts_preidle); | 134 | ts_idle = timespec_sub(ts_postidle, ts_preidle); |
@@ -141,79 +167,90 @@ DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); | |||
141 | /* omap3_init_power_states - Initialises the OMAP3 specific C states. | 167 | /* omap3_init_power_states - Initialises the OMAP3 specific C states. |
142 | * | 168 | * |
143 | * Below is the desciption of each C state. | 169 | * Below is the desciption of each C state. |
144 | * C1 . MPU WFI + Core active | 170 | * C1 . MPU WFI + Core active |
145 | * C2 . MPU CSWR + Core active | 171 | * C2 . MPU WFI + Core inactive |
146 | * C3 . MPU OFF + Core active | 172 | * C3 . MPU CSWR + Core inactive |
147 | * C4 . MPU CSWR + Core CSWR | 173 | * C4 . MPU OFF + Core inactive |
148 | * C5 . MPU OFF + Core CSWR | 174 | * C5 . MPU CSWR + Core CSWR |
149 | * C6 . MPU OFF + Core OFF | 175 | * C6 . MPU OFF + Core CSWR |
176 | * C7 . MPU OFF + Core OFF | ||
150 | */ | 177 | */ |
151 | void omap_init_power_states(void) | 178 | void omap_init_power_states(void) |
152 | { | 179 | { |
153 | /* C1 . MPU WFI + Core active */ | 180 | /* C1 . MPU WFI + Core active */ |
154 | omap3_power_states[OMAP3_STATE_C1].valid = 1; | 181 | omap3_power_states[OMAP3_STATE_C1].valid = 1; |
155 | omap3_power_states[OMAP3_STATE_C1].type = OMAP3_STATE_C1; | 182 | omap3_power_states[OMAP3_STATE_C1].type = OMAP3_STATE_C1; |
156 | omap3_power_states[OMAP3_STATE_C1].sleep_latency = 10; | 183 | omap3_power_states[OMAP3_STATE_C1].sleep_latency = 2; |
157 | omap3_power_states[OMAP3_STATE_C1].wakeup_latency = 10; | 184 | omap3_power_states[OMAP3_STATE_C1].wakeup_latency = 2; |
158 | omap3_power_states[OMAP3_STATE_C1].threshold = 30; | 185 | omap3_power_states[OMAP3_STATE_C1].threshold = 5; |
159 | omap3_power_states[OMAP3_STATE_C1].mpu_state = PWRDM_POWER_ON; | 186 | omap3_power_states[OMAP3_STATE_C1].mpu_state = PWRDM_POWER_ON; |
160 | omap3_power_states[OMAP3_STATE_C1].core_state = PWRDM_POWER_ON; | 187 | omap3_power_states[OMAP3_STATE_C1].core_state = PWRDM_POWER_ON; |
161 | omap3_power_states[OMAP3_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID; | 188 | omap3_power_states[OMAP3_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID; |
162 | 189 | ||
163 | /* C2 . MPU CSWR + Core active */ | 190 | /* C2 . MPU WFI + Core inactive */ |
164 | omap3_power_states[OMAP3_STATE_C2].valid = 1; | 191 | omap3_power_states[OMAP3_STATE_C2].valid = 1; |
165 | omap3_power_states[OMAP3_STATE_C2].type = OMAP3_STATE_C2; | 192 | omap3_power_states[OMAP3_STATE_C2].type = OMAP3_STATE_C2; |
166 | omap3_power_states[OMAP3_STATE_C2].sleep_latency = 50; | 193 | omap3_power_states[OMAP3_STATE_C2].sleep_latency = 10; |
167 | omap3_power_states[OMAP3_STATE_C2].wakeup_latency = 50; | 194 | omap3_power_states[OMAP3_STATE_C2].wakeup_latency = 10; |
168 | omap3_power_states[OMAP3_STATE_C2].threshold = 300; | 195 | omap3_power_states[OMAP3_STATE_C2].threshold = 30; |
169 | omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_RET; | 196 | omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON; |
170 | omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON; | 197 | omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON; |
171 | omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID | | 198 | omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID; |
172 | CPUIDLE_FLAG_CHECK_BM; | ||
173 | 199 | ||
174 | /* C3 . MPU OFF + Core active */ | 200 | /* C3 . MPU CSWR + Core inactive */ |
175 | omap3_power_states[OMAP3_STATE_C3].valid = 1; | 201 | omap3_power_states[OMAP3_STATE_C3].valid = 1; |
176 | omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3; | 202 | omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3; |
177 | omap3_power_states[OMAP3_STATE_C3].sleep_latency = 1500; | 203 | omap3_power_states[OMAP3_STATE_C3].sleep_latency = 50; |
178 | omap3_power_states[OMAP3_STATE_C3].wakeup_latency = 1800; | 204 | omap3_power_states[OMAP3_STATE_C3].wakeup_latency = 50; |
179 | omap3_power_states[OMAP3_STATE_C3].threshold = 4000; | 205 | omap3_power_states[OMAP3_STATE_C3].threshold = 300; |
180 | omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_OFF; | 206 | omap3_power_states[OMAP3_STATE_C3].mpu_state = PWRDM_POWER_RET; |
181 | omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON; | 207 | omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON; |
182 | omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID | | 208 | omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID | |
183 | CPUIDLE_FLAG_CHECK_BM; | 209 | CPUIDLE_FLAG_CHECK_BM; |
184 | 210 | ||
185 | /* C4 . MPU CSWR + Core CSWR*/ | 211 | /* C4 . MPU OFF + Core inactive */ |
186 | omap3_power_states[OMAP3_STATE_C4].valid = 1; | 212 | omap3_power_states[OMAP3_STATE_C4].valid = 1; |
187 | omap3_power_states[OMAP3_STATE_C4].type = OMAP3_STATE_C4; | 213 | omap3_power_states[OMAP3_STATE_C4].type = OMAP3_STATE_C4; |
188 | omap3_power_states[OMAP3_STATE_C4].sleep_latency = 2500; | 214 | omap3_power_states[OMAP3_STATE_C4].sleep_latency = 1500; |
189 | omap3_power_states[OMAP3_STATE_C4].wakeup_latency = 7500; | 215 | omap3_power_states[OMAP3_STATE_C4].wakeup_latency = 1800; |
190 | omap3_power_states[OMAP3_STATE_C4].threshold = 12000; | 216 | omap3_power_states[OMAP3_STATE_C4].threshold = 4000; |
191 | omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_RET; | 217 | omap3_power_states[OMAP3_STATE_C4].mpu_state = PWRDM_POWER_OFF; |
192 | omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_RET; | 218 | omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON; |
193 | omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID | | 219 | omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID | |
194 | CPUIDLE_FLAG_CHECK_BM; | 220 | CPUIDLE_FLAG_CHECK_BM; |
195 | 221 | ||
196 | /* C5 . MPU OFF + Core CSWR */ | 222 | /* C5 . MPU CSWR + Core CSWR*/ |
197 | omap3_power_states[OMAP3_STATE_C5].valid = 1; | 223 | omap3_power_states[OMAP3_STATE_C5].valid = 1; |
198 | omap3_power_states[OMAP3_STATE_C5].type = OMAP3_STATE_C5; | 224 | omap3_power_states[OMAP3_STATE_C5].type = OMAP3_STATE_C5; |
199 | omap3_power_states[OMAP3_STATE_C5].sleep_latency = 3000; | 225 | omap3_power_states[OMAP3_STATE_C5].sleep_latency = 2500; |
200 | omap3_power_states[OMAP3_STATE_C5].wakeup_latency = 8500; | 226 | omap3_power_states[OMAP3_STATE_C5].wakeup_latency = 7500; |
201 | omap3_power_states[OMAP3_STATE_C5].threshold = 15000; | 227 | omap3_power_states[OMAP3_STATE_C5].threshold = 12000; |
202 | omap3_power_states[OMAP3_STATE_C5].mpu_state = PWRDM_POWER_OFF; | 228 | omap3_power_states[OMAP3_STATE_C5].mpu_state = PWRDM_POWER_RET; |
203 | omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET; | 229 | omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET; |
204 | omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID | | 230 | omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID | |
205 | CPUIDLE_FLAG_CHECK_BM; | 231 | CPUIDLE_FLAG_CHECK_BM; |
206 | 232 | ||
207 | /* C6 . MPU OFF + Core OFF */ | 233 | /* C6 . MPU OFF + Core CSWR */ |
208 | omap3_power_states[OMAP3_STATE_C6].valid = 1; | 234 | omap3_power_states[OMAP3_STATE_C6].valid = 1; |
209 | omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6; | 235 | omap3_power_states[OMAP3_STATE_C6].type = OMAP3_STATE_C6; |
210 | omap3_power_states[OMAP3_STATE_C6].sleep_latency = 10000; | 236 | omap3_power_states[OMAP3_STATE_C6].sleep_latency = 3000; |
211 | omap3_power_states[OMAP3_STATE_C6].wakeup_latency = 30000; | 237 | omap3_power_states[OMAP3_STATE_C6].wakeup_latency = 8500; |
212 | omap3_power_states[OMAP3_STATE_C6].threshold = 300000; | 238 | omap3_power_states[OMAP3_STATE_C6].threshold = 15000; |
213 | omap3_power_states[OMAP3_STATE_C6].mpu_state = PWRDM_POWER_OFF; | 239 | omap3_power_states[OMAP3_STATE_C6].mpu_state = PWRDM_POWER_OFF; |
214 | omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_OFF; | 240 | omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_RET; |
215 | omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID | | 241 | omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID | |
216 | CPUIDLE_FLAG_CHECK_BM; | 242 | CPUIDLE_FLAG_CHECK_BM; |
243 | |||
244 | /* C7 . MPU OFF + Core OFF */ | ||
245 | omap3_power_states[OMAP3_STATE_C7].valid = 1; | ||
246 | omap3_power_states[OMAP3_STATE_C7].type = OMAP3_STATE_C7; | ||
247 | omap3_power_states[OMAP3_STATE_C7].sleep_latency = 10000; | ||
248 | omap3_power_states[OMAP3_STATE_C7].wakeup_latency = 30000; | ||
249 | omap3_power_states[OMAP3_STATE_C7].threshold = 300000; | ||
250 | omap3_power_states[OMAP3_STATE_C7].mpu_state = PWRDM_POWER_OFF; | ||
251 | omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF; | ||
252 | omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID | | ||
253 | CPUIDLE_FLAG_CHECK_BM; | ||
217 | } | 254 | } |
218 | 255 | ||
219 | struct cpuidle_driver omap3_idle_driver = { | 256 | struct cpuidle_driver omap3_idle_driver = { |