From 845b89127bc5458d0152a4d63f165c62a22fcb70 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 10 Sep 2020 11:57:08 +0200 Subject: [PATCH 1/3] i2c: i801: Exclude device from suspend direct complete optimization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By default, PCI drivers with runtime PM enabled will skip the calls to suspend and resume on system PM. For this driver, we don't want that, as we need to perform additional steps for system PM to work properly on all systems. So instruct the PM core to not skip these calls. Fixes: a9c8088c7988 ("i2c: i801: Don't restore config registers on runtime PM") Reported-by: Volker RĂ¼melin Signed-off-by: Jean Delvare Cc: stable@vger.kernel.org Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index ebb4c0b03057..bffca729e1c7 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1917,6 +1917,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) pci_set_drvdata(dev, priv); + dev_pm_set_driver_flags(&dev->dev, DPM_FLAG_NO_DIRECT_COMPLETE); pm_runtime_set_autosuspend_delay(&dev->dev, 1000); pm_runtime_use_autosuspend(&dev->dev); pm_runtime_put_autosuspend(&dev->dev); From a2bd970aa62f2f7f80fd0d212b1d4ccea5df4aed Mon Sep 17 00:00:00 2001 From: Nicolas VINCENT Date: Wed, 23 Sep 2020 16:08:40 +0200 Subject: [PATCH 2/3] i2c: cpm: Fix i2c_ram structure the i2c_ram structure is missing the sdmatmp field mentionned in datasheet for MPC8272 at paragraph 36.5. With this field missing, the hardware would write past the allocated memory done through cpm_muram_alloc for the i2c_ram structure and land in memory allocated for the buffers descriptors corrupting the cbd_bufaddr field. Since this field is only set during setup(), the first i2c transaction would work and the following would send data read from an arbitrary memory location. Fixes: 61045dbe9d8d ("i2c: Add support for I2C bus on Freescale CPM1/CPM2 controllers") Signed-off-by: Nicolas VINCENT Acked-by: Jochen Friedrich Acked-by: Christophe Leroy Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-cpm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 1213e1932ccb..24d584a1c9a7 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -65,6 +65,9 @@ struct i2c_ram { char res1[4]; /* Reserved */ ushort rpbase; /* Relocation pointer */ char res2[2]; /* Reserved */ + /* The following elements are only for CPM2 */ + char res3[4]; /* Reserved */ + uint sdmatmp; /* Internal */ }; #define I2COM_START 0x80 From 8947efc077168c53b84d039881a7c967086a248a Mon Sep 17 00:00:00 2001 From: Tali Perry Date: Sun, 20 Sep 2020 23:48:09 +0300 Subject: [PATCH 3/3] i2c: npcm7xx: Clear LAST bit after a failed transaction. Due to a HW issue, in some scenarios the LAST bit might remain set. This will cause an unexpected NACK after reading 16 bytes on the next read. Example: if user tries to read from a missing device, get a NACK, then if the next command is a long read ( > 16 bytes), the master will stop reading after 16 bytes. To solve this, if a command fails, check if LAST bit is still set. If it does, reset the module. Fixes: 56a1485b102e (i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver) Signed-off-by: Tali Perry Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-npcm7xx.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c index dfcf04e1967f..2ad166355ec9 100644 --- a/drivers/i2c/busses/i2c-npcm7xx.c +++ b/drivers/i2c/busses/i2c-npcm7xx.c @@ -2163,6 +2163,15 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, if (bus->cmd_err == -EAGAIN) ret = i2c_recover_bus(adap); + /* + * After any type of error, check if LAST bit is still set, + * due to a HW issue. + * It cannot be cleared without resetting the module. + */ + if (bus->cmd_err && + (NPCM_I2CRXF_CTL_LAST_PEC & ioread8(bus->reg + NPCM_I2CRXF_CTL))) + npcm_i2c_reset(bus); + #if IS_ENABLED(CONFIG_I2C_SLAVE) /* reenable slave if it was enabled */ if (bus->slave)