aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorAaron Brice <aaron.brice@datasoft.com>2015-04-03 16:39:31 -0400
committerMark Brown <broonie@kernel.org>2015-04-06 13:12:25 -0400
commit95bf15f386417f3ba80bb860c1385b1ebfdcdffa (patch)
tree61b3f2885d7c8f8d3a7cbe2c36fd1bd7b001498a /drivers/spi
parentc1c14957afd3026dcbc2e7ca599e6d035c7d8e01 (diff)
spi: fsl-dspi: Add ~50ns delay between cs and sck
Add delay between chip select and clock signals, before clock starts and after clock stops. Signed-off-by: Aaron Brice <aaron.brice@datasoft.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-fsl-dspi.c64
1 files changed, 60 insertions, 4 deletions
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 96cac87c9f85..4b6032dd0990 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -20,6 +20,7 @@
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/io.h> 21#include <linux/io.h>
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/math64.h>
23#include <linux/module.h> 24#include <linux/module.h>
24#include <linux/of.h> 25#include <linux/of.h>
25#include <linux/of_device.h> 26#include <linux/of_device.h>
@@ -29,6 +30,7 @@
29#include <linux/sched.h> 30#include <linux/sched.h>
30#include <linux/spi/spi.h> 31#include <linux/spi/spi.h>
31#include <linux/spi/spi_bitbang.h> 32#include <linux/spi/spi_bitbang.h>
33#include <linux/time.h>
32 34
33#define DRIVER_NAME "fsl-dspi" 35#define DRIVER_NAME "fsl-dspi"
34 36
@@ -51,7 +53,7 @@
51#define SPI_CTAR_CPOL(x) ((x) << 26) 53#define SPI_CTAR_CPOL(x) ((x) << 26)
52#define SPI_CTAR_CPHA(x) ((x) << 25) 54#define SPI_CTAR_CPHA(x) ((x) << 25)
53#define SPI_CTAR_LSBFE(x) ((x) << 24) 55#define SPI_CTAR_LSBFE(x) ((x) << 24)
54#define SPI_CTAR_PCSSCR(x) (((x) & 0x00000003) << 22) 56#define SPI_CTAR_PCSSCK(x) (((x) & 0x00000003) << 22)
55#define SPI_CTAR_PASC(x) (((x) & 0x00000003) << 20) 57#define SPI_CTAR_PASC(x) (((x) & 0x00000003) << 20)
56#define SPI_CTAR_PDT(x) (((x) & 0x00000003) << 18) 58#define SPI_CTAR_PDT(x) (((x) & 0x00000003) << 18)
57#define SPI_CTAR_PBR(x) (((x) & 0x00000003) << 16) 59#define SPI_CTAR_PBR(x) (((x) & 0x00000003) << 16)
@@ -59,6 +61,7 @@
59#define SPI_CTAR_ASC(x) (((x) & 0x0000000f) << 8) 61#define SPI_CTAR_ASC(x) (((x) & 0x0000000f) << 8)
60#define SPI_CTAR_DT(x) (((x) & 0x0000000f) << 4) 62#define SPI_CTAR_DT(x) (((x) & 0x0000000f) << 4)
61#define SPI_CTAR_BR(x) ((x) & 0x0000000f) 63#define SPI_CTAR_BR(x) ((x) & 0x0000000f)
64#define SPI_CTAR_SCALE_BITS 0xf
62 65
63#define SPI_CTAR0_SLAVE 0x0c 66#define SPI_CTAR0_SLAVE 0x0c
64 67
@@ -174,6 +177,40 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
174 } 177 }
175} 178}
176 179
180static void ns_delay_scale(char *psc, char *sc, int delay_ns,
181 unsigned long clkrate)
182{
183 int pscale_tbl[4] = {1, 3, 5, 7};
184 int scale_needed, scale, minscale = INT_MAX;
185 int i, j;
186 u32 remainder;
187
188 scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC,
189 &remainder);
190 if (remainder)
191 scale_needed++;
192
193 for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++)
194 for (j = 0; j <= SPI_CTAR_SCALE_BITS; j++) {
195 scale = pscale_tbl[i] * (2 << j);
196 if (scale >= scale_needed) {
197 if (scale < minscale) {
198 minscale = scale;
199 *psc = i;
200 *sc = j;
201 }
202 break;
203 }
204 }
205
206 if (minscale == INT_MAX) {
207 pr_warn("Cannot find correct scale values for %dns delay at clkrate %ld, using max prescaler value",
208 delay_ns, clkrate);
209 *psc = ARRAY_SIZE(pscale_tbl) - 1;
210 *sc = SPI_CTAR_SCALE_BITS;
211 }
212}
213
177static int dspi_transfer_write(struct fsl_dspi *dspi) 214static int dspi_transfer_write(struct fsl_dspi *dspi)
178{ 215{
179 int tx_count = 0; 216 int tx_count = 0;
@@ -352,7 +389,10 @@ static int dspi_setup(struct spi_device *spi)
352{ 389{
353 struct chip_data *chip; 390 struct chip_data *chip;
354 struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); 391 struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
355 unsigned char br = 0, pbr = 0, fmsz = 0; 392 u32 cs_sck_delay = 0, sck_cs_delay = 0;
393 unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0;
394 unsigned char pasc = 0, asc = 0, fmsz = 0;
395 unsigned long clkrate;
356 396
357 if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) { 397 if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) {
358 fmsz = spi->bits_per_word - 1; 398 fmsz = spi->bits_per_word - 1;
@@ -369,18 +409,34 @@ static int dspi_setup(struct spi_device *spi)
369 return -ENOMEM; 409 return -ENOMEM;
370 } 410 }
371 411
412 of_property_read_u32(spi->dev.of_node, "fsl,spi-cs-sck-delay",
413 &cs_sck_delay);
414
415 of_property_read_u32(spi->dev.of_node, "fsl,spi-sck-cs-delay",
416 &sck_cs_delay);
417
372 chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS | 418 chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS |
373 SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF; 419 SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
374 420
375 chip->void_write_data = 0; 421 chip->void_write_data = 0;
376 422
377 hz_to_spi_baud(&pbr, &br, 423 clkrate = clk_get_rate(dspi->clk);
378 spi->max_speed_hz, clk_get_rate(dspi->clk)); 424 hz_to_spi_baud(&pbr, &br, spi->max_speed_hz, clkrate);
425
426 /* Set PCS to SCK delay scale values */
427 ns_delay_scale(&pcssck, &cssck, cs_sck_delay, clkrate);
428
429 /* Set After SCK delay scale values */
430 ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate);
379 431
380 chip->ctar_val = SPI_CTAR_FMSZ(fmsz) 432 chip->ctar_val = SPI_CTAR_FMSZ(fmsz)
381 | SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0) 433 | SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
382 | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0) 434 | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
383 | SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0) 435 | SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
436 | SPI_CTAR_PCSSCK(pcssck)
437 | SPI_CTAR_CSSCK(cssck)
438 | SPI_CTAR_PASC(pasc)
439 | SPI_CTAR_ASC(asc)
384 | SPI_CTAR_PBR(pbr) 440 | SPI_CTAR_PBR(pbr)
385 | SPI_CTAR_BR(br); 441 | SPI_CTAR_BR(br);
386 442