All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/22] Improvements for Tegra I2C driver
@ 2020-09-03  0:52 Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 01/22] i2c: tegra: Make tegra_i2c_flush_fifos() usable in atomic transfer Dmitry Osipenko
                   ` (21 more replies)
  0 siblings, 22 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

Hello!

This series performs a small refactoring of the Tegra I2C driver code and
hardens the atomic-transfer mode.

Changelog:

v3: - Optimized "Make tegra_i2c_flush_fifos() usable in atomic transfer"
      patch by pre-checking FIFO state before starting to poll using
      ktime API, which may be expensive under some circumstances.

    - The "Clean up messages in the code" patch now makes all messages
      to use proper capitalization of abbreviations. Thanks to Andy Shevchenko
      and Michał Mirosław for the suggestion.

    - The "Remove unnecessary whitespaces and newlines" patch is transformed
      into "Clean up whitespaces and newlines", it now also adds missing
      newlines and spaces.

    - Reworked the "Clean up probe function" patch in accordance to
      suggestion from Michał Mirosław by factoring out only parts of
      the code that make error unwinding cleaner.

    - Added r-b from Michał Mirosław.

    - Added more patches:

        i2c: tegra: Reorder location of functions in the code
        i2c: tegra: Factor out packet header setup from tegra_i2c_xfer_msg()
        i2c: tegra: Remove "dma" variable
        i2c: tegra: Initialization div-clk rate unconditionally
        i2c: tegra: Remove i2c_dev.clk_divisor_non_hs_mode member

v2: - Cleaned more messages in the "Clean up messages in the code" patch.

    - The error code of reset_control_reset() is checked now.

    - Added these new patches to clean up couple more things:

        i2c: tegra: Check errors for both positive and negative values
        i2c: tegra: Improve coding style of tegra_i2c_wait_for_config_load()
        i2c: tegra: Remove unnecessary whitespaces and newlines
        i2c: tegra: Rename variable in tegra_i2c_issue_bus_clear()
        i2c: tegra: Improve driver module description

Dmitry Osipenko (22):
  i2c: tegra: Make tegra_i2c_flush_fifos() usable in atomic transfer
  i2c: tegra: Add missing newline before returns
  i2c: tegra: Clean up messages in the code
  i2c: tegra: Don't ignore tegra_i2c_flush_fifos() error
  i2c: tegra: Use reset_control_reset()
  i2c: tegra: Improve formatting of function variables
  i2c: tegra: Use dev_err_probe()
  i2c: tegra: Runtime PM always available on Tegra
  i2c: tegra: Clean up probe function
  i2c: tegra: Drop '_timeout' from wait/poll function names
  i2c: tegra: Remove likely/unlikely from the code
  i2c: tegra: Factor out error recovery from tegra_i2c_xfer_msg()
  i2c: tegra: Check errors for both positive and negative values
  i2c: tegra: Improve coding style of tegra_i2c_wait_for_config_load()
  i2c: tegra: Clean up whitespaces and newlines
  i2c: tegra: Rename variable in tegra_i2c_issue_bus_clear()
  i2c: tegra: Improve driver module description
  i2c: tegra: Reorder location of functions in the code
  i2c: tegra: Factor out packet header setup from tegra_i2c_xfer_msg()
  i2c: tegra: Remove "dma" variable
  i2c: tegra: Initialization div-clk rate unconditionally
  i2c: tegra: Remove i2c_dev.clk_divisor_non_hs_mode member

 drivers/i2c/busses/i2c-tegra.c | 1327 ++++++++++++++++----------------
 1 file changed, 684 insertions(+), 643 deletions(-)

-- 
2.27.0


^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v3 01/22] i2c: tegra: Make tegra_i2c_flush_fifos() usable in atomic transfer
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03 11:02   ` Andy Shevchenko
  2020-09-03  0:52 ` [PATCH v3 02/22] i2c: tegra: Add missing newline before returns Dmitry Osipenko
                   ` (20 subsequent siblings)
  21 siblings, 1 reply; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

The tegra_i2c_flush_fifos() shouldn't sleep in atomic transfer and jiffies
are not updating if interrupts are disabled. Hence let's use proper delay
functions and use ktime API in order not to hang atomic transfer. Note
that this patch doesn't fix any known problem because normally FIFO is
flushed at the time of starting a new transfer.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 00d3e4d7a01e..72f03ded2eae 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -470,7 +470,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
 
 static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
 {
-	unsigned long timeout = jiffies + HZ;
+	ktime_t ktime, ktimeout;
 	unsigned int offset;
 	u32 mask, val;
 
@@ -488,14 +488,34 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
 	val |= mask;
 	i2c_writel(i2c_dev, val, offset);
 
+	/*
+	 * ktime_get() may take up to couple milliseconds in a worst case
+	 * and normally FIFOs are flushed, hence let's check the state before
+	 * proceeding to polling.
+	 */
+	if (!(i2c_readl(i2c_dev, offset) & mask))
+		return 0;
+
+	ktime = ktime_get();
+	ktimeout = ktime_add_ms(ktime, 1000);
+
 	while (i2c_readl(i2c_dev, offset) & mask) {
-		if (time_after(jiffies, timeout)) {
-			dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n");
-			return -ETIMEDOUT;
-		}
-		usleep_range(1000, 2000);
+		if (ktime_after(ktime, ktimeout))
+			goto err_timeout;
+
+		if (i2c_dev->is_curr_atomic_xfer)
+			mdelay(1);
+		else
+			fsleep(1000);
+
+		ktime = ktime_get();
 	}
 	return 0;
+
+err_timeout:
+	dev_err(i2c_dev->dev, "FIFO flushing timed out\n");
+
+	return -ETIMEDOUT;
 }
 
 static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 02/22] i2c: tegra: Add missing newline before returns
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 01/22] i2c: tegra: Make tegra_i2c_flush_fifos() usable in atomic transfer Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 03/22] i2c: tegra: Clean up messages in the code Dmitry Osipenko
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

Some places in the code are missing a newline before return, making
code more difficult to read and creating inconsistency of the code.
This patch adds the missing newlines.

Reviewed-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 72f03ded2eae..efc6e97aeb8a 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -317,6 +317,7 @@ static unsigned long tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev,
 		reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40;
 	else if (i2c_dev->is_vi)
 		reg = 0xc00 + (reg << 2);
+
 	return reg;
 }
 
@@ -392,6 +393,7 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len)
 	dma_desc->callback_param = i2c_dev;
 	dmaengine_submit(dma_desc);
 	dma_async_issue_pending(chan);
+
 	return 0;
 }
 
@@ -510,6 +512,7 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
 
 		ktime = ktime_get();
 	}
+
 	return 0;
 
 err_timeout:
@@ -717,6 +720,7 @@ static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
 	clk_disable(i2c_dev->slow_clk);
 disable_fast_clk:
 	clk_disable(i2c_dev->fast_clk);
+
 	return ret;
 }
 
@@ -1431,6 +1435,7 @@ static u32 tegra_i2c_func(struct i2c_adapter *adap)
 
 	if (i2c_dev->hw->has_continue_xfer_support)
 		ret |= I2C_FUNC_NOSTART;
+
 	return ret;
 }
 
@@ -1898,6 +1903,7 @@ static int tegra_i2c_remove(struct platform_device *pdev)
 	clk_unprepare(i2c_dev->fast_clk);
 
 	tegra_i2c_release_dma(i2c_dev);
+
 	return 0;
 }
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 03/22] i2c: tegra: Clean up messages in the code
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 01/22] i2c: tegra: Make tegra_i2c_flush_fifos() usable in atomic transfer Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 02/22] i2c: tegra: Add missing newline before returns Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03 11:06   ` Andy Shevchenko
  2020-09-03  0:52 ` [PATCH v3 04/22] i2c: tegra: Don't ignore tegra_i2c_flush_fifos() error Dmitry Osipenko
                   ` (18 subsequent siblings)
  21 siblings, 1 reply; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

This patch unifies style of all messages in the driver by starting them
with a lowercase letter and using consistent capitalization and wording
for all messages.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 63 ++++++++++++++++------------------
 1 file changed, 30 insertions(+), 33 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index efc6e97aeb8a..79e542cf3e59 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -427,7 +427,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
 		return 0;
 
 	if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) {
-		dev_dbg(i2c_dev->dev, "Support for APB DMA not enabled!\n");
+		dev_dbg(i2c_dev->dev, "DMA support not enabled\n");
 		return 0;
 	}
 
@@ -450,7 +450,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
 	dma_buf = dma_alloc_coherent(i2c_dev->dev, i2c_dev->dma_buf_size,
 				     &dma_phys, GFP_KERNEL | __GFP_NOWARN);
 	if (!dma_buf) {
-		dev_err(i2c_dev->dev, "failed to allocate the DMA buffer\n");
+		dev_err(i2c_dev->dev, "failed to allocate DMA buffer\n");
 		err = -ENOMEM;
 		goto err_out;
 	}
@@ -682,8 +682,7 @@ static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
 
 	ret = clk_enable(i2c_dev->fast_clk);
 	if (ret < 0) {
-		dev_err(i2c_dev->dev,
-			"Enabling fast clk failed, err %d\n", ret);
+		dev_err(dev, "failed to enable fast clock: %d\n", ret);
 		return ret;
 	}
 
@@ -695,8 +694,7 @@ static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
 
 	ret = clk_enable(i2c_dev->div_clk);
 	if (ret < 0) {
-		dev_err(i2c_dev->dev,
-			"Enabling div clk failed, err %d\n", ret);
+		dev_err(dev, "failed to enable div clock: %d\n", ret);
 		goto disable_slow_clk;
 	}
 
@@ -757,8 +755,7 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
 						I2C_CONFIG_LOAD_TIMEOUT);
 
 		if (err) {
-			dev_warn(i2c_dev->dev,
-				 "timeout waiting for config load\n");
+			dev_err(i2c_dev->dev, "failed to load config\n");
 			return err;
 		}
 	}
@@ -860,7 +857,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
 				   i2c_dev->bus_clk_rate * clk_multiplier);
 		if (err) {
 			dev_err(i2c_dev->dev,
-				"failed changing clock rate: %d\n", err);
+				"failed to set div-clk rate: %d\n", err);
 			return err;
 		}
 	}
@@ -916,7 +913,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
 	status = i2c_readl(i2c_dev, I2C_INT_STATUS);
 
 	if (status == 0) {
-		dev_warn(i2c_dev->dev, "irq status 0 %08x %08x %08x\n",
+		dev_warn(i2c_dev->dev, "IRQ status 0 %08x %08x %08x\n",
 			 i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS),
 			 i2c_readl(i2c_dev, I2C_STATUS),
 			 i2c_readl(i2c_dev, I2C_CNFG));
@@ -1062,8 +1059,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
 		slv_config.device_fc = true;
 		ret = dmaengine_slave_config(chan, &slv_config);
 		if (ret < 0) {
-			dev_err(i2c_dev->dev, "DMA slave config failed: %d\n",
-				ret);
+			dev_err(i2c_dev->dev, "DMA config failed: %d\n", ret);
 			dev_err(i2c_dev->dev, "falling back to PIO\n");
 			tegra_i2c_release_dma(i2c_dev);
 			i2c_dev->is_curr_dma_xfer = false;
@@ -1173,8 +1169,7 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
 
 	reg = i2c_readl(i2c_dev, I2C_BUS_CLEAR_STATUS);
 	if (!(reg & I2C_BC_STATUS)) {
-		dev_err(i2c_dev->dev,
-			"un-recovered arbitration lost\n");
+		dev_err(i2c_dev->dev, "un-recovered arbitration lost\n");
 		return -EIO;
 	}
 
@@ -1231,8 +1226,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 			err = tegra_i2c_dma_submit(i2c_dev, xfer_size);
 			if (err < 0) {
 				dev_err(i2c_dev->dev,
-					"starting RX DMA failed, err %d\n",
-					err);
+					"starting RX DMA failed: %d\n", err);
 				return err;
 			}
 
@@ -1291,8 +1285,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 			err = tegra_i2c_dma_submit(i2c_dev, xfer_size);
 			if (err < 0) {
 				dev_err(i2c_dev->dev,
-					"starting TX DMA failed, err %d\n",
-					err);
+					"starting TX DMA failed: %d\n", err);
 				return err;
 			}
 		} else {
@@ -1310,7 +1303,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 	}
 
 	tegra_i2c_unmask_irq(i2c_dev, int_mask);
-	dev_dbg(i2c_dev->dev, "unmasked irq: %02x\n",
+	dev_dbg(i2c_dev->dev, "unmasked IRQ: %02x\n",
 		i2c_readl(i2c_dev, I2C_INT_MASK));
 
 	if (dma) {
@@ -1352,12 +1345,12 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 	tegra_i2c_mask_irq(i2c_dev, int_mask);
 
 	if (time_left == 0) {
-		dev_err(i2c_dev->dev, "i2c transfer timed out\n");
+		dev_err(i2c_dev->dev, "I2C transfer timed out\n");
 		tegra_i2c_init(i2c_dev, true);
 		return -ETIMEDOUT;
 	}
 
-	dev_dbg(i2c_dev->dev, "transfer complete: %lu %d %d\n",
+	dev_dbg(i2c_dev->dev, "transfer completed: %lu %d %d\n",
 		time_left, completion_done(&i2c_dev->msg_complete),
 		i2c_dev->msg_err);
 
@@ -1686,7 +1679,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
-		dev_err(&pdev->dev, "no irq resource\n");
+		dev_err(dev, "no IRQ resource\n");
 		return -EINVAL;
 	}
 	irq = res->start;
@@ -1694,7 +1687,8 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	div_clk = devm_clk_get(&pdev->dev, "div-clk");
 	if (IS_ERR(div_clk)) {
 		if (PTR_ERR(div_clk) != -EPROBE_DEFER)
-			dev_err(&pdev->dev, "missing controller clock\n");
+			dev_err(&pdev->dev, "failed to get div-clk: %ld\n",
+				PTR_ERR(div_clk));
 
 		return PTR_ERR(div_clk);
 	}
@@ -1715,7 +1709,9 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 
 	i2c_dev->rst = devm_reset_control_get_exclusive(&pdev->dev, "i2c");
 	if (IS_ERR(i2c_dev->rst)) {
-		dev_err(&pdev->dev, "missing controller reset\n");
+		dev_err(dev, "failed to get reset control: %pe\n",
+			i2c_dev->rst);
+
 		return PTR_ERR(i2c_dev->rst);
 	}
 
@@ -1735,7 +1731,9 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	if (!i2c_dev->hw->has_single_clk_source) {
 		fast_clk = devm_clk_get(&pdev->dev, "fast-clk");
 		if (IS_ERR(fast_clk)) {
-			dev_err(&pdev->dev, "missing fast clock\n");
+			dev_err(dev, "failed to get fast clock\n: %ld\n",
+				PTR_ERR(fast_clk));
+
 			return PTR_ERR(fast_clk);
 		}
 		i2c_dev->fast_clk = fast_clk;
@@ -1756,7 +1754,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 
 	ret = clk_prepare(i2c_dev->fast_clk);
 	if (ret < 0) {
-		dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret);
+		dev_err(dev, "failed to prepare fast clock: %d\n", ret);
 		return ret;
 	}
 
@@ -1780,7 +1778,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 
 	ret = clk_prepare(i2c_dev->div_clk);
 	if (ret < 0) {
-		dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret);
+		dev_err(dev, "failed to prepare div-clk: %d\n", ret);
 		goto unprepare_slow_clk;
 	}
 
@@ -1797,13 +1795,13 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	if (!pm_runtime_enabled(&pdev->dev)) {
 		ret = tegra_i2c_runtime_resume(&pdev->dev);
 		if (ret < 0) {
-			dev_err(&pdev->dev, "runtime resume failed\n");
+			dev_err(dev, "runtime resume failed\n");
 			goto unprepare_div_clk;
 		}
 	} else {
 		ret = pm_runtime_get_sync(i2c_dev->dev);
 		if (ret < 0) {
-			dev_err(&pdev->dev, "runtime resume failed\n");
+			dev_err(dev, "runtime resume failed\n");
 			goto disable_rpm;
 		}
 	}
@@ -1811,8 +1809,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	if (i2c_dev->is_multimaster_mode) {
 		ret = clk_enable(i2c_dev->div_clk);
 		if (ret < 0) {
-			dev_err(i2c_dev->dev, "div_clk enable failed %d\n",
-				ret);
+			dev_err(dev, "failed to enable div-clk: %d\n", ret);
 			goto put_rpm;
 		}
 	}
@@ -1826,7 +1823,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 
 	ret = tegra_i2c_init(i2c_dev, false);
 	if (ret) {
-		dev_err(&pdev->dev, "Failed to initialize i2c controller\n");
+		dev_err(dev, "failed to initialize I2C controller\n");
 		goto release_dma;
 	}
 
@@ -1835,7 +1832,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	ret = devm_request_irq(&pdev->dev, i2c_dev->irq, tegra_i2c_isr,
 			       IRQF_NO_SUSPEND, dev_name(&pdev->dev), i2c_dev);
 	if (ret) {
-		dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
+		dev_err(dev, "failed to request IRQ %i\n", i2c_dev->irq);
 		goto release_dma;
 	}
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 04/22] i2c: tegra: Don't ignore tegra_i2c_flush_fifos() error
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (2 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 03/22] i2c: tegra: Clean up messages in the code Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03 11:09   ` Andy Shevchenko
  2020-09-03  0:52 ` [PATCH v3 05/22] i2c: tegra: Use reset_control_reset() Dmitry Osipenko
                   ` (17 subsequent siblings)
  21 siblings, 1 reply; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

The tegra_i2c_flush_fifos() may fail and transfer should be aborted in
this case.

Reviewed-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 79e542cf3e59..b912a7153e3b 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1189,7 +1189,9 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 	bool dma;
 	u16 xfer_time = 100;
 
-	tegra_i2c_flush_fifos(i2c_dev);
+	err = tegra_i2c_flush_fifos(i2c_dev);
+	if (err)
+		return err;
 
 	i2c_dev->msg_buf = msg->buf;
 	i2c_dev->msg_buf_remaining = msg->len;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 05/22] i2c: tegra: Use reset_control_reset()
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (3 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 04/22] i2c: tegra: Don't ignore tegra_i2c_flush_fifos() error Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03 11:11   ` Andy Shevchenko
  2020-09-03  0:52 ` [PATCH v3 06/22] i2c: tegra: Improve formatting of function variables Dmitry Osipenko
                   ` (16 subsequent siblings)
  21 siblings, 1 reply; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

Use a single reset_control_reset() instead of assert/deasset couple in
order to make code cleaner a tad. Note that the reset_control_reset()
uses 1 microsecond delay instead of 2 that was used previously, but this
shouldn't matter. In addition don't ignore potential error of the reset.

Reviewed-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index b912a7153e3b..22f6020e79aa 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -800,9 +800,9 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
 	u32 tsu_thd;
 	u8 tlow, thigh;
 
-	reset_control_assert(i2c_dev->rst);
-	udelay(2);
-	reset_control_deassert(i2c_dev->rst);
+	err = reset_control_reset(i2c_dev->rst);
+	if (WARN_ON_ONCE(err))
+		return err;
 
 	if (i2c_dev->is_dvc)
 		tegra_dvc_init(i2c_dev);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 06/22] i2c: tegra: Improve formatting of function variables
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (4 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 05/22] i2c: tegra: Use reset_control_reset() Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 07/22] i2c: tegra: Use dev_err_probe() Dmitry Osipenko
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

Reorder the definition of variables in the code in order to make code
easier to read.

Reviewed-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 51 ++++++++++++++--------------------
 1 file changed, 21 insertions(+), 30 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 22f6020e79aa..98b1a5656518 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -419,8 +419,8 @@ static void tegra_i2c_release_dma(struct tegra_i2c_dev *i2c_dev)
 static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
 {
 	struct dma_chan *chan;
-	u32 *dma_buf;
 	dma_addr_t dma_phys;
+	u32 *dma_buf;
 	int err;
 
 	if (!i2c_dev->hw->has_apb_dma || i2c_dev->is_vi)
@@ -523,11 +523,11 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
 
 static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
 {
-	u32 val;
-	int rx_fifo_avail;
-	u8 *buf = i2c_dev->msg_buf;
 	size_t buf_remaining = i2c_dev->msg_buf_remaining;
+	u8 *buf = i2c_dev->msg_buf;
 	int words_to_transfer;
+	int rx_fifo_avail;
+	u32 val;
 
 	/*
 	 * Catch overflow due to message fully sent
@@ -584,11 +584,11 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
 
 static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
 {
-	u32 val;
-	int tx_fifo_avail;
-	u8 *buf = i2c_dev->msg_buf;
 	size_t buf_remaining = i2c_dev->msg_buf_remaining;
+	u8 *buf = i2c_dev->msg_buf;
 	int words_to_transfer;
+	int tx_fifo_avail;
+	u32 val;
 
 	if (i2c_dev->hw->has_mst_fifo) {
 		val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
@@ -794,11 +794,8 @@ static void tegra_i2c_vi_init(struct tegra_i2c_dev *i2c_dev)
 
 static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
 {
-	u32 val;
+	u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh;
 	int err;
-	u32 clk_divisor, clk_multiplier;
-	u32 tsu_thd;
-	u8 tlow, thigh;
 
 	err = reset_control_reset(i2c_dev->rst);
 	if (WARN_ON_ONCE(err))
@@ -906,9 +903,9 @@ static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev)
 
 static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
 {
-	u32 status;
 	const u32 status_err = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
 	struct tegra_i2c_dev *i2c_dev = dev_id;
+	u32 status;
 
 	status = i2c_readl(i2c_dev, I2C_INT_STATUS);
 
@@ -1012,12 +1009,11 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
 static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
 				       size_t len)
 {
-	u32 val, reg;
-	u8 dma_burst;
 	struct dma_slave_config slv_config = {0};
+	unsigned long reg_offset;
+	u32 val, reg, dma_burst;
 	struct dma_chan *chan;
 	int ret;
-	unsigned long reg_offset;
 
 	if (i2c_dev->hw->has_mst_fifo)
 		reg = I2C_MST_FIFO_CONTROL;
@@ -1142,9 +1138,9 @@ tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev,
 static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
 {
 	struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
-	int err;
 	unsigned long time_left;
 	u32 reg;
+	int err;
 
 	reinit_completion(&i2c_dev->msg_complete);
 	reg = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND |
@@ -1180,14 +1176,12 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 			      struct i2c_msg *msg,
 			      enum msg_end_type end_state)
 {
-	u32 packet_header;
-	u32 int_mask;
-	unsigned long time_left;
-	size_t xfer_size;
+	unsigned long time_left, xfer_time = 100;
+	u32 packet_header, int_mask;
 	u32 *buffer = NULL;
-	int err = 0;
+	size_t xfer_size;
 	bool dma;
-	u16 xfer_time = 100;
+	int err;
 
 	err = tegra_i2c_flush_fifos(i2c_dev);
 	if (err)
@@ -1381,8 +1375,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
 			  int num)
 {
 	struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
-	int i;
-	int ret;
+	int i, ret;
 
 	ret = pm_runtime_get_sync(i2c_dev->dev);
 	if (ret < 0) {
@@ -1437,8 +1430,8 @@ static u32 tegra_i2c_func(struct i2c_adapter *adap)
 static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
 {
 	struct device_node *np = i2c_dev->dev->of_node;
-	int ret;
 	bool multi_mode;
+	int ret;
 
 	ret = of_property_read_u32(np, "clock-frequency",
 				   &i2c_dev->bus_clk_rate);
@@ -1664,14 +1657,12 @@ MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
 static int tegra_i2c_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct clk *div_clk, *fast_clk;
 	struct tegra_i2c_dev *i2c_dev;
+	phys_addr_t base_phys;
 	struct resource *res;
-	struct clk *div_clk;
-	struct clk *fast_clk;
 	void __iomem *base;
-	phys_addr_t base_phys;
-	int irq;
-	int ret;
+	int irq, ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	base_phys = res->start;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 07/22] i2c: tegra: Use dev_err_probe()
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (5 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 06/22] i2c: tegra: Improve formatting of function variables Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 08/22] i2c: tegra: Runtime PM always available on Tegra Dmitry Osipenko
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

Use dev_err_probe() to replace the manual -EPROBE_DEFER handling, making
code cleaner.

Reviewed-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 32 ++++++++++++--------------------
 1 file changed, 12 insertions(+), 20 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 98b1a5656518..409f6bc5caa8 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1656,8 +1656,8 @@ MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
 
 static int tegra_i2c_probe(struct platform_device *pdev)
 {
+	struct clk *div_clk, *fast_clk, *slow_clk;
 	struct device *dev = &pdev->dev;
-	struct clk *div_clk, *fast_clk;
 	struct tegra_i2c_dev *i2c_dev;
 	phys_addr_t base_phys;
 	struct resource *res;
@@ -1678,13 +1678,9 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	irq = res->start;
 
 	div_clk = devm_clk_get(&pdev->dev, "div-clk");
-	if (IS_ERR(div_clk)) {
-		if (PTR_ERR(div_clk) != -EPROBE_DEFER)
-			dev_err(&pdev->dev, "failed to get div-clk: %ld\n",
-				PTR_ERR(div_clk));
-
-		return PTR_ERR(div_clk);
-	}
+	if (IS_ERR(div_clk))
+		return dev_err_probe(&pdev->dev, PTR_ERR(div_clk),
+				     "failed to get div-clk\n");
 
 	i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
 	if (!i2c_dev)
@@ -1723,24 +1719,20 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 
 	if (!i2c_dev->hw->has_single_clk_source) {
 		fast_clk = devm_clk_get(&pdev->dev, "fast-clk");
-		if (IS_ERR(fast_clk)) {
-			dev_err(dev, "failed to get fast clock\n: %ld\n",
-				PTR_ERR(fast_clk));
+		if (IS_ERR(fast_clk))
+			return dev_err_probe(&pdev->dev, PTR_ERR(fast_clk),
+					     "failed to get fast clock\n");
 
-			return PTR_ERR(fast_clk);
-		}
 		i2c_dev->fast_clk = fast_clk;
 	}
 
 	if (i2c_dev->is_vi) {
-		i2c_dev->slow_clk = devm_clk_get(dev, "slow");
-		if (IS_ERR(i2c_dev->slow_clk)) {
-			if (PTR_ERR(i2c_dev->slow_clk) != -EPROBE_DEFER)
-				dev_err(dev, "failed to get slow clock: %ld\n",
-					PTR_ERR(i2c_dev->slow_clk));
+		slow_clk = devm_clk_get(dev, "slow");
+		if (IS_ERR(slow_clk))
+			return dev_err_probe(&pdev->dev, PTR_ERR(slow_clk),
+					     "failed to get slow clock\n");
 
-			return PTR_ERR(i2c_dev->slow_clk);
-		}
+		i2c_dev->slow_clk = slow_clk;
 	}
 
 	platform_set_drvdata(pdev, i2c_dev);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 08/22] i2c: tegra: Runtime PM always available on Tegra
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (6 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 07/22] i2c: tegra: Use dev_err_probe() Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 09/22] i2c: tegra: Clean up probe function Dmitry Osipenko
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

The runtime PM is guaranteed to be always available on Tegra after commit
40b2bb1b132a ("ARM: tegra: enforce PM requirement"). Hence let's remove
all the RPM-availability checking and handling from the code.

Reviewed-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 28 ++++++----------------------
 1 file changed, 6 insertions(+), 22 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 409f6bc5caa8..a8ef8619b7ef 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1777,18 +1777,10 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 	if (!i2c_dev->is_vi)
 		pm_runtime_irq_safe(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
-	if (!pm_runtime_enabled(&pdev->dev)) {
-		ret = tegra_i2c_runtime_resume(&pdev->dev);
-		if (ret < 0) {
-			dev_err(dev, "runtime resume failed\n");
-			goto unprepare_div_clk;
-		}
-	} else {
-		ret = pm_runtime_get_sync(i2c_dev->dev);
-		if (ret < 0) {
-			dev_err(dev, "runtime resume failed\n");
-			goto disable_rpm;
-		}
+	ret = pm_runtime_get_sync(i2c_dev->dev);
+	if (ret < 0) {
+		dev_err(dev, "runtime resume failed\n");
+		goto disable_rpm;
 	}
 
 	if (i2c_dev->is_multimaster_mode) {
@@ -1846,16 +1838,10 @@ static int tegra_i2c_probe(struct platform_device *pdev)
 		clk_disable(i2c_dev->div_clk);
 
 put_rpm:
-	if (pm_runtime_enabled(&pdev->dev))
-		pm_runtime_put_sync(&pdev->dev);
-	else
-		tegra_i2c_runtime_suspend(&pdev->dev);
+	pm_runtime_put_sync(&pdev->dev);
 
 disable_rpm:
-	if (pm_runtime_enabled(&pdev->dev))
-		pm_runtime_disable(&pdev->dev);
-
-unprepare_div_clk:
+	pm_runtime_disable(&pdev->dev);
 	clk_unprepare(i2c_dev->div_clk);
 
 unprepare_slow_clk:
@@ -1877,8 +1863,6 @@ static int tegra_i2c_remove(struct platform_device *pdev)
 		clk_disable(i2c_dev->div_clk);
 
 	pm_runtime_disable(&pdev->dev);
-	if (!pm_runtime_status_suspended(&pdev->dev))
-		tegra_i2c_runtime_suspend(&pdev->dev);
 
 	clk_unprepare(i2c_dev->div_clk);
 	clk_unprepare(i2c_dev->slow_clk);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 09/22] i2c: tegra: Clean up probe function
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (7 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 08/22] i2c: tegra: Runtime PM always available on Tegra Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03 11:17   ` Andy Shevchenko
  2020-09-03  0:52 ` [PATCH v3 10/22] i2c: tegra: Drop '_timeout' from wait/poll function names Dmitry Osipenko
                   ` (12 subsequent siblings)
  21 siblings, 1 reply; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

The driver's probe function code is difficult to read and follow. This
patch reorders code of the probe function, forming logical groups that are
easy to work with. The clock and hardware initializations are factored
out into separate functions in order to keep code clean and ease error
unwinding.

Driver now makes use of devm_platform_get_and_ioremap_resource() and
platform_get_irq() which are replacing boilerplate parts of the code.

The dev_err_probe() is now used for reset control retrieval because reset
is now requested before clocks, and thus, BPMP driver that provides reset
controls for newer SoCs may cause the probe defer.

The error message of devm_request_irq() is removed because this function
takes care of printing the message by itself.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 359 ++++++++++++++++++---------------
 1 file changed, 196 insertions(+), 163 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index a8ef8619b7ef..35a5d46865bc 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -447,6 +447,9 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
 
 	i2c_dev->tx_dma_chan = chan;
 
+	i2c_dev->dma_buf_size = i2c_dev->hw->quirks->max_write_len +
+				I2C_PACKET_HEADER_SIZE;
+
 	dma_buf = dma_alloc_coherent(i2c_dev->dev, i2c_dev->dma_buf_size,
 				     &dma_phys, GFP_KERNEL | __GFP_NOWARN);
 	if (!dma_buf) {
@@ -1427,19 +1430,25 @@ static u32 tegra_i2c_func(struct i2c_adapter *adap)
 	return ret;
 }
 
-static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
+static int tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
 {
 	struct device_node *np = i2c_dev->dev->of_node;
+	u32 bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ;
 	bool multi_mode;
-	int ret;
 
-	ret = of_property_read_u32(np, "clock-frequency",
-				   &i2c_dev->bus_clk_rate);
-	if (ret)
-		i2c_dev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ; /* default clock rate */
+	of_property_read_u32(np, "clock-frequency", &bus_clk_rate);
+	i2c_dev->bus_clk_rate = bus_clk_rate;
 
 	multi_mode = of_property_read_bool(np, "multi-master");
 	i2c_dev->is_multimaster_mode = multi_mode;
+
+	if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc"))
+		i2c_dev->is_dvc = true;
+
+	if (of_device_is_compatible(np, "nvidia,tegra210-i2c-vi"))
+		i2c_dev->is_vi = true;
+
+	return 0;
 }
 
 static const struct i2c_algorithm tegra_i2c_algo = {
@@ -1654,203 +1663,234 @@ static const struct of_device_id tegra_i2c_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
 
-static int tegra_i2c_probe(struct platform_device *pdev)
+static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
 {
-	struct clk *div_clk, *fast_clk, *slow_clk;
-	struct device *dev = &pdev->dev;
-	struct tegra_i2c_dev *i2c_dev;
-	phys_addr_t base_phys;
-	struct resource *res;
-	void __iomem *base;
-	int irq, ret;
+	const struct tegra_i2c_hw_feature *hw = i2c_dev->hw;
+	struct device *dev = i2c_dev->dev;
+	struct clk *clk;
+	int err, mode;
+
+	clk = devm_clk_get(dev, "div-clk");
+	if (IS_ERR(clk))
+		return dev_err_probe(dev, PTR_ERR(clk),
+				     "failed to get div-clk\n");
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base_phys = res->start;
-	base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
+	i2c_dev->div_clk = clk;
 
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_err(dev, "no IRQ resource\n");
-		return -EINVAL;
+	if (!hw->has_single_clk_source) {
+		clk = devm_clk_get(dev, "fast-clk");
+		if (IS_ERR(clk))
+			return dev_err_probe(dev, PTR_ERR(clk),
+					     "failed to get fast-clk\n");
+
+		i2c_dev->fast_clk = clk;
 	}
-	irq = res->start;
 
-	div_clk = devm_clk_get(&pdev->dev, "div-clk");
-	if (IS_ERR(div_clk))
-		return dev_err_probe(&pdev->dev, PTR_ERR(div_clk),
-				     "failed to get div-clk\n");
+	if (i2c_dev->is_vi) {
+		clk = devm_clk_get(dev, "slow");
+		if (IS_ERR(clk))
+			return dev_err_probe(dev, PTR_ERR(clk),
+					     "failed to get slow clk\n");
 
-	i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
-	if (!i2c_dev)
-		return -ENOMEM;
+		i2c_dev->slow_clk = clk;
+	}
 
-	i2c_dev->base = base;
-	i2c_dev->base_phys = base_phys;
-	i2c_dev->div_clk = div_clk;
-	i2c_dev->adapter.algo = &tegra_i2c_algo;
-	i2c_dev->adapter.retries = 1;
-	i2c_dev->adapter.timeout = 6 * HZ;
-	i2c_dev->irq = irq;
-	i2c_dev->cont_id = pdev->id;
-	i2c_dev->dev = &pdev->dev;
+	err = clk_prepare(i2c_dev->fast_clk);
+	if (err) {
+		dev_err(dev, "failed to prepare fast clk: %d\n", err);
+		return err;
+	}
 
-	i2c_dev->rst = devm_reset_control_get_exclusive(&pdev->dev, "i2c");
-	if (IS_ERR(i2c_dev->rst)) {
-		dev_err(dev, "failed to get reset control: %pe\n",
-			i2c_dev->rst);
+	err = clk_prepare(i2c_dev->slow_clk);
+	if (err) {
+		dev_err(dev, "failed to prepare slow clk: %d\n", err);
+		goto unprepare_fast_clk;
+	}
 
-		return PTR_ERR(i2c_dev->rst);
+	err = clk_prepare(i2c_dev->div_clk);
+	if (err) {
+		dev_err(dev, "failed to prepare div-clk: %d\n", err);
+		goto unprepare_slow_clk;
 	}
 
-	tegra_i2c_parse_dt(i2c_dev);
+	if (i2c_dev->is_multimaster_mode) {
+		err = clk_enable(i2c_dev->div_clk);
+		if (err) {
+			dev_err(dev, "failed to enable div-clk: %d\n", err);
+			goto unprepare_div_clk;
+		}
+	}
 
-	i2c_dev->hw = of_device_get_match_data(&pdev->dev);
-	i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node,
-						  "nvidia,tegra20-i2c-dvc");
-	i2c_dev->is_vi = of_device_is_compatible(dev->of_node,
-						 "nvidia,tegra210-i2c-vi");
-	i2c_dev->adapter.quirks = i2c_dev->hw->quirks;
-	i2c_dev->dma_buf_size = i2c_dev->adapter.quirks->max_write_len +
-				I2C_PACKET_HEADER_SIZE;
-	init_completion(&i2c_dev->msg_complete);
-	init_completion(&i2c_dev->dma_complete);
+	switch (i2c_dev->bus_clk_rate) {
+	case I2C_MAX_FAST_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_PLUS_FREQ:
+		mode = hw->clk_divisor_fast_plus_mode;
+		break;
 
-	if (!i2c_dev->hw->has_single_clk_source) {
-		fast_clk = devm_clk_get(&pdev->dev, "fast-clk");
-		if (IS_ERR(fast_clk))
-			return dev_err_probe(&pdev->dev, PTR_ERR(fast_clk),
-					     "failed to get fast clock\n");
+	case I2C_MAX_STANDARD_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_FREQ:
+		mode = hw->clk_divisor_fast_mode;
+		break;
 
-		i2c_dev->fast_clk = fast_clk;
+	default:
+		mode = hw->clk_divisor_std_mode;
+		break;
 	}
 
-	if (i2c_dev->is_vi) {
-		slow_clk = devm_clk_get(dev, "slow");
-		if (IS_ERR(slow_clk))
-			return dev_err_probe(&pdev->dev, PTR_ERR(slow_clk),
-					     "failed to get slow clock\n");
+	i2c_dev->clk_divisor_non_hs_mode = mode;
 
-		i2c_dev->slow_clk = slow_clk;
-	}
+	return 0;
 
-	platform_set_drvdata(pdev, i2c_dev);
+unprepare_div_clk:
+	clk_unprepare(i2c_dev->div_clk);
+unprepare_slow_clk:
+	clk_unprepare(i2c_dev->slow_clk);
+unprepare_fast_clk:
+	clk_unprepare(i2c_dev->fast_clk);
 
-	ret = clk_prepare(i2c_dev->fast_clk);
-	if (ret < 0) {
-		dev_err(dev, "failed to prepare fast clock: %d\n", ret);
-		return ret;
-	}
+	return err;
+}
 
-	ret = clk_prepare(i2c_dev->slow_clk);
-	if (ret < 0) {
-		dev_err(dev, "failed to prepare slow clock: %d\n", ret);
-		goto unprepare_fast_clk;
-	}
+static void tegra_i2c_release_clocks(struct tegra_i2c_dev *i2c_dev)
+{
+	if (i2c_dev->is_multimaster_mode)
+		clk_disable(i2c_dev->div_clk);
 
-	if (i2c_dev->bus_clk_rate > I2C_MAX_FAST_MODE_FREQ &&
-	    i2c_dev->bus_clk_rate <= I2C_MAX_FAST_MODE_PLUS_FREQ)
-		i2c_dev->clk_divisor_non_hs_mode =
-				i2c_dev->hw->clk_divisor_fast_plus_mode;
-	else if (i2c_dev->bus_clk_rate > I2C_MAX_STANDARD_MODE_FREQ &&
-		 i2c_dev->bus_clk_rate <= I2C_MAX_FAST_MODE_FREQ)
-		i2c_dev->clk_divisor_non_hs_mode =
-				i2c_dev->hw->clk_divisor_fast_mode;
-	else
-		i2c_dev->clk_divisor_non_hs_mode =
-				i2c_dev->hw->clk_divisor_std_mode;
+	clk_unprepare(i2c_dev->div_clk);
+	clk_unprepare(i2c_dev->slow_clk);
+	clk_unprepare(i2c_dev->fast_clk);
+}
 
-	ret = clk_prepare(i2c_dev->div_clk);
-	if (ret < 0) {
-		dev_err(dev, "failed to prepare div-clk: %d\n", ret);
-		goto unprepare_slow_clk;
-	}
+static int tegra_i2c_init_runtime_pm_and_hardware(struct tegra_i2c_dev *i2c_dev)
+{
+	int ret;
 
 	/*
-	 * VI I2C is in VE power domain which is not always on and not
-	 * an IRQ safe. So, IRQ safe device can't be attached to a non-IRQ
-	 * safe domain as it prevents powering off the PM domain.
-	 * Also, VI I2C device don't need to use runtime IRQ safe as it will
-	 * not be used for atomic transfers.
+	 * VI I2C is in VE power domain which is not always ON and not
+	 * IRQ-safe. Thus, IRQ-safe device shouldn't be attached to a
+	 * non IRQ-safe domain because this prevents powering off the power
+	 * domain.
+	 *
+	 * VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't
+	 * be used for atomic transfers.
 	 */
 	if (!i2c_dev->is_vi)
-		pm_runtime_irq_safe(&pdev->dev);
-	pm_runtime_enable(&pdev->dev);
+		pm_runtime_irq_safe(i2c_dev->dev);
+
+	pm_runtime_enable(i2c_dev->dev);
+
 	ret = pm_runtime_get_sync(i2c_dev->dev);
 	if (ret < 0) {
-		dev_err(dev, "runtime resume failed\n");
-		goto disable_rpm;
+		dev_err(i2c_dev->dev, "runtime resume failed: %d\n", ret);
+		pm_runtime_disable(i2c_dev->dev);
+		return ret;
 	}
 
-	if (i2c_dev->is_multimaster_mode) {
-		ret = clk_enable(i2c_dev->div_clk);
-		if (ret < 0) {
-			dev_err(dev, "failed to enable div-clk: %d\n", ret);
-			goto put_rpm;
-		}
-	}
+	/* initialize hardware state */
+	ret = tegra_i2c_init(i2c_dev, false);
 
-	if (i2c_dev->hw->supports_bus_clear)
-		i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info;
+	pm_runtime_put(i2c_dev->dev);
 
-	ret = tegra_i2c_init_dma(i2c_dev);
-	if (ret < 0)
-		goto disable_div_clk;
+	return ret;
+}
 
-	ret = tegra_i2c_init(i2c_dev, false);
-	if (ret) {
-		dev_err(dev, "failed to initialize I2C controller\n");
-		goto release_dma;
-	}
+static int tegra_i2c_probe(struct platform_device *pdev)
+{
+	struct tegra_i2c_dev *i2c_dev;
+	struct resource *res;
+	int err;
 
+	i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
+	if (!i2c_dev)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, i2c_dev);
+
+	init_completion(&i2c_dev->msg_complete);
+	init_completion(&i2c_dev->dma_complete);
+
+	i2c_dev->hw = of_device_get_match_data(&pdev->dev);
+	i2c_dev->cont_id = pdev->id;
+	i2c_dev->dev = &pdev->dev;
+
+	/* initialize virt base of hardware registers */
+	i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+	if (IS_ERR(i2c_dev->base))
+		return PTR_ERR(i2c_dev->base);
+
+	/* initialize phys base of hardware registers */
+	i2c_dev->base_phys = res->start;
+
+	/* initialize controller's interrupt */
+	err = platform_get_irq(pdev, 0);
+	if (err < 0)
+		return err;
+
+	i2c_dev->irq = err;
+
+	/* interrupt will be enabled during of transfer time */
 	irq_set_status_flags(i2c_dev->irq, IRQ_NOAUTOEN);
 
-	ret = devm_request_irq(&pdev->dev, i2c_dev->irq, tegra_i2c_isr,
-			       IRQF_NO_SUSPEND, dev_name(&pdev->dev), i2c_dev);
-	if (ret) {
-		dev_err(dev, "failed to request IRQ %i\n", i2c_dev->irq);
-		goto release_dma;
+	err = devm_request_irq(i2c_dev->dev, i2c_dev->irq, tegra_i2c_isr,
+			       IRQF_NO_SUSPEND, dev_name(i2c_dev->dev),
+			       i2c_dev);
+	if (err)
+		return err;
+
+	/* initialize hardware reset control */
+	i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c");
+	if (IS_ERR(i2c_dev->rst)) {
+		dev_err_probe(i2c_dev->dev, PTR_ERR(i2c_dev->rst),
+			      "failed to get reset control\n");
+		return PTR_ERR(i2c_dev->rst);
 	}
 
-	i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
+	err = tegra_i2c_parse_dt(i2c_dev);
+	if (err)
+		return err;
+
+	err = tegra_i2c_init_clocks(i2c_dev);
+	if (err)
+		return err;
+
+	err = tegra_i2c_init_dma(i2c_dev);
+	if (err)
+		goto release_clocks;
+
+	err = tegra_i2c_init_runtime_pm_and_hardware(i2c_dev);
+	if (err)
+		goto release_dma;
+
+	i2c_dev->adapter.dev.of_node = i2c_dev->dev->of_node;
+	i2c_dev->adapter.dev.parent = i2c_dev->dev;
+	i2c_dev->adapter.retries = 1;
+	i2c_dev->adapter.timeout = 6 * HZ;
+	i2c_dev->adapter.quirks = i2c_dev->hw->quirks;
 	i2c_dev->adapter.owner = THIS_MODULE;
 	i2c_dev->adapter.class = I2C_CLASS_DEPRECATED;
-	strlcpy(i2c_dev->adapter.name, dev_name(&pdev->dev),
+	i2c_dev->adapter.algo = &tegra_i2c_algo;
+	i2c_dev->adapter.nr = i2c_dev->cont_id;
+
+	if (i2c_dev->hw->supports_bus_clear)
+		i2c_dev->adapter.bus_recovery_info = &tegra_i2c_recovery_info;
+
+	strlcpy(i2c_dev->adapter.name, dev_name(i2c_dev->dev),
 		sizeof(i2c_dev->adapter.name));
-	i2c_dev->adapter.dev.parent = &pdev->dev;
-	i2c_dev->adapter.nr = pdev->id;
-	i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
 
-	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
-	if (ret)
-		goto release_dma;
+	i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
 
-	pm_runtime_put(&pdev->dev);
+	err = i2c_add_numbered_adapter(&i2c_dev->adapter);
+	if (err)
+		goto release_rpm;
 
 	return 0;
 
+release_rpm:
+	pm_runtime_disable(i2c_dev->dev);
 release_dma:
 	tegra_i2c_release_dma(i2c_dev);
+release_clocks:
+	tegra_i2c_release_clocks(i2c_dev);
 
-disable_div_clk:
-	if (i2c_dev->is_multimaster_mode)
-		clk_disable(i2c_dev->div_clk);
-
-put_rpm:
-	pm_runtime_put_sync(&pdev->dev);
-
-disable_rpm:
-	pm_runtime_disable(&pdev->dev);
-	clk_unprepare(i2c_dev->div_clk);
-
-unprepare_slow_clk:
-	clk_unprepare(i2c_dev->slow_clk);
-
-unprepare_fast_clk:
-	clk_unprepare(i2c_dev->fast_clk);
-
-	return ret;
+	return err;
 }
 
 static int tegra_i2c_remove(struct platform_device *pdev)
@@ -1858,17 +1898,10 @@ static int tegra_i2c_remove(struct platform_device *pdev)
 	struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
 
 	i2c_del_adapter(&i2c_dev->adapter);
-
-	if (i2c_dev->is_multimaster_mode)
-		clk_disable(i2c_dev->div_clk);
-
-	pm_runtime_disable(&pdev->dev);
-
-	clk_unprepare(i2c_dev->div_clk);
-	clk_unprepare(i2c_dev->slow_clk);
-	clk_unprepare(i2c_dev->fast_clk);
+	pm_runtime_disable(i2c_dev->dev);
 
 	tegra_i2c_release_dma(i2c_dev);
+	tegra_i2c_release_clocks(i2c_dev);
 
 	return 0;
 }
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 10/22] i2c: tegra: Drop '_timeout' from wait/poll function names
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (8 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 09/22] i2c: tegra: Clean up probe function Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 11/22] i2c: tegra: Remove likely/unlikely from the code Dmitry Osipenko
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

Drop '_timeout' postfix from the wait/poll completion function names in
order to make the names shorter, making code cleaner a tad.

Reviewed-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 33 +++++++++++++++------------------
 1 file changed, 15 insertions(+), 18 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 35a5d46865bc..ca43eb86403b 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1077,10 +1077,9 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
 	i2c_writel(i2c_dev, val, reg);
 }
 
-static unsigned long
-tegra_i2c_poll_completion_timeout(struct tegra_i2c_dev *i2c_dev,
-				  struct completion *complete,
-				  unsigned int timeout_ms)
+static unsigned long tegra_i2c_poll_completion(struct tegra_i2c_dev *i2c_dev,
+					       struct completion *complete,
+					       unsigned int timeout_ms)
 {
 	ktime_t ktime = ktime_get();
 	ktime_t ktimeout = ktime_add_ms(ktime, timeout_ms);
@@ -1104,16 +1103,14 @@ tegra_i2c_poll_completion_timeout(struct tegra_i2c_dev *i2c_dev,
 	return 0;
 }
 
-static unsigned long
-tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev,
-				  struct completion *complete,
-				  unsigned int timeout_ms)
+static unsigned long tegra_i2c_wait_completion(struct tegra_i2c_dev *i2c_dev,
+					       struct completion *complete,
+					       unsigned int timeout_ms)
 {
 	unsigned long ret;
 
 	if (i2c_dev->is_curr_atomic_xfer) {
-		ret = tegra_i2c_poll_completion_timeout(i2c_dev, complete,
-							timeout_ms);
+		ret = tegra_i2c_poll_completion(i2c_dev, complete, timeout_ms);
 	} else {
 		enable_irq(i2c_dev->irq);
 		ret = wait_for_completion_timeout(complete,
@@ -1131,8 +1128,7 @@ tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev,
 		 * needs to be checked after timeout.
 		 */
 		if (ret == 0)
-			ret = tegra_i2c_poll_completion_timeout(i2c_dev,
-								complete, 0);
+			ret = tegra_i2c_poll_completion(i2c_dev, complete, 0);
 	}
 
 	return ret;
@@ -1159,8 +1155,8 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
 	i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG);
 	tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
 
-	time_left = tegra_i2c_wait_completion_timeout(
-			i2c_dev, &i2c_dev->msg_complete, 50);
+	time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete,
+					      50);
 	if (time_left == 0) {
 		dev_err(i2c_dev->dev, "timed out for bus clear\n");
 		return -ETIMEDOUT;
@@ -1306,8 +1302,9 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 		i2c_readl(i2c_dev, I2C_INT_MASK));
 
 	if (dma) {
-		time_left = tegra_i2c_wait_completion_timeout(
-				i2c_dev, &i2c_dev->dma_complete, xfer_time);
+		time_left = tegra_i2c_wait_completion(i2c_dev,
+						      &i2c_dev->dma_complete,
+						      xfer_time);
 
 		/*
 		 * Synchronize DMA first, since dmaengine_terminate_sync()
@@ -1338,8 +1335,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 		}
 	}
 
-	time_left = tegra_i2c_wait_completion_timeout(
-			i2c_dev, &i2c_dev->msg_complete, xfer_time);
+	time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete,
+					      xfer_time);
 
 	tegra_i2c_mask_irq(i2c_dev, int_mask);
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 11/22] i2c: tegra: Remove likely/unlikely from the code
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (9 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 10/22] i2c: tegra: Drop '_timeout' from wait/poll function names Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 12/22] i2c: tegra: Factor out error recovery from tegra_i2c_xfer_msg() Dmitry Osipenko
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

The likely/unlikely annotations should be used only in a hot paths of
performance-critical code. The I2C driver doesn't have such paths, and
thus, there is no justification for usage of likely/unlikely annotations
in the code. Hence remove them.

Reviewed-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index ca43eb86403b..f6b9345b8dfa 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -921,7 +921,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
 		goto err;
 	}
 
-	if (unlikely(status & status_err)) {
+	if (status & status_err) {
 		tegra_i2c_disable_packet_mode(i2c_dev);
 		if (status & I2C_INT_NO_ACK)
 			i2c_dev->msg_err |= I2C_ERR_NO_ACK;
@@ -1351,7 +1351,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 		i2c_dev->msg_err);
 
 	i2c_dev->is_curr_dma_xfer = false;
-	if (likely(i2c_dev->msg_err == I2C_ERR_NONE))
+	if (i2c_dev->msg_err == I2C_ERR_NONE)
 		return 0;
 
 	tegra_i2c_init(i2c_dev, true);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 12/22] i2c: tegra: Factor out error recovery from tegra_i2c_xfer_msg()
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (10 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 11/22] i2c: tegra: Remove likely/unlikely from the code Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 13/22] i2c: tegra: Check errors for both positive and negative values Dmitry Osipenko
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

Factor out error recovery code from tegra_i2c_xfer_msg() in order to
make this function easier to read and follow.

Reviewed-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 46 ++++++++++++++++++++++------------
 1 file changed, 30 insertions(+), 16 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index f6b9345b8dfa..19cea39bd4c4 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1171,6 +1171,32 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
 	return -EAGAIN;
 }
 
+static int tegra_i2c_error_recover(struct tegra_i2c_dev *i2c_dev,
+				   struct i2c_msg *msg)
+{
+	if (i2c_dev->msg_err == I2C_ERR_NONE)
+		return 0;
+
+	tegra_i2c_init(i2c_dev, true);
+
+	/* start recovery upon arbitration loss in single master mode */
+	if (i2c_dev->msg_err == I2C_ERR_ARBITRATION_LOST) {
+		if (!i2c_dev->is_multimaster_mode)
+			return i2c_recover_bus(&i2c_dev->adapter);
+
+		return -EAGAIN;
+	}
+
+	if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {
+		if (msg->flags & I2C_M_IGNORE_NAK)
+			return 0;
+
+		return -EREMOTEIO;
+	}
+
+	return -EIO;
+}
+
 static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 			      struct i2c_msg *msg,
 			      enum msg_end_type end_state)
@@ -1351,24 +1377,12 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 		i2c_dev->msg_err);
 
 	i2c_dev->is_curr_dma_xfer = false;
-	if (i2c_dev->msg_err == I2C_ERR_NONE)
-		return 0;
 
-	tegra_i2c_init(i2c_dev, true);
-	/* start recovery upon arbitration loss in single master mode */
-	if (i2c_dev->msg_err == I2C_ERR_ARBITRATION_LOST) {
-		if (!i2c_dev->is_multimaster_mode)
-			return i2c_recover_bus(&i2c_dev->adapter);
-		return -EAGAIN;
-	}
-
-	if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {
-		if (msg->flags & I2C_M_IGNORE_NAK)
-			return 0;
-		return -EREMOTEIO;
-	}
+	err = tegra_i2c_error_recover(i2c_dev, msg);
+	if (err)
+		return err;
 
-	return -EIO;
+	return 0;
 }
 
 static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 13/22] i2c: tegra: Check errors for both positive and negative values
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (11 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 12/22] i2c: tegra: Factor out error recovery from tegra_i2c_xfer_msg() Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03 11:19   ` Andy Shevchenko
  2020-09-03  0:52 ` [PATCH v3 14/22] i2c: tegra: Improve coding style of tegra_i2c_wait_for_config_load() Dmitry Osipenko
                   ` (8 subsequent siblings)
  21 siblings, 1 reply; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

The driver's code is inconsistent in regards to the error values checking.
The correct way should be to check both positive and negative values.
This patch cleans up the error-checks in the code. Note that the
pm_runtime_get_sync() could return positive value on success, hence only
relevant parts of the code are changed by this patch.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 19cea39bd4c4..0f2b6eb5fa27 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -684,19 +684,19 @@ static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
 		return ret;
 
 	ret = clk_enable(i2c_dev->fast_clk);
-	if (ret < 0) {
+	if (ret) {
 		dev_err(dev, "failed to enable fast clock: %d\n", ret);
 		return ret;
 	}
 
 	ret = clk_enable(i2c_dev->slow_clk);
-	if (ret < 0) {
+	if (ret) {
 		dev_err(dev, "failed to enable slow clock: %d\n", ret);
 		goto disable_fast_clk;
 	}
 
 	ret = clk_enable(i2c_dev->div_clk);
-	if (ret < 0) {
+	if (ret) {
 		dev_err(dev, "failed to enable div clock: %d\n", ret);
 		goto disable_slow_clk;
 	}
@@ -1057,7 +1057,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
 
 		slv_config.device_fc = true;
 		ret = dmaengine_slave_config(chan, &slv_config);
-		if (ret < 0) {
+		if (ret) {
 			dev_err(i2c_dev->dev, "DMA config failed: %d\n", ret);
 			dev_err(i2c_dev->dev, "falling back to PIO\n");
 			tegra_i2c_release_dma(i2c_dev);
@@ -1245,7 +1245,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 						   xfer_size,
 						   DMA_FROM_DEVICE);
 			err = tegra_i2c_dma_submit(i2c_dev, xfer_size);
-			if (err < 0) {
+			if (err) {
 				dev_err(i2c_dev->dev,
 					"starting RX DMA failed: %d\n", err);
 				return err;
@@ -1304,7 +1304,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 						   xfer_size,
 						   DMA_TO_DEVICE);
 			err = tegra_i2c_dma_submit(i2c_dev, xfer_size);
-			if (err < 0) {
+			if (err) {
 				dev_err(i2c_dev->dev,
 					"starting TX DMA failed: %d\n", err);
 				return err;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 14/22] i2c: tegra: Improve coding style of tegra_i2c_wait_for_config_load()
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (12 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 13/22] i2c: tegra: Check errors for both positive and negative values Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 15/22] i2c: tegra: Clean up whitespaces and newlines Dmitry Osipenko
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

Improve coding style of the tegra_i2c_wait_for_config_load() function by
making code a bit more narrow, adhering to the common kernel coding style.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 0f2b6eb5fa27..7c5931639d42 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -743,24 +743,23 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
 	u32 val;
 	int err;
 
-	if (i2c_dev->hw->has_config_load_reg) {
-		reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_CONFIG_LOAD);
-		addr = i2c_dev->base + reg_offset;
-		i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
+	if (!i2c_dev->hw->has_config_load_reg)
+		return 0;
 
-		if (i2c_dev->is_curr_atomic_xfer)
-			err = readl_relaxed_poll_timeout_atomic(
-						addr, val, val == 0, 1000,
-						I2C_CONFIG_LOAD_TIMEOUT);
-		else
-			err = readl_relaxed_poll_timeout(
-						addr, val, val == 0, 1000,
-						I2C_CONFIG_LOAD_TIMEOUT);
+	reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_CONFIG_LOAD);
+	addr = i2c_dev->base + reg_offset;
+	i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
 
-		if (err) {
-			dev_err(i2c_dev->dev, "failed to load config\n");
-			return err;
-		}
+	if (i2c_dev->is_curr_atomic_xfer)
+		err = readl_relaxed_poll_timeout_atomic(addr, val, val == 0, 1000,
+							I2C_CONFIG_LOAD_TIMEOUT);
+	else
+		err = readl_relaxed_poll_timeout(addr, val, val == 0, 1000,
+						 I2C_CONFIG_LOAD_TIMEOUT);
+
+	if (err) {
+		dev_err(i2c_dev->dev, "failed to load config\n");
+		return err;
 	}
 
 	return 0;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 15/22] i2c: tegra: Clean up whitespaces and newlines
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (13 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 14/22] i2c: tegra: Improve coding style of tegra_i2c_wait_for_config_load() Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 16/22] i2c: tegra: Rename variable in tegra_i2c_issue_bus_clear() Dmitry Osipenko
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

Clean up couple places in the code by removing unnecessary and adding
necessary whitespaces / newlines.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 7c5931639d42..ed8f2a7c2804 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1223,9 +1223,11 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 		xfer_size = msg->len + I2C_PACKET_HEADER_SIZE;
 
 	xfer_size = ALIGN(xfer_size, BYTES_PER_FIFO_WORD);
+
 	i2c_dev->is_curr_dma_xfer = (xfer_size > I2C_PIO_MODE_PREFERRED_LEN) &&
 				    i2c_dev->dma_buf &&
 				    !i2c_dev->is_curr_atomic_xfer;
+
 	tegra_i2c_config_fifo_trig(i2c_dev, xfer_size);
 	dma = i2c_dev->is_curr_dma_xfer;
 	/*
@@ -1233,16 +1235,18 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 	 * Total bits = 9 bits per byte (including ACK bit) + Start & stop bits
 	 */
 	xfer_time += DIV_ROUND_CLOSEST(((xfer_size * 9) + 2) * MSEC_PER_SEC,
-					i2c_dev->bus_clk_rate);
+				       i2c_dev->bus_clk_rate);
 
 	int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
 	tegra_i2c_unmask_irq(i2c_dev, int_mask);
+
 	if (dma) {
 		if (i2c_dev->msg_read) {
 			dma_sync_single_for_device(i2c_dev->dev,
 						   i2c_dev->dma_phys,
 						   xfer_size,
 						   DMA_FROM_DEVICE);
+
 			err = tegra_i2c_dma_submit(i2c_dev, xfer_size);
 			if (err) {
 				dev_err(i2c_dev->dev,
@@ -1264,32 +1268,39 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 				   PACKET_HEADER0_PROTOCOL_I2C) |
 			FIELD_PREP(PACKET_HEADER0_CONT_ID, i2c_dev->cont_id) |
 			FIELD_PREP(PACKET_HEADER0_PACKET_ID, 1);
+
 	if (dma && !i2c_dev->msg_read)
 		*buffer++ = packet_header;
 	else
 		i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
 
 	packet_header = msg->len - 1;
+
 	if (dma && !i2c_dev->msg_read)
 		*buffer++ = packet_header;
 	else
 		i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
 
 	packet_header = I2C_HEADER_IE_ENABLE;
+
 	if (end_state == MSG_END_CONTINUE)
 		packet_header |= I2C_HEADER_CONTINUE_XFER;
 	else if (end_state == MSG_END_REPEAT_START)
 		packet_header |= I2C_HEADER_REPEAT_START;
+
 	if (msg->flags & I2C_M_TEN) {
 		packet_header |= msg->addr;
 		packet_header |= I2C_HEADER_10BIT_ADDR;
 	} else {
 		packet_header |= msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
 	}
+
 	if (msg->flags & I2C_M_IGNORE_NAK)
 		packet_header |= I2C_HEADER_CONT_ON_NAK;
+
 	if (msg->flags & I2C_M_RD)
 		packet_header |= I2C_HEADER_READ;
+
 	if (dma && !i2c_dev->msg_read)
 		*buffer++ = packet_header;
 	else
@@ -1298,10 +1309,12 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 	if (!i2c_dev->msg_read) {
 		if (dma) {
 			memcpy(buffer, msg->buf, msg->len);
+
 			dma_sync_single_for_device(i2c_dev->dev,
 						   i2c_dev->dma_phys,
 						   xfer_size,
 						   DMA_TO_DEVICE);
+
 			err = tegra_i2c_dma_submit(i2c_dev, xfer_size);
 			if (err) {
 				dev_err(i2c_dev->dev,
@@ -1315,6 +1328,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 
 	if (i2c_dev->hw->has_per_pkt_xfer_complete_irq)
 		int_mask |= I2C_INT_PACKET_XFER_COMPLETE;
+
 	if (!dma) {
 		if (msg->flags & I2C_M_RD)
 			int_mask |= I2C_INT_RX_FIFO_DATA_REQ;
@@ -1355,8 +1369,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 						i2c_dev->dma_phys,
 						xfer_size,
 						DMA_FROM_DEVICE);
-			memcpy(i2c_dev->msg_buf, i2c_dev->dma_buf,
-			       msg->len);
+
+			memcpy(i2c_dev->msg_buf, i2c_dev->dma_buf, msg->len);
 		}
 	}
 
@@ -1969,15 +1983,14 @@ static const struct dev_pm_ops tegra_i2c_pm = {
 };
 
 static struct platform_driver tegra_i2c_driver = {
-	.probe   = tegra_i2c_probe,
-	.remove  = tegra_i2c_remove,
-	.driver  = {
-		.name  = "tegra-i2c",
+	.probe = tegra_i2c_probe,
+	.remove = tegra_i2c_remove,
+	.driver = {
+		.name = "tegra-i2c",
 		.of_match_table = tegra_i2c_of_match,
-		.pm    = &tegra_i2c_pm,
+		.pm = &tegra_i2c_pm,
 	},
 };
-
 module_platform_driver(tegra_i2c_driver);
 
 MODULE_DESCRIPTION("nVidia Tegra2 I2C Bus Controller driver");
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 16/22] i2c: tegra: Rename variable in tegra_i2c_issue_bus_clear()
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (14 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 15/22] i2c: tegra: Clean up whitespaces and newlines Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 17/22] i2c: tegra: Improve driver module description Dmitry Osipenko
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

Rename variable "reg" to "val" in order to better reflect the actual usage
of the variable in the code and to make naming consistent with the rest of
the code.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index ed8f2a7c2804..67f2f4a0fe86 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1137,21 +1137,21 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
 {
 	struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
 	unsigned long time_left;
-	u32 reg;
+	u32 val;
 	int err;
 
 	reinit_completion(&i2c_dev->msg_complete);
-	reg = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND |
+	val = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND |
 	      I2C_BC_TERMINATE;
-	i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG);
+	i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG);
 	if (i2c_dev->hw->has_config_load_reg) {
 		err = tegra_i2c_wait_for_config_load(i2c_dev);
 		if (err)
 			return err;
 	}
 
-	reg |= I2C_BC_ENABLE;
-	i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG);
+	val |= I2C_BC_ENABLE;
+	i2c_writel(i2c_dev, val, I2C_BUS_CLEAR_CNFG);
 	tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
 
 	time_left = tegra_i2c_wait_completion(i2c_dev, &i2c_dev->msg_complete,
@@ -1161,8 +1161,8 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
 		return -ETIMEDOUT;
 	}
 
-	reg = i2c_readl(i2c_dev, I2C_BUS_CLEAR_STATUS);
-	if (!(reg & I2C_BC_STATUS)) {
+	val = i2c_readl(i2c_dev, I2C_BUS_CLEAR_STATUS);
+	if (!(val & I2C_BC_STATUS)) {
 		dev_err(i2c_dev->dev, "un-recovered arbitration lost\n");
 		return -EIO;
 	}
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 17/22] i2c: tegra: Improve driver module description
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (15 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 16/22] i2c: tegra: Rename variable in tegra_i2c_issue_bus_clear() Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 18/22] i2c: tegra: Reorder location of functions in the code Dmitry Osipenko
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

Use proper spelling of "NVIDIA" and don't designate driver as Tegra2-only
since newer SoC generations are supported as well.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 67f2f4a0fe86..5b37435fa36d 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1993,6 +1993,6 @@ static struct platform_driver tegra_i2c_driver = {
 };
 module_platform_driver(tegra_i2c_driver);
 
-MODULE_DESCRIPTION("nVidia Tegra2 I2C Bus Controller driver");
+MODULE_DESCRIPTION("NVIDIA Tegra I2C Bus Controller driver");
 MODULE_AUTHOR("Colin Cross");
 MODULE_LICENSE("GPL v2");
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 18/22] i2c: tegra: Reorder location of functions in the code
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (16 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 17/22] i2c: tegra: Improve driver module description Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 19/22] i2c: tegra: Factor out packet header setup from tegra_i2c_xfer_msg() Dmitry Osipenko
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

Reorder location of functions in the code in order to have definition
of functions closer to the place of the invocation. This change makes
easier to navigate around the code and removes the need to have a
prototype for tegra_i2c_init().

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 550 ++++++++++++++++-----------------
 1 file changed, 274 insertions(+), 276 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 5b37435fa36d..f30ac45c2bfd 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -293,8 +293,6 @@ struct tegra_i2c_dev {
 	bool is_curr_atomic_xfer;
 };
 
-static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit);
-
 static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
 		       unsigned long reg)
 {
@@ -473,186 +471,6 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
 	return err;
 }
 
-static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
-{
-	ktime_t ktime, ktimeout;
-	unsigned int offset;
-	u32 mask, val;
-
-	if (i2c_dev->hw->has_mst_fifo) {
-		mask = I2C_MST_FIFO_CONTROL_TX_FLUSH |
-		       I2C_MST_FIFO_CONTROL_RX_FLUSH;
-		offset = I2C_MST_FIFO_CONTROL;
-	} else {
-		mask = I2C_FIFO_CONTROL_TX_FLUSH |
-		       I2C_FIFO_CONTROL_RX_FLUSH;
-		offset = I2C_FIFO_CONTROL;
-	}
-
-	val = i2c_readl(i2c_dev, offset);
-	val |= mask;
-	i2c_writel(i2c_dev, val, offset);
-
-	/*
-	 * ktime_get() may take up to couple milliseconds in a worst case
-	 * and normally FIFOs are flushed, hence let's check the state before
-	 * proceeding to polling.
-	 */
-	if (!(i2c_readl(i2c_dev, offset) & mask))
-		return 0;
-
-	ktime = ktime_get();
-	ktimeout = ktime_add_ms(ktime, 1000);
-
-	while (i2c_readl(i2c_dev, offset) & mask) {
-		if (ktime_after(ktime, ktimeout))
-			goto err_timeout;
-
-		if (i2c_dev->is_curr_atomic_xfer)
-			mdelay(1);
-		else
-			fsleep(1000);
-
-		ktime = ktime_get();
-	}
-
-	return 0;
-
-err_timeout:
-	dev_err(i2c_dev->dev, "FIFO flushing timed out\n");
-
-	return -ETIMEDOUT;
-}
-
-static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
-{
-	size_t buf_remaining = i2c_dev->msg_buf_remaining;
-	u8 *buf = i2c_dev->msg_buf;
-	int words_to_transfer;
-	int rx_fifo_avail;
-	u32 val;
-
-	/*
-	 * Catch overflow due to message fully sent
-	 * before the check for RX FIFO availability.
-	 */
-	if (WARN_ON_ONCE(!(i2c_dev->msg_buf_remaining)))
-		return -EINVAL;
-
-	if (i2c_dev->hw->has_mst_fifo) {
-		val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
-		rx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_RX, val);
-	} else {
-		val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
-		rx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_RX, val);
-	}
-
-	/* Rounds down to not include partial word at the end of buf */
-	words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
-	if (words_to_transfer > rx_fifo_avail)
-		words_to_transfer = rx_fifo_avail;
-
-	i2c_readsl(i2c_dev, buf, I2C_RX_FIFO, words_to_transfer);
-
-	buf += words_to_transfer * BYTES_PER_FIFO_WORD;
-	buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
-	rx_fifo_avail -= words_to_transfer;
-
-	/*
-	 * If there is a partial word at the end of buf, handle it manually to
-	 * prevent overwriting past the end of buf
-	 */
-	if (rx_fifo_avail > 0 && buf_remaining > 0) {
-		/*
-		 * buf_remaining > 3 check not needed as rx_fifo_avail == 0
-		 * when (words_to_transfer was > rx_fifo_avail) earlier
-		 * in this function.
-		 */
-		val = i2c_readl(i2c_dev, I2C_RX_FIFO);
-		val = cpu_to_le32(val);
-		memcpy(buf, &val, buf_remaining);
-		buf_remaining = 0;
-		rx_fifo_avail--;
-	}
-
-	/* RX FIFO must be drained, otherwise it's an Overflow case. */
-	if (WARN_ON_ONCE(rx_fifo_avail))
-		return -EINVAL;
-
-	i2c_dev->msg_buf_remaining = buf_remaining;
-	i2c_dev->msg_buf = buf;
-
-	return 0;
-}
-
-static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
-{
-	size_t buf_remaining = i2c_dev->msg_buf_remaining;
-	u8 *buf = i2c_dev->msg_buf;
-	int words_to_transfer;
-	int tx_fifo_avail;
-	u32 val;
-
-	if (i2c_dev->hw->has_mst_fifo) {
-		val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
-		tx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_TX, val);
-	} else {
-		val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
-		tx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_TX, val);
-	}
-
-	/* Rounds down to not include partial word at the end of buf */
-	words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
-
-	/* It's very common to have < 4 bytes, so optimize that case. */
-	if (words_to_transfer) {
-		if (words_to_transfer > tx_fifo_avail)
-			words_to_transfer = tx_fifo_avail;
-
-		/*
-		 * Update state before writing to FIFO.  If this casues us
-		 * to finish writing all bytes (AKA buf_remaining goes to 0) we
-		 * have a potential for an interrupt (PACKET_XFER_COMPLETE is
-		 * not maskable).  We need to make sure that the isr sees
-		 * buf_remaining as 0 and doesn't call us back re-entrantly.
-		 */
-		buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
-		tx_fifo_avail -= words_to_transfer;
-		i2c_dev->msg_buf_remaining = buf_remaining;
-		i2c_dev->msg_buf = buf +
-			words_to_transfer * BYTES_PER_FIFO_WORD;
-		barrier();
-
-		i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
-
-		buf += words_to_transfer * BYTES_PER_FIFO_WORD;
-	}
-
-	/*
-	 * If there is a partial word at the end of buf, handle it manually to
-	 * prevent reading past the end of buf, which could cross a page
-	 * boundary and fault.
-	 */
-	if (tx_fifo_avail > 0 && buf_remaining > 0) {
-		/*
-		 * buf_remaining > 3 check not needed as tx_fifo_avail == 0
-		 * when (words_to_transfer was > tx_fifo_avail) earlier
-		 * in this function for non-zero words_to_transfer.
-		 */
-		memcpy(&val, buf, buf_remaining);
-		val = le32_to_cpu(val);
-
-		/* Again update before writing to FIFO to make sure isr sees. */
-		i2c_dev->msg_buf_remaining = 0;
-		i2c_dev->msg_buf = NULL;
-		barrier();
-
-		i2c_writel(i2c_dev, val, I2C_TX_FIFO);
-	}
-
-	return 0;
-}
-
 /*
  * One of the Tegra I2C blocks is inside the DVC (Digital Voltage Controller)
  * block.  This block is identical to the rest of the I2C blocks, except that
@@ -674,66 +492,33 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)
 	dvc_writel(i2c_dev, val, DVC_CTRL_REG1);
 }
 
-static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
+static void tegra_i2c_vi_init(struct tegra_i2c_dev *i2c_dev)
 {
-	struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
-	int ret;
-
-	ret = pinctrl_pm_select_default_state(i2c_dev->dev);
-	if (ret)
-		return ret;
-
-	ret = clk_enable(i2c_dev->fast_clk);
-	if (ret) {
-		dev_err(dev, "failed to enable fast clock: %d\n", ret);
-		return ret;
-	}
-
-	ret = clk_enable(i2c_dev->slow_clk);
-	if (ret) {
-		dev_err(dev, "failed to enable slow clock: %d\n", ret);
-		goto disable_fast_clk;
-	}
-
-	ret = clk_enable(i2c_dev->div_clk);
-	if (ret) {
-		dev_err(dev, "failed to enable div clock: %d\n", ret);
-		goto disable_slow_clk;
-	}
-
-	/*
-	 * VI I2C device is attached to VE power domain which goes through
-	 * power ON/OFF during PM runtime resume/suspend. So, controller
-	 * should go through reset and need to re-initialize after power
-	 * domain ON.
-	 */
-	if (i2c_dev->is_vi) {
-		ret = tegra_i2c_init(i2c_dev, true);
-		if (ret)
-			goto disable_div_clk;
-	}
+	u32 value;
 
-	return 0;
+	value = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, 2) |
+		FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, 4);
+	i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_0);
 
-disable_div_clk:
-	clk_disable(i2c_dev->div_clk);
-disable_slow_clk:
-	clk_disable(i2c_dev->slow_clk);
-disable_fast_clk:
-	clk_disable(i2c_dev->fast_clk);
+	value = FIELD_PREP(I2C_INTERFACE_TIMING_TBUF, 4) |
+		FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STO, 7) |
+		FIELD_PREP(I2C_INTERFACE_TIMING_THD_STA, 4) |
+		FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STA, 4);
+	i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_1);
 
-	return ret;
-}
+	value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_THIGH, 3) |
+		FIELD_PREP(I2C_HS_INTERFACE_TIMING_TLOW, 8);
+	i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_0);
 
-static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev)
-{
-	struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
+	value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STO, 11) |
+		FIELD_PREP(I2C_HS_INTERFACE_TIMING_THD_STA, 11) |
+		FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STA, 11);
+	i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_1);
 
-	clk_disable(i2c_dev->div_clk);
-	clk_disable(i2c_dev->slow_clk);
-	clk_disable(i2c_dev->fast_clk);
+	value = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND;
+	i2c_writel(i2c_dev, value, I2C_BUS_CLEAR_CNFG);
 
-	return pinctrl_pm_select_idle_state(i2c_dev->dev);
+	i2c_writel(i2c_dev, 0x0, I2C_TLOW_SEXT);
 }
 
 static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
@@ -765,33 +550,55 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
 	return 0;
 }
 
-static void tegra_i2c_vi_init(struct tegra_i2c_dev *i2c_dev)
+static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
 {
-	u32 value;
+	ktime_t ktime, ktimeout;
+	unsigned int offset;
+	u32 mask, val;
 
-	value = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, 2) |
-		FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, 4);
-	i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_0);
+	if (i2c_dev->hw->has_mst_fifo) {
+		mask = I2C_MST_FIFO_CONTROL_TX_FLUSH |
+		       I2C_MST_FIFO_CONTROL_RX_FLUSH;
+		offset = I2C_MST_FIFO_CONTROL;
+	} else {
+		mask = I2C_FIFO_CONTROL_TX_FLUSH |
+		       I2C_FIFO_CONTROL_RX_FLUSH;
+		offset = I2C_FIFO_CONTROL;
+	}
 
-	value = FIELD_PREP(I2C_INTERFACE_TIMING_TBUF, 4) |
-		FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STO, 7) |
-		FIELD_PREP(I2C_INTERFACE_TIMING_THD_STA, 4) |
-		FIELD_PREP(I2C_INTERFACE_TIMING_TSU_STA, 4);
-	i2c_writel(i2c_dev, value, I2C_INTERFACE_TIMING_1);
+	val = i2c_readl(i2c_dev, offset);
+	val |= mask;
+	i2c_writel(i2c_dev, val, offset);
+
+	/*
+	 * ktime_get() may take up to couple milliseconds in a worst case
+	 * and normally FIFOs are flushed, hence let's check the state before
+	 * proceeding to polling.
+	 */
+	if (!(i2c_readl(i2c_dev, offset) & mask))
+		return 0;
+
+	ktime = ktime_get();
+	ktimeout = ktime_add_ms(ktime, 1000);
+
+	while (i2c_readl(i2c_dev, offset) & mask) {
+		if (ktime_after(ktime, ktimeout))
+			goto err_timeout;
 
-	value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_THIGH, 3) |
-		FIELD_PREP(I2C_HS_INTERFACE_TIMING_TLOW, 8);
-	i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_0);
+		if (i2c_dev->is_curr_atomic_xfer)
+			mdelay(1);
+		else
+			fsleep(1000);
 
-	value = FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STO, 11) |
-		FIELD_PREP(I2C_HS_INTERFACE_TIMING_THD_STA, 11) |
-		FIELD_PREP(I2C_HS_INTERFACE_TIMING_TSU_STA, 11);
-	i2c_writel(i2c_dev, value, I2C_HS_INTERFACE_TIMING_1);
+		ktime = ktime_get();
+	}
 
-	value = FIELD_PREP(I2C_BC_SCLK_THRESHOLD, 9) | I2C_BC_STOP_COND;
-	i2c_writel(i2c_dev, value, I2C_BUS_CLEAR_CNFG);
+	return 0;
 
-	i2c_writel(i2c_dev, 0x0, I2C_TLOW_SEXT);
+err_timeout:
+	dev_err(i2c_dev->dev, "FIFO flushing timed out\n");
+
+	return -ETIMEDOUT;
 }
 
 static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
@@ -903,6 +710,135 @@ static int tegra_i2c_disable_packet_mode(struct tegra_i2c_dev *i2c_dev)
 	return tegra_i2c_wait_for_config_load(i2c_dev);
 }
 
+static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
+{
+	size_t buf_remaining = i2c_dev->msg_buf_remaining;
+	u8 *buf = i2c_dev->msg_buf;
+	int words_to_transfer;
+	int rx_fifo_avail;
+	u32 val;
+
+	/*
+	 * Catch overflow due to message fully sent
+	 * before the check for RX FIFO availability.
+	 */
+	if (WARN_ON_ONCE(!(i2c_dev->msg_buf_remaining)))
+		return -EINVAL;
+
+	if (i2c_dev->hw->has_mst_fifo) {
+		val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
+		rx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_RX, val);
+	} else {
+		val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+		rx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_RX, val);
+	}
+
+	/* Rounds down to not include partial word at the end of buf */
+	words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
+	if (words_to_transfer > rx_fifo_avail)
+		words_to_transfer = rx_fifo_avail;
+
+	i2c_readsl(i2c_dev, buf, I2C_RX_FIFO, words_to_transfer);
+
+	buf += words_to_transfer * BYTES_PER_FIFO_WORD;
+	buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
+	rx_fifo_avail -= words_to_transfer;
+
+	/*
+	 * If there is a partial word at the end of buf, handle it manually to
+	 * prevent overwriting past the end of buf
+	 */
+	if (rx_fifo_avail > 0 && buf_remaining > 0) {
+		/*
+		 * buf_remaining > 3 check not needed as rx_fifo_avail == 0
+		 * when (words_to_transfer was > rx_fifo_avail) earlier
+		 * in this function.
+		 */
+		val = i2c_readl(i2c_dev, I2C_RX_FIFO);
+		val = cpu_to_le32(val);
+		memcpy(buf, &val, buf_remaining);
+		buf_remaining = 0;
+		rx_fifo_avail--;
+	}
+
+	/* RX FIFO must be drained, otherwise it's an Overflow case. */
+	if (WARN_ON_ONCE(rx_fifo_avail))
+		return -EINVAL;
+
+	i2c_dev->msg_buf_remaining = buf_remaining;
+	i2c_dev->msg_buf = buf;
+
+	return 0;
+}
+
+static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
+{
+	size_t buf_remaining = i2c_dev->msg_buf_remaining;
+	u8 *buf = i2c_dev->msg_buf;
+	int words_to_transfer;
+	int tx_fifo_avail;
+	u32 val;
+
+	if (i2c_dev->hw->has_mst_fifo) {
+		val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
+		tx_fifo_avail = FIELD_GET(I2C_MST_FIFO_STATUS_TX, val);
+	} else {
+		val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+		tx_fifo_avail = FIELD_GET(I2C_FIFO_STATUS_TX, val);
+	}
+
+	/* Rounds down to not include partial word at the end of buf */
+	words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
+
+	/* It's very common to have < 4 bytes, so optimize that case. */
+	if (words_to_transfer) {
+		if (words_to_transfer > tx_fifo_avail)
+			words_to_transfer = tx_fifo_avail;
+
+		/*
+		 * Update state before writing to FIFO.  If this casues us
+		 * to finish writing all bytes (AKA buf_remaining goes to 0) we
+		 * have a potential for an interrupt (PACKET_XFER_COMPLETE is
+		 * not maskable).  We need to make sure that the isr sees
+		 * buf_remaining as 0 and doesn't call us back re-entrantly.
+		 */
+		buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
+		tx_fifo_avail -= words_to_transfer;
+		i2c_dev->msg_buf_remaining = buf_remaining;
+		i2c_dev->msg_buf = buf +
+			words_to_transfer * BYTES_PER_FIFO_WORD;
+		barrier();
+
+		i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
+
+		buf += words_to_transfer * BYTES_PER_FIFO_WORD;
+	}
+
+	/*
+	 * If there is a partial word at the end of buf, handle it manually to
+	 * prevent reading past the end of buf, which could cross a page
+	 * boundary and fault.
+	 */
+	if (tx_fifo_avail > 0 && buf_remaining > 0) {
+		/*
+		 * buf_remaining > 3 check not needed as tx_fifo_avail == 0
+		 * when (words_to_transfer was > tx_fifo_avail) earlier
+		 * in this function for non-zero words_to_transfer.
+		 */
+		memcpy(&val, buf, buf_remaining);
+		val = le32_to_cpu(val);
+
+		/* Again update before writing to FIFO to make sure isr sees. */
+		i2c_dev->msg_buf_remaining = 0;
+		i2c_dev->msg_buf = NULL;
+		barrier();
+
+		i2c_writel(i2c_dev, val, I2C_TX_FIFO);
+	}
+
+	return 0;
+}
+
 static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
 {
 	const u32 status_err = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
@@ -1454,27 +1390,6 @@ static u32 tegra_i2c_func(struct i2c_adapter *adap)
 	return ret;
 }
 
-static int tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
-{
-	struct device_node *np = i2c_dev->dev->of_node;
-	u32 bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ;
-	bool multi_mode;
-
-	of_property_read_u32(np, "clock-frequency", &bus_clk_rate);
-	i2c_dev->bus_clk_rate = bus_clk_rate;
-
-	multi_mode = of_property_read_bool(np, "multi-master");
-	i2c_dev->is_multimaster_mode = multi_mode;
-
-	if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc"))
-		i2c_dev->is_dvc = true;
-
-	if (of_device_is_compatible(np, "nvidia,tegra210-i2c-vi"))
-		i2c_dev->is_vi = true;
-
-	return 0;
-}
-
 static const struct i2c_algorithm tegra_i2c_algo = {
 	.master_xfer		= tegra_i2c_xfer,
 	.master_xfer_atomic	= tegra_i2c_xfer_atomic,
@@ -1687,6 +1602,27 @@ static const struct of_device_id tegra_i2c_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
 
+static int tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
+{
+	struct device_node *np = i2c_dev->dev->of_node;
+	u32 bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ;
+	bool multi_mode;
+
+	of_property_read_u32(np, "clock-frequency", &bus_clk_rate);
+	i2c_dev->bus_clk_rate = bus_clk_rate;
+
+	multi_mode = of_property_read_bool(np, "multi-master");
+	i2c_dev->is_multimaster_mode = multi_mode;
+
+	if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc"))
+		i2c_dev->is_dvc = true;
+
+	if (of_device_is_compatible(np, "nvidia,tegra210-i2c-vi"))
+		i2c_dev->is_vi = true;
+
+	return 0;
+}
+
 static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
 {
 	const struct tegra_i2c_hw_feature *hw = i2c_dev->hw;
@@ -1930,6 +1866,68 @@ static int tegra_i2c_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
+{
+	struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
+	int ret;
+
+	ret = pinctrl_pm_select_default_state(i2c_dev->dev);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(i2c_dev->fast_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable fast clock: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_enable(i2c_dev->slow_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable slow clock: %d\n", ret);
+		goto disable_fast_clk;
+	}
+
+	ret = clk_enable(i2c_dev->div_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable div clock: %d\n", ret);
+		goto disable_slow_clk;
+	}
+
+	/*
+	 * VI I2C device is attached to VE power domain which goes through
+	 * power ON/OFF during PM runtime resume/suspend. So, controller
+	 * should go through reset and need to re-initialize after power
+	 * domain ON.
+	 */
+	if (i2c_dev->is_vi) {
+		ret = tegra_i2c_init(i2c_dev, true);
+		if (ret)
+			goto disable_div_clk;
+	}
+
+	return 0;
+
+disable_div_clk:
+	clk_disable(i2c_dev->div_clk);
+disable_slow_clk:
+	clk_disable(i2c_dev->slow_clk);
+disable_fast_clk:
+	clk_disable(i2c_dev->fast_clk);
+
+	return ret;
+}
+
+static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev)
+{
+	struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
+
+	clk_disable(i2c_dev->div_clk);
+	clk_disable(i2c_dev->slow_clk);
+	clk_disable(i2c_dev->fast_clk);
+
+	return pinctrl_pm_select_idle_state(i2c_dev->dev);
+}
+
 static int __maybe_unused tegra_i2c_suspend(struct device *dev)
 {
 	struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 19/22] i2c: tegra: Factor out packet header setup from tegra_i2c_xfer_msg()
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (17 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 18/22] i2c: tegra: Reorder location of functions in the code Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 20/22] i2c: tegra: Remove "dma" variable Dmitry Osipenko
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

The code related to packet header setting up is a bit messy and makes
tegra_i2c_xfer_msg() more difficult to read than it could be. Let's
factor the packet header setup from tegra_i2c_xfer_msg() to clean up
code a tad.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 100 ++++++++++++++++++---------------
 1 file changed, 54 insertions(+), 46 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index f30ac45c2bfd..d39d66621199 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1106,6 +1106,57 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
 	return -EAGAIN;
 }
 
+static void tegra_i2c_push_packet_header(struct tegra_i2c_dev *i2c_dev,
+					 struct i2c_msg *msg,
+					 enum msg_end_type end_state)
+{
+	u32 *dma_buf = i2c_dev->dma_buf;
+	u32 packet_header;
+
+	packet_header = FIELD_PREP(PACKET_HEADER0_HEADER_SIZE, 0) |
+			FIELD_PREP(PACKET_HEADER0_PROTOCOL,
+				   PACKET_HEADER0_PROTOCOL_I2C) |
+			FIELD_PREP(PACKET_HEADER0_CONT_ID, i2c_dev->cont_id) |
+			FIELD_PREP(PACKET_HEADER0_PACKET_ID, 1);
+
+	if (i2c_dev->is_curr_dma_xfer && !i2c_dev->msg_read)
+		*dma_buf++ = packet_header;
+	else
+		i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+
+	packet_header = msg->len - 1;
+
+	if (i2c_dev->is_curr_dma_xfer && !i2c_dev->msg_read)
+		*dma_buf++ = packet_header;
+	else
+		i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+
+	packet_header = I2C_HEADER_IE_ENABLE;
+
+	if (end_state == MSG_END_CONTINUE)
+		packet_header |= I2C_HEADER_CONTINUE_XFER;
+	else if (end_state == MSG_END_REPEAT_START)
+		packet_header |= I2C_HEADER_REPEAT_START;
+
+	if (msg->flags & I2C_M_TEN) {
+		packet_header |= msg->addr;
+		packet_header |= I2C_HEADER_10BIT_ADDR;
+	} else {
+		packet_header |= msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
+	}
+
+	if (msg->flags & I2C_M_IGNORE_NAK)
+		packet_header |= I2C_HEADER_CONT_ON_NAK;
+
+	if (msg->flags & I2C_M_RD)
+		packet_header |= I2C_HEADER_READ;
+
+	if (i2c_dev->is_curr_dma_xfer && !i2c_dev->msg_read)
+		*dma_buf++ = packet_header;
+	else
+		i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+}
+
 static int tegra_i2c_error_recover(struct tegra_i2c_dev *i2c_dev,
 				   struct i2c_msg *msg)
 {
@@ -1137,9 +1188,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 			      enum msg_end_type end_state)
 {
 	unsigned long time_left, xfer_time = 100;
-	u32 packet_header, int_mask;
-	u32 *buffer = NULL;
 	size_t xfer_size;
+	u32 int_mask;
 	bool dma;
 	int err;
 
@@ -1195,56 +1245,14 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 						i2c_dev->dma_phys,
 						xfer_size,
 						DMA_TO_DEVICE);
-			buffer = i2c_dev->dma_buf;
 		}
 	}
 
-	packet_header = FIELD_PREP(PACKET_HEADER0_HEADER_SIZE, 0) |
-			FIELD_PREP(PACKET_HEADER0_PROTOCOL,
-				   PACKET_HEADER0_PROTOCOL_I2C) |
-			FIELD_PREP(PACKET_HEADER0_CONT_ID, i2c_dev->cont_id) |
-			FIELD_PREP(PACKET_HEADER0_PACKET_ID, 1);
-
-	if (dma && !i2c_dev->msg_read)
-		*buffer++ = packet_header;
-	else
-		i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
-
-	packet_header = msg->len - 1;
-
-	if (dma && !i2c_dev->msg_read)
-		*buffer++ = packet_header;
-	else
-		i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
-
-	packet_header = I2C_HEADER_IE_ENABLE;
-
-	if (end_state == MSG_END_CONTINUE)
-		packet_header |= I2C_HEADER_CONTINUE_XFER;
-	else if (end_state == MSG_END_REPEAT_START)
-		packet_header |= I2C_HEADER_REPEAT_START;
-
-	if (msg->flags & I2C_M_TEN) {
-		packet_header |= msg->addr;
-		packet_header |= I2C_HEADER_10BIT_ADDR;
-	} else {
-		packet_header |= msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
-	}
-
-	if (msg->flags & I2C_M_IGNORE_NAK)
-		packet_header |= I2C_HEADER_CONT_ON_NAK;
-
-	if (msg->flags & I2C_M_RD)
-		packet_header |= I2C_HEADER_READ;
-
-	if (dma && !i2c_dev->msg_read)
-		*buffer++ = packet_header;
-	else
-		i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+	tegra_i2c_push_packet_header(i2c_dev, msg, end_state);
 
 	if (!i2c_dev->msg_read) {
 		if (dma) {
-			memcpy(buffer, msg->buf, msg->len);
+			memcpy(i2c_dev->dma_buf, msg->buf, msg->len);
 
 			dma_sync_single_for_device(i2c_dev->dev,
 						   i2c_dev->dma_phys,
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 20/22] i2c: tegra: Remove "dma" variable
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (18 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 19/22] i2c: tegra: Factor out packet header setup from tegra_i2c_xfer_msg() Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:52 ` [PATCH v3 21/22] i2c: tegra: Initialization div-clk rate unconditionally Dmitry Osipenko
  2020-09-03  0:53 ` [PATCH v3 22/22] i2c: tegra: Remove i2c_dev.clk_divisor_non_hs_mode member Dmitry Osipenko
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

The "dma" variable of tegra_i2c_xfer_msg() function doesn't bring much in
regards to readability and generation of the code, hence let's remove it
to clean up code a tad.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index d39d66621199..79caf87bb4c0 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -1190,7 +1190,6 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 	unsigned long time_left, xfer_time = 100;
 	size_t xfer_size;
 	u32 int_mask;
-	bool dma;
 	int err;
 
 	err = tegra_i2c_flush_fifos(i2c_dev);
@@ -1215,7 +1214,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 				    !i2c_dev->is_curr_atomic_xfer;
 
 	tegra_i2c_config_fifo_trig(i2c_dev, xfer_size);
-	dma = i2c_dev->is_curr_dma_xfer;
+
 	/*
 	 * Transfer time in mSec = Total bits / transfer rate
 	 * Total bits = 9 bits per byte (including ACK bit) + Start & stop bits
@@ -1226,7 +1225,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 	int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
 	tegra_i2c_unmask_irq(i2c_dev, int_mask);
 
-	if (dma) {
+	if (i2c_dev->is_curr_dma_xfer) {
 		if (i2c_dev->msg_read) {
 			dma_sync_single_for_device(i2c_dev->dev,
 						   i2c_dev->dma_phys,
@@ -1251,7 +1250,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 	tegra_i2c_push_packet_header(i2c_dev, msg, end_state);
 
 	if (!i2c_dev->msg_read) {
-		if (dma) {
+		if (i2c_dev->is_curr_dma_xfer) {
 			memcpy(i2c_dev->dma_buf, msg->buf, msg->len);
 
 			dma_sync_single_for_device(i2c_dev->dev,
@@ -1273,7 +1272,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 	if (i2c_dev->hw->has_per_pkt_xfer_complete_irq)
 		int_mask |= I2C_INT_PACKET_XFER_COMPLETE;
 
-	if (!dma) {
+	if (!i2c_dev->is_curr_dma_xfer) {
 		if (msg->flags & I2C_M_RD)
 			int_mask |= I2C_INT_RX_FIFO_DATA_REQ;
 		else if (i2c_dev->msg_buf_remaining)
@@ -1284,7 +1283,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 	dev_dbg(i2c_dev->dev, "unmasked IRQ: %02x\n",
 		i2c_readl(i2c_dev, I2C_INT_MASK));
 
-	if (dma) {
+	if (i2c_dev->is_curr_dma_xfer) {
 		time_left = tegra_i2c_wait_completion(i2c_dev,
 						      &i2c_dev->dma_complete,
 						      xfer_time);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 21/22] i2c: tegra: Initialization div-clk rate unconditionally
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (19 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 20/22] i2c: tegra: Remove "dma" variable Dmitry Osipenko
@ 2020-09-03  0:52 ` Dmitry Osipenko
  2020-09-03  0:53 ` [PATCH v3 22/22] i2c: tegra: Remove i2c_dev.clk_divisor_non_hs_mode member Dmitry Osipenko
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:52 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

It doesn't make sense to conditionalize the div-clk rate changes because
rate is fixed and it won't ever change once it's set at the driver's probe
time. All further changes are NO-OPs because CCF caches rate and skips
rate-change if rate is unchanged.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 32 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 79caf87bb4c0..bc7954c8a5a0 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -601,7 +601,7 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
 	return -ETIMEDOUT;
 }
 
-static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
+static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
 {
 	u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh;
 	int err;
@@ -656,16 +656,14 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit)
 	if (i2c_dev->hw->has_interface_timing_reg && tsu_thd)
 		i2c_writel(i2c_dev, tsu_thd, I2C_INTERFACE_TIMING_1);
 
-	if (!clk_reinit) {
-		clk_multiplier = (tlow + thigh + 2);
-		clk_multiplier *= (i2c_dev->clk_divisor_non_hs_mode + 1);
-		err = clk_set_rate(i2c_dev->div_clk,
-				   i2c_dev->bus_clk_rate * clk_multiplier);
-		if (err) {
-			dev_err(i2c_dev->dev,
-				"failed to set div-clk rate: %d\n", err);
-			return err;
-		}
+	clk_multiplier  = tlow + thigh + 2;
+	clk_multiplier *= i2c_dev->clk_divisor_non_hs_mode + 1;
+
+	err = clk_set_rate(i2c_dev->div_clk,
+			   i2c_dev->bus_clk_rate * clk_multiplier);
+	if (err) {
+		dev_err(i2c_dev->dev, "failed to set div-clk rate: %d\n", err);
+		return err;
 	}
 
 	if (!i2c_dev->is_dvc && !i2c_dev->is_vi) {
@@ -1163,7 +1161,7 @@ static int tegra_i2c_error_recover(struct tegra_i2c_dev *i2c_dev,
 	if (i2c_dev->msg_err == I2C_ERR_NONE)
 		return 0;
 
-	tegra_i2c_init(i2c_dev, true);
+	tegra_i2c_init(i2c_dev);
 
 	/* start recovery upon arbitration loss in single master mode */
 	if (i2c_dev->msg_err == I2C_ERR_ARBITRATION_LOST) {
@@ -1303,7 +1301,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 
 		if (!time_left && !completion_done(&i2c_dev->dma_complete)) {
 			dev_err(i2c_dev->dev, "DMA transfer timeout\n");
-			tegra_i2c_init(i2c_dev, true);
+			tegra_i2c_init(i2c_dev);
 			return -ETIMEDOUT;
 		}
 
@@ -1324,7 +1322,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
 
 	if (time_left == 0) {
 		dev_err(i2c_dev->dev, "I2C transfer timed out\n");
-		tegra_i2c_init(i2c_dev, true);
+		tegra_i2c_init(i2c_dev);
 		return -ETIMEDOUT;
 	}
 
@@ -1752,7 +1750,7 @@ static int tegra_i2c_init_runtime_pm_and_hardware(struct tegra_i2c_dev *i2c_dev)
 	}
 
 	/* initialize hardware state */
-	ret = tegra_i2c_init(i2c_dev, false);
+	ret = tegra_i2c_init(i2c_dev);
 
 	pm_runtime_put(i2c_dev->dev);
 
@@ -1907,7 +1905,7 @@ static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
 	 * domain ON.
 	 */
 	if (i2c_dev->is_vi) {
-		ret = tegra_i2c_init(i2c_dev, true);
+		ret = tegra_i2c_init(i2c_dev);
 		if (ret)
 			goto disable_div_clk;
 	}
@@ -1961,7 +1959,7 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev)
 	if (err)
 		return err;
 
-	err = tegra_i2c_init(i2c_dev, false);
+	err = tegra_i2c_init(i2c_dev);
 	if (err)
 		return err;
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v3 22/22] i2c: tegra: Remove i2c_dev.clk_divisor_non_hs_mode member
  2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
                   ` (20 preceding siblings ...)
  2020-09-03  0:52 ` [PATCH v3 21/22] i2c: tegra: Initialization div-clk rate unconditionally Dmitry Osipenko
@ 2020-09-03  0:53 ` Dmitry Osipenko
  21 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03  0:53 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, Andy Shevchenko
  Cc: linux-i2c, linux-tegra, linux-kernel

The "non_hs_mode" divisor value is fixed, thus there is no need to have
the variable i2c_dev.clk_divisor_non_hs_mode struct member. Let's remove
it and move the mode selection into tegra_i2c_init() where it can be
united with the timing selection.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/i2c/busses/i2c-tegra.c | 52 ++++++++++++++--------------------
 1 file changed, 21 insertions(+), 31 deletions(-)

diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index bc7954c8a5a0..f3540dcb0e06 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -250,7 +250,6 @@ struct tegra_i2c_hw_feature {
  * @msg_buf_remaining: size of unsent data in the message buffer
  * @msg_read: identifies read transfers
  * @bus_clk_rate: current I2C bus clock rate
- * @clk_divisor_non_hs_mode: clock divider for non-high-speed modes
  * @is_multimaster_mode: track if I2C controller is in multi-master mode
  * @tx_dma_chan: DMA transmit channel
  * @rx_dma_chan: DMA receive channel
@@ -281,7 +280,6 @@ struct tegra_i2c_dev {
 	size_t msg_buf_remaining;
 	int msg_read;
 	u32 bus_clk_rate;
-	u16 clk_divisor_non_hs_mode;
 	bool is_multimaster_mode;
 	struct dma_chan *tx_dma_chan;
 	struct dma_chan *rx_dma_chan;
@@ -603,7 +601,7 @@ static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
 
 static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
 {
-	u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh;
+	u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode;
 	int err;
 
 	err = reset_control_reset(i2c_dev->rst);
@@ -625,24 +623,32 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
 	if (i2c_dev->is_vi)
 		tegra_i2c_vi_init(i2c_dev);
 
-	/* Make sure clock divisor programmed correctly */
-	clk_divisor = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE,
-				 i2c_dev->hw->clk_divisor_hs_mode) |
-		      FIELD_PREP(I2C_CLK_DIVISOR_STD_FAST_MODE,
-				 i2c_dev->clk_divisor_non_hs_mode);
-	i2c_writel(i2c_dev, clk_divisor, I2C_CLK_DIVISOR);
-
-	if (i2c_dev->bus_clk_rate > I2C_MAX_STANDARD_MODE_FREQ &&
-	    i2c_dev->bus_clk_rate <= I2C_MAX_FAST_MODE_PLUS_FREQ) {
+	switch (i2c_dev->bus_clk_rate) {
+	case I2C_MAX_STANDARD_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_PLUS_FREQ:
 		tlow = i2c_dev->hw->tlow_fast_fastplus_mode;
 		thigh = i2c_dev->hw->thigh_fast_fastplus_mode;
 		tsu_thd = i2c_dev->hw->setup_hold_time_fast_fast_plus_mode;
-	} else {
+
+		if (i2c_dev->bus_clk_rate > I2C_MAX_FAST_MODE_FREQ)
+			non_hs_mode = i2c_dev->hw->clk_divisor_fast_plus_mode;
+		else
+			non_hs_mode = i2c_dev->hw->clk_divisor_fast_mode;
+		break;
+
+	default:
 		tlow = i2c_dev->hw->tlow_std_mode;
 		thigh = i2c_dev->hw->thigh_std_mode;
 		tsu_thd = i2c_dev->hw->setup_hold_time_std_mode;
+		non_hs_mode = i2c_dev->hw->clk_divisor_std_mode;
+		break;
 	}
 
+	/* Make sure clock divisor programmed correctly */
+	clk_divisor = FIELD_PREP(I2C_CLK_DIVISOR_HSMODE,
+				 i2c_dev->hw->clk_divisor_hs_mode) |
+		      FIELD_PREP(I2C_CLK_DIVISOR_STD_FAST_MODE, non_hs_mode);
+	i2c_writel(i2c_dev, clk_divisor, I2C_CLK_DIVISOR);
+
 	if (i2c_dev->hw->has_interface_timing_reg) {
 		val = FIELD_PREP(I2C_INTERFACE_TIMING_THIGH, thigh) |
 		      FIELD_PREP(I2C_INTERFACE_TIMING_TLOW, tlow);
@@ -657,7 +663,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
 		i2c_writel(i2c_dev, tsu_thd, I2C_INTERFACE_TIMING_1);
 
 	clk_multiplier  = tlow + thigh + 2;
-	clk_multiplier *= i2c_dev->clk_divisor_non_hs_mode + 1;
+	clk_multiplier *= non_hs_mode + 1;
 
 	err = clk_set_rate(i2c_dev->div_clk,
 			   i2c_dev->bus_clk_rate * clk_multiplier);
@@ -1633,7 +1639,7 @@ static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
 	const struct tegra_i2c_hw_feature *hw = i2c_dev->hw;
 	struct device *dev = i2c_dev->dev;
 	struct clk *clk;
-	int err, mode;
+	int err;
 
 	clk = devm_clk_get(dev, "div-clk");
 	if (IS_ERR(clk))
@@ -1686,22 +1692,6 @@ static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
 		}
 	}
 
-	switch (i2c_dev->bus_clk_rate) {
-	case I2C_MAX_FAST_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_PLUS_FREQ:
-		mode = hw->clk_divisor_fast_plus_mode;
-		break;
-
-	case I2C_MAX_STANDARD_MODE_FREQ + 1 ... I2C_MAX_FAST_MODE_FREQ:
-		mode = hw->clk_divisor_fast_mode;
-		break;
-
-	default:
-		mode = hw->clk_divisor_std_mode;
-		break;
-	}
-
-	i2c_dev->clk_divisor_non_hs_mode = mode;
-
 	return 0;
 
 unprepare_div_clk:
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 01/22] i2c: tegra: Make tegra_i2c_flush_fifos() usable in atomic transfer
  2020-09-03  0:52 ` [PATCH v3 01/22] i2c: tegra: Make tegra_i2c_flush_fifos() usable in atomic transfer Dmitry Osipenko
@ 2020-09-03 11:02   ` Andy Shevchenko
  2020-09-03 13:49     ` Dmitry Osipenko
  0 siblings, 1 reply; 36+ messages in thread
From: Andy Shevchenko @ 2020-09-03 11:02 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List

On Thu, Sep 3, 2020 at 3:53 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>
> The tegra_i2c_flush_fifos() shouldn't sleep in atomic transfer and jiffies
> are not updating if interrupts are disabled. Hence let's use proper delay
> functions and use ktime API in order not to hang atomic transfer. Note
> that this patch doesn't fix any known problem because normally FIFO is
> flushed at the time of starting a new transfer.

> +       /*
> +        * ktime_get() may take up to couple milliseconds in a worst case
> +        * and normally FIFOs are flushed, hence let's check the state before
> +        * proceeding to polling.
> +        */

Everything, including above can be done by using macros from iopoll.h. Why not?

> +       if (!(i2c_readl(i2c_dev, offset) & mask))
> +               return 0;
> +
> +       ktime = ktime_get();
> +       ktimeout = ktime_add_ms(ktime, 1000);
> +
>         while (i2c_readl(i2c_dev, offset) & mask) {
> -               if (time_after(jiffies, timeout)) {
> -                       dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n");
> -                       return -ETIMEDOUT;
> -               }
> -               usleep_range(1000, 2000);
> +               if (ktime_after(ktime, ktimeout))
> +                       goto err_timeout;
> +
> +               if (i2c_dev->is_curr_atomic_xfer)
> +                       mdelay(1);
> +               else
> +                       fsleep(1000);
> +
> +               ktime = ktime_get();
>         }
>         return 0;
> +
> +err_timeout:
> +       dev_err(i2c_dev->dev, "FIFO flushing timed out\n");
> +
> +       return -ETIMEDOUT;
>  }


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 03/22] i2c: tegra: Clean up messages in the code
  2020-09-03  0:52 ` [PATCH v3 03/22] i2c: tegra: Clean up messages in the code Dmitry Osipenko
@ 2020-09-03 11:06   ` Andy Shevchenko
  2020-09-03 13:44     ` Dmitry Osipenko
  0 siblings, 1 reply; 36+ messages in thread
From: Andy Shevchenko @ 2020-09-03 11:06 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List

On Thu, Sep 3, 2020 at 3:53 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>
> This patch unifies style of all messages in the driver by starting them
> with a lowercase letter and using consistent capitalization and wording
> for all messages.

I didn't look at the rest (yet) but this series has a patch ordering issue.
Why do we first do some little, non-critical clean ups?

The preferred way is to arrange like:
 - fixes that may be backported
 - fixes that are likely not going to be backported
 - features
 - cleanups

In its turn cleanups go by severity:
 - code affected ones (and maybe logical changers)
 - ...
 - commentary / indentation fixes

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 04/22] i2c: tegra: Don't ignore tegra_i2c_flush_fifos() error
  2020-09-03  0:52 ` [PATCH v3 04/22] i2c: tegra: Don't ignore tegra_i2c_flush_fifos() error Dmitry Osipenko
@ 2020-09-03 11:09   ` Andy Shevchenko
  2020-09-03 13:54     ` Dmitry Osipenko
  0 siblings, 1 reply; 36+ messages in thread
From: Andy Shevchenko @ 2020-09-03 11:09 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List

On Thu, Sep 3, 2020 at 3:53 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>
> The tegra_i2c_flush_fifos() may fail and transfer should be aborted in
> this case.

Sounds like a fix. To add to previous comment, fixes that are likely
to be backported should have Fixes: tags.

> Reviewed-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/i2c/busses/i2c-tegra.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
> index 79e542cf3e59..b912a7153e3b 100644
> --- a/drivers/i2c/busses/i2c-tegra.c
> +++ b/drivers/i2c/busses/i2c-tegra.c
> @@ -1189,7 +1189,9 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
>         bool dma;
>         u16 xfer_time = 100;
>
> -       tegra_i2c_flush_fifos(i2c_dev);
> +       err = tegra_i2c_flush_fifos(i2c_dev);
> +       if (err)
> +               return err;
>
>         i2c_dev->msg_buf = msg->buf;
>         i2c_dev->msg_buf_remaining = msg->len;
> --
> 2.27.0
>


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 05/22] i2c: tegra: Use reset_control_reset()
  2020-09-03  0:52 ` [PATCH v3 05/22] i2c: tegra: Use reset_control_reset() Dmitry Osipenko
@ 2020-09-03 11:11   ` Andy Shevchenko
  2020-09-03 13:47     ` Dmitry Osipenko
  0 siblings, 1 reply; 36+ messages in thread
From: Andy Shevchenko @ 2020-09-03 11:11 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List

On Thu, Sep 3, 2020 at 3:53 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>
> Use a single reset_control_reset() instead of assert/deasset couple in
> order to make code cleaner a tad.

> Note that the reset_control_reset()
> uses 1 microsecond delay instead of 2 that was used previously, but this
> shouldn't matter.

What datasheet says about this delay?

> In addition don't ignore potential error of the reset.
>
> Reviewed-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 09/22] i2c: tegra: Clean up probe function
  2020-09-03  0:52 ` [PATCH v3 09/22] i2c: tegra: Clean up probe function Dmitry Osipenko
@ 2020-09-03 11:17   ` Andy Shevchenko
  2020-09-03 13:48     ` Dmitry Osipenko
  0 siblings, 1 reply; 36+ messages in thread
From: Andy Shevchenko @ 2020-09-03 11:17 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List

On Thu, Sep 3, 2020 at 3:54 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>
> The driver's probe function code is difficult to read and follow. This
> patch reorders code of the probe function, forming logical groups that are
> easy to work with. The clock and hardware initializations are factored
> out into separate functions in order to keep code clean and ease error
> unwinding.
>
> Driver now makes use of devm_platform_get_and_ioremap_resource() and
> platform_get_irq() which are replacing boilerplate parts of the code.
>
> The dev_err_probe() is now used for reset control retrieval because reset
> is now requested before clocks, and thus, BPMP driver that provides reset
> controls for newer SoCs may cause the probe defer.

> The error message of devm_request_irq() is removed because this function
> takes care of printing the message by itself.

I see no evidence of this.

...

> +       of_property_read_u32(np, "clock-frequency", &bus_clk_rate);
> +       i2c_dev->bus_clk_rate = bus_clk_rate;

Hmm... I dunno if Wolfram is going to implement a special helper
exactly for this. I remember we discussed that with him during v5.8
(?) times.

...

> +static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)

Hmm... Don't we have something like devm_clk_bulk_get_all() or so?

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 13/22] i2c: tegra: Check errors for both positive and negative values
  2020-09-03  0:52 ` [PATCH v3 13/22] i2c: tegra: Check errors for both positive and negative values Dmitry Osipenko
@ 2020-09-03 11:19   ` Andy Shevchenko
  0 siblings, 0 replies; 36+ messages in thread
From: Andy Shevchenko @ 2020-09-03 11:19 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List

On Thu, Sep 3, 2020 at 3:54 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>
> The driver's code is inconsistent in regards to the error values checking.
> The correct way should be to check both positive and negative values.
> This patch cleans up the error-checks in the code. Note that the
> pm_runtime_get_sync() could return positive value on success, hence only
> relevant parts of the code are changed by this patch.

Yeah, fix the order of the series. Now it seems like arbitrary mess.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 03/22] i2c: tegra: Clean up messages in the code
  2020-09-03 11:06   ` Andy Shevchenko
@ 2020-09-03 13:44     ` Dmitry Osipenko
  0 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03 13:44 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List

03.09.2020 14:06, Andy Shevchenko пишет:
> On Thu, Sep 3, 2020 at 3:53 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>>
>> This patch unifies style of all messages in the driver by starting them
>> with a lowercase letter and using consistent capitalization and wording
>> for all messages.
> 
> I didn't look at the rest (yet) but this series has a patch ordering issue.
> Why do we first do some little, non-critical clean ups?
> 
> The preferred way is to arrange like:
>  - fixes that may be backported
>  - fixes that are likely not going to be backported
>  - features
>  - cleanups
> 
> In its turn cleanups go by severity:
>  - code affected ones (and maybe logical changers)
>  - ...
>  - commentary / indentation fixes
> 

That's a good suggestion! All patches in this version are ordered by the
time they were created ans since none of these patches should be
worthwhile to backport (IMO) and because majority of patches do minor
changes, it appeared to me that it should be okay as-is.

I agree that it should be worthwhile to reorder the patches now, after
the series grew up a tad in regards to amount of patches. I'll change
the order in the next version, thanks!

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 05/22] i2c: tegra: Use reset_control_reset()
  2020-09-03 11:11   ` Andy Shevchenko
@ 2020-09-03 13:47     ` Dmitry Osipenko
  0 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03 13:47 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List, Peter De Schrijver

03.09.2020 14:11, Andy Shevchenko пишет:
> On Thu, Sep 3, 2020 at 3:53 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>>
>> Use a single reset_control_reset() instead of assert/deasset couple in
>> order to make code cleaner a tad.
> 
>> Note that the reset_control_reset()
>> uses 1 microsecond delay instead of 2 that was used previously, but this
>> shouldn't matter.
> 
> What datasheet says about this delay?

The public datasheet doesn't say anything specific about the I2C
controller reset time. IIUC, controller logic runs at 200/400 MHz, so
1us should be enough for the reset.

I'm sure that somebody from NVIDIA should know the exact answer and will
correct me if I'm wrong. I CC'd Peter De Schrijver who is a maintainer
of the Tegra's clock-and-reset driver.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 09/22] i2c: tegra: Clean up probe function
  2020-09-03 11:17   ` Andy Shevchenko
@ 2020-09-03 13:48     ` Dmitry Osipenko
  2020-09-03 14:02       ` Andy Shevchenko
  0 siblings, 1 reply; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03 13:48 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List

03.09.2020 14:17, Andy Shevchenko пишет:
> On Thu, Sep 3, 2020 at 3:54 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>>
>> The driver's probe function code is difficult to read and follow. This
>> patch reorders code of the probe function, forming logical groups that are
>> easy to work with. The clock and hardware initializations are factored
>> out into separate functions in order to keep code clean and ease error
>> unwinding.
>>
>> Driver now makes use of devm_platform_get_and_ioremap_resource() and
>> platform_get_irq() which are replacing boilerplate parts of the code.
>>
>> The dev_err_probe() is now used for reset control retrieval because reset
>> is now requested before clocks, and thus, BPMP driver that provides reset
>> controls for newer SoCs may cause the probe defer.
> 
>> The error message of devm_request_irq() is removed because this function
>> takes care of printing the message by itself.
> 
> I see no evidence of this.

Good catch! I confused it with the platform_get_irq() which prints the
message! I'll correct it in v4, thanks!

Anyways, the message of devm_request_irq() needs a correction since it
prints the number of vIRQ instead of the error code.

> ...
> 
>> +       of_property_read_u32(np, "clock-frequency", &bus_clk_rate);
>> +       i2c_dev->bus_clk_rate = bus_clk_rate;
> 
> Hmm... I dunno if Wolfram is going to implement a special helper
> exactly for this. I remember we discussed that with him during v5.8
> (?) times.

I now see that there is a i2c_parse_fw_timings() which parses
"clock-frequency" and other common properties. I could switch to use
that helper, but not sure whether it would be really worthwhile because
only one property is needed to be parsed. I'll consider this change for
v4, thank you for the suggestion!

> ...
> 
>> +static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
> 
> Hmm... Don't we have something like devm_clk_bulk_get_all() or so?
> 

Sounds like a good suggestion! I'll consider it for the v4, thanks!

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 01/22] i2c: tegra: Make tegra_i2c_flush_fifos() usable in atomic transfer
  2020-09-03 11:02   ` Andy Shevchenko
@ 2020-09-03 13:49     ` Dmitry Osipenko
  0 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03 13:49 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List

03.09.2020 14:02, Andy Shevchenko пишет:
> On Thu, Sep 3, 2020 at 3:53 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>>
>> The tegra_i2c_flush_fifos() shouldn't sleep in atomic transfer and jiffies
>> are not updating if interrupts are disabled. Hence let's use proper delay
>> functions and use ktime API in order not to hang atomic transfer. Note
>> that this patch doesn't fix any known problem because normally FIFO is
>> flushed at the time of starting a new transfer.
> 
>> +       /*
>> +        * ktime_get() may take up to couple milliseconds in a worst case
>> +        * and normally FIFOs are flushed, hence let's check the state before
>> +        * proceeding to polling.
>> +        */
> 
> Everything, including above can be done by using macros from iopoll.h. Why not?

Perhaps indeed it should be possible to use the common macros, at least
I can't recall why I chose not to use them. Maybe because it appeared to
me that the current variant is a bit nicer than:

if (atomic)
	read_poll_atomic()
else
	read_poll()


I'll consider to use the common iopoll macros in v4, thanks!

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 04/22] i2c: tegra: Don't ignore tegra_i2c_flush_fifos() error
  2020-09-03 11:09   ` Andy Shevchenko
@ 2020-09-03 13:54     ` Dmitry Osipenko
  0 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03 13:54 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List

03.09.2020 14:09, Andy Shevchenko пишет:
> On Thu, Sep 3, 2020 at 3:53 AM Dmitry Osipenko <digetx@gmail.com> wrote:
>>
>> The tegra_i2c_flush_fifos() may fail and transfer should be aborted in
>> this case.
> 
> Sounds like a fix. To add to previous comment, fixes that are likely
> to be backported should have Fixes: tags.

I'll reword the commit title and message in order to make it not to
sound like this is a bug fix. Thanks!

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 09/22] i2c: tegra: Clean up probe function
  2020-09-03 13:48     ` Dmitry Osipenko
@ 2020-09-03 14:02       ` Andy Shevchenko
  2020-09-03 15:56         ` Dmitry Osipenko
  0 siblings, 1 reply; 36+ messages in thread
From: Andy Shevchenko @ 2020-09-03 14:02 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List

On Thu, Sep 3, 2020 at 4:48 PM Dmitry Osipenko <digetx@gmail.com> wrote:
> 03.09.2020 14:17, Andy Shevchenko пишет:
> > On Thu, Sep 3, 2020 at 3:54 AM Dmitry Osipenko <digetx@gmail.com> wrote:

...

> >> +       of_property_read_u32(np, "clock-frequency", &bus_clk_rate);
> >> +       i2c_dev->bus_clk_rate = bus_clk_rate;
> >
> > Hmm... I dunno if Wolfram is going to implement a special helper
> > exactly for this. I remember we discussed that with him during v5.8
> > (?) times.
>
> I now see that there is a i2c_parse_fw_timings() which parses
> "clock-frequency" and other common properties. I could switch to use
> that helper, but not sure whether it would be really worthwhile because
> only one property is needed to be parsed. I'll consider this change for
> v4, thank you for the suggestion!

That's exactly why I was wondering about the current state of affairs
with the discussed helper which should only parse the clock-frequency
property.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v3 09/22] i2c: tegra: Clean up probe function
  2020-09-03 14:02       ` Andy Shevchenko
@ 2020-09-03 15:56         ` Dmitry Osipenko
  0 siblings, 0 replies; 36+ messages in thread
From: Dmitry Osipenko @ 2020-09-03 15:56 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Thierry Reding, Jonathan Hunter, Laxman Dewangan, Wolfram Sang,
	Michał Mirosław, linux-i2c, linux-tegra,
	Linux Kernel Mailing List

03.09.2020 17:02, Andy Shevchenko пишет:
> On Thu, Sep 3, 2020 at 4:48 PM Dmitry Osipenko <digetx@gmail.com> wrote:
>> 03.09.2020 14:17, Andy Shevchenko пишет:
>>> On Thu, Sep 3, 2020 at 3:54 AM Dmitry Osipenko <digetx@gmail.com> wrote:
> 
> ...
> 
>>>> +       of_property_read_u32(np, "clock-frequency", &bus_clk_rate);
>>>> +       i2c_dev->bus_clk_rate = bus_clk_rate;
>>>
>>> Hmm... I dunno if Wolfram is going to implement a special helper
>>> exactly for this. I remember we discussed that with him during v5.8
>>> (?) times.
>>
>> I now see that there is a i2c_parse_fw_timings() which parses
>> "clock-frequency" and other common properties. I could switch to use
>> that helper, but not sure whether it would be really worthwhile because
>> only one property is needed to be parsed. I'll consider this change for
>> v4, thank you for the suggestion!
> 
> That's exactly why I was wondering about the current state of affairs
> with the discussed helper which should only parse the clock-frequency
> property.
> 

Alright, I see that many other I2C drivers are in the same position, so
perhaps should better to keep the current variant as-is until a common
solution will become available.

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2020-09-03 15:56 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-03  0:52 [PATCH v3 00/22] Improvements for Tegra I2C driver Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 01/22] i2c: tegra: Make tegra_i2c_flush_fifos() usable in atomic transfer Dmitry Osipenko
2020-09-03 11:02   ` Andy Shevchenko
2020-09-03 13:49     ` Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 02/22] i2c: tegra: Add missing newline before returns Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 03/22] i2c: tegra: Clean up messages in the code Dmitry Osipenko
2020-09-03 11:06   ` Andy Shevchenko
2020-09-03 13:44     ` Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 04/22] i2c: tegra: Don't ignore tegra_i2c_flush_fifos() error Dmitry Osipenko
2020-09-03 11:09   ` Andy Shevchenko
2020-09-03 13:54     ` Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 05/22] i2c: tegra: Use reset_control_reset() Dmitry Osipenko
2020-09-03 11:11   ` Andy Shevchenko
2020-09-03 13:47     ` Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 06/22] i2c: tegra: Improve formatting of function variables Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 07/22] i2c: tegra: Use dev_err_probe() Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 08/22] i2c: tegra: Runtime PM always available on Tegra Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 09/22] i2c: tegra: Clean up probe function Dmitry Osipenko
2020-09-03 11:17   ` Andy Shevchenko
2020-09-03 13:48     ` Dmitry Osipenko
2020-09-03 14:02       ` Andy Shevchenko
2020-09-03 15:56         ` Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 10/22] i2c: tegra: Drop '_timeout' from wait/poll function names Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 11/22] i2c: tegra: Remove likely/unlikely from the code Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 12/22] i2c: tegra: Factor out error recovery from tegra_i2c_xfer_msg() Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 13/22] i2c: tegra: Check errors for both positive and negative values Dmitry Osipenko
2020-09-03 11:19   ` Andy Shevchenko
2020-09-03  0:52 ` [PATCH v3 14/22] i2c: tegra: Improve coding style of tegra_i2c_wait_for_config_load() Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 15/22] i2c: tegra: Clean up whitespaces and newlines Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 16/22] i2c: tegra: Rename variable in tegra_i2c_issue_bus_clear() Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 17/22] i2c: tegra: Improve driver module description Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 18/22] i2c: tegra: Reorder location of functions in the code Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 19/22] i2c: tegra: Factor out packet header setup from tegra_i2c_xfer_msg() Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 20/22] i2c: tegra: Remove "dma" variable Dmitry Osipenko
2020-09-03  0:52 ` [PATCH v3 21/22] i2c: tegra: Initialization div-clk rate unconditionally Dmitry Osipenko
2020-09-03  0:53 ` [PATCH v3 22/22] i2c: tegra: Remove i2c_dev.clk_divisor_non_hs_mode member Dmitry Osipenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.