Skip to content

Commit 3b77001

Browse files
Wolfram SangWolfram Sang
authored andcommitted
i2c: rcar: handle RXDMA HW behaviour on Gen3
On Gen3, we can only do RXDMA once per transfer reliably. For that, we must reset the device, then we can have RXDMA once. This patch implements this. When there is no reset controller or the reset fails, RXDMA will be blocked completely. Otherwise, it will be disabled after the first RXDMA transfer. Based on a commit from the BSP by Hiromitsu Yamasaki, yet completely refactored to handle multiple read messages within one transfer. Signed-off-by: Wolfram Sang <[email protected]> Reviewed-by: Geert Uytterhoeven <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 263fe5d commit 3b77001

File tree

1 file changed

+51
-3
lines changed

1 file changed

+51
-3
lines changed

drivers/i2c/busses/i2c-rcar.c

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <linux/of_device.h>
3333
#include <linux/platform_device.h>
3434
#include <linux/pm_runtime.h>
35+
#include <linux/reset.h>
3536
#include <linux/slab.h>
3637

3738
/* register offsets */
@@ -111,8 +112,9 @@
111112
#define ID_ARBLOST (1 << 3)
112113
#define ID_NACK (1 << 4)
113114
/* persistent flags */
115+
#define ID_P_NO_RXDMA (1 << 30) /* HW forbids RXDMA sometimes */
114116
#define ID_P_PM_BLOCKED (1 << 31)
115-
#define ID_P_MASK ID_P_PM_BLOCKED
117+
#define ID_P_MASK (ID_P_PM_BLOCKED | ID_P_NO_RXDMA)
116118

117119
enum rcar_i2c_type {
118120
I2C_RCAR_GEN1,
@@ -141,6 +143,8 @@ struct rcar_i2c_priv {
141143
struct dma_chan *dma_rx;
142144
struct scatterlist sg;
143145
enum dma_data_direction dma_direction;
146+
147+
struct reset_control *rstc;
144148
};
145149

146150
#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
@@ -371,6 +375,11 @@ static void rcar_i2c_dma_unmap(struct rcar_i2c_priv *priv)
371375
dma_unmap_single(chan->device->dev, sg_dma_address(&priv->sg),
372376
sg_dma_len(&priv->sg), priv->dma_direction);
373377

378+
/* Gen3 can only do one RXDMA per transfer and we just completed it */
379+
if (priv->devtype == I2C_RCAR_GEN3 &&
380+
priv->dma_direction == DMA_FROM_DEVICE)
381+
priv->flags |= ID_P_NO_RXDMA;
382+
374383
priv->dma_direction = DMA_NONE;
375384
}
376385

@@ -408,8 +417,9 @@ static void rcar_i2c_dma(struct rcar_i2c_priv *priv)
408417
unsigned char *buf;
409418
int len;
410419

411-
/* Do not use DMA if it's not available or for messages < 8 bytes */
412-
if (IS_ERR(chan) || msg->len < 8 || !(msg->flags & I2C_M_DMA_SAFE))
420+
/* Do various checks to see if DMA is feasible at all */
421+
if (IS_ERR(chan) || msg->len < 8 || !(msg->flags & I2C_M_DMA_SAFE) ||
422+
(read && priv->flags & ID_P_NO_RXDMA))
413423
return;
414424

415425
if (read) {
@@ -740,6 +750,25 @@ static void rcar_i2c_release_dma(struct rcar_i2c_priv *priv)
740750
}
741751
}
742752

753+
/* I2C is a special case, we need to poll the status of a reset */
754+
static int rcar_i2c_do_reset(struct rcar_i2c_priv *priv)
755+
{
756+
int i, ret;
757+
758+
ret = reset_control_reset(priv->rstc);
759+
if (ret)
760+
return ret;
761+
762+
for (i = 0; i < LOOP_TIMEOUT; i++) {
763+
ret = reset_control_status(priv->rstc);
764+
if (ret == 0)
765+
return 0;
766+
udelay(1);
767+
}
768+
769+
return -ETIMEDOUT;
770+
}
771+
743772
static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
744773
struct i2c_msg *msgs,
745774
int num)
@@ -751,6 +780,16 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
751780

752781
pm_runtime_get_sync(dev);
753782

783+
/* Gen3 needs a reset before allowing RXDMA once */
784+
if (priv->devtype == I2C_RCAR_GEN3) {
785+
priv->flags |= ID_P_NO_RXDMA;
786+
if (!IS_ERR(priv->rstc)) {
787+
ret = rcar_i2c_do_reset(priv);
788+
if (ret == 0)
789+
priv->flags &= ~ID_P_NO_RXDMA;
790+
}
791+
}
792+
754793
rcar_i2c_init(priv);
755794

756795
ret = rcar_i2c_bus_barrier(priv);
@@ -921,6 +960,15 @@ static int rcar_i2c_probe(struct platform_device *pdev)
921960
if (ret < 0)
922961
goto out_pm_put;
923962

963+
if (priv->devtype == I2C_RCAR_GEN3) {
964+
priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
965+
if (!IS_ERR(priv->rstc)) {
966+
ret = reset_control_status(priv->rstc);
967+
if (ret < 0)
968+
priv->rstc = ERR_PTR(-ENOTSUPP);
969+
}
970+
}
971+
924972
/* Stay always active when multi-master to keep arbitration working */
925973
if (of_property_read_bool(dev->of_node, "multi-master"))
926974
priv->flags |= ID_P_PM_BLOCKED;

0 commit comments

Comments
 (0)