Merge branch 'i2c/for-current-fixed' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fixes from Wolfram Sang: "A set of driver bugfixes for the I2C subsystem" * 'i2c/for-current-fixed' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: uniphier-f: fix violation of tLOW requirement for Fast-mode i2c: uniphier: fix violation of tLOW requirement for Fast-mode i2c: uniphier-f: fill TX-FIFO only in IRQ handler for repeated START i2c: uniphier-f: fix timeout error after reading 8 bytes i2c: scmi: Fix probe error on devices with an empty SMB0001 ACPI device node i2c: axxia: properly handle master timeout i2c: rcar: check bus state before reinitializing i2c: nvidia-gpu: limit reads also for combined messages i2c: nvidia-gpu: adhere to I2C fault codes
This commit is contained in:
commit
52f842ccd6
@ -74,8 +74,7 @@
|
||||
MST_STATUS_ND)
|
||||
#define MST_STATUS_ERR (MST_STATUS_NAK | \
|
||||
MST_STATUS_AL | \
|
||||
MST_STATUS_IP | \
|
||||
MST_STATUS_TSS)
|
||||
MST_STATUS_IP)
|
||||
#define MST_TX_BYTES_XFRD 0x50
|
||||
#define MST_RX_BYTES_XFRD 0x54
|
||||
#define SCL_HIGH_PERIOD 0x80
|
||||
@ -241,7 +240,7 @@ static int axxia_i2c_empty_rx_fifo(struct axxia_i2c_dev *idev)
|
||||
*/
|
||||
if (c <= 0 || c > I2C_SMBUS_BLOCK_MAX) {
|
||||
idev->msg_err = -EPROTO;
|
||||
i2c_int_disable(idev, ~0);
|
||||
i2c_int_disable(idev, ~MST_STATUS_TSS);
|
||||
complete(&idev->msg_complete);
|
||||
break;
|
||||
}
|
||||
@ -299,14 +298,19 @@ static irqreturn_t axxia_i2c_isr(int irq, void *_dev)
|
||||
|
||||
if (status & MST_STATUS_SCC) {
|
||||
/* Stop completed */
|
||||
i2c_int_disable(idev, ~0);
|
||||
i2c_int_disable(idev, ~MST_STATUS_TSS);
|
||||
complete(&idev->msg_complete);
|
||||
} else if (status & MST_STATUS_SNS) {
|
||||
/* Transfer done */
|
||||
i2c_int_disable(idev, ~0);
|
||||
i2c_int_disable(idev, ~MST_STATUS_TSS);
|
||||
if (i2c_m_rd(idev->msg) && idev->msg_xfrd < idev->msg->len)
|
||||
axxia_i2c_empty_rx_fifo(idev);
|
||||
complete(&idev->msg_complete);
|
||||
} else if (status & MST_STATUS_TSS) {
|
||||
/* Transfer timeout */
|
||||
idev->msg_err = -ETIMEDOUT;
|
||||
i2c_int_disable(idev, ~MST_STATUS_TSS);
|
||||
complete(&idev->msg_complete);
|
||||
} else if (unlikely(status & MST_STATUS_ERR)) {
|
||||
/* Transfer error */
|
||||
i2c_int_disable(idev, ~0);
|
||||
@ -339,10 +343,10 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
|
||||
u32 rx_xfer, tx_xfer;
|
||||
u32 addr_1, addr_2;
|
||||
unsigned long time_left;
|
||||
unsigned int wt_value;
|
||||
|
||||
idev->msg = msg;
|
||||
idev->msg_xfrd = 0;
|
||||
idev->msg_err = 0;
|
||||
reinit_completion(&idev->msg_complete);
|
||||
|
||||
if (i2c_m_ten(msg)) {
|
||||
@ -383,9 +387,18 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
|
||||
else if (axxia_i2c_fill_tx_fifo(idev) != 0)
|
||||
int_mask |= MST_STATUS_TFL;
|
||||
|
||||
wt_value = WT_VALUE(readl(idev->base + WAIT_TIMER_CONTROL));
|
||||
/* Disable wait timer temporarly */
|
||||
writel(wt_value, idev->base + WAIT_TIMER_CONTROL);
|
||||
/* Check if timeout error happened */
|
||||
if (idev->msg_err)
|
||||
goto out;
|
||||
|
||||
/* Start manual mode */
|
||||
writel(CMD_MANUAL, idev->base + MST_COMMAND);
|
||||
|
||||
writel(WT_EN | wt_value, idev->base + WAIT_TIMER_CONTROL);
|
||||
|
||||
i2c_int_enable(idev, int_mask);
|
||||
|
||||
time_left = wait_for_completion_timeout(&idev->msg_complete,
|
||||
@ -396,13 +409,15 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
|
||||
if (readl(idev->base + MST_COMMAND) & CMD_BUSY)
|
||||
dev_warn(idev->dev, "busy after xfer\n");
|
||||
|
||||
if (time_left == 0)
|
||||
if (time_left == 0) {
|
||||
idev->msg_err = -ETIMEDOUT;
|
||||
|
||||
if (idev->msg_err == -ETIMEDOUT)
|
||||
i2c_recover_bus(&idev->adapter);
|
||||
axxia_i2c_init(idev);
|
||||
}
|
||||
|
||||
if (unlikely(idev->msg_err) && idev->msg_err != -ENXIO)
|
||||
out:
|
||||
if (unlikely(idev->msg_err) && idev->msg_err != -ENXIO &&
|
||||
idev->msg_err != -ETIMEDOUT)
|
||||
axxia_i2c_init(idev);
|
||||
|
||||
return idev->msg_err;
|
||||
@ -410,7 +425,7 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
|
||||
|
||||
static int axxia_i2c_stop(struct axxia_i2c_dev *idev)
|
||||
{
|
||||
u32 int_mask = MST_STATUS_ERR | MST_STATUS_SCC;
|
||||
u32 int_mask = MST_STATUS_ERR | MST_STATUS_SCC | MST_STATUS_TSS;
|
||||
unsigned long time_left;
|
||||
|
||||
reinit_completion(&idev->msg_complete);
|
||||
@ -437,6 +452,9 @@ axxia_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
idev->msg_err = 0;
|
||||
i2c_int_enable(idev, MST_STATUS_TSS);
|
||||
|
||||
for (i = 0; ret == 0 && i < num; ++i)
|
||||
ret = axxia_i2c_xfer_msg(idev, &msgs[i]);
|
||||
|
||||
|
@ -89,7 +89,7 @@ static int gpu_i2c_check_status(struct gpu_i2c_dev *i2cd)
|
||||
|
||||
if (time_is_before_jiffies(target)) {
|
||||
dev_err(i2cd->dev, "i2c timeout error %x\n", val);
|
||||
return -ETIME;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
val = readl(i2cd->regs + I2C_MST_CNTL);
|
||||
@ -97,9 +97,9 @@ static int gpu_i2c_check_status(struct gpu_i2c_dev *i2cd)
|
||||
case I2C_MST_CNTL_STATUS_OKAY:
|
||||
return 0;
|
||||
case I2C_MST_CNTL_STATUS_NO_ACK:
|
||||
return -EIO;
|
||||
return -ENXIO;
|
||||
case I2C_MST_CNTL_STATUS_TIMEOUT:
|
||||
return -ETIME;
|
||||
return -ETIMEDOUT;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -218,6 +218,7 @@ stop:
|
||||
|
||||
static const struct i2c_adapter_quirks gpu_i2c_quirks = {
|
||||
.max_read_len = 4,
|
||||
.max_comb_2nd_msg_len = 4,
|
||||
.flags = I2C_AQ_COMB_WRITE_THEN_READ,
|
||||
};
|
||||
|
||||
|
@ -779,6 +779,11 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
/* Check bus state before init otherwise bus busy info will be lost */
|
||||
ret = rcar_i2c_bus_barrier(priv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* Gen3 needs a reset before allowing RXDMA once */
|
||||
if (priv->devtype == I2C_RCAR_GEN3) {
|
||||
priv->flags |= ID_P_NO_RXDMA;
|
||||
@ -791,10 +796,6 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
|
||||
|
||||
rcar_i2c_init(priv);
|
||||
|
||||
ret = rcar_i2c_bus_barrier(priv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
rcar_i2c_request_dma(priv, msgs + i);
|
||||
|
||||
|
@ -367,6 +367,7 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_smbus_cmi *smbus_cmi;
|
||||
const struct acpi_device_id *id;
|
||||
int ret;
|
||||
|
||||
smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL);
|
||||
if (!smbus_cmi)
|
||||
@ -388,8 +389,10 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
|
||||
acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1,
|
||||
acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL);
|
||||
|
||||
if (smbus_cmi->cap_info == 0)
|
||||
if (smbus_cmi->cap_info == 0) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
snprintf(smbus_cmi->adapter.name, sizeof(smbus_cmi->adapter.name),
|
||||
"SMBus CMI adapter %s",
|
||||
@ -400,7 +403,8 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
|
||||
smbus_cmi->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
smbus_cmi->adapter.dev.parent = &device->dev;
|
||||
|
||||
if (i2c_add_adapter(&smbus_cmi->adapter)) {
|
||||
ret = i2c_add_adapter(&smbus_cmi->adapter);
|
||||
if (ret) {
|
||||
dev_err(&device->dev, "Couldn't register adapter!\n");
|
||||
goto err;
|
||||
}
|
||||
@ -410,7 +414,7 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
|
||||
err:
|
||||
kfree(smbus_cmi);
|
||||
device->driver_data = NULL;
|
||||
return -EIO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int acpi_smbus_cmi_remove(struct acpi_device *device)
|
||||
|
@ -173,8 +173,6 @@ static irqreturn_t uniphier_fi2c_interrupt(int irq, void *dev_id)
|
||||
"interrupt: enabled_irqs=%04x, irq_status=%04x\n",
|
||||
priv->enabled_irqs, irq_status);
|
||||
|
||||
uniphier_fi2c_clear_irqs(priv, irq_status);
|
||||
|
||||
if (irq_status & UNIPHIER_FI2C_INT_STOP)
|
||||
goto complete;
|
||||
|
||||
@ -214,7 +212,13 @@ static irqreturn_t uniphier_fi2c_interrupt(int irq, void *dev_id)
|
||||
|
||||
if (irq_status & (UNIPHIER_FI2C_INT_RF | UNIPHIER_FI2C_INT_RB)) {
|
||||
uniphier_fi2c_drain_rxfifo(priv);
|
||||
if (!priv->len)
|
||||
/*
|
||||
* If the number of bytes to read is multiple of the FIFO size
|
||||
* (msg->len == 8, 16, 24, ...), the INT_RF bit is set a little
|
||||
* earlier than INT_RB. We wait for INT_RB to confirm the
|
||||
* completion of the current message.
|
||||
*/
|
||||
if (!priv->len && (irq_status & UNIPHIER_FI2C_INT_RB))
|
||||
goto data_done;
|
||||
|
||||
if (unlikely(priv->flags & UNIPHIER_FI2C_MANUAL_NACK)) {
|
||||
@ -253,12 +257,20 @@ complete:
|
||||
}
|
||||
|
||||
handled:
|
||||
/*
|
||||
* This controller makes a pause while any bit of the IRQ status is
|
||||
* asserted. Clear the asserted bit to kick the controller just before
|
||||
* exiting the handler.
|
||||
*/
|
||||
uniphier_fi2c_clear_irqs(priv, irq_status);
|
||||
|
||||
spin_unlock(&priv->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void uniphier_fi2c_tx_init(struct uniphier_fi2c_priv *priv, u16 addr)
|
||||
static void uniphier_fi2c_tx_init(struct uniphier_fi2c_priv *priv, u16 addr,
|
||||
bool repeat)
|
||||
{
|
||||
priv->enabled_irqs |= UNIPHIER_FI2C_INT_TE;
|
||||
uniphier_fi2c_set_irqs(priv);
|
||||
@ -268,8 +280,12 @@ static void uniphier_fi2c_tx_init(struct uniphier_fi2c_priv *priv, u16 addr)
|
||||
/* set slave address */
|
||||
writel(UNIPHIER_FI2C_DTTX_CMD | addr << 1,
|
||||
priv->membase + UNIPHIER_FI2C_DTTX);
|
||||
/* first chunk of data */
|
||||
uniphier_fi2c_fill_txfifo(priv, true);
|
||||
/*
|
||||
* First chunk of data. For a repeated START condition, do not write
|
||||
* data to the TX fifo here to avoid the timing issue.
|
||||
*/
|
||||
if (!repeat)
|
||||
uniphier_fi2c_fill_txfifo(priv, true);
|
||||
}
|
||||
|
||||
static void uniphier_fi2c_rx_init(struct uniphier_fi2c_priv *priv, u16 addr)
|
||||
@ -350,7 +366,7 @@ static int uniphier_fi2c_master_xfer_one(struct i2c_adapter *adap,
|
||||
if (is_read)
|
||||
uniphier_fi2c_rx_init(priv, msg->addr);
|
||||
else
|
||||
uniphier_fi2c_tx_init(priv, msg->addr);
|
||||
uniphier_fi2c_tx_init(priv, msg->addr, repeat);
|
||||
|
||||
dev_dbg(&adap->dev, "start condition\n");
|
||||
/*
|
||||
@ -502,9 +518,26 @@ static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv)
|
||||
|
||||
uniphier_fi2c_reset(priv);
|
||||
|
||||
/*
|
||||
* Standard-mode: tLOW + tHIGH = 10 us
|
||||
* Fast-mode: tLOW + tHIGH = 2.5 us
|
||||
*/
|
||||
writel(cyc, priv->membase + UNIPHIER_FI2C_CYC);
|
||||
writel(cyc / 2, priv->membase + UNIPHIER_FI2C_LCTL);
|
||||
/*
|
||||
* Standard-mode: tLOW = 4.7 us, tHIGH = 4.0 us, tBUF = 4.7 us
|
||||
* Fast-mode: tLOW = 1.3 us, tHIGH = 0.6 us, tBUF = 1.3 us
|
||||
* "tLow/tHIGH = 5/4" meets both.
|
||||
*/
|
||||
writel(cyc * 5 / 9, priv->membase + UNIPHIER_FI2C_LCTL);
|
||||
/*
|
||||
* Standard-mode: tHD;STA = 4.0 us, tSU;STA = 4.7 us, tSU;STO = 4.0 us
|
||||
* Fast-mode: tHD;STA = 0.6 us, tSU;STA = 0.6 us, tSU;STO = 0.6 us
|
||||
*/
|
||||
writel(cyc / 2, priv->membase + UNIPHIER_FI2C_SSUT);
|
||||
/*
|
||||
* Standard-mode: tSU;DAT = 250 ns
|
||||
* Fast-mode: tSU;DAT = 100 ns
|
||||
*/
|
||||
writel(cyc / 16, priv->membase + UNIPHIER_FI2C_DSUT);
|
||||
|
||||
uniphier_fi2c_prepare_operation(priv);
|
||||
|
@ -320,7 +320,13 @@ static void uniphier_i2c_hw_init(struct uniphier_i2c_priv *priv)
|
||||
|
||||
uniphier_i2c_reset(priv, true);
|
||||
|
||||
writel((cyc / 2 << 16) | cyc, priv->membase + UNIPHIER_I2C_CLK);
|
||||
/*
|
||||
* Bit30-16: clock cycles of tLOW.
|
||||
* Standard-mode: tLOW = 4.7 us, tHIGH = 4.0 us
|
||||
* Fast-mode: tLOW = 1.3 us, tHIGH = 0.6 us
|
||||
* "tLow/tHIGH = 5/4" meets both.
|
||||
*/
|
||||
writel((cyc * 5 / 9 << 16) | cyc, priv->membase + UNIPHIER_I2C_CLK);
|
||||
|
||||
uniphier_i2c_reset(priv, false);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user