diff options
Diffstat (limited to 'kernel/arch/arm/mach-tegra/cpuidle-tegra114.c')
-rw-r--r-- | kernel/arch/arm/mach-tegra/cpuidle-tegra114.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/kernel/arch/arm/mach-tegra/cpuidle-tegra114.c b/kernel/arch/arm/mach-tegra/cpuidle-tegra114.c new file mode 100644 index 000000000..155807fa6 --- /dev/null +++ b/kernel/arch/arm/mach-tegra/cpuidle-tegra114.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013, NVIDIA Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <asm/firmware.h> +#include <linux/tick.h> +#include <linux/cpuidle.h> +#include <linux/cpu_pm.h> +#include <linux/kernel.h> +#include <linux/module.h> + +#include <asm/cpuidle.h> +#include <asm/smp_plat.h> +#include <asm/suspend.h> + +#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(); + + tick_broadcast_enter(); + + call_firmware_op(prepare_idle); + + /* Do suspend by ourselves if the firmware does not implement it */ + if (call_firmware_op(do_idle, 0) == -ENOSYS) + cpu_suspend(0, tegra30_sleep_cpu_secondary_finish); + + tick_broadcast_exit(); + + cpu_pm_exit(); + tegra_clear_cpu_in_lp2(); + + local_fiq_enable(); + + return index; +} +#endif + +static struct cpuidle_driver tegra_idle_driver = { + .name = "tegra_idle", + .owner = THIS_MODULE, + .state_count = TEGRA114_MAX_STATES, + .states = { + [0] = ARM_CPUIDLE_WFI_STATE_PWR(600), +#ifdef CONFIG_PM_SLEEP + [1] = { + .enter = tegra114_idle_power_down, + .exit_latency = 500, + .target_residency = 1000, + .power_usage = 0, + .name = "powered-down", + .desc = "CPU power gated", + }, +#endif + }, +}; + +int __init tegra114_cpuidle_init(void) +{ + return cpuidle_register(&tegra_idle_driver, NULL); +} |