i2c/i2c_dw: bail out if tx is aborted during send

This enables the driver to process the transmit abort signal
during send.

Change-Id: I3ad1f25669bee214b5e1a04cd858ccb4a8442333
Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2016-01-12 16:23:56 -08:00 committed by Anas Nashif
commit 7b4167ed78

View file

@ -141,7 +141,7 @@ static void _i2c_dw_data_read(struct device *dev)
} }
static void _i2c_dw_data_send(struct device *dev) static int _i2c_dw_data_send(struct device *dev)
{ {
struct i2c_dw_rom_config const * const rom = dev->config->config_info; struct i2c_dw_rom_config const * const rom = dev->config->config_info;
struct i2c_dw_dev_config * const dw = dev->driver_data; struct i2c_dw_dev_config * const dw = dev->driver_data;
@ -156,7 +156,7 @@ static void _i2c_dw_data_send(struct device *dev)
dw->state &= ~I2C_DW_CMD_SEND; dw->state &= ~I2C_DW_CMD_SEND;
return; return DEV_OK;
} }
while (regs->ic_status.bits.tfnf && (dw->xfr_len > 0)) { while (regs->ic_status.bits.tfnf && (dw->xfr_len > 0)) {
@ -178,7 +178,13 @@ static void _i2c_dw_data_send(struct device *dev)
dw->xfr_len--; dw->xfr_len--;
dw->xfr_buf++; dw->xfr_buf++;
if (regs->ic_intr_stat.bits.tx_abrt) {
return DEV_FAIL;
}
} }
return DEV_OK;
} }
static inline void _i2c_dw_transfer_complete(struct device *dev) static inline void _i2c_dw_transfer_complete(struct device *dev)
@ -202,6 +208,7 @@ void i2c_dw_isr(struct device *port)
struct i2c_dw_dev_config * const dw = port->driver_data; struct i2c_dw_dev_config * const dw = port->driver_data;
union ic_interrupt_register intr_stat; union ic_interrupt_register intr_stat;
uint32_t value; uint32_t value;
int ret = DEV_OK;
volatile struct i2c_dw_registers * const regs = volatile struct i2c_dw_registers * const regs =
(struct i2c_dw_registers *)rom->base_address; (struct i2c_dw_registers *)rom->base_address;
@ -243,8 +250,7 @@ void i2c_dw_isr(struct device *port)
DW_INTR_STAT_RX_OVER | DW_INTR_STAT_RX_UNDER) & DW_INTR_STAT_RX_OVER | DW_INTR_STAT_RX_UNDER) &
intr_stat.raw) { intr_stat.raw) {
dw->state = I2C_DW_CMD_ERROR; dw->state = I2C_DW_CMD_ERROR;
_i2c_dw_transfer_complete(port); goto done;
return;
} }
/* Check if the RX FIFO reached threshold */ /* Check if the RX FIFO reached threshold */
@ -259,7 +265,7 @@ void i2c_dw_isr(struct device *port)
if (intr_stat.bits.tx_empty) { if (intr_stat.bits.tx_empty) {
if ((dw->xfr_flags & I2C_MSG_RW_MASK) if ((dw->xfr_flags & I2C_MSG_RW_MASK)
== I2C_MSG_WRITE) { == I2C_MSG_WRITE) {
_i2c_dw_data_send(port); ret = _i2c_dw_data_send(port);
} else { } else {
_i2c_dw_data_ask(port); _i2c_dw_data_ask(port);
} }
@ -267,10 +273,10 @@ void i2c_dw_isr(struct device *port)
/* If STOP is not expected, finish processing this /* If STOP is not expected, finish processing this
* message if there is nothing left to do anymore. * message if there is nothing left to do anymore.
*/ */
if ((dw->xfr_len == 0) if (((dw->xfr_len == 0)
&& !(dw->xfr_flags & I2C_MSG_STOP)) { && !(dw->xfr_flags & I2C_MSG_STOP))
_i2c_dw_transfer_complete(port); || (ret != DEV_OK)) {
return; goto done;
} }
} }
} else { /* we must be configured as a slave device */ } else { /* we must be configured as a slave device */
@ -299,9 +305,13 @@ void i2c_dw_isr(struct device *port)
/* STOP detected: finish processing this message */ /* STOP detected: finish processing this message */
if (intr_stat.bits.stop_det) { if (intr_stat.bits.stop_det) {
value = regs->ic_clr_stop_det; value = regs->ic_clr_stop_det;
_i2c_dw_transfer_complete(port); goto done;
return;
} }
return;
done:
_i2c_dw_transfer_complete(port);
} }