2014-04-14 19:10:13 +04:00
/*
2014-07-23 17:00:50 +04:00
* Marvell Armada 370 , 38 x and XP SoC cpuidle driver
2014-04-14 19:10:13 +04:00
*
* Copyright ( C ) 2014 Marvell
*
* Nadav Haklai < nadavh @ marvell . com >
* Gregory CLEMENT < gregory . clement @ free - electrons . com >
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
*
* Maintainer : Gregory CLEMENT < gregory . clement @ free - electrons . com >
*/
# include <linux/cpu_pm.h>
# include <linux/cpuidle.h>
# include <linux/module.h>
# include <linux/of.h>
# include <linux/suspend.h>
# include <linux/platform_device.h>
# include <asm/cpuidle.h>
2014-07-23 17:00:48 +04:00
# define MVEBU_V7_FLAG_DEEP_IDLE 0x10000
2014-04-14 19:10:13 +04:00
2014-07-23 17:00:48 +04:00
static int ( * mvebu_v7_cpu_suspend ) ( int ) ;
2014-04-14 19:10:13 +04:00
2014-07-23 17:00:48 +04:00
static int mvebu_v7_enter_idle ( struct cpuidle_device * dev ,
2014-04-14 19:10:13 +04:00
struct cpuidle_driver * drv ,
int index )
{
int ret ;
bool deepidle = false ;
cpu_pm_enter ( ) ;
2014-07-23 17:00:48 +04:00
if ( drv - > states [ index ] . flags & MVEBU_V7_FLAG_DEEP_IDLE )
2014-04-14 19:10:13 +04:00
deepidle = true ;
2014-07-23 17:00:48 +04:00
ret = mvebu_v7_cpu_suspend ( deepidle ) ;
2015-02-26 20:20:48 +03:00
cpu_pm_exit ( ) ;
2014-04-14 19:10:13 +04:00
if ( ret )
return ret ;
return index ;
}
2014-07-23 17:00:48 +04:00
static struct cpuidle_driver armadaxp_idle_driver = {
. name = " armada_xp_idle " ,
2014-04-14 19:10:13 +04:00
. states [ 0 ] = ARM_CPUIDLE_WFI_STATE ,
. states [ 1 ] = {
2014-07-23 17:00:48 +04:00
. enter = mvebu_v7_enter_idle ,
2015-02-13 17:55:03 +03:00
. exit_latency = 100 ,
2014-04-14 19:10:13 +04:00
. power_usage = 50 ,
2015-02-13 17:55:03 +03:00
. target_residency = 1000 ,
2014-04-14 19:10:13 +04:00
. name = " MV CPU IDLE " ,
. desc = " CPU power down " ,
} ,
. states [ 2 ] = {
2014-07-23 17:00:48 +04:00
. enter = mvebu_v7_enter_idle ,
2015-02-13 17:55:03 +03:00
. exit_latency = 1000 ,
2014-04-14 19:10:13 +04:00
. power_usage = 5 ,
2015-02-13 17:55:03 +03:00
. target_residency = 10000 ,
2014-11-12 18:03:50 +03:00
. flags = MVEBU_V7_FLAG_DEEP_IDLE ,
2014-04-14 19:10:13 +04:00
. name = " MV CPU DEEP IDLE " ,
. desc = " CPU and L2 Fabric power down " ,
} ,
2014-07-23 17:00:48 +04:00
. state_count = 3 ,
2014-04-14 19:10:13 +04:00
} ;
2014-07-23 17:00:49 +04:00
static struct cpuidle_driver armada370_idle_driver = {
. name = " armada_370_idle " ,
. states [ 0 ] = ARM_CPUIDLE_WFI_STATE ,
. states [ 1 ] = {
. enter = mvebu_v7_enter_idle ,
. exit_latency = 100 ,
. power_usage = 5 ,
. target_residency = 1000 ,
2014-11-12 18:03:50 +03:00
. flags = MVEBU_V7_FLAG_DEEP_IDLE ,
2014-07-23 17:00:49 +04:00
. name = " Deep Idle " ,
. desc = " CPU and L2 Fabric power down " ,
} ,
. state_count = 2 ,
} ;
2014-07-23 17:00:50 +04:00
static struct cpuidle_driver armada38x_idle_driver = {
. name = " armada_38x_idle " ,
. states [ 0 ] = ARM_CPUIDLE_WFI_STATE ,
. states [ 1 ] = {
. enter = mvebu_v7_enter_idle ,
. exit_latency = 10 ,
. power_usage = 5 ,
. target_residency = 100 ,
. name = " Idle " ,
. desc = " CPU and SCU power down " ,
} ,
. state_count = 2 ,
} ;
2014-07-23 17:00:48 +04:00
static int mvebu_v7_cpuidle_probe ( struct platform_device * pdev )
2014-04-14 19:10:13 +04:00
{
2015-10-03 02:24:25 +03:00
const struct platform_device_id * id = pdev - > id_entry ;
2014-07-23 17:00:49 +04:00
2015-10-03 02:24:25 +03:00
if ( ! id )
2014-07-23 17:00:49 +04:00
return - EINVAL ;
2014-04-14 19:10:13 +04:00
2015-10-03 02:24:25 +03:00
mvebu_v7_cpu_suspend = pdev - > dev . platform_data ;
2014-04-14 19:10:13 +04:00
2015-10-03 02:24:25 +03:00
return cpuidle_register ( ( struct cpuidle_driver * ) id - > driver_data , NULL ) ;
}
2014-04-14 19:10:13 +04:00
2015-10-03 02:24:25 +03:00
static const struct platform_device_id mvebu_cpuidle_ids [ ] = {
{
. name = " cpuidle-armada-xp " ,
. driver_data = ( unsigned long ) & armadaxp_idle_driver ,
} , {
2014-07-23 17:00:49 +04:00
. name = " cpuidle-armada-370 " ,
2015-10-03 02:24:25 +03:00
. driver_data = ( unsigned long ) & armada370_idle_driver ,
} , {
. name = " cpuidle-armada-38x " ,
. driver_data = ( unsigned long ) & armada38x_idle_driver ,
2014-07-23 17:00:49 +04:00
} ,
2015-10-03 02:24:25 +03:00
{ }
2014-07-23 17:00:49 +04:00
} ;
2015-10-03 02:24:25 +03:00
static struct platform_driver mvebu_cpuidle_driver = {
. probe = mvebu_v7_cpuidle_probe ,
2014-07-23 17:00:50 +04:00
. driver = {
2015-10-03 02:24:25 +03:00
. name = " cpuidle-mbevu " ,
2015-10-03 02:24:30 +03:00
. suppress_bind_attrs = true ,
2014-07-23 17:00:50 +04:00
} ,
2015-10-03 02:24:25 +03:00
. id_table = mvebu_cpuidle_ids ,
2014-07-23 17:00:50 +04:00
} ;
2015-10-03 02:24:30 +03:00
builtin_platform_driver ( mvebu_cpuidle_driver ) ;
2014-07-23 17:00:50 +04:00
2014-04-14 19:10:13 +04:00
MODULE_AUTHOR ( " Gregory CLEMENT <gregory.clement@free-electrons.com> " ) ;
2014-07-23 17:00:48 +04:00
MODULE_DESCRIPTION ( " Marvell EBU v7 cpuidle driver " ) ;
2014-04-14 19:10:13 +04:00
MODULE_LICENSE ( " GPL " ) ;