Skip to content

Commit c1d305e

Browse files
jgrowdenTTcfriedt
authored andcommitted
drivers: i2c: Correct i2c_dw target implementation
The I2C target implementation for i2c_dw does not follow the zephyr target specification. The following three issues are corrected: 1) The read_requested CB is called on every byte of the transaction - it must be called only on the first byte of the transaction 2) The read_processed CB is called on every byte of the transaction - it must be called only on bytes following the first byte 3) Bytes returned in the data ptr param of read_processed are not sent to the controller -These bytes must be sent to the controller Signed-off-by: James Growden <[email protected]>
1 parent d1287ed commit c1d305e

File tree

2 files changed

+15
-6
lines changed

2 files changed

+15
-6
lines changed

drivers/i2c/i2c_dw.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -593,12 +593,18 @@ static void i2c_dw_isr(const struct device *port)
593593
if (slave_activity) {
594594
read_clr_rd_req(reg_base);
595595
dw->state = I2C_DW_CMD_RECV;
596-
if (slave_cb->read_requested) {
597-
slave_cb->read_requested(dw->slave_cfg, &data);
598-
i2c_dw_write_byte_non_blocking(port, data);
599-
}
600-
if (slave_cb->read_processed) {
601-
slave_cb->read_processed(dw->slave_cfg, &data);
596+
597+
if (!dw->read_in_progress) {
598+
if (slave_cb->read_requested) {
599+
slave_cb->read_requested(dw->slave_cfg, &data);
600+
i2c_dw_write_byte_non_blocking(port, data);
601+
}
602+
dw->read_in_progress = true;
603+
} else {
604+
if (slave_cb->read_processed) {
605+
slave_cb->read_processed(dw->slave_cfg, &data);
606+
i2c_dw_write_byte_non_blocking(port, data);
607+
}
602608
}
603609
}
604610
}
@@ -1125,6 +1131,7 @@ static int i2c_dw_slave_register(const struct device *dev, struct i2c_target_con
11251131
uint32_t reg_base = get_regs(dev);
11261132
int ret;
11271133

1134+
dw->read_in_progress = false;
11281135
dw->slave_cfg = cfg;
11291136
ret = i2c_dw_set_slave_mode(dev, cfg->address);
11301137
write_intr_mask(DW_INTR_MASK_RX_FULL | DW_INTR_MASK_RD_REQ | DW_INTR_MASK_TX_ABRT |
@@ -1188,6 +1195,7 @@ static void i2c_dw_slave_read_clear_intr_bits(const struct device *dev)
11881195
if (intr_stat.bits.stop_det) {
11891196
read_clr_stop_det(reg_base);
11901197
dw->state = I2C_DW_STATE_READY;
1198+
dw->read_in_progress = false;
11911199
if (slave_cb->stop) {
11921200
slave_cb->stop(dw->slave_cfg);
11931201
}

drivers/i2c/i2c_dw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ struct i2c_dw_dev_config {
140140
uint32_t request_bytes;
141141
uint8_t xfr_flags;
142142
bool support_hs_mode;
143+
bool read_in_progress;
143144
#ifdef CONFIG_I2C_DW_LPSS_DMA
144145
uintptr_t phy_addr;
145146
uintptr_t base_addr;

0 commit comments

Comments
 (0)