Arthur Heymans (arthur(a)aheymans.xyz) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17659
-gerrit
commit adbed7c6c7ee30da59bfe29068bf31d6c2f5ba4c
Author: Arthur Heymans <arthur(a)aheymans.xyz>
Date: Wed Nov 30 18:40:38 2016 +0100
nb/x4x: Fix raminit unconditionally resetting
The raminit only succeeds when it starts from a cold boot.
To achieve this it unconditionally did a cold reset.
Now it detects whether it underwent a hot reset (bit 8 of
MCHBAR32(0xf14)) before issuing a cold reset to make raminit work.
It also adds a 2s delay before reset because some disk drives
expect a warm reboot when the OS wants to reboot and therefore are not
shut down properly / in time. If the drive is unexpectedly powered off
which happens during a cold reset, it can cause data loss. Giving the
drive 2 extra seconds can work around this issue.
(A proper fix would be to fix the raminit such that it works on a hot reset)
Change-Id: I6063dd6aed908558155d2523f35d7241ff1f4fde
Signed-off-by: Arthur Heymans <arthur(a)aheymans.xyz>
---
src/northbridge/intel/x4x/raminit_ddr2.c | 22 +++++++++++++++++++---
src/northbridge/intel/x4x/x4x.h | 4 +---
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c
index b3ee34a..ff56a27 100644
--- a/src/northbridge/intel/x4x/raminit_ddr2.c
+++ b/src/northbridge/intel/x4x/raminit_ddr2.c
@@ -258,10 +258,19 @@ static void checkreset_ddr2(struct sysinfo *s)
{
u8 pmcon2;
u8 reset = 0;
+ u32 pmir;
+
+ pmir = pci_read_config32(PCI_DEV(0, 0x1f, 0), 0xac);
+
+ if ((MCHBAR32(0xf14) & (1 << 8))) {
+ printk(BIOS_DEBUG, "Waiting for disks to timeout...\n");
+ mdelay(2000);
+ reset = 1;
+ }
pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2);
- if (!(pmcon2 & 0x80)) {
- pmcon2 |= 0x80;
+ if (pmcon2 & 0x80) {
+ pmcon2 &= ~0x80;
pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
reset = 1;
@@ -273,10 +282,17 @@ static void checkreset_ddr2(struct sysinfo *s)
}
if (reset) {
printk(BIOS_DEBUG, "Reset...\n");
+ /* Do a global reset. only useful on ICH10 */
+ pmir |= (1 << 20);
+ pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xac, pmir);
outb(0xe, 0xcf9);
asm ("hlt");
}
- pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2 | 0x80);
+ pmir &= ~(1 << 20);
+ pmcon |= 0x80;
+ pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2);
+ pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xac, pmir);
+
}
static void setioclk_ddr2(struct sysinfo *s)
diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h
index e4eb8dd..ab9ba80 100644
--- a/src/northbridge/intel/x4x/x4x.h
+++ b/src/northbridge/intel/x4x/x4x.h
@@ -97,9 +97,7 @@
#define CLKCFG_MEMCLK_MASK (7 << CLKCFG_MEMCLK_SHIFT)
#define CLKCFG_UPDATE (1 << 12)
-#define SSKPD_MCHBAR 0x0c1c
-#define SSKPD_CLK_SHIFT 0
-#define SSKPD_CLK_MASK (7 << SSKPD_CLK_SHIFT)
+#define SSKPD_MCHBAR 0x0c20 /* 64bit */
/*
* DMIBAR
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17628
-gerrit
commit bdcfa38cf323855a3f4e9c5bb6e0e28039146c5f
Author: Julius Werner <jwerner(a)chromium.org>
Date: Mon Nov 21 20:14:18 2016 -0800
google/gru: Power-cycle USB ports in developer/recovery modes
Gru only uses USB 2.0 in firmware to avoid all the madness associated
with Type-C port orientation and USB 3.0 tuning. We do this by isolating
the SuperSpeed lines in the Type-C PHY so it looks like they aren't
connected to the device.
Unfortunately, some devices seem to already get "locked" into SuperSpeed
mode as soon as they detect Rx terminations once, and can never snap out
again on their own. Since the terminations are already connected during
power-on reset we cannot disable them fast enough to prevent this, and
the only solution we found to date is to power-cycle the whole USB port.
Now, Gru's USB port power is controlled by the EC, and unfortunately we
have no direct host command to control it. We do however have a command
to force a certain USB PD "role", and forcing our host into "sink" mode
makes it stop sourcing power to the port. So for lack of a saner
solution we'll use this to work around our problem.
BRANCH=gru
BUG=chrome-os-partner:59346
TEST=Booted Kevin in recovery mode, confirmed that my "problem stick"
gets detected immediately (whereas previously I had to unplug/replug
it). Booted Kevin to OS in both developer and normal mode and confirmed
that USB still seems to work.
Change-Id: Ib3cceba9baa170b13f01bd5c01bd413be5b441ba
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: cd695eda33299e50362f1096c46f2f5260c49036
Original-Change-Id: I2db3d6d3710d18a8b8030e94eb1ac2e931f22638
Original-Signed-off-by: Julius Werner <jwerner(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/413031
---
src/mainboard/google/gru/mainboard.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/src/mainboard/google/gru/mainboard.c b/src/mainboard/google/gru/mainboard.c
index 7e360e7..dd986c4 100644
--- a/src/mainboard/google/gru/mainboard.c
+++ b/src/mainboard/google/gru/mainboard.c
@@ -15,9 +15,11 @@
*/
#include <boardid.h>
+#include <console/console.h>
#include <delay.h>
#include <device/device.h>
#include <device/i2c.h>
+#include <ec/google/chromeec/ec.h>
#include <gpio.h>
#include <soc/bl31_plat_params.h>
#include <soc/clock.h>
@@ -230,6 +232,17 @@ static void configure_display(void)
gpio_output(GPIO(4, D, 3), 1); /* CPU3_EDP_VDDEN for P3.3V_DISP */
}
+static void usb_power_cycle(int port)
+{
+ if (google_chromeec_set_usb_pd_role(port, USB_PD_CTRL_ROLE_FORCE_SINK))
+ printk(BIOS_ERR, "ERROR: Cannot force USB%d PD sink\n", port);
+
+ mdelay(10); /* Make sure USB stick is fully depowered. */
+
+ if (google_chromeec_set_usb_pd_role(port, USB_PD_CTRL_ROLE_TOGGLE_ON))
+ printk(BIOS_ERR, "ERROR: Cannot restore USB%d PD mode\n", port);
+}
+
static void setup_usb(void)
{
/* A few magic PHY tuning values that improve eye diagram amplitude
@@ -269,6 +282,17 @@ static void setup_usb(void)
setup_usb_otg0();
setup_usb_otg1();
+
+ /*
+ * Need to power-cycle USB ports for use in firmware, since some devices
+ * can't fall back to USB 2.0 after they saw SuperSpeed terminations.
+ * This takes about a dozen milliseconds, so only do it in boot modes
+ * that have firmware UI (which one could select USB boot from).
+ */
+ if (display_init_required()) {
+ usb_power_cycle(0);
+ usb_power_cycle(1);
+ }
}
static void mainboard_init(device_t dev)
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17627
-gerrit
commit 4f53f36f23c2c7d926bfa61d72a9e2956ad8c4e1
Author: Julius Werner <jwerner(a)chromium.org>
Date: Mon Nov 21 20:14:07 2016 -0800
google/chromeec: Add command to control USB PD role
Normally firmware should have no business messing with the USB PD role
(source/sink/whatever) in the EC. But, as so often happens, ugly issues
crop up that require weird work-arounds, and before you know it you need
to do this for some reason that only makes sense in context. I do now,
so add this function to send the necessary host command in the simplest
possible fashion.
BRANCH=gru
BUG=chrome-os-partner:59346
TEST=Used it in a follow-up patch.
Change-Id: I07d40feafd6a8387a633d6384efb205baf578d76
Signed-off-by: Patrick Georgi <pgeorgi(a)chromium.org>
Original-Commit-Id: 8b71767caccff9b77d458182ce8066f7abf6321c
Original-Change-Id: Ie8d0be98f6b703f4db062fe2f728cd2588347202
Original-Signed-off-by: Julius Werner <jwerner(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/413030
Original-Reviewed-by: Vincent Palatin <vpalatin(a)chromium.org>
---
src/ec/google/chromeec/ec.c | 22 ++++++++++++++++++++++
src/ec/google/chromeec/ec.h | 1 +
2 files changed, 23 insertions(+)
diff --git a/src/ec/google/chromeec/ec.c b/src/ec/google/chromeec/ec.c
index 1308c3d..d0648f7 100644
--- a/src/ec/google/chromeec/ec.c
+++ b/src/ec/google/chromeec/ec.c
@@ -497,6 +497,28 @@ int google_chromeec_set_usb_charge_mode(u8 port_id, enum usb_charge_mode mode)
return google_chromeec_command(&cmd);
}
+int google_chromeec_set_usb_pd_role(u8 port, enum usb_pd_control_role role)
+{
+ struct ec_params_usb_pd_control req = {
+ .port = port,
+ .role = role,
+ .mux = USB_PD_CTRL_MUX_NO_CHANGE,
+ .swap = USB_PD_CTRL_SWAP_NONE,
+ };
+ struct ec_response_usb_pd_control rsp;
+ struct chromeec_command cmd = {
+ .cmd_code = EC_CMD_USB_PD_CONTROL,
+ .cmd_version = 0,
+ .cmd_data_in = &req,
+ .cmd_size_in = sizeof(req),
+ .cmd_data_out = &rsp,
+ .cmd_size_out = sizeof(rsp),
+ .cmd_dev_index = 0,
+ };
+
+ return google_chromeec_command(&cmd);
+}
+
#ifndef __SMM__
static
diff --git a/src/ec/google/chromeec/ec.h b/src/ec/google/chromeec/ec.h
index f765fe4..71cea7e 100644
--- a/src/ec/google/chromeec/ec.h
+++ b/src/ec/google/chromeec/ec.h
@@ -76,6 +76,7 @@ enum usb_charge_mode {
USB_CHARGE_MODE_DOWNSTREAM_1500MA,
};
int google_chromeec_set_usb_charge_mode(u8 port_id, enum usb_charge_mode mode);
+int google_chromeec_set_usb_pd_role(u8 port, enum usb_pd_control_role role);
/* internal structure to send a command to the EC and wait for response. */
struct chromeec_command {