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