13d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee/* linux/arch/arm/mach-exynos4/cpuidle.c
23d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee *
33d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee * Copyright (c) 2011 Samsung Electronics Co., Ltd.
43d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee *		http://www.samsung.com
53d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee *
63d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee * This program is free software; you can redistribute it and/or modify
73d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee * it under the terms of the GNU General Public License version 2 as
83d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee * published by the Free Software Foundation.
93d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee*/
103d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
113d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee#include <linux/kernel.h>
123d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee#include <linux/init.h>
133d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee#include <linux/cpuidle.h>
1467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap#include <linux/cpu_pm.h>
153d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee#include <linux/io.h>
1676ee4557137ce12a60a1e1a070ed341182163a64Kyungmin Park#include <linux/export.h>
1776ee4557137ce12a60a1e1a070ed341182163a64Kyungmin Park#include <linux/time.h>
183d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
193d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee#include <asm/proc-fns.h>
2067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap#include <asm/smp_scu.h>
2167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap#include <asm/suspend.h>
2267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap#include <asm/unified.h>
2367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap#include <mach/regs-pmu.h>
2467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap#include <mach/pmu.h>
2567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
2667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap#include <plat/cpu.h>
2767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
2867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap#define REG_DIRECTGO_ADDR	(samsung_rev() == EXYNOS4210_REV_1_1 ? \
2967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap			S5P_INFORM7 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
3067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap			(S5P_VA_SYSRAM + 0x24) : S5P_INFORM0))
3167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap#define REG_DIRECTGO_FLAG	(samsung_rev() == EXYNOS4210_REV_1_1 ? \
3267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap			S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
3367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap			(S5P_VA_SYSRAM + 0x20) : S5P_INFORM1))
3467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
3567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap#define S5P_CHECK_AFTR		0xFCBA0D10
363d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
373d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Leestatic int exynos4_enter_idle(struct cpuidle_device *dev,
3846bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar			struct cpuidle_driver *drv,
39e978aa7d7d57d04eb5f88a7507c4fb98577def77Deepthi Dharwar			      int index);
4067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhapstatic int exynos4_enter_lowpower(struct cpuidle_device *dev,
4167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap				struct cpuidle_driver *drv,
4267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap				int index);
433d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
4467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhapstatic struct cpuidle_state exynos4_cpuidle_set[] __initdata = {
453d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	[0] = {
463d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee		.enter			= exynos4_enter_idle,
473d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee		.exit_latency		= 1,
483d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee		.target_residency	= 100000,
493d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee		.flags			= CPUIDLE_FLAG_TIME_VALID,
5067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		.name			= "C0",
513d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee		.desc			= "ARM clock gating(WFI)",
523d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	},
5367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	[1] = {
5467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		.enter			= exynos4_enter_lowpower,
5567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		.exit_latency		= 300,
5667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		.target_residency	= 100000,
5767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		.flags			= CPUIDLE_FLAG_TIME_VALID,
5867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		.name			= "C1",
5967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		.desc			= "ARM power down",
6067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	},
613d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee};
623d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
633d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Leestatic DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
643d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
653d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Leestatic struct cpuidle_driver exynos4_idle_driver = {
663d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	.name		= "exynos4_idle",
673d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	.owner		= THIS_MODULE,
683d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee};
693d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
7067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
7167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhapstatic void exynos4_set_wakeupmask(void)
7267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap{
7367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	__raw_writel(0x0000ff3e, S5P_WAKEUP_MASK);
7467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap}
7567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
7667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhapstatic unsigned int g_pwr_ctrl, g_diag_reg;
7767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
7867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhapstatic void save_cpu_arch_register(void)
7967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap{
8067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	/*read power control register*/
8167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	asm("mrc p15, 0, %0, c15, c0, 0" : "=r"(g_pwr_ctrl) : : "cc");
8267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	/*read diagnostic register*/
8367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
8467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	return;
8567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap}
8667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
8767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhapstatic void restore_cpu_arch_register(void)
8867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap{
8967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	/*write power control register*/
9067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	asm("mcr p15, 0, %0, c15, c0, 0" : : "r"(g_pwr_ctrl) : "cc");
9167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	/*write diagnostic register*/
9267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
9367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	return;
9467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap}
9567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
9667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhapstatic int idle_finisher(unsigned long flags)
9767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap{
9867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	cpu_do_idle();
9967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	return 1;
10067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap}
10167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
10267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhapstatic int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
10367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap				struct cpuidle_driver *drv,
10467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap				int index)
10567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap{
10667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	struct timeval before, after;
10767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	int idle_time;
10867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	unsigned long tmp;
10967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
11067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	local_irq_disable();
11167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	do_gettimeofday(&before);
11267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
11367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	exynos4_set_wakeupmask();
11467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
11567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	/* Set value of power down register for aftr mode */
11667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	exynos4_sys_powerdown_conf(SYS_AFTR);
11767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
11867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	__raw_writel(virt_to_phys(s3c_cpu_resume), REG_DIRECTGO_ADDR);
11967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	__raw_writel(S5P_CHECK_AFTR, REG_DIRECTGO_FLAG);
12067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
12167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	save_cpu_arch_register();
12267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
12367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	/* Setting Central Sequence Register for power down mode */
12467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
12567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
12667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
12767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
12867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	cpu_pm_enter();
12967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	cpu_suspend(0, idle_finisher);
13067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
13167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap#ifdef CONFIG_SMP
13267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	scu_enable(S5P_VA_SCU);
13367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap#endif
13467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	cpu_pm_exit();
13567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
13667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	restore_cpu_arch_register();
13767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
13867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	/*
13967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	 * If PMU failed while entering sleep mode, WFI will be
14067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	 * ignored by PMU and then exiting cpu_do_idle().
14167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	 * S5P_CENTRAL_LOWPWR_CFG bit will not be set automatically
14267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	 * in this situation.
14367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	 */
14467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
14567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	if (!(tmp & S5P_CENTRAL_LOWPWR_CFG)) {
14667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		tmp |= S5P_CENTRAL_LOWPWR_CFG;
14767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
14867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	}
14967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
15067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	/* Clear wakeup state register */
15167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	__raw_writel(0x0, S5P_WAKEUP_STAT);
15267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
15367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	do_gettimeofday(&after);
15467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
15567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	local_irq_enable();
15667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
15767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		    (after.tv_usec - before.tv_usec);
15867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
15967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	dev->last_residency = idle_time;
16067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	return index;
16167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap}
16267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
1633d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Leestatic int exynos4_enter_idle(struct cpuidle_device *dev,
16446bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar				struct cpuidle_driver *drv,
16567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap				int index)
1663d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee{
1673d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	struct timeval before, after;
1683d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	int idle_time;
1693d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
1703d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	local_irq_disable();
1713d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	do_gettimeofday(&before);
1723d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
1733d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	cpu_do_idle();
1743d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
1753d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	do_gettimeofday(&after);
1763d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	local_irq_enable();
1773d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
1783d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee		    (after.tv_usec - before.tv_usec);
1793d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
180e978aa7d7d57d04eb5f88a7507c4fb98577def77Deepthi Dharwar	dev->last_residency = idle_time;
181e978aa7d7d57d04eb5f88a7507c4fb98577def77Deepthi Dharwar	return index;
1823d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee}
1833d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
18467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhapstatic int exynos4_enter_lowpower(struct cpuidle_device *dev,
18567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap				struct cpuidle_driver *drv,
18667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap				int index)
18767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap{
18867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	int new_index = index;
18967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
19067173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	/* This mode only can be entered when other core's are offline */
19167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	if (num_online_cpus() > 1)
19267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		new_index = drv->safe_state_index;
19367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
19467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	if (new_index == 0)
19567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		return exynos4_enter_idle(dev, drv, new_index);
19667173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	else
19767173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		return exynos4_enter_core0_aftr(dev, drv, new_index);
19867173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap}
19967173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
2003d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Leestatic int __init exynos4_init_cpuidle(void)
2013d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee{
2023d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	int i, max_cpuidle_state, cpu_id;
2033d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	struct cpuidle_device *device;
20446bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar	struct cpuidle_driver *drv = &exynos4_idle_driver;
20546bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar
20646bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar	/* Setup cpuidle driver */
20746bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar	drv->state_count = (sizeof(exynos4_cpuidle_set) /
20846bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar				       sizeof(struct cpuidle_state));
20946bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar	max_cpuidle_state = drv->state_count;
21046bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar	for (i = 0; i < max_cpuidle_state; i++) {
21146bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar		memcpy(&drv->states[i], &exynos4_cpuidle_set[i],
21246bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar				sizeof(struct cpuidle_state));
21346bcfad7a819bd17ac4e831b04405152d59784abDeepthi Dharwar	}
21467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap	drv->safe_state_index = 0;
2153d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	cpuidle_register_driver(&exynos4_idle_driver);
2163d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
2173d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	for_each_cpu(cpu_id, cpu_online_mask) {
2183d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee		device = &per_cpu(exynos4_cpuidle_device, cpu_id);
2193d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee		device->cpu = cpu_id;
2203d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
22167173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		if (cpu_id == 0)
22267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap			device->state_count = (sizeof(exynos4_cpuidle_set) /
22367173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap					       sizeof(struct cpuidle_state));
22467173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap		else
22567173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap			device->state_count = 1;	/* Support IDLE only */
2263d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee
2273d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee		if (cpuidle_register_device(device)) {
2283d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee			printk(KERN_ERR "CPUidle register device failed\n,");
2293d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee			return -EIO;
2303d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee		}
2313d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	}
23267173ca492ab6f3a6ee6c1283961008635f6322eAmit Daniel Kachhap
2333d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee	return 0;
2343d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Lee}
2353d73998558beac1e56efaaf7c5bf3469ee4c6ba2Jaecheol Leedevice_initcall(exynos4_init_cpuidle);
236