[U-Boot] [PATCH 1/4] Add deep sleep framework support for Freescale QorIQ platforms

Yuantian.Tang at freescale.com
2014-10-09T08:11:35Z

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

When Freescale QorIQ SoCs wake up from deep sleep, 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.

This patch adds the deep sleep framework support for all Freescale
QorIQ platforms that use generic_board configuation.

Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
---
common/board_f.c | 10 +++++++++
drivers/ddr/fsl/arm_ddr_gen3.c | 48 +++++++++++++++++++++++++++++++++++++-----
include/fsl_ddr_sdram.h | 2 ++
include/fsl_sleep.h | 32 ++++++++++++++++++++++++++++
4 files changed, 87 insertions(+), 5 deletions(-)
create mode 100644 include/fsl_sleep.h

diff --git a/common/board_f.c b/common/board_f.c
index e6aa298..b736d29 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -56,6 +56,9 @@
#endif
#include <dm/root.h>
#include <linux/compiler.h>
+#ifdef CONFIG_FSL_DEEP_SLEEP
+#include <fsl_sleep.h>
+#endif

/*
* Pointer to initial global data area
@@ -921,6 +924,9 @@ static init_fnc_t init_sequence_f[] = {
#if defined(CONFIG_MIPS) || defined(CONFIG_PPC)
init_func_ram,
#endif
+#ifdef CONFIG_FSL_DEEP_SLEEP
+ fsl_dp_resume,
+#endif
#ifdef CONFIG_POST
post_init_f,
#endif
@@ -1027,6 +1033,10 @@ void board_init_f(ulong boot_flags)
gd->flags = boot_flags;
gd->have_console = 0;

+#ifdef CONFIG_FSL_DEEP_SLEEP
+ if (is_warm_boot())
+ gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE;
+#endif
if (initcall_run_list(init_sequence_f))
hang();

diff --git a/drivers/ddr/fsl/arm_ddr_gen3.c b/drivers/ddr/fsl/arm_ddr_gen3.c
index 59f2fd6..1a9d82b 100644
--- a/drivers/ddr/fsl/arm_ddr_gen3.c
+++ b/drivers/ddr/fsl/arm_ddr_gen3.c
@@ -12,6 +12,9 @@
#include <asm/processor.h>
#include <fsl_immap.h>
#include <fsl_ddr.h>
+#ifdef CONFIG_FSL_DEEP_SLEEP
+#include <fsl_sleep.h>
+#endif

#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
@@ -92,7 +95,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_out32(&ddr->timing_cfg_0, regs->timing_cfg_0);
ddr_out32(&ddr->timing_cfg_1, regs->timing_cfg_1);
ddr_out32(&ddr->timing_cfg_2, regs->timing_cfg_2);
- ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
ddr_out32(&ddr->sdram_mode, regs->ddr_sdram_mode);
ddr_out32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
ddr_out32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3);
@@ -105,8 +107,25 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_out32(&ddr->sdram_interval, regs->ddr_sdram_interval);
ddr_out32(&ddr->sdram_data_init, regs->ddr_data_init);
ddr_out32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
- ddr_out32(&ddr->init_addr, regs->ddr_init_addr);
- ddr_out32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+#ifdef CONFIG_FSL_DEEP_SLEEP
+ if (is_warm_boot()) {
+ ddr_out32(&ddr->sdram_cfg_2,
+ regs->ddr_sdram_cfg_2 & ~SDRAM_CFG2_D_INIT);
+ ddr_out32(&ddr->init_addr, CONFIG_SYS_SDRAM_BASE);
+ ddr_out32(&ddr->init_ext_addr, (1 << 31));
+
+ /* DRAM VRef will not be trained */
+ temp_sdram_cfg = ddr_in32(&ddr->ddr_cdr2);
+ temp_sdram_cfg &= ~DDR_CDR2_VREF_TRAIN_EN;
+ ddr_out32(&ddr->ddr_cdr2, temp_sdram_cfg);
+ } else
+#endif
+ {
+ ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+ ddr_out32(&ddr->init_addr, regs->ddr_init_addr);
+ ddr_out32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+ ddr_out32(&ddr->ddr_cdr2, regs->ddr_cdr2);
+ }

ddr_out32(&ddr->timing_cfg_4, regs->timing_cfg_4);
ddr_out32(&ddr->timing_cfg_5, regs->timing_cfg_5);
@@ -128,7 +147,6 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
ddr_out32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1);
ddr_out32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2);
ddr_out32(&ddr->ddr_cdr1, regs->ddr_cdr1);
- ddr_out32(&ddr->ddr_cdr2, regs->ddr_cdr2);
ddr_out32(&ddr->err_disable, regs->err_disable);
ddr_out32(&ddr->err_int_en, regs->err_int_en);
for (i = 0; i < 32; i++) {
@@ -167,8 +185,20 @@ step2:
udelay(500);
asm volatile("dsb sy;isb");

+#ifdef CONFIG_FSL_DEEP_SLEEP
+ if (is_warm_boot()) {
+ /* enter self-refresh */
+ temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg_2);
+ temp_sdram_cfg |= SDRAM_CFG2_FRC_SR;
+ ddr_out32(&ddr->sdram_cfg_2, temp_sdram_cfg);
+ /* do board specific memory setup */
+ fsl_dp_mem_setup();
+
+ temp_sdram_cfg = (ddr_in32(&ddr->sdram_cfg) | SDRAM_CFG_BI);
+ } else
+#endif
+ temp_sdram_cfg = (in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI);
/* Let the controller go */
- temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
ddr_out32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
asm volatile("dsb sy;isb");

@@ -211,4 +241,12 @@ step2:

if (timeout <= 0)
printf("Waiting for D_INIT timeout. Memory may not work.\n");
+#ifdef CONFIG_FSL_DEEP_SLEEP
+ if (is_warm_boot()) {
+ /* exit self-refresh */
+ temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg_2);
+ temp_sdram_cfg &= ~SDRAM_CFG2_FRC_SR;
+ ddr_out32(&ddr->sdram_cfg_2, temp_sdram_cfg);
+ }
+#endif
}
diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h
index 5b03c14..b69b1dc 100644
--- a/include/fsl_ddr_sdram.h
+++ b/include/fsl_ddr_sdram.h
@@ -114,6 +114,7 @@ typedef struct ddr4_spd_eeprom_s generic_spd_eeprom_t;
#define SDRAM_CFG_2T_EN 0x00008000
#define SDRAM_CFG_BI 0x00000001

+#define SDRAM_CFG2_FRC_SR 0x80000000
#define SDRAM_CFG2_D_INIT 0x00000010
#define SDRAM_CFG2_ODT_CFG_MASK 0x00600000
#define SDRAM_CFG2_ODT_NEVER 0
@@ -163,6 +164,7 @@ typedef struct ddr4_spd_eeprom_s generic_spd_eeprom_t;
#define DDR_CDR1_ODT(x) ((x & DDR_CDR1_ODT_MASK) << DDR_CDR1_ODT_SHIFT)
#define DDR_CDR2_ODT(x) (x & DDR_CDR2_ODT_MASK)
#define DDR_CDR2_VREF_OVRD(x) (0x00008080 | ((((x) - 37) & 0x3F) << 8))
+#define DDR_CDR2_VREF_TRAIN_EN 0x00000080

#if (defined(CONFIG_SYS_FSL_DDR_VER) && \
(CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7))
diff --git a/include/fsl_sleep.h b/include/fsl_sleep.h
new file mode 100644
index 0000000..429e302
--- /dev/null
+++ b/include/fsl_sleep.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __DEEP_SLEEP_H
+#define __DEEP_SLEEP_H
+
+/*
+ * Functions prototype for sleep.
+ * Each platform that supports deep sleep needs to
+ * implement them on their own.
+ */
+
+/* determine if it is a wakeup from deep sleep */
+bool is_warm_boot(void);
+
+/* board specific memory setup, like CKE isolation */
+void fsl_dp_mem_setup(void);
+
+/* clean up everything and jump to kernel */
+int fsl_dp_resume(void);
+
+/*
+ * When wakeup from deep sleep, the first 128 bytes space
+ * will be used to do DDR training which corrupts the data
+ * in there. This function will restore them.
+ */
+void fsl_dp_ddr_restore(void);
+
+#endif
--
2.1.0.27.g96db324