In order to decrease the power consumption, when go to suspend,
disable the mpddr controller peripheral clock and the DDR clock
after the DDR enters the self-refresh mode.

Due the mpddr controller's issue, postpone the disable clocks operation,
instead of the DDR enters self-fresh mode immediately.

Enable the clocks after resume and before the DDR exits the self-refresh mode.

Signed-off-by: Wenyou Yang <wenyou.y...@atmel.com>
---
 arch/arm/mach-at91/pm.c         |    4 +++
 arch/arm/mach-at91/pm.h         |    8 +++++
 arch/arm/mach-at91/pm_suspend.S |   64 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 50cde92..6bd2a6b 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -145,6 +145,10 @@ static void at91_pm_suspend(suspend_state_t state)
        pm_data |= (state == PM_SUSPEND_MEM) ?
                                AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0;
 
+       pm_data |= AT91_PM_DDRCK(at91_pm_data.ddrck_id);
+
+       pm_data |= AT91_PM_DDRC_ID(at91_pm_data.mpddrc_id[0]);
+
        /* Disable L1 D-cache and L2 cache */
        at91_disable_l1_l2_cache();
 
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index 158575e..fd4c5fc 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -19,6 +19,14 @@
 #define        AT91_PM_MODE_MASK       0x0f
 #define        AT91_PM_MODE(x)         (((x) & AT91_PM_MODE_MASK) << 
AT91_PM_MODE_OFFSET)
 
+#define        AT91_PM_DDRCK_OFFSET    8
+#define        AT91_PM_DDRCK_MASK      0xff
+#define        AT91_PM_DDRCK(x)        (((x) & AT91_PM_DDRCK_MASK) << 
AT91_PM_DDRCK_OFFSET)
+
+#define        AT91_PM_DDRC_ID_OFFSET  16
+#define        AT91_PM_DDRC_ID_MASK    0xff
+#define        AT91_PM_DDRC_ID(x)      (((x) & AT91_PM_DDRC_ID_MASK) << 
AT91_PM_DDRC_ID_OFFSET)
+
 #define        AT91_PM_SLOW_CLOCK      0x01
 
 #endif
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index e6e7f7a..8fb276c 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -26,6 +26,8 @@ memctrl       .req    r3
 tmp1   .req    r4
 tmp2   .req    r5
 mode   .req    r6
+ddrc_id        .req    r7
+ddrck  .req    r8
 
 /*
  * Wait until master clock is ready (after switching master clock source)
@@ -130,6 +132,16 @@ ENTRY(at91_pm_suspend_in_sram)
        and     mode, tmp2, #AT91_PM_MODE_MASK
 
        mov     tmp1, memctrl
+       mov     tmp2, tmp1, lsr#AT91_PM_DDRCK_OFFSET
+       mov     tmp1, #0x01
+       and     tmp2, tmp2, #AT91_PM_DDRCK_MASK
+       mov     ddrck, tmp1, lsl tmp2
+
+       mov     tmp1, memctrl
+       mov     tmp2, tmp1, lsr#AT91_PM_DDRC_ID_OFFSET
+       and     ddrc_id, tmp2, #AT91_PM_DDRC_ID_MASK
+
+       mov     tmp1, memctrl
        and     memctrl, tmp1, #AT91_PM_MEMCTRL_MASK
 
        cmp     memctrl, #AT91_MEMCTRL_MC
@@ -234,6 +246,32 @@ sdr_sr_done:
        str     tmp1, [pmc, #AT91_CKGR_MOR]
 
 skip_disable_main_clock:
+
+       /*
+        * Disable the SDRAM controller clock
+        */
+       cmp     ddrc_id, #0
+       beq     skip_disable_ddrc_clock
+       bic     tmp2, ddrc_id, #0xe0 /* fetch least 5 bits */
+       mov     tmp1, #0x01
+       mov     tmp1, tmp1, lsl tmp2
+
+       tst     ddrc_id, #0xe0  /* > 32 ? */
+       beq     set_pmc_pcdr
+       str     tmp1, [pmc, #AT91_PMC_PCDR1]
+       b       skip_disable_ddrc_clock
+set_pmc_pcdr:
+       str     tmp1, [pmc, #AT91_PMC_PCDR]
+skip_disable_ddrc_clock:
+
+       /*
+        * Disable SDRAM system clock
+        */
+       cmp     ddrck, #0
+       beq     skip_disable_ddrck
+       str     ddrck, [pmc, #AT91_PMC_SCDR]
+skip_disable_ddrck:
+
        /* Wait for interrupt */
        _do_wfi
 
@@ -269,6 +307,32 @@ skip_disable_main_clock:
        wait_mckrdy
 
 skip_enable_main_clock:
+
+       /*
+        * Enable the SDRAM controller clock
+        */
+       cmp     ddrc_id, #0
+       beq     skip_enable_ddrc_clock
+       bic     tmp2, ddrc_id, #0xe0 /* fetch lowest 5 bits */
+       mov     tmp1, #0x01
+       mov     tmp1, tmp1, lsl tmp2
+
+       tst     ddrc_id, #0xe0  /* > 32 ? */
+       beq     set_pmc_pcer
+       str     tmp1, [pmc, #AT91_PMC_PCER1]
+       b       skip_enable_ddrc_clock
+set_pmc_pcer:
+       str     tmp1, [pmc, #AT91_PMC_PCER]
+skip_enable_ddrc_clock:
+
+       /*
+        * Enable SDRAM system clock
+        */
+       cmp     ddrck, #0
+       beq     skip_enable_ddrck
+       str     ddrck, [pmc, #AT91_PMC_SCER]
+skip_enable_ddrck:
+
        /*
         * at91rm9200 Memory controller
         * Do nothing - self-refresh is automatically disabled.
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to