From a9d2ba1444b0af6c2d8534f0b306660ffc045bc6 Mon Sep 17 00:00:00 2001 From: Ian Wisbon Date: Thu, 10 Feb 2011 17:15:15 -0500 Subject: Linux 2.6.31 Release for Digi ConnectCore Wi-i.MX boards --- arch/arm/mach-mx5/pm.c | 81 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 29 deletions(-) (limited to 'arch/arm/mach-mx5/pm.c') 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 #include #include -#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); -- cgit v1.2.3