Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd63bf22 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull i2c fixes from Wolfram Sang:
 "Some driver bugfixes"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: imx: use open drain for recovery GPIO
  i2c: rcar: handle RXDMA HW behaviour on Gen3
  i2c: imx: Fix reinit_completion() use
  i2c: davinci: Avoid zero value of CLKH
parents eb181a81 d2d0ad2a
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -237,12 +237,16 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
	/*
	 * It's not always possible to have 1 to 2 ratio when d=7, so fall back
	 * to minimal possible clkh in this case.
	 *
	 * Note:
	 * CLKH is not allowed to be 0, in this case I2C clock is not generated
	 * at all
	 */
	if (clk >= clkl + d) {
	if (clk > clkl + d) {
		clkh = clk - clkl - d;
		clkl -= d;
	} else {
		clkh = 0;
		clkh = 1;
		clkl = clk - (d << 1);
	}

+2 −3
Original line number Diff line number Diff line
@@ -368,6 +368,7 @@ static int i2c_imx_dma_xfer(struct imx_i2c_struct *i2c_imx,
		goto err_desc;
	}

	reinit_completion(&dma->cmd_complete);
	txdesc->callback = i2c_imx_dma_callback;
	txdesc->callback_param = i2c_imx;
	if (dma_submit_error(dmaengine_submit(txdesc))) {
@@ -622,7 +623,6 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
	 * The first byte must be transmitted by the CPU.
	 */
	imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
	reinit_completion(&i2c_imx->dma->cmd_complete);
	time_left = wait_for_completion_timeout(
				&i2c_imx->dma->cmd_complete,
				msecs_to_jiffies(DMA_TIMEOUT));
@@ -681,7 +681,6 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
	if (result)
		return result;

	reinit_completion(&i2c_imx->dma->cmd_complete);
	time_left = wait_for_completion_timeout(
				&i2c_imx->dma->cmd_complete,
				msecs_to_jiffies(DMA_TIMEOUT));
@@ -1010,7 +1009,7 @@ static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
	i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
			"gpio");
	rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
	rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", GPIOD_OUT_HIGH);
	rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);

	if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER ||
	    PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER) {
+51 −3
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/slab.h>

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

enum rcar_i2c_type {
	I2C_RCAR_GEN1,
@@ -141,6 +143,8 @@ struct rcar_i2c_priv {
	struct dma_chan *dma_rx;
	struct scatterlist sg;
	enum dma_data_direction dma_direction;

	struct reset_control *rstc;
};

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

	/* Gen3 can only do one RXDMA per transfer and we just completed it */
	if (priv->devtype == I2C_RCAR_GEN3 &&
	    priv->dma_direction == DMA_FROM_DEVICE)
		priv->flags |= ID_P_NO_RXDMA;

	priv->dma_direction = DMA_NONE;
}

@@ -407,8 +416,9 @@ static void rcar_i2c_dma(struct rcar_i2c_priv *priv)
	unsigned char *buf;
	int len;

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

	if (read) {
@@ -739,6 +749,25 @@ static void rcar_i2c_release_dma(struct rcar_i2c_priv *priv)
	}
}

/* I2C is a special case, we need to poll the status of a reset */
static int rcar_i2c_do_reset(struct rcar_i2c_priv *priv)
{
	int i, ret;

	ret = reset_control_reset(priv->rstc);
	if (ret)
		return ret;

	for (i = 0; i < LOOP_TIMEOUT; i++) {
		ret = reset_control_status(priv->rstc);
		if (ret == 0)
			return 0;
		udelay(1);
	}

	return -ETIMEDOUT;
}

static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
				struct i2c_msg *msgs,
				int num)
@@ -750,6 +779,16 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,

	pm_runtime_get_sync(dev);

	/* Gen3 needs a reset before allowing RXDMA once */
	if (priv->devtype == I2C_RCAR_GEN3) {
		priv->flags |= ID_P_NO_RXDMA;
		if (!IS_ERR(priv->rstc)) {
			ret = rcar_i2c_do_reset(priv);
			if (ret == 0)
				priv->flags &= ~ID_P_NO_RXDMA;
		}
	}

	rcar_i2c_init(priv);

	ret = rcar_i2c_bus_barrier(priv);
@@ -920,6 +959,15 @@ static int rcar_i2c_probe(struct platform_device *pdev)
	if (ret < 0)
		goto out_pm_put;

	if (priv->devtype == I2C_RCAR_GEN3) {
		priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
		if (!IS_ERR(priv->rstc)) {
			ret = reset_control_status(priv->rstc);
			if (ret < 0)
				priv->rstc = ERR_PTR(-ENOTSUPP);
		}
	}

	/* Stay always active when multi-master to keep arbitration working */
	if (of_property_read_bool(dev->of_node, "multi-master"))
		priv->flags |= ID_P_PM_BLOCKED;