[coreboot-gerrit] Patch set updated for coreboot: d3b1165 pit: Add a "pit" mainboard which is mostly a copy of "snow".

Gabe Black (gabeblack@chromium.org) gerrit at coreboot.org
Wed Jul 10 11:36:31 CEST 2013


Gabe Black (gabeblack at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3646

-gerrit

commit d3b1165247956274149c47d77264f76b0a2d53c3
Author: Gabe Black <gabeblack at google.com>
Date:   Thu May 16 05:53:40 2013 -0700

    pit: Add a "pit" mainboard which is mostly a copy of "snow".
    
    This change adds a pit mainboard which is mostly a copy of snow, except that
    mentions of the 5250 were replaced with the 5420, and mentions of snow were
    replaced with pit.
    
    Change-Id: I8eb0ce379eb2fa353bb88d5656a0c5e2290afbf0
    Signed-off-by: Gabe Black <gabeblack at chromium.org>
---
 src/mainboard/google/Kconfig           |   3 +
 src/mainboard/google/pit/Kconfig       |  56 ++++
 src/mainboard/google/pit/Makefile.inc  |  27 ++
 src/mainboard/google/pit/chromeos.c    | 105 +++++++
 src/mainboard/google/pit/devicetree.cb |  33 ++
 src/mainboard/google/pit/exynos5420.h  |  33 ++
 src/mainboard/google/pit/mainboard.c   | 273 +++++++++++++++++
 src/mainboard/google/pit/memory.c      | 546 +++++++++++++++++++++++++++++++++
 src/mainboard/google/pit/romstage.c    | 191 ++++++++++++
 src/mainboard/google/pit/wakeup.c      |  29 ++
 10 files changed, 1296 insertions(+)

diff --git a/src/mainboard/google/Kconfig b/src/mainboard/google/Kconfig
index e389b59..0e34a8d 100644
--- a/src/mainboard/google/Kconfig
+++ b/src/mainboard/google/Kconfig
@@ -32,6 +32,8 @@ config BOARD_GOOGLE_LINK
 	bool "Link"
 config BOARD_GOOGLE_PARROT
 	bool "Parrot"
+config BOARD_GOOGLE_PIT
+	bool "Pit"
 config BOARD_GOOGLE_SNOW
 	bool "Snow"
 config BOARD_GOOGLE_STOUT
@@ -42,6 +44,7 @@ endchoice
 source "src/mainboard/google/butterfly/Kconfig"
 source "src/mainboard/google/link/Kconfig"
 source "src/mainboard/google/parrot/Kconfig"
+source "src/mainboard/google/pit/Kconfig"
 source "src/mainboard/google/snow/Kconfig"
 source "src/mainboard/google/stout/Kconfig"
 
diff --git a/src/mainboard/google/pit/Kconfig b/src/mainboard/google/pit/Kconfig
new file mode 100644
index 0000000..8aed0a0
--- /dev/null
+++ b/src/mainboard/google/pit/Kconfig
@@ -0,0 +1,56 @@
+##
+## 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_PIT
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	select ARCH_ARMV7
+	select CPU_SAMSUNG_EXYNOS5420
+	select HAVE_UART_MEMORY_MAPPED
+	select EC_GOOGLE_CHROMEEC
+	select EC_GOOGLE_CHROMEEC_I2C
+	select BOARD_ROMSIZE_KB_4096
+	select DRIVER_MAXIM_MAX77686
+	select CHROMEOS
+	select DRIVER_TI_TPS65090
+	select MAINBOARD_HAS_NATIVE_VGA_INIT
+	select MAINBOARD_DO_NATIVE_VGA_INIT
+
+config MAINBOARD_DIR
+	string
+	default google/pit
+
+config MAINBOARD_PART_NUMBER
+	string
+	default "Pit"
+
+config MAX_CPUS
+	int
+	default 2
+
+config DRAM_SIZE_MB
+	int
+	default 2048
+
+config EC_GOOGLE_CHROMEEC_I2C_BUS
+	hex
+	default 4
+
+endif # BOARD_GOOGLE_PIT
diff --git a/src/mainboard/google/pit/Makefile.inc b/src/mainboard/google/pit/Makefile.inc
new file mode 100644
index 0000000..2858743
--- /dev/null
+++ b/src/mainboard/google/pit/Makefile.inc
@@ -0,0 +1,27 @@
+##
+## 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
+
+ramstage-y += mainboard.c
+ramstage-y += chromeos.c
diff --git a/src/mainboard/google/pit/chromeos.c b/src/mainboard/google/pit/chromeos.c
new file mode 100644
index 0000000..349ba1d
--- /dev/null
+++ b/src/mainboard/google/pit/chromeos.c
@@ -0,0 +1,105 @@
+/*
+ * 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 <cpu/samsung/exynos5420/cpu.h>
+#include <cpu/samsung/exynos5420/gpio.h>
+
+enum {
+	ACTIVE_LOW = 0,
+	ACTIVE_HIGH = 1
+};
+
+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_recovery_mode_from_vbnv(void)
+{
+	return 0;
+}
diff --git a/src/mainboard/google/pit/devicetree.cb b/src/mainboard/google/pit/devicetree.cb
new file mode 100644
index 0000000..3b6cdb9
--- /dev/null
+++ b/src/mainboard/google/pit/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 cpu/samsung/exynos5420
+	device cpu_cluster 0 on end
+	register "xres" = "1366"
+	register "yres" = "768"
+	register "bpp" = "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/pit/exynos5420.h b/src/mainboard/google/pit/exynos5420.h
new file mode 100644
index 0000000..98d36f9
--- /dev/null
+++ b/src/mainboard/google/pit/exynos5420.h
@@ -0,0 +1,33 @@
+/*
+ * 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/pit/mainboard.c b/src/mainboard/google/pit/mainboard.c
new file mode 100644
index 0000000..11b72c5
--- /dev/null
+++ b/src/mainboard/google/pit/mainboard.c
@@ -0,0 +1,273 @@
+/*
+ * 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 <arch/exception.h>
+#include <cpu/samsung/exynos5420/tmu.h>
+#include <cpu/samsung/exynos5420/clk.h>
+#include <cpu/samsung/exynos5420/cpu.h>
+#include <cpu/samsung/exynos5420/gpio.h>
+#include <cpu/samsung/exynos5420/power.h>
+#include <cpu/samsung/exynos5420/i2c.h>
+#include <cpu/samsung/exynos5420/dp-core.h>
+
+#include "exynos5420.h"
+
+/* 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... */
+
+static struct edid edid = {
+	.ha = 1366,
+	.va = 768,
+	.bpp = 16,
+};
+
+/* 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_config(PERIPH_ID_DPHPD, 0);
+
+	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 TPS69050_BUS	4	/* Pit-specific */
+
+#define FET1_CTRL	0x0f
+#define FET6_CTRL	0x14
+
+static void lcd_vdd(void)
+{
+	/* Enable FET6, lcd panel */
+	tps65090_fet_enable(TPS69050_BUS, FET6_CTRL);
+}
+
+static void backlight_vdd(void)
+{
+	/* Enable FET1, backlight */
+	tps65090_fet_enable(TPS69050_BUS, FET1_CTRL);
+	udelay(LCD_T5_DELAY_MS * 1000);
+}
+
+//static struct video_info smdk5420_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 EXYNOS5420_DP1_BASE	0x145b0000
+#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);
+}
+
+/* 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 = (struct exynos5_dp *)EXYNOS5420_DP1_BASE,
+		.video_info = &dp_video_info,
+	};
+	void *fb_addr;
+
+	i2c_init(TPS69050_BUS, I2C_0_SPEED, I2C_SLAVE);
+	i2c_init(7, I2C_0_SPEED, I2C_SLAVE);
+
+	tmu_init(&exynos5420_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();
+
+	fb_addr = cbmem_find(CBMEM_ID_CONSOLE);
+	set_vbe_mode_info_valid(&edid, (uintptr_t)(fb_addr) + 64*KiB);
+
+	lcd_vdd();
+	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__);
+
+	gpio_info();
+}
+
+static void mainboard_enable(device_t dev)
+{
+	dev->ops->init = &mainboard_init;
+
+	/* set up coreboot tables */
+	/* FIXME: this should happen somewhere else */
+	high_tables_size = CONFIG_COREBOOT_TABLES_SIZE;
+	high_tables_base = CONFIG_SYS_SDRAM_BASE +
+				((unsigned)CONFIG_DRAM_SIZE_MB << 20ULL) -
+				CONFIG_COREBOOT_TABLES_SIZE;
+	cbmem_init(high_tables_base, high_tables_size);
+
+	/* set up dcache and MMU */
+	/* FIXME: this should happen via resource allocator */
+	exynos5420_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(DRAM_END, 4096 - DRAM_END, DCACHE_OFF);
+	dcache_invalidate_all();
+	dcache_mmu_enable();
+
+	/* this is going to move, but we must have it now and we're
+	 * not sure where */
+	exception_init();
+
+	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,
+};
diff --git a/src/mainboard/google/pit/memory.c b/src/mainboard/google/pit/memory.c
new file mode 100644
index 0000000..e420fe0
--- /dev/null
+++ b/src/mainboard/google/pit/memory.c
@@ -0,0 +1,546 @@
+/*
+ * 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 <cpu/samsung/exynos5420/gpio.h>
+#include <cpu/samsung/exynos5420/setup.h>
+#include <cpu/samsung/exynos5420/dmc.h>
+#include <cpu/samsung/exynos5420/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 {
+	PIT_CONFIG_UNKNOWN = -1,
+	PIT_CONFIG_SAMSUNG_EVT,
+	PIT_CONFIG_ELPIDA_EVT,
+	PIT_CONFIG_SAMSUNG_DVT,
+	PIT_CONFIG_ELPIDA_DVT,
+	PIT_CONFIG_SAMSUNG_PVT,
+	PIT_CONFIG_ELPIDA_PVT,
+	PIT_CONFIG_SAMSUNG_MP,
+	PIT_CONFIG_ELPIDA_MP,
+	PIT_CONFIG_RSVD,
+};
+
+struct {
+	enum mvl3 id0, id1;
+	enum board_config config;
+} id_map[] = {
+	/*  ID0      ID1         config */
+	{ LOGIC_0, LOGIC_0, PIT_CONFIG_SAMSUNG_MP },
+	{ LOGIC_0, LOGIC_1, PIT_CONFIG_ELPIDA_MP },
+	{ LOGIC_1, LOGIC_0, PIT_CONFIG_SAMSUNG_DVT },
+	{ LOGIC_1, LOGIC_1, PIT_CONFIG_ELPIDA_DVT },
+	{ LOGIC_0, LOGIC_Z, PIT_CONFIG_SAMSUNG_PVT },
+	{ LOGIC_1, LOGIC_Z, PIT_CONFIG_ELPIDA_PVT },
+	{ LOGIC_Z, LOGIC_0, PIT_CONFIG_SAMSUNG_MP },
+	{ LOGIC_Z, LOGIC_Z, PIT_CONFIG_ELPIDA_MP },
+	{ LOGIC_Z, LOGIC_1, PIT_CONFIG_RSVD },
+};
+
+static int board_get_config(void)
+{
+	int i;
+	int id0, id1;
+	enum board_config config = PIT_CONFIG_UNKNOWN;
+
+	id0 = gpio_read_mvl3(BOARD_ID0_GPIO);
+	id1 = gpio_read_mvl3(BOARD_ID1_GPIO);
+	if (id0 < 0 || id1 < 0)
+		return -1;
+	printk(BIOS_DEBUG, "%s: id0: %u, id1: %u\n", __func__, id0, id1);
+
+	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 PIT_CONFIG_ELPIDA_EVT:
+	case PIT_CONFIG_ELPIDA_DVT:
+	case PIT_CONFIG_ELPIDA_PVT:
+	case PIT_CONFIG_ELPIDA_MP:
+		mem_manuf = MEM_MANUF_ELPIDA;
+		mem_type = DDR_MODE_DDR3;
+		frequency_mhz = 800;
+		break;
+	case PIT_CONFIG_SAMSUNG_EVT:
+	case PIT_CONFIG_SAMSUNG_DVT:
+	case PIT_CONFIG_SAMSUNG_PVT:
+	case PIT_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/pit/romstage.c b/src/mainboard/google/pit/romstage.c
new file mode 100644
index 0000000..08f19f5
--- /dev/null
+++ b/src/mainboard/google/pit/romstage.c
@@ -0,0 +1,191 @@
+/*
+ * 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 <arch/cache.h>
+#include <cpu/samsung/exynos5420/i2c.h>
+#include <cpu/samsung/exynos5420/clk.h>
+#include <cpu/samsung/exynos5420/cpu.h>
+#include <cpu/samsung/exynos5420/dmc.h>
+#include <cpu/samsung/exynos5420/gpio.h>
+#include <cpu/samsung/exynos5420/setup.h>
+#include <cpu/samsung/exynos5420/periph.h>
+#include <cpu/samsung/exynos5420/power.h>
+#include <cpu/samsung/exynos5420/wakeup.h>
+#include <console/console.h>
+#include <arch/stages.h>
+
+#include <drivers/maxim/max77686/max77686.h>
+#include <device/i2c.h>
+
+#include "exynos5420.h"
+
+#define PMIC_BUS	0
+#define MMC0_GPIO_PIN	(58)
+
+static void setup_power(void)
+{
+	int error = 0;
+
+	power_init();
+
+	/* Initialize I2C bus to configure PMIC. */
+	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_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_config(PERIPH_ID_SDMMC0, PINMUX_FLAG_8BIT_MODE);
+
+	/* MMC2: Removable, 4 bit mode, no GPIO. */
+	clock_set_mshci(PERIPH_ID_SDMMC2);
+	exynos_pinmux_config(PERIPH_ID_SDMMC2, 0);
+}
+
+static void setup_graphics(void)
+{
+	exynos_pinmux_config(PERIPH_ID_DPHPD, 0);
+}
+
+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: 0x%x\n",
+	       mem->mem_manuf,
+	       mem->mem_type,
+	       mem->mpll_mdiv,
+	       mem->frequency_mhz);
+
+	/* FIXME Currently memory initialization with mem_reset on normal boot
+	 * will cause resume to fail (even if we don't do mem_reset on resume),
+	 * and the workaround is to temporarily always enable "is_resume".
+	 * This should be removed when the root cause of resume issue is found.
+	 */
+	is_resume = 1;
+
+	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();
+
+	if (!is_resume) {
+		console_init();
+		setup_power();
+	}
+
+	setup_memory(mem, is_resume);
+
+	if (is_resume) {
+		wakeup();
+	}
+
+	setup_storage();
+	setup_gpio();
+	setup_graphics();
+
+	/* Set SPI (primary CBFS media) clock to 50MHz. */
+	clock_set_rate(PERIPH_ID_SPI1, 50000000);
+
+	entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/coreboot_ram");
+	stage_exit(entry);
+}
diff --git a/src/mainboard/google/pit/wakeup.c b/src/mainboard/google/pit/wakeup.c
new file mode 100644
index 0000000..a82b632
--- /dev/null
+++ b/src/mainboard/google/pit/wakeup.c
@@ -0,0 +1,29 @@
+/*
+ * 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 <cpu/samsung/exynos5420/gpio.h>
+#include <cpu/samsung/exynos5420/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);
+}
+



More information about the coreboot-gerrit mailing list