All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] spi: fsl-dspi (vf610) clock fixes
@ 2015-03-30 17:49 Aaron Brice
  2015-03-30 17:49   ` Aaron Brice
  2015-03-30 17:49 ` [PATCH v2 2/2] spi: fsl-dspi: Add ~50ns delay between cs and sck Aaron Brice
  0 siblings, 2 replies; 9+ messages in thread
From: Aaron Brice @ 2015-03-30 17:49 UTC (permalink / raw)
  To: broonie; +Cc: linux-spi, linux-kernel, stefan

We were having intermittent problems writing to SRAM chip on SPI bus on vf610
SoM.  Added support for CS setup and hold times to meet the SRAM spec.  In the
process noticed that the baud rate was a little high.

Changes since v1:
 * More detail in commit message for clock rate fix

Aaron Brice (2):
  spi: fsl-dspi: Fix clock rate scale values
  spi: fsl-dspi: Add ~50ns delay between cs and sck

 drivers/spi/spi-fsl-dspi.c | 84 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 70 insertions(+), 14 deletions(-)

-- 
2.1.0


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

* [PATCH v2 1/2] spi: fsl-dspi: Fix clock rate scale values
@ 2015-03-30 17:49   ` Aaron Brice
  0 siblings, 0 replies; 9+ messages in thread
From: Aaron Brice @ 2015-03-30 17:49 UTC (permalink / raw)
  To: broonie; +Cc: linux-spi, linux-kernel, stefan

Previous algorithm had an outer loop with the values {2,3,5,7} and an
inner loop with {2,4,6,8,16,32,...,32768}, and would pick the first
value over the required scaling value (where the total scale was the two
numbers multiplied).

Since the inner loop went up to 32768 it would always pick a value of 2
for PBR and a much higher than necessary value for BR.  The desired
scale factor was being divided by two I believe to compensate for the
much higher scale factors (the divide by two not specified in the
reference manual).

Updated to check all values and find the smallest scale factor possible
without going over the desired clock rate.

Signed-off-by: Aaron Brice <aaron.brice@datasoft.com>
---
 drivers/spi/spi-fsl-dspi.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index d1a3924..96cac87 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -148,23 +148,30 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
 		16,	32,	64,	128,
 		256,	512,	1024,	2048,
 		4096,	8192,	16384,	32768 };
-	int temp, i = 0, j = 0;
-
-	temp = clkrate / 2 / speed_hz;
-
-	for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++)
-		for (j = 0; j < ARRAY_SIZE(brs); j++) {
-			if (pbr_tbl[i] * brs[j] >= temp) {
-				*pbr = i;
-				*br = j;
-				return;
+	int scale_needed, scale, minscale = INT_MAX;
+	int i, j;
+
+	scale_needed = clkrate / speed_hz;
+
+	for (i = 0; i < ARRAY_SIZE(brs); i++)
+		for (j = 0; j < ARRAY_SIZE(pbr_tbl); j++) {
+			scale = brs[i] * pbr_tbl[j];
+			if (scale >= scale_needed) {
+				if (scale < minscale) {
+					minscale = scale;
+					*br = i;
+					*pbr = j;
+				}
+				break;
 			}
 		}
 
-	pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld\
-		,we use the max prescaler value.\n", speed_hz, clkrate);
-	*pbr = ARRAY_SIZE(pbr_tbl) - 1;
-	*br =  ARRAY_SIZE(brs) - 1;
+	if (minscale == INT_MAX) {
+		pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld, we use the max prescaler value.\n",
+			speed_hz, clkrate);
+		*pbr = ARRAY_SIZE(pbr_tbl) - 1;
+		*br =  ARRAY_SIZE(brs) - 1;
+	}
 }
 
 static int dspi_transfer_write(struct fsl_dspi *dspi)
-- 
2.1.0


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

* [PATCH v2 1/2] spi: fsl-dspi: Fix clock rate scale values
@ 2015-03-30 17:49   ` Aaron Brice
  0 siblings, 0 replies; 9+ messages in thread
From: Aaron Brice @ 2015-03-30 17:49 UTC (permalink / raw)
  To: broonie-DgEjT+Ai2ygdnm+yROfE0A
  Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, stefan-XLVq0VzYD2Y

Previous algorithm had an outer loop with the values {2,3,5,7} and an
inner loop with {2,4,6,8,16,32,...,32768}, and would pick the first
value over the required scaling value (where the total scale was the two
numbers multiplied).

Since the inner loop went up to 32768 it would always pick a value of 2
for PBR and a much higher than necessary value for BR.  The desired
scale factor was being divided by two I believe to compensate for the
much higher scale factors (the divide by two not specified in the
reference manual).

Updated to check all values and find the smallest scale factor possible
without going over the desired clock rate.

Signed-off-by: Aaron Brice <aaron.brice-vSOi0k5x9wFWk0Htik3J/w@public.gmane.org>
---
 drivers/spi/spi-fsl-dspi.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index d1a3924..96cac87 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -148,23 +148,30 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
 		16,	32,	64,	128,
 		256,	512,	1024,	2048,
 		4096,	8192,	16384,	32768 };
-	int temp, i = 0, j = 0;
-
-	temp = clkrate / 2 / speed_hz;
-
-	for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++)
-		for (j = 0; j < ARRAY_SIZE(brs); j++) {
-			if (pbr_tbl[i] * brs[j] >= temp) {
-				*pbr = i;
-				*br = j;
-				return;
+	int scale_needed, scale, minscale = INT_MAX;
+	int i, j;
+
+	scale_needed = clkrate / speed_hz;
+
+	for (i = 0; i < ARRAY_SIZE(brs); i++)
+		for (j = 0; j < ARRAY_SIZE(pbr_tbl); j++) {
+			scale = brs[i] * pbr_tbl[j];
+			if (scale >= scale_needed) {
+				if (scale < minscale) {
+					minscale = scale;
+					*br = i;
+					*pbr = j;
+				}
+				break;
 			}
 		}
 
-	pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld\
-		,we use the max prescaler value.\n", speed_hz, clkrate);
-	*pbr = ARRAY_SIZE(pbr_tbl) - 1;
-	*br =  ARRAY_SIZE(brs) - 1;
+	if (minscale == INT_MAX) {
+		pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld, we use the max prescaler value.\n",
+			speed_hz, clkrate);
+		*pbr = ARRAY_SIZE(pbr_tbl) - 1;
+		*br =  ARRAY_SIZE(brs) - 1;
+	}
 }
 
 static int dspi_transfer_write(struct fsl_dspi *dspi)
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 2/2] spi: fsl-dspi: Add ~50ns delay between cs and sck
  2015-03-30 17:49 [PATCH v2 0/2] spi: fsl-dspi (vf610) clock fixes Aaron Brice
  2015-03-30 17:49   ` Aaron Brice
@ 2015-03-30 17:49 ` Aaron Brice
  2015-03-30 22:13     ` Stefan Agner
  1 sibling, 1 reply; 9+ messages in thread
From: Aaron Brice @ 2015-03-30 17:49 UTC (permalink / raw)
  To: broonie; +Cc: linux-spi, linux-kernel, stefan

Add delay between chip select and clock signals, before clock starts and
after clock stops.

Signed-off-by: Aaron Brice <aaron.brice@datasoft.com>
---
 drivers/spi/spi-fsl-dspi.c | 53 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 96cac87..41284cc 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -20,6 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/math64.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -51,7 +52,7 @@
 #define SPI_CTAR_CPOL(x)	((x) << 26)
 #define SPI_CTAR_CPHA(x)	((x) << 25)
 #define SPI_CTAR_LSBFE(x)	((x) << 24)
-#define SPI_CTAR_PCSSCR(x)	(((x) & 0x00000003) << 22)
+#define SPI_CTAR_PCSSCK(x)	(((x) & 0x00000003) << 22)
 #define SPI_CTAR_PASC(x)	(((x) & 0x00000003) << 20)
 #define SPI_CTAR_PDT(x)	(((x) & 0x00000003) << 18)
 #define SPI_CTAR_PBR(x)	(((x) & 0x00000003) << 16)
@@ -59,6 +60,7 @@
 #define SPI_CTAR_ASC(x)	(((x) & 0x0000000f) << 8)
 #define SPI_CTAR_DT(x)		(((x) & 0x0000000f) << 4)
 #define SPI_CTAR_BR(x)		((x) & 0x0000000f)
+#define SPI_CTAR_SCALE_BITS	0xf
 
 #define SPI_CTAR0_SLAVE	0x0c
 
@@ -99,6 +101,8 @@
 #define SPI_CS_ASSERT		0x02
 #define SPI_CS_DROP		0x04
 
+#define NSEC_PER_SEC		1000000000L
+
 struct chip_data {
 	u32 mcr_val;
 	u32 ctar_val;
@@ -174,6 +178,40 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
 	}
 }
 
+static void ns_delay_scale(char *psc, char *sc, int delay_ns,
+		unsigned long clkrate)
+{
+	int pscale_tbl[4] = {1, 3, 5, 7};
+	int scale_needed, scale, minscale = INT_MAX;
+	int i, j;
+	u32 remainder;
+
+	scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC,
+			&remainder);
+	if (remainder)
+		scale_needed++;
+
+	for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++)
+		for (j = 0; j <= SPI_CTAR_SCALE_BITS; j++) {
+			scale = pscale_tbl[i] * (2 << j);
+			if (scale >= scale_needed) {
+				if (scale < minscale) {
+					minscale = scale;
+					*psc = i;
+					*sc = j;
+				}
+				break;
+			}
+		}
+
+	if (minscale == INT_MAX) {
+		pr_warn("Cannot find correct scale values for %dns delay at clkrate %ld, using max prescaler value",
+			delay_ns, clkrate);
+		*psc = ARRAY_SIZE(pscale_tbl) - 1;
+		*sc = SPI_CTAR_SCALE_BITS;
+	}
+}
+
 static int dspi_transfer_write(struct fsl_dspi *dspi)
 {
 	int tx_count = 0;
@@ -352,7 +390,8 @@ static int dspi_setup(struct spi_device *spi)
 {
 	struct chip_data *chip;
 	struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
-	unsigned char br = 0, pbr = 0, fmsz = 0;
+	unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0;
+	unsigned char pasc = 0, asc = 0, fmsz = 0;
 
 	if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) {
 		fmsz = spi->bits_per_word - 1;
@@ -377,10 +416,20 @@ static int dspi_setup(struct spi_device *spi)
 	hz_to_spi_baud(&pbr, &br,
 			spi->max_speed_hz, clk_get_rate(dspi->clk));
 
+	/* Set PCS to SCK delay scale values for 50ns delay*/
+	ns_delay_scale(&pcssck, &cssck, 50, clk_get_rate(dspi->clk));
+
+	/* Set After SCK delay scale values for 50ns delay*/
+	ns_delay_scale(&pasc, &asc, 50, clk_get_rate(dspi->clk));
+
 	chip->ctar_val =  SPI_CTAR_FMSZ(fmsz)
 		| SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
 		| SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
 		| SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
+		| SPI_CTAR_PCSSCK(pcssck)
+		| SPI_CTAR_CSSCK(cssck)
+		| SPI_CTAR_PASC(pasc)
+		| SPI_CTAR_ASC(asc)
 		| SPI_CTAR_PBR(pbr)
 		| SPI_CTAR_BR(br);
 
-- 
2.1.0


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

* Re: [PATCH v2 2/2] spi: fsl-dspi: Add ~50ns delay between cs and sck
@ 2015-03-30 22:13     ` Stefan Agner
  0 siblings, 0 replies; 9+ messages in thread
From: Stefan Agner @ 2015-03-30 22:13 UTC (permalink / raw)
  To: Aaron Brice; +Cc: broonie, linux-spi, linux-kernel

Hi Aaron,

Thanks for the fixes! Some comments below:

On 2015-03-30 19:49, Aaron Brice wrote:
> Add delay between chip select and clock signals, before clock starts and
> after clock stops.

This 50ns are specifc to the SPI slave at hand (SRAM) is this correct?
If yes, this would probably need new slave properties. I found a TI
controller which also supports such properties:
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-September/285761.html

> 
> Signed-off-by: Aaron Brice <aaron.brice@datasoft.com>
> ---
>  drivers/spi/spi-fsl-dspi.c | 53 ++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 51 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
> index 96cac87..41284cc 100644
> --- a/drivers/spi/spi-fsl-dspi.c
> +++ b/drivers/spi/spi-fsl-dspi.c
> @@ -20,6 +20,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/io.h>
>  #include <linux/kernel.h>
> +#include <linux/math64.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/of_device.h>
> @@ -51,7 +52,7 @@
>  #define SPI_CTAR_CPOL(x)	((x) << 26)
>  #define SPI_CTAR_CPHA(x)	((x) << 25)
>  #define SPI_CTAR_LSBFE(x)	((x) << 24)
> -#define SPI_CTAR_PCSSCR(x)	(((x) & 0x00000003) << 22)
> +#define SPI_CTAR_PCSSCK(x)	(((x) & 0x00000003) << 22)
>  #define SPI_CTAR_PASC(x)	(((x) & 0x00000003) << 20)
>  #define SPI_CTAR_PDT(x)	(((x) & 0x00000003) << 18)
>  #define SPI_CTAR_PBR(x)	(((x) & 0x00000003) << 16)
> @@ -59,6 +60,7 @@
>  #define SPI_CTAR_ASC(x)	(((x) & 0x0000000f) << 8)
>  #define SPI_CTAR_DT(x)		(((x) & 0x0000000f) << 4)
>  #define SPI_CTAR_BR(x)		((x) & 0x0000000f)
> +#define SPI_CTAR_SCALE_BITS	0xf
>  
>  #define SPI_CTAR0_SLAVE	0x0c
>  
> @@ -99,6 +101,8 @@
>  #define SPI_CS_ASSERT		0x02
>  #define SPI_CS_DROP		0x04
>  
> +#define NSEC_PER_SEC		1000000000L
> +

Avoid redefine this, should be available from headers (e.g. time.h)

>  struct chip_data {
>  	u32 mcr_val;
>  	u32 ctar_val;
> @@ -174,6 +178,40 @@ static void hz_to_spi_baud(char *pbr, char *br,
> int speed_hz,
>  	}
>  }
>  
> +static void ns_delay_scale(char *psc, char *sc, int delay_ns,
> +		unsigned long clkrate)
> +{
> +	int pscale_tbl[4] = {1, 3, 5, 7};
> +	int scale_needed, scale, minscale = INT_MAX;
> +	int i, j;
> +	u32 remainder;
> +
> +	scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC,
> +			&remainder);
> +	if (remainder)
> +		scale_needed++;
> +
> +	for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++)
> +		for (j = 0; j <= SPI_CTAR_SCALE_BITS; j++) {
> +			scale = pscale_tbl[i] * (2 << j);
> +			if (scale >= scale_needed) {
> +				if (scale < minscale) {
> +					minscale = scale;
> +					*psc = i;
> +					*sc = j;
> +				}
> +				break;
> +			}
> +		}
> +
> +	if (minscale == INT_MAX) {
> +		pr_warn("Cannot find correct scale values for %dns delay at clkrate
> %ld, using max prescaler value",
> +			delay_ns, clkrate);
> +		*psc = ARRAY_SIZE(pscale_tbl) - 1;
> +		*sc = SPI_CTAR_SCALE_BITS;
> +	}
> +}
> +
>  static int dspi_transfer_write(struct fsl_dspi *dspi)
>  {
>  	int tx_count = 0;
> @@ -352,7 +390,8 @@ static int dspi_setup(struct spi_device *spi)
>  {
>  	struct chip_data *chip;
>  	struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
> -	unsigned char br = 0, pbr = 0, fmsz = 0;
> +	unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0;
> +	unsigned char pasc = 0, asc = 0, fmsz = 0;
>  
>  	if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) {
>  		fmsz = spi->bits_per_word - 1;
> @@ -377,10 +416,20 @@ static int dspi_setup(struct spi_device *spi)
>  	hz_to_spi_baud(&pbr, &br,
>  			spi->max_speed_hz, clk_get_rate(dspi->clk));
>  
> +	/* Set PCS to SCK delay scale values for 50ns delay*/
> +	ns_delay_scale(&pcssck, &cssck, 50, clk_get_rate(dspi->clk));
> +
> +	/* Set After SCK delay scale values for 50ns delay*/
> +	ns_delay_scale(&pasc, &asc, 50, clk_get_rate(dspi->clk));
> +

This functions calls clk_get_rate three times, can you add a local
variable for it?

>  	chip->ctar_val =  SPI_CTAR_FMSZ(fmsz)
>  		| SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
>  		| SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
>  		| SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
> +		| SPI_CTAR_PCSSCK(pcssck)
> +		| SPI_CTAR_CSSCK(cssck)
> +		| SPI_CTAR_PASC(pasc)
> +		| SPI_CTAR_ASC(asc)
>  		| SPI_CTAR_PBR(pbr)
>  		| SPI_CTAR_BR(br);


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

* Re: [PATCH v2 2/2] spi: fsl-dspi: Add ~50ns delay between cs and sck
@ 2015-03-30 22:13     ` Stefan Agner
  0 siblings, 0 replies; 9+ messages in thread
From: Stefan Agner @ 2015-03-30 22:13 UTC (permalink / raw)
  To: Aaron Brice
  Cc: broonie-DgEjT+Ai2ygdnm+yROfE0A, linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

Hi Aaron,

Thanks for the fixes! Some comments below:

On 2015-03-30 19:49, Aaron Brice wrote:
> Add delay between chip select and clock signals, before clock starts and
> after clock stops.

This 50ns are specifc to the SPI slave at hand (SRAM) is this correct?
If yes, this would probably need new slave properties. I found a TI
controller which also supports such properties:
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-September/285761.html

> 
> Signed-off-by: Aaron Brice <aaron.brice-vSOi0k5x9wFWk0Htik3J/w@public.gmane.org>
> ---
>  drivers/spi/spi-fsl-dspi.c | 53 ++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 51 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
> index 96cac87..41284cc 100644
> --- a/drivers/spi/spi-fsl-dspi.c
> +++ b/drivers/spi/spi-fsl-dspi.c
> @@ -20,6 +20,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/io.h>
>  #include <linux/kernel.h>
> +#include <linux/math64.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/of_device.h>
> @@ -51,7 +52,7 @@
>  #define SPI_CTAR_CPOL(x)	((x) << 26)
>  #define SPI_CTAR_CPHA(x)	((x) << 25)
>  #define SPI_CTAR_LSBFE(x)	((x) << 24)
> -#define SPI_CTAR_PCSSCR(x)	(((x) & 0x00000003) << 22)
> +#define SPI_CTAR_PCSSCK(x)	(((x) & 0x00000003) << 22)
>  #define SPI_CTAR_PASC(x)	(((x) & 0x00000003) << 20)
>  #define SPI_CTAR_PDT(x)	(((x) & 0x00000003) << 18)
>  #define SPI_CTAR_PBR(x)	(((x) & 0x00000003) << 16)
> @@ -59,6 +60,7 @@
>  #define SPI_CTAR_ASC(x)	(((x) & 0x0000000f) << 8)
>  #define SPI_CTAR_DT(x)		(((x) & 0x0000000f) << 4)
>  #define SPI_CTAR_BR(x)		((x) & 0x0000000f)
> +#define SPI_CTAR_SCALE_BITS	0xf
>  
>  #define SPI_CTAR0_SLAVE	0x0c
>  
> @@ -99,6 +101,8 @@
>  #define SPI_CS_ASSERT		0x02
>  #define SPI_CS_DROP		0x04
>  
> +#define NSEC_PER_SEC		1000000000L
> +

Avoid redefine this, should be available from headers (e.g. time.h)

>  struct chip_data {
>  	u32 mcr_val;
>  	u32 ctar_val;
> @@ -174,6 +178,40 @@ static void hz_to_spi_baud(char *pbr, char *br,
> int speed_hz,
>  	}
>  }
>  
> +static void ns_delay_scale(char *psc, char *sc, int delay_ns,
> +		unsigned long clkrate)
> +{
> +	int pscale_tbl[4] = {1, 3, 5, 7};
> +	int scale_needed, scale, minscale = INT_MAX;
> +	int i, j;
> +	u32 remainder;
> +
> +	scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC,
> +			&remainder);
> +	if (remainder)
> +		scale_needed++;
> +
> +	for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++)
> +		for (j = 0; j <= SPI_CTAR_SCALE_BITS; j++) {
> +			scale = pscale_tbl[i] * (2 << j);
> +			if (scale >= scale_needed) {
> +				if (scale < minscale) {
> +					minscale = scale;
> +					*psc = i;
> +					*sc = j;
> +				}
> +				break;
> +			}
> +		}
> +
> +	if (minscale == INT_MAX) {
> +		pr_warn("Cannot find correct scale values for %dns delay at clkrate
> %ld, using max prescaler value",
> +			delay_ns, clkrate);
> +		*psc = ARRAY_SIZE(pscale_tbl) - 1;
> +		*sc = SPI_CTAR_SCALE_BITS;
> +	}
> +}
> +
>  static int dspi_transfer_write(struct fsl_dspi *dspi)
>  {
>  	int tx_count = 0;
> @@ -352,7 +390,8 @@ static int dspi_setup(struct spi_device *spi)
>  {
>  	struct chip_data *chip;
>  	struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
> -	unsigned char br = 0, pbr = 0, fmsz = 0;
> +	unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0;
> +	unsigned char pasc = 0, asc = 0, fmsz = 0;
>  
>  	if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) {
>  		fmsz = spi->bits_per_word - 1;
> @@ -377,10 +416,20 @@ static int dspi_setup(struct spi_device *spi)
>  	hz_to_spi_baud(&pbr, &br,
>  			spi->max_speed_hz, clk_get_rate(dspi->clk));
>  
> +	/* Set PCS to SCK delay scale values for 50ns delay*/
> +	ns_delay_scale(&pcssck, &cssck, 50, clk_get_rate(dspi->clk));
> +
> +	/* Set After SCK delay scale values for 50ns delay*/
> +	ns_delay_scale(&pasc, &asc, 50, clk_get_rate(dspi->clk));
> +

This functions calls clk_get_rate three times, can you add a local
variable for it?

>  	chip->ctar_val =  SPI_CTAR_FMSZ(fmsz)
>  		| SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
>  		| SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
>  		| SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
> +		| SPI_CTAR_PCSSCK(pcssck)
> +		| SPI_CTAR_CSSCK(cssck)
> +		| SPI_CTAR_PASC(pasc)
> +		| SPI_CTAR_ASC(asc)
>  		| SPI_CTAR_PBR(pbr)
>  		| SPI_CTAR_BR(br);

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 1/2] spi: fsl-dspi: Fix clock rate scale values
  2015-03-30 17:49   ` Aaron Brice
  (?)
@ 2015-03-31 11:13   ` Mark Brown
  -1 siblings, 0 replies; 9+ messages in thread
From: Mark Brown @ 2015-03-31 11:13 UTC (permalink / raw)
  To: Aaron Brice; +Cc: linux-spi, linux-kernel, stefan

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

On Mon, Mar 30, 2015 at 10:49:15AM -0700, Aaron Brice wrote:
> Previous algorithm had an outer loop with the values {2,3,5,7} and an
> inner loop with {2,4,6,8,16,32,...,32768}, and would pick the first
> value over the required scaling value (where the total scale was the two
> numbers multiplied).

Applied, thanks.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

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

* Re: [PATCH v2 2/2] spi: fsl-dspi: Add ~50ns delay between cs and sck
@ 2015-03-31 19:14       ` Aaron Brice
  0 siblings, 0 replies; 9+ messages in thread
From: Aaron Brice @ 2015-03-31 19:14 UTC (permalink / raw)
  To: Stefan Agner, broonie; +Cc: linux-spi, linux-kernel

On 03/30/2015 03:13 PM, Stefan Agner wrote:
> Hi Aaron,
>
> Thanks for the fixes! Some comments below:
>

Thanks for the review!

> On 2015-03-30 19:49, Aaron Brice wrote:
>> Add delay between chip select and clock signals, before clock starts and
>> after clock stops.
>
> This 50ns are specifc to the SPI slave at hand (SRAM) is this correct?
> If yes, this would probably need new slave properties. I found a TI
> controller which also supports such properties:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2014-September/285761.html
>

Thanks for the link.  Those properties didn't make it into the kernel, 
Mark said the chip select delays were covered by "the standard delays" 
but I'm not sure what that means?

The minimum 50ns was specified in the SRAM datasheet, but I haven't 
worked with a lot of SPI devices, I don't know if this varies widely or 
if it's more or less standard?

I hard-coded this based on spi-bitbang having a hard-coded ndelay(100) 
after chipselect, although there is a FIXME comment above it..  Should I 
add this as a standard spi-bus slave node binding and update spi-bitbang 
also, or just fsl-dspi?

>>
>> Signed-off-by: Aaron Brice <aaron.brice@datasoft.com>
>> ---
>>   drivers/spi/spi-fsl-dspi.c | 53 ++++++++++++++++++++++++++++++++++++++++++++--
>>   1 file changed, 51 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
>> index 96cac87..41284cc 100644
>> --- a/drivers/spi/spi-fsl-dspi.c
>> +++ b/drivers/spi/spi-fsl-dspi.c
>> @@ -20,6 +20,7 @@
>>   #include <linux/interrupt.h>
>>   #include <linux/io.h>
>>   #include <linux/kernel.h>
>> +#include <linux/math64.h>
>>   #include <linux/module.h>
>>   #include <linux/of.h>
>>   #include <linux/of_device.h>
>> @@ -51,7 +52,7 @@
>>   #define SPI_CTAR_CPOL(x)	((x) << 26)
>>   #define SPI_CTAR_CPHA(x)	((x) << 25)
>>   #define SPI_CTAR_LSBFE(x)	((x) << 24)
>> -#define SPI_CTAR_PCSSCR(x)	(((x) & 0x00000003) << 22)
>> +#define SPI_CTAR_PCSSCK(x)	(((x) & 0x00000003) << 22)
>>   #define SPI_CTAR_PASC(x)	(((x) & 0x00000003) << 20)
>>   #define SPI_CTAR_PDT(x)	(((x) & 0x00000003) << 18)
>>   #define SPI_CTAR_PBR(x)	(((x) & 0x00000003) << 16)
>> @@ -59,6 +60,7 @@
>>   #define SPI_CTAR_ASC(x)	(((x) & 0x0000000f) << 8)
>>   #define SPI_CTAR_DT(x)		(((x) & 0x0000000f) << 4)
>>   #define SPI_CTAR_BR(x)		((x) & 0x0000000f)
>> +#define SPI_CTAR_SCALE_BITS	0xf
>>
>>   #define SPI_CTAR0_SLAVE	0x0c
>>
>> @@ -99,6 +101,8 @@
>>   #define SPI_CS_ASSERT		0x02
>>   #define SPI_CS_DROP		0x04
>>
>> +#define NSEC_PER_SEC		1000000000L
>> +
>
> Avoid redefine this, should be available from headers (e.g. time.h)
>

Ok.

>>   struct chip_data {
>>   	u32 mcr_val;
>>   	u32 ctar_val;
>> @@ -174,6 +178,40 @@ static void hz_to_spi_baud(char *pbr, char *br,
>> int speed_hz,
>>   	}
>>   }
>>
>> +static void ns_delay_scale(char *psc, char *sc, int delay_ns,
>> +		unsigned long clkrate)
>> +{
>> +	int pscale_tbl[4] = {1, 3, 5, 7};
>> +	int scale_needed, scale, minscale = INT_MAX;
>> +	int i, j;
>> +	u32 remainder;
>> +
>> +	scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC,
>> +			&remainder);
>> +	if (remainder)
>> +		scale_needed++;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++)
>> +		for (j = 0; j <= SPI_CTAR_SCALE_BITS; j++) {
>> +			scale = pscale_tbl[i] * (2 << j);
>> +			if (scale >= scale_needed) {
>> +				if (scale < minscale) {
>> +					minscale = scale;
>> +					*psc = i;
>> +					*sc = j;
>> +				}
>> +				break;
>> +			}
>> +		}
>> +
>> +	if (minscale == INT_MAX) {
>> +		pr_warn("Cannot find correct scale values for %dns delay at clkrate
>> %ld, using max prescaler value",
>> +			delay_ns, clkrate);
>> +		*psc = ARRAY_SIZE(pscale_tbl) - 1;
>> +		*sc = SPI_CTAR_SCALE_BITS;
>> +	}
>> +}
>> +
>>   static int dspi_transfer_write(struct fsl_dspi *dspi)
>>   {
>>   	int tx_count = 0;
>> @@ -352,7 +390,8 @@ static int dspi_setup(struct spi_device *spi)
>>   {
>>   	struct chip_data *chip;
>>   	struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
>> -	unsigned char br = 0, pbr = 0, fmsz = 0;
>> +	unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0;
>> +	unsigned char pasc = 0, asc = 0, fmsz = 0;
>>
>>   	if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) {
>>   		fmsz = spi->bits_per_word - 1;
>> @@ -377,10 +416,20 @@ static int dspi_setup(struct spi_device *spi)
>>   	hz_to_spi_baud(&pbr, &br,
>>   			spi->max_speed_hz, clk_get_rate(dspi->clk));
>>
>> +	/* Set PCS to SCK delay scale values for 50ns delay*/
>> +	ns_delay_scale(&pcssck, &cssck, 50, clk_get_rate(dspi->clk));
>> +
>> +	/* Set After SCK delay scale values for 50ns delay*/
>> +	ns_delay_scale(&pasc, &asc, 50, clk_get_rate(dspi->clk));
>> +
>
> This functions calls clk_get_rate three times, can you add a local
> variable for it?
>

Ok.

>>   	chip->ctar_val =  SPI_CTAR_FMSZ(fmsz)
>>   		| SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
>>   		| SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
>>   		| SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
>> +		| SPI_CTAR_PCSSCK(pcssck)
>> +		| SPI_CTAR_CSSCK(cssck)
>> +		| SPI_CTAR_PASC(pasc)
>> +		| SPI_CTAR_ASC(asc)
>>   		| SPI_CTAR_PBR(pbr)
>>   		| SPI_CTAR_BR(br);
>


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

* Re: [PATCH v2 2/2] spi: fsl-dspi: Add ~50ns delay between cs and sck
@ 2015-03-31 19:14       ` Aaron Brice
  0 siblings, 0 replies; 9+ messages in thread
From: Aaron Brice @ 2015-03-31 19:14 UTC (permalink / raw)
  To: Stefan Agner, broonie-DgEjT+Ai2ygdnm+yROfE0A
  Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA

On 03/30/2015 03:13 PM, Stefan Agner wrote:
> Hi Aaron,
>
> Thanks for the fixes! Some comments below:
>

Thanks for the review!

> On 2015-03-30 19:49, Aaron Brice wrote:
>> Add delay between chip select and clock signals, before clock starts and
>> after clock stops.
>
> This 50ns are specifc to the SPI slave at hand (SRAM) is this correct?
> If yes, this would probably need new slave properties. I found a TI
> controller which also supports such properties:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2014-September/285761.html
>

Thanks for the link.  Those properties didn't make it into the kernel, 
Mark said the chip select delays were covered by "the standard delays" 
but I'm not sure what that means?

The minimum 50ns was specified in the SRAM datasheet, but I haven't 
worked with a lot of SPI devices, I don't know if this varies widely or 
if it's more or less standard?

I hard-coded this based on spi-bitbang having a hard-coded ndelay(100) 
after chipselect, although there is a FIXME comment above it..  Should I 
add this as a standard spi-bus slave node binding and update spi-bitbang 
also, or just fsl-dspi?

>>
>> Signed-off-by: Aaron Brice <aaron.brice-vSOi0k5x9wFWk0Htik3J/w@public.gmane.org>
>> ---
>>   drivers/spi/spi-fsl-dspi.c | 53 ++++++++++++++++++++++++++++++++++++++++++++--
>>   1 file changed, 51 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
>> index 96cac87..41284cc 100644
>> --- a/drivers/spi/spi-fsl-dspi.c
>> +++ b/drivers/spi/spi-fsl-dspi.c
>> @@ -20,6 +20,7 @@
>>   #include <linux/interrupt.h>
>>   #include <linux/io.h>
>>   #include <linux/kernel.h>
>> +#include <linux/math64.h>
>>   #include <linux/module.h>
>>   #include <linux/of.h>
>>   #include <linux/of_device.h>
>> @@ -51,7 +52,7 @@
>>   #define SPI_CTAR_CPOL(x)	((x) << 26)
>>   #define SPI_CTAR_CPHA(x)	((x) << 25)
>>   #define SPI_CTAR_LSBFE(x)	((x) << 24)
>> -#define SPI_CTAR_PCSSCR(x)	(((x) & 0x00000003) << 22)
>> +#define SPI_CTAR_PCSSCK(x)	(((x) & 0x00000003) << 22)
>>   #define SPI_CTAR_PASC(x)	(((x) & 0x00000003) << 20)
>>   #define SPI_CTAR_PDT(x)	(((x) & 0x00000003) << 18)
>>   #define SPI_CTAR_PBR(x)	(((x) & 0x00000003) << 16)
>> @@ -59,6 +60,7 @@
>>   #define SPI_CTAR_ASC(x)	(((x) & 0x0000000f) << 8)
>>   #define SPI_CTAR_DT(x)		(((x) & 0x0000000f) << 4)
>>   #define SPI_CTAR_BR(x)		((x) & 0x0000000f)
>> +#define SPI_CTAR_SCALE_BITS	0xf
>>
>>   #define SPI_CTAR0_SLAVE	0x0c
>>
>> @@ -99,6 +101,8 @@
>>   #define SPI_CS_ASSERT		0x02
>>   #define SPI_CS_DROP		0x04
>>
>> +#define NSEC_PER_SEC		1000000000L
>> +
>
> Avoid redefine this, should be available from headers (e.g. time.h)
>

Ok.

>>   struct chip_data {
>>   	u32 mcr_val;
>>   	u32 ctar_val;
>> @@ -174,6 +178,40 @@ static void hz_to_spi_baud(char *pbr, char *br,
>> int speed_hz,
>>   	}
>>   }
>>
>> +static void ns_delay_scale(char *psc, char *sc, int delay_ns,
>> +		unsigned long clkrate)
>> +{
>> +	int pscale_tbl[4] = {1, 3, 5, 7};
>> +	int scale_needed, scale, minscale = INT_MAX;
>> +	int i, j;
>> +	u32 remainder;
>> +
>> +	scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC,
>> +			&remainder);
>> +	if (remainder)
>> +		scale_needed++;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++)
>> +		for (j = 0; j <= SPI_CTAR_SCALE_BITS; j++) {
>> +			scale = pscale_tbl[i] * (2 << j);
>> +			if (scale >= scale_needed) {
>> +				if (scale < minscale) {
>> +					minscale = scale;
>> +					*psc = i;
>> +					*sc = j;
>> +				}
>> +				break;
>> +			}
>> +		}
>> +
>> +	if (minscale == INT_MAX) {
>> +		pr_warn("Cannot find correct scale values for %dns delay at clkrate
>> %ld, using max prescaler value",
>> +			delay_ns, clkrate);
>> +		*psc = ARRAY_SIZE(pscale_tbl) - 1;
>> +		*sc = SPI_CTAR_SCALE_BITS;
>> +	}
>> +}
>> +
>>   static int dspi_transfer_write(struct fsl_dspi *dspi)
>>   {
>>   	int tx_count = 0;
>> @@ -352,7 +390,8 @@ static int dspi_setup(struct spi_device *spi)
>>   {
>>   	struct chip_data *chip;
>>   	struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
>> -	unsigned char br = 0, pbr = 0, fmsz = 0;
>> +	unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0;
>> +	unsigned char pasc = 0, asc = 0, fmsz = 0;
>>
>>   	if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) {
>>   		fmsz = spi->bits_per_word - 1;
>> @@ -377,10 +416,20 @@ static int dspi_setup(struct spi_device *spi)
>>   	hz_to_spi_baud(&pbr, &br,
>>   			spi->max_speed_hz, clk_get_rate(dspi->clk));
>>
>> +	/* Set PCS to SCK delay scale values for 50ns delay*/
>> +	ns_delay_scale(&pcssck, &cssck, 50, clk_get_rate(dspi->clk));
>> +
>> +	/* Set After SCK delay scale values for 50ns delay*/
>> +	ns_delay_scale(&pasc, &asc, 50, clk_get_rate(dspi->clk));
>> +
>
> This functions calls clk_get_rate three times, can you add a local
> variable for it?
>

Ok.

>>   	chip->ctar_val =  SPI_CTAR_FMSZ(fmsz)
>>   		| SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
>>   		| SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
>>   		| SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
>> +		| SPI_CTAR_PCSSCK(pcssck)
>> +		| SPI_CTAR_CSSCK(cssck)
>> +		| SPI_CTAR_PASC(pasc)
>> +		| SPI_CTAR_ASC(asc)
>>   		| SPI_CTAR_PBR(pbr)
>>   		| SPI_CTAR_BR(br);
>

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2015-03-31 19:21 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-30 17:49 [PATCH v2 0/2] spi: fsl-dspi (vf610) clock fixes Aaron Brice
2015-03-30 17:49 ` [PATCH v2 1/2] spi: fsl-dspi: Fix clock rate scale values Aaron Brice
2015-03-30 17:49   ` Aaron Brice
2015-03-31 11:13   ` Mark Brown
2015-03-30 17:49 ` [PATCH v2 2/2] spi: fsl-dspi: Add ~50ns delay between cs and sck Aaron Brice
2015-03-30 22:13   ` Stefan Agner
2015-03-30 22:13     ` Stefan Agner
2015-03-31 19:14     ` Aaron Brice
2015-03-31 19:14       ` Aaron Brice

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