2019-05-28 10:10:04 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2013-01-21 17:49:06 +08:00
/*
* Copyright ( c ) 2013 , NVIDIA Corporation . All rights reserved .
*/
2014-07-11 09:44:49 +02:00
# include <asm/firmware.h>
2015-04-03 02:32:14 +02:00
# include <linux/tick.h>
2013-01-21 17:49:06 +08:00
# include <linux/cpuidle.h>
2013-07-19 17:25:26 +08:00
# include <linux/cpu_pm.h>
2014-07-11 09:44:49 +02:00
# include <linux/kernel.h>
# include <linux/module.h>
2013-01-21 17:49:06 +08:00
2019-04-10 10:47:28 +02:00
# include <linux/firmware/trusted_foundations.h>
2013-01-21 17:49:06 +08:00
# include <asm/cpuidle.h>
2013-07-19 17:25:26 +08:00
# include <asm/smp_plat.h>
2014-07-11 09:44:49 +02:00
# include <asm/suspend.h>
2015-02-23 15:24:11 +01:00
# include <asm/psci.h>
2013-07-19 17:25:26 +08:00
2016-04-28 14:52:45 +02:00
# include "cpuidle.h"
2013-07-19 17:25:26 +08:00
# include "pm.h"
# include "sleep.h"
# ifdef CONFIG_PM_SLEEP
# define TEGRA114_MAX_STATES 2
# else
# define TEGRA114_MAX_STATES 1
# endif
# ifdef CONFIG_PM_SLEEP
static int tegra114_idle_power_down ( struct cpuidle_device * dev ,
struct cpuidle_driver * drv ,
int index )
{
local_fiq_disable ( ) ;
tegra_set_cpu_in_lp2 ( ) ;
cpu_pm_enter ( ) ;
2019-03-18 01:52:05 +03:00
call_firmware_op ( prepare_idle , TF_PM_MODE_LP2_NOFLUSH_L2 ) ;
2014-02-12 11:43:44 +09:00
/* Do suspend by ourselves if the firmware does not implement it */
2014-09-25 17:59:41 +09:00
if ( call_firmware_op ( do_idle , 0 ) = = - ENOSYS )
2014-02-12 11:43:44 +09:00
cpu_suspend ( 0 , tegra30_sleep_cpu_secondary_finish ) ;
2013-07-19 17:25:26 +08:00
cpu_pm_exit ( ) ;
tegra_clear_cpu_in_lp2 ( ) ;
local_fiq_enable ( ) ;
return index ;
}
2015-05-19 16:49:12 +02:00
2017-08-10 00:14:45 +02:00
static void tegra114_idle_enter_s2idle ( struct cpuidle_device * dev ,
2015-05-19 16:49:12 +02:00
struct cpuidle_driver * drv ,
int index )
{
tegra114_idle_power_down ( dev , drv , index ) ;
}
2013-07-19 17:25:26 +08:00
# endif
2013-01-21 17:49:06 +08:00
static struct cpuidle_driver tegra_idle_driver = {
. name = " tegra_idle " ,
. owner = THIS_MODULE ,
2013-07-19 17:25:26 +08:00
. state_count = TEGRA114_MAX_STATES ,
2013-01-21 17:49:06 +08:00
. states = {
[ 0 ] = ARM_CPUIDLE_WFI_STATE_PWR ( 600 ) ,
2013-07-19 17:25:26 +08:00
# ifdef CONFIG_PM_SLEEP
[ 1 ] = {
. enter = tegra114_idle_power_down ,
2017-08-10 00:14:45 +02:00
. enter_s2idle = tegra114_idle_enter_s2idle ,
2013-07-19 17:25:26 +08:00
. exit_latency = 500 ,
. target_residency = 1000 ,
2015-05-19 16:49:12 +02:00
. flags = CPUIDLE_FLAG_TIMER_STOP ,
2013-07-19 17:25:26 +08:00
. power_usage = 0 ,
. name = " powered-down " ,
. desc = " CPU power gated " ,
} ,
# endif
2013-01-21 17:49:06 +08:00
} ,
} ;
int __init tegra114_cpuidle_init ( void )
{
2015-02-23 15:24:11 +01:00
if ( ! psci_smp_available ( ) )
return cpuidle_register ( & tegra_idle_driver , NULL ) ;
return 0 ;
2013-01-21 17:49:06 +08:00
}