summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx5/pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx5/pm.c')
-rw-r--r--arch/arm/mach-mx5/pm.c81
1 files changed, 52 insertions, 29 deletions
diff --git a/arch/arm/mach-mx5/pm.c b/arch/arm/mach-mx5/pm.c
index a63d6e725e8f..b2bf2f8355fd 100644
--- a/arch/arm/mach-mx5/pm.c
+++ b/arch/arm/mach-mx5/pm.c
@@ -25,9 +25,15 @@
#include <asm/tlb.h>
#include <asm/mach/map.h>
#include <mach/hardware.h>
-#include "crm_regs.h"
#include "mach/irqs.h"
+#define MXC_SRPG_EMPGC0_SRPGCR (IO_ADDRESS(GPC_BASE_ADDR) + 0x2C0)
+#define MXC_SRPG_EMPGC1_SRPGCR (IO_ADDRESS(GPC_BASE_ADDR) + 0x2D0)
+#define DATABAHN_CTL_REG0 0
+#define DATABAHN_CTL_REG19 0x4c
+#define DATABAHN_CTL_REG79 0x13c
+#define DATABAHN_PHY_REG25 0x264
+
static struct cpu_wp *cpu_wp_tbl;
static struct clk *cpu_clk;
@@ -41,16 +47,17 @@ extern int set_cpu_freq(int wp);
static struct device *pm_dev;
struct clk *gpc_dvfs_clk;
extern void cpu_do_suspend_workaround(u32 sdclk_iomux_addr);
-extern void cpu_cortexa8_do_idle(void *);
+extern void mx50_suspend(u32 databahn_addr);
extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+extern void __iomem *databahn_base;
extern int iram_ready;
void *suspend_iram_base;
void (*suspend_in_iram)(void *sdclk_iomux_addr) = NULL;
+void __iomem *suspend_param1;
-static int mx51_suspend_enter(suspend_state_t state)
+static int mx5_suspend_enter(suspend_state_t state)
{
- void __iomem *sdclk_iomux_addr = IO_ADDRESS(IOMUXC_BASE_ADDR + 0x4b8);
u32 * wake_src;
/* Check that we have a wake up source. We don't want to suspend if not.*/
@@ -82,12 +89,15 @@ static int mx51_suspend_enter(suspend_state_t state)
local_flush_tlb_all();
flush_cache_all();
- /* Run the suspend code from iRAM. */
- suspend_in_iram(sdclk_iomux_addr);
+ if (cpu_is_mx51() || cpu_is_mx53()) {
+ /* Run the suspend code from iRAM. */
+ suspend_in_iram(suspend_param1);
- /*clear the EMPGC0/1 bits */
- __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
- __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
+ /*clear the EMPGC0/1 bits */
+ __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
+ __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
+ } else
+ suspend_in_iram(databahn_base);
} else {
cpu_do_idle();
}
@@ -99,7 +109,7 @@ static int mx51_suspend_enter(suspend_state_t state)
/*
* Called after processes are frozen, but before we shut down devices.
*/
-static int mx51_suspend_prepare(void)
+static int mx5_suspend_prepare(void)
{
#if defined(CONFIG_CPU_FREQ)
struct cpufreq_freqs freqs;
@@ -122,7 +132,7 @@ static int mx51_suspend_prepare(void)
/*
* Called before devices are re-setup.
*/
-static void mx51_suspend_finish(void)
+static void mx5_suspend_finish(void)
{
#if defined(CONFIG_CPU_FREQ)
struct cpufreq_freqs freqs;
@@ -145,35 +155,35 @@ static void mx51_suspend_finish(void)
/*
* Called after devices are re-setup, but before processes are thawed.
*/
-static void mx51_suspend_end(void)
+static void mx5_suspend_end(void)
{
}
-static int mx51_pm_valid(suspend_state_t state)
+static int mx5_pm_valid(suspend_state_t state)
{
return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
}
-struct platform_suspend_ops mx51_suspend_ops = {
- .valid = mx51_pm_valid,
- .prepare = mx51_suspend_prepare,
- .enter = mx51_suspend_enter,
- .finish = mx51_suspend_finish,
- .end = mx51_suspend_end,
+struct platform_suspend_ops mx5_suspend_ops = {
+ .valid = mx5_pm_valid,
+ .prepare = mx5_suspend_prepare,
+ .enter = mx5_suspend_enter,
+ .finish = mx5_suspend_finish,
+ .end = mx5_suspend_end,
};
-static int __devinit mx51_pm_probe(struct platform_device *pdev)
+static int __devinit mx5_pm_probe(struct platform_device *pdev)
{
pm_dev = &pdev->dev;
return 0;
}
-static struct platform_driver mx51_pm_driver = {
+static struct platform_driver mx5_pm_driver = {
.driver = {
- .name = "mx51_pm",
+ .name = "mx5_pm",
},
- .probe = mx51_pm_probe,
+ .probe = mx5_pm_probe,
};
static int __init pm_init(void)
@@ -181,19 +191,32 @@ static int __init pm_init(void)
int cpu_wp_nr;
unsigned long iram_paddr;
- pr_info("Static Power Management for Freescale i.MX51\n");
- if (platform_driver_register(&mx51_pm_driver) != 0) {
- printk(KERN_ERR "mx51_pm_driver register failed\n");
+ pr_info("Static Power Management for Freescale i.MX5\n");
+ if (platform_driver_register(&mx5_pm_driver) != 0) {
+ printk(KERN_ERR "mx5_pm_driver register failed\n");
return -ENODEV;
}
- suspend_set_ops(&mx51_suspend_ops);
+ suspend_set_ops(&mx5_suspend_ops);
/* Move suspend routine into iRAM */
iram_alloc(SZ_4K, &iram_paddr);
/* Need to remap the area here since we want the memory region
to be executable. */
suspend_iram_base = __arm_ioremap(iram_paddr, SZ_4K,
MT_HIGH_VECTORS);
- memcpy(suspend_iram_base, cpu_do_suspend_workaround, SZ_4K);
+
+ if (cpu_is_mx51() || cpu_is_mx53()) {
+ suspend_param1 = IO_ADDRESS(IOMUXC_BASE_ADDR + 0x4b8);
+ memcpy(suspend_iram_base, cpu_do_suspend_workaround,
+ SZ_4K);
+ } else if (cpu_is_mx50()) {
+ /*
+ * Need to run the suspend code from IRAM as the DDR needs
+ * to be put into self refresh mode manually.
+ */
+ memcpy(suspend_iram_base, mx50_suspend, SZ_4K);
+
+ suspend_param1 = databahn_base;
+ }
suspend_in_iram = (void *)suspend_iram_base;
cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
@@ -212,7 +235,7 @@ static int __init pm_init(void)
static void __exit pm_cleanup(void)
{
/* Unregister the device structure */
- platform_driver_unregister(&mx51_pm_driver);
+ platform_driver_unregister(&mx5_pm_driver);
}
module_init(pm_init);