From 26fd9aea743307c59e41701e4c0cd8e669b5beb6 Mon Sep 17 00:00:00 2001 From: PojuiLiu Date: Wed, 8 Jul 2026 15:48:31 +0800 Subject: [PATCH] fix(ast10x0-i2c): handle buffer-mode rx and smbus probe Fix AST1060 I2C slave-mode status handling that could hang the bus. - Handle buffer-mode RX_DONE (no WAIT_RX_DMA): report DataReceived. - Handle bare SLAVE_MATCH (SMBus quick probe): re-arm and clear status so the slave does not clock-stretch until SMBus timeout. Signed-off-by: PojuiLiu --- target/ast10x0/peripherals/i2c/slave.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/target/ast10x0/peripherals/i2c/slave.rs b/target/ast10x0/peripherals/i2c/slave.rs index 8b118e8b..801049ed 100644 --- a/target/ast10x0/peripherals/i2c/slave.rs +++ b/target/ast10x0/peripherals/i2c/slave.rs @@ -498,12 +498,7 @@ impl Ast1060I2c<'_, Y> { .write(|w| w.bits(constants::AST_I2CS_PKT_DONE)); } let sts = status & (!(constants::AST_I2CS_PKT_DONE | constants::AST_I2CS_PKT_ERROR)); - if sts == constants::AST_I2CS_SLAVE_MATCH - || sts == constants::AST_I2CS_SLAVE_MATCH | constants::AST_I2CS_RX_DONE - { - // S: Sw - return Some(SlaveEvent::WriteRequest); - } else if sts == constants::AST_I2CS_SLAVE_MATCH | constants::AST_I2CS_WAIT_RX_DMA + if sts == constants::AST_I2CS_SLAVE_MATCH | constants::AST_I2CS_WAIT_RX_DMA || sts == constants::AST_I2CS_SLAVE_MATCH | constants::AST_I2CS_RX_DONE @@ -517,6 +512,24 @@ impl Ast1060I2c<'_, Y> { return Some(SlaveEvent::DataReceived { len: self.slave_rx_len(), }); + } else if sts == constants::AST_I2CS_SLAVE_MATCH | constants::AST_I2CS_RX_DONE { + // S: Sw|D (buffer mode — no WAIT_RX_DMA bit) + self.arm_slave_receive(&mut cmd); + unsafe { + self.regs().i2cs28().write(|w| w.bits(cmd)); + } + return Some(SlaveEvent::DataReceived { + len: self.slave_rx_len(), + }); + } else if sts == constants::AST_I2CS_SLAVE_MATCH { + // S: Sw — address match only (e.g. SMBus quick probe); re-arm and + // clear status so the bus does not clock-stretch until timeout. + self.arm_slave_receive(&mut cmd); + unsafe { + self.regs().i2cs28().write(|w| w.bits(cmd)); + self.regs().i2cs24().write(|w| w.bits(sts)); + } + return Some(SlaveEvent::WriteRequest); } else if sts == constants::AST_I2CS_SLAVE_MATCH | constants::AST_I2CS_STOP { // S: Sw|P self.arm_slave_receive(&mut cmd);