summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-09-14 22:27:07 -0700
committerVarun Colbert <vcolbert@nvidia.com>2011-09-16 14:59:00 -0700
commit99966c242920978a92f3f51e5957ada30afc4b1d (patch)
tree61fb9677d54f01bdd51555a06c510c4afe0b1906
parentebea06768d9c9d351a7d1c8dc6499c97f2f5002d (diff)
ARM: tegra: power: Restore Tegra3 MC registers after LP0
On exit from deep sleep (LP0) restore from SDRAM Tegra3 MC registers that are not saved in PMC scratch file for boot-rom restoration. Since SDRAM after LP0 is running at boot rate, MC registers are saved only once during initialization. Bug 874351 Change-Id: Ib9ace46ede1efd5ee4097b17c3591a5b9f937a60 Reviewed-on: http://git-master/r/52526 Reviewed-by: Scott Williams <scwilliams@nvidia.com> Reviewed-by: Ankit Pashiney <apashiney@nvidia.com> Reviewed-by: Daniel Solomon <daniels@nvidia.com> Tested-by: Daniel Solomon <daniels@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/common-t3.c59
-rw-r--r--arch/arm/mach-tegra/suspend-t3.c13
-rw-r--r--arch/arm/mach-tegra/tegra3_emc.h10
3 files changed, 71 insertions, 11 deletions
diff --git a/arch/arm/mach-tegra/common-t3.c b/arch/arm/mach-tegra/common-t3.c
index d5393002b55f..b2a6c9870413 100644
--- a/arch/arm/mach-tegra/common-t3.c
+++ b/arch/arm/mach-tegra/common-t3.c
@@ -40,6 +40,11 @@
#define MC_ERROR_STATUS 0x8
#define MC_ERROR_ADDRESS 0xC
+#define MC_TIMING_REG_NUM1 \
+ ((MC_EMEM_ARB_TIMING_W2R - MC_EMEM_ARB_CFG) / 4 + 1)
+#define MC_TIMING_REG_NUM2 \
+ ((MC_EMEM_ARB_MISC1 - MC_EMEM_ARB_DA_TURNS) / 4 + 1)
+
struct mc_client {
const char *name;
};
@@ -49,6 +54,57 @@ struct mc_client {
.name = _name, \
}
+
+static void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE);
+
+
+#ifdef CONFIG_PM
+static u32 mc_boot_timing[MC_TIMING_REG_NUM1 + MC_TIMING_REG_NUM2 + 4];
+
+static void tegra_mc_timing_save(void)
+{
+ u32 off;
+ u32 *ctx = mc_boot_timing;
+
+ for (off = MC_EMEM_ARB_CFG; off <= MC_EMEM_ARB_TIMING_W2R; off += 4)
+ *ctx++ = readl((u32)mc + off);
+
+ for (off = MC_EMEM_ARB_DA_TURNS; off <= MC_EMEM_ARB_MISC1; off += 4)
+ *ctx++ = readl((u32)mc + off);
+
+ *ctx++ = readl((u32)mc + MC_EMEM_ARB_RING3_THROTTLE);
+ *ctx++ = readl((u32)mc + MC_EMEM_ARB_OVERRIDE);
+ *ctx++ = readl((u32)mc + MC_RESERVED_RSV);
+
+ *ctx++ = readl((u32)mc + MC_INT_MASK);
+}
+
+void tegra_mc_timing_restore(void)
+{
+ u32 off;
+ u32 *ctx = mc_boot_timing;
+
+ for (off = MC_EMEM_ARB_CFG; off <= MC_EMEM_ARB_TIMING_W2R; off += 4)
+ __raw_writel(*ctx++, (u32)mc + off);
+
+ for (off = MC_EMEM_ARB_DA_TURNS; off <= MC_EMEM_ARB_MISC1; off += 4)
+ __raw_writel(*ctx++, (u32)mc + off);
+
+ __raw_writel(*ctx++, (u32)mc + MC_EMEM_ARB_RING3_THROTTLE);
+ __raw_writel(*ctx++, (u32)mc + MC_EMEM_ARB_OVERRIDE);
+ __raw_writel(*ctx++, (u32)mc + MC_RESERVED_RSV);
+
+ writel(*ctx++, (u32)mc + MC_INT_MASK);
+ off = readl((u32)mc + MC_INT_MASK);
+
+ writel(0x1, (u32)mc + MC_TIMING_CONTROL);
+ off = readl((u32)mc + MC_TIMING_CONTROL);
+}
+#else
+#define tegra_mc_timing_save()
+#endif
+
+
static const struct mc_client mc_clients[] = {
client("ptc"),
client("display0_wina"), client("display1_wina"),
@@ -115,7 +171,6 @@ static DECLARE_DELAYED_WORK(unthrottle_prints_work, unthrottle_prints);
static irqreturn_t tegra_mc_error_isr(int irq, void *data)
{
- void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE);
const struct mc_client *client = NULL;
const char *mc_err;
const char *mc_err_info;
@@ -187,7 +242,6 @@ out:
void __init tegra_mc_init(void)
{
- void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE);
u32 reg;
reg = 0x0A7F1010;
@@ -205,4 +259,5 @@ void __init tegra_mc_init(void)
MC_INT_INVALID_SMMU_PAGE;
writel(reg, mc + MC_INT_MASK);
}
+ tegra_mc_timing_save();
}
diff --git a/arch/arm/mach-tegra/suspend-t3.c b/arch/arm/mach-tegra/suspend-t3.c
index 0734b0f07f04..96dff35149c2 100644
--- a/arch/arm/mach-tegra/suspend-t3.c
+++ b/arch/arm/mach-tegra/suspend-t3.c
@@ -415,21 +415,16 @@ int tegra_wake_to_irq(int wake)
return tegra_wake_event_irq[wake];
}
-static u32 mc_reserved_rsv;
-static u32 mc_emem_arb_override;
-
void tegra_lp0_suspend_mc(void)
{
- void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE);
- mc_reserved_rsv = readl(mc + MC_RESERVED_RSV);
- mc_emem_arb_override = readl(mc + MC_EMEM_ARB_OVERRIDE);
+ /* Since memory frequency after LP0 is restored to boot rate,
+ mc timing is saved during init, not on entry to LP0. Keep
+ this hook just in case, anyway */
}
void tegra_lp0_resume_mc(void)
{
- void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE);
- writel(mc_reserved_rsv, mc + MC_RESERVED_RSV);
- writel(mc_emem_arb_override, mc + MC_EMEM_ARB_OVERRIDE);
+ tegra_mc_timing_restore();
}
void tegra_lp0_cpu_mode(bool enter)
diff --git a/arch/arm/mach-tegra/tegra3_emc.h b/arch/arm/mach-tegra/tegra3_emc.h
index df3989764de6..daa313f0f516 100644
--- a/arch/arm/mach-tegra/tegra3_emc.h
+++ b/arch/arm/mach-tegra/tegra3_emc.h
@@ -47,6 +47,13 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size);
int tegra_emc_get_dram_type(void);
+#ifdef CONFIG_PM
+void tegra_mc_timing_restore(void);
+#else
+static inline void tegra_mc_timing_restore(void)
+{ }
+#endif
+
#define EMC_INTSTATUS 0x0
#define EMC_INTSTATUS_CLKCHANGE_COMPLETE (0x1 << 4)
@@ -252,8 +259,11 @@ enum {
#define MC_EMEM_ARB_DA_COVERS 0xd4
#define MC_EMEM_ARB_MISC0 0xd8
#define MC_EMEM_ARB_MISC0_EMC_SAME_FREQ (0x1 << 27)
+#define MC_EMEM_ARB_MISC1 0xdc
#define MC_EMEM_ARB_RING1_THROTTLE 0xe0
+#define MC_EMEM_ARB_RING3_THROTTLE 0xe4
#define MC_EMEM_ARB_OVERRIDE 0xe8
+#define MC_TIMING_CONTROL 0xfc
#define MC_RESERVED_RSV 0x3fc
#endif