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:
Коммит
33256ce194
|
@ -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.
|
||||
|
|
|
@ -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,9 +780,12 @@ 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);
|
||||
i2c_imx_bus_busy(i2c_imx, 0, false);
|
||||
if (!i2c_imx->stopped)
|
||||
i2c_imx_bus_busy(i2c_imx, 0, false);
|
||||
} else {
|
||||
/*
|
||||
* For i2c master receiver repeat restart operation like:
|
||||
|
@ -885,9 +910,12 @@ 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);
|
||||
i2c_imx_bus_busy(i2c_imx, 0, atomic);
|
||||
if (!i2c_imx->stopped)
|
||||
i2c_imx_bus_busy(i2c_imx, 0, atomic);
|
||||
} else {
|
||||
/*
|
||||
* For i2c master receiver repeat restart operation like:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче