Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux...
[pandora-kernel.git] / arch / arm / mach-mx5 / pm-imx5.c
1 /*
2  *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
3  *
4  * The code contained herein is licensed under the GNU General Public
5  * License. You may obtain a copy of the GNU General Public License
6  * Version 2 or later at the following locations:
7  *
8  * http://www.opensource.org/licenses/gpl-license.html
9  * http://www.gnu.org/copyleft/gpl.html
10  */
11 #include <linux/suspend.h>
12 #include <linux/clk.h>
13 #include <linux/io.h>
14 #include <linux/err.h>
15 #include <asm/cacheflush.h>
16 #include <asm/tlbflush.h>
17 #include <mach/system.h>
18 #include "crm_regs.h"
19
20 static struct clk *gpc_dvfs_clk;
21
22 static int mx5_suspend_enter(suspend_state_t state)
23 {
24         clk_enable(gpc_dvfs_clk);
25         switch (state) {
26         case PM_SUSPEND_MEM:
27                 mx5_cpu_lp_set(STOP_POWER_OFF);
28                 break;
29         case PM_SUSPEND_STANDBY:
30                 mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
31                 break;
32         default:
33                 return -EINVAL;
34         }
35
36         if (state == PM_SUSPEND_MEM) {
37                 local_flush_tlb_all();
38                 flush_cache_all();
39
40                 /*clear the EMPGC0/1 bits */
41                 __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
42                 __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
43         }
44         cpu_do_idle();
45         clk_disable(gpc_dvfs_clk);
46
47         return 0;
48 }
49
50 static int mx5_pm_valid(suspend_state_t state)
51 {
52         return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
53 }
54
55 static const struct platform_suspend_ops mx5_suspend_ops = {
56         .valid = mx5_pm_valid,
57         .enter = mx5_suspend_enter,
58 };
59
60 static int __init mx5_pm_init(void)
61 {
62         if (gpc_dvfs_clk == NULL)
63                 gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
64
65         if (!IS_ERR(gpc_dvfs_clk)) {
66                 if (cpu_is_mx51())
67                         suspend_set_ops(&mx5_suspend_ops);
68         } else
69                 return -EPERM;
70
71         return 0;
72 }
73 device_initcall(mx5_pm_init);