summaryrefslogtreecommitdiff
path: root/src/mainboard/google/daisy
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2014-01-22 21:06:32 -0800
committerIsaac Christensen <isaac.christensen@se-eng.com>2014-09-25 19:09:47 +0200
commit49c98dc42b706897e802af12d16349ff65a9bd43 (patch)
tree3538c9fd152f5acf9ffa200b17e50a444a505475 /src/mainboard/google/daisy
parent765705789213e1914cad540bb7868d2154cdbedf (diff)
snow: Rename snow to daisy.
The name snow goes by in many places in chromeos is daisy. Snow is technically a variant of daisy and should really be called daisy_snow, but for historical reasons the daisy board with no variant was used instead. To make it easier to work with within chromeos, this change renames the snow board to daisy. Change-Id: I569b31bf417db55be91832f15271bea4bc30f163 Signed-off-by: Gabe Black <gabeblack@google.com> Reviewed-on: https://chromium-review.googlesource.com/183553 Reviewed-by: David Hendricks <dhendrix@chromium.org> Commit-Queue: Gabe Black <gabeblack@chromium.org> Tested-by: Gabe Black <gabeblack@chromium.org> (cherry picked from commit 13f24d967251c18dce2a00bcea915f448c4c6aa7) Signed-off-by: Isaac Christensen <isaac.christensen@se-eng.com> Reviewed-on: http://review.coreboot.org/6929 Tested-by: build bot (Jenkins)
Diffstat (limited to 'src/mainboard/google/daisy')
-rw-r--r--src/mainboard/google/daisy/Kconfig58
-rw-r--r--src/mainboard/google/daisy/Makefile.inc28
-rw-r--r--src/mainboard/google/daisy/chromeos.c101
-rw-r--r--src/mainboard/google/daisy/devicetree.cb33
-rw-r--r--src/mainboard/google/daisy/exynos5250.h32
-rw-r--r--src/mainboard/google/daisy/mainboard.c364
-rw-r--r--src/mainboard/google/daisy/memory.c545
-rw-r--r--src/mainboard/google/daisy/romstage.c178
-rw-r--r--src/mainboard/google/daisy/wakeup.c28
9 files changed, 1367 insertions, 0 deletions
diff --git a/src/mainboard/google/daisy/Kconfig b/src/mainboard/google/daisy/Kconfig
new file mode 100644
index 0000000000..41b37b3497
--- /dev/null
+++ b/src/mainboard/google/daisy/Kconfig
@@ -0,0 +1,58 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright 2013 Google Inc.
+##
+## 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
+##
+
+if BOARD_GOOGLE_DAISY
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+ select CPU_SAMSUNG_EXYNOS5250
+ select EC_GOOGLE_CHROMEEC
+ select EC_GOOGLE_CHROMEEC_I2C
+ select BOARD_ROMSIZE_KB_4096
+ select DRIVER_MAXIM_MAX77686
+ select MAINBOARD_HAS_CHROMEOS
+ select DRIVER_TI_TPS65090
+ select MAINBOARD_HAS_NATIVE_VGA_INIT
+ select MAINBOARD_DO_NATIVE_VGA_INIT
+
+config MAINBOARD_DIR
+ string
+ default google/daisy
+
+config MAINBOARD_PART_NUMBER
+ string
+ default "Daisy"
+
+config MAX_CPUS
+ int
+ default 2
+
+config DRAM_SIZE_MB
+ int
+ default 2048
+
+config EC_GOOGLE_CHROMEEC_I2C_BUS
+ hex
+ default 4
+
+config UART_FOR_CONSOLE
+ int
+ default 3
+
+endif # BOARD_GOOGLE_DAISY
diff --git a/src/mainboard/google/daisy/Makefile.inc b/src/mainboard/google/daisy/Makefile.inc
new file mode 100644
index 0000000000..df9b797367
--- /dev/null
+++ b/src/mainboard/google/daisy/Makefile.inc
@@ -0,0 +1,28 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright 2012 Google Inc.
+##
+## 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
+##
+
+bootblock-y += wakeup.c
+
+romstage-y += memory.c
+romstage-y += romstage.c
+romstage-y += wakeup.c
+romstage-y += chromeos.c
+
+ramstage-y += mainboard.c
+ramstage-y += chromeos.c
diff --git a/src/mainboard/google/daisy/chromeos.c b/src/mainboard/google/daisy/chromeos.c
new file mode 100644
index 0000000000..f7443becc7
--- /dev/null
+++ b/src/mainboard/google/daisy/chromeos.c
@@ -0,0 +1,101 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2013 Google Inc.
+ *
+ * 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 <boot/coreboot_tables.h>
+#include <console/console.h>
+#include <ec/google/chromeec/ec.h>
+#include <ec/google/chromeec/ec_commands.h>
+#include <string.h>
+#include <vendorcode/google/chromeos/chromeos.h>
+#include <bootmode.h>
+#include <soc/samsung/exynos5250/cpu.h>
+#include <soc/samsung/exynos5250/gpio.h>
+
+void fill_lb_gpios(struct lb_gpios *gpios)
+{
+ int count = 0;
+
+ /* Write Protect: active low */
+ gpios->gpios[count].port = EXYNOS5_GPD1;
+ gpios->gpios[count].polarity = ACTIVE_LOW;
+ gpios->gpios[count].value = gpio_get_value(GPIO_D16); // WP_GPIO
+ strncpy((char *)gpios->gpios[count].name, "write protect",
+ GPIO_MAX_NAME_LENGTH);
+ count++;
+
+ /* Recovery: active low */
+ gpios->gpios[count].port = -1;
+ gpios->gpios[count].polarity = ACTIVE_HIGH;
+ gpios->gpios[count].value = get_recovery_mode_switch();
+ strncpy((char *)gpios->gpios[count].name, "recovery",
+ GPIO_MAX_NAME_LENGTH);
+ count++;
+
+ /* Lid: active high */
+ gpios->gpios[count].port = EXYNOS5_GPX3;
+ gpios->gpios[count].polarity = ACTIVE_HIGH;
+ gpios->gpios[count].value = gpio_get_value(GPIO_X35); // LID_GPIO
+ strncpy((char *)gpios->gpios[count].name, "lid", GPIO_MAX_NAME_LENGTH);
+ count++;
+
+ /* Power: virtual GPIO active low */
+ gpios->gpios[count].port = EXYNOS5_GPX1;
+ gpios->gpios[count].polarity = ACTIVE_LOW;
+ gpios->gpios[count].value =
+ gpio_get_value(GPIO_X13); // POWER_GPIO
+ strncpy((char *)gpios->gpios[count].name, "power",
+ GPIO_MAX_NAME_LENGTH);
+ count++;
+
+ /* Developer: virtual GPIO active high */
+ gpios->gpios[count].port = -1;
+ gpios->gpios[count].polarity = ACTIVE_HIGH;
+ gpios->gpios[count].value = get_developer_mode_switch();
+ strncpy((char *)gpios->gpios[count].name, "developer",
+ GPIO_MAX_NAME_LENGTH);
+ count++;
+
+ gpios->size = sizeof(*gpios) + (count * sizeof(struct lb_gpio));
+ gpios->count = count;
+
+ printk(BIOS_ERR, "Added %d GPIOS size %d\n", count, gpios->size);
+}
+
+int get_developer_mode_switch(void)
+{
+ return 0;
+}
+
+int get_recovery_mode_switch(void)
+{
+ uint32_t ec_events;
+
+ /* The GPIO is active low. */
+ if (!gpio_get_value(GPIO_Y10)) // RECMODE_GPIO
+ return 1;
+
+ ec_events = google_chromeec_get_events_b();
+ return !!(ec_events &
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY));
+}
+
+int get_write_protect_state(void)
+{
+ return !gpio_get_value(GPIO_D16);
+}
diff --git a/src/mainboard/google/daisy/devicetree.cb b/src/mainboard/google/daisy/devicetree.cb
new file mode 100644
index 0000000000..2552e070e0
--- /dev/null
+++ b/src/mainboard/google/daisy/devicetree.cb
@@ -0,0 +1,33 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright 2012 Google Inc.
+##
+## 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
+##
+
+chip soc/samsung/exynos5250
+ device cpu_cluster 0 on end
+ register "xres" = "1366"
+ register "yres" = "768"
+ register "framebuffer_bits_per_pixel" = "16"
+ # complex magic timing!
+ register "clkval_f" = "2"
+ register "upper_margin" = "14"
+ register "lower_margin" = "3"
+ register "vsync" = "5"
+ register "left_margin" = "80"
+ register "right_margin" = "48"
+ register "hsync" = "32"
+end
diff --git a/src/mainboard/google/daisy/exynos5250.h b/src/mainboard/google/daisy/exynos5250.h
new file mode 100644
index 0000000000..0f71a3647d
--- /dev/null
+++ b/src/mainboard/google/daisy/exynos5250.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2013 Google Inc.
+ *
+ * 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
+ */
+
+/* I2C */
+#define I2C_0_SPEED 100000
+#define I2C_SLAVE 0
+
+/* Voltages */
+#define VDD_ARM_MV 1300 // 1.3V
+#define VDD_INT_UV 1012500 // 1.0125V
+#define VDD_MIF_MV 1000 // 1.0V
+#define VDD_G3D_MV 1200 // 1.2V
+#define VDD_LDO2_MV 1500 // 1.5V
+#define VDD_LDO3_MV 1800 // 1.8V
+#define VDD_LDO5_MV 1800 // 1.8V
+#define VDD_LDO10_MV 1800 // 1.8V
diff --git a/src/mainboard/google/daisy/mainboard.c b/src/mainboard/google/daisy/mainboard.c
new file mode 100644
index 0000000000..0adadb6649
--- /dev/null
+++ b/src/mainboard/google/daisy/mainboard.c
@@ -0,0 +1,364 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2013 Google Inc.
+ *
+ * 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 <console/console.h>
+#include <device/device.h>
+#include <device/i2c.h>
+#include <drivers/ti/tps65090/tps65090.h>
+#include <cbmem.h>
+#include <delay.h>
+#include <edid.h>
+#include <vbe.h>
+#include <boot/coreboot_tables.h>
+#include <arch/cache.h>
+#include <soc/samsung/exynos5250/tmu.h>
+#include <soc/samsung/exynos5250/clk.h>
+#include <soc/samsung/exynos5250/gpio.h>
+#include <soc/samsung/exynos5250/power.h>
+#include <soc/samsung/exynos5250/i2c.h>
+#include <soc/samsung/exynos5250/dp-core.h>
+#include <soc/samsung/exynos5250/dp.h>
+#include <soc/samsung/exynos5250/usb.h>
+
+#include "exynos5250.h"
+
+#define MMC0_GPIO_PIN (58)
+
+/* convenient shorthand (in MB) */
+#define DRAM_START (CONFIG_SYS_SDRAM_BASE >> 20)
+#define DRAM_SIZE CONFIG_DRAM_SIZE_MB
+#define DRAM_END (DRAM_START + DRAM_SIZE) /* plus one... */
+
+/* Arbitrary range of DMA memory for depthcharge's drivers */
+#define DMA_START (0x77300000)
+#define DMA_SIZE (0x00100000)
+
+static struct edid edid = {
+ .ha = 1366,
+ .va = 768,
+ .framebuffer_bits_per_pixel = 16,
+ .x_resolution = 1366,
+ .y_resolution = 768,
+ .bytes_per_line = 2 * 1366
+};
+
+/* TODO: transplanted DP stuff, clean up once we have something that works */
+static enum exynos5_gpio_pin dp_pd_l = GPIO_Y25; /* active low */
+static enum exynos5_gpio_pin dp_rst_l = GPIO_X15; /* active low */
+static enum exynos5_gpio_pin dp_hpd = GPIO_X07; /* active high */
+
+static void exynos_dp_bridge_setup(void)
+{
+ exynos_pinmux_dphpd();
+
+ gpio_set_value(dp_pd_l, 1);
+ gpio_cfg_pin(dp_pd_l, GPIO_OUTPUT);
+ gpio_set_pull(dp_pd_l, GPIO_PULL_NONE);
+
+ gpio_set_value(dp_rst_l, 0);
+ gpio_cfg_pin(dp_rst_l, GPIO_OUTPUT);
+ gpio_set_pull(dp_rst_l, GPIO_PULL_NONE);
+ udelay(10);
+ gpio_set_value(dp_rst_l, 1);
+}
+
+static void exynos_dp_bridge_init(void)
+{
+ /* De-assert PD (and possibly RST) to power up the bridge */
+ gpio_set_value(dp_pd_l, 1);
+ gpio_set_value(dp_rst_l, 1);
+
+ /*
+ * We need to wait for 90ms after bringing up the bridge since
+ * there is a phantom "high" on the HPD chip during its
+ * bootup. The phantom high comes within 7ms of de-asserting
+ * PD and persists for at least 15ms. The real high comes
+ * roughly 50ms after PD is de-asserted. The phantom high
+ * makes it hard for us to know when the NXP chip is up.
+ */
+ udelay(90000);
+}
+
+static int exynos_dp_hotplug(void)
+{
+ /* Check HPD. If it's high, we're all good. */
+ return gpio_get_value(dp_hpd) ? 0 : 1;
+}
+
+static void exynos_dp_reset(void)
+{
+ gpio_set_value(dp_pd_l, 0);
+ gpio_set_value(dp_rst_l, 0);
+ /* paranoid delay period (300ms) */
+ udelay(300 * 1000);
+}
+
+/*
+ * This delay is T3 in the LCD timing spec (defined as >200ms). We set
+ * this down to 60ms since that's the approximate maximum amount of time
+ * it'll take a bridge to start outputting LVDS data. The delay of
+ * >200ms is just a conservative value to avoid turning on the backlight
+ * when there's random LCD data on the screen. Shaving 140ms off the
+ * boot is an acceptable trade-off.
+ */
+#define LCD_T3_DELAY_MS 60
+
+#define LCD_T5_DELAY_MS 10
+#define LCD_T6_DELAY_MS 10
+
+static void backlight_pwm(void)
+{
+ /*Configure backlight PWM as a simple output high (100% brightness) */
+ gpio_direction_output(GPIO_B20, 1);
+ udelay(LCD_T6_DELAY_MS * 1000);
+}
+
+static void backlight_en(void)
+{
+ /* Configure GPIO for LCD_BL_EN */
+ gpio_direction_output(GPIO_X30, 1);
+}
+
+#define TPS65090_BUS 4 /* Daisy-specific */
+
+#define FET1_CTRL 0x0f
+#define FET4_CTRL 0x12
+#define FET6_CTRL 0x14
+
+static void lcd_vdd(void)
+{
+ /* Enable FET6, lcd panel */
+ tps65090_fet_enable(TPS65090_BUS, FET6_CTRL);
+}
+
+static void backlight_vdd(void)
+{
+ /* Enable FET1, backlight */
+ tps65090_fet_enable(TPS65090_BUS, FET1_CTRL);
+ udelay(LCD_T5_DELAY_MS * 1000);
+}
+
+static void sdmmc_vdd(void)
+{
+ /* Enable FET4, P3.3V_SDCARD */
+ tps65090_fet_enable(TPS65090_BUS, FET4_CTRL);
+}
+
+static enum exynos5_gpio_pin usb_host_vbus = GPIO_X11;
+static enum exynos5_gpio_pin usb_drd_vbus = GPIO_X27;
+/* static enum exynos5_gpio_pin hsic_reset_l = GPIO_E10; */
+
+static void prepare_usb(void)
+{
+ /* Kick this reset off early so it gets at least 100ms to settle */
+ reset_usb_drd_dwc3();
+}
+
+static void setup_usb(void)
+{
+ /* HSIC not needed in firmware on this board */
+ setup_usb_drd_phy();
+ setup_usb_drd_dwc3();
+ setup_usb_host_phy(0);
+
+ gpio_direction_output(usb_host_vbus, 1);
+ gpio_direction_output(usb_drd_vbus, 1);
+}
+
+//static struct video_info smdk5250_dp_config = {
+static struct video_info dp_video_info = {
+ /* FIXME: fix video_info struct to use const for name */
+ .name = (char *)"eDP-LVDS NXP PTN3460",
+
+ .h_sync_polarity = 0,
+ .v_sync_polarity = 0,
+ .interlaced = 0,
+
+ .color_space = COLOR_RGB,
+ .dynamic_range = VESA,
+ .ycbcr_coeff = COLOR_YCBCR601,
+ .color_depth = COLOR_8,
+
+ .link_rate = LINK_RATE_2_70GBPS,
+ .lane_count = LANE_COUNT2,
+};
+
+/* FIXME: move some place more appropriate */
+#define MAX_DP_TRIES 5
+
+/*
+ * This function disables the USB3.0 PLL to save power
+ */
+static void disable_usb30_pll(void)
+{
+ enum exynos5_gpio_pin usb3_pll_l = GPIO_Y11;
+
+ gpio_direction_output(usb3_pll_l, 0);
+}
+
+static void setup_storage(void)
+{
+ /* MMC0: Fixed, 8 bit mode, connected with GPIO. */
+ if (clock_set_mshci(PERIPH_ID_SDMMC0))
+ printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__);
+ if (gpio_direction_output(MMC0_GPIO_PIN, 1)) {
+ printk(BIOS_CRIT, "%s: Unable to power on MMC0.\n", __func__);
+ }
+ gpio_set_pull(MMC0_GPIO_PIN, GPIO_PULL_NONE);
+ gpio_set_drv(MMC0_GPIO_PIN, GPIO_DRV_4X);
+ exynos_pinmux_sdmmc0();
+
+ /* MMC2: Removable, 4 bit mode, no GPIO. */
+ /* (Must be after romstage to avoid breaking SDMMC boot.) */
+ clock_set_mshci(PERIPH_ID_SDMMC2);
+ exynos_pinmux_sdmmc2();
+}
+
+static void gpio_init(void)
+{
+ /* Set up the I2C busses. */
+ exynos_pinmux_i2c0();
+ exynos_pinmux_i2c1();
+ exynos_pinmux_i2c2();
+ exynos_pinmux_i2c3();
+ exynos_pinmux_i2c4();
+ exynos_pinmux_i2c7();
+
+ /* Set up the GPIOs used to arbitrate for I2C bus 4. */
+ gpio_set_pull(GPIO_F03, GPIO_PULL_NONE);
+ gpio_set_pull(GPIO_E04, GPIO_PULL_NONE);
+ gpio_direction_output(GPIO_F03, 1);
+ gpio_direction_input(GPIO_E04);
+
+ /* Set up the GPIO used to enable the audio codec. */
+ gpio_set_pull(GPIO_X17, GPIO_PULL_NONE);
+ gpio_set_pull(GPIO_X15, GPIO_PULL_NONE);
+ gpio_direction_output(GPIO_X17, 1);
+ gpio_direction_output(GPIO_X15, 1);
+
+ /* Set up the I2S busses. */
+ exynos_pinmux_i2s0();
+ exynos_pinmux_i2s1();
+}
+
+/* this happens after cpu_init where exynos resources are set */
+static void mainboard_init(device_t dev)
+{
+ int dp_tries;
+ struct s5p_dp_device dp_device = {
+ .base = exynos_dp1,
+ .video_info = &dp_video_info,
+ };
+ void *fb_addr = (void *)(get_fb_base_kb() * KiB);
+
+ prepare_usb();
+ gpio_init();
+ setup_storage();
+
+ i2c_init(TPS65090_BUS, I2C_0_SPEED, I2C_SLAVE);
+ i2c_init(7, I2C_0_SPEED, I2C_SLAVE);
+
+ tmu_init(&exynos5250_tmu_info);
+
+ /* Clock Gating all the unused IP's to save power */
+ clock_gate();
+
+ /* Disable USB3.0 PLL to save 250mW of power */
+ disable_usb30_pll();
+
+ sdmmc_vdd();
+
+ set_vbe_mode_info_valid(&edid, (uintptr_t)fb_addr);
+
+ lcd_vdd();
+
+ // FIXME: should timeout
+ do {
+ udelay(50);
+ } while (!exynos_dp_hotplug());
+
+ exynos_dp_bridge_setup();
+ for (dp_tries = 1; dp_tries <= MAX_DP_TRIES; dp_tries++) {
+ exynos_dp_bridge_init();
+ if (exynos_dp_hotplug()) {
+ exynos_dp_reset();
+ continue;
+ }
+
+ if (dp_controller_init(&dp_device))
+ continue;
+
+ udelay(LCD_T3_DELAY_MS * 1000);
+
+ backlight_vdd();
+ backlight_pwm();
+ backlight_en();
+ /* if we're here, we're successful */
+ break;
+ }
+
+ if (dp_tries > MAX_DP_TRIES)
+ printk(BIOS_ERR, "%s: Failed to set up displayport\n", __func__);
+
+ setup_usb();
+
+ // Uncomment to get excessive GPIO output:
+ // gpio_info();
+}
+
+static void mainboard_enable(device_t dev)
+{
+ dev->ops->init = &mainboard_init;
+
+ /* set up dcache and MMU */
+ /* FIXME: this should happen via resource allocator */
+ exynos5250_config_l2_cache();
+ mmu_init();
+ mmu_config_range(0, DRAM_START, DCACHE_OFF);
+ mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK);
+ mmu_config_range(DMA_START >> 20, DMA_SIZE >> 20, DCACHE_OFF);
+ mmu_config_range(DRAM_END, 4096 - DRAM_END, DCACHE_OFF);
+ dcache_invalidate_all();
+ dcache_mmu_enable();
+
+ const unsigned epll_hz = 192000000;
+ const unsigned sample_rate = 48000;
+ const unsigned lr_frame_size = 256;
+ clock_epll_set_rate(epll_hz);
+ clock_select_i2s_clk_source();
+ clock_set_i2s_clk_prescaler(epll_hz, sample_rate * lr_frame_size);
+
+ power_enable_xclkout();
+}
+
+struct chip_operations mainboard_ops = {
+ .name = "Samsung/Google ARM Chromebook",
+ .enable_dev = mainboard_enable,
+};
+
+void lb_board(struct lb_header *header)
+{
+ struct lb_range *dma;
+
+ dma = (struct lb_range *)lb_new_record(header);
+ dma->tag = LB_TAB_DMA;
+ dma->size = sizeof(*dma);
+ dma->range_start = (intptr_t)DMA_START;
+ dma->range_size = DMA_SIZE;
+}
diff --git a/src/mainboard/google/daisy/memory.c b/src/mainboard/google/daisy/memory.c
new file mode 100644
index 0000000000..5640f313e0
--- /dev/null
+++ b/src/mainboard/google/daisy/memory.c
@@ -0,0 +1,545 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Copyright 2013 Google Inc.
+ *
+ * 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 <stddef.h>
+#include <stdlib.h>
+#include <console/console.h>
+
+#include <soc/samsung/exynos5250/gpio.h>
+#include <soc/samsung/exynos5250/setup.h>
+#include <soc/samsung/exynos5250/dmc.h>
+#include <soc/samsung/exynos5250/clk.h>
+
+const struct mem_timings mem_timings[] = {
+ {
+ .mem_manuf = MEM_MANUF_ELPIDA,
+ .mem_type = DDR_MODE_DDR3,
+ .frequency_mhz = 800,
+ .mpll_mdiv = 0x64,
+ .mpll_pdiv = 0x3,
+ .mpll_sdiv = 0x0,
+ .cpll_mdiv = 0xde,
+ .cpll_pdiv = 0x4,
+ .cpll_sdiv = 0x2,
+ .gpll_mdiv = 0x215,
+ .gpll_pdiv = 0xc,
+ .gpll_sdiv = 0x1,
+ .epll_mdiv = 0x60,
+ .epll_pdiv = 0x3,
+ .epll_sdiv = 0x3,
+ .vpll_mdiv = 0x96,
+ .vpll_pdiv = 0x3,
+ .vpll_sdiv = 0x2,
+
+ .bpll_mdiv = 0x64,
+ .bpll_pdiv = 0x3,
+ .bpll_sdiv = 0x0,
+ .use_bpll = 0,
+ .pclk_cdrex_ratio = 0x5,
+ .direct_cmd_msr = {
+ 0x00020018, 0x00030000, 0x00010042, 0x00000d70
+ },
+ .timing_ref = 0x000000bb,
+ .timing_row = 0x8c36660f,
+ .timing_data = 0x3630580b,
+ .timing_power = 0x41000a44,
+ .phy0_dqs = 0x08080808,
+ .phy1_dqs = 0x08080808,
+ .phy0_dq = 0x08080808,
+ .phy1_dq = 0x08080808,
+ .phy0_tFS = 0x4,
+ .phy1_tFS = 0x4,
+ .phy0_pulld_dqs = 0xf,
+ .phy1_pulld_dqs = 0xf,
+
+ .lpddr3_ctrl_phy_reset = 0x1,
+ .ctrl_start_point = 0x10,
+ .ctrl_inc = 0x10,
+ .ctrl_start = 0x1,
+ .ctrl_dll_on = 0x1,
+ .ctrl_ref = 0x8,
+
+ .ctrl_force = 0x1a,
+ .ctrl_rdlat = 0x0b,
+ .ctrl_bstlen = 0x08,
+
+ .fp_resync = 0x8,
+ .iv_size = 0x7,
+ .dfi_init_start = 1,
+ .aref_en = 1,
+
+ .rd_fetch = 0x3,
+
+ .zq_mode_dds = 0x7,
+ .zq_mode_term = 0x1,
+ .zq_mode_noterm = 0,
+
+ /*
+ * Dynamic Clock: Always Running
+ * Memory Burst length: 8
+ * Number of chips: 1
+ * Memory Bus width: 32 bit
+ * Memory Type: DDR3
+ * Additional Latancy for PLL: 0 Cycle
+ */
+ .memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE |
+ DMC_MEMCONTROL_DPWRDN_DISABLE |
+ DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE |
+ DMC_MEMCONTROL_TP_DISABLE |
+ DMC_MEMCONTROL_DSREF_ENABLE |
+ DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) |
+ DMC_MEMCONTROL_MEM_TYPE_DDR3 |
+ DMC_MEMCONTROL_MEM_WIDTH_32BIT |
+ DMC_MEMCONTROL_NUM_CHIP_1 |
+ DMC_MEMCONTROL_BL_8 |
+ DMC_MEMCONTROL_PZQ_DISABLE |
+ DMC_MEMCONTROL_MRR_BYTE_7_0,
+ .memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED |
+ DMC_MEMCONFIGx_CHIP_COL_10 |
+ DMC_MEMCONFIGx_CHIP_ROW_15 |
+ DMC_MEMCONFIGx_CHIP_BANK_8,
+ .membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40),
+ .membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80),
+ .prechconfig_tp_cnt = 0xff,
+ .dpwrdn_cyc = 0xff,
+ .dsref_cyc = 0xffff,
+ .concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE |
+ DMC_CONCONTROL_TIMEOUT_LEVEL0 |
+ DMC_CONCONTROL_RD_FETCH_DISABLE |
+ DMC_CONCONTROL_EMPTY_DISABLE |
+ DMC_CONCONTROL_AREF_EN_DISABLE |
+ DMC_CONCONTROL_IO_PD_CON_DISABLE,
+ .dmc_channels = 2,
+ .chips_per_channel = 2,
+ .chips_to_configure = 1,
+ .send_zq_init = 1,
+ .impedance = IMP_OUTPUT_DRV_30_OHM,
+ .gate_leveling_enable = 0,
+ }, {
+ .mem_manuf = MEM_MANUF_SAMSUNG,
+ .mem_type = DDR_MODE_DDR3,
+ .frequency_mhz = 800,
+ .mpll_mdiv = 0x64,
+ .mpll_pdiv = 0x3,
+ .mpll_sdiv = 0x0,
+ .cpll_mdiv = 0xde,
+ .cpll_pdiv = 0x4,
+ .cpll_sdiv = 0x2,
+ .gpll_mdiv = 0x215,
+ .gpll_pdiv = 0xc,
+ .gpll_sdiv = 0x1,
+ .epll_mdiv = 0x60,
+ .epll_pdiv = 0x3,
+ .epll_sdiv = 0x3,
+ .vpll_mdiv = 0x96,
+ .vpll_pdiv = 0x3,
+ .vpll_sdiv = 0x2,
+
+ .bpll_mdiv = 0x64,
+ .bpll_pdiv = 0x3,
+ .bpll_sdiv = 0x0,
+ .use_bpll = 0,
+ .pclk_cdrex_ratio = 0x5,
+ .direct_cmd_msr = {
+ 0x00020018, 0x00030000, 0x00010000, 0x00000d70
+ },
+ .timing_ref = 0x000000bb,
+ .timing_row = 0x8c36660f,
+ .timing_data = 0x3630580b,
+ .timing_power = 0x41000a44,
+ .phy0_dqs = 0x08080808,
+ .phy1_dqs = 0x08080808,
+ .phy0_dq = 0x08080808,
+ .phy1_dq = 0x08080808,
+ .phy0_tFS = 0x8,
+ .phy1_tFS = 0x8,
+ .phy0_pulld_dqs = 0xf,
+ .phy1_pulld_dqs = 0xf,
+
+ .lpddr3_ctrl_phy_reset = 0x1,
+ .ctrl_start_point = 0x10,
+ .ctrl_inc = 0x10,
+ .ctrl_start = 0x1,
+ .ctrl_dll_on = 0x1,
+ .ctrl_ref = 0x8,
+
+ .ctrl_force = 0x1a,
+ .ctrl_rdlat = 0x0b,
+ .ctrl_bstlen = 0x08,
+
+ .fp_resync = 0x8,
+ .iv_size = 0x7,
+ .dfi_init_start = 1,
+ .aref_en = 1,
+
+ .rd_fetch = 0x3,
+
+ .zq_mode_dds = 0x5,
+ .zq_mode_term = 0x1,
+ .zq_mode_noterm = 1,
+
+ /*
+ * Dynamic Clock: Always Running
+ * Memory Burst length: 8
+ * Number of chips: 1
+ * Memory Bus width: 32 bit
+ * Memory Type: DDR3
+ * Additional Latancy for PLL: 0 Cycle
+ */
+ .memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE |
+ DMC_MEMCONTROL_DPWRDN_DISABLE |
+ DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE |
+ DMC_MEMCONTROL_TP_DISABLE |
+ DMC_MEMCONTROL_DSREF_ENABLE |
+ DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) |
+ DMC_MEMCONTROL_MEM_TYPE_DDR3 |
+ DMC_MEMCONTROL_MEM_WIDTH_32BIT |
+ DMC_MEMCONTROL_NUM_CHIP_1 |
+ DMC_MEMCONTROL_BL_8 |
+ DMC_MEMCONTROL_PZQ_DISABLE |
+ DMC_MEMCONTROL_MRR_BYTE_7_0,
+ .memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED |
+ DMC_MEMCONFIGx_CHIP_COL_10 |
+ DMC_MEMCONFIGx_CHIP_ROW_15 |
+ DMC_MEMCONFIGx_CHIP_BANK_8,
+ .membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40),
+ .membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80),
+ .prechconfig_tp_cnt = 0xff,
+ .dpwrdn_cyc = 0xff,
+ .dsref_cyc = 0xffff,
+ .concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE |
+ DMC_CONCONTROL_TIMEOUT_LEVEL0 |
+ DMC_CONCONTROL_RD_FETCH_DISABLE |
+ DMC_CONCONTROL_EMPTY_DISABLE |
+ DMC_CONCONTROL_AREF_EN_DISABLE |
+ DMC_CONCONTROL_IO_PD_CON_DISABLE,
+ .dmc_channels = 2,
+ .chips_per_channel = 2,
+ .chips_to_configure = 1,
+ .send_zq_init = 1,
+ .impedance = IMP_OUTPUT_DRV_40_OHM,
+ .gate_leveling_enable = 1,
+ },
+ {
+ .mem_manuf = MEM_MANUF_ELPIDA,
+ .mem_type = DDR_MODE_DDR3,
+ .frequency_mhz = 780,
+ .mpll_mdiv = 0x64,
+ .mpll_pdiv = 0x3,
+ .mpll_sdiv = 0x0,
+ .cpll_mdiv = 0xde,
+ .cpll_pdiv = 0x4,
+ .cpll_sdiv = 0x2,
+ .gpll_mdiv = 0x215,
+ .gpll_pdiv = 0xc,
+ .gpll_sdiv = 0x1,
+ .epll_mdiv = 0x60,
+ .epll_pdiv = 0x3,
+ .epll_sdiv = 0x3,
+ .vpll_mdiv = 0x96,
+ .vpll_pdiv = 0x3,
+ .vpll_sdiv = 0x2,
+
+ .bpll_mdiv = 0x82,
+ .bpll_pdiv = 0x4,
+ .bpll_sdiv = 0x0,
+ .use_bpll = 1,
+ .pclk_cdrex_ratio = 0x5,
+ .direct_cmd_msr = {
+ 0x00020018, 0x00030000, 0x00010042, 0x00000d70
+ },
+ .timing_ref = 0x000000bb,
+ .timing_row = 0x8c36660f,
+ .timing_data = 0x3630580b,
+ .timing_power = 0x41000a44,
+ .phy0_dqs = 0x08080808,
+ .phy1_dqs = 0x08080808,
+ .phy0_dq = 0x08080808,
+ .phy1_dq = 0x08080808,
+ .phy0_tFS = 0x4,
+ .phy1_tFS = 0x4,
+ .phy0_pulld_dqs = 0xf,
+ .phy1_pulld_dqs = 0xf,
+
+ .lpddr3_ctrl_phy_reset = 0x1,
+ .ctrl_start_point = 0x10,
+ .ctrl_inc = 0x10,
+ .ctrl_start = 0x1,
+ .ctrl_dll_on = 0x1,
+ .ctrl_ref = 0x8,
+
+ .ctrl_force = 0x1a,
+ .ctrl_rdlat = 0x0b,
+ .ctrl_bstlen = 0x08,
+
+ .fp_resync = 0x8,
+ .iv_size = 0x7,
+ .dfi_init_start = 1,
+ .aref_en = 1,
+
+ .rd_fetch = 0x3,
+
+ .zq_mode_dds = 0x7,
+ .zq_mode_term = 0x1,
+ .zq_mode_noterm = 0,
+
+ /*
+ * Dynamic Clock: Always Running
+ * Memory Burst length: 8
+ * Number of chips: 1
+ * Memory Bus width: 32 bit
+ * Memory Type: DDR3
+ * Additional Latancy for PLL: 0 Cycle
+ */
+ .memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE |
+ DMC_MEMCONTROL_DPWRDN_DISABLE |
+ DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE |
+ DMC_MEMCONTROL_TP_DISABLE |
+ DMC_MEMCONTROL_DSREF_ENABLE |
+ DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) |
+ DMC_MEMCONTROL_MEM_TYPE_DDR3 |
+ DMC_MEMCONTROL_MEM_WIDTH_32BIT |
+ DMC_MEMCONTROL_NUM_CHIP_1 |
+ DMC_MEMCONTROL_BL_8 |
+ DMC_MEMCONTROL_PZQ_DISABLE |
+ DMC_MEMCONTROL_MRR_BYTE_7_0,
+ .memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED |
+ DMC_MEMCONFIGx_CHIP_COL_10 |
+ DMC_MEMCONFIGx_CHIP_ROW_15 |
+ DMC_MEMCONFIGx_CHIP_BANK_8,
+ .membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40),
+ .membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80),
+ .prechconfig_tp_cnt = 0xff,
+ .dpwrdn_cyc = 0xff,
+ .dsref_cyc = 0xffff,
+ .concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE |
+ DMC_CONCONTROL_TIMEOUT_LEVEL0 |
+ DMC_CONCONTROL_RD_FETCH_DISABLE |
+ DMC_CONCONTROL_EMPTY_DISABLE |
+ DMC_CONCONTROL_AREF_EN_DISABLE |
+ DMC_CONCONTROL_IO_PD_CON_DISABLE,
+ .dmc_channels = 2,
+ .chips_per_channel = 2,
+ .chips_to_configure = 1,
+ .send_zq_init = 1,
+ .impedance = IMP_OUTPUT_DRV_30_OHM,
+ .gate_leveling_enable = 0,
+ }, {
+ .mem_manuf = MEM_MANUF_SAMSUNG,
+ .mem_type = DDR_MODE_DDR3,
+ .frequency_mhz = 780,
+ .mpll_mdiv = 0x64,
+ .mpll_pdiv = 0x3,
+ .mpll_sdiv = 0x0,
+ .cpll_mdiv = 0xde,
+ .cpll_pdiv = 0x4,
+ .cpll_sdiv = 0x2,
+ .gpll_mdiv = 0x215,
+ .gpll_pdiv = 0xc,
+ .gpll_sdiv = 0x1,
+ .epll_mdiv = 0x60,
+ .epll_pdiv = 0x3,
+ .epll_sdiv = 0x3,
+ .vpll_mdiv = 0x96,
+ .vpll_pdiv = 0x3,
+ .vpll_sdiv = 0x2,
+
+ .bpll_mdiv = 0x82,
+ .bpll_pdiv = 0x4,
+ .bpll_sdiv = 0x0,
+ .use_bpll = 1,
+ .pclk_cdrex_ratio = 0x5,
+ .direct_cmd_msr = {
+ 0x00020018, 0x00030000, 0x00010000, 0x00000d70
+ },
+ .timing_ref = 0x000000bb,
+ .timing_row = 0x8c36660f,
+ .timing_data = 0x3630580b,
+ .timing_power = 0x41000a44,
+ .phy0_dqs = 0x08080808,
+ .phy1_dqs = 0x08080808,
+ .phy0_dq = 0x08080808,
+ .phy1_dq = 0x08080808,
+ .phy0_tFS = 0x8,
+ .phy1_tFS = 0x8,
+ .phy0_pulld_dqs = 0xf,
+ .phy1_pulld_dqs = 0xf,
+
+ .lpddr3_ctrl_phy_reset = 0x1,
+ .ctrl_start_point = 0x10,
+ .ctrl_inc = 0x10,
+ .ctrl_start = 0x1,
+ .ctrl_dll_on = 0x1,
+ .ctrl_ref = 0x8,
+
+ .ctrl_force = 0x1a,
+ .ctrl_rdlat = 0x0b,
+ .ctrl_bstlen = 0x08,
+
+ .fp_resync = 0x8,
+ .iv_size = 0x7,
+ .dfi_init_start = 1,
+ .aref_en = 1,
+
+ .rd_fetch = 0x3,
+
+ .zq_mode_dds = 0x5,
+ .zq_mode_term = 0x1,
+ .zq_mode_noterm = 1,
+
+ /*
+ * Dynamic Clock: Always Running
+ * Memory Burst length: 8
+ * Number of chips: 1
+ * Memory Bus width: 32 bit
+ * Memory Type: DDR3
+ * Additional Latancy for PLL: 0 Cycle
+ */
+ .memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE |
+ DMC_MEMCONTROL_DPWRDN_DISABLE |
+ DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE |
+ DMC_MEMCONTROL_TP_DISABLE |
+ DMC_MEMCONTROL_DSREF_ENABLE |
+ DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) |
+ DMC_MEMCONTROL_MEM_TYPE_DDR3 |
+ DMC_MEMCONTROL_MEM_WIDTH_32BIT |
+ DMC_MEMCONTROL_NUM_CHIP_1 |
+ DMC_MEMCONTROL_BL_8 |
+ DMC_MEMCONTROL_PZQ_DISABLE |
+ DMC_MEMCONTROL_MRR_BYTE_7_0,
+ .memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED |
+ DMC_MEMCONFIGx_CHIP_COL_10 |
+ DMC_MEMCONFIGx_CHIP_ROW_15 |
+ DMC_MEMCONFIGx_CHIP_BANK_8,
+ .membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40),
+ .membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80),
+ .prechconfig_tp_cnt = 0xff,
+ .dpwrdn_cyc = 0xff,
+ .dsref_cyc = 0xffff,
+ .concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE |
+ DMC_CONCONTROL_TIMEOUT_LEVEL0 |
+ DMC_CONCONTROL_RD_FETCH_DISABLE |
+ DMC_CONCONTROL_EMPTY_DISABLE |
+ DMC_CONCONTROL_AREF_EN_DISABLE |
+ DMC_CONCONTROL_IO_PD_CON_DISABLE,
+ .dmc_channels = 2,
+ .chips_per_channel = 2,
+ .chips_to_configure = 1,
+ .send_zq_init = 1,
+ .impedance = IMP_OUTPUT_DRV_40_OHM,
+ .gate_leveling_enable = 1,
+ }
+};
+
+#define BOARD_ID0_GPIO 88 /* GPD0, pin 0 */
+#define BOARD_ID1_GPIO 89 /* GPD0, pin 1 */
+
+enum board_config {
+ DAISY_CONFIG_UNKNOWN = -1,
+ DAISY_CONFIG_SAMSUNG_EVT,
+ DAISY_CONFIG_ELPIDA_EVT,
+ DAISY_CONFIG_SAMSUNG_DVT,
+ DAISY_CONFIG_ELPIDA_DVT,
+ DAISY_CONFIG_SAMSUNG_PVT,
+ DAISY_CONFIG_ELPIDA_PVT,
+ DAISY_CONFIG_SAMSUNG_MP,
+ DAISY_CONFIG_ELPIDA_MP,
+ DAISY_CONFIG_RSVD,
+};
+
+struct {
+ enum mvl3 id0, id1;
+ enum board_config config;
+} id_map[] = {
+ /* ID0 ID1 config */
+ { LOGIC_0, LOGIC_0, DAISY_CONFIG_SAMSUNG_MP },
+ { LOGIC_0, LOGIC_1, DAISY_CONFIG_ELPIDA_MP },
+ { LOGIC_1, LOGIC_0, DAISY_CONFIG_SAMSUNG_DVT },
+ { LOGIC_1, LOGIC_1, DAISY_CONFIG_ELPIDA_DVT },
+ { LOGIC_0, LOGIC_Z, DAISY_CONFIG_SAMSUNG_PVT },
+ { LOGIC_1, LOGIC_Z, DAISY_CONFIG_ELPIDA_PVT },
+ { LOGIC_Z, LOGIC_0, DAISY_CONFIG_SAMSUNG_MP },
+ { LOGIC_Z, LOGIC_Z, DAISY_CONFIG_ELPIDA_MP },
+ { LOGIC_Z, LOGIC_1, DAISY_CONFIG_RSVD },
+};
+
+static int board_get_config(void)
+{
+ int i;
+ int id0, id1;
+ enum board_config config = DAISY_CONFIG_UNKNOWN;
+
+ id0 = gpio_read_mvl3(BOARD_ID0_GPIO);
+ id1 = gpio_read_mvl3(BOARD_ID1_GPIO);
+ if (id0 < 0 || id1 < 0)
+ return -1;
+
+ for (i = 0; i < ARRAY_SIZE(id_map); i++) {
+ if (id0 == id_map[i].id0 && id1 == id_map[i].id1) {
+ config = id_map[i].config;
+ break;
+ }
+ }
+
+ return config;
+}
+
+struct mem_timings *get_mem_timings(void)
+{
+ int i;
+ enum board_config config;
+ enum ddr_mode mem_type;
+ unsigned int frequency_mhz;
+ enum mem_manuf mem_manuf;
+ const struct mem_timings *mem;
+
+ config = board_get_config();
+ switch (config) {
+ case DAISY_CONFIG_ELPIDA_EVT:
+ case DAISY_CONFIG_ELPIDA_DVT:
+ case DAISY_CONFIG_ELPIDA_PVT:
+ case DAISY_CONFIG_ELPIDA_MP:
+ mem_manuf = MEM_MANUF_ELPIDA;
+ mem_type = DDR_MODE_DDR3;
+ frequency_mhz = 800;
+ break;
+ case DAISY_CONFIG_SAMSUNG_EVT:
+ case DAISY_CONFIG_SAMSUNG_DVT:
+ case DAISY_CONFIG_SAMSUNG_PVT:
+ case DAISY_CONFIG_SAMSUNG_MP:
+ mem_manuf = MEM_MANUF_SAMSUNG;
+ mem_type = DDR_MODE_DDR3;
+ frequency_mhz = 800;
+ break;
+ default:
+ printk(BIOS_CRIT, "Unknown board configuration.\n");
+ return NULL;
+ }
+
+ for (i = 0, mem = mem_timings; i < ARRAY_SIZE(mem_timings);
+ i++, mem++) {
+ if (mem->mem_type == mem_type &&
+ mem->frequency_mhz == frequency_mhz &&
+ mem->mem_manuf == mem_manuf)
+ return (struct mem_timings *)mem;
+ }
+
+ return NULL;
+}
diff --git a/src/mainboard/google/daisy/romstage.c b/src/mainboard/google/daisy/romstage.c
new file mode 100644
index 0000000000..9b35c4a6d4
--- /dev/null
+++ b/src/mainboard/google/daisy/romstage.c
@@ -0,0 +1,178 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 The ChromiumOS 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 <types.h>
+
+#include <armv7.h>
+#include <cbfs.h>
+#include <cbmem.h>
+
+#include <arch/cache.h>
+#include <arch/exception.h>
+#include <soc/samsung/exynos5250/i2c.h>
+#include <soc/samsung/exynos5250/clk.h>
+#include <soc/samsung/exynos5250/cpu.h>
+#include <soc/samsung/exynos5250/dmc.h>
+#include <soc/samsung/exynos5250/gpio.h>
+#include <soc/samsung/exynos5250/setup.h>
+#include <soc/samsung/exynos5250/periph.h>
+#include <soc/samsung/exynos5250/power.h>
+#include <soc/samsung/exynos5250/trustzone.h>
+#include <soc/samsung/exynos5250/wakeup.h>
+#include <console/console.h>
+#include <arch/stages.h>
+
+#include <drivers/maxim/max77686/max77686.h>
+#include <device/i2c.h>
+
+#include "exynos5250.h"
+
+#define PMIC_BUS 0
+
+static void setup_power(int is_resume)
+{
+ int error = 0;
+
+ power_init();
+
+ if (is_resume) {
+ return;
+ }
+
+ /* Initialize I2C bus to configure PMIC. */
+ exynos_pinmux_i2c0();
+ i2c_init(0, I2C_0_SPEED, 0x00);
+
+ printk(BIOS_DEBUG, "%s: Setting up PMIC...\n", __func__);
+ /*
+ * We're using CR1616 coin cell battery that is non-rechargeable
+ * battery. But, BBCHOSTEN bit of the BBAT Charger Register in
+ * MAX77686 is enabled by default for charging coin cell.
+ *
+ * Also, we cannot meet the coin cell reverse current spec. in UL
+ * standard if BBCHOSTEN bit is enabled.
+ *
+ * Disable Coin BATT Charging
+ */
+ error = max77686_disable_backup_batt(PMIC_BUS);
+
+ error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK2, VDD_ARM_MV,
+ REG_ENABLE, MAX77686_MV);
+ error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK3, VDD_INT_UV,
+ REG_ENABLE, MAX77686_UV);
+ error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK1, VDD_MIF_MV,
+ REG_ENABLE, MAX77686_MV);
+ error |= max77686_volsetting(PMIC_BUS, PMIC_BUCK4, VDD_G3D_MV,
+ REG_ENABLE, MAX77686_MV);
+ error |= max77686_volsetting(PMIC_BUS, PMIC_LDO2, VDD_LDO2_MV,
+ REG_ENABLE, MAX77686_MV);
+ error |= max77686_volsetting(PMIC_BUS, PMIC_LDO3, VDD_LDO3_MV,
+ REG_ENABLE, MAX77686_MV);
+ error |= max77686_volsetting(PMIC_BUS, PMIC_LDO5, VDD_LDO5_MV,
+ REG_ENABLE, MAX77686_MV);
+ error |= max77686_volsetting(PMIC_BUS, PMIC_LDO10, VDD_LDO10_MV,
+ REG_ENABLE, MAX77686_MV);
+
+ error |= max77686_enable_32khz_cp(PMIC_BUS);
+
+ if (error) {
+ printk(BIOS_CRIT, "%s: PMIC error: %#x\n", __func__, error);
+ die("Failed to intialize PMIC.\n");
+ }
+}
+
+static void setup_graphics(void)
+{
+ exynos_pinmux_dphpd();
+}
+
+static void setup_gpio(void)
+{
+ gpio_direction_input(GPIO_D16); // WP_GPIO
+ gpio_set_pull(GPIO_D16, GPIO_PULL_NONE);
+
+ gpio_direction_input(GPIO_Y10); // RECMODE_GPIO
+ gpio_set_pull(GPIO_Y10, GPIO_PULL_NONE);
+
+ gpio_direction_input(GPIO_X35); // LID_GPIO
+ gpio_set_pull(GPIO_X35, GPIO_PULL_NONE);
+
+ gpio_direction_input(GPIO_X13); // POWER_GPIO
+ gpio_set_pull(GPIO_X13, GPIO_PULL_NONE);
+}
+
+static void setup_memory(struct mem_timings *mem, int is_resume)
+{
+ printk(BIOS_SPEW, "man: 0x%x type: 0x%x, div: 0x%x, mhz: %d\n",
+ mem->mem_manuf,
+ mem->mem_type,
+ mem->mpll_mdiv,
+ mem->frequency_mhz);
+
+ if (ddr3_mem_ctrl_init(mem, DMC_INTERLEAVE_SIZE, !is_resume)) {
+ die("Failed to initialize memory controller.\n");
+ }
+}
+
+static struct mem_timings *setup_clock(void)
+{
+ struct mem_timings *mem = get_mem_timings();
+ struct arm_clk_ratios *arm_ratios = get_arm_clk_ratios();
+ if (!mem) {
+ die("Unable to auto-detect memory timings\n");
+ }
+ system_clock_init(mem, arm_ratios);
+ return mem;
+}
+
+void main(void)
+{
+ struct mem_timings *mem;
+ void *entry;
+ int is_resume = (get_wakeup_state() != IS_NOT_WAKEUP);
+
+ /* Clock must be initialized before console_init, otherwise you may need
+ * to re-initialize serial console drivers again. */
+ mem = setup_clock();
+
+ console_init();
+ exception_init();
+
+ setup_power(is_resume);
+ setup_memory(mem, is_resume);
+
+ /* This needs to happen on normal boots and on resume. */
+ trustzone_init();
+
+ if (is_resume) {
+ wakeup();
+ }
+
+ setup_gpio();
+ setup_graphics();
+
+ /* Set SPI (primary CBFS media) clock to 50MHz and configure pinmux. */
+ exynos_pinmux_spi1();
+ clock_set_rate(PERIPH_ID_SPI1, 50000000);
+
+ cbmem_initialize_empty();
+
+ entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/ramstage");
+ stage_exit(entry);
+}
diff --git a/src/mainboard/google/daisy/wakeup.c b/src/mainboard/google/daisy/wakeup.c
new file mode 100644
index 0000000000..8b7fc4b9d2
--- /dev/null
+++ b/src/mainboard/google/daisy/wakeup.c
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2013 Google Inc.
+ *
+ * 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 <soc/samsung/exynos5250/gpio.h>
+#include <soc/samsung/exynos5250/wakeup.h>
+
+int wakeup_need_reset(void)
+{
+ /* The "wake up" event is not reliable (known as "bad wakeup") and needs
+ * reset if GPIO value is high. */
+ return gpio_get_value(GPIO_Y10);
+}