diff mbox series

[09/11] i2c: imx-lpi2c: fix i2c timing issue

Message ID 20210317065359.3109394-10-xiaoning.wang@nxp.com (mailing list archive)
State New, archived
Headers show
Series i2c: imx-lpi2c: New features and bug fixes | expand

Commit Message

Clark Wang March 17, 2021, 6:53 a.m. UTC
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.

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

Comments

Aisheng Dong March 19, 2021, 5:15 a.m. UTC | #1
> From: Clark Wang <xiaoning.wang@nxp.com>
> Sent: Wednesday, March 17, 2021 2:54 PM
> 
> 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.
> 
> Reviewed-by: Fugang Duan <fugang.duan@nxp.com>
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> ---
>  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 7216a393095d..5dbe85126f24 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

Where is this ratio coming from?
Can you describe why use it in commit message?

Regards
Aisheng

>  #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
Clark Wang March 19, 2021, 7:21 a.m. UTC | #2
> -----Original Message-----
> From: Aisheng Dong <aisheng.dong@nxp.com>
> Sent: Friday, March 19, 2021 13:15
> To: Clark Wang <xiaoning.wang@nxp.com>; shawnguo@kernel.org;
> s.hauer@pengutronix.de
> Cc: kernel@pengutronix.de; festevam@gmail.com; dl-linux-imx <linux-
> imx@nxp.com>; sumit.semwal@linaro.org; christian.koenig@amd.com;
> linux-i2c@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-
> kernel@vger.kernel.org
> Subject: RE: [PATCH 09/11] i2c: imx-lpi2c: fix i2c timing issue
>
> > From: Clark Wang <xiaoning.wang@nxp.com>
> > Sent: Wednesday, March 17, 2021 2:54 PM
> >
> > 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.
> >
> > Reviewed-by: Fugang Duan <fugang.duan@nxp.com>
> > Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> > ---
> >  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 7216a393095d..5dbe85126f24 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
>
> Where is this ratio coming from?
> Can you describe why use it in commit message?

This ratio is a value obtained after passing the test.
I2C's Tlow should longer than the spec.
For example, in FAST mode, Tlow should be longer than 1.3us.
The previous calculation violated the spec.
So I re-write the calculation of clk_cycle by referring the RM. Then test the 
ratio to let Tlow match the spec by catching the waveform.

Best Regards,
Clark Wang

>
> Regards
> Aisheng
>
> >  #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
diff mbox series

Patch

diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index 7216a393095d..5dbe85126f24 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;