aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2013-08-20 11:30:19 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:01:23 -0400
commitc4b48f2fe3c15e63de453e9fa06096f29650db70 (patch)
tree469efc9d7ff12566a528f7d8e3ef165f78d66be1
parentd5954fd96aa9b7657e8ba43d48c34e12445115d0 (diff)
ENGR00275821-1 ARM: imx: rename pm-imx6q.c
To support all i.MX6 SOCs' suspend/resume, need to rename pm-imx6q.c to pm-imx6.c and move common code of ccm setting from platform specific clk file to pm-imx6.c to avoid duplicated code. Signed-off-by: Anson Huang <b20788@freescale.com>
-rw-r--r--arch/arm/mach-imx/Makefile4
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c187
-rw-r--r--arch/arm/mach-imx/common.h10
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6q.c6
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c2
-rw-r--r--arch/arm/mach-imx/pm-imx6.c333
-rw-r--r--arch/arm/mach-imx/pm-imx6q.c152
7 files changed, 346 insertions, 348 deletions
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 1a76d593e713..64aacbe49e61 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -102,9 +102,7 @@ obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o
102obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o 102obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o
103 103
104AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a 104AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
105ifeq ($(CONFIG_PM),y) 105obj-$(CONFIG_PM) += pm-imx6.o headsmp.o suspend-imx6.o
106obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o suspend-imx6.o
107endif
108 106
109# i.MX5 based machines 107# i.MX5 based machines
110obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o 108obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 549568df147c..77d17eca0d9b 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -14,7 +14,6 @@
14#include <linux/types.h> 14#include <linux/types.h>
15#include <linux/clk.h> 15#include <linux/clk.h>
16#include <linux/clkdev.h> 16#include <linux/clkdev.h>
17#include <linux/delay.h>
18#include <linux/err.h> 17#include <linux/err.h>
19#include <linux/io.h> 18#include <linux/io.h>
20#include <linux/of.h> 19#include <linux/of.h>
@@ -25,188 +24,6 @@
25#include "common.h" 24#include "common.h"
26#include "hardware.h" 25#include "hardware.h"
27 26
28#define CCR 0x0
29#define BM_CCR_WB_COUNT (0x7 << 16)
30#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21)
31#define BM_CCR_RBC_EN (0x1 << 27)
32
33#define CCGR0 0x68
34#define CCGR1 0x6c
35#define CCGR2 0x70
36#define CCGR3 0x74
37#define CCGR4 0x78
38#define CCGR5 0x7c
39#define CCGR6 0x80
40#define CCGR7 0x84
41
42#define CLPCR 0x54
43#define BP_CLPCR_LPM 0
44#define BM_CLPCR_LPM (0x3 << 0)
45#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
46#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
47#define BM_CLPCR_SBYOS (0x1 << 6)
48#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
49#define BM_CLPCR_VSTBY (0x1 << 8)
50#define BP_CLPCR_STBY_COUNT 9
51#define BM_CLPCR_STBY_COUNT (0x3 << 9)
52#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
53#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
54#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
55#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
56#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
57#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
58#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
59#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
60#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
61#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
62#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
63
64#define CGPR 0x64
65#define BM_CGPR_INT_MEM_CLK_LPM (0x1 << 17)
66
67#define MX6Q_INT_IOMUXC 32
68
69static void __iomem *ccm_base;
70
71void imx6q_set_cache_lpm_in_wait(bool enable)
72{
73 if ((cpu_is_imx6q() && imx_get_soc_revision() >
74 IMX_CHIP_REVISION_1_1) ||
75 (cpu_is_imx6dl() && imx_get_soc_revision() >
76 IMX_CHIP_REVISION_1_0)) {
77 u32 val;
78
79 val = readl_relaxed(ccm_base + CGPR);
80 if (enable)
81 val |= BM_CGPR_INT_MEM_CLK_LPM;
82 else
83 val &= ~BM_CGPR_INT_MEM_CLK_LPM;
84 writel_relaxed(val, ccm_base + CGPR);
85 }
86}
87
88static void imx6q_enable_rbc(bool enable)
89{
90 u32 val;
91 static bool last_rbc_mode;
92
93 if (last_rbc_mode == enable)
94 return;
95 /*
96 * need to mask all interrupts in GPC before
97 * operating RBC configurations
98 */
99 imx_gpc_mask_all();
100
101 /* configure RBC enable bit */
102 val = readl_relaxed(ccm_base + CCR);
103 val &= ~BM_CCR_RBC_EN;
104 val |= enable ? BM_CCR_RBC_EN : 0;
105 writel_relaxed(val, ccm_base + CCR);
106
107 /* configure RBC count */
108 val = readl_relaxed(ccm_base + CCR);
109 val &= ~BM_CCR_RBC_BYPASS_COUNT;
110 val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
111 writel(val, ccm_base + CCR);
112
113 /*
114 * need to delay at least 2 cycles of CKIL(32K)
115 * due to hardware design requirement, which is
116 * ~61us, here we use 65us for safe
117 */
118 udelay(65);
119
120 /* restore GPC interrupt mask settings */
121 imx_gpc_restore_all();
122
123 last_rbc_mode = enable;
124}
125
126static void imx6q_enable_wb(bool enable)
127{
128 u32 val;
129 static bool last_wb_mode;
130
131 if (last_wb_mode == enable)
132 return;
133
134 /* configure well bias enable bit */
135 val = readl_relaxed(ccm_base + CLPCR);
136 val &= ~BM_CLPCR_WB_PER_AT_LPM;
137 val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
138 writel_relaxed(val, ccm_base + CLPCR);
139
140 /* configure well bias count */
141 val = readl_relaxed(ccm_base + CCR);
142 val &= ~BM_CCR_WB_COUNT;
143 val |= enable ? BM_CCR_WB_COUNT : 0;
144 writel_relaxed(val, ccm_base + CCR);
145
146 last_wb_mode = enable;
147}
148
149int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
150{
151 u32 val = readl_relaxed(ccm_base + CLPCR);
152 struct irq_desc *desc = irq_to_desc(MX6Q_INT_IOMUXC);
153
154 /*
155 * CCM state machine has restriction, before enabling
156 * LPM mode, need to make sure last LPM mode is waked up
157 * by dsm_wakeup_signal, which means the wakeup source
158 * must be seen by GPC, then CCM will clean its state machine
159 * and re-sample necessary signal to decide whether it can
160 * enter LPM mode. We force irq #32 to be always pending,
161 * unmask it before we enable LPM mode and mask it after LPM
162 * is enabled, this flow will make sure CCM state machine in
163 * reliable status before entering LPM mode. Otherwise, CCM
164 * may enter LPM mode by mistake which will cause system bus
165 * locked by CPU access not finished, as when CCM enter
166 * LPM mode, CPU will stop running.
167 */
168 imx_gpc_irq_unmask(&desc->irq_data);
169
170 val &= ~BM_CLPCR_LPM;
171 switch (mode) {
172 case WAIT_CLOCKED:
173 imx6q_enable_wb(false);
174 imx6q_enable_rbc(false);
175 break;
176 case WAIT_UNCLOCKED:
177 val |= 0x1 << BP_CLPCR_LPM;
178 val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
179 break;
180 case STOP_POWER_ON:
181 val |= 0x2 << BP_CLPCR_LPM;
182 val &= ~BM_CLPCR_VSTBY;
183 val &= ~BM_CLPCR_SBYOS;
184 val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
185 break;
186 case WAIT_UNCLOCKED_POWER_OFF:
187 val |= 0x1 << BP_CLPCR_LPM;
188 val &= ~BM_CLPCR_VSTBY;
189 val &= ~BM_CLPCR_SBYOS;
190 break;
191 case STOP_POWER_OFF:
192 val |= 0x2 << BP_CLPCR_LPM;
193 val |= 0x3 << BP_CLPCR_STBY_COUNT;
194 val |= BM_CLPCR_VSTBY;
195 val |= BM_CLPCR_SBYOS;
196 val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
197 imx6q_enable_wb(true);
198 break;
199 default:
200 imx_gpc_irq_mask(&desc->irq_data);
201 return -EINVAL;
202 }
203
204 writel_relaxed(val, ccm_base + CLPCR);
205 imx_gpc_irq_mask(&desc->irq_data);
206
207 return 0;
208}
209
210static const char *step_sels[] = { "osc", "pll2_pfd2_396m", }; 27static const char *step_sels[] = { "osc", "pll2_pfd2_396m", };
211static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; 28static const char *pll1_sw_sels[] = { "pll1_sys", "step", };
212static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", }; 29static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
@@ -400,7 +217,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
400 np = ccm_node; 217 np = ccm_node;
401 base = of_iomap(np, 0); 218 base = of_iomap(np, 0);
402 WARN_ON(!base); 219 WARN_ON(!base);
403 ccm_base = base; 220 imx6_pm_set_ccm_base(base);
404 221
405 /* name reg shift width parent_names num_parents */ 222 /* name reg shift width parent_names num_parents */
406 clk[step] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); 223 clk[step] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels));
@@ -667,7 +484,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
667 pr_warn("failed to set up CLKO: %d\n", ret); 484 pr_warn("failed to set up CLKO: %d\n", ret);
668 485
669 /* Set initial power mode */ 486 /* Set initial power mode */
670 imx6q_set_lpm(WAIT_CLOCKED); 487 imx6_set_lpm(WAIT_CLOCKED);
671 488
672 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); 489 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
673 base = of_iomap(np, 0); 490 base = of_iomap(np, 0);
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 310867dbca88..ab19a1f839f6 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -143,18 +143,20 @@ extern void imx_gpc_restore_all(void);
143extern void imx_anatop_init(void); 143extern void imx_anatop_init(void);
144extern void imx_anatop_pre_suspend(void); 144extern void imx_anatop_pre_suspend(void);
145extern void imx_anatop_post_resume(void); 145extern void imx_anatop_post_resume(void);
146extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); 146extern int imx6_set_lpm(enum mxc_cpu_pwr_mode mode);
147extern void imx6q_set_cache_lpm_in_wait(bool enable); 147extern void imx6_set_cache_lpm_in_wait(bool enable);
148 148
149extern void imx_cpu_die(unsigned int cpu); 149extern void imx_cpu_die(unsigned int cpu);
150extern int imx_cpu_kill(unsigned int cpu); 150extern int imx_cpu_kill(unsigned int cpu);
151 151
152#ifdef CONFIG_PM 152#ifdef CONFIG_PM
153extern void imx6q_pm_init(void); 153extern void imx6_pm_init(void);
154extern void imx6_pm_set_ccm_base(void __iomem *base);
154extern void imx51_pm_init(void); 155extern void imx51_pm_init(void);
155extern void imx53_pm_init(void); 156extern void imx53_pm_init(void);
156#else 157#else
157static inline void imx6q_pm_init(void) {} 158static inline void imx6_pm_init(void) {}
159static inline void imx6_pm_set_ccm_base(void __iomem *base) {}
158static inline void imx51_pm_init(void) {} 160static inline void imx51_pm_init(void) {}
159static inline void imx53_pm_init(void) {} 161static inline void imx53_pm_init(void) {}
160#endif 162#endif
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c
index 8065e185daed..d74d0ce794ab 100644
--- a/arch/arm/mach-imx/cpuidle-imx6q.c
+++ b/arch/arm/mach-imx/cpuidle-imx6q.c
@@ -27,9 +27,9 @@ static int imx6q_enter_wait(struct cpuidle_device *dev,
27 */ 27 */
28 if (!spin_trylock(&master_lock)) 28 if (!spin_trylock(&master_lock))
29 goto idle; 29 goto idle;
30 imx6q_set_lpm(WAIT_UNCLOCKED); 30 imx6_set_lpm(WAIT_UNCLOCKED);
31 cpu_do_idle(); 31 cpu_do_idle();
32 imx6q_set_lpm(WAIT_CLOCKED); 32 imx6_set_lpm(WAIT_CLOCKED);
33 spin_unlock(&master_lock); 33 spin_unlock(&master_lock);
34 goto done; 34 goto done;
35 } 35 }
@@ -69,7 +69,7 @@ int __init imx6q_cpuidle_init(void)
69 imx_scu_standby_enable(); 69 imx_scu_standby_enable();
70 70
71 /* Set cache lpm bit for reliable WAIT mode support */ 71 /* Set cache lpm bit for reliable WAIT mode support */
72 imx6q_set_cache_lpm_in_wait(true); 72 imx6_set_cache_lpm_in_wait(true);
73 73
74 return cpuidle_register(&imx6q_cpuidle_driver, NULL); 74 return cpuidle_register(&imx6q_cpuidle_driver, NULL);
75} 75}
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index e1e334380534..cfa93827c9ad 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -213,7 +213,7 @@ static void __init imx6q_init_machine(void)
213 of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); 213 of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
214 214
215 imx_anatop_init(); 215 imx_anatop_init();
216 imx6q_pm_init(); 216 imx6_pm_init();
217 imx6q_1588_init(); 217 imx6q_1588_init();
218 imx6q_lvds_cabc_init(); 218 imx6q_lvds_cabc_init();
219} 219}
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
new file mode 100644
index 000000000000..e1c5eb5e03a1
--- /dev/null
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -0,0 +1,333 @@
1/*
2 * Copyright 2011-2013 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/delay.h>
14#include <linux/init.h>
15#include <linux/io.h>
16#include <linux/of.h>
17#include <linux/of_device.h>
18#include <linux/of_irq.h>
19#include <linux/suspend.h>
20#include <linux/genalloc.h>
21#include <asm/cacheflush.h>
22#include <asm/fncpy.h>
23#include <asm/proc-fns.h>
24#include <asm/suspend.h>
25#include <asm/hardware/cache-l2x0.h>
26#include <asm/mach/map.h>
27
28#include "common.h"
29#include "hardware.h"
30
31#define CCR 0x0
32#define BM_CCR_WB_COUNT (0x7 << 16)
33#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21)
34#define BM_CCR_RBC_EN (0x1 << 27)
35
36#define CLPCR 0x54
37#define BP_CLPCR_LPM 0
38#define BM_CLPCR_LPM (0x3 << 0)
39#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2)
40#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
41#define BM_CLPCR_SBYOS (0x1 << 6)
42#define BM_CLPCR_DIS_REF_OSC (0x1 << 7)
43#define BM_CLPCR_VSTBY (0x1 << 8)
44#define BP_CLPCR_STBY_COUNT 9
45#define BM_CLPCR_STBY_COUNT (0x3 << 9)
46#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11)
47#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16)
48#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17)
49#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19)
50#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21)
51#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22)
52#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23)
53#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24)
54#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25)
55#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
56#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
57
58#define CGPR 0x64
59#define BM_CGPR_INT_MEM_CLK_LPM (0x1 << 17)
60
61#define MX6_INT_IOMUXC 32
62
63static struct gen_pool *iram_pool;
64static void *suspend_iram_base;
65static unsigned long iram_size, iram_paddr;
66static int (*suspend_in_iram_fn)(void *iram_vbase,
67 unsigned long iram_pbase, unsigned int cpu_type);
68static unsigned int cpu_type;
69static void __iomem *ccm_base;
70
71void imx6_set_cache_lpm_in_wait(bool enable)
72{
73 if ((cpu_is_imx6q() && imx_get_soc_revision() >
74 IMX_CHIP_REVISION_1_1) ||
75 (cpu_is_imx6dl() && imx_get_soc_revision() >
76 IMX_CHIP_REVISION_1_0)) {
77 u32 val;
78
79 val = readl_relaxed(ccm_base + CGPR);
80 if (enable)
81 val |= BM_CGPR_INT_MEM_CLK_LPM;
82 else
83 val &= ~BM_CGPR_INT_MEM_CLK_LPM;
84 writel_relaxed(val, ccm_base + CGPR);
85 }
86}
87
88static void imx6_enable_rbc(bool enable)
89{
90 u32 val;
91 static bool last_rbc_mode;
92
93 if (last_rbc_mode == enable)
94 return;
95 /*
96 * need to mask all interrupts in GPC before
97 * operating RBC configurations
98 */
99 imx_gpc_mask_all();
100
101 /* configure RBC enable bit */
102 val = readl_relaxed(ccm_base + CCR);
103 val &= ~BM_CCR_RBC_EN;
104 val |= enable ? BM_CCR_RBC_EN : 0;
105 writel_relaxed(val, ccm_base + CCR);
106
107 /* configure RBC count */
108 val = readl_relaxed(ccm_base + CCR);
109 val &= ~BM_CCR_RBC_BYPASS_COUNT;
110 val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
111 writel(val, ccm_base + CCR);
112
113 /*
114 * need to delay at least 2 cycles of CKIL(32K)
115 * due to hardware design requirement, which is
116 * ~61us, here we use 65us for safe
117 */
118 udelay(65);
119
120 /* restore GPC interrupt mask settings */
121 imx_gpc_restore_all();
122
123 last_rbc_mode = enable;
124}
125
126static void imx6_enable_wb(bool enable)
127{
128 u32 val;
129 static bool last_wb_mode;
130
131 if (last_wb_mode == enable)
132 return;
133
134 /* configure well bias enable bit */
135 val = readl_relaxed(ccm_base + CLPCR);
136 val &= ~BM_CLPCR_WB_PER_AT_LPM;
137 val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
138 writel_relaxed(val, ccm_base + CLPCR);
139
140 /* configure well bias count */
141 val = readl_relaxed(ccm_base + CCR);
142 val &= ~BM_CCR_WB_COUNT;
143 val |= enable ? BM_CCR_WB_COUNT : 0;
144 writel_relaxed(val, ccm_base + CCR);
145
146 last_wb_mode = enable;
147}
148
149int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
150{
151 u32 val = readl_relaxed(ccm_base + CLPCR);
152 struct irq_desc *desc = irq_to_desc(MX6_INT_IOMUXC);
153
154 /*
155 * CCM state machine has restriction, before enabling
156 * LPM mode, need to make sure last LPM mode is waked up
157 * by dsm_wakeup_signal, which means the wakeup source
158 * must be seen by GPC, then CCM will clean its state machine
159 * and re-sample necessary signal to decide whether it can
160 * enter LPM mode. We force irq #32 to be always pending,
161 * unmask it before we enable LPM mode and mask it after LPM
162 * is enabled, this flow will make sure CCM state machine in
163 * reliable status before entering LPM mode. Otherwise, CCM
164 * may enter LPM mode by mistake which will cause system bus
165 * locked by CPU access not finished, as when CCM enter
166 * LPM mode, CPU will stop running.
167 */
168 imx_gpc_irq_unmask(&desc->irq_data);
169
170 val &= ~BM_CLPCR_LPM;
171 switch (mode) {
172 case WAIT_CLOCKED:
173 imx6_enable_wb(false);
174 imx6_enable_rbc(false);
175 break;
176 case WAIT_UNCLOCKED:
177 val |= 0x1 << BP_CLPCR_LPM;
178 val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
179 break;
180 case STOP_POWER_ON:
181 val |= 0x2 << BP_CLPCR_LPM;
182 val &= ~BM_CLPCR_VSTBY;
183 val &= ~BM_CLPCR_SBYOS;
184 val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
185 break;
186 case WAIT_UNCLOCKED_POWER_OFF:
187 val |= 0x1 << BP_CLPCR_LPM;
188 val &= ~BM_CLPCR_VSTBY;
189 val &= ~BM_CLPCR_SBYOS;
190 break;
191 case STOP_POWER_OFF:
192 val |= 0x2 << BP_CLPCR_LPM;
193 val |= 0x3 << BP_CLPCR_STBY_COUNT;
194 val |= BM_CLPCR_VSTBY;
195 val |= BM_CLPCR_SBYOS;
196 val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
197 imx6_enable_wb(true);
198 break;
199 default:
200 imx_gpc_irq_mask(&desc->irq_data);
201 return -EINVAL;
202 }
203
204 writel_relaxed(val, ccm_base + CLPCR);
205 imx_gpc_irq_mask(&desc->irq_data);
206
207 return 0;
208}
209
210static int imx6_suspend_finish(unsigned long val)
211{
212 /*
213 * call low level suspend function in iram,
214 * as we need to float DDR IO.
215 */
216 suspend_in_iram_fn(suspend_iram_base, iram_paddr, cpu_type);
217 return 0;
218}
219
220static int imx6_pm_enter(suspend_state_t state)
221{
222 switch (state) {
223 case PM_SUSPEND_STANDBY:
224 imx6_set_lpm(STOP_POWER_ON);
225 imx6_set_cache_lpm_in_wait(true);
226 imx_gpc_pre_suspend(false);
227 /* Zzz ... */
228 cpu_do_idle();
229 imx_gpc_post_resume();
230 imx6_set_lpm(WAIT_CLOCKED);
231 break;
232 case PM_SUSPEND_MEM:
233 imx6_set_cache_lpm_in_wait(false);
234 imx6_set_lpm(STOP_POWER_OFF);
235 imx_gpc_pre_suspend(true);
236 imx_anatop_pre_suspend();
237 imx_set_cpu_jump(0, v7_cpu_resume);
238 /* Zzz ... */
239 cpu_suspend(0, imx6_suspend_finish);
240 imx_smp_prepare();
241 imx_anatop_post_resume();
242 imx_gpc_post_resume();
243 imx6_set_cache_lpm_in_wait(true);
244 imx6_set_lpm(WAIT_CLOCKED);
245 break;
246 default:
247 return -EINVAL;
248 }
249
250 return 0;
251}
252
253static struct map_desc imx6_pm_io_desc[] __initdata = {
254 imx_map_entry(MX6Q, MMDC_P0, MT_DEVICE),
255 imx_map_entry(MX6Q, MMDC_P1, MT_DEVICE),
256 imx_map_entry(MX6Q, SRC, MT_DEVICE),
257 imx_map_entry(MX6Q, IOMUXC, MT_DEVICE),
258 imx_map_entry(MX6Q, CCM, MT_DEVICE),
259 imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
260 imx_map_entry(MX6Q, GPC, MT_DEVICE),
261 imx_map_entry(MX6Q, L2, MT_DEVICE),
262};
263
264void __init imx6_pm_map_io(void)
265{
266 iotable_init(imx6_pm_io_desc, ARRAY_SIZE(imx6_pm_io_desc));
267}
268
269static int imx6_pm_valid(suspend_state_t state)
270{
271 return (state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM);
272}
273
274static const struct platform_suspend_ops imx6_pm_ops = {
275 .enter = imx6_pm_enter,
276 .valid = imx6_pm_valid,
277};
278
279void imx6_pm_set_ccm_base(void __iomem *base)
280{
281 if (!base)
282 pr_warn("ccm base is NULL!\n");
283 ccm_base = base;
284}
285
286void __init imx6_pm_init(void)
287{
288 struct device_node *node;
289 unsigned long iram_base;
290 struct platform_device *pdev;
291
292 node = of_find_compatible_node(NULL, NULL, "mmio-sram");
293 if (!node) {
294 pr_err("failed to find ocram node!\n");
295 return;
296 }
297
298 pdev = of_find_device_by_node(node);
299 if (!pdev) {
300 pr_err("failed to find ocram device!\n");
301 return;
302 }
303
304 iram_pool = dev_get_gen_pool(&pdev->dev);
305 if (!iram_pool) {
306 pr_err("iram pool unavailable!\n");
307 return;
308 }
309
310 iram_size = MX6_SUSPEND_IRAM_SIZE;
311
312 iram_base = gen_pool_alloc(iram_pool, iram_size);
313 if (!iram_base) {
314 pr_err("unable to alloc iram!\n");
315 return;
316 }
317
318 iram_paddr = gen_pool_virt_to_phys(iram_pool, iram_base);
319
320 suspend_iram_base = __arm_ioremap(iram_paddr, iram_size,
321 MT_MEMORY_NONCACHED);
322
323 suspend_in_iram_fn = (void *)fncpy(suspend_iram_base,
324 &imx6_suspend, iram_size);
325
326 suspend_set_ops(&imx6_pm_ops);
327
328 /* Set cpu_type for DSM */
329 if (cpu_is_imx6q())
330 cpu_type = MXC_CPU_IMX6Q;
331 else if (cpu_is_imx6dl())
332 cpu_type = MXC_CPU_IMX6DL;
333}
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
deleted file mode 100644
index 637653b81db9..000000000000
--- a/arch/arm/mach-imx/pm-imx6q.c
+++ /dev/null
@@ -1,152 +0,0 @@
1/*
2 * Copyright 2011-2013 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd.
4 *
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/of.h>
16#include <linux/of_device.h>
17#include <linux/suspend.h>
18#include <linux/genalloc.h>
19#include <asm/cacheflush.h>
20#include <asm/fncpy.h>
21#include <asm/proc-fns.h>
22#include <asm/suspend.h>
23#include <asm/hardware/cache-l2x0.h>
24#include <asm/mach/map.h>
25
26#include "common.h"
27#include "hardware.h"
28
29static struct gen_pool *iram_pool;
30static void *suspend_iram_base;
31static unsigned long iram_size, iram_paddr;
32static int (*suspend_in_iram_fn)(void *iram_vbase,
33 unsigned long iram_pbase, unsigned int cpu_type);
34static unsigned int cpu_type;
35
36static int imx6q_suspend_finish(unsigned long val)
37{
38 /*
39 * call low level suspend function in iram,
40 * as we need to float DDR IO.
41 */
42 suspend_in_iram_fn(suspend_iram_base, iram_paddr, cpu_type);
43 return 0;
44}
45
46static int imx6q_pm_enter(suspend_state_t state)
47{
48 switch (state) {
49 case PM_SUSPEND_STANDBY:
50 imx6q_set_lpm(STOP_POWER_ON);
51 imx6q_set_cache_lpm_in_wait(true);
52 imx_gpc_pre_suspend(false);
53 /* Zzz ... */
54 cpu_do_idle();
55 imx_gpc_post_resume();
56 imx6q_set_lpm(WAIT_CLOCKED);
57 break;
58 case PM_SUSPEND_MEM:
59 imx6q_set_cache_lpm_in_wait(false);
60 imx6q_set_lpm(STOP_POWER_OFF);
61 imx_gpc_pre_suspend(true);
62 imx_anatop_pre_suspend();
63 imx_set_cpu_jump(0, v7_cpu_resume);
64 /* Zzz ... */
65 cpu_suspend(0, imx6q_suspend_finish);
66 imx_smp_prepare();
67 imx_anatop_post_resume();
68 imx_gpc_post_resume();
69 imx6q_set_cache_lpm_in_wait(true);
70 imx6q_set_lpm(WAIT_CLOCKED);
71 break;
72 default:
73 return -EINVAL;
74 }
75
76 return 0;
77}
78
79static struct map_desc imx6_pm_io_desc[] __initdata = {
80 imx_map_entry(MX6Q, MMDC_P0, MT_DEVICE),
81 imx_map_entry(MX6Q, MMDC_P1, MT_DEVICE),
82 imx_map_entry(MX6Q, SRC, MT_DEVICE),
83 imx_map_entry(MX6Q, IOMUXC, MT_DEVICE),
84 imx_map_entry(MX6Q, CCM, MT_DEVICE),
85 imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
86 imx_map_entry(MX6Q, GPC, MT_DEVICE),
87 imx_map_entry(MX6Q, L2, MT_DEVICE),
88};
89
90void __init imx6_pm_map_io(void)
91{
92 iotable_init(imx6_pm_io_desc, ARRAY_SIZE(imx6_pm_io_desc));
93}
94
95static int imx6q_pm_valid(suspend_state_t state)
96{
97 return (state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM);
98}
99
100static const struct platform_suspend_ops imx6q_pm_ops = {
101 .enter = imx6q_pm_enter,
102 .valid = imx6q_pm_valid,
103};
104
105void __init imx6q_pm_init(void)
106{
107 struct device_node *node;
108 unsigned long iram_base;
109 struct platform_device *pdev;
110
111 node = of_find_compatible_node(NULL, NULL, "mmio-sram");
112 if (!node) {
113 pr_err("failed to find ocram node!\n");
114 return;
115 }
116
117 pdev = of_find_device_by_node(node);
118 if (!pdev) {
119 pr_err("failed to find ocram device!\n");
120 return;
121 }
122
123 iram_pool = dev_get_gen_pool(&pdev->dev);
124 if (!iram_pool) {
125 pr_err("iram pool unavailable!\n");
126 return;
127 }
128
129 iram_size = MX6_SUSPEND_IRAM_SIZE;
130
131 iram_base = gen_pool_alloc(iram_pool, iram_size);
132 if (!iram_base) {
133 pr_err("unable to alloc iram!\n");
134 return;
135 }
136
137 iram_paddr = gen_pool_virt_to_phys(iram_pool, iram_base);
138
139 suspend_iram_base = __arm_ioremap(iram_paddr, iram_size,
140 MT_MEMORY_NONCACHED);
141
142 suspend_in_iram_fn = (void *)fncpy(suspend_iram_base,
143 &imx6_suspend, iram_size);
144
145 suspend_set_ops(&imx6q_pm_ops);
146
147 /* Set cpu_type for DSM */
148 if (cpu_is_imx6q())
149 cpu_type = MXC_CPU_IMX6Q;
150 else if (cpu_is_imx6dl())
151 cpu_type = MXC_CPU_IMX6DL;
152}