1 /* linux/arch/arm/mach-s5pv310/cpuidle.c
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/platform_device.h>
14 #include <linux/cpuidle.h>
16 #include <linux/dma-mapping.h>
17 #include <linux/rfkill.h>
19 #include <asm/proc-fns.h>
20 #include <asm/cacheflush.h>
21 #include <asm/hardware/cache-l2x0.h>
25 #include <plat/devs.h>
26 #include <plat/s5pv310.h>
27 #include <plat/regs-otg.h>
29 #include <mach/regs-clock.h>
30 #include <mach/regs-pmu.h>
31 #include <mach/gpio.h>
32 #include <mach/regs-gpio.h>
34 #include <mach/ext-gic.h>
36 #define MAX_CHK_DEV 0xf
38 #define REG_DIRECTGO_ADDR (s5pv310_subrev() == 0 ?\
39 (S5P_VA_SYSRAM + 0x24) : S5P_INFORM7)
40 #define REG_DIRECTGO_FLAG (s5pv310_subrev() == 0 ?\
41 (S5P_VA_SYSRAM + 0x20) : S5P_INFORM6)
43 static unsigned int cpu_core;
44 static unsigned int old_div;
45 /* Shared with pm-hotplug.c, which waits for idle to complete */
46 DEFINE_SPINLOCK(idle_lock);
47 bool hotplugging = false;
55 struct check_device_op {
57 struct platform_device *pdev;
61 static struct check_device_op chk_dev_op[] = {
62 #if defined(CONFIG_S3C_DEV_HSMMC)
63 {.base = 0, .pdev = &s3c_device_hsmmc0, .type = HC_SDHCI},
65 #if defined(CONFIG_S3C_DEV_HSMMC1)
66 {.base = 0, .pdev = &s3c_device_hsmmc1, .type = HC_SDHCI},
68 #if defined(CONFIG_S3C_DEV_HSMMC2)
69 {.base = 0, .pdev = &s3c_device_hsmmc2, .type = HC_SDHCI},
71 #if defined(CONFIG_S3C_DEV_HSMMC3)
72 {.base = 0, .pdev = &s3c_device_hsmmc3, .type = HC_SDHCI},
74 #if defined(CONFIG_S3C_DEV_HSMMC4)
75 {.base = 0, .pdev = &s3c_device_hsmmc4, .type = HC_MSHCI},
79 static unsigned long *regs_save;
80 static dma_addr_t phy_regs_save;
82 static struct sleep_save s5pv310_aftr_save[] = {
84 #ifndef CONFIG_USE_EXT_GIC
85 SAVE_ITEM(S5P_VA_GIC_CPU + 0x000),
86 SAVE_ITEM(S5P_VA_GIC_CPU + 0x004),
87 SAVE_ITEM(S5P_VA_GIC_CPU + 0x008),
88 SAVE_ITEM(S5P_VA_GIC_CPU + 0x014),
89 SAVE_ITEM(S5P_VA_GIC_CPU + 0x018),
90 SAVE_ITEM(S5P_VA_GIC_DIST + 0x000),
91 SAVE_ITEM(S5P_VA_GIC_DIST + 0x004),
92 SAVE_ITEM(S5P_VA_GIC_DIST + 0x100),
93 SAVE_ITEM(S5P_VA_GIC_DIST + 0x104),
94 SAVE_ITEM(S5P_VA_GIC_DIST + 0x108),
95 SAVE_ITEM(S5P_VA_GIC_DIST + 0x300),
96 SAVE_ITEM(S5P_VA_GIC_DIST + 0x304),
97 SAVE_ITEM(S5P_VA_GIC_DIST + 0x308),
98 SAVE_ITEM(S5P_VA_GIC_DIST + 0x400),
99 SAVE_ITEM(S5P_VA_GIC_DIST + 0x404),
100 SAVE_ITEM(S5P_VA_GIC_DIST + 0x408),
101 SAVE_ITEM(S5P_VA_GIC_DIST + 0x40C),
102 SAVE_ITEM(S5P_VA_GIC_DIST + 0x410),
103 SAVE_ITEM(S5P_VA_GIC_DIST + 0x414),
104 SAVE_ITEM(S5P_VA_GIC_DIST + 0x418),
105 SAVE_ITEM(S5P_VA_GIC_DIST + 0x41C),
106 SAVE_ITEM(S5P_VA_GIC_DIST + 0x420),
107 SAVE_ITEM(S5P_VA_GIC_DIST + 0x424),
108 SAVE_ITEM(S5P_VA_GIC_DIST + 0x428),
109 SAVE_ITEM(S5P_VA_GIC_DIST + 0x42C),
110 SAVE_ITEM(S5P_VA_GIC_DIST + 0x430),
111 SAVE_ITEM(S5P_VA_GIC_DIST + 0x434),
112 SAVE_ITEM(S5P_VA_GIC_DIST + 0x438),
113 SAVE_ITEM(S5P_VA_GIC_DIST + 0x43C),
114 SAVE_ITEM(S5P_VA_GIC_DIST + 0x440),
115 SAVE_ITEM(S5P_VA_GIC_DIST + 0x444),
116 SAVE_ITEM(S5P_VA_GIC_DIST + 0x448),
117 SAVE_ITEM(S5P_VA_GIC_DIST + 0x44C),
118 SAVE_ITEM(S5P_VA_GIC_DIST + 0x450),
119 SAVE_ITEM(S5P_VA_GIC_DIST + 0x454),
120 SAVE_ITEM(S5P_VA_GIC_DIST + 0x458),
121 SAVE_ITEM(S5P_VA_GIC_DIST + 0x45C),
123 SAVE_ITEM(S5P_VA_GIC_DIST + 0x800),
124 SAVE_ITEM(S5P_VA_GIC_DIST + 0x804),
125 SAVE_ITEM(S5P_VA_GIC_DIST + 0x808),
126 SAVE_ITEM(S5P_VA_GIC_DIST + 0x80C),
127 SAVE_ITEM(S5P_VA_GIC_DIST + 0x810),
128 SAVE_ITEM(S5P_VA_GIC_DIST + 0x814),
129 SAVE_ITEM(S5P_VA_GIC_DIST + 0x818),
130 SAVE_ITEM(S5P_VA_GIC_DIST + 0x81C),
131 SAVE_ITEM(S5P_VA_GIC_DIST + 0x820),
132 SAVE_ITEM(S5P_VA_GIC_DIST + 0x824),
133 SAVE_ITEM(S5P_VA_GIC_DIST + 0x828),
134 SAVE_ITEM(S5P_VA_GIC_DIST + 0x82C),
135 SAVE_ITEM(S5P_VA_GIC_DIST + 0x830),
136 SAVE_ITEM(S5P_VA_GIC_DIST + 0x834),
137 SAVE_ITEM(S5P_VA_GIC_DIST + 0x838),
138 SAVE_ITEM(S5P_VA_GIC_DIST + 0x83C),
139 SAVE_ITEM(S5P_VA_GIC_DIST + 0x840),
140 SAVE_ITEM(S5P_VA_GIC_DIST + 0x844),
141 SAVE_ITEM(S5P_VA_GIC_DIST + 0x848),
142 SAVE_ITEM(S5P_VA_GIC_DIST + 0x84C),
143 SAVE_ITEM(S5P_VA_GIC_DIST + 0x850),
144 SAVE_ITEM(S5P_VA_GIC_DIST + 0x854),
145 SAVE_ITEM(S5P_VA_GIC_DIST + 0x858),
146 SAVE_ITEM(S5P_VA_GIC_DIST + 0x85C),
148 SAVE_ITEM(S5P_VA_GIC_DIST + 0xC00),
149 SAVE_ITEM(S5P_VA_GIC_DIST + 0xC04),
150 SAVE_ITEM(S5P_VA_GIC_DIST + 0xC08),
151 SAVE_ITEM(S5P_VA_GIC_DIST + 0xC0C),
152 SAVE_ITEM(S5P_VA_GIC_DIST + 0xC10),
153 SAVE_ITEM(S5P_VA_GIC_DIST + 0xC14),
155 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x000),
156 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x010),
157 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x020),
158 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x030),
159 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x040),
160 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x050),
161 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x060),
162 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070),
163 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080),
164 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090),
165 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x0C0),
166 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x0D0),
170 static struct sleep_save s5pv310_lpa_save[] = {
172 #ifndef CONFIG_USE_EXT_GIC
173 SAVE_ITEM(S5P_VA_GIC_CPU + 0x000),
174 SAVE_ITEM(S5P_VA_GIC_CPU + 0x004),
175 SAVE_ITEM(S5P_VA_GIC_CPU + 0x008),
176 SAVE_ITEM(S5P_VA_GIC_CPU + 0x014),
177 SAVE_ITEM(S5P_VA_GIC_CPU + 0x018),
178 SAVE_ITEM(S5P_VA_GIC_DIST + 0x000),
179 SAVE_ITEM(S5P_VA_GIC_DIST + 0x004),
180 SAVE_ITEM(S5P_VA_GIC_DIST + 0x100),
181 SAVE_ITEM(S5P_VA_GIC_DIST + 0x104),
182 SAVE_ITEM(S5P_VA_GIC_DIST + 0x108),
183 SAVE_ITEM(S5P_VA_GIC_DIST + 0x300),
184 SAVE_ITEM(S5P_VA_GIC_DIST + 0x304),
185 SAVE_ITEM(S5P_VA_GIC_DIST + 0x308),
186 SAVE_ITEM(S5P_VA_GIC_DIST + 0x400),
187 SAVE_ITEM(S5P_VA_GIC_DIST + 0x404),
188 SAVE_ITEM(S5P_VA_GIC_DIST + 0x408),
189 SAVE_ITEM(S5P_VA_GIC_DIST + 0x40C),
190 SAVE_ITEM(S5P_VA_GIC_DIST + 0x410),
191 SAVE_ITEM(S5P_VA_GIC_DIST + 0x414),
192 SAVE_ITEM(S5P_VA_GIC_DIST + 0x418),
193 SAVE_ITEM(S5P_VA_GIC_DIST + 0x41C),
194 SAVE_ITEM(S5P_VA_GIC_DIST + 0x420),
195 SAVE_ITEM(S5P_VA_GIC_DIST + 0x424),
196 SAVE_ITEM(S5P_VA_GIC_DIST + 0x428),
197 SAVE_ITEM(S5P_VA_GIC_DIST + 0x42C),
198 SAVE_ITEM(S5P_VA_GIC_DIST + 0x430),
199 SAVE_ITEM(S5P_VA_GIC_DIST + 0x434),
200 SAVE_ITEM(S5P_VA_GIC_DIST + 0x438),
201 SAVE_ITEM(S5P_VA_GIC_DIST + 0x43C),
202 SAVE_ITEM(S5P_VA_GIC_DIST + 0x440),
203 SAVE_ITEM(S5P_VA_GIC_DIST + 0x444),
204 SAVE_ITEM(S5P_VA_GIC_DIST + 0x448),
205 SAVE_ITEM(S5P_VA_GIC_DIST + 0x44C),
206 SAVE_ITEM(S5P_VA_GIC_DIST + 0x450),
207 SAVE_ITEM(S5P_VA_GIC_DIST + 0x454),
208 SAVE_ITEM(S5P_VA_GIC_DIST + 0x458),
209 SAVE_ITEM(S5P_VA_GIC_DIST + 0x45C),
211 SAVE_ITEM(S5P_VA_GIC_DIST + 0x800),
212 SAVE_ITEM(S5P_VA_GIC_DIST + 0x804),
213 SAVE_ITEM(S5P_VA_GIC_DIST + 0x808),
214 SAVE_ITEM(S5P_VA_GIC_DIST + 0x80C),
215 SAVE_ITEM(S5P_VA_GIC_DIST + 0x810),
216 SAVE_ITEM(S5P_VA_GIC_DIST + 0x814),
217 SAVE_ITEM(S5P_VA_GIC_DIST + 0x818),
218 SAVE_ITEM(S5P_VA_GIC_DIST + 0x81C),
219 SAVE_ITEM(S5P_VA_GIC_DIST + 0x820),
220 SAVE_ITEM(S5P_VA_GIC_DIST + 0x824),
221 SAVE_ITEM(S5P_VA_GIC_DIST + 0x828),
222 SAVE_ITEM(S5P_VA_GIC_DIST + 0x82C),
223 SAVE_ITEM(S5P_VA_GIC_DIST + 0x830),
224 SAVE_ITEM(S5P_VA_GIC_DIST + 0x834),
225 SAVE_ITEM(S5P_VA_GIC_DIST + 0x838),
226 SAVE_ITEM(S5P_VA_GIC_DIST + 0x83C),
227 SAVE_ITEM(S5P_VA_GIC_DIST + 0x840),
228 SAVE_ITEM(S5P_VA_GIC_DIST + 0x844),
229 SAVE_ITEM(S5P_VA_GIC_DIST + 0x848),
230 SAVE_ITEM(S5P_VA_GIC_DIST + 0x84C),
231 SAVE_ITEM(S5P_VA_GIC_DIST + 0x850),
232 SAVE_ITEM(S5P_VA_GIC_DIST + 0x854),
233 SAVE_ITEM(S5P_VA_GIC_DIST + 0x858),
234 SAVE_ITEM(S5P_VA_GIC_DIST + 0x85C),
236 SAVE_ITEM(S5P_VA_GIC_DIST + 0xC00),
237 SAVE_ITEM(S5P_VA_GIC_DIST + 0xC04),
238 SAVE_ITEM(S5P_VA_GIC_DIST + 0xC08),
239 SAVE_ITEM(S5P_VA_GIC_DIST + 0xC0C),
240 SAVE_ITEM(S5P_VA_GIC_DIST + 0xC10),
241 SAVE_ITEM(S5P_VA_GIC_DIST + 0xC14),
243 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x000),
244 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x010),
245 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x020),
246 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x030),
247 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x040),
248 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x050),
249 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x060),
250 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070),
251 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080),
252 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090),
253 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x0C0),
254 SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x0D0),
257 SAVE_ITEM(S5P_CLKSRC_MASK_TOP),
258 SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
259 SAVE_ITEM(S5P_CLKSRC_MASK_TV),
260 SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
261 SAVE_ITEM(S5P_CLKSRC_MASK_LCD1),
262 SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO),
263 SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
264 SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
265 SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
266 SAVE_ITEM(S5P_CLKSRC_MASK_DMC),
269 static struct sleep_save s5pv310_aftr[] = {
270 { .reg = S5P_ARM_CORE0_LOWPWR , .val = 0x0, },
271 { .reg = S5P_DIS_IRQ_CORE0 , .val = 0x0, },
272 { .reg = S5P_DIS_IRQ_CENTRAL0 , .val = 0x0, },
273 { .reg = S5P_ARM_CORE1_LOWPWR , .val = 0x0, },
274 { .reg = S5P_DIS_IRQ_CORE1 , .val = 0x0, },
275 { .reg = S5P_DIS_IRQ_CENTRAL1 , .val = 0x0, },
276 { .reg = S5P_ARM_COMMON_LOWPWR , .val = 0x0, },
277 { .reg = S5P_L2_0_LOWPWR , .val = 0x2, },
278 { .reg = S5P_L2_1_LOWPWR , .val = 0x2, },
279 { .reg = S5P_CMU_ACLKSTOP_LOWPWR , .val = 0x1, },
280 { .reg = S5P_CMU_SCLKSTOP_LOWPWR , .val = 0x1, },
281 { .reg = S5P_CMU_RESET_LOWPWR , .val = 0x1, },
282 { .reg = S5P_APLL_SYSCLK_LOWPWR , .val = 0x1, },
283 { .reg = S5P_MPLL_SYSCLK_LOWPWR , .val = 0x1, },
284 { .reg = S5P_VPLL_SYSCLK_LOWPWR , .val = 0x1, },
285 { .reg = S5P_EPLL_SYSCLK_LOWPWR , .val = 0x1, },
286 { .reg = S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR , .val = 0x1, },
287 { .reg = S5P_CMU_RESET_GPSALIVE_LOWPWR , .val = 0x1, },
288 { .reg = S5P_CMU_CLKSTOP_CAM_LOWPWR , .val = 0x1, },
289 { .reg = S5P_CMU_CLKSTOP_TV_LOWPWR , .val = 0x1, },
290 { .reg = S5P_CMU_CLKSTOP_MFC_LOWPWR , .val = 0x1, },
291 { .reg = S5P_CMU_CLKSTOP_G3D_LOWPWR , .val = 0x1, },
292 { .reg = S5P_CMU_CLKSTOP_LCD0_LOWPWR , .val = 0x1, },
293 { .reg = S5P_CMU_CLKSTOP_LCD1_LOWPWR , .val = 0x1, },
294 { .reg = S5P_CMU_CLKSTOP_MAUDIO_LOWPWR , .val = 0x1, },
295 { .reg = S5P_CMU_CLKSTOP_GPS_LOWPWR , .val = 0x1, },
296 { .reg = S5P_CMU_RESET_CAM_LOWPWR , .val = 0x1, },
297 { .reg = S5P_CMU_RESET_TV_LOWPWR , .val = 0x1, },
298 { .reg = S5P_CMU_RESET_MFC_LOWPWR , .val = 0x1, },
299 { .reg = S5P_CMU_RESET_G3D_LOWPWR , .val = 0x1, },
300 { .reg = S5P_CMU_RESET_LCD0_LOWPWR , .val = 0x1, },
301 { .reg = S5P_CMU_RESET_LCD1_LOWPWR , .val = 0x1, },
302 { .reg = S5P_CMU_RESET_MAUDIO_LOWPWR , .val = 0x1, },
303 { .reg = S5P_CMU_RESET_GPS_LOWPWR , .val = 0x1, },
304 { .reg = S5P_TOP_BUS_LOWPWR , .val = 0x3, },
305 { .reg = S5P_TOP_RETENTION_LOWPWR , .val = 0x1, },
306 { .reg = S5P_TOP_PWR_LOWPWR , .val = 0x3, },
307 { .reg = S5P_LOGIC_RESET_LOWPWR , .val = 0x1, },
308 { .reg = S5P_ONENAND_MEM_LOWPWR , .val = 0x3, },
309 { .reg = S5P_MODIMIF_MEM_LOWPWR , .val = 0x3, },
310 { .reg = S5P_G2D_ACP_MEM_LOWPWR , .val = 0x3, },
311 { .reg = S5P_USBOTG_MEM_LOWPWR , .val = 0x3, },
312 { .reg = S5P_HSMMC_MEM_LOWPWR , .val = 0x3, },
313 { .reg = S5P_CSSYS_MEM_LOWPWR , .val = 0x3, },
314 { .reg = S5P_SECSS_MEM_LOWPWR , .val = 0x3, },
315 { .reg = S5P_PCIE_MEM_LOWPWR , .val = 0x3, },
316 { .reg = S5P_SATA_MEM_LOWPWR , .val = 0x3, },
317 { .reg = S5P_PAD_RETENTION_DRAM_LOWPWR , .val = 0x1, },
318 { .reg = S5P_PAD_RETENTION_MAUDIO_LOWPWR , .val = 0x1, },
319 { .reg = S5P_PAD_RETENTION_GPIO_LOWPWR , .val = 0x1, },
320 { .reg = S5P_PAD_RETENTION_UART_LOWPWR , .val = 0x1, },
321 { .reg = S5P_PAD_RETENTION_MMCA_LOWPWR , .val = 0x1, },
322 { .reg = S5P_PAD_RETENTION_MMCB_LOWPWR , .val = 0x1, },
323 { .reg = S5P_PAD_RETENTION_EBIA_LOWPWR , .val = 0x1, },
324 { .reg = S5P_PAD_RETENTION_EBIB_LOWPWR , .val = 0x1, },
325 { .reg = S5P_PAD_RETENTION_ISOLATION_LOWPWR , .val = 0x1, },
326 { .reg = S5P_PAD_RETENTION_ALV_SEL_LOWPWR , .val = 0x1, },
327 { .reg = S5P_XUSBXTI_LOWPWR , .val = 0x1, },
328 { .reg = S5P_XXTI_LOWPWR , .val = 0x1, },
329 { .reg = S5P_EXT_REGULATOR_LOWPWR , .val = 0x1, },
330 { .reg = S5P_GPIO_MODE_LOWPWR , .val = 0x1, },
331 { .reg = S5P_GPIO_MODE_MAUDIO_LOWPWR , .val = 0x1, },
332 { .reg = S5P_CAM_LOWPWR , .val = 0x7, },
333 { .reg = S5P_TV_LOWPWR , .val = 0x7, },
334 { .reg = S5P_MFC_LOWPWR , .val = 0x7, },
335 { .reg = S5P_G3D_LOWPWR , .val = 0x7, },
336 { .reg = S5P_LCD0_LOWPWR , .val = 0x7, },
337 { .reg = S5P_LCD1_LOWPWR , .val = 0x7, },
338 { .reg = S5P_MAUDIO_LOWPWR , .val = 0x7, },
339 { .reg = S5P_GPS_LOWPWR , .val = 0x7, },
340 { .reg = S5P_GPS_ALIVE_LOWPWR , .val = 0x7, },
343 static struct sleep_save s5pv310_lpa[] = {
344 { .reg = S5P_ARM_CORE0_LOWPWR , .val = 0x0, },
345 { .reg = S5P_DIS_IRQ_CORE0 , .val = 0x0, },
346 { .reg = S5P_DIS_IRQ_CENTRAL0 , .val = 0x0, },
347 { .reg = S5P_ARM_CORE1_LOWPWR , .val = 0x0, },
348 { .reg = S5P_DIS_IRQ_CORE1 , .val = 0x0, },
349 { .reg = S5P_DIS_IRQ_CENTRAL1 , .val = 0x0, },
350 { .reg = S5P_ARM_COMMON_LOWPWR , .val = 0x0, },
351 { .reg = S5P_L2_0_LOWPWR , .val = 0x2, },
352 { .reg = S5P_L2_1_LOWPWR , .val = 0x2, },
353 { .reg = S5P_CMU_ACLKSTOP_LOWPWR , .val = 0x0, },
354 { .reg = S5P_CMU_SCLKSTOP_LOWPWR , .val = 0x0, },
355 { .reg = S5P_CMU_RESET_LOWPWR , .val = 0x1, },
356 { .reg = S5P_APLL_SYSCLK_LOWPWR , .val = 0x0, },
357 { .reg = S5P_MPLL_SYSCLK_LOWPWR , .val = 0x0, },
358 { .reg = S5P_VPLL_SYSCLK_LOWPWR , .val = 0x0, },
359 { .reg = S5P_EPLL_SYSCLK_LOWPWR , .val = 0x1, },
360 { .reg = S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR , .val = 0x1, },
361 { .reg = S5P_CMU_RESET_GPSALIVE_LOWPWR , .val = 0x1, },
362 { .reg = S5P_CMU_CLKSTOP_CAM_LOWPWR , .val = 0x1, },
363 { .reg = S5P_CMU_CLKSTOP_TV_LOWPWR , .val = 0x1, },
364 { .reg = S5P_CMU_CLKSTOP_MFC_LOWPWR , .val = 0x1, },
365 { .reg = S5P_CMU_CLKSTOP_G3D_LOWPWR , .val = 0x1, },
366 { .reg = S5P_CMU_CLKSTOP_LCD0_LOWPWR , .val = 0x1, },
367 { .reg = S5P_CMU_CLKSTOP_LCD1_LOWPWR , .val = 0x1, },
368 { .reg = S5P_CMU_CLKSTOP_MAUDIO_LOWPWR , .val = 0x1, },
369 { .reg = S5P_CMU_CLKSTOP_GPS_LOWPWR , .val = 0x1, },
370 { .reg = S5P_CMU_RESET_CAM_LOWPWR , .val = 0x1, },
371 { .reg = S5P_CMU_RESET_TV_LOWPWR , .val = 0x1, },
372 { .reg = S5P_CMU_RESET_MFC_LOWPWR , .val = 0x1, },
373 { .reg = S5P_CMU_RESET_G3D_LOWPWR , .val = 0x1, },
374 { .reg = S5P_CMU_RESET_LCD0_LOWPWR , .val = 0x1, },
375 { .reg = S5P_CMU_RESET_LCD1_LOWPWR , .val = 0x1, },
376 { .reg = S5P_CMU_RESET_MAUDIO_LOWPWR , .val = 0x1, },
377 { .reg = S5P_CMU_RESET_GPS_LOWPWR , .val = 0x1, },
378 { .reg = S5P_TOP_BUS_LOWPWR , .val = 0x0, },
379 { .reg = S5P_TOP_RETENTION_LOWPWR , .val = 0x0, },
380 { .reg = S5P_TOP_PWR_LOWPWR , .val = 0x0, },
381 { .reg = S5P_LOGIC_RESET_LOWPWR , .val = 0x1, },
382 { .reg = S5P_ONENAND_MEM_LOWPWR , .val = 0x0, },
383 { .reg = S5P_MODIMIF_MEM_LOWPWR , .val = 0x0, },
384 { .reg = S5P_G2D_ACP_MEM_LOWPWR , .val = 0x0, },
385 { .reg = S5P_USBOTG_MEM_LOWPWR , .val = 0x0, },
386 { .reg = S5P_HSMMC_MEM_LOWPWR , .val = 0x0, },
387 { .reg = S5P_CSSYS_MEM_LOWPWR , .val = 0x0, },
388 { .reg = S5P_SECSS_MEM_LOWPWR , .val = 0x0, },
389 { .reg = S5P_PCIE_MEM_LOWPWR , .val = 0x0, },
390 { .reg = S5P_SATA_MEM_LOWPWR , .val = 0x0, },
391 { .reg = S5P_PAD_RETENTION_DRAM_LOWPWR , .val = 0x0, },
392 { .reg = S5P_PAD_RETENTION_MAUDIO_LOWPWR , .val = 0x1, },
393 { .reg = S5P_PAD_RETENTION_GPIO_LOWPWR , .val = 0x0, },
394 { .reg = S5P_PAD_RETENTION_UART_LOWPWR , .val = 0x0, },
395 { .reg = S5P_PAD_RETENTION_MMCA_LOWPWR , .val = 0x0, },
396 { .reg = S5P_PAD_RETENTION_MMCB_LOWPWR , .val = 0x0, },
397 { .reg = S5P_PAD_RETENTION_EBIA_LOWPWR , .val = 0x0, },
398 { .reg = S5P_PAD_RETENTION_EBIB_LOWPWR , .val = 0x0, },
399 { .reg = S5P_PAD_RETENTION_ISOLATION_LOWPWR , .val = 0x0, },
400 { .reg = S5P_PAD_RETENTION_ALV_SEL_LOWPWR , .val = 0x0, },
401 { .reg = S5P_XUSBXTI_LOWPWR , .val = 0x1, },
402 { .reg = S5P_XXTI_LOWPWR , .val = 0x1, },
403 { .reg = S5P_EXT_REGULATOR_LOWPWR , .val = 0x1, },
404 { .reg = S5P_GPIO_MODE_LOWPWR , .val = 0x0, },
405 { .reg = S5P_GPIO_MODE_MAUDIO_LOWPWR , .val = 0x1, },
406 { .reg = S5P_CAM_LOWPWR , .val = 0x0, },
407 { .reg = S5P_TV_LOWPWR , .val = 0x0, },
408 { .reg = S5P_MFC_LOWPWR , .val = 0x0, },
409 { .reg = S5P_G3D_LOWPWR , .val = 0x0, },
410 { .reg = S5P_LCD0_LOWPWR , .val = 0x0, },
411 { .reg = S5P_LCD1_LOWPWR , .val = 0x0, },
412 { .reg = S5P_MAUDIO_LOWPWR , .val = 0x7, },
413 { .reg = S5P_GPS_LOWPWR , .val = 0x0, },
414 { .reg = S5P_GPS_ALIVE_LOWPWR , .val = 0x0, },
417 static struct sleep_save s5pv310_set_clksrc[] = {
418 { .reg = S5P_CLKSRC_MASK_TOP , .val = 0x00000001, },
419 { .reg = S5P_CLKSRC_MASK_CAM , .val = 0x11111111, },
420 { .reg = S5P_CLKSRC_MASK_TV , .val = 0x00000111, },
421 { .reg = S5P_CLKSRC_MASK_LCD0 , .val = 0x00001111, },
422 { .reg = S5P_CLKSRC_MASK_LCD1 , .val = 0x00001111, },
423 { .reg = S5P_CLKSRC_MASK_MAUDIO , .val = 0x00000001, },
424 { .reg = S5P_CLKSRC_MASK_FSYS , .val = 0x01011111, },
425 { .reg = S5P_CLKSRC_MASK_PERIL0 , .val = 0x01111111, },
426 { .reg = S5P_CLKSRC_MASK_PERIL1 , .val = 0x01110111, },
427 { .reg = S5P_CLKSRC_MASK_DMC , .val = 0x00010000, },
431 * This function is called by s3c_cpu_save() in sleep.S. The contents of
432 * the SVC mode stack area and s3c_sleep_save_phys variable should be
433 * updated to physical memory until entering AFTR mode. The memory contents
434 * are used by s3c_cpu_resume() and resume_with_mmu before enabling L2 cache.
436 void s5p_aftr_cache_clean(void *stack_addr)
440 clean_dcache_area(stack_addr, 0x5f);
441 clean_dcache_area(&s3c_sleep_save_phys, 1);
442 #ifdef CONFIG_OUTER_CACHE
443 /* SVC mode stack area is cleaned from L2 cache */
444 tmp = virt_to_phys(stack_addr);
445 outer_cache.clean_range(tmp, tmp + 0x5f);
447 /* The variable is cleaned from L2 cache */
448 tmp = virt_to_phys(&s3c_sleep_save_phys);
449 outer_cache.clean_range(tmp, tmp + 1);
460 static void s5pv310_gic_ctrl(enum gic_loc gic, unsigned int ctrl)
462 if (ctrl > 1 || gic >= END_GIC) {
463 printk(KERN_ERR "Invalid input argument: %s, %d\n",
470 __raw_writel(ctrl, S5P_VA_GIC_DIST + 0x00);
471 __raw_writel(ctrl, S5P_VA_GIC_CPU + 0x00);
474 __raw_writel(ctrl, S5P_VA_EXTGIC_DIST + 0x00);
475 __raw_writel(ctrl, S5P_VA_EXTGIC_CPU + 0x00);
482 static int s5pv310_enter_idle(struct cpuidle_device *dev,
483 struct cpuidle_state *state);
485 static int s5pv310_enter_lowpower(struct cpuidle_device *dev,
486 struct cpuidle_state *state);
488 static struct cpuidle_state s5pv310_cpuidle_set[] = {
490 .enter = s5pv310_enter_idle,
492 .target_residency = 1000,
493 .flags = CPUIDLE_FLAG_TIME_VALID,
495 .desc = "ARM clock gating(WFI)",
499 .enter = s5pv310_enter_lowpower,
501 .target_residency = 10000,
502 .flags = CPUIDLE_FLAG_TIME_VALID,
504 .desc = "ARM power down",
509 static DEFINE_PER_CPU(struct cpuidle_device, s5pv310_cpuidle_device);
511 static struct cpuidle_driver s5pv310_idle_driver = {
512 .name = "s5pv310_idle",
513 .owner = THIS_MODULE,
516 void s5pv310_set_core0_pwroff(void)
520 * Setting Central Sequence Register for power down mode
522 tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
523 tmp &= ~(S5P_CENTRAL_LOWPWR_CFG);
524 __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
531 static int s5pv310_check_gic_pending(enum gic_loc gic)
535 if (gic >= END_GIC) {
536 printk(KERN_ERR "Invalid input argument: %s, %d\n",
541 tmp = __raw_readl(S5P_VA_GIC_CPU + 0x0c);
543 tmp = __raw_readl(S5P_VA_EXTGIC_CPU + 0x0c);
547 __raw_writel(tmp, S5P_VA_GIC_CPU + 0x10);
549 __raw_writel(tmp, S5P_VA_EXTGIC_CPU + 0x10);
556 #define GPIO_OFFSET 0x20
557 #define GPIO_PUD_OFFSET 0x08
558 #define GPIO_CON_PDN_OFFSET 0x10
559 #define GPIO_PUD_PDN_OFFSET 0x14
560 #define GPIO_END_OFFSET 0x200
561 static void s5pv310_gpio_conpdn_reg(void)
563 void __iomem *gpio_base = S5P_VA_GPIO;
567 /* Keep the previous state in didle mode */
568 __raw_writel(0xffff, gpio_base + GPIO_CON_PDN_OFFSET);
570 /* Pull up-down state in didle is same as normal */
571 val = __raw_readl(gpio_base + GPIO_PUD_OFFSET);
572 __raw_writel(val, gpio_base + GPIO_PUD_PDN_OFFSET);
574 gpio_base += GPIO_OFFSET;
576 if (gpio_base == S5P_VA_GPIO + GPIO_END_OFFSET)
577 gpio_base = S5PV310_VA_GPIO2;
579 } while (gpio_base <= S5PV310_VA_GPIO2 + GPIO_END_OFFSET);
582 gpio_base = S5P_VA_GPIO3;
583 __raw_writel(0xffff, gpio_base + GPIO_CON_PDN_OFFSET);
585 val = __raw_readl(gpio_base + GPIO_PUD_OFFSET);
586 __raw_writel(val, gpio_base + GPIO_PUD_PDN_OFFSET);
589 static void s5pv310_set_wakeupmask(void)
591 __raw_writel(0x0000ff3e, S5P_WAKEUP_MASK);
594 static int s5pv310_enter_core0_aftr(struct cpuidle_device *dev,
595 struct cpuidle_state *state)
597 struct timeval before, after;
601 s3c_pm_do_save(s5pv310_aftr_save, ARRAY_SIZE(s5pv310_aftr_save));
603 s3c_sleep_save_phys = phy_regs_save;
606 do_gettimeofday(&before);
608 s5pv310_set_wakeupmask();
609 #ifndef CONFIG_USE_EXT_GIC
610 if (s5pv310_check_gic_pending(INT_GIC))
614 s5pv310_gic_ctrl(INT_GIC, 0);
615 s5pv310_gic_ctrl(EXT_GIC, 1);
617 /* ensure at least INFORM0 has the resume address */
618 __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
620 __raw_writel(virt_to_phys(s3c_cpu_resume), REG_DIRECTGO_ADDR);
621 __raw_writel(0xfcba0d10, REG_DIRECTGO_FLAG);
623 /* Set value of power down register for aftr mode */
624 s3c_pm_do_restore(s5pv310_aftr, ARRAY_SIZE(s5pv310_aftr));
625 __raw_writel(S5P_CHECK_DIDLE, S5P_INFORM1);
626 /* Obsolete: for the compatibility with obsolete s-boot */
627 if (s5pv310_subrev() == 0)
628 __raw_writel(S5P_CHECK_DIDLE, S5P_INFORM7);
630 if (s3c_cpu_save(regs_save) == 0) {
632 * Clear Central Sequence Register in exiting early wakeup
634 tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
635 tmp |= (S5P_CENTRAL_LOWPWR_CFG);
636 __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
637 #ifndef CONFIG_USE_EXT_GIC
638 /* Clear Ext GIC interrupt pending */
639 tmp = s5pv310_check_gic_pending(EXT_GIC);
641 /* Disable external GIC */
642 s5pv310_gic_ctrl(EXT_GIC, 0);
644 /* Enable internal GIC */
645 s5pv310_gic_ctrl(INT_GIC, 1);
651 #ifndef CONFIG_USE_EXT_GIC
652 /* Disable external GIC */
653 s5pv310_gic_ctrl(EXT_GIC, 0);
655 s3c_pm_do_restore_core(s5pv310_aftr_save,
656 ARRAY_SIZE(s5pv310_aftr_save));
659 /* Clear wakeup state register */
660 __raw_writel(0x0, S5P_WAKEUP_STAT);
662 do_gettimeofday(&after);
665 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
666 (after.tv_usec - before.tv_usec);
671 static int s5pv310_check_enter(void)
674 unsigned int check_val;
678 /* Check UART for console is empty */
679 check_val = __raw_readl(S5P_VA_UART(CONFIG_S3C_LOWLEVEL_UART_PORT) +
682 ret = ((check_val >> 16) & 0xff);
687 static int s5pv310_enter_core0_lpa(struct cpuidle_device *dev,
688 struct cpuidle_state *state)
690 struct timeval before, after;
694 printk(KERN_DEBUG "+++ %s\n", __func__);
696 s3c_pm_do_save(s5pv310_lpa_save, ARRAY_SIZE(s5pv310_lpa_save));
699 * Before enter central sequence mode, clock src register have to set
701 s3c_pm_do_restore_core(s5pv310_set_clksrc,
702 ARRAY_SIZE(s5pv310_set_clksrc));
704 s3c_sleep_save_phys = phy_regs_save;
707 do_gettimeofday(&before);
710 * Unmasking all wakeup source.
712 __raw_writel(0x0, S5P_WAKEUP_MASK);
714 /* Configure GPIO Power down control register */
715 s5pv310_gpio_conpdn_reg();
717 /* ensure at least INFORM0 has the resume address */
718 __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
720 __raw_writel(virt_to_phys(s3c_cpu_resume), REG_DIRECTGO_ADDR);
721 __raw_writel(0xfcba0d10, REG_DIRECTGO_FLAG);
723 __raw_writel(S5P_CHECK_LPA, S5P_INFORM1);
724 /* Obsolete: for the compatibility with obsolete s-boot */
725 if (s5pv310_subrev() == 0)
726 __raw_writel(S5P_CHECK_LPA, S5P_INFORM7);
727 s3c_pm_do_restore(s5pv310_lpa, ARRAY_SIZE(s5pv310_lpa));
729 __raw_writel(0xfcba0d10, S5P_VA_SYSRAM + 0x20);
733 } while (s5pv310_check_enter());
736 if (s3c_cpu_save(regs_save) == 0) {
738 tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
739 tmp |= (S5P_CENTRAL_LOWPWR_CFG);
740 __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
747 s3c_pm_do_restore_core(s5pv310_lpa_save,
748 ARRAY_SIZE(s5pv310_lpa_save));
750 /* For release retention */
751 __raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
752 __raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
753 __raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
754 __raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
755 __raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
756 __raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
760 /* Clear wakeup state register */
761 __raw_writel(0x0, S5P_WAKEUP_STAT);
763 __raw_writel(0x0, S5P_WAKEUP_MASK);
765 do_gettimeofday(&after);
768 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
769 (after.tv_usec - before.tv_usec);
771 printk(KERN_DEBUG "--- %s\n", __func__);
776 static int s5pv310_enter_idle(struct cpuidle_device *dev,
777 struct cpuidle_state *state)
779 struct timeval before, after;
782 unsigned int tmp, nr_cores;
785 do_gettimeofday(&before);
789 spin_lock(&idle_lock);
791 /* Let hotplug cpu_down/up finish first */
793 spin_unlock(&idle_lock);
796 do_gettimeofday(&after);
798 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
799 (after.tv_usec - before.tv_usec);
804 cpu_core |= (1 << cpu);
811 if (cpu_core == nr_cores) {
812 old_div = __raw_readl(S5P_CLKDIV_CPU);
814 tmp |= ((0x7 << 28) | (0x7 << 0));
815 __raw_writel(tmp , S5P_CLKDIV_CPU);
818 tmp = __raw_readl(S5P_CLKDIV_STATCPU);
819 } while (tmp & 0x10000001);
822 spin_unlock(&idle_lock);
826 spin_lock(&idle_lock);
828 if (cpu_core == nr_cores) {
829 __raw_writel(old_div, S5P_CLKDIV_CPU);
832 tmp = __raw_readl(S5P_CLKDIV_STATCPU);
833 } while (tmp & 0x10000001);
836 cpu_core &= ~(1 << cpu);
839 spin_unlock(&idle_lock);
843 do_gettimeofday(&after);
845 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
846 (after.tv_usec - before.tv_usec);
852 * Check conditions to enter LPA mode
854 static int check_power_domain(void)
858 tmp = __raw_readl(S5P_PMU_LCD0_CONF);
859 if ((tmp & S5P_INT_LOCAL_PWR_EN) == S5P_INT_LOCAL_PWR_EN)
862 tmp = __raw_readl(S5P_PMU_MFC_CONF);
863 if ((tmp & S5P_INT_LOCAL_PWR_EN) == S5P_INT_LOCAL_PWR_EN)
866 tmp = __raw_readl(S5P_PMU_G3D_CONF);
867 if ((tmp & S5P_INT_LOCAL_PWR_EN) == S5P_INT_LOCAL_PWR_EN)
870 tmp = __raw_readl(S5P_PMU_CAM_CONF);
871 if ((tmp & S5P_INT_LOCAL_PWR_EN) == S5P_INT_LOCAL_PWR_EN)
874 tmp = __raw_readl(S5P_PMU_TV_CONF);
875 if ((tmp & S5P_INT_LOCAL_PWR_EN) == S5P_INT_LOCAL_PWR_EN)
878 tmp = __raw_readl(S5P_PMU_GPS_CONF);
879 if ((tmp & S5P_INT_LOCAL_PWR_EN) == S5P_INT_LOCAL_PWR_EN)
885 static int check_clock_gating(void)
889 tmp = __raw_readl(S5P_CLKGATE_IP_IMAGE);
890 if (tmp & (S5P_CLKGATE_IP_IMAGE_MDMA_MASK
891 | S5P_CLKGATE_IP_IMAGE_SMMUMDMA_MASK
892 | S5P_CLKGATE_IP_IMAGE_QEMDMA_MASK)) {
893 printk(KERN_DEBUG "MDMA is in use (CLKGATE_IP_IMAGE:0x%x\n", tmp);
897 tmp = __raw_readl(S5P_CLKGATE_IP_FSYS);
898 if (tmp & (S5P_CLKGATE_IP_FSYS_PDMA0_MASK
899 | S5P_CLKGATE_IP_FSYS_PDMA1_MASK)) {
900 printk(KERN_DEBUG "PDMA is in use (CLKGATE_IP_FSYS:0x%x\n", tmp);
905 tmp = __raw_readl(S5P_CLKGATE_IP_PERIL);
906 if (tmp & S5P_CLKGATE_IP_PERIL_I2C0_8_MASK) {
907 printk(KERN_DEBUG "I2C is in use (CLKGATE_IP_PERIL:0x%x)\n", tmp);
915 #define SDHCI_PRNSTS (0x24)
916 #define SDHCI_PRNSTS_CMDINHCMD (0x1 << 0)
917 #define SDHCI_PRNSTS_CMDINHDAT (0x1 << 1)
918 #define SDHCI_CLKCON (0x2c)
919 #define SDHCI_CLKCON_ENSDCLK (0x1 << 2)
921 #define MSHCI_CLKENA (0x10) /* Clock enable */
922 #define MSHCI_STATUS (0x48) /* Status */
923 #define MSHCI_DATA_BUSY (0x1 << 9)
924 #define MSHCI_ENCLK (0x1 << 0)
926 static int sdmmc_dev_num = 0;
927 static int check_sdmmc_op(unsigned int ch)
929 unsigned int reg1, reg2;
930 void __iomem *base_addr;
932 if (unlikely(ch > sdmmc_dev_num)) {
933 printk(KERN_ERR "Invalid ch[%d] for SD/MMC\n", ch);
937 if (chk_dev_op[ch].type == HC_SDHCI) {
938 base_addr = chk_dev_op[ch].base;
940 /* Check CMDINHDAT[1] and CMDINHCMD [0] */
941 reg1 = readl(base_addr + SDHCI_PRNSTS);
942 /* Check CLKCON [2]: ENSDCLK */
943 reg2 = readl(base_addr + SDHCI_CLKCON);
945 if (reg1 & (SDHCI_PRNSTS_CMDINHCMD | SDHCI_PRNSTS_CMDINHDAT)) {
946 printk(KERN_DEBUG "%s is in use(CMD/DATA)\n",
947 dev_name(&chk_dev_op[ch].pdev->dev));
949 } else if (reg2 & (SDHCI_CLKCON_ENSDCLK)) {
950 printk(KERN_DEBUG "%s is clock on\n",
951 dev_name(&chk_dev_op[ch].pdev->dev));
955 } else if (chk_dev_op[ch].type == HC_MSHCI) {
956 base_addr = chk_dev_op[ch].base;
958 base_addr = chk_dev_op[ch].base;
959 /* Check STATUS [9] for data busy */
960 reg1 = readl(base_addr + MSHCI_STATUS);
961 /* Check CLKENA [0] for clock on/off */
962 reg2 = readl(base_addr + MSHCI_CLKENA);
964 if (reg1 & (MSHCI_DATA_BUSY)) {
965 printk(KERN_DEBUG "\t%s: DATA BUSY\n",
966 dev_name(&chk_dev_op[ch].pdev->dev));
968 if (reg2 & (MSHCI_ENCLK)) {
969 printk(KERN_DEBUG "\t%s: CLKENA\n",
970 dev_name(&chk_dev_op[ch].pdev->dev));
973 return (reg1 & (MSHCI_DATA_BUSY)) ||
974 (reg2 & (MSHCI_ENCLK));
979 /* Check all sdmmc controller */
980 static int check_sdmmc_state(void)
984 for (i = 0; i < sdmmc_dev_num + 1; i++) {
985 if (check_sdmmc_op(i))
991 extern int is_usb_host_phy_suspend(void);
992 static int check_usb_host_op(void)
994 return is_usb_host_phy_suspend();
998 * Check USBOTG is working or not
999 * GOTGCTL(0xEC000000)
1000 * BSesVld (Indicates the Device mode transceiver status)
1001 * BSesVld = 1b : B-session is valid
1002 * 0b : B-session is not valid
1004 static int check_usb_otg_op(void)
1008 val = __raw_readl(S3C_UDC_OTG_GOTGCTL);
1009 return val & (A_SESSION_VALID | B_SESSION_VALID);
1012 bool extern rfkill_get_global_sw_state(const enum rfkill_type type);
1013 static int check_wireless_op(void)
1015 if (!rfkill_get_global_sw_state(RFKILL_TYPE_BLUETOOTH)) {
1016 printk(KERN_DEBUG "BT: rfkill s/w state is unblocked\n");
1018 } else if (!rfkill_get_global_sw_state(RFKILL_TYPE_WLAN)) {
1019 printk(KERN_DEBUG "WLAN: rfkill s/w state is unblocked\n");
1023 /* FIXME: GPS is always on becuase don't off GPS using rfkill on platform. */
1025 else if (!rfkill_get_global_sw_state(RFKILL_TYPE_GPS))
1032 static int s5pv310_check_entermode(void)
1036 ret = S5P_CHECK_DIDLE;
1038 if (check_power_domain())
1040 else if (check_clock_gating())
1042 else if (check_sdmmc_state())
1044 else if (check_usb_host_op() || check_usb_otg_op())
1046 else if (check_wireless_op())
1049 ret = S5P_CHECK_LPA;
1054 static int s5pv310_enter_lowpower(struct cpuidle_device *dev,
1055 struct cpuidle_state *state)
1057 struct cpuidle_state *new_state = state;
1058 unsigned int enter_mode;
1060 /* This mode only can be entered when Core1 is offline */
1061 if (cpu_online(1)) {
1062 BUG_ON(!dev->safe_state);
1063 new_state = dev->safe_state;
1065 dev->last_state = new_state;
1067 if (new_state == &dev->states[0])
1068 return s5pv310_enter_idle(dev, new_state);
1070 enter_mode = s5pv310_check_entermode();
1072 if (enter_mode == S5P_CHECK_DIDLE)
1073 return s5pv310_enter_core0_aftr(dev, new_state);
1075 return s5pv310_enter_core0_lpa(dev, new_state);
1078 return s5pv310_enter_idle(dev, new_state);
1081 static int s5pv310_init_cpuidle(void)
1083 int i, max_cpuidle_state, cpu_id;
1084 struct cpuidle_device *device;
1085 struct platform_device *pdev;
1086 struct resource *res;
1088 cpuidle_register_driver(&s5pv310_idle_driver);
1090 for_each_cpu(cpu_id, cpu_online_mask) {
1091 device = &per_cpu(s5pv310_cpuidle_device, cpu_id);
1092 device->cpu = cpu_id;
1095 device->state_count = (sizeof(s5pv310_cpuidle_set) /
1096 sizeof(struct cpuidle_state));
1098 device->state_count = 1; /* Support IDLE only */
1100 max_cpuidle_state = device->state_count;
1102 for (i = 0; i < max_cpuidle_state; i++) {
1103 memcpy(&device->states[i], &s5pv310_cpuidle_set[i],
1104 sizeof(struct cpuidle_state));
1107 device->safe_state = &device->states[0];
1109 if (cpuidle_register_device(device)) {
1110 printk(KERN_ERR "CPUidle register device failed\n,");
1115 sdmmc_dev_num = ARRAY_SIZE(chk_dev_op);
1116 for (i = 0 ; i < sdmmc_dev_num ; i++) {
1118 pdev = chk_dev_op[i].pdev;
1123 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1125 printk(KERN_ERR "failed to get iomem region\n");
1128 chk_dev_op[i].base = ioremap_nocache(res->start, 4096);
1130 if (!chk_dev_op[i].base) {
1131 printk(KERN_ERR "failed to map io region\n");
1136 regs_save = dma_alloc_coherent(NULL, 4096, &phy_regs_save, GFP_KERNEL);
1137 if (regs_save == NULL) {
1138 printk(KERN_ERR "Alloc memory for CPUIDLE failed\n");
1141 #ifndef CONFIG_USE_EXT_GIC
1147 device_initcall(s5pv310_init_cpuidle);