Parcourir la source

Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:
 "Here are some driver bugfixes from I2C.

  Unusual this time are the two reverts. One because I accidently picked
  a patch from the list which I should have pulled from my co-maintainer
  instead ("missing of_node_put"). And one which I wrongly assumed to be
  an easy fix but it turned out already that it needs more iterations
  ("copy device properties")"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  Revert "i2c: copy device properties when using i2c_register_board_info()"
  Revert "i2c: add missing of_node_put in i2c_mux_del_adapters"
  i2c: exynos5: Avoid transaction timeouts due TRANSFER_DONE_AUTO not set
  i2c: designware: add reset interface
  i2c: meson: fix wrong variable usage in meson_i2c_put_data
  i2c: copy device properties when using i2c_register_board_info()
  i2c: m65xx: drop superfluous quirk structure
  i2c: brcmstb: Fix START and STOP conditions
  i2c: add missing of_node_put in i2c_mux_del_adapters
  i2c: riic: fix restart condition
  i2c: add missing of_node_put in i2c_mux_del_adapters
Linus Torvalds il y a 8 ans
Parent
commit
2baf38095c

+ 21 - 6
drivers/i2c/busses/i2c-brcmstb.c

@@ -465,6 +465,7 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
 	u8 *tmp_buf;
 	u8 *tmp_buf;
 	int len = 0;
 	int len = 0;
 	int xfersz = brcmstb_i2c_get_xfersz(dev);
 	int xfersz = brcmstb_i2c_get_xfersz(dev);
+	u32 cond, cond_per_msg;
 
 
 	if (dev->is_suspended)
 	if (dev->is_suspended)
 		return -EBUSY;
 		return -EBUSY;
@@ -481,10 +482,11 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
 			pmsg->buf ? pmsg->buf[0] : '0', pmsg->len);
 			pmsg->buf ? pmsg->buf[0] : '0', pmsg->len);
 
 
 		if (i < (num - 1) && (msgs[i + 1].flags & I2C_M_NOSTART))
 		if (i < (num - 1) && (msgs[i + 1].flags & I2C_M_NOSTART))
-			brcmstb_set_i2c_start_stop(dev, ~(COND_START_STOP));
+			cond = ~COND_START_STOP;
 		else
 		else
-			brcmstb_set_i2c_start_stop(dev,
-						   COND_RESTART | COND_NOSTOP);
+			cond = COND_RESTART | COND_NOSTOP;
+
+		brcmstb_set_i2c_start_stop(dev, cond);
 
 
 		/* Send slave address */
 		/* Send slave address */
 		if (!(pmsg->flags & I2C_M_NOSTART)) {
 		if (!(pmsg->flags & I2C_M_NOSTART)) {
@@ -497,13 +499,24 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
 			}
 			}
 		}
 		}
 
 
+		cond_per_msg = cond;
+
 		/* Perform data transfer */
 		/* Perform data transfer */
 		while (len) {
 		while (len) {
 			bytes_to_xfer = min(len, xfersz);
 			bytes_to_xfer = min(len, xfersz);
 
 
-			if (len <= xfersz && i == (num - 1))
-				brcmstb_set_i2c_start_stop(dev,
-							   ~(COND_START_STOP));
+			if (len <= xfersz) {
+				if (i == (num - 1))
+					cond_per_msg = cond_per_msg &
+						~(COND_RESTART | COND_NOSTOP);
+				else
+					cond_per_msg = cond;
+			} else {
+				cond_per_msg = (cond_per_msg & ~COND_RESTART) |
+					COND_NOSTOP;
+			}
+
+			brcmstb_set_i2c_start_stop(dev, cond_per_msg);
 
 
 			rc = brcmstb_i2c_xfer_bsc_data(dev, tmp_buf,
 			rc = brcmstb_i2c_xfer_bsc_data(dev, tmp_buf,
 						       bytes_to_xfer, pmsg);
 						       bytes_to_xfer, pmsg);
@@ -512,6 +525,8 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
 
 
 			len -=  bytes_to_xfer;
 			len -=  bytes_to_xfer;
 			tmp_buf += bytes_to_xfer;
 			tmp_buf += bytes_to_xfer;
+
+			cond_per_msg = COND_NOSTART | COND_NOSTOP;
 		}
 		}
 	}
 	}
 
 

+ 1 - 0
drivers/i2c/busses/i2c-designware-core.h

@@ -88,6 +88,7 @@ struct dw_i2c_dev {
 	void __iomem		*base;
 	void __iomem		*base;
 	struct completion	cmd_complete;
 	struct completion	cmd_complete;
 	struct clk		*clk;
 	struct clk		*clk;
+	struct reset_control	*rst;
 	u32			(*get_clk_rate_khz) (struct dw_i2c_dev *dev);
 	u32			(*get_clk_rate_khz) (struct dw_i2c_dev *dev);
 	struct dw_pci_controller *controller;
 	struct dw_pci_controller *controller;
 	int			cmd_err;
 	int			cmd_err;

+ 24 - 4
drivers/i2c/busses/i2c-designware-platdrv.c

@@ -38,6 +38,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
 #include <linux/property.h>
 #include <linux/property.h>
 #include <linux/io.h>
 #include <linux/io.h>
+#include <linux/reset.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
 #include <linux/platform_data/i2c-designware.h>
 #include <linux/platform_data/i2c-designware.h>
@@ -199,6 +200,14 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
 	dev->irq = irq;
 	dev->irq = irq;
 	platform_set_drvdata(pdev, dev);
 	platform_set_drvdata(pdev, dev);
 
 
+	dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+	if (IS_ERR(dev->rst)) {
+		if (PTR_ERR(dev->rst) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+	} else {
+		reset_control_deassert(dev->rst);
+	}
+
 	if (pdata) {
 	if (pdata) {
 		dev->clk_freq = pdata->i2c_scl_freq;
 		dev->clk_freq = pdata->i2c_scl_freq;
 	} else {
 	} else {
@@ -235,12 +244,13 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
 	    && dev->clk_freq != 1000000 && dev->clk_freq != 3400000) {
 	    && dev->clk_freq != 1000000 && dev->clk_freq != 3400000) {
 		dev_err(&pdev->dev,
 		dev_err(&pdev->dev,
 			"Only 100kHz, 400kHz, 1MHz and 3.4MHz supported");
 			"Only 100kHz, 400kHz, 1MHz and 3.4MHz supported");
-		return -EINVAL;
+		r = -EINVAL;
+		goto exit_reset;
 	}
 	}
 
 
 	r = i2c_dw_eval_lock_support(dev);
 	r = i2c_dw_eval_lock_support(dev);
 	if (r)
 	if (r)
-		return r;
+		goto exit_reset;
 
 
 	dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
 	dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
 
 
@@ -286,10 +296,18 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	r = i2c_dw_probe(dev);
 	r = i2c_dw_probe(dev);
-	if (r && !dev->pm_runtime_disabled)
-		pm_runtime_disable(&pdev->dev);
+	if (r)
+		goto exit_probe;
 
 
 	return r;
 	return r;
+
+exit_probe:
+	if (!dev->pm_runtime_disabled)
+		pm_runtime_disable(&pdev->dev);
+exit_reset:
+	if (!IS_ERR_OR_NULL(dev->rst))
+		reset_control_assert(dev->rst);
+	return r;
 }
 }
 
 
 static int dw_i2c_plat_remove(struct platform_device *pdev)
 static int dw_i2c_plat_remove(struct platform_device *pdev)
@@ -306,6 +324,8 @@ static int dw_i2c_plat_remove(struct platform_device *pdev)
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_put_sync(&pdev->dev);
 	if (!dev->pm_runtime_disabled)
 	if (!dev->pm_runtime_disabled)
 		pm_runtime_disable(&pdev->dev);
 		pm_runtime_disable(&pdev->dev);
+	if (!IS_ERR_OR_NULL(dev->rst))
+		reset_control_assert(dev->rst);
 
 
 	return 0;
 	return 0;
 }
 }

+ 2 - 1
drivers/i2c/busses/i2c-exynos5.c

@@ -457,7 +457,6 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
 
 
 	int_status = readl(i2c->regs + HSI2C_INT_STATUS);
 	int_status = readl(i2c->regs + HSI2C_INT_STATUS);
 	writel(int_status, i2c->regs + HSI2C_INT_STATUS);
 	writel(int_status, i2c->regs + HSI2C_INT_STATUS);
-	trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS);
 
 
 	/* handle interrupt related to the transfer status */
 	/* handle interrupt related to the transfer status */
 	if (i2c->variant->hw == HSI2C_EXYNOS7) {
 	if (i2c->variant->hw == HSI2C_EXYNOS7) {
@@ -482,11 +481,13 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
 			goto stop;
 			goto stop;
 		}
 		}
 
 
+		trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS);
 		if ((trans_status & HSI2C_MASTER_ST_MASK) == HSI2C_MASTER_ST_LOSE) {
 		if ((trans_status & HSI2C_MASTER_ST_MASK) == HSI2C_MASTER_ST_LOSE) {
 			i2c->state = -EAGAIN;
 			i2c->state = -EAGAIN;
 			goto stop;
 			goto stop;
 		}
 		}
 	} else if (int_status & HSI2C_INT_I2C) {
 	} else if (int_status & HSI2C_INT_I2C) {
+		trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS);
 		if (trans_status & HSI2C_NO_DEV_ACK) {
 		if (trans_status & HSI2C_NO_DEV_ACK) {
 			dev_dbg(i2c->dev, "No ACK from device\n");
 			dev_dbg(i2c->dev, "No ACK from device\n");
 			i2c->state = -ENXIO;
 			i2c->state = -ENXIO;

+ 1 - 1
drivers/i2c/busses/i2c-meson.c

@@ -175,7 +175,7 @@ static void meson_i2c_put_data(struct meson_i2c *i2c, char *buf, int len)
 		wdata1 |= *buf++ << ((i - 4) * 8);
 		wdata1 |= *buf++ << ((i - 4) * 8);
 
 
 	writel(wdata0, i2c->regs + REG_TOK_WDATA0);
 	writel(wdata0, i2c->regs + REG_TOK_WDATA0);
-	writel(wdata0, i2c->regs + REG_TOK_WDATA1);
+	writel(wdata1, i2c->regs + REG_TOK_WDATA1);
 
 
 	dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__,
 	dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__,
 		wdata0, wdata1, len);
 		wdata0, wdata1, len);

+ 0 - 9
drivers/i2c/busses/i2c-mt65xx.c

@@ -172,14 +172,6 @@ static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
 	.max_comb_2nd_msg_len = 31,
 	.max_comb_2nd_msg_len = 31,
 };
 };
 
 
-static const struct i2c_adapter_quirks mt8173_i2c_quirks = {
-	.max_num_msgs = 65535,
-	.max_write_len = 65535,
-	.max_read_len = 65535,
-	.max_comb_1st_msg_len = 65535,
-	.max_comb_2nd_msg_len = 65535,
-};
-
 static const struct mtk_i2c_compatible mt6577_compat = {
 static const struct mtk_i2c_compatible mt6577_compat = {
 	.quirks = &mt6577_i2c_quirks,
 	.quirks = &mt6577_i2c_quirks,
 	.pmic_i2c = 0,
 	.pmic_i2c = 0,
@@ -199,7 +191,6 @@ static const struct mtk_i2c_compatible mt6589_compat = {
 };
 };
 
 
 static const struct mtk_i2c_compatible mt8173_compat = {
 static const struct mtk_i2c_compatible mt8173_compat = {
-	.quirks = &mt8173_i2c_quirks,
 	.pmic_i2c = 0,
 	.pmic_i2c = 0,
 	.dcm = 1,
 	.dcm = 1,
 	.auto_restart = 1,
 	.auto_restart = 1,

+ 5 - 1
drivers/i2c/busses/i2c-riic.c

@@ -218,8 +218,12 @@ static irqreturn_t riic_tend_isr(int irq, void *data)
 	}
 	}
 
 
 	if (riic->is_last || riic->err) {
 	if (riic->is_last || riic->err) {
-		riic_clear_set_bit(riic, 0, ICIER_SPIE, RIIC_ICIER);
+		riic_clear_set_bit(riic, ICIER_TEIE, ICIER_SPIE, RIIC_ICIER);
 		writeb(ICCR2_SP, riic->base + RIIC_ICCR2);
 		writeb(ICCR2_SP, riic->base + RIIC_ICCR2);
+	} else {
+		/* Transfer is complete, but do not send STOP */
+		riic_clear_set_bit(riic, ICIER_TEIE, 0, RIIC_ICIER);
+		complete(&riic->msg_done);
 	}
 	}
 
 
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;

+ 2 - 0
drivers/i2c/i2c-mux.c

@@ -429,6 +429,7 @@ void i2c_mux_del_adapters(struct i2c_mux_core *muxc)
 	while (muxc->num_adapters) {
 	while (muxc->num_adapters) {
 		struct i2c_adapter *adap = muxc->adapter[--muxc->num_adapters];
 		struct i2c_adapter *adap = muxc->adapter[--muxc->num_adapters];
 		struct i2c_mux_priv *priv = adap->algo_data;
 		struct i2c_mux_priv *priv = adap->algo_data;
+		struct device_node *np = adap->dev.of_node;
 
 
 		muxc->adapter[muxc->num_adapters] = NULL;
 		muxc->adapter[muxc->num_adapters] = NULL;
 
 
@@ -438,6 +439,7 @@ void i2c_mux_del_adapters(struct i2c_mux_core *muxc)
 
 
 		sysfs_remove_link(&priv->adap.dev.kobj, "mux_device");
 		sysfs_remove_link(&priv->adap.dev.kobj, "mux_device");
 		i2c_del_adapter(adap);
 		i2c_del_adapter(adap);
+		of_node_put(np);
 		kfree(priv);
 		kfree(priv);
 	}
 	}
 }
 }