diff options
-rw-r--r-- | arch/arm/mach-tegra/pm-t3.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pm.c | 66 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pm.h | 8 | ||||
-rw-r--r-- | arch/arm64/mach-tegra/pm.c | 14 | ||||
-rw-r--r-- | drivers/platform/tegra/Makefile | 1 | ||||
-rw-r--r-- | drivers/platform/tegra/pm.c | 92 | ||||
-rw-r--r-- | include/linux/tegra-pm.h | 19 | ||||
-rw-r--r-- | include/linux/tegra-pmc.h | 10 |
8 files changed, 116 insertions, 97 deletions
diff --git a/arch/arm/mach-tegra/pm-t3.c b/arch/arm/mach-tegra/pm-t3.c index 371f48448ac6..167f796271c9 100644 --- a/arch/arm/mach-tegra/pm-t3.c +++ b/arch/arm/mach-tegra/pm-t3.c @@ -3,7 +3,7 @@ * * Tegra3 SOC-specific power and cluster management * - * Copyright (c) 2009-2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2009-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +33,7 @@ #include <linux/tegra-powergate.h> #include <linux/tegra-soc.h> #include <linux/tegra-cpuidle.h> +#include <linux/tegra-pm.h> #include <mach/irqs.h> #include <mach/io_dpd.h> diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 16e9b2cf55a9..4d4415f54a61 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -134,8 +134,6 @@ static u64 suspend_time; static u64 suspend_entry_time; #endif -static RAW_NOTIFIER_HEAD(tegra_pm_chain_head); - #if defined(CONFIG_ARCH_TEGRA_14x_SOC) static void update_pmc_registers(unsigned long rate); #endif @@ -281,27 +279,6 @@ void tegra_cluster_switch_time(unsigned int flags, int id) } #endif -int tegra_register_pm_notifier(struct notifier_block *nb) -{ - return raw_notifier_chain_register(&tegra_pm_chain_head, nb); -} -EXPORT_SYMBOL(tegra_register_pm_notifier); - -int tegra_unregister_pm_notifier(struct notifier_block *nb) -{ - return raw_notifier_chain_unregister(&tegra_pm_chain_head, nb); -} -EXPORT_SYMBOL(tegra_unregister_pm_notifier); - -#ifdef CONFIG_TEGRA_LP0_IN_IDLE -static int tegra_pm_notifier_call_chain(unsigned int val) -{ - int ret = raw_notifier_call_chain(&tegra_pm_chain_head, val, NULL); - - return notifier_to_errno(ret); -} -#endif - #ifdef CONFIG_PM_SLEEP static const char *tegra_suspend_name[TEGRA_MAX_SUSPEND_MODE] = { [TEGRA_SUSPEND_NONE] = "none", @@ -1331,49 +1308,6 @@ static void tegra_disable_lp1bb_interrupt(void) } #endif -#ifdef CONFIG_TEGRA_LP0_IN_IDLE -int tegra_enter_lp0(unsigned long sleep_time) -{ - int err = 0; - - /* This state is managed by power domains, hence no voice call expected if - * we are entering this state */ - - tegra_pm_notifier_call_chain(TEGRA_PM_SUSPEND); - - tegra_rtc_set_trigger(sleep_time); - - tegra_actmon_save(); - - tegra_dma_save(); - - tegra_smmu_save(); - - err = syscore_save(); - if (err) { - tegra_smmu_restore(); - tegra_dma_restore(); - tegra_rtc_set_trigger(0); - return err; - } - - tegra_suspend_dram(TEGRA_SUSPEND_LP0, 0); - - syscore_restore(); - - tegra_smmu_restore(); - - tegra_dma_restore(); - - tegra_actmon_restore(); - - tegra_rtc_set_trigger(0); - - tegra_pm_notifier_call_chain(TEGRA_PM_RESUME); - - return 0; -} -#endif int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags) { diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h index cda2282e1ae4..d2eb583985ae 100644 --- a/arch/arm/mach-tegra/pm.h +++ b/arch/arm/mach-tegra/pm.h @@ -30,6 +30,7 @@ #include <linux/errno.h> #include <linux/clkdev.h> #include <linux/tegra-pmc.h> +#include <linux/tegra-pm.h> #include "iomap.h" @@ -112,13 +113,6 @@ bool tegra_set_cpu_in_pd(int cpu); void tegra_mc_clk_prepare(void); void tegra_mc_clk_finish(void); -int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags); -#ifdef CONFIG_TEGRA_LP0_IN_IDLE -int tegra_enter_lp0(unsigned long sleep_time); -#else -static inline int tegra_enter_lp0(unsigned long sleep_time) -{ return 0; } -#endif #ifdef CONFIG_TEGRA_LP1_LOW_COREVOLTAGE int tegra_is_lp1_suspend_mode(void); #endif diff --git a/arch/arm64/mach-tegra/pm.c b/arch/arm64/mach-tegra/pm.c index 58b56ab792a0..f5bf54445a61 100644 --- a/arch/arm64/mach-tegra/pm.c +++ b/arch/arm64/mach-tegra/pm.c @@ -127,8 +127,6 @@ static u64 suspend_time; static u64 suspend_entry_time; #endif -static RAW_NOTIFIER_HEAD(tegra_pm_chain_head); - struct suspend_context tegra_sctx; #define TEGRA_POWER_PWRREQ_POLARITY (1 << 8) /* core power request polarity */ @@ -216,18 +214,6 @@ bool tegra_suspend_in_progress(void) return suspend_in_progress; } -int tegra_register_pm_notifier(struct notifier_block *nb) -{ - return raw_notifier_chain_register(&tegra_pm_chain_head, nb); -} -EXPORT_SYMBOL(tegra_register_pm_notifier); - -int tegra_unregister_pm_notifier(struct notifier_block *nb) -{ - return raw_notifier_chain_unregister(&tegra_pm_chain_head, nb); -} -EXPORT_SYMBOL(tegra_unregister_pm_notifier); - bool tegra_dvfs_is_dfll_bypass(void) { #ifdef CONFIG_REGULATOR_TEGRA_DFLL_BYPASS diff --git a/drivers/platform/tegra/Makefile b/drivers/platform/tegra/Makefile index 918e2af246b6..50d5e494b02f 100644 --- a/drivers/platform/tegra/Makefile +++ b/drivers/platform/tegra/Makefile @@ -15,6 +15,7 @@ endif obj-y += mc/ obj-$(CONFIG_PM_SLEEP) += pm-irq.o obj-y += pmc.o +obj-y += pm.o obj-$(CONFIG_TEGRA_MC_DOMAINS) += pm_domains.o diff --git a/drivers/platform/tegra/pm.c b/drivers/platform/tegra/pm.c new file mode 100644 index 000000000000..654ff2460349 --- /dev/null +++ b/drivers/platform/tegra/pm.c @@ -0,0 +1,92 @@ +/* + * drivers/platform/tegra/pm.c + * + * CPU complex suspend & resume functions for Tegra SoCs + * + * Copyright (c) 2009-2014, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <linux/notifier.h> +#include <linux/tegra_pm_domains.h> + +static RAW_NOTIFIER_HEAD(tegra_pm_chain_head); + +int tegra_register_pm_notifier(struct notifier_block *nb) +{ + return raw_notifier_chain_register(&tegra_pm_chain_head, nb); +} +EXPORT_SYMBOL(tegra_register_pm_notifier); + +int tegra_unregister_pm_notifier(struct notifier_block *nb) +{ + return raw_notifier_chain_unregister(&tegra_pm_chain_head, nb); +} +EXPORT_SYMBOL(tegra_unregister_pm_notifier); + +#ifdef CONFIG_TEGRA_LP0_IN_IDLE +static int tegra_pm_notifier_call_chain(unsigned int val) +{ + int ret = raw_notifier_call_chain(&tegra_pm_chain_head, val, NULL); + + return notifier_to_errno(ret); +} + +int tegra_enter_lp0(unsigned long sleep_time) +{ + int err = 0; + + /* + * This state is managed by power domains, + * hence no voice call expected if + * we are entering this state + */ + + tegra_pm_notifier_call_chain(TEGRA_PM_SUSPEND); + + tegra_rtc_set_trigger(sleep_time); + + tegra_actmon_save(); + + tegra_dma_save(); + + tegra_smmu_save(); + + err = syscore_save(); + if (err) { + tegra_smmu_restore(); + tegra_dma_restore(); + tegra_rtc_set_trigger(0); + return err; + } + + tegra_suspend_dram(TEGRA_SUSPEND_LP0, 0); + + syscore_restore(); + + tegra_smmu_restore(); + + tegra_dma_restore(); + + tegra_actmon_restore(); + + tegra_rtc_set_trigger(0); + + tegra_pm_notifier_call_chain(TEGRA_PM_RESUME); + + return 0; +} +#endif diff --git a/include/linux/tegra-pm.h b/include/linux/tegra-pm.h index 37ccc88cbbf6..38d5ba6e5e8d 100644 --- a/include/linux/tegra-pm.h +++ b/include/linux/tegra-pm.h @@ -1,7 +1,7 @@ /* * include/linux/tegra-pm.h * - * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. * * 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 @@ -23,7 +23,24 @@ #define TEGRA_PM_SUSPEND 0x0001 #define TEGRA_PM_RESUME 0x0002 +enum tegra_suspend_mode { + TEGRA_SUSPEND_NONE = 0, + TEGRA_SUSPEND_LP2, /* CPU voltage off */ + TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */ + TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */ + TEGRA_MAX_SUSPEND_MODE, +}; + +int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags); + int tegra_register_pm_notifier(struct notifier_block *nb); int tegra_unregister_pm_notifier(struct notifier_block *nb); +#ifdef CONFIG_TEGRA_LP0_IN_IDLE +int tegra_enter_lp0(unsigned long sleep_time); +#else +static inline int tegra_enter_lp0(unsigned long sleep_time) +{ return 0; } +#endif + #endif /* _LINUX_TEGRA_PM_H_ */ diff --git a/include/linux/tegra-pmc.h b/include/linux/tegra-pmc.h index 002f8849905d..1bcb11a81449 100644 --- a/include/linux/tegra-pmc.h +++ b/include/linux/tegra-pmc.h @@ -21,6 +21,8 @@ #ifndef __LINUX_TEGRA_PMC_H__ #define __LINUX_TEGRA_PMC_H__ +#include <linux/tegra-pm.h> + extern void tegra_pmc_set_dpd_sample(void); extern void tegra_pmc_clear_dpd_sample(void); extern void tegra_pmc_remove_dpd_req(void); @@ -28,14 +30,6 @@ extern void __iomem *tegra_pmc_base; extern bool tegra_is_dpd_mode; -enum tegra_suspend_mode { - TEGRA_SUSPEND_NONE = 0, - TEGRA_SUSPEND_LP2, /* CPU voltage off */ - TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */ - TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */ - TEGRA_MAX_SUSPEND_MODE, -}; - struct pmc_pm_data { u32 cpu_good_time; /* CPU power good time in uS */ u32 cpu_off_time; /* CPU power off time in uS */ |