[coreboot-gerrit] New patch to review for coreboot: 49b5d42 google/snow: Support sleep/resume.

Hung-Te Lin (hungte@chromium.org) gerrit at coreboot.org
Tue Apr 16 14:04:08 CEST 2013


Hung-Te Lin (hungte at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3102

-gerrit

commit 49b5d420df391b3c10621fc83553c7012470d19f
Author: Hung-Te Lin <hungte at chromium.org>
Date:   Tue Apr 16 20:03:00 2013 +0800

    google/snow: Support sleep/resume.
    
    WIP. Do not submit.
    
    Change-Id: I65681c42eeef2736e55bb906595f42a5b1dfdf11
    Signed-off-by: Hung-Te Lin <hungte at chromium.org>
---
 src/cpu/samsung/exynos5250/dmc_init_ddr3.c   |  14 +++-
 src/cpu/samsung/exynos5250/lowlevel_init_c.c |   1 +
 src/cpu/samsung/exynos5250/setup.h           |   4 +-
 src/mainboard/google/snow/romstage.c         | 119 +++++++++++++++++++--------
 4 files changed, 99 insertions(+), 39 deletions(-)

diff --git a/src/cpu/samsung/exynos5250/dmc_init_ddr3.c b/src/cpu/samsung/exynos5250/dmc_init_ddr3.c
index 9a4ead0..e926cde 100644
--- a/src/cpu/samsung/exynos5250/dmc_init_ddr3.c
+++ b/src/cpu/samsung/exynos5250/dmc_init_ddr3.c
@@ -58,7 +58,8 @@ static void reset_phy_ctrl(void)
 	sdelay(425000);
 }
 
-int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size)
+int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size,
+		       int mem_reset)
 {
 	unsigned int val;
 	struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl;
@@ -68,9 +69,14 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size)
 	phy0_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY0_BASE;
 	phy1_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY1_BASE;
 	dmc = (struct exynos5_dmc *)EXYNOS5_DMC_CTRL_BASE;
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: reset phy: ");
-	reset_phy_ctrl();
-	printk(BIOS_SPEW, "done\n");
+
+	if (mem_reset) {
+		printk(BIOS_SPEW, "%s: reset phy: ", __func__);
+		reset_phy_ctrl();
+		printk(BIOS_SPEW, "done\n");
+	} else {
+		printk(BIOS_SPEW, "%s: skip mem_reset.\n", __func__);
+	}
 
 	/* Set Impedance Output Driver */
 	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Set Impedance Output Driver\n");
diff --git a/src/cpu/samsung/exynos5250/lowlevel_init_c.c b/src/cpu/samsung/exynos5250/lowlevel_init_c.c
index daa691f..e403353 100644
--- a/src/cpu/samsung/exynos5250/lowlevel_init_c.c
+++ b/src/cpu/samsung/exynos5250/lowlevel_init_c.c
@@ -73,6 +73,7 @@ enum {
 	DO_UART		= 1 << 1,
 	DO_CLOCKS	= 1 << 2,
 	DO_POWER	= 1 << 3,
+	DO_MEM_RESET    = 1 << 4,
 };
 
 int lowlevel_init_subsystems(void)
diff --git a/src/cpu/samsung/exynos5250/setup.h b/src/cpu/samsung/exynos5250/setup.h
index 4f7f58c..952c125 100644
--- a/src/cpu/samsung/exynos5250/setup.h
+++ b/src/cpu/samsung/exynos5250/setup.h
@@ -702,9 +702,11 @@ void mem_ctrl_init(void);
  *			which the DMC uses to decide how to split a memory
  *			chunk into smaller chunks to support concurrent
  *			accesses; may vary across boards.
+ * @param mem_reset	Reset memory when initialization.
  * @return 0 if ok, SETUP_ERR_... if there is a problem
  */
-int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size);
+int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size,
+		       int mem_reset);
 
 void tzpc_init(void);
 /*
diff --git a/src/mainboard/google/snow/romstage.c b/src/mainboard/google/snow/romstage.c
index dda4e7c..febe995 100644
--- a/src/mainboard/google/snow/romstage.c
+++ b/src/mainboard/google/snow/romstage.c
@@ -25,6 +25,8 @@
 
 #include <arch/cache.h>
 #include <arch/gpio.h>
+#include <arch/hlt.h>
+#include <cpu/samsung/exynos5-common/exynos5-common.h>
 #include <cpu/samsung/exynos5-common/i2c.h>
 #include <cpu/samsung/exynos5250/clk.h>
 #include <cpu/samsung/exynos5250/cpu.h>
@@ -46,9 +48,9 @@
 #define PMIC_BUS	0
 #define MMC0_GPIO_PIN	(58)
 
-#if 0
-static int board_wakeup_permitted(void)
+static int wakeup_permitted(void)
 {
+#if 0
 	const int gpio = GPIO_Y10;
 	int is_bad_wake;
 
@@ -56,8 +58,9 @@ static int board_wakeup_permitted(void)
 	is_bad_wake = ((gpio != -1) && gpio_get_value(gpio));
 
 	return !is_bad_wake;
-}
 #endif
+	return 1;
+}
 
 static int setup_pmic(void)
 {
@@ -145,53 +148,101 @@ static void chromeos_gpios(void)
 	s5p_gpio_set_pull(&gpio_pt2->x3, LID_OPEN, EXYNOS_GPIO_PULL_NONE);
 }
 
+/* Initialization steps */
+enum {
+	DO_WAKEUP	= 1 << 0,
+	DO_UART		= 1 << 1,
+	DO_CLOCKS	= 1 << 2,
+	DO_POWER	= 1 << 3,
+	DO_MEM_RESET    = 1 << 4,
+};
+
 void main(void)
 {
 	struct mem_timings *mem;
 	struct arm_clk_ratios *arm_ratios;
-	int ret;
+	int ret, actions;
 	void *entry;
+	uint32_t reset_status;
+
+	reset_status = power_read_reset_status();
+	switch (reset_status) {
+		case S5P_CHECK_SLEEP:
+			actions = DO_CLOCKS | DO_WAKEUP;
+			break;
+
+		case S5P_CHECK_DIDLE:
+		case S5P_CHECK_LPA:
+			actions = DO_WAKEUP;
+			break;
+
+		default:
+			/* Normal boot (not wake from sleep). */
+			actions = DO_UART | DO_CLOCKS | DO_POWER | DO_MEM_RESET;
+			break;
+	}
 
-	clock_set_rate(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */
-
-	/* Clock must be initialized before console_init, otherwise you may need
-	 * to re-initialize serial console drivers again. */
-	mem = get_mem_timings();
-	arm_ratios = get_arm_clk_ratios();
-	system_clock_init(mem, arm_ratios);
+	if (actions & DO_CLOCKS) {
+		/* Clock must be initialized before console_init, otherwise you
+		 * may need to re-initialize serial console drivers again. */
+		mem = get_mem_timings();
+		arm_ratios = get_arm_clk_ratios();
+		system_clock_init(mem, arm_ratios);
+	}
 
-	console_init();
+	if (actions & DO_UART) {
+		console_init();
+	}
 
-	i2c_init(0, CONFIG_SYS_I2C_SPEED, 0x00);
-	if (power_init())
-		power_shutdown();
-	printk(BIOS_DEBUG, "%s: setting up pmic...\n", __func__);
-	if (setup_pmic())
-		power_shutdown();
+	printk(BIOS_INFO, "%s: Booting from %s mode.\n", __func__,
+	       reset_status == S5P_CHECK_SLEEP ? "sleep" :
+	       reset_status == S5P_CHECK_DIDLE ? "D-idle" :
+	       reset_status == S5P_CHECK_LPA ? "LPA" :
+	       "normal");
+
+	if (actions & DO_POWER) {
+		if (power_init())
+			power_shutdown();
+		/* Initialize I2C to program PMIC. */
+		i2c_init(0, CONFIG_SYS_I2C_SPEED, 0x00);
+		printk(BIOS_DEBUG, "%s: setting up pmic...\n", __func__);
+		if (setup_pmic())
+			power_shutdown();
+	}
 
-	if (!mem) {
-		printk(BIOS_CRIT, "Unable to auto-detect memory timings\n");
-		while(1);
+	if (actions & DO_CLOCKS) {
+		if (!mem) {
+			printk(BIOS_CRIT,
+			       "%s: Unable to auto-detect memory timings\n",
+			       __func__);
+			hlt();
+		}
+		printk(BIOS_SPEW, "mem: %#x type: %#x, div: %#x, mhz: %#x\n",
+		       mem->mem_manuf, mem->mem_type, mem->mpll_mdiv,
+		       mem->frequency_mhz);
+		ret = ddr3_mem_ctrl_init(mem, DMC_INTERLEAVE_SIZE,
+					 actions & DO_MEM_RESET);
+		if (ret) {
+			printk(BIOS_CRIT,
+			       "%s: Memory controller init failed, err: %#x\n",
+			       __func__, ret);
+			hlt();
+		}
 	}
-	printk(BIOS_SPEW, "man: 0x%x type: 0x%x, div: 0x%x, mhz: 0x%x\n",
-		mem->mem_manuf,
-		mem->mem_type,
-		mem->mpll_mdiv,
-		mem->frequency_mhz);
-
-	ret = ddr3_mem_ctrl_init(mem, DMC_INTERLEAVE_SIZE);
-	if (ret) {
-		printk(BIOS_ERR, "Memory controller init failed, err: %x\n",
-		ret);
-		while(1);
+
+	if (actions & DO_WAKEUP) {
+		printk(BIOS_SPEW, "%s: Try to wake up.\n", __func__);
+		if (!wakeup_permitted())
+			power_reset();
+		power_exit_wakeup();
 	}
 
+	/* Initialize peripherals. */
 	initialize_s5p_mshc();
-
 	chromeos_gpios();
-
 	graphics();
 
+	clock_set_rate(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */
 	entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/coreboot_ram");
 	printk(BIOS_INFO, "entry is 0x%p, leaving romstage.\n", entry);
 



More information about the coreboot-gerrit mailing list