summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-10-22 19:06:33 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:46 -0800
commit8eb7374dbf3c7b312d23e36f80dcd685e09a3738 (patch)
treed14bdcc0edb23888fa9a1d01f0455cbe4f61db28 /arch
parent9738f60a41ff7910e58f3100f5dcb1fb5c2e0321 (diff)
ARM: tegra: power: Enable Tegra3 EMC bridge in suspend
When dvfs is suspended core rail is set to nominal voltage underneath clock framework. On Tegra3 DDR3 platforms low EMC rates are not safe at high voltage that exceeds EMC bridge minimum level. Enabling EMC bridge during suspend for Tegra3 DDR3 platforms guarantees safe EMC operations at high voltage. (cherry picked from commit 677c01d3d9edaf7e91f09de5025e7864b6a288d8) (cherry picked from commit 75710c173caa46f2e3cd24e48cc82f030cdb52d9) Change-Id: I1e300c18867295b1394184da39eeffcab43de4c7 Reviewed-on: http://git-master/r/62030 Tested-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Krishna Reddy <vdumpa@nvidia.com> Rebase-Id: R2a3a91b370d2517e89e1d30f27f9fd41a9a81267
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/tegra3_emc.c48
1 files changed, 46 insertions, 2 deletions
diff --git a/arch/arm/mach-tegra/tegra3_emc.c b/arch/arm/mach-tegra/tegra3_emc.c
index e8df8c8209ab..49833f28f56a 100644
--- a/arch/arm/mach-tegra/tegra3_emc.c
+++ b/arch/arm/mach-tegra/tegra3_emc.c
@@ -25,6 +25,7 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/suspend.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
@@ -195,9 +196,10 @@ static int tegra_emc_table_size;
static u32 dram_dev_num;
static u32 emc_cfg_saved;
-
static u32 dram_type = -1;
+
static struct clk *emc;
+static struct clk *bridge;
static struct {
cputime64_t time_at_clock[TEGRA_EMC_TABLE_MAX_SIZE];
@@ -746,7 +748,8 @@ static bool is_emc_bridge(void)
{
int mv;
unsigned long rate;
- struct clk *bridge = tegra_get_clock_by_name("bridge.emc");
+
+ bridge = tegra_get_clock_by_name("bridge.emc");
BUG_ON(!bridge);
/* LPDDR2 does not need a bridge entry in DFS table: just lock bridge
@@ -772,6 +775,44 @@ static bool is_emc_bridge(void)
return true;
}
+static int tegra_emc_suspend_notify(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ if (event != PM_SUSPEND_PREPARE)
+ return NOTIFY_OK;
+
+ if (dram_type == DRAM_TYPE_DDR3) {
+ if (clk_enable(bridge)) {
+ pr_info("Tegra emc suspend:"
+ " failed to enable bridge.emc\n");
+ return NOTIFY_STOP;
+ }
+ pr_info("Tegra emc suspend: enabled bridge.emc\n");
+ }
+ return NOTIFY_OK;
+};
+static struct notifier_block tegra_emc_suspend_nb = {
+ .notifier_call = tegra_emc_suspend_notify,
+ .priority = 2,
+};
+
+static int tegra_emc_resume_notify(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ if (event != PM_POST_SUSPEND)
+ return NOTIFY_OK;
+
+ if (dram_type == DRAM_TYPE_DDR3) {
+ clk_disable(bridge);
+ pr_info("Tegra emc resume: disabled bridge.emc\n");
+ }
+ return NOTIFY_OK;
+};
+static struct notifier_block tegra_emc_resume_nb = {
+ .notifier_call = tegra_emc_resume_notify,
+ .priority = -1,
+};
+
void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
{
int i;
@@ -866,6 +907,9 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
pr_err("tegra: invalid EMC DFS table: emc bridge not found");
}
pr_info("tegra: validated EMC DFS table\n");
+
+ register_pm_notifier(&tegra_emc_suspend_nb);
+ register_pm_notifier(&tegra_emc_resume_nb);
}
void tegra_emc_timing_invalidate(void)