From: Tang Yuantian <yuantian.t...@freescale.com>

When system wakes up from warm reset, control is passed to the
primary core that starts executing uboot. After re-initialized some
IP blocks, like DDRC, kernel will take responsibility to continue
to restore environment it leaves before.

Signed-off-by: Tang Yuantian <yuantian.t...@freescale.com>
---
 arch/powerpc/cpu/mpc85xx/cpu_init.c    |  7 ++++
 arch/powerpc/cpu/mpc85xx/fdt.c         | 27 +++++++++++++++
 arch/powerpc/cpu/mpc85xx/liodn.c       | 24 +++++++++----
 arch/powerpc/cpu/mpc85xx/start.S       |  8 +++++
 arch/powerpc/include/asm/global_data.h |  1 +
 arch/powerpc/lib/board.c               | 61 +++++++++++++++++++++++++++++++---
 drivers/ddr/fsl/mpc85xx_ddr_gen3.c     | 44 +++++++++++++++++++++---
 include/fsl_ddr_sdram.h                |  6 ++++
 8 files changed, 163 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c 
b/arch/powerpc/cpu/mpc85xx/cpu_init.c
index b31efb7..376c659 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -231,6 +231,7 @@ void cpu_init_f (void)
 #ifdef CONFIG_MPC8548
        ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR);
        uint svr = get_svr();
+       gd = (gd_t *)(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
 
        /*
         * CPU2 errata workaround: A core hang possible while executing
@@ -282,6 +283,12 @@ void cpu_init_f (void)
        in_be32(&gur->dcsrcr);
 #endif
 
+#ifdef CONFIG_DEEP_SLEEP
+       /* disable the console if boot from warm reset */
+       if (in_be32(&gur->scrtsr[0]) & (1 << 3))
+               gd->flags |=
+                       GD_FLG_SILENT | GD_FLG_WARM_BOOT | 
GD_FLG_DISABLE_CONSOLE;
+#endif
 }
 
 /* Implement a dummy function for those platforms w/o SERDES */
diff --git a/arch/powerpc/cpu/mpc85xx/fdt.c b/arch/powerpc/cpu/mpc85xx/fdt.c
index 33bc900..b3b9250 100644
--- a/arch/powerpc/cpu/mpc85xx/fdt.c
+++ b/arch/powerpc/cpu/mpc85xx/fdt.c
@@ -24,6 +24,9 @@ DECLARE_GLOBAL_DATA_PTR;
 extern void ft_qe_setup(void *blob);
 extern void ft_fixup_num_cores(void *blob);
 extern void ft_srio_setup(void *blob);
+#ifdef CONFIG_DEEP_SLEEP
+extern ulong __bss_end;
+#endif
 
 #ifdef CONFIG_MP
 #include "mp.h"
@@ -35,6 +38,9 @@ void ft_fixup_cpu(void *blob, u64 memory_limit)
        u32 bootpg = determine_mp_bootpg(NULL);
        u32 id = get_my_id();
        const char *enable_method;
+#ifdef CONFIG_DEEP_SLEEP
+       ulong len;
+#endif
 
        off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
        while (off != -FDT_ERR_NOTFOUND) {
@@ -77,6 +83,25 @@ void ft_fixup_cpu(void *blob, u64 memory_limit)
                                "device_type", "cpu", 4);
        }
 
+#ifdef CONFIG_DEEP_SLEEP
+       /*
+        * reserve the memory space for warm reset.
+        * This space will be re-used next time when boot from deep sleep.
+        * The space includes bd_t, gd_t, stack and uboot image.
+        * Reserve 1K for stack.
+        */
+       len = sizeof(bd_t) + sizeof(gd_t) + (1 << 10);
+       /* round up to 4K */
+       len = (len + (4096 - 1)) & ~(4096 - 1);
+
+       off = fdt_add_mem_rsv(blob, gd->relocaddr - len,
+                       len + ((ulong)&__bss_end - gd->relocaddr));
+       if (off < 0)
+               printf("Failed to reserve memory for warm reset: %s\n",
+                       fdt_strerror(off));
+
+#endif
+
        /* Reserve the boot page so OSes dont use it */
        if ((u64)bootpg < memory_limit) {
                off = fdt_add_mem_rsv(blob, bootpg, (u64)4096);
@@ -100,6 +125,7 @@ void ft_fixup_cpu(void *blob, u64 memory_limit)
        }
 #endif
 
+#ifndef CONFIG_DEEP_SLEEP
        /* Reserve spin table page */
        if (spin_tbl_addr < memory_limit) {
                off = fdt_add_mem_rsv(blob,
@@ -108,6 +134,7 @@ void ft_fixup_cpu(void *blob, u64 memory_limit)
                        printf("Failed to reserve memory for spin table: %s\n",
                                fdt_strerror(off));
        }
+#endif
 }
 #endif
 
diff --git a/arch/powerpc/cpu/mpc85xx/liodn.c b/arch/powerpc/cpu/mpc85xx/liodn.c
index 19e130e..898685b 100644
--- a/arch/powerpc/cpu/mpc85xx/liodn.c
+++ b/arch/powerpc/cpu/mpc85xx/liodn.c
@@ -14,6 +14,10 @@
 #include <asm/fsl_portals.h>
 #include <asm/fsl_liodn.h>
 
+#ifdef CONFIG_DEEP_SLEEP
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
 int get_dpaa_liodn(enum fsl_dpaa_dev dpaa_dev, u32 *liodns, int liodn_offset)
 {
        liodns[0] = liodn_bases[dpaa_dev].id[0] + liodn_offset;
@@ -180,14 +184,22 @@ void set_liodns(void)
 
        /* setup FMAN block(s) liodn bases & offsets if we have one */
 #ifdef CONFIG_SYS_DPAA_FMAN
-       set_liodn(fman1_liodn_tbl, fman1_liodn_tbl_sz);
-       setup_fman_liodn_base(FSL_HW_PORTAL_FMAN1, fman1_liodn_tbl,
-                               fman1_liodn_tbl_sz);
+#ifdef CONFIG_DEEP_SLEEP
+       if ((gd->flags & GD_FLG_WARM_BOOT) == 0) {
+               set_liodn(fman1_liodn_tbl, fman1_liodn_tbl_sz);
+               setup_fman_liodn_base(FSL_HW_PORTAL_FMAN1, fman1_liodn_tbl,
+                                       fman1_liodn_tbl_sz);
+       }
+#endif
 
 #if (CONFIG_SYS_NUM_FMAN == 2)
-       set_liodn(fman2_liodn_tbl, fman2_liodn_tbl_sz);
-       setup_fman_liodn_base(FSL_HW_PORTAL_FMAN2, fman2_liodn_tbl,
-                               fman2_liodn_tbl_sz);
+#ifdef CONFIG_DEEP_SLEEP
+       if ((gd->flags & GD_FLG_WARM_BOOT) == 0) {
+               set_liodn(fman2_liodn_tbl, fman2_liodn_tbl_sz);
+               setup_fman_liodn_base(FSL_HW_PORTAL_FMAN2, fman2_liodn_tbl,
+                                       fman2_liodn_tbl_sz);
+       }
+#endif
 #endif
 #endif
        /* setup PME liodn base */
diff --git a/arch/powerpc/cpu/mpc85xx/start.S b/arch/powerpc/cpu/mpc85xx/start.S
index db84d10..4e66edc 100644
--- a/arch/powerpc/cpu/mpc85xx/start.S
+++ b/arch/powerpc/cpu/mpc85xx/start.S
@@ -1671,6 +1671,14 @@ relocate_code:
         * Now relocate code
         */
 
+#ifdef CONFIG_DEEP_SLEEP
+       /* don't copy uboot again in warm reset case */
+       mr r0, r3
+       bl check_warmboot
+       cmpwi r3, 0
+       bne 7f
+       mr r3, r0
+#endif
        cmplw   cr1,r3,r4
        addi    r0,r5,3
        srwi.   r0,r0,2
diff --git a/arch/powerpc/include/asm/global_data.h 
b/arch/powerpc/include/asm/global_data.h
index 8e59e8b..1ab05ff 100644
--- a/arch/powerpc/include/asm/global_data.h
+++ b/arch/powerpc/include/asm/global_data.h
@@ -117,6 +117,7 @@ struct arch_global_data {
 #include <asm-generic/global_data.h>
 
 #if 1
+#define GD_FLG_WARM_BOOT       0x10000
 #define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r2")
 #else /* We could use plain global data, but the resulting code is bigger */
 #define XTRN_DECLARE_GLOBAL_DATA_PTR   extern
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index 34bbfca..7383e32 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -350,6 +350,13 @@ unsigned long logbuffer_base(void)
 }
 #endif
 
+#ifdef CONFIG_DEEP_SLEEP
+int check_warmboot(void)
+{
+       return !!(gd->flags & GD_FLG_WARM_BOOT);
+}
+#endif
+
 void board_init_f(ulong bootflag)
 {
        bd_t *bd;
@@ -475,12 +482,18 @@ void board_init_f(ulong bootflag)
 
        debug("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
 
+#ifdef CONFIG_DEEP_SLEEP
        /*
         * reserve memory for malloc() arena
+        * don't reserve it in warm reset case
         */
-       addr_sp = addr - TOTAL_MALLOC_LEN;
-       debug("Reserving %dk for malloc() at: %08lx\n",
-             TOTAL_MALLOC_LEN >> 10, addr_sp);
+       if ((gd->flags & GD_FLG_WARM_BOOT) == 0) {
+               addr_sp = addr - TOTAL_MALLOC_LEN;
+               debug("Reserving %dk for malloc() at: %08lx\n",
+                       TOTAL_MALLOC_LEN >> 10, addr_sp);
+       } else
+               addr_sp = addr;
+#endif
 
        /*
         * (permanently) allocate a Board Info struct
@@ -591,6 +604,14 @@ void board_init_r(gd_t *id, ulong dest_addr)
 {
        bd_t *bd;
        ulong malloc_start;
+#ifdef CONFIG_DEEP_SLEEP
+       u32 start;
+       int i;
+       struct ccsr_scfg *scfg = (void *)CONFIG_SYS_MPC85xx_SCFG;
+       u64 *src, *dst;
+       typedef void (*func_t)(void);
+       func_t kernel_resume;
+#endif
 
 #ifndef CONFIG_SYS_NO_FLASH
        ulong flash_size;
@@ -601,6 +622,21 @@ void board_init_r(gd_t *id, ulong dest_addr)
 
        gd->flags |= GD_FLG_RELOC;      /* tell others: relocation done */
 
+#ifdef CONFIG_DEEP_SLEEP
+       /*
+        * restore 128-byte memory space which corrupted
+        * by DDRC training.
+        */
+       if (gd->flags & GD_FLG_WARM_BOOT) {
+               src = (u64 *)in_be32(&scfg->sparecr[2]);
+               dst = (u64 *)(0);
+               for (i = 0; i < 128/sizeof(u64); i++) {
+                       *dst = *src;
+                       dst++;
+                       src++;
+               }
+       }
+#endif
        /* The Malloc area is immediately below the monitor copy in DRAM */
        malloc_start = dest_addr - TOTAL_MALLOC_LEN;
 
@@ -639,7 +675,10 @@ void board_init_r(gd_t *id, ulong dest_addr)
        /*
         * Setup trap handlers
         */
-       trap_init(dest_addr);
+#ifdef CONFIG_DEEP_SLEEP
+       if ((gd->flags & GD_FLG_WARM_BOOT) == 0)
+               trap_init(dest_addr);
+#endif
 
 #ifdef CONFIG_ADDR_MAP
        init_addr_map();
@@ -686,7 +725,10 @@ void board_init_r(gd_t *id, ulong dest_addr)
 
        asm("sync ; isync");
 
-       mem_malloc_init(malloc_start, TOTAL_MALLOC_LEN);
+#ifdef CONFIG_DEEP_SLEEP
+       if ((gd->flags & GD_FLG_WARM_BOOT) == 0)
+               mem_malloc_init(malloc_start, TOTAL_MALLOC_LEN);
+#endif
 
 #if !defined(CONFIG_SYS_NO_FLASH)
        puts("Flash: ");
@@ -743,6 +785,15 @@ void board_init_r(gd_t *id, ulong dest_addr)
        /* initialize higher level parts of CPU like time base and timers */
        cpu_init_r();
 
+#ifdef CONFIG_DEEP_SLEEP
+       /* Jump to kernel in warm reset case */
+       if (gd->flags & GD_FLG_WARM_BOOT) {
+               start = in_be32(&scfg->sparecr[1]);
+               kernel_resume = (func_t)start;
+               kernel_resume();
+       }
+#endif
+
        WATCHDOG_RESET();
 
 #ifdef CONFIG_SPI
diff --git a/drivers/ddr/fsl/mpc85xx_ddr_gen3.c 
b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
index c805086..3d4f11a 100644
--- a/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
+++ b/drivers/ddr/fsl/mpc85xx_ddr_gen3.c
@@ -15,6 +15,9 @@
 #error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
 #endif
 
+#ifdef CONFIG_DEEP_SLEEP
+DECLARE_GLOBAL_DATA_PTR;
+#endif
 
 /*
  * regs has the to-be-set values for DDR controller registers
@@ -119,7 +122,13 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t 
*regs,
        out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0);
        out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
        out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
-       out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+#ifdef CONFIG_DEEP_SLEEP
+       if (gd->flags & GD_FLG_WARM_BOOT)
+               out_be32(&ddr->sdram_cfg_2,
+                       regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
+       else
+#endif
+               out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
        out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
        out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
        out_be32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3);
@@ -132,8 +141,16 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t 
*regs,
        out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
        out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
        out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
-       out_be32(&ddr->init_addr, regs->ddr_init_addr);
-       out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+#ifdef CONFIG_DEEP_SLEEP
+       if (gd->flags & GD_FLG_WARM_BOOT) {
+               out_be32(&ddr->init_addr, 0);
+               out_be32(&ddr->init_ext_addr, (1 << 31));
+       } else
+#endif
+       {
+               out_be32(&ddr->init_addr, regs->ddr_init_addr);
+               out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+       }
 
        out_be32(&ddr->timing_cfg_4, regs->timing_cfg_4);
        out_be32(&ddr->timing_cfg_5, regs->timing_cfg_5);
@@ -374,8 +391,22 @@ step2:
        udelay(500);
        asm volatile("sync;isync");
 
+#ifdef CONFIG_DEEP_SLEEP
+       if (gd->flags & GD_FLG_WARM_BOOT) {
+               /* enter self-refresh */
+               setbits_be32(&ddr->sdram_cfg_2, (1 << 31));
+               /* do board specific memory setup */
+               board_mem_sleep_setup();
+       }
+#endif
+
        /* Let the controller go */
-       temp_sdram_cfg = in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
+#ifdef CONFIG_DEEP_SLEEP
+       if (gd->flags & GD_FLG_WARM_BOOT)
+               temp_sdram_cfg = (in_be32(&ddr->sdram_cfg) | SDRAM_CFG_BI);
+       else
+#endif
+               temp_sdram_cfg = (in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI);
        out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
        asm volatile("sync;isync");
 
@@ -526,4 +557,9 @@ step2:
                clrbits_be32(&ddr->sdram_cfg, 0x2);
        }
 #endif /* CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 */
+#ifdef CONFIG_DEEP_SLEEP
+       if (gd->flags & GD_FLG_WARM_BOOT)
+               /* exit self-refresh */
+               clrbits_be32(&ddr->sdram_cfg_2, (1 << 31));
+#endif
 }
diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h
index 16cccc7..d8ab779 100644
--- a/include/fsl_ddr_sdram.h
+++ b/include/fsl_ddr_sdram.h
@@ -356,6 +356,12 @@ static int __board_need_mem_reset(void)
 int board_need_mem_reset(void)
        __attribute__((weak, alias("__board_need_mem_reset")));
 
+static void __board_mem_sleep_setup(void)
+{
+}
+void board_mem_sleep_setup(void)
+       __attribute__((weak, alias("__board_mem_sleep_setup")));
+
 /*
  * The 85xx boards have a common prototype for fixed_sdram so put the
  * declaration here.
-- 
1.8.0


_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to