diff options
Diffstat (limited to 'src/ec/google/chromeec')
-rw-r--r-- | src/ec/google/chromeec/ec_spi.c | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/src/ec/google/chromeec/ec_spi.c b/src/ec/google/chromeec/ec_spi.c index d6b7b0c4ea..f1bdd3caaa 100644 --- a/src/ec/google/chromeec/ec_spi.c +++ b/src/ec/google/chromeec/ec_spi.c @@ -18,28 +18,60 @@ */ #include <console/console.h> -#include <spi-generic.h> - #include "ec.h" #include "ec_commands.h" +#include <spi-generic.h> +#include <timer.h> + +static const uint8_t EcFramingByte = 0xec; static int crosec_spi_io(uint8_t *write_bytes, size_t write_size, uint8_t *read_bytes, size_t read_size, void *context) { struct spi_slave *slave = (struct spi_slave *)context; - int rv; spi_claim_bus(slave); - rv = spi_xfer(slave, write_bytes, write_size, read_bytes, - read_size); - spi_release_bus(slave); - if (rv != 0) { - printk(BIOS_ERR, "%s: Cannot complete SPI I/O\n", __func__); + if (spi_xfer(slave, write_bytes, write_size, NULL, 0)) { + printk(BIOS_ERR, "%s: Failed to send request.\n", __func__); + spi_release_bus(slave); return -1; } + uint8_t byte; + struct mono_time start; + struct rela_time rt; + timer_monotonic_get(&start); + while (1) { + 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; + } + if (byte == EcFramingByte) + break; + + // Wait 1s for a framing byte. + rt = current_time_from(&start); + if (rela_time_in_microseconds(&rt) > 1000 * 1000) { + printk(BIOS_ERR, + "%s: Timeout waiting for framing byte.\n", + __func__); + spi_release_bus(slave); + return -1; + } + } + + if (spi_xfer(slave, NULL, 0, read_bytes, read_size)) { + printk(BIOS_ERR, "%s: Failed to receive response.\n", __func__); + spi_release_bus(slave); + return -1; + } + + spi_release_bus(slave); + return 0; } |