Merge tag 'i2c-updates-for-v2023.10-rc3' of https://source.denx.de/u-boot/custodians/u-boot-i2c

i2c updates for v2023.10-rc3

Bugfixes:
- mvtwsi driver fix stuck "bus error" state
  from Sam
This commit is contained in:
Tom Rini 2023-08-15 10:44:20 -04:00
commit ae9de10d5f

View File

@ -142,6 +142,8 @@ enum mvtwsi_ctrl_register_fields {
* code. * code.
*/ */
enum mvstwsi_status_values { enum mvstwsi_status_values {
/* Protocol violation on bus; this is a terminal state */
MVTWSI_BUS_ERROR = 0x00,
/* START condition transmitted */ /* START condition transmitted */
MVTWSI_STATUS_START = 0x08, MVTWSI_STATUS_START = 0x08,
/* Repeated START condition transmitted */ /* Repeated START condition transmitted */
@ -525,6 +527,36 @@ static void __twsi_i2c_init(struct mvtwsi_registers *twsi, int speed,
#endif #endif
} }
/*
* __twsi_i2c_reinit() - Reset and reinitialize the I2C controller.
*
* This function should be called to get the MVTWSI controller out of the
* "bus error" state. It saves and restores the baud and address registers.
*
* @twsi: The MVTWSI register structure to use.
* @tick: The duration of a clock cycle at the current I2C speed.
*/
static void __twsi_i2c_reinit(struct mvtwsi_registers *twsi, uint tick)
{
uint baud;
uint slaveadd;
/* Save baud, address registers */
baud = readl(&twsi->baudrate);
slaveadd = readl(&twsi->slave_address);
/* Reset controller */
twsi_reset(twsi);
/* Restore baud, address registers */
writel(baud, &twsi->baudrate);
writel(slaveadd, &twsi->slave_address);
writel(0, &twsi->xtnd_slave_addr);
/* Assert STOP, but don't care for the result */
(void) twsi_stop(twsi, tick);
}
/* /*
* i2c_begin() - Start a I2C transaction. * i2c_begin() - Start a I2C transaction.
* *
@ -621,6 +653,11 @@ static int __twsi_i2c_read(struct mvtwsi_registers *twsi, uchar chip,
int stop_status; int stop_status;
int expected_start = MVTWSI_STATUS_START; int expected_start = MVTWSI_STATUS_START;
/* Check for (and clear) a bus error from a previous failed transaction
* or another master on the same bus */
if (readl(&twsi->status) == MVTWSI_BUS_ERROR)
__twsi_i2c_reinit(twsi, tick);
if (alen > 0) { if (alen > 0) {
/* Begin i2c write to send the address bytes */ /* Begin i2c write to send the address bytes */
status = i2c_begin(twsi, expected_start, (chip << 1), tick); status = i2c_begin(twsi, expected_start, (chip << 1), tick);
@ -668,6 +705,11 @@ static int __twsi_i2c_write(struct mvtwsi_registers *twsi, uchar chip,
{ {
int status, stop_status; int status, stop_status;
/* Check for (and clear) a bus error from a previous failed transaction
* or another master on the same bus */
if (readl(&twsi->status) == MVTWSI_BUS_ERROR)
__twsi_i2c_reinit(twsi, tick);
/* Begin i2c write to send first the address bytes, then the /* Begin i2c write to send first the address bytes, then the
* data bytes */ * data bytes */
status = i2c_begin(twsi, MVTWSI_STATUS_START, (chip << 1), tick); status = i2c_begin(twsi, MVTWSI_STATUS_START, (chip << 1), tick);