[coreboot-gerrit] Patch set updated for coreboot: f8404bd google/snow: Support sleep/resume.

David Hendricks (dhendrix@chromium.org) gerrit at coreboot.org
Sun Apr 21 04:02:00 CEST 2013


David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3102

-gerrit

commit f8404bdc9685685f63fdc065b94585248a96e2dc
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>
    Signed-off-by: David Hendricks <dhendrix at chromium.org>
---
 src/cpu/samsung/exynos5250/Makefile.inc    |  2 +-
 src/cpu/samsung/exynos5250/dmc_init_ddr3.c | 14 +++--
 src/cpu/samsung/exynos5250/power.c         |  7 +--
 src/cpu/samsung/exynos5250/setup.h         |  4 +-
 src/mainboard/google/snow/Makefile.inc     |  3 +
 src/mainboard/google/snow/bootblock.c      | 12 ++++
 src/mainboard/google/snow/mainboard.h      |  2 +
 src/mainboard/google/snow/romstage.c       | 97 ++++++++++++++++--------------
 src/mainboard/google/snow/wakeup.c         | 28 +++++++++
 9 files changed, 113 insertions(+), 56 deletions(-)

diff --git a/src/cpu/samsung/exynos5250/Makefile.inc b/src/cpu/samsung/exynos5250/Makefile.inc
index 8788a6c..25d1bc5 100644
--- a/src/cpu/samsung/exynos5250/Makefile.inc
+++ b/src/cpu/samsung/exynos5250/Makefile.inc
@@ -3,7 +3,7 @@
 # image outside of CBFS
 #INTERMEDIATE += exynos5250_add_bl1
 
-bootblock-y += pinmux.c mct.c
+bootblock-y += pinmux.c mct.c power.c
 # Clock is required for UART
 bootblock-$(CONFIG_EARLY_CONSOLE) += clock_init.c
 bootblock-$(CONFIG_EARLY_CONSOLE) += clock.c
diff --git a/src/cpu/samsung/exynos5250/dmc_init_ddr3.c b/src/cpu/samsung/exynos5250/dmc_init_ddr3.c
index 5bb8a37..132471d 100644
--- a/src/cpu/samsung/exynos5250/dmc_init_ddr3.c
+++ b/src/cpu/samsung/exynos5250/dmc_init_ddr3.c
@@ -61,7 +61,8 @@ static void reset_phy_ctrl(void)
 	udelay(500);
 }
 
-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;
@@ -71,9 +72,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/power.c b/src/cpu/samsung/exynos5250/power.c
index 8aba0e8..6ed6af7 100644
--- a/src/cpu/samsung/exynos5250/power.c
+++ b/src/cpu/samsung/exynos5250/power.c
@@ -25,7 +25,7 @@
 #include <common.h>
 #include <arch/hlt.h>
 #include <arch/io.h>
-#include <arch/hlt.h>
+#include <arch/stages.h>
 #include <console/console.h>
 #include <cpu/samsung/exynos5-common/power.h>
 #include <cpu/samsung/exynos5250/cpu.h>
@@ -122,9 +122,8 @@ void power_exit_wakeup(void)
 {
 	struct exynos5_power *power =
 		samsung_get_base_power();
-	typedef void (*resume_func)(void);
-
-	((resume_func)power->inform0)();
+	ps_hold_setup();
+	stage_exit((void *)power->inform0);
 }
 
 int power_init(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/Makefile.inc b/src/mainboard/google/snow/Makefile.inc
index 46e366f..84a8c05 100644
--- a/src/mainboard/google/snow/Makefile.inc
+++ b/src/mainboard/google/snow/Makefile.inc
@@ -17,9 +17,12 @@
 ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 ##
 
+bootblock-y += wakeup.c
+
 romstage-y += mainboard.c
 romstage-y += memory.c
 romstage-y += romstage.c
+romstage-y += wakeup.c
 
 # ramstage-y += ec.c
 ramstage-y += ramstage.c
diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/snow/bootblock.c
index d2e0b50..cd617e4 100644
--- a/src/mainboard/google/snow/bootblock.c
+++ b/src/mainboard/google/snow/bootblock.c
@@ -23,17 +23,29 @@
 #include <uart.h>
 #include <time.h>
 #include <console/console.h>
+#include <cpu/samsung/exynos5-common/exynos5-common.h>
 #include <cpu/samsung/exynos5250/periph.h>
 #include <cpu/samsung/exynos5250/pinmux.h>
+#include <cpu/samsung/exynos5250/power.h>
+#include "mainboard.h"
 
 void bootblock_mainboard_init(void);
 void bootblock_mainboard_init(void)
 {
+	int reset_status;
+
 	/* kick off the microsecond timer. We want to do this as early
 	 * as we can.
 	 */
 	timer_start();
 
+	reset_status = power_read_reset_status();
+	if (reset_status == S5P_CHECK_DIDLE ||
+	    reset_status == S5P_CHECK_LPA) {
+		if (wakeup_permitted())
+			power_exit_wakeup();
+	}
+
 	exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE);
 #if CONFIG_EARLY_CONSOLE
 	exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
diff --git a/src/mainboard/google/snow/mainboard.h b/src/mainboard/google/snow/mainboard.h
index 6fe371f..17777ad 100644
--- a/src/mainboard/google/snow/mainboard.h
+++ b/src/mainboard/google/snow/mainboard.h
@@ -35,4 +35,6 @@ enum snow_board_config {
 
 int board_get_config(void);
 
+int wakeup_permitted(void);
+
 #endif	/* MAINBOARD_H */
diff --git a/src/mainboard/google/snow/romstage.c b/src/mainboard/google/snow/romstage.c
index 41b88e1..f221055 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,19 +48,6 @@
 #define PMIC_BUS	0
 #define MMC0_GPIO_PIN	(58)
 
-#if 0
-static int board_wakeup_permitted(void)
-{
-	const int gpio = GPIO_Y10;
-	int is_bad_wake;
-
-	/* We're a bad wakeup if the gpio was defined and was high */
-	is_bad_wake = ((gpio != -1) && gpio_get_value(gpio));
-
-	return !is_bad_wake;
-}
-#endif
-
 static int setup_pmic(void)
 {
 	int error = 0;
@@ -100,7 +89,22 @@ static int setup_pmic(void)
 	return error;
 }
 
-static void initialize_s5p_mshc(void)
+static int setup_memory(struct mem_timings *mem, int reset)
+{
+	int ret;
+	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, reset);
+	if (ret) {
+		printk(BIOS_CRIT,
+		       "%s: Memory controller init failed, err: %#x\n",
+		       __func__, ret);
+	}
+	return ret;
+}
+
+static void setup_mmc(void)
 {
 	/* MMC0: Fixed, 8 bit mode, connected with GPIO. */
 	if (clock_set_mshci(PERIPH_ID_SDMMC0))
@@ -117,12 +121,12 @@ static void initialize_s5p_mshc(void)
 	exynos_pinmux_config(PERIPH_ID_SDMMC2, 0);
 }
 
-static void graphics(void)
+static void setup_graphics(void)
 {
 	exynos_pinmux_config(PERIPH_ID_DPHPD, 0);
 }
 
-static void chromeos_gpios(void)
+static void setup_chromeos_gpios(void)
 {
 	struct exynos5_gpio_part1 *gpio_pt1;
 	struct exynos5_gpio_part2 *gpio_pt2;
@@ -154,49 +158,50 @@ void main(void)
 {
 	struct mem_timings *mem;
 	struct arm_clk_ratios *arm_ratios;
-	int ret;
+	int is_resume = 0;
 	void *entry;
+	uint32_t reset_status;
 
-	clock_set_rate(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */
+	reset_status = power_read_reset_status();
+	/* S5P_CHECK_DIDLE / S5P_CHECK_LPA are already handled in bootblock. */
+	if (reset_status == S5P_CHECK_SLEEP)
+		is_resume = 1;
 
-	/* Clock must be initialized before console_init, otherwise you may need
-	 * to re-initialize serial console drivers again. */
+	/* Clock must be initialized before console_init, otherwise you
+	 * may need to re-initialize serial console drivers again. */
 	mem = get_mem_timings();
+	if (!mem)
+		die("Unable to auto-detect memory timings");
 	arm_ratios = get_arm_clk_ratios();
 	system_clock_init(mem, arm_ratios);
-
 	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();
-
-	if (!mem) {
-		printk(BIOS_CRIT, "Unable to auto-detect memory timings\n");
-		while(1);
+	power_init();
+	if (!is_resume) {
+		/* Initialize I2C to program PMIC. */
+		i2c_init(0, CONFIG_SYS_I2C_SPEED, 0x00);
+		printk(BIOS_SPEW, "%s: Set up PMIC.\n", __func__);
+		if (setup_pmic())
+			power_shutdown();
 	}
-	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);
-	}
-
-	initialize_s5p_mshc();
+	if (setup_memory(mem, !is_resume))
+		power_shutdown();
 
-	chromeos_gpios();
+	if (is_resume) {
+		printk(BIOS_SPEW, "%s: Trying to wake up.\n", __func__);
+		if (!wakeup_permitted())
+			power_reset();
+		power_exit_wakeup();
+		/* Never returns. */
+	}
 
-	graphics();
+	/* Initialize peripherals. */
+	setup_mmc();
+	setup_chromeos_gpios();
+	setup_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);
 
diff --git a/src/mainboard/google/snow/wakeup.c b/src/mainboard/google/snow/wakeup.c
new file mode 100644
index 0000000..d5f7a25
--- /dev/null
+++ b/src/mainboard/google/snow/wakeup.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 The Chromium OS Authors.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/gpio.h>
+#include <cpu/samsung/exynos5250/gpio.h>
+
+#include "mainboard.h"
+
+int wakeup_permitted(void)
+{
+	/* We're a bad wakeup if the gpio is high */
+	return gpio_get_value(GPIO_Y10);
+}
+



More information about the coreboot-gerrit mailing list