blob: 654ff2460349ff5665f8c13bdc599f7fde0cbdb5 [file] [log] [blame]
/*
* 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