Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:
 "Some more I2C driver updates. IMX updates are a tad bigger, but not
  exceptionally big"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: mlxbf: Fix the return check of devm_ioremap and ioremap
  i2c: mlxbf: select CONFIG_I2C_SLAVE
  i2c: imx: Don't generate STOP condition if arbitration has been lost
  i2c: imx: Check for I2SR_IAL after every byte
  i2c: imx: Fix reset of I2SR_IAL flag
  i2c: qcom: Fix IRQ error misassignement
  i2c: qup: Fix error return code in qup_i2c_bam_schedule_desc()
This commit is contained in:
Linus Torvalds 2020-12-05 15:27:22 -08:00
commit 33256ce194
5 changed files with 47 additions and 17 deletions

View file

@ -734,6 +734,7 @@ config I2C_LPC2K
config I2C_MLXBF
tristate "Mellanox BlueField I2C controller"
depends on MELLANOX_PLATFORM && ARM64
select I2C_SLAVE
help
Enabling this option will add I2C SMBus support for Mellanox BlueField
system.

View file

@ -412,6 +412,19 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
dma->chan_using = NULL;
}
static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits)
{
unsigned int temp;
/*
* i2sr_clr_opcode is the value to clear all interrupts. Here we want to
* clear only <bits>, so we write ~i2sr_clr_opcode with just <bits>
* toggled. This is required because i.MX needs W0C and Vybrid uses W1C.
*/
temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
}
static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic)
{
unsigned long orig_jiffies = jiffies;
@ -424,8 +437,7 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool a
/* check for arbitration lost */
if (temp & I2SR_IAL) {
temp &= ~I2SR_IAL;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
return -EAGAIN;
}
@ -469,7 +481,7 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)
*/
readb_poll_timeout_atomic(addr, regval, regval & I2SR_IIF, 5, 1000 + 100);
i2c_imx->i2csr = regval;
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
i2c_imx_clear_irq(i2c_imx, I2SR_IIF | I2SR_IAL);
} else {
wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
}
@ -478,6 +490,16 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)
dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
return -ETIMEDOUT;
}
/* check for arbitration lost */
if (i2c_imx->i2csr & I2SR_IAL) {
dev_dbg(&i2c_imx->adapter.dev, "<%s> Arbitration lost\n", __func__);
i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
i2c_imx->i2csr = 0;
return -EAGAIN;
}
dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__);
i2c_imx->i2csr = 0;
return 0;
@ -593,6 +615,8 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic)
/* Stop I2C transaction */
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
if (!(temp & I2CR_MSTA))
i2c_imx->stopped = 1;
temp &= ~(I2CR_MSTA | I2CR_MTX);
if (i2c_imx->dma)
temp &= ~I2CR_DMAEN;
@ -623,9 +647,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
if (temp & I2SR_IIF) {
/* save status register */
i2c_imx->i2csr = temp;
temp &= ~I2SR_IIF;
temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
i2c_imx_clear_irq(i2c_imx, I2SR_IIF);
wake_up(&i2c_imx->queue);
return IRQ_HANDLED;
}
@ -758,8 +780,11 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
*/
dev_dbg(dev, "<%s> clear MSTA\n", __func__);
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
if (!(temp & I2CR_MSTA))
i2c_imx->stopped = 1;
temp &= ~(I2CR_MSTA | I2CR_MTX);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
if (!i2c_imx->stopped)
i2c_imx_bus_busy(i2c_imx, 0, false);
} else {
/*
@ -885,8 +910,11 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
dev_dbg(&i2c_imx->adapter.dev,
"<%s> clear MSTA\n", __func__);
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
if (!(temp & I2CR_MSTA))
i2c_imx->stopped = 1;
temp &= ~(I2CR_MSTA | I2CR_MTX);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
if (!i2c_imx->stopped)
i2c_imx_bus_busy(i2c_imx, 0, atomic);
} else {
/*

View file

@ -1258,9 +1258,9 @@ static int mlxbf_i2c_get_gpio(struct platform_device *pdev,
return -EFAULT;
gpio_res->io = devm_ioremap(dev, params->start, size);
if (IS_ERR(gpio_res->io)) {
if (!gpio_res->io) {
devm_release_mem_region(dev, params->start, size);
return PTR_ERR(gpio_res->io);
return -ENOMEM;
}
return 0;
@ -1323,9 +1323,9 @@ static int mlxbf_i2c_get_corepll(struct platform_device *pdev,
return -EFAULT;
corepll_res->io = devm_ioremap(dev, params->start, size);
if (IS_ERR(corepll_res->io)) {
if (!corepll_res->io) {
devm_release_mem_region(dev, params->start, size);
return PTR_ERR(corepll_res->io);
return -ENOMEM;
}
return 0;
@ -1717,9 +1717,9 @@ static int mlxbf_i2c_init_coalesce(struct platform_device *pdev,
return -EFAULT;
coalesce_res->io = ioremap(params->start, size);
if (IS_ERR(coalesce_res->io)) {
if (!coalesce_res->io) {
release_mem_region(params->start, size);
return PTR_ERR(coalesce_res->io);
return -ENOMEM;
}
priv->coalesce = coalesce_res;

View file

@ -194,9 +194,9 @@ static irqreturn_t cci_isr(int irq, void *dev)
if (unlikely(val & CCI_IRQ_STATUS_0_I2C_M1_ERROR)) {
if (val & CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERR ||
val & CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERR)
cci->master[0].status = -ENXIO;
cci->master[1].status = -ENXIO;
else
cci->master[0].status = -EIO;
cci->master[1].status = -EIO;
writel(CCI_HALT_REQ_I2C_M1_Q0Q1, cci->base + CCI_HALT_REQ);
ret = IRQ_HANDLED;

View file

@ -801,7 +801,8 @@ static int qup_i2c_bam_schedule_desc(struct qup_i2c_dev *qup)
if (ret || qup->bus_err || qup->qup_err) {
reinit_completion(&qup->xfer);
if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret) {
dev_err(qup->dev, "change to run state timed out");
goto desc_err;
}