summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Mooney <charliemooney@chromium.org>2012-08-15 08:37:58 -0700
committerGerrit <chrome-bot@google.com>2012-08-16 10:58:20 -0700
commitcd55d3afaf5317eeec099338b7e79f5a1c78aa84 (patch)
treeae3b3e12da2d56ac63e18a356052404021dbcebf
parentcebbe4c0e708be36140c8c0fdce45a106f824650 (diff)
downloadchrome-ec-cd55d3afaf5317eeec099338b7e79f5a1c78aa84.tar.gz
Snow: Possible problems with i2c error handling
Fixing a couple problems in the error handling for i2c interrupts. The code could fail and not notice if master_start() returned an error code with the TASK_EVEN_WAKE bit set. Now it stores the return values separately to prevent this. Also, the task id's that the ISR's use to wake up the i2c task after the transfer is complete were uninitialized. They should always be initialized by a call to dma_enable_tc_interrupt() but just in case, now they all get a default value in dma_init() which is called on startup in board.c BUG=chrome-os-partner:12405 TEST=confirm that i2c is still working in both slave and master mode by using the battery and pmu commands from the EC console, then booting up the machine and using the keyboard. Confirm there are no error messages on the cpu console. Change-Id: I49c3da0bf17d0853247a37131cac9719face7ed4 Signed-off-by: Charlie Mooney <charliemooney@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/30417 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--chip/stm32/dma.c6
-rw-r--r--chip/stm32/i2c.c20
2 files changed, 18 insertions, 8 deletions
diff --git a/chip/stm32/dma.c b/chip/stm32/dma.c
index 9d7f72df6f..c37063a894 100644
--- a/chip/stm32/dma.c
+++ b/chip/stm32/dma.c
@@ -193,8 +193,14 @@ void dma_test(void)
void dma_init(void)
{
+ int i;
+
/* Enable DMA1, we don't support DMA2 yet */
STM32_RCC_AHBENR |= RCC_AHBENR_DMA1EN;
+
+ /* Initialize data for interrupt handlers */
+ for (i = 0; i < DMA_NUM_CHANNELS; i++)
+ id[i] = TASK_ID_INVALID;
}
int dma_wait(int channel)
diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c
index f74479310c..bc3aac9eac 100644
--- a/chip/stm32/i2c.c
+++ b/chip/stm32/i2c.c
@@ -535,7 +535,7 @@ cr_cleanup:
static int i2c_master_transmit(int port, int slave_addr, uint8_t *data,
int size, int stop)
{
- int rv;
+ int rv, rv_start;
struct dma_channel *chan;
disable_ack(port);
@@ -552,17 +552,19 @@ static int i2c_master_transmit(int port, int slave_addr, uint8_t *data,
STM32_I2C_CR2(port) |= CR2_DMAEN;
/* Initialise i2c communication by sending START and ADDR */
- rv = master_start(port, slave_addr);
+ rv_start = master_start(port, slave_addr);
/* If it started, wait for the transmission complete Interrupt */
- if (!rv)
+ if (!rv_start)
rv = task_wait_event(DMA_TRANSFER_TIMEOUT_US);
dma_disable(DMAC_I2C_TX);
dma_disable_tc_interrupt(DMAC_I2C_TX);
STM32_I2C_CR2(port) &= ~CR2_DMAEN;
- if (rv && !(rv & TASK_EVENT_WAKE))
+ if (rv_start)
+ return rv_start;
+ if (!(rv & TASK_EVENT_WAKE))
return rv;
rv = wait_status(port, SR1_BTF, WAIT_XMIT_BTF);
@@ -580,7 +582,7 @@ static int i2c_master_transmit(int port, int slave_addr, uint8_t *data,
static int i2c_master_receive(int port, int slave_addr, uint8_t *data,
int size)
{
- int rv;
+ int rv, rv_start;
if (data == NULL || size < 1)
return EC_ERROR_INVAL;
@@ -596,8 +598,8 @@ static int i2c_master_receive(int port, int slave_addr, uint8_t *data,
STM32_I2C_CR2(port) |= CR2_DMAEN;
STM32_I2C_CR2(port) |= CR2_LAST;
- rv = master_start(port, slave_addr | 1);
- if (!rv)
+ rv_start = master_start(port, slave_addr | 1);
+ if (!rv_start)
rv = task_wait_event(DMA_TRANSFER_TIMEOUT_US);
dma_disable(DMAC_I2C_RX);
@@ -605,7 +607,9 @@ static int i2c_master_receive(int port, int slave_addr, uint8_t *data,
STM32_I2C_CR2(port) &= ~CR2_DMAEN;
disable_ack(port);
- if (rv && !(rv & TASK_EVENT_WAKE))
+ if (rv_start)
+ return rv_start;
+ if (!(rv & TASK_EVENT_WAKE))
return rv;
master_stop(port);