Commit | Line | Data |
---|---|---|
51dc5259 JL |
1 | /* |
2 | * Copyright (c) 2013, NVIDIA Corporation. All rights reserved. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms and conditions of the GNU General Public License, | |
6 | * version 2, as published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope it will be useful, but WITHOUT | |
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
11 | * more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License | |
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
a0524acc | 17 | #include <asm/firmware.h> |
a0b41224 | 18 | #include <linux/tick.h> |
51dc5259 | 19 | #include <linux/cpuidle.h> |
3045cb33 | 20 | #include <linux/cpu_pm.h> |
a0524acc TR |
21 | #include <linux/kernel.h> |
22 | #include <linux/module.h> | |
51dc5259 JL |
23 | |
24 | #include <asm/cpuidle.h> | |
3045cb33 | 25 | #include <asm/smp_plat.h> |
a0524acc | 26 | #include <asm/suspend.h> |
3045cb33 JL |
27 | |
28 | #include "pm.h" | |
29 | #include "sleep.h" | |
30 | ||
31 | #ifdef CONFIG_PM_SLEEP | |
32 | #define TEGRA114_MAX_STATES 2 | |
33 | #else | |
34 | #define TEGRA114_MAX_STATES 1 | |
35 | #endif | |
36 | ||
37 | #ifdef CONFIG_PM_SLEEP | |
38 | static int tegra114_idle_power_down(struct cpuidle_device *dev, | |
39 | struct cpuidle_driver *drv, | |
40 | int index) | |
41 | { | |
42 | local_fiq_disable(); | |
43 | ||
44 | tegra_set_cpu_in_lp2(); | |
45 | cpu_pm_enter(); | |
46 | ||
a0b41224 | 47 | tick_broadcast_enter(); |
3045cb33 | 48 | |
338f2aad AC |
49 | call_firmware_op(prepare_idle); |
50 | ||
51 | /* Do suspend by ourselves if the firmware does not implement it */ | |
0b7778a8 | 52 | if (call_firmware_op(do_idle, 0) == -ENOSYS) |
338f2aad | 53 | cpu_suspend(0, tegra30_sleep_cpu_secondary_finish); |
3045cb33 | 54 | |
a0b41224 | 55 | tick_broadcast_exit(); |
3045cb33 JL |
56 | |
57 | cpu_pm_exit(); | |
58 | tegra_clear_cpu_in_lp2(); | |
59 | ||
60 | local_fiq_enable(); | |
61 | ||
62 | return index; | |
63 | } | |
64 | #endif | |
51dc5259 JL |
65 | |
66 | static struct cpuidle_driver tegra_idle_driver = { | |
67 | .name = "tegra_idle", | |
68 | .owner = THIS_MODULE, | |
3045cb33 | 69 | .state_count = TEGRA114_MAX_STATES, |
51dc5259 JL |
70 | .states = { |
71 | [0] = ARM_CPUIDLE_WFI_STATE_PWR(600), | |
3045cb33 JL |
72 | #ifdef CONFIG_PM_SLEEP |
73 | [1] = { | |
74 | .enter = tegra114_idle_power_down, | |
75 | .exit_latency = 500, | |
76 | .target_residency = 1000, | |
77 | .power_usage = 0, | |
3045cb33 JL |
78 | .name = "powered-down", |
79 | .desc = "CPU power gated", | |
80 | }, | |
81 | #endif | |
51dc5259 JL |
82 | }, |
83 | }; | |
84 | ||
51dc5259 JL |
85 | int __init tegra114_cpuidle_init(void) |
86 | { | |
e158f9da | 87 | return cpuidle_register(&tegra_idle_driver, NULL); |
51dc5259 | 88 | } |