drivers/i2c: it51xxx: Refactor ISR to reduce clock stretch in PIO mode
Move handling of write-to-clear status and stop detect to the beginning of the ISR for PIO mode to reduce unnecessary clock stretching and improve responsiveness during transfers. This patch also separates status clearing for shared FIFO mode, ensuring it is done at the appropriate point after data handling completes, maintaining correct transfer behavior. Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
This commit is contained in:
parent
b8bfa36250
commit
648919f6df
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user