2014-05-09 01:43:26 +04:00
/* linux/arch/arm/mach-exynos/cpuidle.c
2011-03-16 01:28:23 +03:00
*
* Copyright ( c ) 2011 Samsung Electronics Co . , Ltd .
* http : //www.samsung.com
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/cpuidle.h>
2012-03-08 14:07:27 +04:00
# include <linux/cpu_pm.h>
2011-11-08 14:57:59 +04:00
# include <linux/export.h>
2014-03-19 21:29:36 +04:00
# include <linux/module.h>
2013-08-30 14:15:04 +04:00
# include <linux/platform_device.h>
2011-03-16 01:28:23 +03:00
# include <asm/proc-fns.h>
2012-03-08 14:07:27 +04:00
# include <asm/suspend.h>
2012-05-12 11:29:21 +04:00
# include <asm/cpuidle.h>
2012-03-08 14:07:27 +04:00
2014-05-09 01:56:29 +04:00
static void ( * exynos_enter_aftr ) ( void ) ;
2012-12-31 22:06:48 +04:00
2014-05-09 01:43:26 +04:00
static int exynos_enter_lowpower ( struct cpuidle_device * dev ,
2012-03-08 14:07:27 +04:00
struct cpuidle_driver * drv ,
int index )
{
int new_index = index ;
2013-12-20 22:47:23 +04:00
/* AFTR can only be entered when cores other than CPU0 are offline */
if ( num_online_cpus ( ) > 1 | | dev - > cpu ! = 0 )
2012-03-08 14:07:27 +04:00
new_index = drv - > safe_state_index ;
if ( new_index = = 0 )
2012-05-12 11:29:21 +04:00
return arm_cpuidle_simple_enter ( dev , drv , new_index ) ;
2014-08-05 16:43:10 +04:00
exynos_enter_aftr ( ) ;
return new_index ;
2012-03-08 14:07:27 +04:00
}
2014-05-09 01:43:26 +04:00
static struct cpuidle_driver exynos_idle_driver = {
. name = " exynos_idle " ,
2014-05-09 01:43:26 +04:00
. owner = THIS_MODULE ,
. states = {
[ 0 ] = ARM_CPUIDLE_WFI_STATE ,
[ 1 ] = {
2014-05-09 01:43:26 +04:00
. enter = exynos_enter_lowpower ,
2014-05-09 01:43:26 +04:00
. exit_latency = 300 ,
. target_residency = 100000 ,
. name = " C1 " ,
. desc = " ARM power down " ,
} ,
} ,
. state_count = 2 ,
. safe_state_index = 0 ,
} ;
2013-10-21 05:53:03 +04:00
static int exynos_cpuidle_probe ( struct platform_device * pdev )
2011-03-16 01:28:23 +03:00
{
2014-05-09 01:43:26 +04:00
int ret ;
2011-10-28 14:50:42 +04:00
2014-05-09 01:56:29 +04:00
exynos_enter_aftr = ( void * ) ( pdev - > dev . platform_data ) ;
2014-05-09 01:43:26 +04:00
ret = cpuidle_register ( & exynos_idle_driver , NULL ) ;
2013-01-19 09:57:58 +04:00
if ( ret ) {
2013-10-21 05:52:15 +04:00
dev_err ( & pdev - > dev , " failed to register cpuidle driver \n " ) ;
2013-01-19 09:57:58 +04:00
return ret ;
2011-10-28 14:50:42 +04:00
}
2011-03-16 01:28:23 +03:00
return 0 ;
}
2013-08-30 14:15:04 +04:00
static struct platform_driver exynos_cpuidle_driver = {
. probe = exynos_cpuidle_probe ,
. driver = {
. name = " exynos_cpuidle " ,
} ,
} ;
module_platform_driver ( exynos_cpuidle_driver ) ;