diff --git a/drivers/i2c/i2c_dw.c b/drivers/i2c/i2c_dw.c index ef2b205ab9c..0edcd147052 100644 --- a/drivers/i2c/i2c_dw.c +++ b/drivers/i2c/i2c_dw.c @@ -541,12 +541,17 @@ static void i2c_dw_isr(const struct device *port) } } #else - if (slave_cb->read_requested) { - slave_cb->read_requested(dw->slave_cfg, &data); - i2c_dw_write_byte_non_blocking(port, data); - } - if (slave_cb->read_processed) { - slave_cb->read_processed(dw->slave_cfg, &data); + if (!dw->read_in_progress) { + if (slave_cb->read_requested) { + slave_cb->read_requested(dw->slave_cfg, &data); + i2c_dw_write_byte_non_blocking(port, data); + } + dw->read_in_progress = true; + } else { + if (slave_cb->read_processed) { + slave_cb->read_processed(dw->slave_cfg, &data); + i2c_dw_write_byte_non_blocking(port, data); + } } #endif } @@ -986,6 +991,7 @@ static int i2c_dw_slave_register(const struct device *dev, struct i2c_target_con uint32_t reg_base = get_regs(dev); int ret; + dw->read_in_progress = false; dw->slave_cfg = cfg; ret = i2c_dw_set_slave_mode(dev, cfg->address, cfg->flags); write_intr_mask(DW_INTR_MASK_RX_FULL | DW_INTR_MASK_RD_REQ | DW_INTR_MASK_TX_ABRT | @@ -1049,6 +1055,7 @@ static void i2c_dw_slave_read_clear_intr_bits(const struct device *dev) if (intr_stat.bits.stop_det) { read_clr_stop_det(reg_base); dw->state = I2C_DW_STATE_READY; + dw->read_in_progress = false; if (slave_cb->stop) { slave_cb->stop(dw->slave_cfg); } @@ -1057,6 +1064,7 @@ static void i2c_dw_slave_read_clear_intr_bits(const struct device *dev) if (intr_stat.bits.start_det) { read_clr_start_det(reg_base); dw->state = I2C_DW_STATE_READY; + dw->read_in_progress = false; } if (intr_stat.bits.gen_call) { diff --git a/drivers/i2c/i2c_dw.h b/drivers/i2c/i2c_dw.h index 57c2dd607fd..ed763820725 100644 --- a/drivers/i2c/i2c_dw.h +++ b/drivers/i2c/i2c_dw.h @@ -173,6 +173,7 @@ struct i2c_dw_dev_config { uint32_t request_bytes; uint8_t xfr_flags; bool support_hs_mode; + bool read_in_progress; #ifdef CONFIG_I2C_DW_LPSS_DMA uintptr_t phy_addr; uintptr_t base_addr;