diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-08-19 19:22:41 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-08-19 19:22:41 +0200 |
commit | 9e6c269de404bef2fb50b9407e988083a0805e3b (patch) | |
tree | a061a61fe10789f07655d5a3dd22786759a3c134 | |
parent | Merge tag 'for-6.5-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff) | |
parent | i2c: bcm-iproc: Fix bcm_iproc_i2c_isr deadlock issue (diff) | |
download | linux-9e6c269de404bef2fb50b9407e988083a0805e3b.tar.xz linux-9e6c269de404bef2fb50b9407e988083a0805e3b.zip |
Merge tag 'i2c-for-6.5-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fixes from Wolfram Sang:
"Usual set of driver fixes. A bit more than usual because I was
unavailable for a while"
* tag 'i2c-for-6.5-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
i2c: bcm-iproc: Fix bcm_iproc_i2c_isr deadlock issue
i2c: Update documentation to use .probe() again
i2c: sun6i-p2wi: Fix an error message in probe()
i2c: hisi: Only handle the interrupt of the driver's transfer
i2c: tegra: Fix i2c-tegra DMA config option processing
i2c: tegra: Fix failure during probe deferral cleanup
i2c: designware: Handle invalid SMBus block data response length value
i2c: designware: Correct length byte validation logic
i2c: imx-lpi2c: return -EINVAL when i2c peripheral clk doesn't work
-rw-r--r-- | Documentation/i2c/writing-clients.rst | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-bcm-iproc.c | 11 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware-master.c | 16 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-hisi.c | 8 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-imx-lpi2c.c | 3 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-sun6i-p2wi.c | 3 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 3 |
7 files changed, 37 insertions, 9 deletions
diff --git a/Documentation/i2c/writing-clients.rst b/Documentation/i2c/writing-clients.rst index b7d3ae7458f8..41ddc10f1ac7 100644 --- a/Documentation/i2c/writing-clients.rst +++ b/Documentation/i2c/writing-clients.rst @@ -46,7 +46,7 @@ driver model device node, and its I2C address. }, .id_table = foo_idtable, - .probe_new = foo_probe, + .probe = foo_probe, .remove = foo_remove, /* if device autodetection is needed: */ .class = I2C_CLASS_SOMETHING, diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index 2d8342fdc25d..05c80680dff4 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -233,13 +233,14 @@ static inline u32 iproc_i2c_rd_reg(struct bcm_iproc_i2c_dev *iproc_i2c, u32 offset) { u32 val; + unsigned long flags; if (iproc_i2c->idm_base) { - spin_lock(&iproc_i2c->idm_lock); + spin_lock_irqsave(&iproc_i2c->idm_lock, flags); writel(iproc_i2c->ape_addr_mask, iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET); val = readl(iproc_i2c->base + offset); - spin_unlock(&iproc_i2c->idm_lock); + spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags); } else { val = readl(iproc_i2c->base + offset); } @@ -250,12 +251,14 @@ static inline u32 iproc_i2c_rd_reg(struct bcm_iproc_i2c_dev *iproc_i2c, static inline void iproc_i2c_wr_reg(struct bcm_iproc_i2c_dev *iproc_i2c, u32 offset, u32 val) { + unsigned long flags; + if (iproc_i2c->idm_base) { - spin_lock(&iproc_i2c->idm_lock); + spin_lock_irqsave(&iproc_i2c->idm_lock, flags); writel(iproc_i2c->ape_addr_mask, iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET); writel(val, iproc_i2c->base + offset); - spin_unlock(&iproc_i2c->idm_lock); + spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags); } else { writel(val, iproc_i2c->base + offset); } diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 3bfd7a2232db..24bef0025c98 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -588,9 +588,21 @@ i2c_dw_read(struct dw_i2c_dev *dev) u32 flags = msgs[dev->msg_read_idx].flags; regmap_read(dev->map, DW_IC_DATA_CMD, &tmp); + tmp &= DW_IC_DATA_CMD_DAT; /* Ensure length byte is a valid value */ - if (flags & I2C_M_RECV_LEN && - (tmp & DW_IC_DATA_CMD_DAT) <= I2C_SMBUS_BLOCK_MAX && tmp > 0) { + if (flags & I2C_M_RECV_LEN) { + /* + * if IC_EMPTYFIFO_HOLD_MASTER_EN is set, which cannot be + * detected from the registers, the controller can be + * disabled if the STOP bit is set. But it is only set + * after receiving block data response length in + * I2C_FUNC_SMBUS_BLOCK_DATA case. That needs to read + * another byte with STOP bit set when the block data + * response length is invalid to complete the transaction. + */ + if (!tmp || tmp > I2C_SMBUS_BLOCK_MAX) + tmp = 1; + len = i2c_dw_recv_len(dev, tmp); } *buf++ = tmp; diff --git a/drivers/i2c/busses/i2c-hisi.c b/drivers/i2c/busses/i2c-hisi.c index e067671b3ce2..0980c773cb5b 100644 --- a/drivers/i2c/busses/i2c-hisi.c +++ b/drivers/i2c/busses/i2c-hisi.c @@ -330,6 +330,14 @@ static irqreturn_t hisi_i2c_irq(int irq, void *context) struct hisi_i2c_controller *ctlr = context; u32 int_stat; + /* + * Don't handle the interrupt if cltr->completion is NULL. We may + * reach here because the interrupt is spurious or the transfer is + * started by another port (e.g. firmware) rather than us. + */ + if (!ctlr->completion) + return IRQ_NONE; + int_stat = readl(ctlr->iobase + HISI_I2C_INT_MSTAT); hisi_i2c_clear_int(ctlr, int_stat); if (!(int_stat & HISI_I2C_INT_ALL)) diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c index c3287c887c6f..150d923ca7f1 100644 --- a/drivers/i2c/busses/i2c-imx-lpi2c.c +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c @@ -209,6 +209,9 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx) lpi2c_imx_set_mode(lpi2c_imx); clk_rate = clk_get_rate(lpi2c_imx->clks[0].clk); + if (!clk_rate) + return -EINVAL; + if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST) filt = 0; else diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c index ad8270cdbd3e..fa6020dced59 100644 --- a/drivers/i2c/busses/i2c-sun6i-p2wi.c +++ b/drivers/i2c/busses/i2c-sun6i-p2wi.c @@ -250,7 +250,8 @@ static int p2wi_probe(struct platform_device *pdev) p2wi->rstc = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(p2wi->rstc)) { - dev_err(dev, "failed to retrieve reset controller: %d\n", ret); + dev_err(dev, "failed to retrieve reset controller: %pe\n", + p2wi->rstc); return PTR_ERR(p2wi->rstc); } diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index bcbbf23aa530..03fc10b45bd6 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -442,7 +442,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) if (IS_VI(i2c_dev)) return 0; - if (!i2c_dev->hw->has_apb_dma) { + if (i2c_dev->hw->has_apb_dma) { if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) { dev_dbg(i2c_dev->dev, "APB DMA support not enabled\n"); return 0; @@ -460,6 +460,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) i2c_dev->dma_chan = dma_request_chan(i2c_dev->dev, "tx"); if (IS_ERR(i2c_dev->dma_chan)) { err = PTR_ERR(i2c_dev->dma_chan); + i2c_dev->dma_chan = NULL; goto err_out; } |