blob: 9e19d401b25fa594e2a4c0c57d6f37e05e3d7c70 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* arch/arm/mach-msm/pm.c
2 *
3 * MSM Power Management Routines
4 *
5 * Copyright (C) 2007 Google, Inc.
6 * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19#include <linux/module.h>
20#include <linux/kernel.h>
21#include <linux/clk.h>
22#include <linux/delay.h>
23#include <linux/init.h>
24#include <linux/pm.h>
25#include <linux/pm_qos_params.h>
26#include <linux/proc_fs.h>
27#include <linux/suspend.h>
28#include <linux/reboot.h>
29#include <linux/uaccess.h>
30#include <mach/msm_iomap.h>
31#include <mach/system.h>
32#include <asm/io.h>
33
34#ifdef CONFIG_HAS_WAKELOCK
35#include <linux/wakelock.h>
36#endif
37
38#include "smd_private.h"
39#include "smd_rpcrouter.h"
40#include "acpuclock.h"
41#include "clock.h"
42#include "proc_comm.h"
43#include "idle.h"
44#include "irq.h"
45#include "gpio.h"
46#include "timer.h"
47#include "pm.h"
48
49enum {
50 MSM_PM_DEBUG_SUSPEND = 1U << 0,
51 MSM_PM_DEBUG_POWER_COLLAPSE = 1U << 1,
52 MSM_PM_DEBUG_STATE = 1U << 2,
53 MSM_PM_DEBUG_CLOCK = 1U << 3,
54 MSM_PM_DEBUG_RESET_VECTOR = 1U << 4,
55 MSM_PM_DEBUG_SMSM_STATE = 1U << 5,
56 MSM_PM_DEBUG_IDLE = 1U << 6,
57};
58static int msm_pm_debug_mask;
59module_param_named(debug_mask, msm_pm_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
60
61#ifdef CONFIG_MSM_SLEEP_TIME_OVERRIDE
62static int msm_pm_sleep_time_override;
63module_param_named(sleep_time_override,
64 msm_pm_sleep_time_override, int, S_IRUGO | S_IWUSR | S_IWGRP);
65#endif
66
67static int msm_pm_sleep_mode = CONFIG_MSM7X00A_SLEEP_MODE;
68module_param_named(sleep_mode, msm_pm_sleep_mode, int, S_IRUGO | S_IWUSR | S_IWGRP);
69static int msm_pm_idle_sleep_mode = CONFIG_MSM7X00A_IDLE_SLEEP_MODE;
70module_param_named(idle_sleep_mode, msm_pm_idle_sleep_mode, int, S_IRUGO | S_IWUSR | S_IWGRP);
71static int msm_pm_idle_sleep_min_time = CONFIG_MSM7X00A_IDLE_SLEEP_MIN_TIME;
72module_param_named(idle_sleep_min_time, msm_pm_idle_sleep_min_time, int, S_IRUGO | S_IWUSR | S_IWGRP);
73static int msm_pm_idle_spin_time = CONFIG_MSM7X00A_IDLE_SPIN_TIME;
74module_param_named(idle_spin_time, msm_pm_idle_spin_time, int, S_IRUGO | S_IWUSR | S_IWGRP);
75
76#define A11S_CLK_SLEEP_EN (MSM_CSR_BASE + 0x11c)
77#define A11S_PWRDOWN (MSM_CSR_BASE + 0x440)
78#define A11S_STANDBY_CTL (MSM_CSR_BASE + 0x108)
79#define A11RAMBACKBIAS (MSM_CSR_BASE + 0x508)
80
81enum {
82 SLEEP_LIMIT_NONE = 0,
83 SLEEP_LIMIT_NO_TCXO_SHUTDOWN = 2
84};
85
86static atomic_t msm_pm_init_done = ATOMIC_INIT(0);
87struct smsm_interrupt_info_ext {
88 uint32_t aArm_en_mask;
89 uint32_t aArm_interrupts_pending;
90 uint32_t aArm_wakeup_reason;
91 uint32_t aArm_rpc_prog;
92 uint32_t aArm_rpc_proc;
93 char aArm_smd_port_name[20];
94 uint32_t aArm_gpio_info;
95};
96static struct msm_pm_smem_addr_t {
97 uint32_t *sleep_delay;
98 uint32_t *limit_sleep;
99 struct smsm_interrupt_info *int_info;
100 struct smsm_interrupt_info_ext *int_info_ext;
101} msm_pm_sma;
102
103static uint32_t *msm_pm_reset_vector;
104static uint32_t msm_pm_max_sleep_time;
105static struct msm_pm_platform_data *msm_pm_modes;
106
107#ifdef CONFIG_MSM_IDLE_STATS
108enum msm_pm_time_stats_id {
109 MSM_PM_STAT_REQUESTED_IDLE,
110 MSM_PM_STAT_IDLE_SPIN,
111 MSM_PM_STAT_IDLE_WFI,
112 MSM_PM_STAT_IDLE_SLEEP,
113 MSM_PM_STAT_IDLE_FAILED_SLEEP,
114 MSM_PM_STAT_IDLE_POWER_COLLAPSE,
115 MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE,
116 MSM_PM_STAT_SUSPEND,
117 MSM_PM_STAT_FAILED_SUSPEND,
118 MSM_PM_STAT_NOT_IDLE,
119 MSM_PM_STAT_COUNT
120};
121
122static struct msm_pm_time_stats {
123 const char *name;
124 int64_t first_bucket_time;
125 int bucket[CONFIG_MSM_IDLE_STATS_BUCKET_COUNT];
126 int64_t min_time[CONFIG_MSM_IDLE_STATS_BUCKET_COUNT];
127 int64_t max_time[CONFIG_MSM_IDLE_STATS_BUCKET_COUNT];
128 int count;
129 int64_t total_time;
130} msm_pm_stats[MSM_PM_STAT_COUNT] = {
131 [MSM_PM_STAT_REQUESTED_IDLE].name = "idle-request",
132 [MSM_PM_STAT_REQUESTED_IDLE].first_bucket_time =
133 CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
134
135 [MSM_PM_STAT_IDLE_SPIN].name = "idle-spin",
136 [MSM_PM_STAT_IDLE_SPIN].first_bucket_time =
137 CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
138
139 [MSM_PM_STAT_IDLE_WFI].name = "idle-wfi",
140 [MSM_PM_STAT_IDLE_WFI].first_bucket_time =
141 CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
142
143 [MSM_PM_STAT_IDLE_SLEEP].name = "idle-sleep",
144 [MSM_PM_STAT_IDLE_SLEEP].first_bucket_time =
145 CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
146
147 [MSM_PM_STAT_IDLE_FAILED_SLEEP].name = "idle-failed-sleep",
148 [MSM_PM_STAT_IDLE_FAILED_SLEEP].first_bucket_time =
149 CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
150
151 [MSM_PM_STAT_IDLE_POWER_COLLAPSE].name = "idle-power-collapse",
152 [MSM_PM_STAT_IDLE_POWER_COLLAPSE].first_bucket_time =
153 CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
154
155 [MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].name =
156 "idle-failed-power-collapse",
157 [MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].first_bucket_time =
158 CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
159
160 [MSM_PM_STAT_SUSPEND].name = "suspend",
161 [MSM_PM_STAT_SUSPEND].first_bucket_time =
162 CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET,
163
164 [MSM_PM_STAT_FAILED_SUSPEND].name = "failed-suspend",
165 [MSM_PM_STAT_FAILED_SUSPEND].first_bucket_time =
166 CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
167
168 [MSM_PM_STAT_NOT_IDLE].name = "not-idle",
169 [MSM_PM_STAT_NOT_IDLE].first_bucket_time =
170 CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
171};
172
173static void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t)
174{
175 int i;
176 int64_t bt;
177 msm_pm_stats[id].total_time += t;
178 msm_pm_stats[id].count++;
179 bt = t;
180 do_div(bt, msm_pm_stats[id].first_bucket_time);
181 if (bt < 1ULL << (CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT *
182 (CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1)))
183 i = DIV_ROUND_UP(fls((uint32_t)bt),
184 CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT);
185 else
186 i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1;
187 msm_pm_stats[id].bucket[i]++;
188 if (t < msm_pm_stats[id].min_time[i] || !msm_pm_stats[id].max_time[i])
189 msm_pm_stats[id].min_time[i] = t;
190 if (t > msm_pm_stats[id].max_time[i])
191 msm_pm_stats[id].max_time[i] = t;
192}
193
194static uint32_t msm_pm_sleep_limit = SLEEP_LIMIT_NONE;
195#endif
196
197static int
198msm_pm_wait_state(uint32_t wait_state_all_set, uint32_t wait_state_all_clear,
199 uint32_t wait_state_any_set, uint32_t wait_state_any_clear)
200{
201 int i;
202 uint32_t state;
203
204 for (i = 0; i < 2000000; i++) {
205 state = smsm_get_state(SMSM_MODEM_STATE);
206 if (((state & wait_state_all_set) == wait_state_all_set) &&
207 ((~state & wait_state_all_clear) == wait_state_all_clear) &&
208 (wait_state_any_set == 0 || (state & wait_state_any_set) ||
209 wait_state_any_clear == 0 || (state & wait_state_any_clear)))
210 return 0;
211 }
212 printk(KERN_ERR "msm_pm_wait_state(%x, %x, %x, %x) failed %x\n",
213 wait_state_all_set, wait_state_all_clear,
214 wait_state_any_set, wait_state_any_clear, state);
215 return -ETIMEDOUT;
216}
217
218/*
219 * Respond to timing out waiting for Modem
220 *
221 * NOTE: The function never returns.
222 */
223static void msm_pm_timeout(void)
224{
225#if defined(CONFIG_MSM_PM_TIMEOUT_RESET_CHIP)
226 printk(KERN_EMERG "%s(): resetting chip\n", __func__);
227 msm_proc_comm(PCOM_RESET_CHIP_IMM, NULL, NULL);
228#elif defined(CONFIG_MSM_PM_TIMEOUT_RESET_MODEM)
229 printk(KERN_EMERG "%s(): resetting modem\n", __func__);
230 msm_proc_comm_reset_modem_now();
231#elif defined(CONFIG_MSM_PM_TIMEOUT_HALT)
232 printk(KERN_EMERG "%s(): halting\n", __func__);
233#endif
234 for (;;)
235 ;
236}
237
238static int msm_sleep(int sleep_mode, uint32_t sleep_delay,
239 uint32_t sleep_limit, int from_idle)
240{
241 uint32_t saved_vector[2];
242 int collapsed;
243 uint32_t enter_state;
244 uint32_t enter_wait_set = 0;
245 uint32_t enter_wait_clear = 0;
246 uint32_t exit_state;
247 uint32_t exit_wait_clear = 0;
248 uint32_t exit_wait_set = 0;
249 unsigned long pm_saved_acpu_clk_rate = 0;
250 int ret;
251 int rv = -EINTR;
252
253 if (msm_pm_debug_mask & MSM_PM_DEBUG_SUSPEND)
254 printk(KERN_INFO "msm_sleep(): "
255 "mode %d delay %u limit %u idle %d\n",
256 sleep_mode, sleep_delay, sleep_limit, from_idle);
257
258 switch (sleep_mode) {
259 case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
260 enter_state = SMSM_PWRC;
261 enter_wait_set = SMSM_RSA;
262 exit_state = SMSM_WFPI;
263 exit_wait_clear = SMSM_RSA;
264 break;
265 case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND:
266 enter_state = SMSM_PWRC_SUSPEND;
267 enter_wait_set = SMSM_RSA;
268 exit_state = SMSM_WFPI;
269 exit_wait_clear = SMSM_RSA;
270 break;
271 case MSM_PM_SLEEP_MODE_APPS_SLEEP:
272 enter_state = SMSM_SLEEP;
273 exit_state = SMSM_SLEEPEXIT;
274 exit_wait_set = SMSM_SLEEPEXIT;
275 break;
276 default:
277 enter_state = 0;
278 exit_state = 0;
279 }
280
281 if (enter_state && !(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RUN)) {
282 if ((MSM_PM_DEBUG_POWER_COLLAPSE | MSM_PM_DEBUG_SUSPEND) &
283 msm_pm_debug_mask)
284 printk(KERN_INFO "msm_sleep(): modem not ready\n");
285 rv = -EBUSY;
286 goto check_failed;
287 }
288
289 memset(msm_pm_sma.int_info, 0, sizeof(*msm_pm_sma.int_info));
290 msm_irq_enter_sleep1(!!enter_state, from_idle,
291 &msm_pm_sma.int_info->aArm_en_mask);
292 msm_gpio_enter_sleep(from_idle);
293
294 if (enter_state) {
295 if (sleep_delay == 0 && sleep_mode >= MSM_PM_SLEEP_MODE_APPS_SLEEP)
296 sleep_delay = 192000*5; /* APPS_SLEEP does not allow infinite timeout */
297
298 *msm_pm_sma.sleep_delay = sleep_delay;
299 *msm_pm_sma.limit_sleep = sleep_limit;
300 ret = smsm_change_state(SMSM_APPS_STATE, SMSM_RUN, enter_state);
301 if (ret) {
302 printk(KERN_ERR "msm_sleep(): smsm_change_state %x failed\n", enter_state);
303 enter_state = 0;
304 exit_state = 0;
305 }
306 ret = msm_pm_wait_state(enter_wait_set, enter_wait_clear, 0, 0);
307 if (ret) {
308 printk(KERN_EMERG "msm_sleep(): power collapse entry "
309 "timed out waiting for Modem's response\n");
310 msm_pm_timeout();
311 }
312 }
313 if (msm_irq_enter_sleep2(!!enter_state, from_idle))
314 goto enter_failed;
315
316 if (enter_state) {
317 __raw_writel(0x1f, A11S_CLK_SLEEP_EN);
318 __raw_writel(1, A11S_PWRDOWN);
319
320 __raw_writel(0, A11S_STANDBY_CTL);
321 __raw_writel(0, A11RAMBACKBIAS);
322
323 if (msm_pm_debug_mask & MSM_PM_DEBUG_STATE)
324 printk(KERN_INFO "msm_sleep(): enter "
325 "A11S_CLK_SLEEP_EN %x, A11S_PWRDOWN %x, "
326 "smsm_get_state %x\n",
327 __raw_readl(A11S_CLK_SLEEP_EN),
328 __raw_readl(A11S_PWRDOWN),
329 smsm_get_state(SMSM_MODEM_STATE));
330 }
331
332 if (sleep_mode <= MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT) {
333 pm_saved_acpu_clk_rate = acpuclk_power_collapse();
334 if (msm_pm_debug_mask & MSM_PM_DEBUG_CLOCK)
335 printk(KERN_INFO "msm_sleep(): %ld enter power collapse"
336 "\n", pm_saved_acpu_clk_rate);
337 if (pm_saved_acpu_clk_rate == 0)
338 goto ramp_down_failed;
339 }
340 if (sleep_mode < MSM_PM_SLEEP_MODE_APPS_SLEEP) {
341 if (msm_pm_debug_mask & MSM_PM_DEBUG_SMSM_STATE)
342 smsm_print_sleep_info(*msm_pm_sma.sleep_delay,
343 *msm_pm_sma.limit_sleep,
344 msm_pm_sma.int_info->aArm_en_mask,
345 msm_pm_sma.int_info->aArm_wakeup_reason,
346 msm_pm_sma.int_info->aArm_interrupts_pending);
347 saved_vector[0] = msm_pm_reset_vector[0];
348 saved_vector[1] = msm_pm_reset_vector[1];
349 msm_pm_reset_vector[0] = 0xE51FF004; /* ldr pc, 4 */
350 msm_pm_reset_vector[1] = virt_to_phys(msm_pm_collapse_exit);
351 if (msm_pm_debug_mask & MSM_PM_DEBUG_RESET_VECTOR)
352 printk(KERN_INFO "msm_sleep(): vector %x %x -> "
353 "%x %x\n", saved_vector[0], saved_vector[1],
354 msm_pm_reset_vector[0], msm_pm_reset_vector[1]);
355 collapsed = msm_pm_collapse();
356 msm_pm_reset_vector[0] = saved_vector[0];
357 msm_pm_reset_vector[1] = saved_vector[1];
358 if (collapsed) {
359 cpu_init();
360 local_fiq_enable();
361 rv = 0;
362 }
363 if (msm_pm_debug_mask & MSM_PM_DEBUG_POWER_COLLAPSE)
364 printk(KERN_INFO "msm_pm_collapse(): returned %d\n",
365 collapsed);
366 if (msm_pm_debug_mask & MSM_PM_DEBUG_SMSM_STATE)
367 smsm_print_sleep_info(*msm_pm_sma.sleep_delay,
368 *msm_pm_sma.limit_sleep,
369 msm_pm_sma.int_info->aArm_en_mask,
370 msm_pm_sma.int_info->aArm_wakeup_reason,
371 msm_pm_sma.int_info->aArm_interrupts_pending);
372 } else {
373 msm_arch_idle();
374 rv = 0;
375 }
376
377 if (sleep_mode <= MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT) {
378 if (msm_pm_debug_mask & MSM_PM_DEBUG_CLOCK)
379 printk(KERN_INFO "msm_sleep(): exit power collapse %ld"
380 "\n", pm_saved_acpu_clk_rate);
381 if (acpuclk_set_rate(smp_processor_id(),
382 pm_saved_acpu_clk_rate, SETRATE_PC) < 0)
383 printk(KERN_ERR "msm_sleep(): clk_set_rate %ld "
384 "failed\n", pm_saved_acpu_clk_rate);
385 }
386 if (msm_pm_debug_mask & MSM_PM_DEBUG_STATE)
387 printk(KERN_INFO "msm_sleep(): exit A11S_CLK_SLEEP_EN %x, "
388 "A11S_PWRDOWN %x, smsm_get_state %x\n",
389 __raw_readl(A11S_CLK_SLEEP_EN),
390 __raw_readl(A11S_PWRDOWN),
391 smsm_get_state(SMSM_MODEM_STATE));
392ramp_down_failed:
393 msm_irq_exit_sleep1(msm_pm_sma.int_info->aArm_en_mask,
394 msm_pm_sma.int_info->aArm_wakeup_reason,
395 msm_pm_sma.int_info->aArm_interrupts_pending);
396enter_failed:
397 if (enter_state) {
398 __raw_writel(0x00, A11S_CLK_SLEEP_EN);
399 __raw_writel(0, A11S_PWRDOWN);
400 smsm_change_state(SMSM_APPS_STATE, enter_state, exit_state);
401 if (msm_pm_wait_state(exit_wait_set, exit_wait_clear, 0, 0)) {
402 printk(KERN_EMERG "msm_sleep(): power collapse exit "
403 "timed out waiting for Modem's response\n");
404 msm_pm_timeout();
405 }
406 if (msm_pm_debug_mask & MSM_PM_DEBUG_STATE)
407 printk(KERN_INFO "msm_sleep(): sleep exit "
408 "A11S_CLK_SLEEP_EN %x, A11S_PWRDOWN %x, "
409 "smsm_get_state %x\n",
410 __raw_readl(A11S_CLK_SLEEP_EN),
411 __raw_readl(A11S_PWRDOWN),
412 smsm_get_state(SMSM_MODEM_STATE));
413 if (msm_pm_debug_mask & MSM_PM_DEBUG_SMSM_STATE)
414 smsm_print_sleep_info(*msm_pm_sma.sleep_delay,
415 *msm_pm_sma.limit_sleep,
416 msm_pm_sma.int_info->aArm_en_mask,
417 msm_pm_sma.int_info->aArm_wakeup_reason,
418 msm_pm_sma.int_info->aArm_interrupts_pending);
419 }
420 msm_irq_exit_sleep2(msm_pm_sma.int_info->aArm_en_mask,
421 msm_pm_sma.int_info->aArm_wakeup_reason,
422 msm_pm_sma.int_info->aArm_interrupts_pending);
423 if (enter_state) {
424 smsm_change_state(SMSM_APPS_STATE, exit_state, SMSM_RUN);
425 if (msm_pm_debug_mask & MSM_PM_DEBUG_STATE)
426 printk(KERN_INFO "msm_sleep(): sleep exit "
427 "A11S_CLK_SLEEP_EN %x, A11S_PWRDOWN %x, "
428 "smsm_get_state %x\n",
429 __raw_readl(A11S_CLK_SLEEP_EN),
430 __raw_readl(A11S_PWRDOWN),
431 smsm_get_state(SMSM_MODEM_STATE));
432 }
433 msm_irq_exit_sleep3(msm_pm_sma.int_info->aArm_en_mask,
434 msm_pm_sma.int_info->aArm_wakeup_reason,
435 msm_pm_sma.int_info->aArm_interrupts_pending);
436 msm_gpio_exit_sleep();
437 smd_sleep_exit();
438
439check_failed:
440 return rv;
441}
442
443void msm_pm_set_max_sleep_time(int64_t max_sleep_time_ns)
444{
445 int64_t max_sleep_time_bs = max_sleep_time_ns;
446
447 /* Convert from ns -> BS units */
448 do_div(max_sleep_time_bs, NSEC_PER_SEC / 32768);
449
450 if (max_sleep_time_bs > 0x6DDD000)
451 msm_pm_max_sleep_time = (uint32_t) 0x6DDD000;
452 else
453 msm_pm_max_sleep_time = (uint32_t) max_sleep_time_bs;
454
455 if (msm_pm_debug_mask & MSM_PM_DEBUG_SUSPEND)
456 printk(KERN_INFO "%s: Requested %lldns (%lldbs), Giving %ubs\n",
457 __func__, max_sleep_time_ns,
458 max_sleep_time_bs,
459 msm_pm_max_sleep_time);
460}
461EXPORT_SYMBOL(msm_pm_set_max_sleep_time);
462
463void arch_idle(void)
464{
465 int ret;
466 int spin;
467 int64_t sleep_time;
468 int low_power = 0;
469 struct msm_pm_platform_data *mode;
470#ifdef CONFIG_MSM_IDLE_STATS
471 int64_t t1;
472 static int64_t t2;
473 int exit_stat;
474#endif
475 int latency_qos = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
476 uint32_t sleep_limit = SLEEP_LIMIT_NONE;
477 int allow_sleep =
478 msm_pm_idle_sleep_mode < MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT &&
479#ifdef CONFIG_HAS_WAKELOCK
480 !has_wake_lock(WAKE_LOCK_IDLE) &&
481#endif
482 msm_irq_idle_sleep_allowed();
483
484 if (!atomic_read(&msm_pm_init_done))
485 return;
486
487 sleep_time = msm_timer_enter_idle();
488
489#ifdef CONFIG_MSM_IDLE_STATS
490 t1 = ktime_to_ns(ktime_get());
491 msm_pm_add_stat(MSM_PM_STAT_NOT_IDLE, t1 - t2);
492 msm_pm_add_stat(MSM_PM_STAT_REQUESTED_IDLE, sleep_time);
493#endif
494
495 mode = &msm_pm_modes[MSM_PM_SLEEP_MODE_POWER_COLLAPSE];
496 if (mode->latency >= latency_qos)
497 sleep_limit = SLEEP_LIMIT_NO_TCXO_SHUTDOWN;
498
499 mode = &msm_pm_modes[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN];
500 if (mode->latency >= latency_qos)
501 allow_sleep = false;
502
503 mode = &msm_pm_modes[
504 MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT];
505 if (mode->latency >= latency_qos) {
506 /* no time even for SWFI */
507 while (!msm_irq_pending())
508 udelay(1);
509#ifdef CONFIG_MSM_IDLE_STATS
510 exit_stat = MSM_PM_STAT_IDLE_SPIN;
511#endif
512 goto abort_idle;
513 }
514
515 if (msm_pm_debug_mask & MSM_PM_DEBUG_IDLE)
516 printk(KERN_INFO "arch_idle: sleep time %llu, allow_sleep %d\n",
517 sleep_time, allow_sleep);
518 spin = msm_pm_idle_spin_time >> 10;
519 while (spin-- > 0) {
520 if (msm_irq_pending()) {
521#ifdef CONFIG_MSM_IDLE_STATS
522 exit_stat = MSM_PM_STAT_IDLE_SPIN;
523#endif
524 goto abort_idle;
525 }
526 udelay(1);
527 }
528 if (sleep_time < msm_pm_idle_sleep_min_time || !allow_sleep) {
529 unsigned long saved_rate;
530 saved_rate = acpuclk_wait_for_irq();
531 if (msm_pm_debug_mask & MSM_PM_DEBUG_CLOCK)
532 printk(KERN_DEBUG "arch_idle: clk %ld -> swfi\n",
533 saved_rate);
534 if (saved_rate) {
535 msm_arch_idle();
536#ifdef CONFIG_MSM_IDLE_STATS
537 exit_stat = MSM_PM_STAT_IDLE_WFI;
538#endif
539 } else {
540 while (!msm_irq_pending())
541 udelay(1);
542#ifdef CONFIG_MSM_IDLE_STATS
543 exit_stat = MSM_PM_STAT_IDLE_SPIN;
544#endif
545 }
546 if (msm_pm_debug_mask & MSM_PM_DEBUG_CLOCK)
547 printk(KERN_DEBUG "msm_sleep: clk swfi -> %ld\n",
548 saved_rate);
549 if (saved_rate
550 && acpuclk_set_rate(smp_processor_id(),
551 saved_rate, SETRATE_SWFI) < 0)
552 printk(KERN_ERR "msm_sleep(): clk_set_rate %ld "
553 "failed\n", saved_rate);
554 } else {
555 low_power = 1;
556 do_div(sleep_time, NSEC_PER_SEC / 32768);
557 if (sleep_time > 0x6DDD000) {
558 printk("sleep_time too big %lld\n", sleep_time);
559 sleep_time = 0x6DDD000;
560 }
561 ret = msm_sleep(msm_pm_idle_sleep_mode, sleep_time,
562 sleep_limit, 1);
563#ifdef CONFIG_MSM_IDLE_STATS
564 switch (msm_pm_idle_sleep_mode) {
565 case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND:
566 case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
567 if (ret)
568 exit_stat =
569 MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE;
570 else {
571 exit_stat = MSM_PM_STAT_IDLE_POWER_COLLAPSE;
572 msm_pm_sleep_limit = sleep_limit;
573 }
574 break;
575 case MSM_PM_SLEEP_MODE_APPS_SLEEP:
576 if (ret)
577 exit_stat = MSM_PM_STAT_IDLE_FAILED_SLEEP;
578 else
579 exit_stat = MSM_PM_STAT_IDLE_SLEEP;
580 break;
581 default:
582 exit_stat = MSM_PM_STAT_IDLE_WFI;
583 }
584#endif
585 }
586abort_idle:
587 msm_timer_exit_idle(low_power);
588#ifdef CONFIG_MSM_IDLE_STATS
589 t2 = ktime_to_ns(ktime_get());
590 msm_pm_add_stat(exit_stat, t2 - t1);
591#endif
592}
593
594static int msm_pm_enter(suspend_state_t state)
595{
596 uint32_t sleep_limit = SLEEP_LIMIT_NONE;
597 int ret;
598#ifdef CONFIG_MSM_IDLE_STATS
599 int64_t period = 0;
600 int64_t time = 0;
601
602 time = msm_timer_get_sclk_time(&period);
603#endif
604
605 clock_debug_print_enabled();
606
607#ifdef CONFIG_MSM_SLEEP_TIME_OVERRIDE
608 if (msm_pm_sleep_time_override > 0) {
609 int64_t ns = NSEC_PER_SEC * (int64_t)msm_pm_sleep_time_override;
610 msm_pm_set_max_sleep_time(ns);
611 msm_pm_sleep_time_override = 0;
612 }
613#endif
614
615 ret = msm_sleep(msm_pm_sleep_mode,
616 msm_pm_max_sleep_time, sleep_limit, 0);
617
618#ifdef CONFIG_MSM_IDLE_STATS
619 if (msm_pm_sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND ||
620 msm_pm_sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
621 enum msm_pm_time_stats_id id;
622 int64_t end_time;
623
624 if (ret)
625 id = MSM_PM_STAT_FAILED_SUSPEND;
626 else {
627 id = MSM_PM_STAT_SUSPEND;
628 msm_pm_sleep_limit = sleep_limit;
629 }
630
631 if (time != 0) {
632 end_time = msm_timer_get_sclk_time(NULL);
633 if (end_time != 0) {
634 time = end_time - time;
635 if (time < 0)
636 time += period;
637 } else
638 time = 0;
639 }
640
641 msm_pm_add_stat(id, time);
642 }
643#endif
644
645 return 0;
646}
647
648static struct platform_suspend_ops msm_pm_ops = {
649 .enter = msm_pm_enter,
650 .valid = suspend_valid_only_mem,
651};
652
653static uint32_t restart_reason = 0x776655AA;
654
655static void msm_pm_power_off(void)
656{
657 msm_rpcrouter_close();
658 msm_proc_comm(PCOM_POWER_DOWN, 0, 0);
659 for (;;) ;
660}
661
662static void msm_pm_restart(char str, const char *cmd)
663{
664 msm_rpcrouter_close();
665 msm_proc_comm(PCOM_RESET_CHIP, &restart_reason, 0);
666
667 for (;;) ;
668}
669
670static int msm_reboot_call(struct notifier_block *this, unsigned long code, void *_cmd)
671{
672 if((code == SYS_RESTART) && _cmd) {
673 char *cmd = _cmd;
674 if (!strcmp(cmd, "bootloader")) {
675 restart_reason = 0x77665500;
676 } else if (!strcmp(cmd, "recovery")) {
677 restart_reason = 0x77665502;
678 } else if (!strcmp(cmd, "eraseflash")) {
679 restart_reason = 0x776655EF;
680 } else if (!strncmp(cmd, "oem-", 4)) {
681 unsigned code = simple_strtoul(cmd + 4, 0, 16) & 0xff;
682 restart_reason = 0x6f656d00 | code;
683 } else {
684 restart_reason = 0x77665501;
685 }
686 }
687 return NOTIFY_DONE;
688}
689
690static struct notifier_block msm_reboot_notifier = {
691 .notifier_call = msm_reboot_call,
692};
693
694#ifdef CONFIG_MSM_IDLE_STATS
695/*
696 * Helper function of snprintf where buf is auto-incremented, size is auto-
697 * decremented, and there is no return value.
698 *
699 * NOTE: buf and size must be l-values (e.g. variables)
700 */
701#define SNPRINTF(buf, size, format, ...) \
702 do { \
703 if (size > 0) { \
704 int ret; \
705 ret = snprintf(buf, size, format, ## __VA_ARGS__); \
706 if (ret > size) { \
707 buf += size; \
708 size = 0; \
709 } else { \
710 buf += ret; \
711 size -= ret; \
712 } \
713 } \
714 } while (0)
715
716/*
717 * Write out the power management statistics.
718 */
719static int msm_pm_read_proc(
720 char *page, char **start, off_t off, int count, int *eof, void *data)
721{
722 int i;
723 char *p = page;
724
725 if (count < 1024) {
726 *start = (char *) 0;
727 *eof = 0;
728 return 0;
729 }
730
731 if (!off) {
732 SNPRINTF(p, count, "Last power collapse voted ");
733 if (msm_pm_sleep_limit == SLEEP_LIMIT_NONE)
734 SNPRINTF(p, count, "for TCXO shutdown\n\n");
735 else
736 SNPRINTF(p, count, "against TCXO shutdown\n\n");
737
738 *start = (char *) 1;
739 *eof = 0;
740 } else if (--off < ARRAY_SIZE(msm_pm_stats)) {
741 int64_t bucket_time;
742 int64_t s;
743 uint32_t ns;
744
745 s = msm_pm_stats[off].total_time;
746 ns = do_div(s, NSEC_PER_SEC);
747 SNPRINTF(p, count,
748 "%s:\n"
749 " count: %7d\n"
750 " total_time: %lld.%09u\n",
751 msm_pm_stats[off].name,
752 msm_pm_stats[off].count,
753 s, ns);
754
755 bucket_time = msm_pm_stats[off].first_bucket_time;
756 for (i = 0; i < CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; i++) {
757 s = bucket_time;
758 ns = do_div(s, NSEC_PER_SEC);
759 SNPRINTF(p, count,
760 " <%6lld.%09u: %7d (%lld-%lld)\n",
761 s, ns, msm_pm_stats[off].bucket[i],
762 msm_pm_stats[off].min_time[i],
763 msm_pm_stats[off].max_time[i]);
764
765 bucket_time <<= CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT;
766 }
767
768 SNPRINTF(p, count, " >=%6lld.%09u: %7d (%lld-%lld)\n",
769 s, ns, msm_pm_stats[off].bucket[i],
770 msm_pm_stats[off].min_time[i],
771 msm_pm_stats[off].max_time[i]);
772
773 *start = (char *) 1;
774 *eof = (off + 1 >= ARRAY_SIZE(msm_pm_stats));
775 }
776
777 return p - page;
778}
779#undef SNPRINTF
780
781#define MSM_PM_STATS_RESET "reset"
782
783/*
784 * Reset the power management statistics values.
785 */
786static int msm_pm_write_proc(struct file *file, const char __user *buffer,
787 unsigned long count, void *data)
788{
789 char buf[sizeof(MSM_PM_STATS_RESET)];
790 int ret;
791 unsigned long flags;
792 int i;
793
794 if (count < strlen(MSM_PM_STATS_RESET)) {
795 ret = -EINVAL;
796 goto write_proc_failed;
797 }
798
799 if (copy_from_user(buf, buffer, strlen(MSM_PM_STATS_RESET))) {
800 ret = -EFAULT;
801 goto write_proc_failed;
802 }
803
804 if (memcmp(buf, MSM_PM_STATS_RESET, strlen(MSM_PM_STATS_RESET))) {
805 ret = -EINVAL;
806 goto write_proc_failed;
807 }
808
809 local_irq_save(flags);
810 for (i = 0; i < ARRAY_SIZE(msm_pm_stats); i++) {
811 memset(msm_pm_stats[i].bucket,
812 0, sizeof(msm_pm_stats[i].bucket));
813 memset(msm_pm_stats[i].min_time,
814 0, sizeof(msm_pm_stats[i].min_time));
815 memset(msm_pm_stats[i].max_time,
816 0, sizeof(msm_pm_stats[i].max_time));
817 msm_pm_stats[i].count = 0;
818 msm_pm_stats[i].total_time = 0;
819 }
820
821 msm_pm_sleep_limit = SLEEP_LIMIT_NONE;
822 local_irq_restore(flags);
823
824 return count;
825
826write_proc_failed:
827 return ret;
828}
829#undef MSM_PM_STATS_RESET
830#endif /* CONFIG_MSM_IDLE_STATS */
831
832static int __init msm_pm_init(void)
833{
834#ifdef CONFIG_MSM_IDLE_STATS
835 struct proc_dir_entry *d_entry;
836#endif
837 int ret;
838
839 pm_power_off = msm_pm_power_off;
840 arm_pm_restart = msm_pm_restart;
841 msm_pm_max_sleep_time = 0;
842
843 register_reboot_notifier(&msm_reboot_notifier);
844
845 msm_pm_sma.sleep_delay = smem_alloc(SMEM_SMSM_SLEEP_DELAY,
846 sizeof(*msm_pm_sma.sleep_delay));
847 if (msm_pm_sma.sleep_delay == NULL) {
848 printk(KERN_ERR "msm_pm_init: failed get SLEEP_DELAY\n");
849 return -ENODEV;
850 }
851
852 msm_pm_sma.limit_sleep = smem_alloc(SMEM_SMSM_LIMIT_SLEEP,
853 sizeof(*msm_pm_sma.limit_sleep));
854 if (msm_pm_sma.limit_sleep == NULL) {
855 printk(KERN_ERR "msm_pm_init: failed get LIMIT_SLEEP\n");
856 return -ENODEV;
857 }
858
859 msm_pm_sma.int_info_ext = smem_alloc(SMEM_SMSM_INT_INFO,
860 sizeof(*msm_pm_sma.int_info_ext));
861
862 if (msm_pm_sma.int_info_ext)
863 msm_pm_sma.int_info = (struct smsm_interrupt_info *)
864 msm_pm_sma.int_info_ext;
865 else
866 msm_pm_sma.int_info = smem_alloc(SMEM_SMSM_INT_INFO,
867 sizeof(*msm_pm_sma.int_info));
868
869 if (msm_pm_sma.int_info == NULL) {
870 printk(KERN_ERR "msm_pm_init: failed get INT_INFO\n");
871 return -ENODEV;
872 }
873
874#if defined(CONFIG_ARCH_MSM_SCORPION) && !defined(CONFIG_MSM_SMP)
875 /* The bootloader is responsible for initializing many of Scorpion's
876 * coprocessor registers for things like cache timing. The state of
877 * these coprocessor registers is lost on reset, so part of the
878 * bootloader must be re-executed. Do not overwrite the reset vector
879 * or bootloader area.
880 */
881 msm_pm_reset_vector = (uint32_t *) PAGE_OFFSET;
882#else
883 msm_pm_reset_vector = ioremap(0, PAGE_SIZE);
884 if (msm_pm_reset_vector == NULL) {
885 printk(KERN_ERR "msm_pm_init: failed to map reset vector\n");
886 return -ENODEV;
887 }
888#endif /* CONFIG_ARCH_MSM_SCORPION */
889
890 ret = msm_timer_init_time_sync(msm_pm_timeout);
891 if (ret)
892 return ret;
893
894 BUG_ON(msm_pm_modes == NULL);
895
896 atomic_set(&msm_pm_init_done, 1);
897 suspend_set_ops(&msm_pm_ops);
898
899#ifdef CONFIG_MSM_IDLE_STATS
900 d_entry = create_proc_entry("msm_pm_stats",
901 S_IRUGO | S_IWUSR | S_IWGRP, NULL);
902 if (d_entry) {
903 d_entry->read_proc = msm_pm_read_proc;
904 d_entry->write_proc = msm_pm_write_proc;
905 d_entry->data = NULL;
906 }
907#endif
908
909 return 0;
910}
911
912void __init msm_pm_set_platform_data(
913 struct msm_pm_platform_data *data, int count)
914{
915 BUG_ON(MSM_PM_SLEEP_MODE_NR != count);
916 msm_pm_modes = data;
917}
918
919late_initcall(msm_pm_init);