summaryrefslogtreecommitdiff
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-amd-mp2.h1
-rw-r--r--drivers/i2c/busses/i2c-at91-core.c1
-rw-r--r--drivers/i2c/busses/i2c-at91-master.c1
-rw-r--r--drivers/i2c/busses/i2c-cadence.c1
-rw-r--r--drivers/i2c/busses/i2c-davinci.c2
-rw-r--r--drivers/i2c/busses/i2c-designware-master.c1
-rw-r--r--drivers/i2c/busses/i2c-hix5hd2.c1
-rw-r--r--drivers/i2c/busses/i2c-i801.c1
-rw-r--r--drivers/i2c/busses/i2c-img-scb.c3
-rw-r--r--drivers/i2c/busses/i2c-imx-lpi2c.c4
-rw-r--r--drivers/i2c/busses/i2c-imx.c3
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c1
-rw-r--r--drivers/i2c/busses/i2c-nvidia-gpu.c1
-rw-r--r--drivers/i2c/busses/i2c-omap.c3
-rw-r--r--drivers/i2c/busses/i2c-qcom-cci.c2
-rw-r--r--drivers/i2c/busses/i2c-qcom-geni.c249
-rw-r--r--drivers/i2c/busses/i2c-qup.c3
-rw-r--r--drivers/i2c/busses/i2c-riic.c2
-rw-r--r--drivers/i2c/busses/i2c-rzv2m.c1
-rw-r--r--drivers/i2c/busses/i2c-sprd.c2
-rw-r--r--drivers/i2c/busses/i2c-stm32f7.c5
-rw-r--r--drivers/i2c/busses/i2c-usbio.c1
-rw-r--r--drivers/i2c/busses/i2c-xiic.c1
-rw-r--r--drivers/i2c/muxes/i2c-mux-pca954x.c50
24 files changed, 248 insertions, 92 deletions
diff --git a/drivers/i2c/busses/i2c-amd-mp2.h b/drivers/i2c/busses/i2c-amd-mp2.h
index 018a42de8b1e..9b7e9494dd12 100644
--- a/drivers/i2c/busses/i2c-amd-mp2.h
+++ b/drivers/i2c/busses/i2c-amd-mp2.h
@@ -207,7 +207,6 @@ static inline void amd_mp2_pm_runtime_get(struct amd_mp2_dev *mp2_dev)
static inline void amd_mp2_pm_runtime_put(struct amd_mp2_dev *mp2_dev)
{
- pm_runtime_mark_last_busy(&mp2_dev->pci_dev->dev);
pm_runtime_put_autosuspend(&mp2_dev->pci_dev->dev);
}
diff --git a/drivers/i2c/busses/i2c-at91-core.c b/drivers/i2c/busses/i2c-at91-core.c
index edc047e3e535..b64adef778d4 100644
--- a/drivers/i2c/busses/i2c-at91-core.c
+++ b/drivers/i2c/busses/i2c-at91-core.c
@@ -313,7 +313,6 @@ static int __maybe_unused at91_twi_resume_noirq(struct device *dev)
return ret;
}
- pm_runtime_mark_last_busy(dev);
pm_request_autosuspend(dev);
at91_init_twi_bus(twi_dev);
diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c
index 59795c1c24ff..894cedbca99f 100644
--- a/drivers/i2c/busses/i2c-at91-master.c
+++ b/drivers/i2c/busses/i2c-at91-master.c
@@ -717,7 +717,6 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
ret = (ret < 0) ? ret : num;
out:
- pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
return ret;
diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
index 697d095afbe4..0fb728ade92e 100644
--- a/drivers/i2c/busses/i2c-cadence.c
+++ b/drivers/i2c/busses/i2c-cadence.c
@@ -1128,7 +1128,6 @@ out:
cdns_i2c_set_mode(CDNS_I2C_MODE_SLAVE, id);
#endif
- pm_runtime_mark_last_busy(id->dev);
pm_runtime_put_autosuspend(id->dev);
return ret;
}
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 6a3d4e9e07f4..a773ba082321 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -543,7 +543,6 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
ret = num;
out:
- pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
return ret;
@@ -821,7 +820,6 @@ static int davinci_i2c_probe(struct platform_device *pdev)
if (r)
goto err_unuse_clocks;
- pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
return 0;
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index c7a72c28786c..41e9b5ecad20 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -901,7 +901,6 @@ done:
i2c_dw_release_lock(dev);
done_nolock:
- pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
return ret;
diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c
index 5358f5ddf924..95ab910b80c0 100644
--- a/drivers/i2c/busses/i2c-hix5hd2.c
+++ b/drivers/i2c/busses/i2c-hix5hd2.c
@@ -373,7 +373,6 @@ static int hix5hd2_i2c_xfer(struct i2c_adapter *adap,
ret = num;
out:
- pm_runtime_mark_last_busy(priv->dev);
pm_runtime_put_autosuspend(priv->dev);
return ret;
}
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index cba992fa6557..57fbec1259be 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -930,7 +930,6 @@ out:
*/
iowrite8(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv));
- pm_runtime_mark_last_busy(&priv->pci_dev->dev);
pm_runtime_put_autosuspend(&priv->pci_dev->dev);
return ret;
}
diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c
index a454f9f25146..88192c25c44c 100644
--- a/drivers/i2c/busses/i2c-img-scb.c
+++ b/drivers/i2c/busses/i2c-img-scb.c
@@ -1131,7 +1131,6 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
break;
}
- pm_runtime_mark_last_busy(adap->dev.parent);
pm_runtime_put_autosuspend(adap->dev.parent);
return i2c->msg_status ? i2c->msg_status : num;
@@ -1165,7 +1164,6 @@ static int img_i2c_init(struct img_i2c *i2c)
"Unknown hardware revision (%d.%d.%d.%d)\n",
(rev >> 24) & 0xff, (rev >> 16) & 0xff,
(rev >> 8) & 0xff, rev & 0xff);
- pm_runtime_mark_last_busy(i2c->adap.dev.parent);
pm_runtime_put_autosuspend(i2c->adap.dev.parent);
return -EINVAL;
}
@@ -1317,7 +1315,6 @@ static int img_i2c_init(struct img_i2c *i2c)
/* Perform a synchronous sequence to reset the bus */
ret = img_i2c_reset_bus(i2c);
- pm_runtime_mark_last_busy(i2c->adap.dev.parent);
pm_runtime_put_autosuspend(i2c->adap.dev.parent);
return ret;
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 03b5a7e8c361..2a0962a0b441 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -363,7 +363,6 @@ static int lpi2c_imx_master_enable(struct lpi2c_imx_struct *lpi2c_imx)
return 0;
rpm_put:
- pm_runtime_mark_last_busy(lpi2c_imx->adapter.dev.parent);
pm_runtime_put_autosuspend(lpi2c_imx->adapter.dev.parent);
return ret;
@@ -377,7 +376,6 @@ static int lpi2c_imx_master_disable(struct lpi2c_imx_struct *lpi2c_imx)
temp &= ~MCR_MEN;
writel(temp, lpi2c_imx->base + LPI2C_MCR);
- pm_runtime_mark_last_busy(lpi2c_imx->adapter.dev.parent);
pm_runtime_put_autosuspend(lpi2c_imx->adapter.dev.parent);
return 0;
@@ -1462,7 +1460,6 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
if (ret)
goto rpm_disable;
- pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
dev_info(&lpi2c_imx->adapter.dev, "LPI2C adapter registered\n");
@@ -1564,7 +1561,6 @@ static int lpi2c_suspend(struct device *dev)
static int lpi2c_resume(struct device *dev)
{
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return 0;
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 60f5c790ad7c..dcce882f3eba 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1637,7 +1637,6 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
result = i2c_imx_xfer_common(adapter, msgs, num, false);
- pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent);
pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent);
return result;
@@ -1822,7 +1821,6 @@ static int i2c_imx_probe(struct platform_device *pdev)
if (ret < 0)
goto clk_notifier_unregister;
- pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq);
@@ -1928,7 +1926,6 @@ static int i2c_imx_suspend(struct device *dev)
static int i2c_imx_resume(struct device *dev)
{
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return 0;
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 8fc26a511320..1acba628e16c 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -766,7 +766,6 @@ mv64xxx_i2c_xfer_core(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
drv_data->num_msgs = 0;
drv_data->msgs = NULL;
- pm_runtime_mark_last_busy(&adap->dev);
pm_runtime_put_autosuspend(&adap->dev);
return ret;
diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c
index 541d808d62d0..14c059b03945 100644
--- a/drivers/i2c/busses/i2c-nvidia-gpu.c
+++ b/drivers/i2c/busses/i2c-nvidia-gpu.c
@@ -216,7 +216,6 @@ exit:
if (status2 < 0)
dev_err(i2cd->dev, "i2c stop failed %d\n", status2);
}
- pm_runtime_mark_last_busy(i2cd->dev);
pm_runtime_put_autosuspend(i2cd->dev);
return status;
}
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 5fcc9f6c33e5..d9f590f0c384 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -828,7 +828,6 @@ omap_i2c_xfer_common(struct i2c_adapter *adap, struct i2c_msg msgs[], int num,
omap->set_mpu_wkup_lat(omap->dev, -1);
out:
- pm_runtime_mark_last_busy(omap->dev);
pm_runtime_put_autosuspend(omap->dev);
return r;
}
@@ -1510,7 +1509,6 @@ omap_i2c_probe(struct platform_device *pdev)
dev_info(omap->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr,
major, minor, omap->speed);
- pm_runtime_mark_last_busy(omap->dev);
pm_runtime_put_autosuspend(omap->dev);
return 0;
@@ -1605,7 +1603,6 @@ static int omap_i2c_suspend(struct device *dev)
static int omap_i2c_resume(struct device *dev)
{
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return 0;
diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c
index a3afa11a71a1..e631d79baf14 100644
--- a/drivers/i2c/busses/i2c-qcom-cci.c
+++ b/drivers/i2c/busses/i2c-qcom-cci.c
@@ -450,7 +450,6 @@ static int cci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
ret = num;
err:
- pm_runtime_mark_last_busy(cci->dev);
pm_runtime_put_autosuspend(cci->dev);
return ret;
@@ -508,7 +507,6 @@ static int __maybe_unused cci_suspend(struct device *dev)
static int __maybe_unused cci_resume(struct device *dev)
{
cci_resume_runtime(dev);
- pm_runtime_mark_last_busy(dev);
pm_request_autosuspend(dev);
return 0;
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 95a577764d5c..3a04016db2c3 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -77,6 +77,25 @@ enum geni_i2c_err_code {
#define XFER_TIMEOUT HZ
#define RST_TIMEOUT HZ
+#define QCOM_I2C_MIN_NUM_OF_MSGS_MULTI_DESC 2
+
+/**
+ * struct geni_i2c_gpi_multi_desc_xfer - Structure for multi transfer support
+ *
+ * @msg_idx_cnt: Current message index being processed in the transfer
+ * @unmap_msg_cnt: Number of messages that have been unmapped
+ * @irq_cnt: Number of transfer completion interrupts received
+ * @dma_buf: Array of virtual addresses for DMA-safe buffers
+ * @dma_addr: Array of DMA addresses corresponding to the buffers
+ */
+struct geni_i2c_gpi_multi_desc_xfer {
+ u32 msg_idx_cnt;
+ u32 unmap_msg_cnt;
+ u32 irq_cnt;
+ void **dma_buf;
+ dma_addr_t *dma_addr;
+};
+
struct geni_i2c_dev {
struct geni_se se;
u32 tx_wm;
@@ -99,6 +118,9 @@ struct geni_i2c_dev {
struct dma_chan *rx_c;
bool gpi_mode;
bool abort_done;
+ bool is_tx_multi_desc_xfer;
+ u32 num_msgs;
+ struct geni_i2c_gpi_multi_desc_xfer i2c_multi_desc_config;
};
struct geni_i2c_desc {
@@ -499,6 +521,7 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
static void i2c_gpi_cb_result(void *cb, const struct dmaengine_result *result)
{
struct geni_i2c_dev *gi2c = cb;
+ struct geni_i2c_gpi_multi_desc_xfer *tx_multi_xfer;
if (result->result != DMA_TRANS_NOERROR) {
dev_err(gi2c->se.dev, "DMA txn failed:%d\n", result->result);
@@ -507,6 +530,11 @@ static void i2c_gpi_cb_result(void *cb, const struct dmaengine_result *result)
dev_dbg(gi2c->se.dev, "DMA xfer has pending: %d\n", result->residue);
}
+ if (gi2c->is_tx_multi_desc_xfer) {
+ tx_multi_xfer = &gi2c->i2c_multi_desc_config;
+ tx_multi_xfer->irq_cnt++;
+ }
+
complete(&gi2c->done);
}
@@ -525,7 +553,72 @@ static void geni_i2c_gpi_unmap(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
}
}
-static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
+/**
+ * geni_i2c_gpi_multi_desc_unmap() - Unmaps DMA buffers post multi message TX transfers
+ * @gi2c: I2C dev handle
+ * @msgs: Array of I2C messages
+ * @peripheral: Pointer to gpi_i2c_config
+ */
+static void geni_i2c_gpi_multi_desc_unmap(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[],
+ struct gpi_i2c_config *peripheral)
+{
+ u32 msg_xfer_cnt, wr_idx = 0;
+ struct geni_i2c_gpi_multi_desc_xfer *tx_multi_xfer = &gi2c->i2c_multi_desc_config;
+
+ msg_xfer_cnt = gi2c->err ? tx_multi_xfer->msg_idx_cnt : tx_multi_xfer->irq_cnt;
+
+ /* Unmap the processed DMA buffers based on the received interrupt count */
+ for (; tx_multi_xfer->unmap_msg_cnt < msg_xfer_cnt; tx_multi_xfer->unmap_msg_cnt++) {
+ wr_idx = tx_multi_xfer->unmap_msg_cnt;
+ geni_i2c_gpi_unmap(gi2c, &msgs[wr_idx],
+ tx_multi_xfer->dma_buf[wr_idx],
+ tx_multi_xfer->dma_addr[wr_idx],
+ NULL, 0);
+
+ if (tx_multi_xfer->unmap_msg_cnt == gi2c->num_msgs - 1) {
+ kfree(tx_multi_xfer->dma_buf);
+ kfree(tx_multi_xfer->dma_addr);
+ break;
+ }
+ }
+}
+
+/**
+ * geni_i2c_gpi_multi_xfer_timeout_handler() - Handles multi message transfer timeout
+ * @dev: Pointer to the corresponding dev node
+ * @multi_xfer: Pointer to the geni_i2c_gpi_multi_desc_xfer
+ * @transfer_timeout_msecs: Timeout value in milliseconds
+ * @transfer_comp: Completion object of the transfer
+ *
+ * This function waits for the completion of each processed transfer messages
+ * based on the interrupts generated upon transfer completion.
+ *
+ * Return: On success returns 0, -ETIMEDOUT on timeout.
+ */
+static int geni_i2c_gpi_multi_xfer_timeout_handler(struct device *dev,
+ struct geni_i2c_gpi_multi_desc_xfer *multi_xfer,
+ u32 transfer_timeout_msecs,
+ struct completion *transfer_comp)
+{
+ int i;
+ u32 time_left;
+
+ for (i = 0; i < multi_xfer->msg_idx_cnt - 1; i++) {
+ reinit_completion(transfer_comp);
+
+ if (multi_xfer->msg_idx_cnt != multi_xfer->irq_cnt) {
+ time_left = wait_for_completion_timeout(transfer_comp,
+ transfer_timeout_msecs);
+ if (!time_left) {
+ dev_err(dev, "%s: Transfer timeout\n", __func__);
+ return -ETIMEDOUT;
+ }
+ }
+ }
+ return 0;
+}
+
+static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[],
struct dma_slave_config *config, dma_addr_t *dma_addr_p,
void **buf, unsigned int op, struct dma_chan *dma_chan)
{
@@ -537,26 +630,45 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
enum dma_transfer_direction dma_dirn;
struct dma_async_tx_descriptor *desc;
int ret;
+ struct geni_i2c_gpi_multi_desc_xfer *gi2c_gpi_xfer;
+ dma_cookie_t cookie;
+ u32 msg_idx;
peripheral = config->peripheral_config;
+ gi2c_gpi_xfer = &gi2c->i2c_multi_desc_config;
+ msg_idx = gi2c_gpi_xfer->msg_idx_cnt;
- dma_buf = i2c_get_dma_safe_msg_buf(msg, 1);
- if (!dma_buf)
- return -ENOMEM;
+ dma_buf = i2c_get_dma_safe_msg_buf(&msgs[msg_idx], 1);
+ if (!dma_buf) {
+ ret = -ENOMEM;
+ goto out;
+ }
if (op == I2C_WRITE)
map_dirn = DMA_TO_DEVICE;
else
map_dirn = DMA_FROM_DEVICE;
- addr = dma_map_single(gi2c->se.dev->parent, dma_buf, msg->len, map_dirn);
+ addr = dma_map_single(gi2c->se.dev->parent, dma_buf,
+ msgs[msg_idx].len, map_dirn);
if (dma_mapping_error(gi2c->se.dev->parent, addr)) {
- i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
- return -ENOMEM;
+ i2c_put_dma_safe_msg_buf(dma_buf, &msgs[msg_idx], false);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (gi2c->is_tx_multi_desc_xfer) {
+ flags = DMA_CTRL_ACK;
+
+ /* BEI bit to be cleared for last TRE */
+ if (msg_idx == gi2c->num_msgs - 1)
+ flags |= DMA_PREP_INTERRUPT;
+ } else {
+ flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
}
/* set the length as message for rx txn */
- peripheral->rx_len = msg->len;
+ peripheral->rx_len = msgs[msg_idx].len;
peripheral->op = op;
ret = dmaengine_slave_config(dma_chan, config);
@@ -567,14 +679,21 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
peripheral->set_config = 0;
peripheral->multi_msg = true;
- flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
if (op == I2C_WRITE)
dma_dirn = DMA_MEM_TO_DEV;
else
dma_dirn = DMA_DEV_TO_MEM;
- desc = dmaengine_prep_slave_single(dma_chan, addr, msg->len, dma_dirn, flags);
+ desc = dmaengine_prep_slave_single(dma_chan, addr, msgs[msg_idx].len,
+ dma_dirn, flags);
+ if (!desc && !(flags & DMA_PREP_INTERRUPT)) {
+ /* Retry with interrupt if not enough TREs */
+ flags |= DMA_PREP_INTERRUPT;
+ desc = dmaengine_prep_slave_single(dma_chan, addr, msgs[msg_idx].len,
+ dma_dirn, flags);
+ }
+
if (!desc) {
dev_err(gi2c->se.dev, "prep_slave_sg failed\n");
ret = -EIO;
@@ -584,15 +703,48 @@ static int geni_i2c_gpi(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
desc->callback_result = i2c_gpi_cb_result;
desc->callback_param = gi2c;
- dmaengine_submit(desc);
- *buf = dma_buf;
- *dma_addr_p = addr;
+ if (!((msgs[msg_idx].flags & I2C_M_RD) && op == I2C_WRITE))
+ gi2c_gpi_xfer->msg_idx_cnt++;
+ cookie = dmaengine_submit(desc);
+ if (dma_submit_error(cookie)) {
+ dev_err(gi2c->se.dev,
+ "%s: dmaengine_submit failed (%d)\n", __func__, cookie);
+ ret = -EINVAL;
+ goto err_config;
+ }
+
+ if (gi2c->is_tx_multi_desc_xfer) {
+ gi2c_gpi_xfer->dma_buf[msg_idx] = dma_buf;
+ gi2c_gpi_xfer->dma_addr[msg_idx] = addr;
+
+ dma_async_issue_pending(gi2c->tx_c);
+
+ if ((msg_idx == (gi2c->num_msgs - 1)) || flags & DMA_PREP_INTERRUPT) {
+ ret = geni_i2c_gpi_multi_xfer_timeout_handler(gi2c->se.dev, gi2c_gpi_xfer,
+ XFER_TIMEOUT, &gi2c->done);
+ if (ret) {
+ dev_err(gi2c->se.dev,
+ "I2C multi write msg transfer timeout: %d\n",
+ ret);
+ gi2c->err = ret;
+ return ret;
+ }
+ }
+ } else {
+ /* Non multi descriptor message transfer */
+ *buf = dma_buf;
+ *dma_addr_p = addr;
+ }
return 0;
err_config:
- dma_unmap_single(gi2c->se.dev->parent, addr, msg->len, map_dirn);
- i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
+ dma_unmap_single(gi2c->se.dev->parent, addr,
+ msgs[msg_idx].len, map_dirn);
+ i2c_put_dma_safe_msg_buf(dma_buf, &msgs[msg_idx], false);
+
+out:
+ gi2c->err = ret;
return ret;
}
@@ -604,6 +756,7 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i
unsigned long time_left;
dma_addr_t tx_addr, rx_addr;
void *tx_buf = NULL, *rx_buf = NULL;
+ struct geni_i2c_gpi_multi_desc_xfer *tx_multi_xfer;
const struct geni_i2c_clk_fld *itr = gi2c->clk_fld;
config.peripheral_config = &peripheral;
@@ -617,6 +770,41 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i
peripheral.set_config = 1;
peripheral.multi_msg = false;
+ gi2c->num_msgs = num;
+ gi2c->is_tx_multi_desc_xfer = false;
+
+ tx_multi_xfer = &gi2c->i2c_multi_desc_config;
+ memset(tx_multi_xfer, 0, sizeof(struct geni_i2c_gpi_multi_desc_xfer));
+
+ /*
+ * If number of write messages are two and higher then
+ * configure hardware for multi descriptor transfers with BEI.
+ */
+ if (num >= QCOM_I2C_MIN_NUM_OF_MSGS_MULTI_DESC) {
+ gi2c->is_tx_multi_desc_xfer = true;
+ for (i = 0; i < num; i++) {
+ if (msgs[i].flags & I2C_M_RD) {
+ /*
+ * Multi descriptor transfer with BEI
+ * support is enabled for write transfers.
+ * TODO: Add BEI optimization support for
+ * read transfers later.
+ */
+ gi2c->is_tx_multi_desc_xfer = false;
+ break;
+ }
+ }
+ }
+
+ if (gi2c->is_tx_multi_desc_xfer) {
+ tx_multi_xfer->dma_buf = kcalloc(num, sizeof(void *), GFP_KERNEL);
+ tx_multi_xfer->dma_addr = kcalloc(num, sizeof(dma_addr_t), GFP_KERNEL);
+ if (!tx_multi_xfer->dma_buf || !tx_multi_xfer->dma_addr) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ }
+
for (i = 0; i < num; i++) {
gi2c->cur = &msgs[i];
gi2c->err = 0;
@@ -627,14 +815,16 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i
peripheral.stretch = 1;
peripheral.addr = msgs[i].addr;
+ if (i > 0 && (!(msgs[i].flags & I2C_M_RD)))
+ peripheral.multi_msg = false;
- ret = geni_i2c_gpi(gi2c, &msgs[i], &config,
+ ret = geni_i2c_gpi(gi2c, msgs, &config,
&tx_addr, &tx_buf, I2C_WRITE, gi2c->tx_c);
if (ret)
goto err;
if (msgs[i].flags & I2C_M_RD) {
- ret = geni_i2c_gpi(gi2c, &msgs[i], &config,
+ ret = geni_i2c_gpi(gi2c, msgs, &config,
&rx_addr, &rx_buf, I2C_READ, gi2c->rx_c);
if (ret)
goto err;
@@ -642,18 +832,24 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i
dma_async_issue_pending(gi2c->rx_c);
}
- dma_async_issue_pending(gi2c->tx_c);
-
- time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
- if (!time_left)
- gi2c->err = -ETIMEDOUT;
+ if (!gi2c->is_tx_multi_desc_xfer) {
+ dma_async_issue_pending(gi2c->tx_c);
+ time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
+ if (!time_left) {
+ dev_err(gi2c->se.dev, "%s:I2C timeout\n", __func__);
+ gi2c->err = -ETIMEDOUT;
+ }
+ }
if (gi2c->err) {
ret = gi2c->err;
goto err;
}
- geni_i2c_gpi_unmap(gi2c, &msgs[i], tx_buf, tx_addr, rx_buf, rx_addr);
+ if (!gi2c->is_tx_multi_desc_xfer)
+ geni_i2c_gpi_unmap(gi2c, &msgs[i], tx_buf, tx_addr, rx_buf, rx_addr);
+ else if (tx_multi_xfer->unmap_msg_cnt != tx_multi_xfer->irq_cnt)
+ geni_i2c_gpi_multi_desc_unmap(gi2c, msgs, &peripheral);
}
return num;
@@ -662,7 +858,11 @@ err:
dev_err(gi2c->se.dev, "GPI transfer failed: %d\n", ret);
dmaengine_terminate_sync(gi2c->rx_c);
dmaengine_terminate_sync(gi2c->tx_c);
- geni_i2c_gpi_unmap(gi2c, &msgs[i], tx_buf, tx_addr, rx_buf, rx_addr);
+ if (gi2c->is_tx_multi_desc_xfer)
+ geni_i2c_gpi_multi_desc_unmap(gi2c, msgs, &peripheral);
+ else
+ geni_i2c_gpi_unmap(gi2c, &msgs[i], tx_buf, tx_addr, rx_buf, rx_addr);
+
return ret;
}
@@ -714,7 +914,6 @@ static int geni_i2c_xfer(struct i2c_adapter *adap,
else
ret = geni_i2c_fifo_xfer(gi2c, msgs, num);
- pm_runtime_mark_last_busy(gi2c->se.dev);
pm_runtime_put_autosuspend(gi2c->se.dev);
gi2c->cur = NULL;
gi2c->err = 0;
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index fc348924d522..a0e076fc5f36 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1139,7 +1139,6 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
ret = num;
out:
- pm_runtime_mark_last_busy(qup->dev);
pm_runtime_put_autosuspend(qup->dev);
return ret;
@@ -1624,7 +1623,6 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
if (ret == 0)
ret = num;
out:
- pm_runtime_mark_last_busy(qup->dev);
pm_runtime_put_autosuspend(qup->dev);
return ret;
@@ -1991,7 +1989,6 @@ static int qup_i2c_suspend(struct device *device)
static int qup_i2c_resume(struct device *device)
{
qup_i2c_pm_resume_runtime(device);
- pm_runtime_mark_last_busy(device);
pm_request_autosuspend(device);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c
index b0ee9ac45a97..3e8f126cb7f7 100644
--- a/drivers/i2c/busses/i2c-riic.c
+++ b/drivers/i2c/busses/i2c-riic.c
@@ -206,7 +206,6 @@ static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
}
out:
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return riic->err ?: num;
@@ -452,7 +451,6 @@ static int riic_init_hw(struct riic_dev *riic)
riic_clear_set_bit(riic, ICCR1_IICRST, 0, RIIC_ICCR1);
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-rzv2m.c b/drivers/i2c/busses/i2c-rzv2m.c
index b0e9c0b62429..238714850673 100644
--- a/drivers/i2c/busses/i2c-rzv2m.c
+++ b/drivers/i2c/busses/i2c-rzv2m.c
@@ -372,7 +372,6 @@ static int rzv2m_i2c_xfer(struct i2c_adapter *adap,
ret = num;
out:
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return ret;
diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c
index 26ec34b19ad5..1b490525d8dd 100644
--- a/drivers/i2c/busses/i2c-sprd.c
+++ b/drivers/i2c/busses/i2c-sprd.c
@@ -302,7 +302,6 @@ static int sprd_i2c_xfer(struct i2c_adapter *i2c_adap,
ret = sprd_i2c_handle_msg(i2c_adap, &msgs[im++], 1);
err_msg:
- pm_runtime_mark_last_busy(i2c_dev->dev);
pm_runtime_put_autosuspend(i2c_dev->dev);
return ret < 0 ? ret : im;
@@ -559,7 +558,6 @@ static int sprd_i2c_probe(struct platform_device *pdev)
goto err_rpm_put;
}
- pm_runtime_mark_last_busy(i2c_dev->dev);
pm_runtime_put_autosuspend(i2c_dev->dev);
return 0;
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
index e6815f6cae78..dc69ed934ec8 100644
--- a/drivers/i2c/busses/i2c-stm32f7.c
+++ b/drivers/i2c/busses/i2c-stm32f7.c
@@ -1761,7 +1761,6 @@ static int stm32f7_i2c_xfer_core(struct i2c_adapter *i2c_adap,
}
pm_free:
- pm_runtime_mark_last_busy(i2c_dev->dev);
pm_runtime_put_autosuspend(i2c_dev->dev);
return (ret < 0) ? ret : num;
@@ -1870,7 +1869,6 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
}
pm_free:
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return ret;
}
@@ -1977,7 +1975,6 @@ pm_free:
if (!stm32f7_i2c_is_slave_registered(i2c_dev))
stm32f7_i2c_enable_wakeup(i2c_dev, false);
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return ret;
@@ -2015,7 +2012,6 @@ static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
stm32f7_i2c_enable_wakeup(i2c_dev, false);
}
- pm_runtime_mark_last_busy(i2c_dev->dev);
pm_runtime_put_autosuspend(i2c_dev->dev);
return 0;
@@ -2328,7 +2324,6 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
dev_info(i2c_dev->dev, "STM32F7 I2C-%d bus adapter\n", adap->nr);
- pm_runtime_mark_last_busy(i2c_dev->dev);
pm_runtime_put_autosuspend(i2c_dev->dev);
return 0;
diff --git a/drivers/i2c/busses/i2c-usbio.c b/drivers/i2c/busses/i2c-usbio.c
index d42f9ab6e9a5..e7799abf6787 100644
--- a/drivers/i2c/busses/i2c-usbio.c
+++ b/drivers/i2c/busses/i2c-usbio.c
@@ -27,6 +27,7 @@ static const struct acpi_device_id usbio_i2c_acpi_hids[] = {
{ "INTC1008" }, /* MTL */
{ "INTC10B3" }, /* ARL */
{ "INTC10B6" }, /* LNL */
+ { "INTC10D2" }, /* MTL-CVF */
{ "INTC10E3" }, /* PTL */
{ }
};
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index 607026c921d6..28015d77599d 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -1349,7 +1349,6 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
mutex_unlock(&i2c->lock);
out:
- pm_runtime_mark_last_busy(i2c->dev);
pm_runtime_put_autosuspend(i2c->dev);
return err;
}
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 75c8d08fa24e..b9f370c9f018 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -118,6 +118,7 @@ struct pca954x {
raw_spinlock_t lock;
struct regulator *supply;
+ struct gpio_desc *reset_gpio;
struct reset_control *reset_cont;
};
@@ -315,25 +316,6 @@ static u8 pca954x_regval(struct pca954x *data, u8 chan)
return 1 << chan;
}
-static void pca954x_reset_assert(struct pca954x *data)
-{
- if (data->reset_cont)
- reset_control_assert(data->reset_cont);
-}
-
-static void pca954x_reset_deassert(struct pca954x *data)
-{
- if (data->reset_cont)
- reset_control_deassert(data->reset_cont);
-}
-
-static void pca954x_reset_mux(struct pca954x *data)
-{
- pca954x_reset_assert(data);
- udelay(1);
- pca954x_reset_deassert(data);
-}
-
static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
{
struct pca954x *data = i2c_mux_priv(muxc);
@@ -347,8 +329,6 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
ret = pca954x_reg_write(muxc->parent, client, regval);
data->last_chan = ret < 0 ? 0 : regval;
}
- if (ret == -ETIMEDOUT && data->reset_cont)
- pca954x_reset_mux(data);
return ret;
}
@@ -358,7 +338,6 @@ static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
struct pca954x *data = i2c_mux_priv(muxc);
struct i2c_client *client = data->client;
s32 idle_state;
- int ret = 0;
idle_state = READ_ONCE(data->idle_state);
if (idle_state >= 0)
@@ -368,10 +347,8 @@ static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
if (idle_state == MUX_IDLE_DISCONNECT) {
/* Deselect active channel */
data->last_chan = 0;
- ret = pca954x_reg_write(muxc->parent, client,
- data->last_chan);
- if (ret == -ETIMEDOUT && data->reset_cont)
- pca954x_reset_mux(data);
+ return pca954x_reg_write(muxc->parent, client,
+ data->last_chan);
}
/* otherwise leave as-is */
@@ -550,10 +527,29 @@ static int pca954x_get_reset(struct device *dev, struct pca954x *data)
if (IS_ERR(data->reset_cont))
return dev_err_probe(dev, PTR_ERR(data->reset_cont),
"Failed to get reset\n");
+ else if (data->reset_cont)
+ return 0;
+
+ /*
+ * fallback to legacy reset-gpios
+ */
+ data->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(data->reset_gpio)) {
+ return dev_err_probe(dev, PTR_ERR(data->reset_gpio),
+ "Failed to get reset gpio");
+ }
return 0;
}
+static void pca954x_reset_deassert(struct pca954x *data)
+{
+ if (data->reset_cont)
+ reset_control_deassert(data->reset_cont);
+ else
+ gpiod_set_value_cansleep(data->reset_gpio, 0);
+}
+
/*
* I2C init/probing/exit functions
*/
@@ -593,7 +589,7 @@ static int pca954x_probe(struct i2c_client *client)
if (ret)
goto fail_cleanup;
- if (data->reset_cont) {
+ if (data->reset_cont || data->reset_gpio) {
udelay(1);
pca954x_reset_deassert(data);
/* Give the chip some time to recover. */