linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/3] spi: fsl-dspi (vf610) clock fixes
@ 2015-04-03 20:39 Aaron Brice
  2015-04-03 20:39 ` [PATCH v3 1/3] spi: fsl-dspi: Fix clock rate scale values Aaron Brice
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Aaron Brice @ 2015-04-03 20:39 UTC (permalink / raw)
  To: broonie; +Cc: linux-spi, linux-kernel, stefan, devicetree

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 v2:
 * Incorporate fixes per Stefen Agner review, namely moved hard-coded 50ns
   delays to device tree properties
 * Fix for baud rate scale value remainders, reported by Andy Shevchenko

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

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

 .../devicetree/bindings/spi/spi-fsl-dspi.txt       |  8 ++
 drivers/spi/spi-fsl-dspi.c                         | 97 ++++++++++++++++++----
 2 files changed, 89 insertions(+), 16 deletions(-)

-- 
2.1.0


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

* [PATCH v3 1/3] spi: fsl-dspi: Fix clock rate scale values
  2015-04-03 20:39 [PATCH v3 0/3] spi: fsl-dspi (vf610) clock fixes Aaron Brice
@ 2015-04-03 20:39 ` Aaron Brice
  2015-04-06 17:11   ` Mark Brown
  2015-04-03 20:39 ` [PATCH v3 2/3] devicetree: spi: fsl-dspi: Add cs-sck delays Aaron Brice
  2015-04-03 20:39 ` [PATCH v3 3/3] spi: fsl-dspi: Add ~50ns delay between cs and sck Aaron Brice
  2 siblings, 1 reply; 7+ messages in thread
From: Aaron Brice @ 2015-04-03 20:39 UTC (permalink / raw)
  To: broonie; +Cc: linux-spi, linux-kernel, stefan, devicetree

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 | 37 +++++++++++++++++++++++--------------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index d1a3924..8213358 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -148,23 +148,32 @@ 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;
+	if (clkrate % speed_hz)
+		scale_needed++;
+
+	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] 7+ messages in thread

* [PATCH v3 2/3] devicetree: spi: fsl-dspi: Add cs-sck delays
  2015-04-03 20:39 [PATCH v3 0/3] spi: fsl-dspi (vf610) clock fixes Aaron Brice
  2015-04-03 20:39 ` [PATCH v3 1/3] spi: fsl-dspi: Fix clock rate scale values Aaron Brice
@ 2015-04-03 20:39 ` Aaron Brice
  2015-04-06 17:12   ` Mark Brown
  2015-04-03 20:39 ` [PATCH v3 3/3] spi: fsl-dspi: Add ~50ns delay between cs and sck Aaron Brice
  2 siblings, 1 reply; 7+ messages in thread
From: Aaron Brice @ 2015-04-03 20:39 UTC (permalink / raw)
  To: broonie; +Cc: linux-spi, linux-kernel, stefan, devicetree

Adding fsl,spi-cs-sck-delay and fsl,spi-sck-cs-delay properties to
support delays before and after starting the clock in a transfer.

Signed-off-by: Aaron Brice <aaron.brice@datasoft.com>
---
 Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
index cbbe16e..70af78a 100644
--- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
@@ -16,6 +16,12 @@ Optional property:
   in big endian mode, otherwise in native mode(same with CPU), for more
   detail please see: Documentation/devicetree/bindings/regmap/regmap.txt.
 
+Optional SPI slave node properties:
+- fsl,spi-cs-sck-delay: a delay in nanoseconds between activating chip
+  select and the start of clock signal, at the start of a transfer.
+- fsl,spi-sck-cs-delay: a delay in nanoseconds between stopping the clock
+  signal and deactivating chip select, at the end of a transfer.
+
 Example:
 
 dspi0@4002c000 {
@@ -43,6 +49,8 @@ dspi0@4002c000 {
 		reg = <0>;
 		linux,modalias = "m25p80";
 		modal = "at26df081a";
+		fsl,spi-cs-sck-delay = <100>;
+		fsl,spi-sck-cs-delay = <50>;
 	};
 };
 
-- 
2.1.0


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

* [PATCH v3 3/3] spi: fsl-dspi: Add ~50ns delay between cs and sck
  2015-04-03 20:39 [PATCH v3 0/3] spi: fsl-dspi (vf610) clock fixes Aaron Brice
  2015-04-03 20:39 ` [PATCH v3 1/3] spi: fsl-dspi: Fix clock rate scale values Aaron Brice
  2015-04-03 20:39 ` [PATCH v3 2/3] devicetree: spi: fsl-dspi: Add cs-sck delays Aaron Brice
@ 2015-04-03 20:39 ` Aaron Brice
  2015-04-06 17:12   ` Mark Brown
  2 siblings, 1 reply; 7+ messages in thread
From: Aaron Brice @ 2015-04-03 20:39 UTC (permalink / raw)
  To: broonie; +Cc: linux-spi, linux-kernel, stefan, devicetree

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 | 64 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 60 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 8213358..5fe54cd 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>
@@ -29,6 +30,7 @@
 #include <linux/sched.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
+#include <linux/time.h>
 
 #define DRIVER_NAME "fsl-dspi"
 
@@ -51,7 +53,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 +61,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
 
@@ -176,6 +179,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;
@@ -354,7 +391,10 @@ 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;
+	u32 cs_sck_delay = 0, sck_cs_delay = 0;
+	unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0;
+	unsigned char pasc = 0, asc = 0, fmsz = 0;
+	unsigned long clkrate;
 
 	if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) {
 		fmsz = spi->bits_per_word - 1;
@@ -371,18 +411,34 @@ static int dspi_setup(struct spi_device *spi)
 			return -ENOMEM;
 	}
 
+	of_property_read_u32(spi->dev.of_node, "fsl,spi-cs-sck-delay",
+			&cs_sck_delay);
+
+	of_property_read_u32(spi->dev.of_node, "fsl,spi-sck-cs-delay",
+			&sck_cs_delay);
+
 	chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS |
 		SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
 
 	chip->void_write_data = 0;
 
-	hz_to_spi_baud(&pbr, &br,
-			spi->max_speed_hz, clk_get_rate(dspi->clk));
+	clkrate = clk_get_rate(dspi->clk);
+	hz_to_spi_baud(&pbr, &br, spi->max_speed_hz, clkrate);
+
+	/* Set PCS to SCK delay scale values */
+	ns_delay_scale(&pcssck, &cssck, cs_sck_delay, clkrate);
+
+	/* Set After SCK delay scale values */
+	ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate);
 
 	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] 7+ messages in thread

* Re: [PATCH v3 1/3] spi: fsl-dspi: Fix clock rate scale values
  2015-04-03 20:39 ` [PATCH v3 1/3] spi: fsl-dspi: Fix clock rate scale values Aaron Brice
@ 2015-04-06 17:11   ` Mark Brown
  0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2015-04-06 17:11 UTC (permalink / raw)
  To: Aaron Brice; +Cc: linux-spi, linux-kernel, stefan, devicetree

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

On Fri, Apr 03, 2015 at 01:39:29PM -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] 7+ messages in thread

* Re: [PATCH v3 2/3] devicetree: spi: fsl-dspi: Add cs-sck delays
  2015-04-03 20:39 ` [PATCH v3 2/3] devicetree: spi: fsl-dspi: Add cs-sck delays Aaron Brice
@ 2015-04-06 17:12   ` Mark Brown
  0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2015-04-06 17:12 UTC (permalink / raw)
  To: Aaron Brice; +Cc: linux-spi, linux-kernel, stefan, devicetree

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

On Fri, Apr 03, 2015 at 01:39:30PM -0700, Aaron Brice wrote:
> Adding fsl,spi-cs-sck-delay and fsl,spi-sck-cs-delay properties to
> support delays before and after starting the clock in a transfer.

Applied, please use subject lines matching the style for the subsystem.

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

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

* Re: [PATCH v3 3/3] spi: fsl-dspi: Add ~50ns delay between cs and sck
  2015-04-03 20:39 ` [PATCH v3 3/3] spi: fsl-dspi: Add ~50ns delay between cs and sck Aaron Brice
@ 2015-04-06 17:12   ` Mark Brown
  0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2015-04-06 17:12 UTC (permalink / raw)
  To: Aaron Brice; +Cc: linux-spi, linux-kernel, stefan, devicetree

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

On Fri, Apr 03, 2015 at 01:39:31PM -0700, Aaron Brice wrote:
> Add delay between chip select and clock signals, before clock starts and
> after clock stops.

Applied, thanks.

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

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

end of thread, other threads:[~2015-04-06 17:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-03 20:39 [PATCH v3 0/3] spi: fsl-dspi (vf610) clock fixes Aaron Brice
2015-04-03 20:39 ` [PATCH v3 1/3] spi: fsl-dspi: Fix clock rate scale values Aaron Brice
2015-04-06 17:11   ` Mark Brown
2015-04-03 20:39 ` [PATCH v3 2/3] devicetree: spi: fsl-dspi: Add cs-sck delays Aaron Brice
2015-04-06 17:12   ` Mark Brown
2015-04-03 20:39 ` [PATCH v3 3/3] spi: fsl-dspi: Add ~50ns delay between cs and sck Aaron Brice
2015-04-06 17:12   ` Mark Brown

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).