Patrick Georgi (pgeorgi@google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16885
-gerrit
commit 65692da37ff59603a2b679fc4137486a6c0a14a8 Author: Julius Werner jwerner@chromium.org Date: Mon Oct 3 12:52:55 2016 -0700
ec/google/chromeec: Add minimum delay between SPI CS assertions
Some Chrome OS ECs require a small amount of time after a SPI transaction to reset their controllers before they can service the next CS assertion. The kernel and depthcharge have always enforced a 200us minimum delay for this... coreboot should've done the same.
BRANCH=gru BUG=chrome-os-partner:58046 TEST=Booted Kevin in recovery mode, confirmed that recovery events got logged with correct timestamps in eventlog.
Change-Id: I32ec343f3293ac93729d3e6e2f43d7605a396cdb Signed-off-by: Patrick Georgi pgeorgi@chromium.org Original-Commit-Id: b9e4696533d4318ae7c8715b71ab963d8897c16c Original-Change-Id: I6a7baf7859d5d50e299495d118e7890dcaa2c1b0 Original-Signed-off-by: Julius Werner jwerner@chromium.org Original-Reviewed-on: https://chromium-review.googlesource.com/392206 Original-Tested-by: Shawn N shawnn@chromium.org Original-Reviewed-by: Shawn N shawnn@chromium.org --- src/ec/google/chromeec/ec_spi.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/src/ec/google/chromeec/ec_spi.c b/src/ec/google/chromeec/ec_spi.c index e93d038..a0049c6 100644 --- a/src/ec/google/chromeec/ec_spi.c +++ b/src/ec/google/chromeec/ec_spi.c @@ -20,6 +20,11 @@ #include <spi-generic.h> #include <timer.h>
+/* This is assuming that this driver is not used on x86. If that changes, this + might need to become a CAR_GLOBAL or maybe even more complicated. */ +static struct stopwatch cs_cooldown_sw; +static const long cs_cooldown_us = 200; + static const uint8_t EcFramingByte = 0xec;
#define PROTO3_MAX_PACKET_SIZE 268 @@ -44,7 +49,10 @@ void *crosec_get_buffer(size_t size, int req) static int crosec_spi_io(size_t req_size, size_t resp_size, void *context) { struct spi_slave *slave = (struct spi_slave *)context; + int ret = 0;
+ while (!stopwatch_expired(&cs_cooldown_sw)) + /* Wait minimum delay between CS assertions. */; spi_claim_bus(slave);
/* Allow EC to ramp up clock after being awaken. @@ -53,8 +61,8 @@ static int crosec_spi_io(size_t req_size, size_t resp_size, void *context)
if (spi_xfer(slave, req_buf, req_size, NULL, 0)) { printk(BIOS_ERR, "%s: Failed to send request.\n", __func__); - spi_release_bus(slave); - return -1; + ret = -1; + goto out; }
uint8_t byte; @@ -65,8 +73,8 @@ static int crosec_spi_io(size_t req_size, size_t resp_size, void *context) if (spi_xfer(slave, NULL, 0, &byte, sizeof(byte))) { printk(BIOS_ERR, "%s: Failed to receive byte.\n", __func__); - spi_release_bus(slave); - return -1; + ret = -1; + goto out; } if (byte == EcFramingByte) break; @@ -75,28 +83,30 @@ static int crosec_spi_io(size_t req_size, size_t resp_size, void *context) printk(BIOS_ERR, "%s: Timeout waiting for framing byte.\n", __func__); - spi_release_bus(slave); - return -1; + ret = -1; + goto out; } }
if (spi_xfer(slave, NULL, 0, resp_buf, resp_size)) { printk(BIOS_ERR, "%s: Failed to receive response.\n", __func__); - spi_release_bus(slave); - return -1; + ret = -1; }
+out: spi_release_bus(slave); - - return 0; + stopwatch_init_usecs_expire(&cs_cooldown_sw, cs_cooldown_us); + return ret; }
int google_chromeec_command(struct chromeec_command *cec_command) { static struct spi_slave *slave = NULL; - if (!slave) + if (!slave) { slave = spi_setup_slave(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, CONFIG_EC_GOOGLE_CHROMEEC_SPI_CHIP); + stopwatch_init(&cs_cooldown_sw); + } return crosec_command_proto(cec_command, crosec_spi_io, slave); }