Skip to content

Commit ac0b60c

Browse files
author
Josh Tsai
committed
WORKAROUND: avoid the i2c controller no response
When the LAB flag is set in i2c controller status register, we should reset the controller to avoid i2c controller no response. We also need to change the ttansaction_state to stopped when i2c read is completed. Signed-off-by: Josh Tsai <josh_tsai@compal.com>
1 parent 510c647 commit ac0b60c

1 file changed

Lines changed: 46 additions & 1 deletion

File tree

chip/mchp/i2c.c

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@
8080
#define CFG_ENABLE BIT(10) /* enable controller */
8181
#define CFG_GC_DIS BIT(14) /* disable general call address */
8282
#define CFG_PROM_EN BIT(15) /* enable Promiscuous mode */
83+
#define CFG_FLUSH_SXBUF (16) /* clear slave Tx buffer */
84+
#define CFG_FLUSH_SRBUF (17) /* clear slave Rx buffer */
85+
#define CFG_FLUSH_MXBUF (18) /* clear master Tx buffer */
86+
#define CFG_FLUSH_MRBUF (19) /* clear master Rx buffer */
8387
#define CFG_ENIDI BIT(29) /* Enable I2C idle interrupt */
8488
/* Enable network layer master done interrupt */
8589
#define CFG_ENMI BIT(30)
@@ -619,6 +623,21 @@ static int i2c_mtx(int ctrl)
619623
cdata[ctrl].transaction_state = I2C_TRANSACTION_OPEN;
620624
}
621625

626+
/* Workaround to revocer the LAB flag error */
627+
while (MCHP_I2C_STATUS(ctrl) & STS_LAB) {
628+
CPRINTS("I2C%d wSTS LAB error, doing reset!", ctrl);
629+
MCHP_I2C_CONFIG(ctrl) |= CFG_FLUSH_MRBUF | CFG_FLUSH_MXBUF |
630+
CFG_FLUSH_SRBUF | CFG_FLUSH_SXBUF;
631+
reset_controller(ctrl);
632+
usleep(1000);
633+
634+
MCHP_I2C_DATA(ctrl) = cdata[ctrl].slv_addr_8bit;
635+
/* Clock out the slave address, sending START bit */
636+
MCHP_I2C_CTRL(ctrl) = CTRL_PIN | CTRL_ESO | CTRL_ENI |
637+
CTRL_ACK | CTRL_STA;
638+
cdata[ctrl].transaction_state = I2C_TRANSACTION_OPEN;
639+
}
640+
622641
for (i = 0; i < cdata[ctrl].out_size; ++i) {
623642
rv = wait_byte_done(ctrl, 0xff, 0x00);
624643
if (rv) {
@@ -702,6 +721,30 @@ static int i2c_mrx_start(int ctrl)
702721
/* address then START */
703722
MCHP_I2C_CTRL(ctrl) = u8 | CTRL_PIN;
704723
}
724+
725+
/* Workaround to revocer the LAB flag error */
726+
while (MCHP_I2C_STATUS(ctrl) & STS_LAB) {
727+
CPRINTS("I2C%d rSTS LAB error, doing reset!", ctrl);
728+
MCHP_I2C_CONFIG(ctrl) |= CFG_FLUSH_MRBUF | CFG_FLUSH_MXBUF |
729+
CFG_FLUSH_SRBUF | CFG_FLUSH_SXBUF;
730+
reset_controller(ctrl);
731+
usleep(1000);
732+
733+
if (cdata[ctrl].transaction_state == I2C_TRANSACTION_OPEN) {
734+
cdata[ctrl].flags |= (1ul << 5);
735+
/* Repeated-START then address */
736+
MCHP_I2C_CTRL(ctrl) = u8;
737+
}
738+
739+
MCHP_I2C_DATA(ctrl) = cdata[ctrl].slv_addr_8bit | 0x01;
740+
if (cdata[ctrl].transaction_state == I2C_TRANSACTION_STOPPED) {
741+
cdata[ctrl].flags |= (1ul << 6);
742+
/* address then START */
743+
MCHP_I2C_CTRL(ctrl) = u8 | CTRL_PIN;
744+
}
745+
}
746+
747+
705748
cdata[ctrl].transaction_state = I2C_TRANSACTION_OPEN;
706749
/* Controller generates START, transmits data(address) capturing
707750
* 9-bits from SDA (8-bit address + (N)Ack bit).
@@ -843,8 +886,10 @@ int chip_i2c_xfer(int port, uint16_t slave_addr_flags,
843886

844887
cdata[ctrl].flags |= (1ul << 15);
845888
/* MCHP wait for STOP to complete */
846-
if (cdata[ctrl].xflags & I2C_XFER_STOP)
889+
if (cdata[ctrl].xflags & I2C_XFER_STOP) {
890+
cdata[ctrl].transaction_state = I2C_TRANSACTION_STOPPED;
847891
wait_idle(ctrl);
892+
}
848893

849894
/* Check for error conditions */
850895
if (MCHP_I2C_STATUS(ctrl) & (STS_LAB | STS_BER)) {

0 commit comments

Comments
 (0)