Gabe Black (gabeblack(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3719
-gerrit
commit fbe1bf2d5a8553e509b8a55937732a6b62137e10
Author: Ronald G. Minnich <rminnich(a)google.com>
Date: Wed Jun 26 17:28:52 2013 -0700
PIT: add panel to the list of things to be powered up by the PMIC
This appears to be needed, though we have no way to test yet.
Change-Id: I39033581011e056258193f2cdff78814361a8d55
Signed-off-by: Ronald G. Minnich <rminnich(a)google.com>
Signed-off-by: Gabe Black <gabeblack(a)chromium.org>
---
src/mainboard/google/pit/romstage.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/mainboard/google/pit/romstage.c b/src/mainboard/google/pit/romstage.c
index 30c8aeb..f123253 100644
--- a/src/mainboard/google/pit/romstage.c
+++ b/src/mainboard/google/pit/romstage.c
@@ -71,7 +71,8 @@ struct pmic_write pmic_writes[] =
MAX77802_BUCK_TYPE2_IGNORE_PWRREQ },
{ 0, MAX77802_REG_PMIC_BUCK6DVS1, MAX77802_BUCK6DVS1_1V },
{ 1, MAX77802_REG_PMIC_BUCK6CTRL, MAX77802_BUCK_TYPE1_ON |
- MAX77802_BUCK_TYPE1_IGNORE_PWRREQ }
+ MAX77802_BUCK_TYPE1_IGNORE_PWRREQ },
+ { 1, MAX77802_REG_PMIC_LDO35CTRL1, MAX77802_LDO35CTRL1_1_2V },
};
static void setup_power(int is_resume)
Gabe Black (gabeblack(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3717
-gerrit
commit b913b3327adf5b9bbcd0679f82427cbd47c21879
Author: Gabe Black <gabeblack(a)google.com>
Date: Fri Jun 28 14:27:16 2013 -0700
pit: Replace the tps65090 functions and adjust the hotplug detect line.
The functions which manipulated the tps65090 were removed a while ago because
it isn't accessible directly from the AP, it's on an I2C bus that has to be
accessed by the EC on our behalf. Now that that capability has been added, we
can rewrite the small portion of the the tps65090 we actually used but using
the EC passthrough commands.
Also, we should not be configuring the hardware display port hotplug detect
line since we're using it as a GPIO for other purposes. The GPIO we're using
instead defaults to being an input, but to be safe we should probably
explicitly configure it as one anyway.
Change-Id: I7f8a8a767e3cccb813513940a5feceea482982f5
Signed-off-by: Gabe Black <gabeblack(a)chromium.org>
---
src/mainboard/google/pit/mainboard.c | 39 ++++++++++++++++++++++++++++++++----
1 file changed, 35 insertions(+), 4 deletions(-)
diff --git a/src/mainboard/google/pit/mainboard.c b/src/mainboard/google/pit/mainboard.c
index 64783ad..67d3b5d 100644
--- a/src/mainboard/google/pit/mainboard.c
+++ b/src/mainboard/google/pit/mainboard.c
@@ -34,6 +34,7 @@
#include <cpu/samsung/exynos5420/power.h>
#include <cpu/samsung/exynos5420/i2c.h>
#include <cpu/samsung/exynos5420/dp-core.h>
+#include <ec/google/chromeec/ec.h>
#include "exynos5420.h"
@@ -57,8 +58,6 @@ static enum exynos5_gpio_pin bl_en = GPIO_X22; /* 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);
@@ -68,6 +67,8 @@ static void exynos_dp_bridge_setup(void)
gpio_set_pull(dp_rst_l, GPIO_PULL_NONE);
udelay(10);
gpio_set_value(dp_rst_l, 1);
+
+ gpio_cfg_pin(dp_hpd, GPIO_INPUT);
}
static void exynos_dp_bridge_init(void)
@@ -170,6 +171,35 @@ static void gpio_init(void)
exynos_pinmux_i2c10();
}
+enum {
+ FET_CTRL_WAIT = 3 << 2,
+ FET_CTRL_ADENFET = 1 << 1,
+ FET_CTRL_ENFET = 1 << 0
+};
+
+static void tps65090_thru_ec_fet_set(int index)
+{
+ uint8_t value = FET_CTRL_ADENFET | FET_CTRL_WAIT | FET_CTRL_ENFET;
+
+ if (google_chromeec_i2c_xfer(0x48, 0xe + index, 1, &value, 1, 0)) {
+ printk(BIOS_ERR,
+ "Error sending i2c pass through command to EC.\n");
+ return;
+ }
+}
+
+static void lcd_vdd(void)
+{
+ /* Enable FET6, lcd panel */
+ tps65090_thru_ec_fet_set(6);
+}
+
+static void backlight_vdd(void)
+{
+ /* Enable FET1, backlight */
+ tps65090_thru_ec_fet_set(1);
+}
+
/* this happens after cpu_init where exynos resources are set */
static void mainboard_init(device_t dev)
{
@@ -193,7 +223,7 @@ static void mainboard_init(device_t dev)
fb_addr = cbmem_find(CBMEM_ID_CONSOLE);
set_vbe_mode_info_valid(&edid, (uintptr_t)fb_addr);
- // XXX Turn on the LCD power here.
+ lcd_vdd();
// FIXME: should timeout
do {
@@ -204,6 +234,7 @@ static void mainboard_init(device_t dev)
for (dp_tries = 1; dp_tries <= MAX_DP_TRIES; dp_tries++) {
exynos_dp_bridge_init();
if (exynos_dp_hotplug()) {
+ printk(BIOS_ERR, "Hotplug detect failed.\n");
exynos_dp_reset();
continue;
}
@@ -213,7 +244,7 @@ static void mainboard_init(device_t dev)
udelay(LCD_T3_DELAY_MS * 1000);
- // XXX Turn on the backlight power here.
+ backlight_vdd();
backlight_pwm();
backlight_en();
/* if we're here, we're successful */
Gabe Black (gabeblack(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3742
-gerrit
commit 763c146c80b3370d616d4b20de9f2f1a9f164d79
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Tue May 21 07:49:11 2013 -0700
ec: Remove hardcoded GPI offset in EC SCI
With LynxPoint-LP the SCI GPE is no longer a GPIO
that is offset by 16. Remove the Add and fix up
the link definition so it is still accurate.
Change-Id: I091141183a09345b5ffe28365583e48019f9f5e5
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/ec/google/chromeec/acpi/ec.asl | 2 +-
src/mainboard/google/link/ec.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/ec/google/chromeec/acpi/ec.asl b/src/ec/google/chromeec/acpi/ec.asl
index 2fb8e79..cb196a7 100644
--- a/src/ec/google/chromeec/acpi/ec.asl
+++ b/src/ec/google/chromeec/acpi/ec.asl
@@ -27,7 +27,7 @@ Device (EC0)
{
Name (_HID, EISAID ("PNP0C09"))
Name (_UID, 1)
- Name (_GPE, Add(EC_SCI_GPI, 16))
+ Name (_GPE, EC_SCI_GPI)
Name (TOFS, EC_TEMP_SENSOR_OFFSET)
Name (TNOP, 0xFD) // Thermal sensor has no power
Name (TBAD, 0xFE) // Thermal sensor bad reading
diff --git a/src/mainboard/google/link/ec.h b/src/mainboard/google/link/ec.h
index 6133f97..0044347 100644
--- a/src/mainboard/google/link/ec.h
+++ b/src/mainboard/google/link/ec.h
@@ -22,7 +22,7 @@
#include <ec/google/chromeec/ec_commands.h>
-#define EC_SCI_GPI 7 /* GPIO7 is EC_SCI# */
+#define EC_SCI_GPI 23 /* GPIO7/GPE23 is EC_SCI# */
#define EC_SMI_GPI 8 /* GPIO8 is EC_SMI# */
#define LINK_EC_SCI_EVENTS \
Gabe Black (gabeblack(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3753
-gerrit
commit d3138296a23bfcfc1dc95b5da9ba34a723efa968
Author: Gabe Black <gabeblack(a)google.com>
Date: Sun Jun 30 05:56:26 2013 -0700
parade: Add a driver for the parade ps8625.
This driver is basically the same as the one in U-Boot but without the device
tree stuff. That driver is, in turn, a straightforward implementation of the
sequence of register writes described in the data sheet. Comments were added
in U-Boot which helpfully describe what the register writes are actually
doing and are kept.
Change-Id: I64ba6b373478853bb2120f0553a43de901170d02
Signed-off-by: Gabe Black <gabeblack(a)google.com>
---
src/drivers/Kconfig | 1 +
src/drivers/Makefile.inc | 1 +
src/drivers/parade/Kconfig | 20 ++++
src/drivers/parade/Makefile.inc | 20 ++++
src/drivers/parade/ps8625/Kconfig | 24 +++++
src/drivers/parade/ps8625/Makefile.inc | 20 ++++
src/drivers/parade/ps8625/ps8625.c | 161 +++++++++++++++++++++++++++++++++
src/drivers/parade/ps8625/ps8625.h | 25 +++++
8 files changed, 272 insertions(+)
diff --git a/src/drivers/Kconfig b/src/drivers/Kconfig
index 386508a..c4378b1 100644
--- a/src/drivers/Kconfig
+++ b/src/drivers/Kconfig
@@ -27,6 +27,7 @@ source src/drivers/ics/Kconfig
source src/drivers/ipmi/Kconfig
source src/drivers/maxim/Kconfig
source src/drivers/oxford/Kconfig
+source src/drivers/parade/Kconfig
if PC80_SYSTEM
source src/drivers/pc80/Kconfig
endif
diff --git a/src/drivers/Makefile.inc b/src/drivers/Makefile.inc
index f4fe146..9a1be72 100644
--- a/src/drivers/Makefile.inc
+++ b/src/drivers/Makefile.inc
@@ -24,6 +24,7 @@ subdirs-y += generic
subdirs-y += i2c
subdirs-y += maxim
subdirs-y += oxford
+subdirs-y += parade
subdirs-y += realtek
subdirs-y += sil
subdirs-y += trident
diff --git a/src/drivers/parade/Kconfig b/src/drivers/parade/Kconfig
new file mode 100644
index 0000000..b4b2ac2
--- /dev/null
+++ b/src/drivers/parade/Kconfig
@@ -0,0 +1,20 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 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
+##
+
+source src/drivers/parade/ps8625/Kconfig
diff --git a/src/drivers/parade/Makefile.inc b/src/drivers/parade/Makefile.inc
new file mode 100644
index 0000000..efbd11d
--- /dev/null
+++ b/src/drivers/parade/Makefile.inc
@@ -0,0 +1,20 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 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
+##
+
+subdirs-$(CONFIG_DRIVER_PARADE_PS8625) += ps8625/
diff --git a/src/drivers/parade/ps8625/Kconfig b/src/drivers/parade/ps8625/Kconfig
new file mode 100644
index 0000000..41aa92b
--- /dev/null
+++ b/src/drivers/parade/ps8625/Kconfig
@@ -0,0 +1,24 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 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
+##
+
+config DRIVER_PARADE_PS8625
+ bool
+ default n
+ help
+ Parade ps8625 display port to lvds bridge
diff --git a/src/drivers/parade/ps8625/Makefile.inc b/src/drivers/parade/ps8625/Makefile.inc
new file mode 100644
index 0000000..ef546ba
--- /dev/null
+++ b/src/drivers/parade/ps8625/Makefile.inc
@@ -0,0 +1,20 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 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
+##
+
+ramstage-$(CONFIG_DRIVER_PARADE_PS8625) += ps8625.c
diff --git a/src/drivers/parade/ps8625/ps8625.c b/src/drivers/parade/ps8625/ps8625.c
new file mode 100644
index 0000000..6cbe3b7
--- /dev/null
+++ b/src/drivers/parade/ps8625/ps8625.c
@@ -0,0 +1,161 @@
+/*
+ * 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 "ps8625.h"
+
+#include <device/i2c.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+struct parade_write {
+ uint8_t offset;
+ uint8_t reg;
+ uint8_t val;
+};
+
+static const struct parade_write parade_writes[] = {
+ { 0x02, 0xa1, 0x01 }, /* HPD low */
+ /*
+ * SW setting
+ * [1:0] SW output 1.2V voltage is lower to 96%
+ */
+ { 0x04, 0x14, 0x01 },
+ /*
+ * RCO SS setting
+ * [5:4] = b01 0.5%, b10 1%, b11 1.5%
+ */
+ { 0x04, 0xe3, 0x20 },
+ { 0x04, 0xe2, 0x80 }, /* [7] RCO SS enable */
+ /*
+ * RPHY Setting
+ * [3:2] CDR tune wait cycle before
+ * measure for fine tune b00: 1us,
+ * 01: 0.5us, 10:2us, 11:4us.
+ */
+ { 0x04, 0x8a, 0x0c },
+ { 0x04, 0x89, 0x08 }, /* [3] RFD always on */
+ /*
+ * CTN lock in/out:
+ * 20000ppm/80000ppm. Lock out 2
+ * times.
+ */
+ { 0x04, 0x71, 0x2d },
+ /*
+ * 2.7G CDR settings
+ * NOF=40LSB for HBR CDR setting
+ */
+ { 0x04, 0x7d, 0x07 },
+ { 0x04, 0x7b, 0x00 }, /* [1:0] Fmin=+4bands */
+ { 0x04, 0x7a, 0xfd }, /* [7:5] DCO_FTRNG=+-40% */
+ /*
+ * 1.62G CDR settings
+ * [5:2]NOF=64LSB [1:0]DCO scale is 2/5
+ */
+ { 0x04, 0xc0, 0x12 },
+ { 0x04, 0xc1, 0x92 }, /* Gitune=-37% */
+ { 0x04, 0xc2, 0x1c }, /* Fbstep=100% */
+ { 0x04, 0x32, 0x80 }, /* [7] LOS signal disable */
+ /*
+ * RPIO Setting
+ * [7:4] LVDS driver bias current :
+ * 75% (250mV swing)
+ */
+ { 0x04, 0x00, 0xb0 },
+ /*
+ * [7:6] Right-bar GPIO output strength is 8mA
+ */
+ { 0x04, 0x15, 0x40 },
+ /* EQ Training State Machine Setting */
+ { 0x04, 0x54, 0x10 }, /* RCO calibration start */
+ /* [4:0] MAX_LANE_COUNT set to one lane */
+ { 0x01, 0x02, 0x81 },
+ /* [4:0] LANE_COUNT_SET set to one lane */
+ { 0x01, 0x21, 0x81 },
+ { 0x00, 0x52, 0x20 },
+ { 0x00, 0xf1, 0x03 }, /* HPD CP toggle enable */
+ { 0x00, 0x62, 0x41 },
+ /* Counter number, add 1ms counter delay */
+ { 0x00, 0xf6, 0x01 },
+ /*
+ * [6]PWM function control by
+ * DPCD0040f[7], default is PWM
+ * block always works.
+ */
+ { 0x00, 0x77, 0x06 },
+ /*
+ * 04h Adjust VTotal tolerance to
+ * fix the 30Hz no display issue
+ */
+ { 0x00, 0x4c, 0x04 },
+ /* DPCD00400='h00, Parade OUI = 'h001cf8 */
+ { 0x01, 0xc0, 0x00 },
+ { 0x01, 0xc1, 0x1c }, /* DPCD00401='h1c */
+ { 0x01, 0xc2, 0xf8 }, /* DPCD00402='hf8 */
+ /*
+ * DPCD403~408 = ASCII code
+ * D2SLV5='h4432534c5635
+ */
+ { 0x01, 0xc3, 0x44 },
+ { 0x01, 0xc4, 0x32 }, /* DPCD404 */
+ { 0x01, 0xc5, 0x53 }, /* DPCD405 */
+ { 0x01, 0xc6, 0x4c }, /* DPCD406 */
+ { 0x01, 0xc7, 0x56 }, /* DPCD407 */
+ { 0x01, 0xc8, 0x35 }, /* DPCD408 */
+ /*
+ * DPCD40A, Initial Code major revision
+ * '01'
+ */
+ { 0x01, 0xca, 0x01 },
+ /* DPCD40B, Initial Code minor revision '05' */
+ { 0x01, 0xcb, 0x05 },
+ /* DPCD720, Select internal PWM */
+ { 0x01, 0xa5, 0xa0 },
+ /*
+ * FFh for 100% PWM of brightness, 0h for 0%
+ * brightness
+ */
+ { 0x01, 0xa7, 0xff },
+ /*
+ * Set LVDS output as 6bit-VESA mapping,
+ * single LVDS channel
+ */
+ { 0x01, 0xcc, 0x13 },
+ /* Enable SSC set by register */
+ { 0x02, 0xb1, 0x20 },
+ /*
+ * Set SSC enabled and +/-1% central
+ * spreading
+ */
+ { 0x04, 0x10, 0x16 },
+ /* MPU Clock source: LC => RCO */
+ { 0x04, 0x59, 0x60 },
+ { 0x04, 0x54, 0x14 }, /* LC -> RCO */
+ { 0x02, 0xa1, 0x91 } /* HPD high */
+};
+
+void parade_ps8625_bridge_setup(unsigned bus, unsigned chip_base)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(parade_writes); i++) {
+ const struct parade_write *w = ¶de_writes[i];
+ i2c_write(bus, chip_base + w->offset, w->reg, sizeof(w->reg),
+ &w->val, sizeof(w->val));
+ }
+}
diff --git a/src/drivers/parade/ps8625/ps8625.h b/src/drivers/parade/ps8625/ps8625.h
new file mode 100644
index 0000000..2ef7577
--- /dev/null
+++ b/src/drivers/parade/ps8625/ps8625.h
@@ -0,0 +1,25 @@
+/*
+ * 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
+ */
+
+#ifndef __PS8625_H__
+#define __PS8625_H__
+
+void parade_ps8625_bridge_setup(unsigned bus, unsigned chip_base);
+
+#endif
Gabe Black (gabeblack(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3744
-gerrit
commit 58f979db54b966392b95b1e2716f419e9c6835d5
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Tue Jun 4 10:03:34 2013 -0700
ec: Add romstage function for checking and rebooting EC
Now that we are executing VbInit() in coreboot we can end up
in a situation where the recovery reason is consumed during
VbInit (end of romstage) and then the EC is rebooted to RO
during ramstage EC init, thereby losing the recovery reason.
Two possiblities are to remove the EC check+reboot from ramstage
and let it happen in depthcharge. This however means that the
system has to boot all the way into depthcharge and then reboot
the EC and the system again.
Instead if we do a check in romstage before VbInit() is called
then we can reboot the EC into RO early and avoid booting all
the way to depthcharge first.
This change adds a ramstage version the EC init function and
calls it from the shared romstage code immediately after the
PCH decode windows are setup.
Change-Id: I30d2a0c7131b8e4ec30c63eea36944ec111a8fba
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/cpu/intel/haswell/romstage.c | 8 ++++++++
src/ec/google/chromeec/ec.c | 39 +++++++++++++++++++++++++++++++++++++--
src/ec/google/chromeec/ec.h | 1 +
3 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/src/cpu/intel/haswell/romstage.c b/src/cpu/intel/haswell/romstage.c
index 8196273..0cef888 100644
--- a/src/cpu/intel/haswell/romstage.c
+++ b/src/cpu/intel/haswell/romstage.c
@@ -38,6 +38,9 @@
#if CONFIG_CHROMEOS
#include <vendorcode/google/chromeos/chromeos.h>
#endif
+#if CONFIG_EC_GOOGLE_CHROMEEC
+#include <ec/google/chromeec/ec.h>
+#endif
#include "haswell.h"
#include "northbridge/intel/haswell/haswell.h"
#include "northbridge/intel/haswell/raminit.h"
@@ -216,6 +219,11 @@ void romstage_common(const struct romstage_params *params)
wake_from_s3 = early_pch_init(params->gpio_map, params->rcba_config);
+#if CONFIG_EC_GOOGLE_CHROMEEC
+ /* Ensure the EC is in the right mode for recovery */
+ google_chromeec_early_init();
+#endif
+
/* Halt if there was a built in self test failure */
report_bist_failure(params->bist);
diff --git a/src/ec/google/chromeec/ec.c b/src/ec/google/chromeec/ec.c
index d94338f..9b848c0 100644
--- a/src/ec/google/chromeec/ec.c
+++ b/src/ec/google/chromeec/ec.c
@@ -21,12 +21,12 @@
#include <console/console.h>
#include <arch/io.h>
#include <delay.h>
+#include <arch/hlt.h>
+#include <reset.h>
#ifndef __PRE_RAM__
#include <elog.h>
#include <stdlib.h>
#include <string.h>
-#include <reset.h>
-#include <arch/hlt.h>
#include "chip.h"
#endif
#include "ec.h"
@@ -99,6 +99,41 @@ u32 google_chromeec_get_events_b(void)
return google_chromeec_get_mask(EC_CMD_HOST_EVENT_GET_B);
}
+#ifndef __SMM__
+/* Check for recovery mode and ensure EC is in RO */
+void google_chromeec_early_init(void)
+{
+ struct chromeec_command cec_cmd;
+ struct ec_response_get_version cec_resp = {{0}};
+
+ cec_cmd.cmd_code = EC_CMD_GET_VERSION;
+ cec_cmd.cmd_version = 0;
+ cec_cmd.cmd_data_out = &cec_resp;
+ cec_cmd.cmd_size_in = 0;
+ cec_cmd.cmd_size_out = sizeof(cec_resp);
+ google_chromeec_command(&cec_cmd);
+
+ if (cec_cmd.cmd_code ||
+ (recovery_mode_enabled() &&
+ (cec_resp.current_image != EC_IMAGE_RO))) {
+ struct ec_params_reboot_ec reboot_ec;
+ /* Reboot the EC and make it come back in RO mode */
+ reboot_ec.cmd = EC_REBOOT_COLD;
+ reboot_ec.flags = 0;
+ cec_cmd.cmd_code = EC_CMD_REBOOT_EC;
+ cec_cmd.cmd_version = 0;
+ cec_cmd.cmd_data_in = &reboot_ec;
+ cec_cmd.cmd_size_in = sizeof(reboot_ec);
+ cec_cmd.cmd_size_out = 0; /* ignore response, if any */
+ printk(BIOS_DEBUG, "Rebooting with EC in RO mode:\n");
+ google_chromeec_command(&cec_cmd);
+ udelay(1000);
+ hard_reset();
+ hlt();
+ }
+}
+#endif /* ! __SMM__ */
+
#ifndef __PRE_RAM__
static int google_chromeec_set_mask(u8 type, u32 mask)
diff --git a/src/ec/google/chromeec/ec.h b/src/ec/google/chromeec/ec.h
index 3eb555c..7679a8b 100644
--- a/src/ec/google/chromeec/ec.h
+++ b/src/ec/google/chromeec/ec.h
@@ -33,6 +33,7 @@ u16 google_chromeec_get_board_version(void);
void google_chromeec_init(void);
#endif
+void google_chromeec_early_init(void);
uint8_t google_chromeec_calc_checksum(const uint8_t *data, int size);
u32 google_chromeec_get_events_b(void);
int google_chromeec_kbbacklight(int percent);