Hung-Te Lin (hungte@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@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@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);