Commit | Line | Data |
---|---|---|
9952f691 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
51dc5259 JL |
2 | /* |
3 | * Copyright (c) 2013, NVIDIA Corporation. All rights reserved. | |
51dc5259 JL |
4 | */ |
5 | ||
a0524acc | 6 | #include <asm/firmware.h> |
a0b41224 | 7 | #include <linux/tick.h> |
51dc5259 | 8 | #include <linux/cpuidle.h> |
3045cb33 | 9 | #include <linux/cpu_pm.h> |
a0524acc TR |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> | |
51dc5259 | 12 | |
4cb5d9ec TR |
13 | #include <linux/firmware/trusted_foundations.h> |
14 | ||
51dc5259 | 15 | #include <asm/cpuidle.h> |
3045cb33 | 16 | #include <asm/smp_plat.h> |
a0524acc | 17 | #include <asm/suspend.h> |
fc0cf177 | 18 | #include <asm/psci.h> |
3045cb33 | 19 | |
755c47ed | 20 | #include "cpuidle.h" |
3045cb33 JL |
21 | #include "pm.h" |
22 | #include "sleep.h" | |
23 | ||
24 | #ifdef CONFIG_PM_SLEEP | |
25 | #define TEGRA114_MAX_STATES 2 | |
26 | #else | |
27 | #define TEGRA114_MAX_STATES 1 | |
28 | #endif | |
29 | ||
30 | #ifdef CONFIG_PM_SLEEP | |
31 | static int tegra114_idle_power_down(struct cpuidle_device *dev, | |
32 | struct cpuidle_driver *drv, | |
33 | int index) | |
34 | { | |
35 | local_fiq_disable(); | |
36 | ||
37 | tegra_set_cpu_in_lp2(); | |
38 | cpu_pm_enter(); | |
39 | ||
96446e21 | 40 | call_firmware_op(prepare_idle, TF_PM_MODE_LP2_NOFLUSH_L2); |
338f2aad AC |
41 | |
42 | /* Do suspend by ourselves if the firmware does not implement it */ | |
0b7778a8 | 43 | if (call_firmware_op(do_idle, 0) == -ENOSYS) |
338f2aad | 44 | cpu_suspend(0, tegra30_sleep_cpu_secondary_finish); |
3045cb33 | 45 | |
3045cb33 JL |
46 | cpu_pm_exit(); |
47 | tegra_clear_cpu_in_lp2(); | |
48 | ||
49 | local_fiq_enable(); | |
50 | ||
51 | return index; | |
52 | } | |
1ec0e115 | 53 | |
28ba086e | 54 | static void tegra114_idle_enter_s2idle(struct cpuidle_device *dev, |
1ec0e115 TV |
55 | struct cpuidle_driver *drv, |
56 | int index) | |
57 | { | |
58 | tegra114_idle_power_down(dev, drv, index); | |
59 | } | |
3045cb33 | 60 | #endif |
51dc5259 JL |
61 | |
62 | static struct cpuidle_driver tegra_idle_driver = { | |
63 | .name = "tegra_idle", | |
64 | .owner = THIS_MODULE, | |
3045cb33 | 65 | .state_count = TEGRA114_MAX_STATES, |
51dc5259 JL |
66 | .states = { |
67 | [0] = ARM_CPUIDLE_WFI_STATE_PWR(600), | |
3045cb33 JL |
68 | #ifdef CONFIG_PM_SLEEP |
69 | [1] = { | |
70 | .enter = tegra114_idle_power_down, | |
28ba086e | 71 | .enter_s2idle = tegra114_idle_enter_s2idle, |
3045cb33 JL |
72 | .exit_latency = 500, |
73 | .target_residency = 1000, | |
1ec0e115 | 74 | .flags = CPUIDLE_FLAG_TIMER_STOP, |
3045cb33 | 75 | .power_usage = 0, |
3045cb33 JL |
76 | .name = "powered-down", |
77 | .desc = "CPU power gated", | |
78 | }, | |
79 | #endif | |
51dc5259 JL |
80 | }, |
81 | }; | |
82 | ||
51dc5259 JL |
83 | int __init tegra114_cpuidle_init(void) |
84 | { | |
fc0cf177 TR |
85 | if (!psci_smp_available()) |
86 | return cpuidle_register(&tegra_idle_driver, NULL); | |
87 | ||
88 | return 0; | |
51dc5259 | 89 | } |