2009-11-03 15:14:13 +05:30
/*
* CPU idle for DaVinci SoCs
*
* Copyright ( C ) 2009 Texas Instruments Incorporated . http : //www.ti.com/
*
* Derived from Marvell Kirkwood CPU idle code
* ( arch / arm / mach - kirkwood / cpuidle . c )
*
* 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/kernel.h>
# include <linux/init.h>
# include <linux/platform_device.h>
# include <linux/cpuidle.h>
# include <linux/io.h>
2011-07-31 16:17:29 -04:00
# include <linux/export.h>
2009-11-03 15:14:13 +05:30
# include <asm/proc-fns.h>
2012-03-20 15:22:45 -05:00
# include <asm/cpuidle.h>
2009-11-03 15:14:13 +05:30
# include <mach/cpuidle.h>
2011-07-05 22:52:57 -04:00
# include <mach/ddr2.h>
2009-11-03 15:14:13 +05:30
# define DAVINCI_CPUIDLE_MAX_STATES 2
static void __iomem * ddr2_reg_base ;
2013-02-04 12:01:41 +00:00
static bool ddr2_pdown ;
2009-11-03 15:14:13 +05:30
static void davinci_save_ddr_power ( int enter , bool pdown )
{
u32 val ;
val = __raw_readl ( ddr2_reg_base + DDR2_SDRCR_OFFSET ) ;
if ( enter ) {
if ( pdown )
val | = DDR2_SRPD_BIT ;
else
val & = ~ DDR2_SRPD_BIT ;
val | = DDR2_LPMODEN_BIT ;
} else {
val & = ~ ( DDR2_SRPD_BIT | DDR2_LPMODEN_BIT ) ;
}
__raw_writel ( val , ddr2_reg_base + DDR2_SDRCR_OFFSET ) ;
}
2013-02-04 12:01:42 +00:00
/* Actual code that puts the SoC in different idle states */
static int davinci_enter_idle ( struct cpuidle_device * dev ,
2013-04-03 12:15:19 +00:00
struct cpuidle_driver * drv , int index )
2013-02-04 12:01:42 +00:00
{
2013-02-04 12:01:43 +00:00
davinci_save_ddr_power ( 1 , ddr2_pdown ) ;
2013-04-03 12:15:19 +00:00
cpu_do_idle ( ) ;
2013-02-04 12:01:43 +00:00
davinci_save_ddr_power ( 0 , ddr2_pdown ) ;
2013-02-04 12:01:42 +00:00
return index ;
}
static struct cpuidle_driver davinci_idle_driver = {
. name = " cpuidle-davinci " ,
. owner = THIS_MODULE ,
. states [ 0 ] = ARM_CPUIDLE_WFI_STATE ,
. states [ 1 ] = {
. enter = davinci_enter_idle ,
. exit_latency = 10 ,
2013-06-28 12:09:09 +02:00
. target_residency = 10000 ,
2013-02-04 12:01:42 +00:00
. flags = CPUIDLE_FLAG_TIME_VALID ,
. name = " DDR SR " ,
. desc = " WFI and DDR Self Refresh " ,
} ,
. state_count = DAVINCI_CPUIDLE_MAX_STATES ,
} ;
2009-11-03 15:14:13 +05:30
static int __init davinci_cpuidle_probe ( struct platform_device * pdev )
{
struct davinci_cpuidle_config * pdata = pdev - > dev . platform_data ;
if ( ! pdata ) {
dev_err ( & pdev - > dev , " cannot get platform data \n " ) ;
return - ENOENT ;
}
2009-11-16 17:21:37 +05:30
ddr2_reg_base = pdata - > ddr2_ctlr_base ;
2009-11-03 15:14:13 +05:30
2013-02-04 12:01:41 +00:00
ddr2_pdown = pdata - > ddr2_pdown ;
2009-11-03 15:14:13 +05:30
2013-04-23 08:54:44 +00:00
return cpuidle_register ( & davinci_idle_driver , NULL ) ;
2009-11-03 15:14:13 +05:30
}
static struct platform_driver davinci_cpuidle_driver = {
. driver = {
. name = " cpuidle-davinci " ,
. owner = THIS_MODULE ,
} ,
} ;
static int __init davinci_cpuidle_init ( void )
{
return platform_driver_probe ( & davinci_cpuidle_driver ,
davinci_cpuidle_probe ) ;
}
device_initcall ( davinci_cpuidle_init ) ;