diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-10-11 11:03:42 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-10-11 11:03:42 -0700 |
commit | c440f99695236ceb610606e4b5c50e150981f6c5 (patch) | |
tree | dd6820c29b25b7cad2f3fc3f03ba117c253780c1 /drivers | |
parent | 979bb59016aed7c7c58baca2307d9d13890cc6ab (diff) | |
parent | fd66bd74afe880de4f008f96a795fedee887ff44 (diff) |
Merge tag 'i2c-for-6.1-rc1-batch2' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull more i2c updates from Wolfram Sang:
- correct a variable type in the new pci1xxxx driver
- add a new SoC to the qcom-cci driver
- fix an issue with the designware driver which now got enough testing
- the aspeed driver now handles busy target backends better
* tag 'i2c-for-6.1-rc1-batch2' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
i2c: aspeed: Assert NAK when slave is busy
i2c: designware: Fix handling of real but unexpected device interrupts
i2c: qcom-cci: Add MSM8226 compatible
dt-bindings: i2c: qcom,i2c-cci: Document clocks for MSM8974
dt-bindings: i2c: qcom,i2c-cci: Document MSM8226 compatible
i2c: microchip: pci1xxxx: Fix comparison of -EPERM against an unsigned variable
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/busses/i2c-aspeed.c | 9 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.h | 7 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware-master.c | 13 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mchp-pci1xxxx.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-qcom-cci.c | 1 |
5 files changed, 28 insertions, 4 deletions
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index 185dedfebbac..c64c381b69b7 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -244,6 +244,7 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) u32 command, irq_handled = 0; struct i2c_client *slave = bus->slave; u8 value; + int ret; if (!slave) return 0; @@ -311,7 +312,13 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) break; case ASPEED_I2C_SLAVE_WRITE_REQUESTED: bus->slave_state = ASPEED_I2C_SLAVE_WRITE_RECEIVED; - i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value); + ret = i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value); + /* + * Slave ACK's on this address phase already but as the backend driver + * returns an errno, the bus driver should nack the next incoming byte. + */ + if (ret < 0) + writel(ASPEED_I2CD_M_S_RX_CMD_LAST, bus->base + ASPEED_I2C_CMD_REG); break; case ASPEED_I2C_SLAVE_WRITE_RECEIVED: i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value); diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 70b80e710990..4d3a3b464ecd 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -126,8 +126,9 @@ * status codes */ #define STATUS_IDLE 0x0 -#define STATUS_WRITE_IN_PROGRESS 0x1 -#define STATUS_READ_IN_PROGRESS 0x2 +#define STATUS_ACTIVE 0x1 +#define STATUS_WRITE_IN_PROGRESS 0x2 +#define STATUS_READ_IN_PROGRESS 0x4 /* * operation modes @@ -334,12 +335,14 @@ void i2c_dw_disable_int(struct dw_i2c_dev *dev); static inline void __i2c_dw_enable(struct dw_i2c_dev *dev) { + dev->status |= STATUS_ACTIVE; regmap_write(dev->map, DW_IC_ENABLE, 1); } static inline void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev) { regmap_write(dev->map, DW_IC_ENABLE, 0); + dev->status &= ~STATUS_ACTIVE; } void __i2c_dw_disable(struct dw_i2c_dev *dev); diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 44a94b225ed8..dc3c5a15a95b 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -716,6 +716,19 @@ static int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev) u32 stat; stat = i2c_dw_read_clear_intrbits(dev); + + if (!(dev->status & STATUS_ACTIVE)) { + /* + * Unexpected interrupt in driver point of view. State + * variables are either unset or stale so acknowledge and + * disable interrupts for suppressing further interrupts if + * interrupt really came from this HW (E.g. firmware has left + * the HW active). + */ + regmap_write(dev->map, DW_IC_INTR_MASK, 0); + return 0; + } + if (stat & DW_IC_INTR_TX_ABRT) { dev->cmd_err |= DW_IC_ERR_TX_ABRT; dev->status = STATUS_IDLE; diff --git a/drivers/i2c/busses/i2c-mchp-pci1xxxx.c b/drivers/i2c/busses/i2c-mchp-pci1xxxx.c index f5342201eb6b..09af75921147 100644 --- a/drivers/i2c/busses/i2c-mchp-pci1xxxx.c +++ b/drivers/i2c/busses/i2c-mchp-pci1xxxx.c @@ -708,7 +708,7 @@ static void pci1xxxx_i2c_init(struct pci1xxxx_i2c *i2c) void __iomem *p2 = i2c->i2c_base + SMBUS_STATUS_REG_OFF; void __iomem *p1 = i2c->i2c_base + SMB_GPR_REG; u8 regval; - u8 ret; + int ret; ret = set_sys_lock(i2c); if (ret == -EPERM) { diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index ea48e6a9cfca..87739fb4388b 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -807,6 +807,7 @@ static const struct cci_data cci_v2_data = { }; static const struct of_device_id cci_dt_match[] = { + { .compatible = "qcom,msm8226-cci", .data = &cci_v1_data}, { .compatible = "qcom,msm8916-cci", .data = &cci_v1_data}, { .compatible = "qcom,msm8974-cci", .data = &cci_v1_5_data}, { .compatible = "qcom,msm8996-cci", .data = &cci_v2_data}, |