diff --git a/drivers/i2c/i2c_ite_it51xxx.c b/drivers/i2c/i2c_ite_it51xxx.c index 96d76746279..3b655293815 100644 --- a/drivers/i2c/i2c_ite_it51xxx.c +++ b/drivers/i2c/i2c_ite_it51xxx.c @@ -545,23 +545,37 @@ done: #endif } +static void clear_target_status(const struct device *dev, uint8_t status) +{ + const struct i2c_it51xxx_config *config = dev->config; + + /* Write to clear a specific status */ +#ifdef CONFIG_SOC_IT51526AW + sys_write8(status, config->i2cbase_mapping + SMB_SLSTA(config->port)); +#else + sys_write8(status, config->target_base + SMB_SLSTn); +#endif +} + static void target_i2c_isr_pio(const struct device *dev) { const struct i2c_it51xxx_config *config = dev->config; struct i2c_it51xxx_data *data = dev->data; struct i2c_target_config *target_cfg; const struct i2c_target_callbacks *target_cb; - int ret; uint8_t target_status, target_idx; uint8_t val; target_status = sys_read8(config->target_base + SMB_SLSTn); + /* Write to clear a target status */ + clear_target_status(dev, target_status); /* Any error */ if (target_status & SMB_STS) { data->w_index = 0; data->r_index = 0; - goto done; + + return; } /* Which target address to match. */ @@ -569,6 +583,24 @@ static void target_i2c_isr_pio(const struct device *dev) target_cfg = data->target_cfg[target_idx]; target_cb = target_cfg->callbacks; + /* Stop condition, indicate stop condition detected. */ + if (target_status & SMB_SPDS) { + /* Transfer done callback function */ + if (target_cb->stop) { + target_cb->stop(target_cfg); + } + data->w_index = 0; + data->r_index = 0; + + if (config->target_shared_fifo_mode) { + uint8_t sdfpctl; + + /* Disable FIFO mode to clear left count */ + sdfpctl = sys_read8(config->target_base + SMB_SnDFPCTL); + sys_write8(sdfpctl & ~SMB_SADFE, config->target_base + SMB_SnDFPCTL); + } + } + if (target_status & SMB_SDS) { if (target_status & SMB_RCS) { /* Target shared FIFO mode */ @@ -593,6 +625,8 @@ static void target_i2c_isr_pio(const struct device *dev) sndfpctl = sys_read8(config->target_base + SMB_SnDFPCTL); sys_write8(sndfpctl | SMB_SADFE, config->target_base + SMB_SnDFPCTL); + /* Write to clear data status of target */ + clear_target_status(dev, SMB_SDS); } else { /* Host receiving, target transmitting */ if (!data->r_index) { @@ -620,44 +654,14 @@ static void target_i2c_isr_pio(const struct device *dev) /* Read data */ val = sys_read8(config->target_base + SMB_SLDn); if (target_cb->write_received) { - ret = target_cb->write_received(target_cfg, val); - if (!ret) { - /* Release clock pin */ - val = sys_read8(config->target_base + SMB_SLDn); - } + target_cb->write_received(target_cfg, val); } - + /* Release target clock stretch */ + sys_write8(sys_read8(config->target_base + SMB_SLVCTLn) | SMB_RSCS, + config->target_base + SMB_SLVCTLn); data->w_index++; } } - /* Stop condition, indicate stop condition detected. */ - if (target_status & SMB_SPDS) { - /* Transfer done callback function */ - if (target_cb->stop) { - target_cb->stop(target_cfg); - } - data->w_index = 0; - data->r_index = 0; - - if (config->target_shared_fifo_mode) { - uint8_t sdfpctl; - - /* Disable FIFO mode to clear left count */ - sdfpctl = sys_read8(config->target_base + SMB_SnDFPCTL); - sys_write8(sdfpctl & ~SMB_SADFE, config->target_base + SMB_SnDFPCTL); - } - } - -done: - sys_write8(sys_read8(config->target_base + SMB_SLVCTLn) | SMB_RSCS, - config->target_base + SMB_SLVCTLn); - - /* W/C */ -#ifdef CONFIG_SOC_IT51526AW - sys_write8(target_status, config->i2cbase_mapping + SMB_SLSTA(config->port)); -#else - sys_write8(target_status, config->target_base + SMB_SLSTn); -#endif } static void target_i2c_isr(const struct device *dev)