mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-28 10:45:22 +00:00
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>
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user