Skip to content

Commit 648919f

Browse files
GTLin08kartben
authored andcommitted
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 <[email protected]>
1 parent b8bfa36 commit 648919f

File tree

1 file changed

+40
-36
lines changed

1 file changed

+40
-36
lines changed

drivers/i2c/i2c_ite_it51xxx.c

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -545,30 +545,62 @@ static void target_i2c_isr_fifo(const struct device *dev)
545545
#endif
546546
}
547547

548+
static void clear_target_status(const struct device *dev, uint8_t status)
549+
{
550+
const struct i2c_it51xxx_config *config = dev->config;
551+
552+
/* Write to clear a specific status */
553+
#ifdef CONFIG_SOC_IT51526AW
554+
sys_write8(status, config->i2cbase_mapping + SMB_SLSTA(config->port));
555+
#else
556+
sys_write8(status, config->target_base + SMB_SLSTn);
557+
#endif
558+
}
559+
548560
static void target_i2c_isr_pio(const struct device *dev)
549561
{
550562
const struct i2c_it51xxx_config *config = dev->config;
551563
struct i2c_it51xxx_data *data = dev->data;
552564
struct i2c_target_config *target_cfg;
553565
const struct i2c_target_callbacks *target_cb;
554-
int ret;
555566
uint8_t target_status, target_idx;
556567
uint8_t val;
557568

558569
target_status = sys_read8(config->target_base + SMB_SLSTn);
570+
/* Write to clear a target status */
571+
clear_target_status(dev, target_status);
559572

560573
/* Any error */
561574
if (target_status & SMB_STS) {
562575
data->w_index = 0;
563576
data->r_index = 0;
564-
goto done;
577+
578+
return;
565579
}
566580

567581
/* Which target address to match. */
568582
target_idx = (target_status & SMB_MSLA2) ? SMB_SADR2 : SMB_SADR;
569583
target_cfg = data->target_cfg[target_idx];
570584
target_cb = target_cfg->callbacks;
571585

586+
/* Stop condition, indicate stop condition detected. */
587+
if (target_status & SMB_SPDS) {
588+
/* Transfer done callback function */
589+
if (target_cb->stop) {
590+
target_cb->stop(target_cfg);
591+
}
592+
data->w_index = 0;
593+
data->r_index = 0;
594+
595+
if (config->target_shared_fifo_mode) {
596+
uint8_t sdfpctl;
597+
598+
/* Disable FIFO mode to clear left count */
599+
sdfpctl = sys_read8(config->target_base + SMB_SnDFPCTL);
600+
sys_write8(sdfpctl & ~SMB_SADFE, config->target_base + SMB_SnDFPCTL);
601+
}
602+
}
603+
572604
if (target_status & SMB_SDS) {
573605
if (target_status & SMB_RCS) {
574606
/* Target shared FIFO mode */
@@ -593,6 +625,8 @@ static void target_i2c_isr_pio(const struct device *dev)
593625
sndfpctl = sys_read8(config->target_base + SMB_SnDFPCTL);
594626
sys_write8(sndfpctl | SMB_SADFE,
595627
config->target_base + SMB_SnDFPCTL);
628+
/* Write to clear data status of target */
629+
clear_target_status(dev, SMB_SDS);
596630
} else {
597631
/* Host receiving, target transmitting */
598632
if (!data->r_index) {
@@ -620,44 +654,14 @@ static void target_i2c_isr_pio(const struct device *dev)
620654
/* Read data */
621655
val = sys_read8(config->target_base + SMB_SLDn);
622656
if (target_cb->write_received) {
623-
ret = target_cb->write_received(target_cfg, val);
624-
if (!ret) {
625-
/* Release clock pin */
626-
val = sys_read8(config->target_base + SMB_SLDn);
627-
}
657+
target_cb->write_received(target_cfg, val);
628658
}
629-
659+
/* Release target clock stretch */
660+
sys_write8(sys_read8(config->target_base + SMB_SLVCTLn) | SMB_RSCS,
661+
config->target_base + SMB_SLVCTLn);
630662
data->w_index++;
631663
}
632664
}
633-
/* Stop condition, indicate stop condition detected. */
634-
if (target_status & SMB_SPDS) {
635-
/* Transfer done callback function */
636-
if (target_cb->stop) {
637-
target_cb->stop(target_cfg);
638-
}
639-
data->w_index = 0;
640-
data->r_index = 0;
641-
642-
if (config->target_shared_fifo_mode) {
643-
uint8_t sdfpctl;
644-
645-
/* Disable FIFO mode to clear left count */
646-
sdfpctl = sys_read8(config->target_base + SMB_SnDFPCTL);
647-
sys_write8(sdfpctl & ~SMB_SADFE, config->target_base + SMB_SnDFPCTL);
648-
}
649-
}
650-
651-
done:
652-
sys_write8(sys_read8(config->target_base + SMB_SLVCTLn) | SMB_RSCS,
653-
config->target_base + SMB_SLVCTLn);
654-
655-
/* W/C */
656-
#ifdef CONFIG_SOC_IT51526AW
657-
sys_write8(target_status, config->i2cbase_mapping + SMB_SLSTA(config->port));
658-
#else
659-
sys_write8(target_status, config->target_base + SMB_SLSTn);
660-
#endif
661665
}
662666

663667
static void target_i2c_isr(const struct device *dev)

0 commit comments

Comments
 (0)