Skip to content

Commit 5d32c52

Browse files
author
Codrin Ciubotariu
committed
i2c: at91: keep the controller disabled when it is not used
The controller (master mode) should be disabled when it is not used, to avoid potential glitches on the bus. The controller must be disabled only when the controller is not running. This fixes an issue on Microchip's SAMA5D4 platform when pinctrl changes the I2C's pin states between GPIO and I2C, done when GPIO recovery is used. Fixes: 813e30e ("i2c: New Atmel AT91 bus driver") Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@microchip.com> Acked-by: Cristian Birsan <cristian.birsan@microchip.com>
1 parent 119f26f commit 5d32c52

1 file changed

Lines changed: 32 additions & 2 deletions

File tree

drivers/i2c/busses/i2c-at91-master.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ void at91_init_twi_bus_master(struct at91_twi_dev *dev)
3939
/* FIFO should be enabled immediately after the software reset */
4040
if (dev->fifo_size)
4141
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_FIFOEN);
42-
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_MSEN);
42+
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_MSDIS);
4343
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SVDIS);
4444
at91_twi_write(dev, AT91_TWI_CWGR, dev->twi_cwgr_reg);
4545

@@ -594,7 +594,6 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
594594
if (time_left == 0) {
595595
dev->transfer_status |= at91_twi_read(dev, AT91_TWI_SR);
596596
dev_err(dev->dev, "controller timed out\n");
597-
at91_init_twi_bus(dev);
598597
ret = -ETIMEDOUT;
599598
goto error;
600599
}
@@ -643,6 +642,26 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
643642
return ret;
644643
}
645644

645+
static void at91_twi_disable(struct at91_twi_dev *dev)
646+
{
647+
/* return if previous operation is completed */
648+
if (!(at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_TXCOMP)) {
649+
/* wait for previous command to complete before disabling the controller */
650+
dev_dbg(dev->dev, "wait for command to complete...\n");
651+
reinit_completion(&dev->cmd_complete);
652+
dev->transfer_status = 0;
653+
at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
654+
wait_for_completion_timeout(&dev->cmd_complete, dev->adapter.timeout);
655+
if (!(dev->transfer_status & AT91_TWI_TXCOMP)) {
656+
dev_dbg(dev->dev, "IP still busy, resetting the controller...\n");
657+
at91_init_twi_bus(dev);
658+
return;
659+
}
660+
}
661+
662+
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_MSDIS);
663+
}
664+
646665
static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
647666
{
648667
struct at91_twi_dev *dev = i2c_get_adapdata(adap);
@@ -657,6 +676,8 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
657676
if (ret < 0)
658677
goto out;
659678

679+
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_MSEN);
680+
660681
if (num == 2) {
661682
int internal_address = 0;
662683
int i;
@@ -700,13 +721,22 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
700721
ret = at91_do_twi_transfer(dev);
701722

702723
if (ret < 0) {
724+
/* disable controller before using GPIO recovery */
725+
if (!dev->pdata->has_clear_cmd)
726+
at91_twi_disable(dev);
727+
703728
/*
704729
* some faulty I2C slave devices might hold SDA down;
705730
* we can send a bus clear command, hoping that the pins will be
706731
* released
707732
*/
708733
i2c_recover_bus(&dev->adapter);
734+
735+
/* disable controller if not disabled before */
736+
if (dev->pdata->has_clear_cmd)
737+
at91_twi_disable(dev);
709738
} else {
739+
at91_twi_disable(dev);
710740
ret = num;
711741
}
712742

0 commit comments

Comments
 (0)