ARM: at91/pm_slowclock: add runtime detection of memory contoller
authorJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Wed, 22 Feb 2012 16:50:55 +0000 (17:50 +0100)
committerNicolas Ferre <nicolas.ferre@atmel.com>
Thu, 23 Feb 2012 13:57:56 +0000 (14:57 +0100)
This will allow to have all SoC in one kernel image.

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
arch/arm/mach-at91/include/mach/at91_ramc.h
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm_slowclock.S

index 3155499e2ea39ff0684bf4b82f4c402b3c6a4535..d8aeb278614ebba4d51cebea15db71b2f3187cb2 100644 (file)
@@ -21,11 +21,12 @@ extern void __iomem *at91_ramc_base[];
 .extern at91_ramc_base
 #endif
 
-#ifdef CONFIG_ARCH_AT91RM9200
-#include <mach/at91rm9200_mc.h>
-#else
+#define AT91_MEMCTRL_MC                0
+#define AT91_MEMCTRL_SDRAMC    1
+#define AT91_MEMCTRL_DDRSDR    2
+
+#include <mach/at91rm9200_sdramc.h>
 #include <mach/at91sam9_ddrsdr.h>
 #include <mach/at91sam9_sdramc.h>
-#endif
 
 #endif /* __AT91_RAMC_H__ */
index 46dbb7e1339c1f27a6bbf2f12c2dfd98e12e5c01..2793591c73c0d1a6a9da42a7e6a6ae25d5867e8b 100644 (file)
@@ -188,10 +188,12 @@ int at91_suspend_entering_slow_clock(void)
 EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
 
 
-static void (*slow_clock)(void __iomem *pmc, void __iomem *ramc0, void __iomem *ramc1);
+static void (*slow_clock)(void __iomem *pmc, void __iomem *ramc0,
+                         void __iomem *ramc1, int memctrl);
 
 #ifdef CONFIG_AT91_SLOW_CLOCK
-extern void at91_slow_clock(void __iomem *pmc, void __iomem *ramc0, void __iomem *ramc1);
+extern void at91_slow_clock(void __iomem *pmc, void __iomem *ramc0,
+                           void __iomem *ramc1, int memctrl);
 extern u32 at91_slow_clock_sz;
 #endif
 
@@ -241,11 +243,18 @@ static int at91_pm_enter(suspend_state_t state)
                         * turning off the main oscillator; reverse on wakeup.
                         */
                        if (slow_clock) {
+                               int memctrl = AT91_MEMCTRL_SDRAMC;
+
+                               if (cpu_is_at91rm9200())
+                                       memctrl = AT91_MEMCTRL_MC;
+                               else if (cpu_is_at91sam9g45())
+                                       memctrl = AT91_MEMCTRL_DDRSDR;
 #ifdef CONFIG_AT91_SLOW_CLOCK
                                /* copy slow_clock handler to SRAM, and call it */
                                memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz);
 #endif
-                               slow_clock(at91_pmc_base, at91_ramc_base[0], at91_ramc_base[1]);
+                               slow_clock(at91_pmc_base, at91_ramc_base[0],
+                                          at91_ramc_base[1], memctrl);
                                break;
                        } else {
                                pr_info("AT91: PM - no slow clock mode enabled ...\n");
index a2835a81bc846d4086005add6961c674987b0dbe..2c46010953c2ba500d78ec165385e889c571ade8 100644 (file)
@@ -42,8 +42,9 @@
 pmc    .req    r0
 sdramc .req    r1
 ramc1  .req    r2
-tmp1   .req    r3
-tmp2   .req    r4
+memctrl        .req    r3
+tmp1   .req    r4
+tmp2   .req    r5
 
 /*
  * Wait until master clock is ready (after switching master clock source)
@@ -103,29 +104,44 @@ tmp2      .req    r4
 
        .text
 
-/* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc, void __iomem *ramc1) */
+/* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc,
+ *                     void __iomem *ramc1, int memctrl)
+ */
 ENTRY(at91_slow_clock)
        /* Save registers on stack */
-       stmfd   sp!, {r3 - r12, lr}
+       stmfd   sp!, {r4 - r12, lr}
 
        /*
         * Register usage:
         *  R0 = Base address of AT91_PMC
         *  R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
         *  R2 = Base address of second RAM Controller or 0 if not present
-        *  R3 = temporary register
+        *  R3 = Memory controller
         *  R4 = temporary register
+        *  R5 = temporary register
         */
 
        /* Drain write buffer */
        mov     tmp1, #0
        mcr     p15, 0, tmp1, c7, c10, 4
 
-#ifdef CONFIG_ARCH_AT91RM9200
+       cmp     memctrl, #AT91_MEMCTRL_MC
+       bne     ddr_sr_enable
+
+       /*
+        * at91rm9200 Memory controller
+        */
        /* Put SDRAM in self-refresh mode */
        mov     tmp1, #1
        str     tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR]
-#elif defined(CONFIG_ARCH_AT91SAM9G45)
+       b       sdr_sr_done
+
+       /*
+        * DDRSDR Memory controller
+        */
+ddr_sr_enable:
+       cmp     memctrl, #AT91_MEMCTRL_DDRSDR
+       bne     sdr_sr_enable
 
        /* prepare for DDRAM self-refresh mode */
        ldr     tmp1, [sdramc, #AT91_DDRSDRC_LPR]
@@ -143,7 +159,13 @@ ENTRY(at91_slow_clock)
        /* Enable DDRAM self-refresh mode */
        str     tmp1, [sdramc, #AT91_DDRSDRC_LPR]
        strne   tmp2, [ramc1, #AT91_DDRSDRC_LPR]
-#else
+
+       b       sdr_sr_done
+
+       /*
+        * SDRAMC Memory controller
+        */
+sdr_sr_enable:
        /* Enable SDRAM self-refresh mode */
        ldr     tmp1, [sdramc, #AT91_SDRAMC_LPR]
        str     tmp1, .saved_sam9_lpr
@@ -151,8 +173,8 @@ ENTRY(at91_slow_clock)
        bic     tmp1, #AT91_SDRAMC_LPCB
        orr     tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH
        str     tmp1, [sdramc, #AT91_SDRAMC_LPR]
-#endif
 
+sdr_sr_done:
        /* Save Master clock setting */
        ldr     tmp1, [pmc, #(AT91_PMC_MCKR - AT91_PMC)]
        str     tmp1, .saved_mckr
@@ -255,9 +277,18 @@ ENTRY(at91_slow_clock)
 
        wait_mckrdy
 
-#ifdef CONFIG_ARCH_AT91RM9200
-       /* Do nothing - self-refresh is automatically disabled. */
-#elif defined(CONFIG_ARCH_AT91SAM9G45)
+       /*
+        * at91rm9200 Memory controller
+        * Do nothing - self-refresh is automatically disabled.
+        */
+       cmp     memctrl, #AT91_MEMCTRL_MC
+       beq     ram_restored
+
+       /*
+        * DDRSDR Memory controller
+        */
+       cmp     memctrl, #AT91_MEMCTRL_DDRSDR
+       bne     sdr_en_restore
        /* Restore LPR on AT91 with DDRAM */
        ldr     tmp1, .saved_sam9_lpr
        str     tmp1, [sdramc, #AT91_DDRSDRC_LPR]
@@ -267,14 +298,19 @@ ENTRY(at91_slow_clock)
        ldrne   tmp2, .saved_sam9_lpr1
        strne   tmp2, [ramc1, #AT91_DDRSDRC_LPR]
 
-#else
+       b       ram_restored
+
+       /*
+        * SDRAMC Memory controller
+        */
+sdr_en_restore:
        /* Restore LPR on AT91 with SDRAM */
        ldr     tmp1, .saved_sam9_lpr
        str     tmp1, [sdramc, #AT91_SDRAMC_LPR]
-#endif
 
+ram_restored:
        /* Restore registers, and return */
-       ldmfd   sp!, {r3 - r12, pc}
+       ldmfd   sp!, {r4 - r12, pc}
 
 
 .saved_mckr: