diff options
Diffstat (limited to 'drivers/spi/spi-fsl-dspi.c')
-rw-r--r-- | drivers/spi/spi-fsl-dspi.c | 97 |
1 files changed, 81 insertions, 16 deletions
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index d1a39249704a..5fe54cda309f 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 | ||
@@ -148,23 +151,66 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, | |||
148 | 16, 32, 64, 128, | 151 | 16, 32, 64, 128, |
149 | 256, 512, 1024, 2048, | 152 | 256, 512, 1024, 2048, |
150 | 4096, 8192, 16384, 32768 }; | 153 | 4096, 8192, 16384, 32768 }; |
151 | int temp, i = 0, j = 0; | 154 | int scale_needed, scale, minscale = INT_MAX; |
155 | int i, j; | ||
156 | |||
157 | scale_needed = clkrate / speed_hz; | ||
158 | if (clkrate % speed_hz) | ||
159 | scale_needed++; | ||
160 | |||
161 | for (i = 0; i < ARRAY_SIZE(brs); i++) | ||
162 | for (j = 0; j < ARRAY_SIZE(pbr_tbl); j++) { | ||
163 | scale = brs[i] * pbr_tbl[j]; | ||
164 | if (scale >= scale_needed) { | ||
165 | if (scale < minscale) { | ||
166 | minscale = scale; | ||
167 | *br = i; | ||
168 | *pbr = j; | ||
169 | } | ||
170 | break; | ||
171 | } | ||
172 | } | ||
152 | 173 | ||
153 | temp = clkrate / 2 / speed_hz; | 174 | if (minscale == INT_MAX) { |
175 | pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld, we use the max prescaler value.\n", | ||
176 | speed_hz, clkrate); | ||
177 | *pbr = ARRAY_SIZE(pbr_tbl) - 1; | ||
178 | *br = ARRAY_SIZE(brs) - 1; | ||
179 | } | ||
180 | } | ||
154 | 181 | ||
155 | for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++) | 182 | static void ns_delay_scale(char *psc, char *sc, int delay_ns, |
156 | for (j = 0; j < ARRAY_SIZE(brs); j++) { | 183 | unsigned long clkrate) |
157 | if (pbr_tbl[i] * brs[j] >= temp) { | 184 | { |
158 | *pbr = i; | 185 | int pscale_tbl[4] = {1, 3, 5, 7}; |
159 | *br = j; | 186 | int scale_needed, scale, minscale = INT_MAX; |
160 | return; | 187 | int i, j; |
188 | u32 remainder; | ||
189 | |||
190 | scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC, | ||
191 | &remainder); | ||
192 | if (remainder) | ||
193 | scale_needed++; | ||
194 | |||
195 | for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++) | ||
196 | for (j = 0; j <= SPI_CTAR_SCALE_BITS; j++) { | ||
197 | scale = pscale_tbl[i] * (2 << j); | ||
198 | if (scale >= scale_needed) { | ||
199 | if (scale < minscale) { | ||
200 | minscale = scale; | ||
201 | *psc = i; | ||
202 | *sc = j; | ||
203 | } | ||
204 | break; | ||
161 | } | 205 | } |
162 | } | 206 | } |
163 | 207 | ||
164 | pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld\ | 208 | if (minscale == INT_MAX) { |
165 | ,we use the max prescaler value.\n", speed_hz, clkrate); | 209 | pr_warn("Cannot find correct scale values for %dns delay at clkrate %ld, using max prescaler value", |
166 | *pbr = ARRAY_SIZE(pbr_tbl) - 1; | 210 | delay_ns, clkrate); |
167 | *br = ARRAY_SIZE(brs) - 1; | 211 | *psc = ARRAY_SIZE(pscale_tbl) - 1; |
212 | *sc = SPI_CTAR_SCALE_BITS; | ||
213 | } | ||
168 | } | 214 | } |
169 | 215 | ||
170 | static int dspi_transfer_write(struct fsl_dspi *dspi) | 216 | static int dspi_transfer_write(struct fsl_dspi *dspi) |
@@ -345,7 +391,10 @@ static int dspi_setup(struct spi_device *spi) | |||
345 | { | 391 | { |
346 | struct chip_data *chip; | 392 | struct chip_data *chip; |
347 | struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); | 393 | struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); |
348 | unsigned char br = 0, pbr = 0, fmsz = 0; | 394 | u32 cs_sck_delay = 0, sck_cs_delay = 0; |
395 | unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0; | ||
396 | unsigned char pasc = 0, asc = 0, fmsz = 0; | ||
397 | unsigned long clkrate; | ||
349 | 398 | ||
350 | if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) { | 399 | if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) { |
351 | fmsz = spi->bits_per_word - 1; | 400 | fmsz = spi->bits_per_word - 1; |
@@ -362,18 +411,34 @@ static int dspi_setup(struct spi_device *spi) | |||
362 | return -ENOMEM; | 411 | return -ENOMEM; |
363 | } | 412 | } |
364 | 413 | ||
414 | of_property_read_u32(spi->dev.of_node, "fsl,spi-cs-sck-delay", | ||
415 | &cs_sck_delay); | ||
416 | |||
417 | of_property_read_u32(spi->dev.of_node, "fsl,spi-sck-cs-delay", | ||
418 | &sck_cs_delay); | ||
419 | |||
365 | chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS | | 420 | chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS | |
366 | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF; | 421 | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF; |
367 | 422 | ||
368 | chip->void_write_data = 0; | 423 | chip->void_write_data = 0; |
369 | 424 | ||
370 | hz_to_spi_baud(&pbr, &br, | 425 | clkrate = clk_get_rate(dspi->clk); |
371 | spi->max_speed_hz, clk_get_rate(dspi->clk)); | 426 | hz_to_spi_baud(&pbr, &br, spi->max_speed_hz, clkrate); |
427 | |||
428 | /* Set PCS to SCK delay scale values */ | ||
429 | ns_delay_scale(&pcssck, &cssck, cs_sck_delay, clkrate); | ||
430 | |||
431 | /* Set After SCK delay scale values */ | ||
432 | ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate); | ||
372 | 433 | ||
373 | chip->ctar_val = SPI_CTAR_FMSZ(fmsz) | 434 | chip->ctar_val = SPI_CTAR_FMSZ(fmsz) |
374 | | SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0) | 435 | | SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0) |
375 | | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0) | 436 | | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0) |
376 | | SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0) | 437 | | SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0) |
438 | | SPI_CTAR_PCSSCK(pcssck) | ||
439 | | SPI_CTAR_CSSCK(cssck) | ||
440 | | SPI_CTAR_PASC(pasc) | ||
441 | | SPI_CTAR_ASC(asc) | ||
377 | | SPI_CTAR_PBR(pbr) | 442 | | SPI_CTAR_PBR(pbr) |
378 | | SPI_CTAR_BR(br); | 443 | | SPI_CTAR_BR(br); |
379 | 444 | ||