linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes
@ 2021-04-06 11:32 Clark Wang
  2021-04-06 11:32 ` [PATCH V2 01/18] i2c: imx-lpi2c: directly retrun ISR when detect a NACK Clark Wang
                   ` (17 more replies)
  0 siblings, 18 replies; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:32 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

Hi,

According to V1's feedback, V2 has been modified.
For summary of the changes, please refer to the header of each patch file.

Added some dt-bindings and dts patches.
At the same time, a patch has been added to fix the problem that data larger
than 256 bytes cannot be sent in one frame in PIO mode.

Clark Wang (14):
  i2c: imx-lpi2c: add ipg clk for lpi2c driver
  ARM: dts: imx7ulp: add the missing lpi2c ipg clock
  ARM: dts: imx7ulp: add the missing lpi2c nodes
  ARM64: dts: imx8: add the missing lpi2c ipg clock
  ARM64: dts: imx8: change i2c irq number to non-combined
  i2c: imx-lpi2c: increase PM timeout to avoid operate clk frequently
  i2c: imx-lpi2c: add bus recovery feature
  dt-bindings: i2c: imx-lpi2c: Add bus recovery example
  i2c: imx-lpi2c: fix i2c timing issue
  i2c: imx-lpi2c: fix type char overflow issue when calculating the
    clock cycle
  i2c: imx-lpi2c: add edma mode support
  dt-bindings: i2c: imx-lpi2c: Add dma configuration example
  ARM: dts: imx7ulp: add dma configurations for lpi2c
  ARM: dts: imx7ulp: add the missing status property of lpi2c5
  i2c: imx-lpi2c: fix pio mode cannot send 256+ bytes in one frame

Fugang Duan (1):
  i2c: imx-lpi2c: manage irq resource request/release in runtime pm

Gao Pan (2):
  i2c: imx-lpi2c: directly retrun ISR when detect a NACK
  i2c: imx-lpi2c: add debug message when i2c peripheral clk doesn't work

 .../bindings/i2c/i2c-imx-lpi2c.yaml           |  26 +
 arch/arm/boot/dts/imx7ulp.dtsi                |  50 +-
 .../arm64/boot/dts/freescale/imx8-ss-dma.dtsi |  32 +-
 drivers/i2c/busses/i2c-imx-lpi2c.c            | 506 ++++++++++++++++--
 4 files changed, 548 insertions(+), 66 deletions(-)

-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 01/18] i2c: imx-lpi2c: directly retrun ISR when detect a NACK
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
@ 2021-04-06 11:32 ` Clark Wang
  2021-04-06 11:32 ` [PATCH V2 02/18] i2c: imx-lpi2c: add ipg clk for lpi2c driver Clark Wang
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:32 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

From: Gao Pan <pandy.gao@nxp.com>

A NACK flag in ISR means i2c bus error. In such codition,
there is no need to do read/write operation. It's better
to return ISR directly and then stop i2c transfer.

Signed-off-by: Gao Pan <pandy.gao@nxp.com>
Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
Reviewed-by: Dong Aisheng <aisheng.dong@nxp.com>
---
V2 changes:
 - No change. Has been reviewed by Dong Aisheng <aisheng.dong@nxp.com> in V1.
---
 drivers/i2c/busses/i2c-imx-lpi2c.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 9db6ccded5e9..bbf44ac95021 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -507,15 +507,17 @@ static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id)
 	lpi2c_imx_intctrl(lpi2c_imx, 0);
 	temp = readl(lpi2c_imx->base + LPI2C_MSR);
 
+	if (temp & MSR_NDF) {
+		complete(&lpi2c_imx->complete);
+		goto ret;
+	}
+
 	if (temp & MSR_RDF)
 		lpi2c_imx_read_rxfifo(lpi2c_imx);
-
-	if (temp & MSR_TDF)
+	else if (temp & MSR_TDF)
 		lpi2c_imx_write_txfifo(lpi2c_imx);
 
-	if (temp & MSR_NDF)
-		complete(&lpi2c_imx->complete);
-
+ret:
 	return IRQ_HANDLED;
 }
 
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 02/18] i2c: imx-lpi2c: add ipg clk for lpi2c driver
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
  2021-04-06 11:32 ` [PATCH V2 01/18] i2c: imx-lpi2c: directly retrun ISR when detect a NACK Clark Wang
@ 2021-04-06 11:32 ` Clark Wang
  2021-05-21  6:14   ` Aisheng Dong
  2021-04-06 11:32 ` [PATCH V2 03/18] ARM: dts: imx7ulp: add the missing lpi2c ipg clock Clark Wang
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:32 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

The lpi2c IP needs two clks: ipg clk and per clk. The old lpi2c
driver missed ipg clk. This patch adds ipg clk for lpi2c driver.

Signed-off-by: Gao Pan <pandy.gao@nxp.com>
Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
Acked-by: Fugang Duan <fugang.duan@nxp.com>
---
V2 changes:
 - Merge two clocks' prepare funtions to lpi2c_imx_clocks_prepare().
---
 drivers/i2c/busses/i2c-imx-lpi2c.c | 61 +++++++++++++++++++++---------
 1 file changed, 44 insertions(+), 17 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index bbf44ac95021..89b7b0795f51 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -94,7 +94,8 @@ enum lpi2c_imx_pincfg {
 
 struct lpi2c_imx_struct {
 	struct i2c_adapter	adapter;
-	struct clk		*clk;
+	struct clk		*clk_per;
+	struct clk		*clk_ipg;
 	void __iomem		*base;
 	__u8			*rx_buf;
 	__u8			*tx_buf;
@@ -207,7 +208,7 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
 
 	lpi2c_imx_set_mode(lpi2c_imx);
 
-	clk_rate = clk_get_rate(lpi2c_imx->clk);
+	clk_rate = clk_get_rate(lpi2c_imx->clk_per);
 	if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST)
 		filt = 0;
 	else
@@ -538,6 +539,34 @@ static const struct of_device_id lpi2c_imx_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, lpi2c_imx_of_match);
 
+static int lpi2c_imx_clocks_prepare(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	int ret = 0;
+
+	ret = clk_prepare_enable(lpi2c_imx->clk_per);
+	if (ret) {
+		dev_err(lpi2c_imx->adapter.dev.parent,
+				"can't enable I2C per clock, ret=%d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(lpi2c_imx->clk_ipg);
+	if (ret) {
+		clk_disable_unprepare(lpi2c_imx->clk_per);
+		dev_err(lpi2c_imx->adapter.dev.parent,
+				"can't enable I2C ipg clock, ret=%d\n", ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static void lpi2c_imx_clocks_unprepare(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	clk_disable_unprepare(lpi2c_imx->clk_ipg);
+	clk_disable_unprepare(lpi2c_imx->clk_per);
+}
+
 static int lpi2c_imx_probe(struct platform_device *pdev)
 {
 	struct lpi2c_imx_struct *lpi2c_imx;
@@ -563,10 +592,16 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
 	strlcpy(lpi2c_imx->adapter.name, pdev->name,
 		sizeof(lpi2c_imx->adapter.name));
 
-	lpi2c_imx->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(lpi2c_imx->clk)) {
+	lpi2c_imx->clk_per = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(lpi2c_imx->clk_per)) {
 		dev_err(&pdev->dev, "can't get I2C peripheral clock\n");
-		return PTR_ERR(lpi2c_imx->clk);
+		return PTR_ERR(lpi2c_imx->clk_per);
+	}
+
+	lpi2c_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(lpi2c_imx->clk_ipg)) {
+		dev_err(&pdev->dev, "can't get I2C ipg clock\n");
+		return PTR_ERR(lpi2c_imx->clk_ipg);
 	}
 
 	ret = of_property_read_u32(pdev->dev.of_node,
@@ -584,11 +619,9 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
 	i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx);
 	platform_set_drvdata(pdev, lpi2c_imx);
 
-	ret = clk_prepare_enable(lpi2c_imx->clk);
-	if (ret) {
-		dev_err(&pdev->dev, "clk enable failed %d\n", ret);
+	ret = lpi2c_imx_clocks_prepare(lpi2c_imx);
+	if (ret)
 		return ret;
-	}
 
 	pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
 	pm_runtime_use_autosuspend(&pdev->dev);
@@ -635,7 +668,7 @@ static int __maybe_unused lpi2c_runtime_suspend(struct device *dev)
 {
 	struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
 
-	clk_disable_unprepare(lpi2c_imx->clk);
+	lpi2c_imx_clocks_unprepare(lpi2c_imx);
 	pinctrl_pm_select_sleep_state(dev);
 
 	return 0;
@@ -644,16 +677,10 @@ static int __maybe_unused lpi2c_runtime_suspend(struct device *dev)
 static int __maybe_unused lpi2c_runtime_resume(struct device *dev)
 {
 	struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
-	int ret;
 
 	pinctrl_pm_select_default_state(dev);
-	ret = clk_prepare_enable(lpi2c_imx->clk);
-	if (ret) {
-		dev_err(dev, "failed to enable I2C clock, ret=%d\n", ret);
-		return ret;
-	}
 
-	return 0;
+	return lpi2c_imx_clocks_prepare(lpi2c_imx);
 }
 
 static const struct dev_pm_ops lpi2c_pm_ops = {
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 03/18] ARM: dts: imx7ulp: add the missing lpi2c ipg clock
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
  2021-04-06 11:32 ` [PATCH V2 01/18] i2c: imx-lpi2c: directly retrun ISR when detect a NACK Clark Wang
  2021-04-06 11:32 ` [PATCH V2 02/18] i2c: imx-lpi2c: add ipg clk for lpi2c driver Clark Wang
@ 2021-04-06 11:32 ` Clark Wang
  2021-05-21  6:17   ` Aisheng Dong
  2021-04-06 11:32 ` [PATCH V2 04/18] ARM: dts: imx7ulp: add the missing lpi2c nodes Clark Wang
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:32 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

The lpi2c driver has add the missing ipg clock.
So add the ipg clock here for all lpi2c nodes.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
---
V2 changes:
 - New patch added in V2
---
 arch/arm/boot/dts/imx7ulp.dtsi | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
index b7ea37ad4e55..eb0d4b8f624d 100644
--- a/arch/arm/boot/dts/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/imx7ulp.dtsi
@@ -328,8 +328,9 @@ lpi2c6: i2c@40a40000 {
 			compatible = "fsl,imx7ulp-lpi2c";
 			reg = <0x40a40000 0x10000>;
 			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>;
-			clock-names = "ipg";
+			clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>,
+				 <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>;
+			clock-names = "per", "ipg";
 			assigned-clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>;
 			assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
 			assigned-clock-rates = <48000000>;
@@ -340,8 +341,9 @@ lpi2c7: i2c@40a50000 {
 			compatible = "fsl,imx7ulp-lpi2c";
 			reg = <0x40a50000 0x10000>;
 			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>;
-			clock-names = "ipg";
+			clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>,
+				 <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>;
+			clock-names = "per", "ipg";
 			assigned-clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>;
 			assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
 			assigned-clock-rates = <48000000>;
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 04/18] ARM: dts: imx7ulp: add the missing lpi2c nodes
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (2 preceding siblings ...)
  2021-04-06 11:32 ` [PATCH V2 03/18] ARM: dts: imx7ulp: add the missing lpi2c ipg clock Clark Wang
@ 2021-04-06 11:32 ` Clark Wang
  2021-05-21  6:25   ` Aisheng Dong
  2021-04-06 11:32 ` [PATCH V2 05/18] ARM64: dts: imx8: add the missing lpi2c ipg clock Clark Wang
                   ` (13 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:32 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

Add the missing lpi2c4/5 nodes for imx7ulp.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
---
V2 changes:
 - New patch added in V2
---
 arch/arm/boot/dts/imx7ulp.dtsi | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
index eb0d4b8f624d..0c51fa79c0bc 100644
--- a/arch/arm/boot/dts/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/imx7ulp.dtsi
@@ -22,8 +22,10 @@ aliases {
 		gpio1 = &gpio_ptd;
 		gpio2 = &gpio_pte;
 		gpio3 = &gpio_ptf;
-		i2c0 = &lpi2c6;
-		i2c1 = &lpi2c7;
+		i2c0 = &lpi2c4;
+		i2c1 = &lpi2c5;
+		i2c2 = &lpi2c6;
+		i2c3 = &lpi2c7;
 		mmc0 = &usdhc0;
 		mmc1 = &usdhc1;
 		serial0 = &lpuart4;
@@ -145,6 +147,31 @@ sec_jr1: jr@2000 {
 			};
 		};
 
+		lpi2c4: lpi2c4@402b0000 {
+			compatible = "fsl,imx7ulp-lpi2c";
+			reg = <0x402b0000 0x10000>;
+			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pcc2 IMX7ULP_CLK_LPI2C4>,
+				 <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>;
+			clock-names = "per", "ipg";
+			assigned-clocks = <&pcc2 IMX7ULP_CLK_LPI2C4>;
+			assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
+			assigned-clock-rates = <48000000>;
+			status = "disabled";
+		};
+
+		lpi2c5: lpi2c5@402c0000 {
+			compatible = "fsl,imx7ulp-lpi2c";
+			reg = <0x402c0000 0x10000>;
+			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pcc2 IMX7ULP_CLK_LPI2C5>,
+				 <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>;
+			clock-names = "per", "ipg";
+			assigned-clocks = <&pcc2 IMX7ULP_CLK_LPI2C5>;
+			assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
+			assigned-clock-rates = <48000000>;
+		};
+
 		lpuart4: serial@402d0000 {
 			compatible = "fsl,imx7ulp-lpuart";
 			reg = <0x402d0000 0x1000>;
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 05/18] ARM64: dts: imx8: add the missing lpi2c ipg clock
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (3 preceding siblings ...)
  2021-04-06 11:32 ` [PATCH V2 04/18] ARM: dts: imx7ulp: add the missing lpi2c nodes Clark Wang
@ 2021-04-06 11:32 ` Clark Wang
  2021-05-11  2:59   ` Shawn Guo
  2021-05-21  6:28   ` Aisheng Dong
  2021-04-06 11:32 ` [PATCH V2 06/18] ARM64: dts: imx8: change i2c irq number to non-combined Clark Wang
                   ` (12 subsequent siblings)
  17 siblings, 2 replies; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:32 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

The lpi2c driver has add the missing ipg clock.
So add the ipg clock here for all lpi2c nodes.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
---
V2 changes:
 - New patch added in V2
---
 .../arm64/boot/dts/freescale/imx8-ss-dma.dtsi | 24 ++++++++++++-------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
index 960a802b8b6e..b5ed12a06538 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
@@ -111,8 +111,10 @@ uart3_lpcg: clock-controller@5a490000 {
 	i2c0: i2c@5a800000 {
 		reg = <0x5a800000 0x4000>;
 		interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>;
-		clock-names = "per";
+		interrupt-parent = <&gic>;
+		clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>,
+			 <&i2c0_lpcg IMX_LPCG_CLK_4>;
+		clock-names = "per", "ipg";
 		assigned-clocks = <&clk IMX_SC_R_I2C_0 IMX_SC_PM_CLK_PER>;
 		assigned-clock-rates = <24000000>;
 		power-domains = <&pd IMX_SC_R_I2C_0>;
@@ -122,8 +124,10 @@ i2c0: i2c@5a800000 {
 	i2c1: i2c@5a810000 {
 		reg = <0x5a810000 0x4000>;
 		interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>;
-		clock-names = "per";
+		interrupt-parent = <&gic>;
+		clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>,
+			 <&i2c1_lpcg IMX_LPCG_CLK_4>;
+		clock-names = "per", "ipg";
 		assigned-clocks = <&clk IMX_SC_R_I2C_1 IMX_SC_PM_CLK_PER>;
 		assigned-clock-rates = <24000000>;
 		power-domains = <&pd IMX_SC_R_I2C_1>;
@@ -133,8 +137,10 @@ i2c1: i2c@5a810000 {
 	i2c2: i2c@5a820000 {
 		reg = <0x5a820000 0x4000>;
 		interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>;
-		clock-names = "per";
+		interrupt-parent = <&gic>;
+		clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>,
+			 <&i2c2_lpcg IMX_LPCG_CLK_4>;
+		clock-names = "per", "ipg";
 		assigned-clocks = <&clk IMX_SC_R_I2C_2 IMX_SC_PM_CLK_PER>;
 		assigned-clock-rates = <24000000>;
 		power-domains = <&pd IMX_SC_R_I2C_2>;
@@ -144,8 +150,10 @@ i2c2: i2c@5a820000 {
 	i2c3: i2c@5a830000 {
 		reg = <0x5a830000 0x4000>;
 		interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>;
-		clock-names = "per";
+		interrupt-parent = <&gic>;
+		clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>,
+			 <&i2c3_lpcg IMX_LPCG_CLK_4>;
+		clock-names = "per", "ipg";
 		assigned-clocks = <&clk IMX_SC_R_I2C_3 IMX_SC_PM_CLK_PER>;
 		assigned-clock-rates = <24000000>;
 		power-domains = <&pd IMX_SC_R_I2C_3>;
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 06/18] ARM64: dts: imx8: change i2c irq number to non-combined
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (4 preceding siblings ...)
  2021-04-06 11:32 ` [PATCH V2 05/18] ARM64: dts: imx8: add the missing lpi2c ipg clock Clark Wang
@ 2021-04-06 11:32 ` Clark Wang
  2021-05-21  6:32   ` Aisheng Dong
  2021-04-06 11:32 ` [PATCH V2 07/18] i2c: imx-lpi2c: manage irq resource request/release in runtime pm Clark Wang
                   ` (11 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:32 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

Combined interrupt number may cause unexcepted irq event when using DMA
and too many interrupts will be generated.
So change all i2c interrupts number to non-combined for
imx8qxp/8qm/8dxl.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
---
V2 changes:
 - New patch added in V2
---
 arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
index b5ed12a06538..9ba57f04859b 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
@@ -110,7 +110,7 @@ uart3_lpcg: clock-controller@5a490000 {
 
 	i2c0: i2c@5a800000 {
 		reg = <0x5a800000 0x4000>;
-		interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-parent = <&gic>;
 		clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>,
 			 <&i2c0_lpcg IMX_LPCG_CLK_4>;
@@ -123,7 +123,7 @@ i2c0: i2c@5a800000 {
 
 	i2c1: i2c@5a810000 {
 		reg = <0x5a810000 0x4000>;
-		interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-parent = <&gic>;
 		clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>,
 			 <&i2c1_lpcg IMX_LPCG_CLK_4>;
@@ -136,7 +136,7 @@ i2c1: i2c@5a810000 {
 
 	i2c2: i2c@5a820000 {
 		reg = <0x5a820000 0x4000>;
-		interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-parent = <&gic>;
 		clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>,
 			 <&i2c2_lpcg IMX_LPCG_CLK_4>;
@@ -149,7 +149,7 @@ i2c2: i2c@5a820000 {
 
 	i2c3: i2c@5a830000 {
 		reg = <0x5a830000 0x4000>;
-		interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-parent = <&gic>;
 		clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>,
 			 <&i2c3_lpcg IMX_LPCG_CLK_4>;
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 07/18] i2c: imx-lpi2c: manage irq resource request/release in runtime pm
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (5 preceding siblings ...)
  2021-04-06 11:32 ` [PATCH V2 06/18] ARM64: dts: imx8: change i2c irq number to non-combined Clark Wang
@ 2021-04-06 11:32 ` Clark Wang
  2021-05-21  6:38   ` Aisheng Dong
  2021-04-06 11:32 ` [PATCH V2 08/18] i2c: imx-lpi2c: add debug message when i2c peripheral clk doesn't work Clark Wang
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:32 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

From: Fugang Duan <fugang.duan@nxp.com>

Manage irq resource request/release in runtime pm to save irq domain's
power.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
V2 changes:
 - Change to use request_irq/free_irq.
---
 drivers/i2c/busses/i2c-imx-lpi2c.c | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 89b7b0795f51..333209ba81c1 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -94,6 +94,7 @@ enum lpi2c_imx_pincfg {
 
 struct lpi2c_imx_struct {
 	struct i2c_adapter	adapter;
+	int			irq;
 	struct clk		*clk_per;
 	struct clk		*clk_ipg;
 	void __iomem		*base;
@@ -571,7 +572,7 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
 {
 	struct lpi2c_imx_struct *lpi2c_imx;
 	unsigned int temp;
-	int irq, ret;
+	int ret;
 
 	lpi2c_imx = devm_kzalloc(&pdev->dev, sizeof(*lpi2c_imx), GFP_KERNEL);
 	if (!lpi2c_imx)
@@ -581,9 +582,9 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
 	if (IS_ERR(lpi2c_imx->base))
 		return PTR_ERR(lpi2c_imx->base);
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
+	lpi2c_imx->irq = platform_get_irq(pdev, 0);
+	if (lpi2c_imx->irq < 0)
+		return lpi2c_imx->irq;
 
 	lpi2c_imx->adapter.owner	= THIS_MODULE;
 	lpi2c_imx->adapter.algo		= &lpi2c_imx_algo;
@@ -609,13 +610,6 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
 	if (ret)
 		lpi2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ;
 
-	ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, 0,
-			       pdev->name, lpi2c_imx);
-	if (ret) {
-		dev_err(&pdev->dev, "can't claim irq %d\n", irq);
-		return ret;
-	}
-
 	i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx);
 	platform_set_drvdata(pdev, lpi2c_imx);
 
@@ -668,6 +662,7 @@ static int __maybe_unused lpi2c_runtime_suspend(struct device *dev)
 {
 	struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
 
+	free_irq(lpi2c_imx->irq, lpi2c_imx);
 	lpi2c_imx_clocks_unprepare(lpi2c_imx);
 	pinctrl_pm_select_sleep_state(dev);
 
@@ -677,10 +672,21 @@ static int __maybe_unused lpi2c_runtime_suspend(struct device *dev)
 static int __maybe_unused lpi2c_runtime_resume(struct device *dev)
 {
 	struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
+	int ret = 0;
 
 	pinctrl_pm_select_default_state(dev);
+	ret = lpi2c_imx_clocks_prepare(lpi2c_imx);
+	if (ret)
+		return ret;
 
-	return lpi2c_imx_clocks_prepare(lpi2c_imx);
+	ret = request_irq(lpi2c_imx->irq, lpi2c_imx_isr, 0,
+			       dev_name(dev), lpi2c_imx);
+	if (ret) {
+		dev_err(dev, "can't claim irq %d\n", lpi2c_imx->irq);
+		return ret;
+	}
+
+	return ret;
 }
 
 static const struct dev_pm_ops lpi2c_pm_ops = {
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 08/18] i2c: imx-lpi2c: add debug message when i2c peripheral clk doesn't work
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (6 preceding siblings ...)
  2021-04-06 11:32 ` [PATCH V2 07/18] i2c: imx-lpi2c: manage irq resource request/release in runtime pm Clark Wang
@ 2021-04-06 11:32 ` Clark Wang
  2021-05-21  6:43   ` Aisheng Dong
  2021-04-06 11:32 ` [PATCH V2 09/18] i2c: imx-lpi2c: increase PM timeout to avoid operate clk frequently Clark Wang
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:32 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

From: Gao Pan <pandy.gao@nxp.com>

add debug message when i2c peripheral clk rate is 0, then
directly return -EINVAL.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
Signed-off-by: Gao Pan <pandy.gao@nxp.com>
Reviewed-by: Andy Duan <fugang.duan@nxp.com>
---
V2 changes:
 - Add my signed-off.
---
 drivers/i2c/busses/i2c-imx-lpi2c.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 333209ba81c1..dfec334712c2 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -210,6 +210,11 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
 	lpi2c_imx_set_mode(lpi2c_imx);
 
 	clk_rate = clk_get_rate(lpi2c_imx->clk_per);
+	if (!clk_rate) {
+		dev_dbg(&lpi2c_imx->adapter.dev, "clk_per rate is 0\n");
+		return -EINVAL;
+	}
+
 	if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST)
 		filt = 0;
 	else
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 09/18] i2c: imx-lpi2c: increase PM timeout to avoid operate clk frequently
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (7 preceding siblings ...)
  2021-04-06 11:32 ` [PATCH V2 08/18] i2c: imx-lpi2c: add debug message when i2c peripheral clk doesn't work Clark Wang
@ 2021-04-06 11:32 ` Clark Wang
  2021-04-06 11:32 ` [PATCH V2 10/18] i2c: imx-lpi2c: add bus recovery feature Clark Wang
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:32 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

Switching the clock frequently will affect the data transmission
efficiency, and prolong the timeout to reduce autosuspend times for
lpi2c.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
Acked-by: Fugang Duan <fugang.duan@nxp.com>
Reviewed-by: Dong Aisheng <aisheng.dong@nxp.com>
---
V2 changes:
 - No change. Has been reviewed by Dong Aisheng <aisheng.dong@nxp.com> in V1.
---
 drivers/i2c/busses/i2c-imx-lpi2c.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index dfec334712c2..77ceb743b282 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -75,7 +75,7 @@
 #define I2C_CLK_RATIO	2
 #define CHUNK_DATA	256
 
-#define I2C_PM_TIMEOUT		10 /* ms */
+#define I2C_PM_TIMEOUT		1000 /* ms */
 
 enum lpi2c_imx_mode {
 	STANDARD,	/* 100+Kbps */
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 10/18] i2c: imx-lpi2c: add bus recovery feature
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (8 preceding siblings ...)
  2021-04-06 11:32 ` [PATCH V2 09/18] i2c: imx-lpi2c: increase PM timeout to avoid operate clk frequently Clark Wang
@ 2021-04-06 11:32 ` Clark Wang
  2021-04-07  0:34   ` kernel test robot
  2021-05-21  6:44   ` Aisheng Dong
  2021-04-06 11:32 ` [PATCH V2 11/18] dt-bindings: i2c: imx-lpi2c: Add bus recovery example Clark Wang
                   ` (7 subsequent siblings)
  17 siblings, 2 replies; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:32 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

Add bus recovery feature for LPI2C.
Need add gpio pinctrl, scl-gpios and sda-gpios configuration in dts.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
---
V2 changes:
 - No change. Add dt-bindings in the next patch.
---
 drivers/i2c/busses/i2c-imx-lpi2c.c | 83 ++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)

diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 77ceb743b282..77dd6ee5a4a8 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
@@ -108,6 +109,11 @@ struct lpi2c_imx_struct {
 	unsigned int		txfifosize;
 	unsigned int		rxfifosize;
 	enum lpi2c_imx_mode	mode;
+
+	struct i2c_bus_recovery_info rinfo;
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pinctrl_pins_default;
+	struct pinctrl_state *pinctrl_pins_gpio;
 };
 
 static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx,
@@ -135,6 +141,8 @@ static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx)
 
 		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
 			dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n");
+			if (lpi2c_imx->adapter.bus_recovery_info)
+				i2c_recover_bus(&lpi2c_imx->adapter);
 			return -ETIMEDOUT;
 		}
 		schedule();
@@ -192,6 +200,8 @@ static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx)
 
 		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
 			dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n");
+			if (lpi2c_imx->adapter.bus_recovery_info)
+				i2c_recover_bus(&lpi2c_imx->adapter);
 			break;
 		}
 		schedule();
@@ -329,6 +339,8 @@ static int lpi2c_imx_txfifo_empty(struct lpi2c_imx_struct *lpi2c_imx)
 
 		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
 			dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n");
+			if (lpi2c_imx->adapter.bus_recovery_info)
+				i2c_recover_bus(&lpi2c_imx->adapter);
 			return -ETIMEDOUT;
 		}
 		schedule();
@@ -528,6 +540,71 @@ static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static void lpi2c_imx_prepare_recovery(struct i2c_adapter *adap)
+{
+	struct lpi2c_imx_struct *lpi2c_imx;
+
+	lpi2c_imx = container_of(adap, struct lpi2c_imx_struct, adapter);
+
+	pinctrl_select_state(lpi2c_imx->pinctrl, lpi2c_imx->pinctrl_pins_gpio);
+}
+
+static void lpi2c_imx_unprepare_recovery(struct i2c_adapter *adap)
+{
+	struct lpi2c_imx_struct *lpi2c_imx;
+
+	lpi2c_imx = container_of(adap, struct lpi2c_imx_struct, adapter);
+
+	pinctrl_select_state(lpi2c_imx->pinctrl, lpi2c_imx->pinctrl_pins_default);
+}
+
+/*
+ * We switch SCL and SDA to their GPIO function and do some bitbanging
+ * for bus recovery. These alternative pinmux settings can be
+ * described in the device tree by a separate pinctrl state "gpio". If
+ * this is missing this is not a big problem, the only implication is
+ * that we can't do bus recovery.
+ */
+static int lpi2c_imx_init_recovery_info(struct lpi2c_imx_struct *lpi2c_imx,
+		struct platform_device *pdev)
+{
+	struct i2c_bus_recovery_info *rinfo = &lpi2c_imx->rinfo;
+
+	lpi2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (!lpi2c_imx->pinctrl || IS_ERR(lpi2c_imx->pinctrl)) {
+		dev_info(&pdev->dev, "can't get pinctrl, bus recovery not supported\n");
+		return PTR_ERR(lpi2c_imx->pinctrl);
+	}
+
+	lpi2c_imx->pinctrl_pins_default = pinctrl_lookup_state(lpi2c_imx->pinctrl,
+			PINCTRL_STATE_DEFAULT);
+	lpi2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(lpi2c_imx->pinctrl,
+			"gpio");
+	rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
+	rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
+
+	if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER ||
+	    PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER) {
+		return -EPROBE_DEFER;
+	} else if (IS_ERR(rinfo->sda_gpiod) ||
+		   IS_ERR(rinfo->scl_gpiod) ||
+		   IS_ERR(lpi2c_imx->pinctrl_pins_default) ||
+		   IS_ERR(lpi2c_imx->pinctrl_pins_gpio)) {
+		dev_dbg(&pdev->dev, "recovery information incomplete\n");
+		return 0;
+	}
+
+	dev_info(&pdev->dev, "using scl%s for recovery\n",
+		 rinfo->sda_gpiod ? ",sda" : "");
+
+	rinfo->prepare_recovery = lpi2c_imx_prepare_recovery;
+	rinfo->unprepare_recovery = lpi2c_imx_unprepare_recovery;
+	rinfo->recover_bus = i2c_generic_scl_recovery;
+	lpi2c_imx->adapter.bus_recovery_info = rinfo;
+
+	return 0;
+}
+
 static u32 lpi2c_imx_func(struct i2c_adapter *adapter)
 {
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
@@ -632,6 +709,12 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
 	lpi2c_imx->txfifosize = 1 << (temp & 0x0f);
 	lpi2c_imx->rxfifosize = 1 << ((temp >> 8) & 0x0f);
 
+	/* Init optional bus recovery function */
+	ret = lpi2c_imx_init_recovery_info(lpi2c_imx, pdev);
+	/* Give it another chance if pinctrl used is not ready yet */
+	if (ret == -EPROBE_DEFER)
+		goto rpm_disable;
+
 	ret = i2c_add_adapter(&lpi2c_imx->adapter);
 	if (ret)
 		goto rpm_disable;
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 11/18] dt-bindings: i2c: imx-lpi2c: Add bus recovery example
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (9 preceding siblings ...)
  2021-04-06 11:32 ` [PATCH V2 10/18] i2c: imx-lpi2c: add bus recovery feature Clark Wang
@ 2021-04-06 11:32 ` Clark Wang
  2021-04-06 13:24   ` Rob Herring
  2021-05-21  7:02   ` Aisheng Dong
  2021-04-06 11:33 ` [PATCH V2 12/18] i2c: imx-lpi2c: fix i2c timing issue Clark Wang
                   ` (6 subsequent siblings)
  17 siblings, 2 replies; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:32 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

Add i2c bus recovery configuration example.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
---
V2 changes:
 - New patch added in V2
---
 .../devicetree/bindings/i2c/i2c-imx-lpi2c.yaml     | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
index 29b9447f3b84..0a4b28827dcc 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
@@ -42,6 +42,15 @@ properties:
   power-domains:
     maxItems: 1
 
+  pinctrl-names:
+    minItems: 1
+
+  scl-gpios:
+    maxItems: 1
+
+  sda-gpios:
+    maxItems: 1
+
 required:
   - compatible
   - reg
@@ -61,4 +70,9 @@ examples:
         interrupt-parent = <&intc>;
         interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
         clocks = <&clks IMX7ULP_CLK_LPI2C7>;
+        pinctrl-names = "default","gpio";
+        pinctrl-0 = <&pinctrl_i2c>;
+        pinctrl-1 = <&pinctrl_i2c_recovery>;
+        scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+        sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
     };
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 12/18] i2c: imx-lpi2c: fix i2c timing issue
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (10 preceding siblings ...)
  2021-04-06 11:32 ` [PATCH V2 11/18] dt-bindings: i2c: imx-lpi2c: Add bus recovery example Clark Wang
@ 2021-04-06 11:33 ` Clark Wang
  2021-04-06 11:33 ` [PATCH V2 13/18] i2c: imx-lpi2c: fix type char overflow issue when calculating the clock cycle Clark Wang
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:33 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

The clkhi and clklo ratio was not very precise before that can make the
time of START/STOP/HIGH LEVEL out of specification.

Therefore, the calculation of these times has been modified in this patch.
At the same time, the mode rate definition of i2c is corrected.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
Reviewed-by: Fugang Duan <fugang.duan@nxp.com>
---
V2 changes:
 - No change.
---
 drivers/i2c/busses/i2c-imx-lpi2c.c | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 77dd6ee5a4a8..d124c4000823 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -73,17 +73,17 @@
 #define MCFGR1_IGNACK	BIT(9)
 #define MRDR_RXEMPTY	BIT(14)
 
-#define I2C_CLK_RATIO	2
+#define I2C_CLK_RATIO	24 / 59
 #define CHUNK_DATA	256
 
 #define I2C_PM_TIMEOUT		1000 /* ms */
 
 enum lpi2c_imx_mode {
-	STANDARD,	/* 100+Kbps */
-	FAST,		/* 400+Kbps */
-	FAST_PLUS,	/* 1.0+Mbps */
-	HS,		/* 3.4+Mbps */
-	ULTRA_FAST,	/* 5.0+Mbps */
+	STANDARD,	/* <=100Kbps */
+	FAST,		/* <=400Kbps */
+	FAST_PLUS,	/* <=1.0Mbps */
+	HS,		/* <=3.4Mbps */
+	ULTRA_FAST,	/* <=5.0Mbps */
 };
 
 enum lpi2c_imx_pincfg {
@@ -156,13 +156,13 @@ static void lpi2c_imx_set_mode(struct lpi2c_imx_struct *lpi2c_imx)
 	unsigned int bitrate = lpi2c_imx->bitrate;
 	enum lpi2c_imx_mode mode;
 
-	if (bitrate < I2C_MAX_FAST_MODE_FREQ)
+	if (bitrate <= I2C_MAX_STANDARD_MODE_FREQ)
 		mode = STANDARD;
-	else if (bitrate < I2C_MAX_FAST_MODE_PLUS_FREQ)
+	else if (bitrate <= I2C_MAX_FAST_MODE_FREQ)
 		mode = FAST;
-	else if (bitrate < I2C_MAX_HIGH_SPEED_MODE_FREQ)
+	else if (bitrate <= I2C_MAX_FAST_MODE_PLUS_FREQ)
 		mode = FAST_PLUS;
-	else if (bitrate < I2C_MAX_ULTRA_FAST_MODE_FREQ)
+	else if (bitrate <= I2C_MAX_HIGH_SPEED_MODE_FREQ)
 		mode = HS;
 	else
 		mode = ULTRA_FAST;
@@ -209,7 +209,8 @@ static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx)
 	} while (1);
 }
 
-/* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2 */
+/* CLKLO = (1 - I2C_CLK_RATIO) * clk_cycle, SETHOLD = CLKHI, DATAVD = CLKHI/2
+   CLKHI = I2C_CLK_RATIO * clk_cycle */
 static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
 {
 	u8 prescale, filt, sethold, clkhi, clklo, datavd;
@@ -232,8 +233,8 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
 
 	for (prescale = 0; prescale <= 7; prescale++) {
 		clk_cycle = clk_rate / ((1 << prescale) * lpi2c_imx->bitrate)
-			    - 3 - (filt >> 1);
-		clkhi = (clk_cycle + I2C_CLK_RATIO) / (I2C_CLK_RATIO + 1);
+			    - (2 + filt) / (1 << prescale);
+		clkhi = clk_cycle * I2C_CLK_RATIO;
 		clklo = clk_cycle - clkhi;
 		if (clklo < 64)
 			break;
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 13/18] i2c: imx-lpi2c: fix type char overflow issue when calculating the clock cycle
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (11 preceding siblings ...)
  2021-04-06 11:33 ` [PATCH V2 12/18] i2c: imx-lpi2c: fix i2c timing issue Clark Wang
@ 2021-04-06 11:33 ` Clark Wang
  2021-04-06 11:33 ` [PATCH V2 14/18] i2c: imx-lpi2c: add edma mode support Clark Wang
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:33 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

Claim clkhi and clklo as integer type to avoid possible calculation
errors caused by data overflow.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
Reviewed-by: Fugang Duan <fugang.duan@nxp.com>
Reviewed-by: Dong Aisheng <aisheng.dong@nxp.com>
---
V2 changes:
 - No change. Has been reviewed by Dong Aisheng <aisheng.dong@nxp.com> in V1.
---
 drivers/i2c/busses/i2c-imx-lpi2c.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index d124c4000823..c2f8e49660ea 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -213,8 +213,8 @@ static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx)
    CLKHI = I2C_CLK_RATIO * clk_cycle */
 static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
 {
-	u8 prescale, filt, sethold, clkhi, clklo, datavd;
-	unsigned int clk_rate, clk_cycle;
+	u8 prescale, filt, sethold, datavd;
+	unsigned int clk_rate, clk_cycle, clkhi, clklo;
 	enum lpi2c_imx_pincfg pincfg;
 	unsigned int temp;
 
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 14/18] i2c: imx-lpi2c: add edma mode support
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (12 preceding siblings ...)
  2021-04-06 11:33 ` [PATCH V2 13/18] i2c: imx-lpi2c: fix type char overflow issue when calculating the clock cycle Clark Wang
@ 2021-04-06 11:33 ` Clark Wang
  2021-04-06 11:41   ` Clark Wang
  2021-04-06 11:33 ` [PATCH V2 15/18] dt-bindings: i2c: imx-lpi2c: Add dma configuration example Clark Wang
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:33 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

Add eDMA receive and send mode support.
Support to read and write data larger than 256 bytes in one frame.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
Reviewed-by: Li Jun <jun.li@nxp.com>
---
V2 changes:
 - change marco I2C_USE_PIO to DMA_ERR_I2C_USE_PIO. It is a error code defined
   in this driver to 
---
 drivers/i2c/busses/i2c-imx-lpi2c.c | 290 ++++++++++++++++++++++++++++-
 1 file changed, 288 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index c2f8e49660ea..d1a56d52f19f 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -8,6 +8,8 @@
 #include <linux/clk.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
@@ -31,6 +33,7 @@
 #define LPI2C_MCR	0x10	/* i2c contrl register */
 #define LPI2C_MSR	0x14	/* i2c status register */
 #define LPI2C_MIER	0x18	/* i2c interrupt enable */
+#define LPI2C_MDER	0x1C	/* i2c DMA enable */
 #define LPI2C_MCFGR0	0x20	/* i2c master configuration */
 #define LPI2C_MCFGR1	0x24	/* i2c master configuration */
 #define LPI2C_MCFGR2	0x28	/* i2c master configuration */
@@ -72,11 +75,15 @@
 #define MCFGR1_AUTOSTOP	BIT(8)
 #define MCFGR1_IGNACK	BIT(9)
 #define MRDR_RXEMPTY	BIT(14)
+#define MDER_TDDE	BIT(0)
+#define MDER_RDDE	BIT(1)
 
 #define I2C_CLK_RATIO	24 / 59
 #define CHUNK_DATA	256
 
 #define I2C_PM_TIMEOUT		1000 /* ms */
+#define I2C_DMA_THRESHOLD	16 /* bytes */
+#define DMA_ERR_I2C_USE_PIO	(-150)
 
 enum lpi2c_imx_mode {
 	STANDARD,	/* <=100Kbps */
@@ -95,6 +102,7 @@ enum lpi2c_imx_pincfg {
 
 struct lpi2c_imx_struct {
 	struct i2c_adapter	adapter;
+	resource_size_t		phy_addr;
 	int			irq;
 	struct clk		*clk_per;
 	struct clk		*clk_ipg;
@@ -114,6 +122,17 @@ struct lpi2c_imx_struct {
 	struct pinctrl *pinctrl;
 	struct pinctrl_state *pinctrl_pins_default;
 	struct pinctrl_state *pinctrl_pins_gpio;
+
+	bool			can_use_dma;
+	bool			using_dma;
+	bool			xferred;
+	struct i2c_msg		*msg;
+	dma_addr_t		dma_addr;
+	struct dma_chan		*dma_tx;
+	struct dma_chan		*dma_rx;
+	enum dma_data_direction dma_direction;
+	u8			*dma_buf;
+	unsigned int		dma_len;
 };
 
 static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx,
@@ -289,6 +308,9 @@ static int lpi2c_imx_master_enable(struct lpi2c_imx_struct *lpi2c_imx)
 	if (ret)
 		goto rpm_put;
 
+	if (lpi2c_imx->can_use_dma)
+		writel(MDER_TDDE | MDER_RDDE, lpi2c_imx->base + LPI2C_MDER);
+
 	temp = readl(lpi2c_imx->base + LPI2C_MCR);
 	temp |= MCR_MEN;
 	writel(temp, lpi2c_imx->base + LPI2C_MCR);
@@ -462,6 +484,154 @@ static void lpi2c_imx_read(struct lpi2c_imx_struct *lpi2c_imx,
 	lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE | MIER_NDIE);
 }
 
+static void lpi2c_dma_unmap(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	struct dma_chan *chan = lpi2c_imx->dma_direction == DMA_FROM_DEVICE
+				? lpi2c_imx->dma_rx : lpi2c_imx->dma_tx;
+
+	dma_unmap_single(chan->device->dev, lpi2c_imx->dma_addr,
+			 lpi2c_imx->dma_len, lpi2c_imx->dma_direction);
+
+	lpi2c_imx->dma_direction = DMA_NONE;
+}
+
+static void lpi2c_cleanup_dma(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	if (lpi2c_imx->dma_direction == DMA_NONE)
+		return;
+	else if (lpi2c_imx->dma_direction == DMA_FROM_DEVICE)
+		dmaengine_terminate_all(lpi2c_imx->dma_rx);
+	else if (lpi2c_imx->dma_direction == DMA_TO_DEVICE)
+		dmaengine_terminate_all(lpi2c_imx->dma_tx);
+
+	lpi2c_dma_unmap(lpi2c_imx);
+}
+
+static void lpi2c_dma_callback(void *data)
+{
+	struct lpi2c_imx_struct *lpi2c_imx = (struct lpi2c_imx_struct *)data;
+
+	lpi2c_dma_unmap(lpi2c_imx);
+	writel(GEN_STOP << 8, lpi2c_imx->base + LPI2C_MTDR);
+	lpi2c_imx->xferred = true;
+
+	complete(&lpi2c_imx->complete);
+}
+
+static int lpi2c_dma_submit(struct lpi2c_imx_struct *lpi2c_imx,
+			   struct i2c_msg *msg)
+{
+	bool read = msg->flags & I2C_M_RD;
+	enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	struct dma_chan *chan = read ? lpi2c_imx->dma_rx : lpi2c_imx->dma_tx;
+	struct dma_async_tx_descriptor *txdesc;
+	dma_cookie_t cookie;
+
+	lpi2c_imx->dma_len = read ? msg->len - 1 : msg->len;
+	lpi2c_imx->msg = msg;
+	lpi2c_imx->dma_direction = dir;
+
+	if (IS_ERR(chan))
+		return PTR_ERR(chan);
+
+	lpi2c_imx->dma_addr = dma_map_single(chan->device->dev,
+					     lpi2c_imx->dma_buf,
+					     lpi2c_imx->dma_len, dir);
+	if (dma_mapping_error(chan->device->dev, lpi2c_imx->dma_addr)) {
+		dev_err(&lpi2c_imx->adapter.dev, "dma map failed, use pio\n");
+		return -EINVAL;
+	}
+
+	txdesc = dmaengine_prep_slave_single(chan, lpi2c_imx->dma_addr,
+					lpi2c_imx->dma_len, read ?
+					DMA_DEV_TO_MEM : DMA_MEM_TO_DEV,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!txdesc) {
+		dev_err(&lpi2c_imx->adapter.dev, "dma prep slave sg failed, use pio\n");
+		lpi2c_cleanup_dma(lpi2c_imx);
+		return -EINVAL;
+	}
+
+	reinit_completion(&lpi2c_imx->complete);
+	txdesc->callback = lpi2c_dma_callback;
+	txdesc->callback_param = (void *)lpi2c_imx;
+
+	cookie = dmaengine_submit(txdesc);
+	if (dma_submit_error(cookie)) {
+		dev_err(&lpi2c_imx->adapter.dev, "submitting dma failed, use pio\n");
+		lpi2c_cleanup_dma(lpi2c_imx);
+		return -EINVAL;
+	}
+
+	lpi2c_imx_intctrl(lpi2c_imx, MIER_NDIE);
+
+	dma_async_issue_pending(chan);
+
+	return 0;
+}
+
+static bool is_use_dma(struct lpi2c_imx_struct *lpi2c_imx, struct i2c_msg *msg)
+{
+	if (!lpi2c_imx->can_use_dma)
+		return false;
+
+	if (msg->len < I2C_DMA_THRESHOLD)
+		return false;
+
+	return true;
+}
+
+static int lpi2c_imx_dma_push_rx_cmd(struct lpi2c_imx_struct *lpi2c_imx,
+				 struct i2c_msg *msg)
+{
+	unsigned int temp, rx_remain;
+	unsigned long orig_jiffies = jiffies;
+
+	if ((msg->flags & I2C_M_RD)) {
+		rx_remain = msg->len;
+		do {
+			temp = rx_remain > CHUNK_DATA ?
+				CHUNK_DATA - 1 : rx_remain - 1;
+			temp |= (RECV_DATA << 8);
+			while ((readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff) > (lpi2c_imx->rxfifosize >> 1)) {
+				if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(1000))) {
+					dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n");
+					if (lpi2c_imx->adapter.bus_recovery_info)
+						i2c_recover_bus(&lpi2c_imx->adapter);
+					return -ETIMEDOUT;
+				}
+				schedule();
+			}
+			writel(temp, lpi2c_imx->base + LPI2C_MTDR);
+			rx_remain = rx_remain - (temp & 0xff) - 1;
+		} while (rx_remain > 0);
+	}
+
+	return 0;
+}
+
+static int lpi2c_dma_xfer(struct lpi2c_imx_struct *lpi2c_imx,
+			   struct i2c_msg *msg)
+{
+	int result;
+
+	result = lpi2c_dma_submit(lpi2c_imx, msg);
+	if (!result) {
+		result = lpi2c_imx_dma_push_rx_cmd(lpi2c_imx, msg);
+		if (result)
+			return result;
+		result = lpi2c_imx_msg_complete(lpi2c_imx);
+		return result;
+	}
+
+	/* DMA xfer failed, try to use PIO, clean up dma things */
+	i2c_put_dma_safe_msg_buf(lpi2c_imx->dma_buf, lpi2c_imx->msg,
+				 lpi2c_imx->xferred);
+	lpi2c_cleanup_dma(lpi2c_imx);
+
+	return DMA_ERR_I2C_USE_PIO;
+}
+
 static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
 			  struct i2c_msg *msgs, int num)
 {
@@ -474,6 +644,9 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
 		return result;
 
 	for (i = 0; i < num; i++) {
+		lpi2c_imx->xferred = false;
+		lpi2c_imx->using_dma = false;
+
 		result = lpi2c_imx_start(lpi2c_imx, &msgs[i]);
 		if (result)
 			goto disable;
@@ -482,9 +655,24 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
 		if (num == 1 && msgs[0].len == 0)
 			goto stop;
 
+		if (is_use_dma(lpi2c_imx, &msgs[i])) {
+			lpi2c_imx->using_dma = true;
+
+			writel(0x1, lpi2c_imx->base + LPI2C_MFCR);
+
+			lpi2c_imx->dma_buf = i2c_get_dma_safe_msg_buf(&msgs[i],
+							    I2C_DMA_THRESHOLD);
+			if (lpi2c_imx->dma_buf) {
+				result = lpi2c_dma_xfer(lpi2c_imx, &msgs[i]);
+				if (result != DMA_ERR_I2C_USE_PIO)
+					goto stop;
+			}
+		}
+
+		lpi2c_imx->using_dma = false;
 		lpi2c_imx->delivered = 0;
 		lpi2c_imx->msglen = msgs[i].len;
-		init_completion(&lpi2c_imx->complete);
+		reinit_completion(&lpi2c_imx->complete);
 
 		if (msgs[i].flags & I2C_M_RD)
 			lpi2c_imx_read(lpi2c_imx, &msgs[i]);
@@ -503,7 +691,16 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
 	}
 
 stop:
-	lpi2c_imx_stop(lpi2c_imx);
+	if (!lpi2c_imx->using_dma)
+		lpi2c_imx_stop(lpi2c_imx);
+	else {
+		i2c_put_dma_safe_msg_buf(lpi2c_imx->dma_buf, lpi2c_imx->msg,
+					 lpi2c_imx->xferred);
+		if (result) {
+			lpi2c_cleanup_dma(lpi2c_imx);
+			writel(GEN_STOP << 8, lpi2c_imx->base + LPI2C_MTDR);
+		}
+	}
 
 	temp = readl(lpi2c_imx->base + LPI2C_MSR);
 	if ((temp & MSR_NDF) && !result)
@@ -528,6 +725,10 @@ static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id)
 	temp = readl(lpi2c_imx->base + LPI2C_MSR);
 
 	if (temp & MSR_NDF) {
+		if (lpi2c_imx->using_dma) {
+			lpi2c_cleanup_dma(lpi2c_imx);
+			writel(GEN_STOP << 8, lpi2c_imx->base + LPI2C_MTDR);
+		}
 		complete(&lpi2c_imx->complete);
 		goto ret;
 	}
@@ -623,6 +824,77 @@ static const struct of_device_id lpi2c_imx_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, lpi2c_imx_of_match);
 
+static void lpi2c_dma_exit(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	if (lpi2c_imx->dma_rx) {
+		dma_release_channel(lpi2c_imx->dma_rx);
+		lpi2c_imx->dma_rx = NULL;
+	}
+
+	if (lpi2c_imx->dma_tx) {
+		dma_release_channel(lpi2c_imx->dma_tx);
+		lpi2c_imx->dma_tx = NULL;
+	}
+}
+
+static int lpi2c_dma_init(struct device *dev,
+			  struct lpi2c_imx_struct *lpi2c_imx)
+{
+	int ret;
+	struct dma_slave_config dma_sconfig;
+
+	/* Prepare for TX DMA: */
+	lpi2c_imx->dma_tx = dma_request_chan(dev, "tx");
+	if (IS_ERR(lpi2c_imx->dma_tx)) {
+		ret = PTR_ERR(lpi2c_imx->dma_tx);
+		dev_err(dev, "can't get the TX DMA channel, error %d!\n", ret);
+		lpi2c_imx->dma_tx = NULL;
+		goto err;
+	}
+
+	dma_sconfig.dst_addr = lpi2c_imx->phy_addr + LPI2C_MTDR;
+	dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	dma_sconfig.dst_maxburst = 1;
+	dma_sconfig.direction = DMA_MEM_TO_DEV;
+	ret = dmaengine_slave_config(lpi2c_imx->dma_tx, &dma_sconfig);
+	if (ret < 0) {
+		dev_err(dev, "can't configure tx channel (%d)\n", ret);
+		goto fail_tx;
+	}
+
+	/* Prepare for RX DMA: */
+	lpi2c_imx->dma_rx = dma_request_chan(dev, "rx");
+	if (IS_ERR(lpi2c_imx->dma_rx)) {
+		ret = PTR_ERR(lpi2c_imx->dma_rx);
+		dev_err(dev, "can't get the RX DMA channel, error %d\n", ret);
+		lpi2c_imx->dma_rx = NULL;
+		goto fail_tx;
+	}
+
+	dma_sconfig.src_addr = lpi2c_imx->phy_addr + LPI2C_MRDR;
+	dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	dma_sconfig.src_maxburst = 1;
+	dma_sconfig.direction = DMA_DEV_TO_MEM;
+	ret = dmaengine_slave_config(lpi2c_imx->dma_rx, &dma_sconfig);
+	if (ret < 0) {
+		dev_err(dev, "can't configure rx channel (%d)\n", ret);
+		goto fail_rx;
+	}
+
+	lpi2c_imx->can_use_dma = true;
+	lpi2c_imx->using_dma = false;
+
+	return 0;
+fail_rx:
+	dma_release_channel(lpi2c_imx->dma_rx);
+fail_tx:
+	dma_release_channel(lpi2c_imx->dma_tx);
+err:
+	lpi2c_dma_exit(lpi2c_imx);
+	lpi2c_imx->can_use_dma = false;
+	return ret;
+}
+
 static int lpi2c_imx_clocks_prepare(struct lpi2c_imx_struct *lpi2c_imx)
 {
 	int ret = 0;
@@ -656,15 +928,18 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
 	struct lpi2c_imx_struct *lpi2c_imx;
 	unsigned int temp;
 	int ret;
+	struct resource *res;
 
 	lpi2c_imx = devm_kzalloc(&pdev->dev, sizeof(*lpi2c_imx), GFP_KERNEL);
 	if (!lpi2c_imx)
 		return -ENOMEM;
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	lpi2c_imx->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(lpi2c_imx->base))
 		return PTR_ERR(lpi2c_imx->base);
 
+	lpi2c_imx->phy_addr = (dma_addr_t)res->start;
 	lpi2c_imx->irq = platform_get_irq(pdev, 0);
 	if (lpi2c_imx->irq < 0)
 		return lpi2c_imx->irq;
@@ -716,6 +991,17 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
 	if (ret == -EPROBE_DEFER)
 		goto rpm_disable;
 
+	/* Init DMA */
+	lpi2c_imx->dma_direction = DMA_NONE;
+	ret = lpi2c_dma_init(&pdev->dev, lpi2c_imx);
+	if (ret) {
+		dev_err_probe(&pdev->dev, ret, "dma setup error %d, use pio\n", ret);
+		if (ret == -EPROBE_DEFER)
+			goto rpm_disable;
+	}
+
+	init_completion(&lpi2c_imx->complete);
+
 	ret = i2c_add_adapter(&lpi2c_imx->adapter);
 	if (ret)
 		goto rpm_disable;
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 15/18] dt-bindings: i2c: imx-lpi2c: Add dma configuration example
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (13 preceding siblings ...)
  2021-04-06 11:33 ` [PATCH V2 14/18] i2c: imx-lpi2c: add edma mode support Clark Wang
@ 2021-04-06 11:33 ` Clark Wang
  2021-04-09 16:33   ` Rob Herring
  2021-04-06 11:33 ` [PATCH V2 16/18] ARM: dts: imx7ulp: add dma configurations for lpi2c Clark Wang
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:33 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

Add i2c bus dma mode configuration example.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
---
V2 changes:
 - New patch added in V2
---
 .../devicetree/bindings/i2c/i2c-imx-lpi2c.yaml       | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
index 0a4b28827dcc..3868fec0cf27 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
@@ -51,6 +51,16 @@ properties:
   sda-gpios:
     maxItems: 1
 
+  dmas:
+    minItems: 2
+    maxItems: 2
+
+  dma-names:
+    minItems: 2
+    maxItems: 2
+    items:
+      enum: [ "tx", "rx" ]
+
 required:
   - compatible
   - reg
@@ -75,4 +85,6 @@ examples:
         pinctrl-1 = <&pinctrl_i2c_recovery>;
         scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
         sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+        dmas = <&edma1 0 16>, <&edma1 0 15>;
+        dma-names = "tx","rx";
     };
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 16/18] ARM: dts: imx7ulp: add dma configurations for lpi2c
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (14 preceding siblings ...)
  2021-04-06 11:33 ` [PATCH V2 15/18] dt-bindings: i2c: imx-lpi2c: Add dma configuration example Clark Wang
@ 2021-04-06 11:33 ` Clark Wang
  2021-04-06 11:33 ` [PATCH V2 17/18] ARM: dts: imx7ulp: add the missing status property of lpi2c5 Clark Wang
  2021-04-06 11:33 ` [PATCH V2 18/18] i2c: imx-lpi2c: fix pio mode cannot send 256+ bytes in one frame Clark Wang
  17 siblings, 0 replies; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:33 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

Enable dma support for all lpi2c nodes.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
---
V2 changes:
 - New patch added in V2
---
 arch/arm/boot/dts/imx7ulp.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
index 0c51fa79c0bc..a6681836ca05 100644
--- a/arch/arm/boot/dts/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/imx7ulp.dtsi
@@ -157,6 +157,8 @@ lpi2c4: lpi2c4@402b0000 {
 			assigned-clocks = <&pcc2 IMX7ULP_CLK_LPI2C4>;
 			assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
 			assigned-clock-rates = <48000000>;
+			dmas = <&edma1 0 10>, <&edma1 0 9>;
+			dma-names = "tx","rx";
 			status = "disabled";
 		};
 
@@ -170,6 +172,8 @@ lpi2c5: lpi2c5@402c0000 {
 			assigned-clocks = <&pcc2 IMX7ULP_CLK_LPI2C5>;
 			assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
 			assigned-clock-rates = <48000000>;
+			dmas = <&edma1 0 12>, <&edma1 0 11>;
+			dma-names = "tx","rx";
 		};
 
 		lpuart4: serial@402d0000 {
@@ -361,6 +365,8 @@ lpi2c6: i2c@40a40000 {
 			assigned-clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>;
 			assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
 			assigned-clock-rates = <48000000>;
+			dmas = <&edma1 0 14>, <&edma1 0 13>;
+			dma-names = "tx","rx";
 			status = "disabled";
 		};
 
@@ -374,6 +380,8 @@ lpi2c7: i2c@40a50000 {
 			assigned-clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>;
 			assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
 			assigned-clock-rates = <48000000>;
+			dmas = <&edma1 0 16>, <&edma1 0 15>;
+			dma-names = "tx","rx";
 			status = "disabled";
 		};
 
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 17/18] ARM: dts: imx7ulp: add the missing status property of lpi2c5
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (15 preceding siblings ...)
  2021-04-06 11:33 ` [PATCH V2 16/18] ARM: dts: imx7ulp: add dma configurations for lpi2c Clark Wang
@ 2021-04-06 11:33 ` Clark Wang
  2021-04-06 11:33 ` [PATCH V2 18/18] i2c: imx-lpi2c: fix pio mode cannot send 256+ bytes in one frame Clark Wang
  17 siblings, 0 replies; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:33 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

Add the missing lpi2c5 status property.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
---
V2 changes:
 - New patch added in V2
---
 arch/arm/boot/dts/imx7ulp.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
index a6681836ca05..b16441e18231 100644
--- a/arch/arm/boot/dts/imx7ulp.dtsi
+++ b/arch/arm/boot/dts/imx7ulp.dtsi
@@ -174,6 +174,7 @@ lpi2c5: lpi2c5@402c0000 {
 			assigned-clock-rates = <48000000>;
 			dmas = <&edma1 0 12>, <&edma1 0 11>;
 			dma-names = "tx","rx";
+			status = "disabled";
 		};
 
 		lpuart4: serial@402d0000 {
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH V2 18/18] i2c: imx-lpi2c: fix pio mode cannot send 256+ bytes in one frame
  2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
                   ` (16 preceding siblings ...)
  2021-04-06 11:33 ` [PATCH V2 17/18] ARM: dts: imx7ulp: add the missing status property of lpi2c5 Clark Wang
@ 2021-04-06 11:33 ` Clark Wang
  17 siblings, 0 replies; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:33 UTC (permalink / raw)
  To: aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel, linux-kernel

The next MTDR command should be filled before the last receive command is
fininshed. Otherwise, a NACK will be sent when the current MTDR command
is finished. It causes lpi2c cannot send the next chunk data
successfully.

Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
---
V2 changes:
 - New patch added in V2
---
 drivers/i2c/busses/i2c-imx-lpi2c.c | 43 +++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 3c0f16a79185..8d908b9b5112 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -112,6 +112,7 @@ struct lpi2c_imx_struct {
 	struct completion	complete;
 	unsigned int		msglen;
 	unsigned int		delivered;
+	unsigned int		remain_chunk_num;
 	unsigned int		block_data;
 	unsigned int		bitrate;
 	unsigned int		txfifosize;
@@ -413,6 +414,28 @@ static void lpi2c_imx_write_txfifo(struct lpi2c_imx_struct *lpi2c_imx)
 		complete(&lpi2c_imx->complete);
 }
 
+static void lpi2c_imx_pio_push_rx_cmd(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	unsigned int remaining, temp;
+	u8 last_chunk_num = lpi2c_imx->msglen % CHUNK_DATA;
+
+	if (lpi2c_imx->remain_chunk_num > 0 &&
+		(lpi2c_imx->delivered % CHUNK_DATA) > (CHUNK_DATA >> 1)) {
+		if ((readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff) <=
+						(lpi2c_imx->rxfifosize >> 1)) {
+			if (last_chunk_num)
+				remaining = (lpi2c_imx->remain_chunk_num - 1) *
+					    CHUNK_DATA + last_chunk_num;
+			else
+				remaining = lpi2c_imx->remain_chunk_num * CHUNK_DATA;
+			temp = (remaining > CHUNK_DATA ? CHUNK_DATA : remaining) - 1;
+			temp |= (RECV_DATA << 8);
+			writel(temp, lpi2c_imx->base + LPI2C_MTDR);
+			lpi2c_imx->remain_chunk_num--;
+		}
+	}
+}
+
 static void lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx)
 {
 	unsigned int blocklen, remaining;
@@ -420,10 +443,16 @@ static void lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx)
 
 	do {
 		data = readl(lpi2c_imx->base + LPI2C_MRDR);
-		if (data & MRDR_RXEMPTY)
-			break;
+		if (data & MRDR_RXEMPTY) {
+			if (lpi2c_imx->delivered == lpi2c_imx->msglen ||
+			    lpi2c_imx->block_data)
+				break;
+			else
+				continue;
+		}
 
 		lpi2c_imx->rx_buf[lpi2c_imx->delivered++] = data & 0xff;
+		lpi2c_imx_pio_push_rx_cmd(lpi2c_imx);
 	} while (1);
 
 	/*
@@ -451,13 +480,9 @@ static void lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx)
 		temp = remaining;
 		temp |= (RECV_DATA << 8);
 		writel(temp, lpi2c_imx->base + LPI2C_MTDR);
-	} else if (!(lpi2c_imx->delivered & 0xff)) {
-		temp = (remaining > CHUNK_DATA ? CHUNK_DATA : remaining) - 1;
-		temp |= (RECV_DATA << 8);
-		writel(temp, lpi2c_imx->base + LPI2C_MTDR);
 	}
 
-	lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE);
+	lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE | MIER_NDIE);
 }
 
 static void lpi2c_imx_write(struct lpi2c_imx_struct *lpi2c_imx,
@@ -477,6 +502,10 @@ static void lpi2c_imx_read(struct lpi2c_imx_struct *lpi2c_imx,
 	lpi2c_imx->block_data = msgs->flags & I2C_M_RECV_LEN;
 
 	lpi2c_imx_set_rx_watermark(lpi2c_imx);
+	if (msgs->len > CHUNK_DATA) {
+		temp = CHUNK_DATA - 1;
+		lpi2c_imx->remain_chunk_num = DIV_ROUND_UP(msgs->len, CHUNK_DATA) - 1;
+	}
 	temp = msgs->len > CHUNK_DATA ? CHUNK_DATA - 1 : msgs->len - 1;
 	temp |= (RECV_DATA << 8);
 	writel(temp, lpi2c_imx->base + LPI2C_MTDR);
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH V2 14/18] i2c: imx-lpi2c: add edma mode support
  2021-04-06 11:33 ` [PATCH V2 14/18] i2c: imx-lpi2c: add edma mode support Clark Wang
@ 2021-04-06 11:41   ` Clark Wang
  0 siblings, 0 replies; 33+ messages in thread
From: Clark Wang @ 2021-04-06 11:41 UTC (permalink / raw)
  To: Aisheng Dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, dl-linux-imx, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel


[-- Attachment #1.1: Type: text/plain, Size: 13688 bytes --]


> -----Original Message-----
> From: Clark Wang <xiaoning.wang@nxp.com>
> Sent: Tuesday, April 6, 2021 19:33
> To: Aisheng Dong <aisheng.dong@nxp.com>; robh+dt@kernel.org;
> shawnguo@kernel.org; s.hauer@pengutronix.de; festevam@gmail.com
> Cc: kernel@pengutronix.de; dl-linux-imx <linux-imx@nxp.com>; linux-
> i2c@vger.kernel.org; devicetree@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org; linux-kernel@vger.kernel.org
> Subject: [PATCH V2 14/18] i2c: imx-lpi2c: add edma mode support
> 
> Add eDMA receive and send mode support.
> Support to read and write data larger than 256 bytes in one frame.
> 
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> Reviewed-by: Li Jun <jun.li@nxp.com>
> ---
> V2 changes:
>  - change marco I2C_USE_PIO to DMA_ERR_I2C_USE_PIO. It is a error code
> defined
>    in this driver to

It is an error code defined in this driver to identify the DMA sending
error, then driver will try to use PIO to send data.

Best Regards,
Clark Wang
> ---
>  drivers/i2c/busses/i2c-imx-lpi2c.c | 290 ++++++++++++++++++++++++++++-
>  1 file changed, 288 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c
b/drivers/i2c/busses/i2c-imx-
> lpi2c.c
> index c2f8e49660ea..d1a56d52f19f 100644
> --- a/drivers/i2c/busses/i2c-imx-lpi2c.c
> +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
> @@ -8,6 +8,8 @@
>  #include <linux/clk.h>
>  #include <linux/completion.h>
>  #include <linux/delay.h>
> +#include <linux/dmaengine.h>
> +#include <linux/dma-mapping.h>
>  #include <linux/err.h>
>  #include <linux/errno.h>
>  #include <linux/i2c.h>
> @@ -31,6 +33,7 @@
>  #define LPI2C_MCR	0x10	/* i2c contrl register */
>  #define LPI2C_MSR	0x14	/* i2c status register */
>  #define LPI2C_MIER	0x18	/* i2c interrupt enable */
> +#define LPI2C_MDER	0x1C	/* i2c DMA enable */
>  #define LPI2C_MCFGR0	0x20	/* i2c master configuration */
>  #define LPI2C_MCFGR1	0x24	/* i2c master configuration */
>  #define LPI2C_MCFGR2	0x28	/* i2c master configuration */
> @@ -72,11 +75,15 @@
>  #define MCFGR1_AUTOSTOP	BIT(8)
>  #define MCFGR1_IGNACK	BIT(9)
>  #define MRDR_RXEMPTY	BIT(14)
> +#define MDER_TDDE	BIT(0)
> +#define MDER_RDDE	BIT(1)
> 
>  #define I2C_CLK_RATIO	24 / 59
>  #define CHUNK_DATA	256
> 
>  #define I2C_PM_TIMEOUT		1000 /* ms */
> +#define I2C_DMA_THRESHOLD	16 /* bytes */
> +#define DMA_ERR_I2C_USE_PIO	(-150)
> 
>  enum lpi2c_imx_mode {
>  	STANDARD,	/* <=100Kbps */
> @@ -95,6 +102,7 @@ enum lpi2c_imx_pincfg {
> 
>  struct lpi2c_imx_struct {
>  	struct i2c_adapter	adapter;
> +	resource_size_t		phy_addr;
>  	int			irq;
>  	struct clk		*clk_per;
>  	struct clk		*clk_ipg;
> @@ -114,6 +122,17 @@ struct lpi2c_imx_struct {
>  	struct pinctrl *pinctrl;
>  	struct pinctrl_state *pinctrl_pins_default;
>  	struct pinctrl_state *pinctrl_pins_gpio;
> +
> +	bool			can_use_dma;
> +	bool			using_dma;
> +	bool			xferred;
> +	struct i2c_msg		*msg;
> +	dma_addr_t		dma_addr;
> +	struct dma_chan		*dma_tx;
> +	struct dma_chan		*dma_rx;
> +	enum dma_data_direction dma_direction;
> +	u8			*dma_buf;
> +	unsigned int		dma_len;
>  };
> 
>  static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx, @@
-289,6
> +308,9 @@ static int lpi2c_imx_master_enable(struct lpi2c_imx_struct
> *lpi2c_imx)
>  	if (ret)
>  		goto rpm_put;
> 
> +	if (lpi2c_imx->can_use_dma)
> +		writel(MDER_TDDE | MDER_RDDE, lpi2c_imx->base +
> LPI2C_MDER);
> +
>  	temp = readl(lpi2c_imx->base + LPI2C_MCR);
>  	temp |= MCR_MEN;
>  	writel(temp, lpi2c_imx->base + LPI2C_MCR); @@ -462,6 +484,154 @@
> static void lpi2c_imx_read(struct lpi2c_imx_struct *lpi2c_imx,
>  	lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE | MIER_NDIE);  }
> 
> +static void lpi2c_dma_unmap(struct lpi2c_imx_struct *lpi2c_imx) {
> +	struct dma_chan *chan = lpi2c_imx->dma_direction ==
> DMA_FROM_DEVICE
> +				? lpi2c_imx->dma_rx : lpi2c_imx->dma_tx;
> +
> +	dma_unmap_single(chan->device->dev, lpi2c_imx->dma_addr,
> +			 lpi2c_imx->dma_len, lpi2c_imx->dma_direction);
> +
> +	lpi2c_imx->dma_direction = DMA_NONE;
> +}
> +
> +static void lpi2c_cleanup_dma(struct lpi2c_imx_struct *lpi2c_imx) {
> +	if (lpi2c_imx->dma_direction == DMA_NONE)
> +		return;
> +	else if (lpi2c_imx->dma_direction == DMA_FROM_DEVICE)
> +		dmaengine_terminate_all(lpi2c_imx->dma_rx);
> +	else if (lpi2c_imx->dma_direction == DMA_TO_DEVICE)
> +		dmaengine_terminate_all(lpi2c_imx->dma_tx);
> +
> +	lpi2c_dma_unmap(lpi2c_imx);
> +}
> +
> +static void lpi2c_dma_callback(void *data) {
> +	struct lpi2c_imx_struct *lpi2c_imx = (struct lpi2c_imx_struct
*)data;
> +
> +	lpi2c_dma_unmap(lpi2c_imx);
> +	writel(GEN_STOP << 8, lpi2c_imx->base + LPI2C_MTDR);
> +	lpi2c_imx->xferred = true;
> +
> +	complete(&lpi2c_imx->complete);
> +}
> +
> +static int lpi2c_dma_submit(struct lpi2c_imx_struct *lpi2c_imx,
> +			   struct i2c_msg *msg)
> +{
> +	bool read = msg->flags & I2C_M_RD;
> +	enum dma_data_direction dir = read ? DMA_FROM_DEVICE :
> DMA_TO_DEVICE;
> +	struct dma_chan *chan = read ? lpi2c_imx->dma_rx :
lpi2c_imx->dma_tx;
> +	struct dma_async_tx_descriptor *txdesc;
> +	dma_cookie_t cookie;
> +
> +	lpi2c_imx->dma_len = read ? msg->len - 1 : msg->len;
> +	lpi2c_imx->msg = msg;
> +	lpi2c_imx->dma_direction = dir;
> +
> +	if (IS_ERR(chan))
> +		return PTR_ERR(chan);
> +
> +	lpi2c_imx->dma_addr = dma_map_single(chan->device->dev,
> +					     lpi2c_imx->dma_buf,
> +					     lpi2c_imx->dma_len, dir);
> +	if (dma_mapping_error(chan->device->dev, lpi2c_imx->dma_addr)) {
> +		dev_err(&lpi2c_imx->adapter.dev, "dma map failed, use
pio\n");
> +		return -EINVAL;
> +	}
> +
> +	txdesc = dmaengine_prep_slave_single(chan, lpi2c_imx->dma_addr,
> +					lpi2c_imx->dma_len, read ?
> +					DMA_DEV_TO_MEM :
> DMA_MEM_TO_DEV,
> +					DMA_PREP_INTERRUPT |
> DMA_CTRL_ACK);
> +	if (!txdesc) {
> +		dev_err(&lpi2c_imx->adapter.dev, "dma prep slave sg failed,
> use pio\n");
> +		lpi2c_cleanup_dma(lpi2c_imx);
> +		return -EINVAL;
> +	}
> +
> +	reinit_completion(&lpi2c_imx->complete);
> +	txdesc->callback = lpi2c_dma_callback;
> +	txdesc->callback_param = (void *)lpi2c_imx;
> +
> +	cookie = dmaengine_submit(txdesc);
> +	if (dma_submit_error(cookie)) {
> +		dev_err(&lpi2c_imx->adapter.dev, "submitting dma failed, use
> pio\n");
> +		lpi2c_cleanup_dma(lpi2c_imx);
> +		return -EINVAL;
> +	}
> +
> +	lpi2c_imx_intctrl(lpi2c_imx, MIER_NDIE);
> +
> +	dma_async_issue_pending(chan);
> +
> +	return 0;
> +}
> +
> +static bool is_use_dma(struct lpi2c_imx_struct *lpi2c_imx, struct
> +i2c_msg *msg) {
> +	if (!lpi2c_imx->can_use_dma)
> +		return false;
> +
> +	if (msg->len < I2C_DMA_THRESHOLD)
> +		return false;
> +
> +	return true;
> +}
> +
> +static int lpi2c_imx_dma_push_rx_cmd(struct lpi2c_imx_struct *lpi2c_imx,
> +				 struct i2c_msg *msg)
> +{
> +	unsigned int temp, rx_remain;
> +	unsigned long orig_jiffies = jiffies;
> +
> +	if ((msg->flags & I2C_M_RD)) {
> +		rx_remain = msg->len;
> +		do {
> +			temp = rx_remain > CHUNK_DATA ?
> +				CHUNK_DATA - 1 : rx_remain - 1;
> +			temp |= (RECV_DATA << 8);
> +			while ((readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff)
>
> (lpi2c_imx->rxfifosize >> 1)) {
> +				if (time_after(jiffies, orig_jiffies +
> msecs_to_jiffies(1000))) {
> +					dev_dbg(&lpi2c_imx->adapter.dev,
> "txfifo empty timeout\n");
> +					if (lpi2c_imx-
> >adapter.bus_recovery_info)
> +						i2c_recover_bus(&lpi2c_imx-
> >adapter);
> +					return -ETIMEDOUT;
> +				}
> +				schedule();
> +			}
> +			writel(temp, lpi2c_imx->base + LPI2C_MTDR);
> +			rx_remain = rx_remain - (temp & 0xff) - 1;
> +		} while (rx_remain > 0);
> +	}
> +
> +	return 0;
> +}
> +
> +static int lpi2c_dma_xfer(struct lpi2c_imx_struct *lpi2c_imx,
> +			   struct i2c_msg *msg)
> +{
> +	int result;
> +
> +	result = lpi2c_dma_submit(lpi2c_imx, msg);
> +	if (!result) {
> +		result = lpi2c_imx_dma_push_rx_cmd(lpi2c_imx, msg);
> +		if (result)
> +			return result;
> +		result = lpi2c_imx_msg_complete(lpi2c_imx);
> +		return result;
> +	}
> +
> +	/* DMA xfer failed, try to use PIO, clean up dma things */
> +	i2c_put_dma_safe_msg_buf(lpi2c_imx->dma_buf, lpi2c_imx->msg,
> +				 lpi2c_imx->xferred);
> +	lpi2c_cleanup_dma(lpi2c_imx);
> +
> +	return DMA_ERR_I2C_USE_PIO;
> +}
> +
>  static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
>  			  struct i2c_msg *msgs, int num)
>  {
> @@ -474,6 +644,9 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
>  		return result;
> 
>  	for (i = 0; i < num; i++) {
> +		lpi2c_imx->xferred = false;
> +		lpi2c_imx->using_dma = false;
> +
>  		result = lpi2c_imx_start(lpi2c_imx, &msgs[i]);
>  		if (result)
>  			goto disable;
> @@ -482,9 +655,24 @@ static int lpi2c_imx_xfer(struct i2c_adapter
*adapter,
>  		if (num == 1 && msgs[0].len == 0)
>  			goto stop;
> 
> +		if (is_use_dma(lpi2c_imx, &msgs[i])) {
> +			lpi2c_imx->using_dma = true;
> +
> +			writel(0x1, lpi2c_imx->base + LPI2C_MFCR);
> +
> +			lpi2c_imx->dma_buf =
> i2c_get_dma_safe_msg_buf(&msgs[i],
> +
> I2C_DMA_THRESHOLD);
> +			if (lpi2c_imx->dma_buf) {
> +				result = lpi2c_dma_xfer(lpi2c_imx,
&msgs[i]);
> +				if (result != DMA_ERR_I2C_USE_PIO)
> +					goto stop;
> +			}
> +		}
> +
> +		lpi2c_imx->using_dma = false;
>  		lpi2c_imx->delivered = 0;
>  		lpi2c_imx->msglen = msgs[i].len;
> -		init_completion(&lpi2c_imx->complete);
> +		reinit_completion(&lpi2c_imx->complete);
> 
>  		if (msgs[i].flags & I2C_M_RD)
>  			lpi2c_imx_read(lpi2c_imx, &msgs[i]); @@ -503,7
> +691,16 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
>  	}
> 
>  stop:
> -	lpi2c_imx_stop(lpi2c_imx);
> +	if (!lpi2c_imx->using_dma)
> +		lpi2c_imx_stop(lpi2c_imx);
> +	else {
> +		i2c_put_dma_safe_msg_buf(lpi2c_imx->dma_buf, lpi2c_imx-
> >msg,
> +					 lpi2c_imx->xferred);
> +		if (result) {
> +			lpi2c_cleanup_dma(lpi2c_imx);
> +			writel(GEN_STOP << 8, lpi2c_imx->base + LPI2C_MTDR);
> +		}
> +	}
> 
>  	temp = readl(lpi2c_imx->base + LPI2C_MSR);
>  	if ((temp & MSR_NDF) && !result)
> @@ -528,6 +725,10 @@ static irqreturn_t lpi2c_imx_isr(int irq, void
*dev_id)
>  	temp = readl(lpi2c_imx->base + LPI2C_MSR);
> 
>  	if (temp & MSR_NDF) {
> +		if (lpi2c_imx->using_dma) {
> +			lpi2c_cleanup_dma(lpi2c_imx);
> +			writel(GEN_STOP << 8, lpi2c_imx->base + LPI2C_MTDR);
> +		}
>  		complete(&lpi2c_imx->complete);
>  		goto ret;
>  	}
> @@ -623,6 +824,77 @@ static const struct of_device_id lpi2c_imx_of_match[]
> = {  };  MODULE_DEVICE_TABLE(of, lpi2c_imx_of_match);
> 
> +static void lpi2c_dma_exit(struct lpi2c_imx_struct *lpi2c_imx) {
> +	if (lpi2c_imx->dma_rx) {
> +		dma_release_channel(lpi2c_imx->dma_rx);
> +		lpi2c_imx->dma_rx = NULL;
> +	}
> +
> +	if (lpi2c_imx->dma_tx) {
> +		dma_release_channel(lpi2c_imx->dma_tx);
> +		lpi2c_imx->dma_tx = NULL;
> +	}
> +}
> +
> +static int lpi2c_dma_init(struct device *dev,
> +			  struct lpi2c_imx_struct *lpi2c_imx) {
> +	int ret;
> +	struct dma_slave_config dma_sconfig;
> +
> +	/* Prepare for TX DMA: */
> +	lpi2c_imx->dma_tx = dma_request_chan(dev, "tx");
> +	if (IS_ERR(lpi2c_imx->dma_tx)) {
> +		ret = PTR_ERR(lpi2c_imx->dma_tx);
> +		dev_err(dev, "can't get the TX DMA channel, error %d!\n",
ret);
> +		lpi2c_imx->dma_tx = NULL;
> +		goto err;
> +	}
> +
> +	dma_sconfig.dst_addr = lpi2c_imx->phy_addr + LPI2C_MTDR;
> +	dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
> +	dma_sconfig.dst_maxburst = 1;
> +	dma_sconfig.direction = DMA_MEM_TO_DEV;
> +	ret = dmaengine_slave_config(lpi2c_imx->dma_tx, &dma_sconfig);
> +	if (ret < 0) {
> +		dev_err(dev, "can't configure tx channel (%d)\n", ret);
> +		goto fail_tx;
> +	}
> +
> +	/* Prepare for RX DMA: */
> +	lpi2c_imx->dma_rx = dma_request_chan(dev, "rx");
> +	if (IS_ERR(lpi2c_imx->dma_rx)) {
> +		ret = PTR_ERR(lpi2c_imx->dma_rx);
> +		dev_err(dev, "can't get the RX DMA channel, error %d\n",
ret);
> +		lpi2c_imx->dma_rx = NULL;
> +		goto fail_tx;
> +	}
> +
> +	dma_sconfig.src_addr = lpi2c_imx->phy_addr + LPI2C_MRDR;
> +	dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
> +	dma_sconfig.src_maxburst = 1;
> +	dma_sconfig.direction = DMA_DEV_TO_MEM;
> +	ret = dmaengine_slave_config(lpi2c_imx->dma_rx, &dma_sconfig);
> +	if (ret < 0) {
> +		dev_err(dev, "can't configure rx channel (%d)\n", ret);
> +		goto fail_rx;
> +	}
> +
> +	lpi2c_imx->can_use_dma = true;
> +	lpi2c_imx->using_dma = false;
> +
> +	return 0;
> +fail_rx:
> +	dma_release_channel(lpi2c_imx->dma_rx);
> +fail_tx:
> +	dma_release_channel(lpi2c_imx->dma_tx);
> +err:
> +	lpi2c_dma_exit(lpi2c_imx);
> +	lpi2c_imx->can_use_dma = false;
> +	return ret;
> +}
> +
>  static int lpi2c_imx_clocks_prepare(struct lpi2c_imx_struct *lpi2c_imx)
{
>  	int ret = 0;
> @@ -656,15 +928,18 @@ static int lpi2c_imx_probe(struct platform_device
> *pdev)
>  	struct lpi2c_imx_struct *lpi2c_imx;
>  	unsigned int temp;
>  	int ret;
> +	struct resource *res;
> 
>  	lpi2c_imx = devm_kzalloc(&pdev->dev, sizeof(*lpi2c_imx),
GFP_KERNEL);
>  	if (!lpi2c_imx)
>  		return -ENOMEM;
> 
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	lpi2c_imx->base = devm_platform_ioremap_resource(pdev, 0);
>  	if (IS_ERR(lpi2c_imx->base))
>  		return PTR_ERR(lpi2c_imx->base);
> 
> +	lpi2c_imx->phy_addr = (dma_addr_t)res->start;
>  	lpi2c_imx->irq = platform_get_irq(pdev, 0);
>  	if (lpi2c_imx->irq < 0)
>  		return lpi2c_imx->irq;
> @@ -716,6 +991,17 @@ static int lpi2c_imx_probe(struct platform_device
> *pdev)
>  	if (ret == -EPROBE_DEFER)
>  		goto rpm_disable;
> 
> +	/* Init DMA */
> +	lpi2c_imx->dma_direction = DMA_NONE;
> +	ret = lpi2c_dma_init(&pdev->dev, lpi2c_imx);
> +	if (ret) {
> +		dev_err_probe(&pdev->dev, ret, "dma setup error %d, use
> pio\n", ret);
> +		if (ret == -EPROBE_DEFER)
> +			goto rpm_disable;
> +	}
> +
> +	init_completion(&lpi2c_imx->complete);
> +
>  	ret = i2c_add_adapter(&lpi2c_imx->adapter);
>  	if (ret)
>  		goto rpm_disable;
> --
> 2.25.1


[-- Attachment #1.2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 9583 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH V2 11/18] dt-bindings: i2c: imx-lpi2c: Add bus recovery example
  2021-04-06 11:32 ` [PATCH V2 11/18] dt-bindings: i2c: imx-lpi2c: Add bus recovery example Clark Wang
@ 2021-04-06 13:24   ` Rob Herring
  2021-05-21  7:02   ` Aisheng Dong
  1 sibling, 0 replies; 33+ messages in thread
From: Rob Herring @ 2021-04-06 13:24 UTC (permalink / raw)
  To: Clark Wang
  Cc: linux-arm-kernel, linux-kernel, kernel, robh+dt, s.hauer,
	linux-imx, linux-i2c, festevam, aisheng.dong, shawnguo,
	devicetree

On Tue, 06 Apr 2021 19:32:59 +0800, Clark Wang wrote:
> Add i2c bus recovery configuration example.
> 
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> ---
> V2 changes:
>  - New patch added in V2
> ---
>  .../devicetree/bindings/i2c/i2c-imx-lpi2c.yaml     | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Error: Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.example.dts:31.37-38 syntax error
FATAL ERROR: Unable to parse input tree
make[1]: *** [scripts/Makefile.lib:377: Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.example.dt.yaml] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1414: dt_binding_check] Error 2

See https://patchwork.ozlabs.org/patch/1462762

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH V2 10/18] i2c: imx-lpi2c: add bus recovery feature
  2021-04-06 11:32 ` [PATCH V2 10/18] i2c: imx-lpi2c: add bus recovery feature Clark Wang
@ 2021-04-07  0:34   ` kernel test robot
  2021-05-21  6:44   ` Aisheng Dong
  1 sibling, 0 replies; 33+ messages in thread
From: kernel test robot @ 2021-04-07  0:34 UTC (permalink / raw)
  To: Clark Wang, aisheng.dong, robh+dt, shawnguo, s.hauer, festevam
  Cc: kbuild-all, kernel, linux-imx, linux-i2c, devicetree, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 4978 bytes --]

Hi Clark,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on shawnguo/for-next]
[also build test ERROR on next-20210406]
[cannot apply to wsa/i2c/for-next robh/for-next v5.12-rc6]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Clark-Wang/i2c-imx-lpi2c-New-features-and-bug-fixes/20210406-193539
base:   https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git for-next
config: nios2-randconfig-r003-20210406 (attached as .config)
compiler: nios2-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/5853de64dd40e1cc71f0adede924934aee4c4f0e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Clark-Wang/i2c-imx-lpi2c-New-features-and-bug-fixes/20210406-193539
        git checkout 5853de64dd40e1cc71f0adede924934aee4c4f0e
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=nios2 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/i2c/busses/i2c-imx-lpi2c.c: In function 'lpi2c_imx_init_recovery_info':
>> drivers/i2c/busses/i2c-imx-lpi2c.c:583:21: error: implicit declaration of function 'devm_gpiod_get'; did you mean 'devm_gpio_free'? [-Werror=implicit-function-declaration]
     583 |  rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
         |                     ^~~~~~~~~~~~~~
         |                     devm_gpio_free
>> drivers/i2c/busses/i2c-imx-lpi2c.c:583:55: error: 'GPIOD_IN' undeclared (first use in this function); did you mean 'GPIOF_IN'?
     583 |  rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
         |                                                       ^~~~~~~~
         |                                                       GPIOF_IN
   drivers/i2c/busses/i2c-imx-lpi2c.c:583:55: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/i2c/busses/i2c-imx-lpi2c.c:584:55: error: 'GPIOD_OUT_HIGH_OPEN_DRAIN' undeclared (first use in this function)
     584 |  rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
         |                                                       ^~~~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors


vim +583 drivers/i2c/busses/i2c-imx-lpi2c.c

   560	
   561	/*
   562	 * We switch SCL and SDA to their GPIO function and do some bitbanging
   563	 * for bus recovery. These alternative pinmux settings can be
   564	 * described in the device tree by a separate pinctrl state "gpio". If
   565	 * this is missing this is not a big problem, the only implication is
   566	 * that we can't do bus recovery.
   567	 */
   568	static int lpi2c_imx_init_recovery_info(struct lpi2c_imx_struct *lpi2c_imx,
   569			struct platform_device *pdev)
   570	{
   571		struct i2c_bus_recovery_info *rinfo = &lpi2c_imx->rinfo;
   572	
   573		lpi2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev);
   574		if (!lpi2c_imx->pinctrl || IS_ERR(lpi2c_imx->pinctrl)) {
   575			dev_info(&pdev->dev, "can't get pinctrl, bus recovery not supported\n");
   576			return PTR_ERR(lpi2c_imx->pinctrl);
   577		}
   578	
   579		lpi2c_imx->pinctrl_pins_default = pinctrl_lookup_state(lpi2c_imx->pinctrl,
   580				PINCTRL_STATE_DEFAULT);
   581		lpi2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(lpi2c_imx->pinctrl,
   582				"gpio");
 > 583		rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
 > 584		rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
   585	
   586		if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER ||
   587		    PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER) {
   588			return -EPROBE_DEFER;
   589		} else if (IS_ERR(rinfo->sda_gpiod) ||
   590			   IS_ERR(rinfo->scl_gpiod) ||
   591			   IS_ERR(lpi2c_imx->pinctrl_pins_default) ||
   592			   IS_ERR(lpi2c_imx->pinctrl_pins_gpio)) {
   593			dev_dbg(&pdev->dev, "recovery information incomplete\n");
   594			return 0;
   595		}
   596	
   597		dev_info(&pdev->dev, "using scl%s for recovery\n",
   598			 rinfo->sda_gpiod ? ",sda" : "");
   599	
   600		rinfo->prepare_recovery = lpi2c_imx_prepare_recovery;
   601		rinfo->unprepare_recovery = lpi2c_imx_unprepare_recovery;
   602		rinfo->recover_bus = i2c_generic_scl_recovery;
   603		lpi2c_imx->adapter.bus_recovery_info = rinfo;
   604	
   605		return 0;
   606	}
   607	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 29278 bytes --]

[-- Attachment #3: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH V2 15/18] dt-bindings: i2c: imx-lpi2c: Add dma configuration example
  2021-04-06 11:33 ` [PATCH V2 15/18] dt-bindings: i2c: imx-lpi2c: Add dma configuration example Clark Wang
@ 2021-04-09 16:33   ` Rob Herring
  0 siblings, 0 replies; 33+ messages in thread
From: Rob Herring @ 2021-04-09 16:33 UTC (permalink / raw)
  To: Clark Wang
  Cc: aisheng.dong, shawnguo, s.hauer, festevam, kernel, linux-imx,
	linux-i2c, devicetree, linux-arm-kernel, linux-kernel

On Tue, Apr 06, 2021 at 07:33:03PM +0800, Clark Wang wrote:
> Add i2c bus dma mode configuration example.
> 
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> ---
> V2 changes:
>  - New patch added in V2
> ---
>  .../devicetree/bindings/i2c/i2c-imx-lpi2c.yaml       | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
> index 0a4b28827dcc..3868fec0cf27 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
> +++ b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
> @@ -51,6 +51,16 @@ properties:
>    sda-gpios:
>      maxItems: 1
>  
> +  dmas:
> +    minItems: 2
> +    maxItems: 2
> +
> +  dma-names:
> +    minItems: 2
> +    maxItems: 2
> +    items:
> +      enum: [ "tx", "rx" ]

Please define the order:

items:
  - const: tx
  - const: rx

> +
>  required:
>    - compatible
>    - reg
> @@ -75,4 +85,6 @@ examples:
>          pinctrl-1 = <&pinctrl_i2c_recovery>;
>          scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
>          sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
> +        dmas = <&edma1 0 16>, <&edma1 0 15>;
> +        dma-names = "tx","rx";
>      };
> -- 
> 2.25.1
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH V2 05/18] ARM64: dts: imx8: add the missing lpi2c ipg clock
  2021-04-06 11:32 ` [PATCH V2 05/18] ARM64: dts: imx8: add the missing lpi2c ipg clock Clark Wang
@ 2021-05-11  2:59   ` Shawn Guo
  2021-05-21  6:28   ` Aisheng Dong
  1 sibling, 0 replies; 33+ messages in thread
From: Shawn Guo @ 2021-05-11  2:59 UTC (permalink / raw)
  To: Clark Wang
  Cc: aisheng.dong, robh+dt, s.hauer, festevam, kernel, linux-imx,
	linux-i2c, devicetree, linux-arm-kernel, linux-kernel

On Tue, Apr 06, 2021 at 07:32:53PM +0800, Clark Wang wrote:
> The lpi2c driver has add the missing ipg clock.
> So add the ipg clock here for all lpi2c nodes.
> 
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>

Historically, we use 'arm64: dts: ...' as subject prefix for arm64 DTS
patch, and 'ARM: dts: ...' for arm.

Shawn

> ---
> V2 changes:
>  - New patch added in V2
> ---
>  .../arm64/boot/dts/freescale/imx8-ss-dma.dtsi | 24 ++++++++++++-------
>  1 file changed, 16 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
> index 960a802b8b6e..b5ed12a06538 100644
> --- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
> @@ -111,8 +111,10 @@ uart3_lpcg: clock-controller@5a490000 {
>  	i2c0: i2c@5a800000 {
>  		reg = <0x5a800000 0x4000>;
>  		interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
> -		clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>;
> -		clock-names = "per";
> +		interrupt-parent = <&gic>;
> +		clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>,
> +			 <&i2c0_lpcg IMX_LPCG_CLK_4>;
> +		clock-names = "per", "ipg";
>  		assigned-clocks = <&clk IMX_SC_R_I2C_0 IMX_SC_PM_CLK_PER>;
>  		assigned-clock-rates = <24000000>;
>  		power-domains = <&pd IMX_SC_R_I2C_0>;
> @@ -122,8 +124,10 @@ i2c0: i2c@5a800000 {
>  	i2c1: i2c@5a810000 {
>  		reg = <0x5a810000 0x4000>;
>  		interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
> -		clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>;
> -		clock-names = "per";
> +		interrupt-parent = <&gic>;
> +		clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>,
> +			 <&i2c1_lpcg IMX_LPCG_CLK_4>;
> +		clock-names = "per", "ipg";
>  		assigned-clocks = <&clk IMX_SC_R_I2C_1 IMX_SC_PM_CLK_PER>;
>  		assigned-clock-rates = <24000000>;
>  		power-domains = <&pd IMX_SC_R_I2C_1>;
> @@ -133,8 +137,10 @@ i2c1: i2c@5a810000 {
>  	i2c2: i2c@5a820000 {
>  		reg = <0x5a820000 0x4000>;
>  		interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>;
> -		clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>;
> -		clock-names = "per";
> +		interrupt-parent = <&gic>;
> +		clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>,
> +			 <&i2c2_lpcg IMX_LPCG_CLK_4>;
> +		clock-names = "per", "ipg";
>  		assigned-clocks = <&clk IMX_SC_R_I2C_2 IMX_SC_PM_CLK_PER>;
>  		assigned-clock-rates = <24000000>;
>  		power-domains = <&pd IMX_SC_R_I2C_2>;
> @@ -144,8 +150,10 @@ i2c2: i2c@5a820000 {
>  	i2c3: i2c@5a830000 {
>  		reg = <0x5a830000 0x4000>;
>  		interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
> -		clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>;
> -		clock-names = "per";
> +		interrupt-parent = <&gic>;
> +		clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>,
> +			 <&i2c3_lpcg IMX_LPCG_CLK_4>;
> +		clock-names = "per", "ipg";
>  		assigned-clocks = <&clk IMX_SC_R_I2C_3 IMX_SC_PM_CLK_PER>;
>  		assigned-clock-rates = <24000000>;
>  		power-domains = <&pd IMX_SC_R_I2C_3>;
> -- 
> 2.25.1
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH V2 02/18] i2c: imx-lpi2c: add ipg clk for lpi2c driver
  2021-04-06 11:32 ` [PATCH V2 02/18] i2c: imx-lpi2c: add ipg clk for lpi2c driver Clark Wang
@ 2021-05-21  6:14   ` Aisheng Dong
  0 siblings, 0 replies; 33+ messages in thread
From: Aisheng Dong @ 2021-05-21  6:14 UTC (permalink / raw)
  To: Clark Wang, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, dl-linux-imx, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel

> From: Clark Wang <xiaoning.wang@nxp.com>
> Sent: Tuesday, April 6, 2021 7:33 PM
> 
> The lpi2c IP needs two clks: ipg clk and per clk. The old lpi2c driver missed ipg
> clk. This patch adds ipg clk for lpi2c driver.
> 
> Signed-off-by: Gao Pan <pandy.gao@nxp.com>
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> Acked-by: Fugang Duan <fugang.duan@nxp.com>

You can drop the original Ack or signed-off if there're significant changes

BTW, please move the binding doc change before this patch.

> ---
> V2 changes:
>  - Merge two clocks' prepare funtions to lpi2c_imx_clocks_prepare().
> ---
>  drivers/i2c/busses/i2c-imx-lpi2c.c | 61 +++++++++++++++++++++---------
>  1 file changed, 44 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c
> b/drivers/i2c/busses/i2c-imx-lpi2c.c
> index bbf44ac95021..89b7b0795f51 100644
> --- a/drivers/i2c/busses/i2c-imx-lpi2c.c
> +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
> @@ -94,7 +94,8 @@ enum lpi2c_imx_pincfg {
> 
>  struct lpi2c_imx_struct {
>  	struct i2c_adapter	adapter;
> -	struct clk		*clk;
> +	struct clk		*clk_per;
> +	struct clk		*clk_ipg;
>  	void __iomem		*base;
>  	__u8			*rx_buf;
>  	__u8			*tx_buf;
> @@ -207,7 +208,7 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct
> *lpi2c_imx)
> 
>  	lpi2c_imx_set_mode(lpi2c_imx);
> 
> -	clk_rate = clk_get_rate(lpi2c_imx->clk);
> +	clk_rate = clk_get_rate(lpi2c_imx->clk_per);
>  	if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST)
>  		filt = 0;
>  	else
> @@ -538,6 +539,34 @@ static const struct of_device_id lpi2c_imx_of_match[]
> = {  };  MODULE_DEVICE_TABLE(of, lpi2c_imx_of_match);
> 
> +static int lpi2c_imx_clocks_prepare(struct lpi2c_imx_struct *lpi2c_imx)
> +{
> +	int ret = 0;

Unnecessary initialization

> +
> +	ret = clk_prepare_enable(lpi2c_imx->clk_per);
> +	if (ret) {
> +		dev_err(lpi2c_imx->adapter.dev.parent,
> +				"can't enable I2C per clock, ret=%d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = clk_prepare_enable(lpi2c_imx->clk_ipg);
> +	if (ret) {
> +		clk_disable_unprepare(lpi2c_imx->clk_per);
> +		dev_err(lpi2c_imx->adapter.dev.parent,
> +				"can't enable I2C ipg clock, ret=%d\n", ret);
> +		return ret;
> +	}
> +
> +	return ret;

Return 0

> +}
> +
> +static void lpi2c_imx_clocks_unprepare(struct lpi2c_imx_struct
> +*lpi2c_imx) {
> +	clk_disable_unprepare(lpi2c_imx->clk_ipg);
> +	clk_disable_unprepare(lpi2c_imx->clk_per);
> +}
> +
>  static int lpi2c_imx_probe(struct platform_device *pdev)  {
>  	struct lpi2c_imx_struct *lpi2c_imx;
> @@ -563,10 +592,16 @@ static int lpi2c_imx_probe(struct platform_device
> *pdev)
>  	strlcpy(lpi2c_imx->adapter.name, pdev->name,
>  		sizeof(lpi2c_imx->adapter.name));
> 
> -	lpi2c_imx->clk = devm_clk_get(&pdev->dev, NULL);
> -	if (IS_ERR(lpi2c_imx->clk)) {
> +	lpi2c_imx->clk_per = devm_clk_get(&pdev->dev, "per");
> +	if (IS_ERR(lpi2c_imx->clk_per)) {
>  		dev_err(&pdev->dev, "can't get I2C peripheral clock\n");
> -		return PTR_ERR(lpi2c_imx->clk);
> +		return PTR_ERR(lpi2c_imx->clk_per);
> +	}

Will this patch break imx7ulp which doesn't have per clock?

> +
> +	lpi2c_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
> +	if (IS_ERR(lpi2c_imx->clk_ipg)) {
> +		dev_err(&pdev->dev, "can't get I2C ipg clock\n");
> +		return PTR_ERR(lpi2c_imx->clk_ipg);
>  	}
> 
>  	ret = of_property_read_u32(pdev->dev.of_node,
> @@ -584,11 +619,9 @@ static int lpi2c_imx_probe(struct platform_device
> *pdev)
>  	i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx);
>  	platform_set_drvdata(pdev, lpi2c_imx);
> 
> -	ret = clk_prepare_enable(lpi2c_imx->clk);
> -	if (ret) {
> -		dev_err(&pdev->dev, "clk enable failed %d\n", ret);
> +	ret = lpi2c_imx_clocks_prepare(lpi2c_imx);
> +	if (ret)
>  		return ret;
> -	}
> 
>  	pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
>  	pm_runtime_use_autosuspend(&pdev->dev);
> @@ -635,7 +668,7 @@ static int __maybe_unused
> lpi2c_runtime_suspend(struct device *dev)  {
>  	struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
> 
> -	clk_disable_unprepare(lpi2c_imx->clk);
> +	lpi2c_imx_clocks_unprepare(lpi2c_imx);
>  	pinctrl_pm_select_sleep_state(dev);
> 
>  	return 0;
> @@ -644,16 +677,10 @@ static int __maybe_unused
> lpi2c_runtime_suspend(struct device *dev)  static int __maybe_unused
> lpi2c_runtime_resume(struct device *dev)  {
>  	struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
> -	int ret;
> 
>  	pinctrl_pm_select_default_state(dev);
> -	ret = clk_prepare_enable(lpi2c_imx->clk);
> -	if (ret) {
> -		dev_err(dev, "failed to enable I2C clock, ret=%d\n", ret);
> -		return ret;
> -	}
> 
> -	return 0;
> +	return lpi2c_imx_clocks_prepare(lpi2c_imx);
>  }
> 
>  static const struct dev_pm_ops lpi2c_pm_ops = {
> --
> 2.25.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH V2 03/18] ARM: dts: imx7ulp: add the missing lpi2c ipg clock
  2021-04-06 11:32 ` [PATCH V2 03/18] ARM: dts: imx7ulp: add the missing lpi2c ipg clock Clark Wang
@ 2021-05-21  6:17   ` Aisheng Dong
  0 siblings, 0 replies; 33+ messages in thread
From: Aisheng Dong @ 2021-05-21  6:17 UTC (permalink / raw)
  To: Clark Wang, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, dl-linux-imx, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel

> From: Clark Wang <xiaoning.wang@nxp.com>
> Sent: Tuesday, April 6, 2021 7:33 PM
> 
> The lpi2c driver has add the missing ipg clock.

Pls drop this line as binding is not decided by driver 

> So add the ipg clock here for all lpi2c nodes.

Per clock?

Maybe better refined as add the missing per clock ....

> 
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> ---
> V2 changes:
>  - New patch added in V2
> ---
>  arch/arm/boot/dts/imx7ulp.dtsi | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
> index b7ea37ad4e55..eb0d4b8f624d 100644
> --- a/arch/arm/boot/dts/imx7ulp.dtsi
> +++ b/arch/arm/boot/dts/imx7ulp.dtsi
> @@ -328,8 +328,9 @@ lpi2c6: i2c@40a40000 {
>  			compatible = "fsl,imx7ulp-lpi2c";
>  			reg = <0x40a40000 0x10000>;
>  			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
> -			clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>;
> -			clock-names = "ipg";
> +			clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>,
> +				 <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>;
> +			clock-names = "per", "ipg";
>  			assigned-clocks = <&pcc3 IMX7ULP_CLK_LPI2C6>;
>  			assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
>  			assigned-clock-rates = <48000000>;
> @@ -340,8 +341,9 @@ lpi2c7: i2c@40a50000 {
>  			compatible = "fsl,imx7ulp-lpi2c";
>  			reg = <0x40a50000 0x10000>;
>  			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
> -			clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>;
> -			clock-names = "ipg";
> +			clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>,
> +				 <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>;
> +			clock-names = "per", "ipg";
>  			assigned-clocks = <&pcc3 IMX7ULP_CLK_LPI2C7>;
>  			assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
>  			assigned-clock-rates = <48000000>;
> --
> 2.25.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH V2 04/18] ARM: dts: imx7ulp: add the missing lpi2c nodes
  2021-04-06 11:32 ` [PATCH V2 04/18] ARM: dts: imx7ulp: add the missing lpi2c nodes Clark Wang
@ 2021-05-21  6:25   ` Aisheng Dong
  0 siblings, 0 replies; 33+ messages in thread
From: Aisheng Dong @ 2021-05-21  6:25 UTC (permalink / raw)
  To: Clark Wang, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, dl-linux-imx, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel

> From: Clark Wang <xiaoning.wang@nxp.com>
> Sent: Tuesday, April 6, 2021 7:33 PM
> 
> Add the missing lpi2c4/5 nodes for imx7ulp.
> 
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> ---
> V2 changes:
>  - New patch added in V2
> ---
>  arch/arm/boot/dts/imx7ulp.dtsi | 31 +++++++++++++++++++++++++++++--
>  1 file changed, 29 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/imx7ulp.dtsi b/arch/arm/boot/dts/imx7ulp.dtsi
> index eb0d4b8f624d..0c51fa79c0bc 100644
> --- a/arch/arm/boot/dts/imx7ulp.dtsi
> +++ b/arch/arm/boot/dts/imx7ulp.dtsi
> @@ -22,8 +22,10 @@ aliases {
>  		gpio1 = &gpio_ptd;
>  		gpio2 = &gpio_pte;
>  		gpio3 = &gpio_ptf;
> -		i2c0 = &lpi2c6;
> -		i2c1 = &lpi2c7;
> +		i2c0 = &lpi2c4;
> +		i2c1 = &lpi2c5;
> +		i2c2 = &lpi2c6;
> +		i2c3 = &lpi2c7;
>  		mmc0 = &usdhc0;
>  		mmc1 = &usdhc1;
>  		serial0 = &lpuart4;
> @@ -145,6 +147,31 @@ sec_jr1: jr@2000 {
>  			};
>  		};
> 
> +		lpi2c4: lpi2c4@402b0000 {

Generic node name is preferred. E.g. I2c@xxxxx

> +			compatible = "fsl,imx7ulp-lpi2c";
> +			reg = <0x402b0000 0x10000>;
> +			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&pcc2 IMX7ULP_CLK_LPI2C4>,
> +				 <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>;
> +			clock-names = "per", "ipg";
> +			assigned-clocks = <&pcc2 IMX7ULP_CLK_LPI2C4>;
> +			assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
> +			assigned-clock-rates = <48000000>;
> +			status = "disabled";
> +		};
> +
> +		lpi2c5: lpi2c5@402c0000 {

Ditto

> +			compatible = "fsl,imx7ulp-lpi2c";
> +			reg = <0x402c0000 0x10000>;
> +			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&pcc2 IMX7ULP_CLK_LPI2C5>,
> +				 <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>;
> +			clock-names = "per", "ipg";
> +			assigned-clocks = <&pcc2 IMX7ULP_CLK_LPI2C5>;
> +			assigned-clock-parents = <&scg1 IMX7ULP_CLK_FIRC>;
> +			assigned-clock-rates = <48000000>;
> +		};
> +
>  		lpuart4: serial@402d0000 {
>  			compatible = "fsl,imx7ulp-lpuart";
>  			reg = <0x402d0000 0x1000>;
> --
> 2.25.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH V2 05/18] ARM64: dts: imx8: add the missing lpi2c ipg clock
  2021-04-06 11:32 ` [PATCH V2 05/18] ARM64: dts: imx8: add the missing lpi2c ipg clock Clark Wang
  2021-05-11  2:59   ` Shawn Guo
@ 2021-05-21  6:28   ` Aisheng Dong
  1 sibling, 0 replies; 33+ messages in thread
From: Aisheng Dong @ 2021-05-21  6:28 UTC (permalink / raw)
  To: Clark Wang, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, dl-linux-imx, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel

> From: Clark Wang <xiaoning.wang@nxp.com>
> Sent: Tuesday, April 6, 2021 7:33 PM
> 
> The lpi2c driver has add the missing ipg clock.
> So add the ipg clock here for all lpi2c nodes.
> 
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> ---
> V2 changes:
>  - New patch added in V2
> ---
>  .../arm64/boot/dts/freescale/imx8-ss-dma.dtsi | 24 ++++++++++++-------
>  1 file changed, 16 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
> b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
> index 960a802b8b6e..b5ed12a06538 100644
> --- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
> @@ -111,8 +111,10 @@ uart3_lpcg: clock-controller@5a490000 {
>  	i2c0: i2c@5a800000 {
>  		reg = <0x5a800000 0x4000>;
>  		interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
> -		clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>;
> -		clock-names = "per";
> +		interrupt-parent = <&gic>;

Added by mistake?

> +		clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>,
> +			 <&i2c0_lpcg IMX_LPCG_CLK_4>;
> +		clock-names = "per", "ipg";
>  		assigned-clocks = <&clk IMX_SC_R_I2C_0 IMX_SC_PM_CLK_PER>;
>  		assigned-clock-rates = <24000000>;
>  		power-domains = <&pd IMX_SC_R_I2C_0>; @@ -122,8 +124,10 @@
> i2c0: i2c@5a800000 {
>  	i2c1: i2c@5a810000 {
>  		reg = <0x5a810000 0x4000>;
>  		interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
> -		clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>;
> -		clock-names = "per";
> +		interrupt-parent = <&gic>;

Ditto

> +		clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>,
> +			 <&i2c1_lpcg IMX_LPCG_CLK_4>;
> +		clock-names = "per", "ipg";
>  		assigned-clocks = <&clk IMX_SC_R_I2C_1 IMX_SC_PM_CLK_PER>;
>  		assigned-clock-rates = <24000000>;
>  		power-domains = <&pd IMX_SC_R_I2C_1>; @@ -133,8 +137,10 @@
> i2c1: i2c@5a810000 {
>  	i2c2: i2c@5a820000 {
>  		reg = <0x5a820000 0x4000>;
>  		interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>;
> -		clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>;
> -		clock-names = "per";
> +		interrupt-parent = <&gic>;
> +		clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>,
> +			 <&i2c2_lpcg IMX_LPCG_CLK_4>;
> +		clock-names = "per", "ipg";
>  		assigned-clocks = <&clk IMX_SC_R_I2C_2 IMX_SC_PM_CLK_PER>;
>  		assigned-clock-rates = <24000000>;
>  		power-domains = <&pd IMX_SC_R_I2C_2>; @@ -144,8 +150,10 @@
> i2c2: i2c@5a820000 {
>  	i2c3: i2c@5a830000 {
>  		reg = <0x5a830000 0x4000>;
>  		interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
> -		clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>;
> -		clock-names = "per";
> +		interrupt-parent = <&gic>;
> +		clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>,
> +			 <&i2c3_lpcg IMX_LPCG_CLK_4>;
> +		clock-names = "per", "ipg";
>  		assigned-clocks = <&clk IMX_SC_R_I2C_3 IMX_SC_PM_CLK_PER>;
>  		assigned-clock-rates = <24000000>;
>  		power-domains = <&pd IMX_SC_R_I2C_3>;
> --
> 2.25.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH V2 06/18] ARM64: dts: imx8: change i2c irq number to non-combined
  2021-04-06 11:32 ` [PATCH V2 06/18] ARM64: dts: imx8: change i2c irq number to non-combined Clark Wang
@ 2021-05-21  6:32   ` Aisheng Dong
  0 siblings, 0 replies; 33+ messages in thread
From: Aisheng Dong @ 2021-05-21  6:32 UTC (permalink / raw)
  To: Clark Wang, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, dl-linux-imx, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel

> From: Clark Wang <xiaoning.wang@nxp.com>
> Sent: Tuesday, April 6, 2021 7:33 PM
> 
> Combined interrupt number may cause unexcepted irq event when using DMA
> and too many interrupts will be generated.
> So change all i2c interrupts number to non-combined for imx8qxp/8qm/8dxl.

Still no mx8dxl support in upstream, I guess imx8 is enough.
BTW, pls changing tile format as below as pointed by Shawn in another patch:
arm64: dts: xxxx

Otherwise:
Reviewed-by: Dong Aisheng <aisheng.dong@nxp.com>

Regards
Aisheng

> 
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> ---
> V2 changes:
>  - New patch added in V2
> ---
>  arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
> b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
> index b5ed12a06538..9ba57f04859b 100644
> --- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
> @@ -110,7 +110,7 @@ uart3_lpcg: clock-controller@5a490000 {
> 
>  	i2c0: i2c@5a800000 {
>  		reg = <0x5a800000 0x4000>;
> -		interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
> +		interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>;
>  		interrupt-parent = <&gic>;
>  		clocks = <&i2c0_lpcg IMX_LPCG_CLK_0>,
>  			 <&i2c0_lpcg IMX_LPCG_CLK_4>;
> @@ -123,7 +123,7 @@ i2c0: i2c@5a800000 {
> 
>  	i2c1: i2c@5a810000 {
>  		reg = <0x5a810000 0x4000>;
> -		interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
> +		interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
>  		interrupt-parent = <&gic>;
>  		clocks = <&i2c1_lpcg IMX_LPCG_CLK_0>,
>  			 <&i2c1_lpcg IMX_LPCG_CLK_4>;
> @@ -136,7 +136,7 @@ i2c1: i2c@5a810000 {
> 
>  	i2c2: i2c@5a820000 {
>  		reg = <0x5a820000 0x4000>;
> -		interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>;
> +		interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>;
>  		interrupt-parent = <&gic>;
>  		clocks = <&i2c2_lpcg IMX_LPCG_CLK_0>,
>  			 <&i2c2_lpcg IMX_LPCG_CLK_4>;
> @@ -149,7 +149,7 @@ i2c2: i2c@5a820000 {
> 
>  	i2c3: i2c@5a830000 {
>  		reg = <0x5a830000 0x4000>;
> -		interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
> +		interrupts = <GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>;
>  		interrupt-parent = <&gic>;
>  		clocks = <&i2c3_lpcg IMX_LPCG_CLK_0>,
>  			 <&i2c3_lpcg IMX_LPCG_CLK_4>;
> --
> 2.25.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH V2 07/18] i2c: imx-lpi2c: manage irq resource request/release in runtime pm
  2021-04-06 11:32 ` [PATCH V2 07/18] i2c: imx-lpi2c: manage irq resource request/release in runtime pm Clark Wang
@ 2021-05-21  6:38   ` Aisheng Dong
  0 siblings, 0 replies; 33+ messages in thread
From: Aisheng Dong @ 2021-05-21  6:38 UTC (permalink / raw)
  To: Clark Wang, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, dl-linux-imx, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel

> From: Clark Wang <xiaoning.wang@nxp.com>
> Sent: Tuesday, April 6, 2021 7:33 PM
> 
> Manage irq resource request/release in runtime pm to save irq domain's
> power.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> Reviewed-by: Frank Li <Frank.Li@nxp.com>

Reviewed-by: Dong Aisheng <aisheng.dong@nxp.com>

Regards
Aisheng

> ---
> V2 changes:
>  - Change to use request_irq/free_irq.
> ---
>  drivers/i2c/busses/i2c-imx-lpi2c.c | 30 ++++++++++++++++++------------
>  1 file changed, 18 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c
> b/drivers/i2c/busses/i2c-imx-lpi2c.c
> index 89b7b0795f51..333209ba81c1 100644
> --- a/drivers/i2c/busses/i2c-imx-lpi2c.c
> +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
> @@ -94,6 +94,7 @@ enum lpi2c_imx_pincfg {
> 
>  struct lpi2c_imx_struct {
>  	struct i2c_adapter	adapter;
> +	int			irq;
>  	struct clk		*clk_per;
>  	struct clk		*clk_ipg;
>  	void __iomem		*base;
> @@ -571,7 +572,7 @@ static int lpi2c_imx_probe(struct platform_device
> *pdev)  {
>  	struct lpi2c_imx_struct *lpi2c_imx;
>  	unsigned int temp;
> -	int irq, ret;
> +	int ret;
> 
>  	lpi2c_imx = devm_kzalloc(&pdev->dev, sizeof(*lpi2c_imx), GFP_KERNEL);
>  	if (!lpi2c_imx)
> @@ -581,9 +582,9 @@ static int lpi2c_imx_probe(struct platform_device
> *pdev)
>  	if (IS_ERR(lpi2c_imx->base))
>  		return PTR_ERR(lpi2c_imx->base);
> 
> -	irq = platform_get_irq(pdev, 0);
> -	if (irq < 0)
> -		return irq;
> +	lpi2c_imx->irq = platform_get_irq(pdev, 0);
> +	if (lpi2c_imx->irq < 0)
> +		return lpi2c_imx->irq;
> 
>  	lpi2c_imx->adapter.owner	= THIS_MODULE;
>  	lpi2c_imx->adapter.algo		= &lpi2c_imx_algo;
> @@ -609,13 +610,6 @@ static int lpi2c_imx_probe(struct platform_device
> *pdev)
>  	if (ret)
>  		lpi2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ;
> 
> -	ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, 0,
> -			       pdev->name, lpi2c_imx);
> -	if (ret) {
> -		dev_err(&pdev->dev, "can't claim irq %d\n", irq);
> -		return ret;
> -	}
> -
>  	i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx);
>  	platform_set_drvdata(pdev, lpi2c_imx);
> 
> @@ -668,6 +662,7 @@ static int __maybe_unused
> lpi2c_runtime_suspend(struct device *dev)  {
>  	struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
> 
> +	free_irq(lpi2c_imx->irq, lpi2c_imx);
>  	lpi2c_imx_clocks_unprepare(lpi2c_imx);
>  	pinctrl_pm_select_sleep_state(dev);
> 
> @@ -677,10 +672,21 @@ static int __maybe_unused
> lpi2c_runtime_suspend(struct device *dev)  static int __maybe_unused
> lpi2c_runtime_resume(struct device *dev)  {
>  	struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
> +	int ret = 0;
> 
>  	pinctrl_pm_select_default_state(dev);
> +	ret = lpi2c_imx_clocks_prepare(lpi2c_imx);
> +	if (ret)
> +		return ret;
> 
> -	return lpi2c_imx_clocks_prepare(lpi2c_imx);
> +	ret = request_irq(lpi2c_imx->irq, lpi2c_imx_isr, 0,
> +			       dev_name(dev), lpi2c_imx);
> +	if (ret) {
> +		dev_err(dev, "can't claim irq %d\n", lpi2c_imx->irq);
> +		return ret;
> +	}
> +
> +	return ret;
>  }
> 
>  static const struct dev_pm_ops lpi2c_pm_ops = {
> --
> 2.25.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH V2 08/18] i2c: imx-lpi2c: add debug message when i2c peripheral clk doesn't work
  2021-04-06 11:32 ` [PATCH V2 08/18] i2c: imx-lpi2c: add debug message when i2c peripheral clk doesn't work Clark Wang
@ 2021-05-21  6:43   ` Aisheng Dong
  0 siblings, 0 replies; 33+ messages in thread
From: Aisheng Dong @ 2021-05-21  6:43 UTC (permalink / raw)
  To: Clark Wang, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, dl-linux-imx, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel

> From: Clark Wang <xiaoning.wang@nxp.com>
> Sent: Tuesday, April 6, 2021 7:33 PM
> 
> add debug message when i2c peripheral clk rate is 0, then directly return
> -EINVAL.
> 
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>

You sign-off should be put after the original patch author

> Signed-off-by: Gao Pan <pandy.gao@nxp.com>
> Reviewed-by: Andy Duan <fugang.duan@nxp.com>

Drop the original review when they're significant changes

> ---
> V2 changes:
>  - Add my signed-off.
> ---
>  drivers/i2c/busses/i2c-imx-lpi2c.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c
> b/drivers/i2c/busses/i2c-imx-lpi2c.c
> index 333209ba81c1..dfec334712c2 100644
> --- a/drivers/i2c/busses/i2c-imx-lpi2c.c
> +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
> @@ -210,6 +210,11 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct
> *lpi2c_imx)
>  	lpi2c_imx_set_mode(lpi2c_imx);
> 
>  	clk_rate = clk_get_rate(lpi2c_imx->clk_per);
> +	if (!clk_rate) {
> +		dev_dbg(&lpi2c_imx->adapter.dev, "clk_per rate is 0\n");

s/dev_dbg/dev_err

> +		return -EINVAL;
> +	}
> +
>  	if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST)
>  		filt = 0;
>  	else
> --
> 2.25.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH V2 10/18] i2c: imx-lpi2c: add bus recovery feature
  2021-04-06 11:32 ` [PATCH V2 10/18] i2c: imx-lpi2c: add bus recovery feature Clark Wang
  2021-04-07  0:34   ` kernel test robot
@ 2021-05-21  6:44   ` Aisheng Dong
  1 sibling, 0 replies; 33+ messages in thread
From: Aisheng Dong @ 2021-05-21  6:44 UTC (permalink / raw)
  To: Clark Wang, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, dl-linux-imx, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel

> From: Clark Wang <xiaoning.wang@nxp.com>
> Sent: Tuesday, April 6, 2021 7:33 PM
> 
> Add bus recovery feature for LPI2C.
> Need add gpio pinctrl, scl-gpios and sda-gpios configuration in dts.
> 
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> ---
> V2 changes:
>  - No change. Add dt-bindings in the next patch.

Dt binding patch should be sent before driver change

> ---
>  drivers/i2c/busses/i2c-imx-lpi2c.c | 83 ++++++++++++++++++++++++++++++
>  1 file changed, 83 insertions(+)
> 
> diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c
> b/drivers/i2c/busses/i2c-imx-lpi2c.c
> index 77ceb743b282..77dd6ee5a4a8 100644
> --- a/drivers/i2c/busses/i2c-imx-lpi2c.c
> +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
> @@ -18,6 +18,7 @@
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/of_device.h>
> +#include <linux/of_gpio.h>
>  #include <linux/pinctrl/consumer.h>
>  #include <linux/platform_device.h>
>  #include <linux/pm_runtime.h>
> @@ -108,6 +109,11 @@ struct lpi2c_imx_struct {
>  	unsigned int		txfifosize;
>  	unsigned int		rxfifosize;
>  	enum lpi2c_imx_mode	mode;
> +
> +	struct i2c_bus_recovery_info rinfo;
> +	struct pinctrl *pinctrl;
> +	struct pinctrl_state *pinctrl_pins_default;
> +	struct pinctrl_state *pinctrl_pins_gpio;
>  };
> 
>  static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx, @@ -135,6
> +141,8 @@ static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx)
> 
>  		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
>  			dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n");
> +			if (lpi2c_imx->adapter.bus_recovery_info)
> +				i2c_recover_bus(&lpi2c_imx->adapter);
>  			return -ETIMEDOUT;
>  		}
>  		schedule();
> @@ -192,6 +200,8 @@ static void lpi2c_imx_stop(struct lpi2c_imx_struct
> *lpi2c_imx)
> 
>  		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
>  			dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n");
> +			if (lpi2c_imx->adapter.bus_recovery_info)
> +				i2c_recover_bus(&lpi2c_imx->adapter);
>  			break;
>  		}
>  		schedule();
> @@ -329,6 +339,8 @@ static int lpi2c_imx_txfifo_empty(struct
> lpi2c_imx_struct *lpi2c_imx)
> 
>  		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
>  			dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n");
> +			if (lpi2c_imx->adapter.bus_recovery_info)
> +				i2c_recover_bus(&lpi2c_imx->adapter);
>  			return -ETIMEDOUT;
>  		}
>  		schedule();
> @@ -528,6 +540,71 @@ static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id)
>  	return IRQ_HANDLED;
>  }
> 
> +static void lpi2c_imx_prepare_recovery(struct i2c_adapter *adap) {
> +	struct lpi2c_imx_struct *lpi2c_imx;
> +
> +	lpi2c_imx = container_of(adap, struct lpi2c_imx_struct, adapter);
> +
> +	pinctrl_select_state(lpi2c_imx->pinctrl,
> +lpi2c_imx->pinctrl_pins_gpio); }
> +
> +static void lpi2c_imx_unprepare_recovery(struct i2c_adapter *adap) {
> +	struct lpi2c_imx_struct *lpi2c_imx;
> +
> +	lpi2c_imx = container_of(adap, struct lpi2c_imx_struct, adapter);
> +
> +	pinctrl_select_state(lpi2c_imx->pinctrl,
> +lpi2c_imx->pinctrl_pins_default); }
> +
> +/*
> + * We switch SCL and SDA to their GPIO function and do some bitbanging
> + * for bus recovery. These alternative pinmux settings can be
> + * described in the device tree by a separate pinctrl state "gpio". If
> + * this is missing this is not a big problem, the only implication is
> + * that we can't do bus recovery.
> + */
> +static int lpi2c_imx_init_recovery_info(struct lpi2c_imx_struct *lpi2c_imx,
> +		struct platform_device *pdev)
> +{
> +	struct i2c_bus_recovery_info *rinfo = &lpi2c_imx->rinfo;
> +
> +	lpi2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev);
> +	if (!lpi2c_imx->pinctrl || IS_ERR(lpi2c_imx->pinctrl)) {
> +		dev_info(&pdev->dev, "can't get pinctrl, bus recovery not
> supported\n");
> +		return PTR_ERR(lpi2c_imx->pinctrl);
> +	}
> +
> +	lpi2c_imx->pinctrl_pins_default = pinctrl_lookup_state(lpi2c_imx->pinctrl,
> +			PINCTRL_STATE_DEFAULT);
> +	lpi2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(lpi2c_imx->pinctrl,
> +			"gpio");
> +	rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
> +	rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl",
> +GPIOD_OUT_HIGH_OPEN_DRAIN);
> +
> +	if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER ||
> +	    PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER) {
> +		return -EPROBE_DEFER;
> +	} else if (IS_ERR(rinfo->sda_gpiod) ||
> +		   IS_ERR(rinfo->scl_gpiod) ||
> +		   IS_ERR(lpi2c_imx->pinctrl_pins_default) ||
> +		   IS_ERR(lpi2c_imx->pinctrl_pins_gpio)) {
> +		dev_dbg(&pdev->dev, "recovery information incomplete\n");
> +		return 0;
> +	}
> +
> +	dev_info(&pdev->dev, "using scl%s for recovery\n",
> +		 rinfo->sda_gpiod ? ",sda" : "");
> +
> +	rinfo->prepare_recovery = lpi2c_imx_prepare_recovery;
> +	rinfo->unprepare_recovery = lpi2c_imx_unprepare_recovery;
> +	rinfo->recover_bus = i2c_generic_scl_recovery;
> +	lpi2c_imx->adapter.bus_recovery_info = rinfo;
> +
> +	return 0;
> +}
> +
>  static u32 lpi2c_imx_func(struct i2c_adapter *adapter)  {
>  	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | @@ -632,6 +709,12
> @@ static int lpi2c_imx_probe(struct platform_device *pdev)
>  	lpi2c_imx->txfifosize = 1 << (temp & 0x0f);
>  	lpi2c_imx->rxfifosize = 1 << ((temp >> 8) & 0x0f);
> 
> +	/* Init optional bus recovery function */
> +	ret = lpi2c_imx_init_recovery_info(lpi2c_imx, pdev);
> +	/* Give it another chance if pinctrl used is not ready yet */
> +	if (ret == -EPROBE_DEFER)
> +		goto rpm_disable;
> +
>  	ret = i2c_add_adapter(&lpi2c_imx->adapter);
>  	if (ret)
>  		goto rpm_disable;
> --
> 2.25.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH V2 11/18] dt-bindings: i2c: imx-lpi2c: Add bus recovery example
  2021-04-06 11:32 ` [PATCH V2 11/18] dt-bindings: i2c: imx-lpi2c: Add bus recovery example Clark Wang
  2021-04-06 13:24   ` Rob Herring
@ 2021-05-21  7:02   ` Aisheng Dong
  1 sibling, 0 replies; 33+ messages in thread
From: Aisheng Dong @ 2021-05-21  7:02 UTC (permalink / raw)
  To: Clark Wang, robh+dt, shawnguo, s.hauer, festevam
  Cc: kernel, dl-linux-imx, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel

> From: Clark Wang <xiaoning.wang@nxp.com>
> Sent: Tuesday, April 6, 2021 7:33 PM
> Subject: [PATCH V2 11/18] dt-bindings: i2c: imx-lpi2c: Add bus recovery
> example

s/example/support

and pls pass make dt_binding_check

> 
> Add i2c bus recovery configuration example.
> 
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> ---
> V2 changes:
>  - New patch added in V2
> ---
>  .../devicetree/bindings/i2c/i2c-imx-lpi2c.yaml     | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
> b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
> index 29b9447f3b84..0a4b28827dcc 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
> +++ b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml
> @@ -42,6 +42,15 @@ properties:
>    power-domains:
>      maxItems: 1
> 
> +  pinctrl-names:
> +    minItems: 1
> +
> +  scl-gpios:
> +    maxItems: 1
> +
> +  sda-gpios:
> +    maxItems: 1
> +
>  required:
>    - compatible
>    - reg
> @@ -61,4 +70,9 @@ examples:
>          interrupt-parent = <&intc>;
>          interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
>          clocks = <&clks IMX7ULP_CLK_LPI2C7>;
> +        pinctrl-names = "default","gpio";
> +        pinctrl-0 = <&pinctrl_i2c>;
> +        pinctrl-1 = <&pinctrl_i2c_recovery>;
> +        scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
> +        sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH |
> GPIO_OPEN_DRAIN)>;
>      };
> --
> 2.25.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, other threads:[~2021-05-21  7:04 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-06 11:32 [PATCH V2 00/18] i2c: imx-lpi2c: New features and bug fixes Clark Wang
2021-04-06 11:32 ` [PATCH V2 01/18] i2c: imx-lpi2c: directly retrun ISR when detect a NACK Clark Wang
2021-04-06 11:32 ` [PATCH V2 02/18] i2c: imx-lpi2c: add ipg clk for lpi2c driver Clark Wang
2021-05-21  6:14   ` Aisheng Dong
2021-04-06 11:32 ` [PATCH V2 03/18] ARM: dts: imx7ulp: add the missing lpi2c ipg clock Clark Wang
2021-05-21  6:17   ` Aisheng Dong
2021-04-06 11:32 ` [PATCH V2 04/18] ARM: dts: imx7ulp: add the missing lpi2c nodes Clark Wang
2021-05-21  6:25   ` Aisheng Dong
2021-04-06 11:32 ` [PATCH V2 05/18] ARM64: dts: imx8: add the missing lpi2c ipg clock Clark Wang
2021-05-11  2:59   ` Shawn Guo
2021-05-21  6:28   ` Aisheng Dong
2021-04-06 11:32 ` [PATCH V2 06/18] ARM64: dts: imx8: change i2c irq number to non-combined Clark Wang
2021-05-21  6:32   ` Aisheng Dong
2021-04-06 11:32 ` [PATCH V2 07/18] i2c: imx-lpi2c: manage irq resource request/release in runtime pm Clark Wang
2021-05-21  6:38   ` Aisheng Dong
2021-04-06 11:32 ` [PATCH V2 08/18] i2c: imx-lpi2c: add debug message when i2c peripheral clk doesn't work Clark Wang
2021-05-21  6:43   ` Aisheng Dong
2021-04-06 11:32 ` [PATCH V2 09/18] i2c: imx-lpi2c: increase PM timeout to avoid operate clk frequently Clark Wang
2021-04-06 11:32 ` [PATCH V2 10/18] i2c: imx-lpi2c: add bus recovery feature Clark Wang
2021-04-07  0:34   ` kernel test robot
2021-05-21  6:44   ` Aisheng Dong
2021-04-06 11:32 ` [PATCH V2 11/18] dt-bindings: i2c: imx-lpi2c: Add bus recovery example Clark Wang
2021-04-06 13:24   ` Rob Herring
2021-05-21  7:02   ` Aisheng Dong
2021-04-06 11:33 ` [PATCH V2 12/18] i2c: imx-lpi2c: fix i2c timing issue Clark Wang
2021-04-06 11:33 ` [PATCH V2 13/18] i2c: imx-lpi2c: fix type char overflow issue when calculating the clock cycle Clark Wang
2021-04-06 11:33 ` [PATCH V2 14/18] i2c: imx-lpi2c: add edma mode support Clark Wang
2021-04-06 11:41   ` Clark Wang
2021-04-06 11:33 ` [PATCH V2 15/18] dt-bindings: i2c: imx-lpi2c: Add dma configuration example Clark Wang
2021-04-09 16:33   ` Rob Herring
2021-04-06 11:33 ` [PATCH V2 16/18] ARM: dts: imx7ulp: add dma configurations for lpi2c Clark Wang
2021-04-06 11:33 ` [PATCH V2 17/18] ARM: dts: imx7ulp: add the missing status property of lpi2c5 Clark Wang
2021-04-06 11:33 ` [PATCH V2 18/18] i2c: imx-lpi2c: fix pio mode cannot send 256+ bytes in one frame Clark Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).