[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