diff options
author | Alex Frid <afrid@nvidia.com> | 2011-09-14 22:27:07 -0700 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-09-16 14:59:00 -0700 |
commit | 99966c242920978a92f3f51e5957ada30afc4b1d (patch) | |
tree | 61fb9677d54f01bdd51555a06c510c4afe0b1906 /arch | |
parent | ebea06768d9c9d351a7d1c8dc6499c97f2f5002d (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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/common-t3.c | 59 | ||||
-rw-r--r-- | arch/arm/mach-tegra/suspend-t3.c | 13 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_emc.h | 10 |
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 |