summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2014-06-10 21:13:43 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-06-12 01:37:49 +0000
commit4670e537169b2ed4befa375cbd9c13a2bd8c39c7 (patch)
tree113d27315333c85b6e351be5ec9d35966a228076
parentb170291c3668807ed923748de2ebc7e707856f92 (diff)
downloadchrome-ec-4670e537169b2ed4befa375cbd9c13a2bd8c39c7.tar.gz
Keyborg: improve error recovery
Previously an error in master-slave communication often leaves the chips in bad states and thus prevents further operation. Improve this by: - Making master_slave_sync() state-less. - Restoring SPI_NSS and disabling DMA on error. BUG=None TEST=Inject errors on master side and slave side. Check the subsequent operations succeed. BRANCH=None Change-Id: Ief8b5b0df3d4be6319957bb1f9daf93e0e9b5d92 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/203337 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/keyborg/master_slave.c16
-rw-r--r--board/keyborg/spi_comm.c15
-rw-r--r--board/keyborg/touch_scan.c53
3 files changed, 56 insertions, 28 deletions
diff --git a/board/keyborg/master_slave.c b/board/keyborg/master_slave.c
index a74ddf554b..5bb03c4e70 100644
--- a/board/keyborg/master_slave.c
+++ b/board/keyborg/master_slave.c
@@ -15,7 +15,6 @@
#define SYNC2 (1 << 2) /* PI2 */
static int is_master = -1;
-static int last_sync; /* = 0 -> Low */
int master_slave_is_master(void)
{
@@ -36,15 +35,20 @@ static int wait_sync_signal(int mask, int v, int timeout_ms)
int master_slave_sync(int timeout_ms)
{
int err = EC_SUCCESS;
- last_sync ^= 1;
if (is_master) {
- STM32_GPIO_BSRR(GPIO_I) = SYNC1 << (last_sync ? 0 : 16);
- if (wait_sync_signal(SYNC2, last_sync, timeout_ms))
+ STM32_GPIO_BSRR(GPIO_I) = SYNC1 << 0;
+ if (wait_sync_signal(SYNC2, 1, timeout_ms))
+ err = EC_ERROR_TIMEOUT;
+ STM32_GPIO_BSRR(GPIO_I) = SYNC1 << 16;
+ if (wait_sync_signal(SYNC2, 0, 5))
err = EC_ERROR_TIMEOUT;
} else {
- if (wait_sync_signal(SYNC1, last_sync, timeout_ms))
+ if (wait_sync_signal(SYNC1, 1, timeout_ms))
+ err = EC_ERROR_TIMEOUT;
+ STM32_GPIO_BSRR(GPIO_I) = SYNC2 << 0;
+ if (wait_sync_signal(SYNC1, 0, 5))
err = EC_ERROR_TIMEOUT;
- STM32_GPIO_BSRR(GPIO_I) = SYNC2 << (last_sync ? 0 : 16);
+ STM32_GPIO_BSRR(GPIO_I) = SYNC2 << 16;
}
return err;
}
diff --git a/board/keyborg/spi_comm.c b/board/keyborg/spi_comm.c
index 444661a23c..380ab6906b 100644
--- a/board/keyborg/spi_comm.c
+++ b/board/keyborg/spi_comm.c
@@ -309,9 +309,12 @@ void spi_slave_init(void)
int spi_slave_send_response(struct spi_comm_packet *resp)
{
- if (spi_slave_send_response_async(resp) != EC_SUCCESS)
- return EC_ERROR_UNKNOWN;
- return spi_slave_send_response_flush();
+ int r;
+
+ r = spi_slave_send_response_async(resp);
+ r |= spi_slave_send_response_flush();
+
+ return r;
}
int spi_slave_send_response_async(struct spi_comm_packet *resp)
@@ -325,7 +328,8 @@ int spi_slave_send_response_async(struct spi_comm_packet *resp)
if (out_msg != (uint8_t *)resp)
memcpy(out_msg, resp, size);
- master_slave_sync(100);
+ if (master_slave_sync(100) != EC_SUCCESS)
+ return EC_ERROR_UNKNOWN;
if (spi->sr & STM32_SPI_SR_RXNE)
in_msg[0] = spi->dr;
@@ -344,7 +348,8 @@ int spi_slave_send_response_async(struct spi_comm_packet *resp)
dma_prepare_tx(&dma_tx_option, size - 1, out_msg + 1);
dma_go(dma_get_channel(STM32_DMAC_SPI1_TX));
- master_slave_sync(5);
+ if (master_slave_sync(5) != EC_SUCCESS)
+ return EC_ERROR_UNKNOWN;
return EC_SUCCESS;
}
diff --git a/board/keyborg/touch_scan.c b/board/keyborg/touch_scan.c
index 53eec0ae16..da71b605a5 100644
--- a/board/keyborg/touch_scan.c
+++ b/board/keyborg/touch_scan.c
@@ -152,7 +152,7 @@ static inline void set_scan_needed(int col)
int fast_scan(uint32_t *data)
{
int col;
- int chip_col;
+ int chip_col = 0;
memset(data, 0, SCAN_BUF_SIZE * 4);
@@ -168,7 +168,7 @@ int fast_scan(uint32_t *data)
}
if (master_slave_sync(5) != EC_SUCCESS)
- return EC_ERROR_UNKNOWN;
+ goto fast_scan_err;
start_adc_sample(0, ADC_SMPL_CPU_CYCLE);
while (!(STM32_ADC_SR(0) & (1 << 1)))
@@ -177,7 +177,7 @@ int fast_scan(uint32_t *data)
set_scan_needed(col);
if (master_slave_sync(5) != EC_SUCCESS)
- return EC_ERROR_UNKNOWN;
+ goto fast_scan_err;
if (chip_col >= 0) {
enable_col(chip_col, 0);
STM32_PMSE_MCCR = 0;
@@ -186,6 +186,11 @@ int fast_scan(uint32_t *data)
STM32_PMSE_MRCR = 0;
return EC_SUCCESS;
+fast_scan_err:
+ enable_col(chip_col, 0);
+ STM32_PMSE_MCCR = 0;
+ STM32_PMSE_MRCR = 0;
+ return EC_ERROR_UNKNOWN;
}
#else
int fast_scan(uint32_t *data)
@@ -224,11 +229,11 @@ void scan_column(uint8_t *data)
void touch_scan_slave_start(void)
{
- int col, i, v;
+ int col = 0, i, v;
struct spi_comm_packet *resp = (struct spi_comm_packet *)buf;
if (fast_scan(scan_needed) != EC_SUCCESS)
- return;
+ goto slave_err;
/* Discharge the panel */
discharge();
@@ -240,7 +245,7 @@ void touch_scan_slave_start(void)
}
if (master_slave_sync(20) != EC_SUCCESS)
- return;
+ goto slave_err;
if (GET_SCAN_NEEDED(col)) {
scan_column(resp->data);
@@ -260,13 +265,15 @@ void touch_scan_slave_start(void)
/* Flush the last response */
if (col != 0)
- spi_slave_send_response_flush();
+ if (spi_slave_send_response_flush() != EC_SUCCESS)
+ goto slave_err;
if (master_slave_sync(40) != EC_SUCCESS)
- return;
+ goto slave_err;
/* Start sending the response for the current column */
- spi_slave_send_response_async(resp);
+ if (spi_slave_send_response_async(resp) != EC_SUCCESS)
+ goto slave_err;
/* Disable the current column and discharge */
if (col < COL_COUNT) {
@@ -277,13 +284,19 @@ void touch_scan_slave_start(void)
}
spi_slave_send_response_flush();
master_slave_sync(20);
+ return;
+slave_err:
+ if (col < COL_COUNT)
+ enable_col(col, 0);
+ STM32_PMSE_MCCR = 0;
+ spi_slave_send_response_flush();
}
int touch_scan_full_matrix(void)
{
struct spi_comm_packet cmd;
const struct spi_comm_packet *resp;
- int col;
+ int col = 0;
timestamp_t st = get_time();
uint8_t *dptr = NULL, *last_dptr = NULL;
@@ -291,12 +304,12 @@ int touch_scan_full_matrix(void)
cmd.size = 0;
if (spi_master_send_command(&cmd))
- return EC_ERROR_UNKNOWN;
+ goto master_err;
encode_reset();
if (fast_scan(scan_needed) != EC_SUCCESS)
- return EC_ERROR_UNKNOWN;
+ goto master_err;
/* Discharge the panel */
discharge();
@@ -308,7 +321,7 @@ int touch_scan_full_matrix(void)
}
if (master_slave_sync(20) != EC_SUCCESS)
- return EC_ERROR_UNKNOWN;
+ goto master_err;
last_dptr = dptr;
dptr = buf[col & 1];
@@ -322,7 +335,7 @@ int touch_scan_full_matrix(void)
/* Flush the data from the slave for the last column */
resp = spi_master_wait_response_done();
if (resp == NULL)
- return EC_ERROR_UNKNOWN;
+ goto master_err;
if (resp->size)
memcpy(last_dptr, resp->data, ROW_COUNT);
else
@@ -331,11 +344,11 @@ int touch_scan_full_matrix(void)
}
if (master_slave_sync(40) != EC_SUCCESS)
- return EC_ERROR_UNKNOWN;
+ goto master_err;
/* Start receiving data for the current column */
if (spi_master_wait_response_async() != EC_SUCCESS)
- return EC_ERROR_UNKNOWN;
+ goto master_err;
/* Disable the current column and discharge */
if (col >= COL_COUNT) {
@@ -347,7 +360,7 @@ int touch_scan_full_matrix(void)
resp = spi_master_wait_response_done();
if (resp == NULL)
- return EC_ERROR_UNKNOWN;
+ goto master_err;
if (resp->size)
memcpy(last_dptr, resp->data, ROW_COUNT);
else
@@ -360,4 +373,10 @@ int touch_scan_full_matrix(void)
encode_dump_matrix();
return EC_SUCCESS;
+master_err:
+ spi_master_wait_response_done();
+ if (col >= COL_COUNT)
+ enable_col(col - COL_COUNT, 0);
+ STM32_PMSE_MCCR = 0;
+ return EC_ERROR_UNKNOWN;
}