diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-13 14:38:27 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-13 14:38:27 -0500 |
commit | 50ae833e471fe1a1a906a0342bdaa690e69fcc19 (patch) | |
tree | 15f4871eff7574f5677ce80a4faa2bf865d733d8 /drivers/spi | |
parent | ac53b2e053fffc74372da94e734b92f37e70d32c (diff) | |
parent | cabeea980879c2c701b0bd03f145c9f7dae17a63 (diff) |
Merge tag 'spi-v4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
"A quiet release for SPI, not even many driver updates:
- Add a dummy loopback driver for use in exercising framework
features during development.
- Move the test utilities to tools/ and add support for transferring
data to and from a file instead of stdin and stdout to spidev_test.
- Support for Mediatek MT2701 and Renesas AG5 deices"
* tag 'spi-v4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (69 commits)
spi: loopback: fix typo in MODULE_PARM_DESC
spi: sun4i: Prevent chip-select from being activated twice before a transfer
spi: loopback-test: spi_check_rx_ranges can get always done
spi: loopback-test: rename method spi_test_fill_tx to spi_test_fill_pattern
spi: loopback-test: write rx pattern also when running without tx_buf
spi: fsl-espi: expose maximum transfer size limit
spi: expose master transfer size limitation.
spi: zynq: use to_platform_device()
spi: cadence: use to_platform_device()
spi: mediatek: Add spi support for mt2701 IC
spi: mediatek: merge all identical compat to mtk_common_compat
spi: mtk: Add bindings for mediatek MT2701 soc platform
spi: mediatek: Prevent overflows in FIFO transfers
spi: s3c64xx: Remove unused platform_device_id entries
spi: use to_spi_device
spi: dw: Use SPI_TMOD_TR rather than magic const 0 to set tmode
spi: imx: defer spi initialization, if DMA engine is
spi: imx: return error from dma channel request
spi: imx: enable loopback only for ECSPI controller family
spi: imx: fix loopback mode setup after controller reset
...
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/Kconfig | 11 | ||||
-rw-r--r-- | drivers/spi/Makefile | 1 | ||||
-rw-r--r-- | drivers/spi/spi-bcm63xx.c | 7 | ||||
-rw-r--r-- | drivers/spi/spi-butterfly.c | 30 | ||||
-rw-r--r-- | drivers/spi/spi-cadence.c | 6 | ||||
-rw-r--r-- | drivers/spi/spi-davinci.c | 17 | ||||
-rw-r--r-- | drivers/spi/spi-dw-mid.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-dw.c | 2 | ||||
-rw-r--r-- | drivers/spi/spi-dw.h | 2 | ||||
-rw-r--r-- | drivers/spi/spi-fsl-espi.c | 6 | ||||
-rw-r--r-- | drivers/spi/spi-imx.c | 101 | ||||
-rw-r--r-- | drivers/spi/spi-lm70llp.c | 43 | ||||
-rw-r--r-- | drivers/spi/spi-loopback-test.c | 1005 | ||||
-rw-r--r-- | drivers/spi/spi-mt65xx.c | 64 | ||||
-rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 31 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx.c | 3 | ||||
-rw-r--r-- | drivers/spi/spi-s3c64xx.c | 33 | ||||
-rw-r--r-- | drivers/spi/spi-sun4i.c | 14 | ||||
-rw-r--r-- | drivers/spi/spi-sun6i.c | 8 | ||||
-rw-r--r-- | drivers/spi/spi-test.h | 136 | ||||
-rw-r--r-- | drivers/spi/spi-zynqmp-gqspi.c | 8 | ||||
-rw-r--r-- | drivers/spi/spi.c | 32 | ||||
-rw-r--r-- | drivers/spi/spidev.c | 2 |
23 files changed, 1387 insertions, 177 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 8b9c2a38d1cc..77064160dd76 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -585,7 +585,7 @@ config SPI_TEGRA20_SLINK | |||
585 | 585 | ||
586 | config SPI_TOPCLIFF_PCH | 586 | config SPI_TOPCLIFF_PCH |
587 | tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) SPI" | 587 | tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) SPI" |
588 | depends on PCI && (X86_32 || COMPILE_TEST) | 588 | depends on PCI && (X86_32 || MIPS || COMPILE_TEST) |
589 | help | 589 | help |
590 | SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus | 590 | SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus |
591 | used in some x86 embedded processors. | 591 | used in some x86 embedded processors. |
@@ -689,6 +689,15 @@ config SPI_SPIDEV | |||
689 | Note that this application programming interface is EXPERIMENTAL | 689 | Note that this application programming interface is EXPERIMENTAL |
690 | and hence SUBJECT TO CHANGE WITHOUT NOTICE while it stabilizes. | 690 | and hence SUBJECT TO CHANGE WITHOUT NOTICE while it stabilizes. |
691 | 691 | ||
692 | config SPI_LOOPBACK_TEST | ||
693 | tristate "spi loopback test framework support" | ||
694 | depends on m | ||
695 | help | ||
696 | This enables the SPI loopback testing framework driver | ||
697 | |||
698 | primarily used for development of spi_master drivers | ||
699 | and to detect regressions | ||
700 | |||
692 | config SPI_TLE62X0 | 701 | config SPI_TLE62X0 |
693 | tristate "Infineon TLE62X0 (for power switching)" | 702 | tristate "Infineon TLE62X0 (for power switching)" |
694 | depends on SYSFS | 703 | depends on SYSFS |
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 31fb7fb2a0b6..8991ffce6e12 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
@@ -8,6 +8,7 @@ ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG | |||
8 | # config declarations into driver model code | 8 | # config declarations into driver model code |
9 | obj-$(CONFIG_SPI_MASTER) += spi.o | 9 | obj-$(CONFIG_SPI_MASTER) += spi.o |
10 | obj-$(CONFIG_SPI_SPIDEV) += spidev.o | 10 | obj-$(CONFIG_SPI_SPIDEV) += spidev.o |
11 | obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o | ||
11 | 12 | ||
12 | # SPI master controller drivers (bus) | 13 | # SPI master controller drivers (bus) |
13 | obj-$(CONFIG_SPI_ALTERA) += spi-altera.o | 14 | obj-$(CONFIG_SPI_ALTERA) += spi-altera.o |
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index bf9a610e5b89..fee747030ee6 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c | |||
@@ -207,6 +207,9 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi, | |||
207 | u8 clk_cfg, reg; | 207 | u8 clk_cfg, reg; |
208 | int i; | 208 | int i; |
209 | 209 | ||
210 | /* Default to lowest clock configuration */ | ||
211 | clk_cfg = SPI_CLK_0_391MHZ; | ||
212 | |||
210 | /* Find the closest clock configuration */ | 213 | /* Find the closest clock configuration */ |
211 | for (i = 0; i < SPI_CLK_MASK; i++) { | 214 | for (i = 0; i < SPI_CLK_MASK; i++) { |
212 | if (t->speed_hz >= bcm63xx_spi_freq_table[i][0]) { | 215 | if (t->speed_hz >= bcm63xx_spi_freq_table[i][0]) { |
@@ -215,10 +218,6 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi, | |||
215 | } | 218 | } |
216 | } | 219 | } |
217 | 220 | ||
218 | /* No matching configuration found, default to lowest */ | ||
219 | if (i == SPI_CLK_MASK) | ||
220 | clk_cfg = SPI_CLK_0_391MHZ; | ||
221 | |||
222 | /* clear existing clock configuration bits of the register */ | 221 | /* clear existing clock configuration bits of the register */ |
223 | reg = bcm_spi_readb(bs, SPI_CLK_CFG); | 222 | reg = bcm_spi_readb(bs, SPI_CLK_CFG); |
224 | reg &= ~SPI_CLK_MASK; | 223 | reg &= ~SPI_CLK_MASK; |
diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c index 9a95862986c8..22a31e4a1a11 100644 --- a/drivers/spi/spi-butterfly.c +++ b/drivers/spi/spi-butterfly.c | |||
@@ -27,7 +27,6 @@ | |||
27 | 27 | ||
28 | #include <linux/mtd/partitions.h> | 28 | #include <linux/mtd/partitions.h> |
29 | 29 | ||
30 | |||
31 | /* | 30 | /* |
32 | * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card | 31 | * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card |
33 | * with a battery powered AVR microcontroller and lots of goodies. You | 32 | * with a battery powered AVR microcontroller and lots of goodies. You |
@@ -37,7 +36,6 @@ | |||
37 | * and use this custom parallel port cable. | 36 | * and use this custom parallel port cable. |
38 | */ | 37 | */ |
39 | 38 | ||
40 | |||
41 | /* DATA output bits (pins 2..9 == D0..D7) */ | 39 | /* DATA output bits (pins 2..9 == D0..D7) */ |
42 | #define butterfly_nreset (1 << 1) /* pin 3 */ | 40 | #define butterfly_nreset (1 << 1) /* pin 3 */ |
43 | 41 | ||
@@ -52,14 +50,11 @@ | |||
52 | /* CONTROL output bits */ | 50 | /* CONTROL output bits */ |
53 | #define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */ | 51 | #define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */ |
54 | 52 | ||
55 | |||
56 | |||
57 | static inline struct butterfly *spidev_to_pp(struct spi_device *spi) | 53 | static inline struct butterfly *spidev_to_pp(struct spi_device *spi) |
58 | { | 54 | { |
59 | return spi->controller_data; | 55 | return spi->controller_data; |
60 | } | 56 | } |
61 | 57 | ||
62 | |||
63 | struct butterfly { | 58 | struct butterfly { |
64 | /* REVISIT ... for now, this must be first */ | 59 | /* REVISIT ... for now, this must be first */ |
65 | struct spi_bitbang bitbang; | 60 | struct spi_bitbang bitbang; |
@@ -140,7 +135,6 @@ static void butterfly_chipselect(struct spi_device *spi, int value) | |||
140 | parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); | 135 | parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); |
141 | } | 136 | } |
142 | 137 | ||
143 | |||
144 | /* we only needed to implement one mode here, and choose SPI_MODE_0 */ | 138 | /* we only needed to implement one mode here, and choose SPI_MODE_0 */ |
145 | 139 | ||
146 | #define spidelay(X) do { } while (0) | 140 | #define spidelay(X) do { } while (0) |
@@ -149,9 +143,8 @@ static void butterfly_chipselect(struct spi_device *spi, int value) | |||
149 | #include "spi-bitbang-txrx.h" | 143 | #include "spi-bitbang-txrx.h" |
150 | 144 | ||
151 | static u32 | 145 | static u32 |
152 | butterfly_txrx_word_mode0(struct spi_device *spi, | 146 | butterfly_txrx_word_mode0(struct spi_device *spi, unsigned nsecs, u32 word, |
153 | unsigned nsecs, | 147 | u8 bits) |
154 | u32 word, u8 bits) | ||
155 | { | 148 | { |
156 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); | 149 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits); |
157 | } | 150 | } |
@@ -186,7 +179,6 @@ static struct flash_platform_data flash = { | |||
186 | .nr_parts = ARRAY_SIZE(partitions), | 179 | .nr_parts = ARRAY_SIZE(partitions), |
187 | }; | 180 | }; |
188 | 181 | ||
189 | |||
190 | /* REVISIT remove this ugly global and its "only one" limitation */ | 182 | /* REVISIT remove this ugly global and its "only one" limitation */ |
191 | static struct butterfly *butterfly; | 183 | static struct butterfly *butterfly; |
192 | 184 | ||
@@ -197,6 +189,7 @@ static void butterfly_attach(struct parport *p) | |||
197 | struct butterfly *pp; | 189 | struct butterfly *pp; |
198 | struct spi_master *master; | 190 | struct spi_master *master; |
199 | struct device *dev = p->physport->dev; | 191 | struct device *dev = p->physport->dev; |
192 | struct pardev_cb butterfly_cb; | ||
200 | 193 | ||
201 | if (butterfly || !dev) | 194 | if (butterfly || !dev) |
202 | return; | 195 | return; |
@@ -229,9 +222,9 @@ static void butterfly_attach(struct parport *p) | |||
229 | * parport hookup | 222 | * parport hookup |
230 | */ | 223 | */ |
231 | pp->port = p; | 224 | pp->port = p; |
232 | pd = parport_register_device(p, "spi_butterfly", | 225 | memset(&butterfly_cb, 0, sizeof(butterfly_cb)); |
233 | NULL, NULL, NULL, | 226 | butterfly_cb.private = pp; |
234 | 0 /* FLAGS */, pp); | 227 | pd = parport_register_dev_model(p, "spi_butterfly", &butterfly_cb, 0); |
235 | if (!pd) { | 228 | if (!pd) { |
236 | status = -ENOMEM; | 229 | status = -ENOMEM; |
237 | goto clean0; | 230 | goto clean0; |
@@ -262,7 +255,6 @@ static void butterfly_attach(struct parport *p) | |||
262 | parport_write_data(pp->port, pp->lastbyte); | 255 | parport_write_data(pp->port, pp->lastbyte); |
263 | msleep(100); | 256 | msleep(100); |
264 | 257 | ||
265 | |||
266 | /* | 258 | /* |
267 | * Start SPI ... for now, hide that we're two physical busses. | 259 | * Start SPI ... for now, hide that we're two physical busses. |
268 | */ | 260 | */ |
@@ -283,7 +275,7 @@ static void butterfly_attach(struct parport *p) | |||
283 | pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]); | 275 | pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]); |
284 | if (pp->dataflash) | 276 | if (pp->dataflash) |
285 | pr_debug("%s: dataflash at %s\n", p->name, | 277 | pr_debug("%s: dataflash at %s\n", p->name, |
286 | dev_name(&pp->dataflash->dev)); | 278 | dev_name(&pp->dataflash->dev)); |
287 | 279 | ||
288 | pr_info("%s: AVR Butterfly\n", p->name); | 280 | pr_info("%s: AVR Butterfly\n", p->name); |
289 | butterfly = pp; | 281 | butterfly = pp; |
@@ -297,7 +289,7 @@ clean2: | |||
297 | clean1: | 289 | clean1: |
298 | parport_unregister_device(pd); | 290 | parport_unregister_device(pd); |
299 | clean0: | 291 | clean0: |
300 | (void) spi_master_put(pp->bitbang.master); | 292 | spi_master_put(pp->bitbang.master); |
301 | done: | 293 | done: |
302 | pr_debug("%s: butterfly probe, fail %d\n", p->name, status); | 294 | pr_debug("%s: butterfly probe, fail %d\n", p->name, status); |
303 | } | 295 | } |
@@ -325,16 +317,16 @@ static void butterfly_detach(struct parport *p) | |||
325 | parport_release(pp->pd); | 317 | parport_release(pp->pd); |
326 | parport_unregister_device(pp->pd); | 318 | parport_unregister_device(pp->pd); |
327 | 319 | ||
328 | (void) spi_master_put(pp->bitbang.master); | 320 | spi_master_put(pp->bitbang.master); |
329 | } | 321 | } |
330 | 322 | ||
331 | static struct parport_driver butterfly_driver = { | 323 | static struct parport_driver butterfly_driver = { |
332 | .name = "spi_butterfly", | 324 | .name = "spi_butterfly", |
333 | .attach = butterfly_attach, | 325 | .match_port = butterfly_attach, |
334 | .detach = butterfly_detach, | 326 | .detach = butterfly_detach, |
327 | .devmodel = true, | ||
335 | }; | 328 | }; |
336 | 329 | ||
337 | |||
338 | static int __init butterfly_init(void) | 330 | static int __init butterfly_init(void) |
339 | { | 331 | { |
340 | return parport_register_driver(&butterfly_driver); | 332 | return parport_register_driver(&butterfly_driver); |
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 5a6749881ff9..121a4135b540 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c | |||
@@ -617,8 +617,7 @@ static int cdns_spi_remove(struct platform_device *pdev) | |||
617 | */ | 617 | */ |
618 | static int __maybe_unused cdns_spi_suspend(struct device *dev) | 618 | static int __maybe_unused cdns_spi_suspend(struct device *dev) |
619 | { | 619 | { |
620 | struct platform_device *pdev = container_of(dev, | 620 | struct platform_device *pdev = to_platform_device(dev); |
621 | struct platform_device, dev); | ||
622 | struct spi_master *master = platform_get_drvdata(pdev); | 621 | struct spi_master *master = platform_get_drvdata(pdev); |
623 | struct cdns_spi *xspi = spi_master_get_devdata(master); | 622 | struct cdns_spi *xspi = spi_master_get_devdata(master); |
624 | 623 | ||
@@ -641,8 +640,7 @@ static int __maybe_unused cdns_spi_suspend(struct device *dev) | |||
641 | */ | 640 | */ |
642 | static int __maybe_unused cdns_spi_resume(struct device *dev) | 641 | static int __maybe_unused cdns_spi_resume(struct device *dev) |
643 | { | 642 | { |
644 | struct platform_device *pdev = container_of(dev, | 643 | struct platform_device *pdev = to_platform_device(dev); |
645 | struct platform_device, dev); | ||
646 | struct spi_master *master = platform_get_drvdata(pdev); | 644 | struct spi_master *master = platform_get_drvdata(pdev); |
647 | struct cdns_spi *xspi = spi_master_get_devdata(master); | 645 | struct cdns_spi *xspi = spi_master_get_devdata(master); |
648 | int ret = 0; | 646 | int ret = 0; |
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 7d3af3eacf57..fddb7a3be322 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c | |||
@@ -477,33 +477,33 @@ static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status) | |||
477 | struct device *sdev = dspi->bitbang.master->dev.parent; | 477 | struct device *sdev = dspi->bitbang.master->dev.parent; |
478 | 478 | ||
479 | if (int_status & SPIFLG_TIMEOUT_MASK) { | 479 | if (int_status & SPIFLG_TIMEOUT_MASK) { |
480 | dev_dbg(sdev, "SPI Time-out Error\n"); | 480 | dev_err(sdev, "SPI Time-out Error\n"); |
481 | return -ETIMEDOUT; | 481 | return -ETIMEDOUT; |
482 | } | 482 | } |
483 | if (int_status & SPIFLG_DESYNC_MASK) { | 483 | if (int_status & SPIFLG_DESYNC_MASK) { |
484 | dev_dbg(sdev, "SPI Desynchronization Error\n"); | 484 | dev_err(sdev, "SPI Desynchronization Error\n"); |
485 | return -EIO; | 485 | return -EIO; |
486 | } | 486 | } |
487 | if (int_status & SPIFLG_BITERR_MASK) { | 487 | if (int_status & SPIFLG_BITERR_MASK) { |
488 | dev_dbg(sdev, "SPI Bit error\n"); | 488 | dev_err(sdev, "SPI Bit error\n"); |
489 | return -EIO; | 489 | return -EIO; |
490 | } | 490 | } |
491 | 491 | ||
492 | if (dspi->version == SPI_VERSION_2) { | 492 | if (dspi->version == SPI_VERSION_2) { |
493 | if (int_status & SPIFLG_DLEN_ERR_MASK) { | 493 | if (int_status & SPIFLG_DLEN_ERR_MASK) { |
494 | dev_dbg(sdev, "SPI Data Length Error\n"); | 494 | dev_err(sdev, "SPI Data Length Error\n"); |
495 | return -EIO; | 495 | return -EIO; |
496 | } | 496 | } |
497 | if (int_status & SPIFLG_PARERR_MASK) { | 497 | if (int_status & SPIFLG_PARERR_MASK) { |
498 | dev_dbg(sdev, "SPI Parity Error\n"); | 498 | dev_err(sdev, "SPI Parity Error\n"); |
499 | return -EIO; | 499 | return -EIO; |
500 | } | 500 | } |
501 | if (int_status & SPIFLG_OVRRUN_MASK) { | 501 | if (int_status & SPIFLG_OVRRUN_MASK) { |
502 | dev_dbg(sdev, "SPI Data Overrun error\n"); | 502 | dev_err(sdev, "SPI Data Overrun error\n"); |
503 | return -EIO; | 503 | return -EIO; |
504 | } | 504 | } |
505 | if (int_status & SPIFLG_BUF_INIT_ACTIVE_MASK) { | 505 | if (int_status & SPIFLG_BUF_INIT_ACTIVE_MASK) { |
506 | dev_dbg(sdev, "SPI Buffer Init Active\n"); | 506 | dev_err(sdev, "SPI Buffer Init Active\n"); |
507 | return -EBUSY; | 507 | return -EBUSY; |
508 | } | 508 | } |
509 | } | 509 | } |
@@ -703,7 +703,8 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) | |||
703 | 703 | ||
704 | /* Wait for the transfer to complete */ | 704 | /* Wait for the transfer to complete */ |
705 | if (spicfg->io_type != SPI_IO_TYPE_POLL) { | 705 | if (spicfg->io_type != SPI_IO_TYPE_POLL) { |
706 | wait_for_completion_interruptible(&(dspi->done)); | 706 | if (wait_for_completion_timeout(&dspi->done, HZ) == 0) |
707 | errors = SPIFLG_TIMEOUT_MASK; | ||
707 | } else { | 708 | } else { |
708 | while (dspi->rcount > 0 || dspi->wcount > 0) { | 709 | while (dspi->rcount > 0 || dspi->wcount > 0) { |
709 | errors = davinci_spi_process_events(dspi); | 710 | errors = davinci_spi_process_events(dspi); |
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index bb1052e748f2..9185f6c08459 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c | |||
@@ -283,7 +283,7 @@ static void mid_spi_dma_stop(struct dw_spi *dws) | |||
283 | } | 283 | } |
284 | } | 284 | } |
285 | 285 | ||
286 | static struct dw_spi_dma_ops mid_dma_ops = { | 286 | static const struct dw_spi_dma_ops mid_dma_ops = { |
287 | .dma_init = mid_spi_dma_init, | 287 | .dma_init = mid_spi_dma_init, |
288 | .dma_exit = mid_spi_dma_exit, | 288 | .dma_exit = mid_spi_dma_exit, |
289 | .dma_setup = mid_spi_dma_setup, | 289 | .dma_setup = mid_spi_dma_setup, |
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 882cd6618cd5..c09bb745693a 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c | |||
@@ -425,7 +425,7 @@ static int dw_spi_setup(struct spi_device *spi) | |||
425 | chip->type = chip_info->type; | 425 | chip->type = chip_info->type; |
426 | } | 426 | } |
427 | 427 | ||
428 | chip->tmode = 0; /* Tx & Rx */ | 428 | chip->tmode = SPI_TMOD_TR; |
429 | 429 | ||
430 | if (gpio_is_valid(spi->cs_gpio)) { | 430 | if (gpio_is_valid(spi->cs_gpio)) { |
431 | ret = gpio_direction_output(spi->cs_gpio, | 431 | ret = gpio_direction_output(spi->cs_gpio, |
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index 35589a270468..61bc3cbab38d 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h | |||
@@ -130,7 +130,7 @@ struct dw_spi { | |||
130 | struct dma_chan *rxchan; | 130 | struct dma_chan *rxchan; |
131 | unsigned long dma_chan_busy; | 131 | unsigned long dma_chan_busy; |
132 | dma_addr_t dma_addr; /* phy address of the Data register */ | 132 | dma_addr_t dma_addr; /* phy address of the Data register */ |
133 | struct dw_spi_dma_ops *dma_ops; | 133 | const struct dw_spi_dma_ops *dma_ops; |
134 | void *dma_tx; | 134 | void *dma_tx; |
135 | void *dma_rx; | 135 | void *dma_rx; |
136 | 136 | ||
diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index c27124a5ec8e..7fd6a4c009d2 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c | |||
@@ -643,6 +643,11 @@ static int fsl_espi_runtime_resume(struct device *dev) | |||
643 | } | 643 | } |
644 | #endif | 644 | #endif |
645 | 645 | ||
646 | static size_t fsl_espi_max_transfer_size(struct spi_device *spi) | ||
647 | { | ||
648 | return SPCOM_TRANLEN_MAX; | ||
649 | } | ||
650 | |||
646 | static struct spi_master * fsl_espi_probe(struct device *dev, | 651 | static struct spi_master * fsl_espi_probe(struct device *dev, |
647 | struct resource *mem, unsigned int irq) | 652 | struct resource *mem, unsigned int irq) |
648 | { | 653 | { |
@@ -670,6 +675,7 @@ static struct spi_master * fsl_espi_probe(struct device *dev, | |||
670 | master->cleanup = fsl_espi_cleanup; | 675 | master->cleanup = fsl_espi_cleanup; |
671 | master->transfer_one_message = fsl_espi_do_one_msg; | 676 | master->transfer_one_message = fsl_espi_do_one_msg; |
672 | master->auto_runtime_pm = true; | 677 | master->auto_runtime_pm = true; |
678 | master->max_transfer_size = fsl_espi_max_transfer_size; | ||
673 | 679 | ||
674 | mpc8xxx_spi = spi_master_get_devdata(master); | 680 | mpc8xxx_spi = spi_master_get_devdata(master); |
675 | 681 | ||
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 0e5723ab47f0..d98c33cb64f9 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c | |||
@@ -104,9 +104,7 @@ struct spi_imx_data { | |||
104 | unsigned int dma_is_inited; | 104 | unsigned int dma_is_inited; |
105 | unsigned int dma_finished; | 105 | unsigned int dma_finished; |
106 | bool usedma; | 106 | bool usedma; |
107 | u32 rx_wml; | 107 | u32 wml; |
108 | u32 tx_wml; | ||
109 | u32 rxt_wml; | ||
110 | struct completion dma_rx_completion; | 108 | struct completion dma_rx_completion; |
111 | struct completion dma_tx_completion; | 109 | struct completion dma_tx_completion; |
112 | 110 | ||
@@ -124,9 +122,14 @@ static inline int is_imx35_cspi(struct spi_imx_data *d) | |||
124 | return d->devtype_data->devtype == IMX35_CSPI; | 122 | return d->devtype_data->devtype == IMX35_CSPI; |
125 | } | 123 | } |
126 | 124 | ||
125 | static inline int is_imx51_ecspi(struct spi_imx_data *d) | ||
126 | { | ||
127 | return d->devtype_data->devtype == IMX51_ECSPI; | ||
128 | } | ||
129 | |||
127 | static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d) | 130 | static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d) |
128 | { | 131 | { |
129 | return (d->devtype_data->devtype == IMX51_ECSPI) ? 64 : 8; | 132 | return is_imx51_ecspi(d) ? 64 : 8; |
130 | } | 133 | } |
131 | 134 | ||
132 | #define MXC_SPI_BUF_RX(type) \ | 135 | #define MXC_SPI_BUF_RX(type) \ |
@@ -201,9 +204,8 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, | |||
201 | { | 204 | { |
202 | struct spi_imx_data *spi_imx = spi_master_get_devdata(master); | 205 | struct spi_imx_data *spi_imx = spi_master_get_devdata(master); |
203 | 206 | ||
204 | if (spi_imx->dma_is_inited | 207 | if (spi_imx->dma_is_inited && |
205 | && transfer->len > spi_imx->rx_wml * sizeof(u32) | 208 | transfer->len > spi_imx->wml * sizeof(u32)) |
206 | && transfer->len > spi_imx->tx_wml * sizeof(u32)) | ||
207 | return true; | 209 | return true; |
208 | return false; | 210 | return false; |
209 | } | 211 | } |
@@ -244,6 +246,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, | |||
244 | #define MX51_ECSPI_STAT 0x18 | 246 | #define MX51_ECSPI_STAT 0x18 |
245 | #define MX51_ECSPI_STAT_RR (1 << 3) | 247 | #define MX51_ECSPI_STAT_RR (1 << 3) |
246 | 248 | ||
249 | #define MX51_ECSPI_TESTREG 0x20 | ||
250 | #define MX51_ECSPI_TESTREG_LBC BIT(31) | ||
251 | |||
247 | /* MX51 eCSPI */ | 252 | /* MX51 eCSPI */ |
248 | static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi, | 253 | static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi, |
249 | unsigned int *fres) | 254 | unsigned int *fres) |
@@ -313,7 +318,7 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, | |||
313 | { | 318 | { |
314 | u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0; | 319 | u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0; |
315 | u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg; | 320 | u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg; |
316 | u32 clk = config->speed_hz, delay; | 321 | u32 clk = config->speed_hz, delay, reg; |
317 | 322 | ||
318 | /* | 323 | /* |
319 | * The hardware seems to have a race condition when changing modes. The | 324 | * The hardware seems to have a race condition when changing modes. The |
@@ -351,7 +356,16 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, | |||
351 | else | 356 | else |
352 | cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs); | 357 | cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs); |
353 | 358 | ||
359 | /* CTRL register always go first to bring out controller from reset */ | ||
354 | writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); | 360 | writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); |
361 | |||
362 | reg = readl(spi_imx->base + MX51_ECSPI_TESTREG); | ||
363 | if (config->mode & SPI_LOOP) | ||
364 | reg |= MX51_ECSPI_TESTREG_LBC; | ||
365 | else | ||
366 | reg &= ~MX51_ECSPI_TESTREG_LBC; | ||
367 | writel(reg, spi_imx->base + MX51_ECSPI_TESTREG); | ||
368 | |||
355 | writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); | 369 | writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); |
356 | 370 | ||
357 | /* | 371 | /* |
@@ -378,10 +392,9 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx, | |||
378 | if (spi_imx->dma_is_inited) { | 392 | if (spi_imx->dma_is_inited) { |
379 | dma = readl(spi_imx->base + MX51_ECSPI_DMA); | 393 | dma = readl(spi_imx->base + MX51_ECSPI_DMA); |
380 | 394 | ||
381 | spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2; | 395 | rx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RX_WML_OFFSET; |
382 | rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET; | 396 | tx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_TX_WML_OFFSET; |
383 | tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET; | 397 | rxt_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET; |
384 | rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET; | ||
385 | dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK | 398 | dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK |
386 | & ~MX51_ECSPI_DMA_RX_WML_MASK | 399 | & ~MX51_ECSPI_DMA_RX_WML_MASK |
387 | & ~MX51_ECSPI_DMA_RXT_WML_MASK) | 400 | & ~MX51_ECSPI_DMA_RXT_WML_MASK) |
@@ -832,18 +845,21 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, | |||
832 | if (of_machine_is_compatible("fsl,imx6dl")) | 845 | if (of_machine_is_compatible("fsl,imx6dl")) |
833 | return 0; | 846 | return 0; |
834 | 847 | ||
848 | spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2; | ||
849 | |||
835 | /* Prepare for TX DMA: */ | 850 | /* Prepare for TX DMA: */ |
836 | master->dma_tx = dma_request_slave_channel(dev, "tx"); | 851 | master->dma_tx = dma_request_slave_channel_reason(dev, "tx"); |
837 | if (!master->dma_tx) { | 852 | if (IS_ERR(master->dma_tx)) { |
838 | dev_err(dev, "cannot get the TX DMA channel!\n"); | 853 | ret = PTR_ERR(master->dma_tx); |
839 | ret = -EINVAL; | 854 | dev_dbg(dev, "can't get the TX DMA channel, error %d!\n", ret); |
855 | master->dma_tx = NULL; | ||
840 | goto err; | 856 | goto err; |
841 | } | 857 | } |
842 | 858 | ||
843 | slave_config.direction = DMA_MEM_TO_DEV; | 859 | slave_config.direction = DMA_MEM_TO_DEV; |
844 | slave_config.dst_addr = res->start + MXC_CSPITXDATA; | 860 | slave_config.dst_addr = res->start + MXC_CSPITXDATA; |
845 | slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | 861 | slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; |
846 | slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 2; | 862 | slave_config.dst_maxburst = spi_imx->wml; |
847 | ret = dmaengine_slave_config(master->dma_tx, &slave_config); | 863 | ret = dmaengine_slave_config(master->dma_tx, &slave_config); |
848 | if (ret) { | 864 | if (ret) { |
849 | dev_err(dev, "error in TX dma configuration.\n"); | 865 | dev_err(dev, "error in TX dma configuration.\n"); |
@@ -851,17 +867,18 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, | |||
851 | } | 867 | } |
852 | 868 | ||
853 | /* Prepare for RX : */ | 869 | /* Prepare for RX : */ |
854 | master->dma_rx = dma_request_slave_channel(dev, "rx"); | 870 | master->dma_rx = dma_request_slave_channel_reason(dev, "rx"); |
855 | if (!master->dma_rx) { | 871 | if (IS_ERR(master->dma_rx)) { |
856 | dev_dbg(dev, "cannot get the DMA channel.\n"); | 872 | ret = PTR_ERR(master->dma_rx); |
857 | ret = -EINVAL; | 873 | dev_dbg(dev, "can't get the RX DMA channel, error %d\n", ret); |
874 | master->dma_rx = NULL; | ||
858 | goto err; | 875 | goto err; |
859 | } | 876 | } |
860 | 877 | ||
861 | slave_config.direction = DMA_DEV_TO_MEM; | 878 | slave_config.direction = DMA_DEV_TO_MEM; |
862 | slave_config.src_addr = res->start + MXC_CSPIRXDATA; | 879 | slave_config.src_addr = res->start + MXC_CSPIRXDATA; |
863 | slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | 880 | slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; |
864 | slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2; | 881 | slave_config.src_maxburst = spi_imx->wml; |
865 | ret = dmaengine_slave_config(master->dma_rx, &slave_config); | 882 | ret = dmaengine_slave_config(master->dma_rx, &slave_config); |
866 | if (ret) { | 883 | if (ret) { |
867 | dev_err(dev, "error in RX dma configuration.\n"); | 884 | dev_err(dev, "error in RX dma configuration.\n"); |
@@ -874,8 +891,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, | |||
874 | master->max_dma_len = MAX_SDMA_BD_BYTES; | 891 | master->max_dma_len = MAX_SDMA_BD_BYTES; |
875 | spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX | | 892 | spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX | |
876 | SPI_MASTER_MUST_TX; | 893 | SPI_MASTER_MUST_TX; |
877 | spi_imx->tx_wml = spi_imx_get_fifosize(spi_imx) / 2; | ||
878 | spi_imx->rx_wml = spi_imx_get_fifosize(spi_imx) / 2; | ||
879 | spi_imx->dma_is_inited = 1; | 894 | spi_imx->dma_is_inited = 1; |
880 | 895 | ||
881 | return 0; | 896 | return 0; |
@@ -942,14 +957,22 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, | |||
942 | dma = readl(spi_imx->base + MX51_ECSPI_DMA); | 957 | dma = readl(spi_imx->base + MX51_ECSPI_DMA); |
943 | dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK); | 958 | dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK); |
944 | /* Change RX_DMA_LENGTH trigger dma fetch tail data */ | 959 | /* Change RX_DMA_LENGTH trigger dma fetch tail data */ |
945 | left = transfer->len % spi_imx->rxt_wml; | 960 | left = transfer->len % spi_imx->wml; |
946 | if (left) | 961 | if (left) |
947 | writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET), | 962 | writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET), |
948 | spi_imx->base + MX51_ECSPI_DMA); | 963 | spi_imx->base + MX51_ECSPI_DMA); |
964 | /* | ||
965 | * Set these order to avoid potential RX overflow. The overflow may | ||
966 | * happen if we enable SPI HW before starting RX DMA due to rescheduling | ||
967 | * for another task and/or interrupt. | ||
968 | * So RX DMA enabled first to make sure data would be read out from FIFO | ||
969 | * ASAP. TX DMA enabled next to start filling TX FIFO with new data. | ||
970 | * And finaly SPI HW enabled to start actual data transfer. | ||
971 | */ | ||
972 | dma_async_issue_pending(master->dma_rx); | ||
973 | dma_async_issue_pending(master->dma_tx); | ||
949 | spi_imx->devtype_data->trigger(spi_imx); | 974 | spi_imx->devtype_data->trigger(spi_imx); |
950 | 975 | ||
951 | dma_async_issue_pending(master->dma_tx); | ||
952 | dma_async_issue_pending(master->dma_rx); | ||
953 | /* Wait SDMA to finish the data transfer.*/ | 976 | /* Wait SDMA to finish the data transfer.*/ |
954 | timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion, | 977 | timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion, |
955 | IMX_DMA_TIMEOUT); | 978 | IMX_DMA_TIMEOUT); |
@@ -958,6 +981,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, | |||
958 | dev_driver_string(&master->dev), | 981 | dev_driver_string(&master->dev), |
959 | dev_name(&master->dev)); | 982 | dev_name(&master->dev)); |
960 | dmaengine_terminate_all(master->dma_tx); | 983 | dmaengine_terminate_all(master->dma_tx); |
984 | dmaengine_terminate_all(master->dma_rx); | ||
961 | } else { | 985 | } else { |
962 | timeout = wait_for_completion_timeout( | 986 | timeout = wait_for_completion_timeout( |
963 | &spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT); | 987 | &spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT); |
@@ -968,8 +992,9 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, | |||
968 | spi_imx->devtype_data->reset(spi_imx); | 992 | spi_imx->devtype_data->reset(spi_imx); |
969 | dmaengine_terminate_all(master->dma_rx); | 993 | dmaengine_terminate_all(master->dma_rx); |
970 | } | 994 | } |
995 | dma &= ~MX51_ECSPI_DMA_RXT_WML_MASK; | ||
971 | writel(dma | | 996 | writel(dma | |
972 | spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET, | 997 | spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET, |
973 | spi_imx->base + MX51_ECSPI_DMA); | 998 | spi_imx->base + MX51_ECSPI_DMA); |
974 | } | 999 | } |
975 | 1000 | ||
@@ -1117,6 +1142,9 @@ static int spi_imx_probe(struct platform_device *pdev) | |||
1117 | spi_imx = spi_master_get_devdata(master); | 1142 | spi_imx = spi_master_get_devdata(master); |
1118 | spi_imx->bitbang.master = master; | 1143 | spi_imx->bitbang.master = master; |
1119 | 1144 | ||
1145 | spi_imx->devtype_data = of_id ? of_id->data : | ||
1146 | (struct spi_imx_devtype_data *)pdev->id_entry->driver_data; | ||
1147 | |||
1120 | for (i = 0; i < master->num_chipselect; i++) { | 1148 | for (i = 0; i < master->num_chipselect; i++) { |
1121 | int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); | 1149 | int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); |
1122 | if (!gpio_is_valid(cs_gpio) && mxc_platform_info) | 1150 | if (!gpio_is_valid(cs_gpio) && mxc_platform_info) |
@@ -1142,12 +1170,11 @@ static int spi_imx_probe(struct platform_device *pdev) | |||
1142 | spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message; | 1170 | spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message; |
1143 | spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message; | 1171 | spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message; |
1144 | spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | 1172 | spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
1173 | if (is_imx51_ecspi(spi_imx)) | ||
1174 | spi_imx->bitbang.master->mode_bits |= SPI_LOOP; | ||
1145 | 1175 | ||
1146 | init_completion(&spi_imx->xfer_done); | 1176 | init_completion(&spi_imx->xfer_done); |
1147 | 1177 | ||
1148 | spi_imx->devtype_data = of_id ? of_id->data : | ||
1149 | (struct spi_imx_devtype_data *) pdev->id_entry->driver_data; | ||
1150 | |||
1151 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1178 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1152 | spi_imx->base = devm_ioremap_resource(&pdev->dev, res); | 1179 | spi_imx->base = devm_ioremap_resource(&pdev->dev, res); |
1153 | if (IS_ERR(spi_imx->base)) { | 1180 | if (IS_ERR(spi_imx->base)) { |
@@ -1193,9 +1220,15 @@ static int spi_imx_probe(struct platform_device *pdev) | |||
1193 | * Only validated on i.mx6 now, can remove the constrain if validated on | 1220 | * Only validated on i.mx6 now, can remove the constrain if validated on |
1194 | * other chips. | 1221 | * other chips. |
1195 | */ | 1222 | */ |
1196 | if (spi_imx->devtype_data == &imx51_ecspi_devtype_data | 1223 | if (is_imx51_ecspi(spi_imx)) { |
1197 | && spi_imx_sdma_init(&pdev->dev, spi_imx, master, res)) | 1224 | ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master, res); |
1198 | dev_err(&pdev->dev, "dma setup error,use pio instead\n"); | 1225 | if (ret == -EPROBE_DEFER) |
1226 | goto out_clk_put; | ||
1227 | |||
1228 | if (ret < 0) | ||
1229 | dev_err(&pdev->dev, "dma setup error %d, use pio\n", | ||
1230 | ret); | ||
1231 | } | ||
1199 | 1232 | ||
1200 | spi_imx->devtype_data->reset(spi_imx); | 1233 | spi_imx->devtype_data->reset(spi_imx); |
1201 | 1234 | ||
diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c index ba72347cb99d..61ee0f4269ae 100644 --- a/drivers/spi/spi-lm70llp.c +++ b/drivers/spi/spi-lm70llp.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
17 | #include <linux/init.h> | 19 | #include <linux/init.h> |
18 | #include <linux/module.h> | 20 | #include <linux/module.h> |
19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
@@ -23,11 +25,9 @@ | |||
23 | #include <linux/sysfs.h> | 25 | #include <linux/sysfs.h> |
24 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
25 | 27 | ||
26 | |||
27 | #include <linux/spi/spi.h> | 28 | #include <linux/spi/spi.h> |
28 | #include <linux/spi/spi_bitbang.h> | 29 | #include <linux/spi/spi_bitbang.h> |
29 | 30 | ||
30 | |||
31 | /* | 31 | /* |
32 | * The LM70 communicates with a host processor using a 3-wire variant of | 32 | * The LM70 communicates with a host processor using a 3-wire variant of |
33 | * the SPI/Microwire bus interface. This driver specifically supports an | 33 | * the SPI/Microwire bus interface. This driver specifically supports an |
@@ -88,7 +88,6 @@ struct spi_lm70llp { | |||
88 | /* REVISIT : ugly global ; provides "exclusive open" facility */ | 88 | /* REVISIT : ugly global ; provides "exclusive open" facility */ |
89 | static struct spi_lm70llp *lm70llp; | 89 | static struct spi_lm70llp *lm70llp; |
90 | 90 | ||
91 | |||
92 | /*-------------------------------------------------------------------*/ | 91 | /*-------------------------------------------------------------------*/ |
93 | 92 | ||
94 | static inline struct spi_lm70llp *spidev_to_pp(struct spi_device *spi) | 93 | static inline struct spi_lm70llp *spidev_to_pp(struct spi_device *spi) |
@@ -122,12 +121,14 @@ static inline void assertCS(struct spi_lm70llp *pp) | |||
122 | static inline void clkHigh(struct spi_lm70llp *pp) | 121 | static inline void clkHigh(struct spi_lm70llp *pp) |
123 | { | 122 | { |
124 | u8 data = parport_read_data(pp->port); | 123 | u8 data = parport_read_data(pp->port); |
124 | |||
125 | parport_write_data(pp->port, data | SCLK); | 125 | parport_write_data(pp->port, data | SCLK); |
126 | } | 126 | } |
127 | 127 | ||
128 | static inline void clkLow(struct spi_lm70llp *pp) | 128 | static inline void clkLow(struct spi_lm70llp *pp) |
129 | { | 129 | { |
130 | u8 data = parport_read_data(pp->port); | 130 | u8 data = parport_read_data(pp->port); |
131 | |||
131 | parport_write_data(pp->port, data & ~SCLK); | 132 | parport_write_data(pp->port, data & ~SCLK); |
132 | } | 133 | } |
133 | 134 | ||
@@ -166,8 +167,10 @@ static inline void setmosi(struct spi_device *s, int is_on) | |||
166 | static inline int getmiso(struct spi_device *s) | 167 | static inline int getmiso(struct spi_device *s) |
167 | { | 168 | { |
168 | struct spi_lm70llp *pp = spidev_to_pp(s); | 169 | struct spi_lm70llp *pp = spidev_to_pp(s); |
169 | return ((SIO == (parport_read_status(pp->port) & SIO)) ? 0 : 1 ); | 170 | |
171 | return ((SIO == (parport_read_status(pp->port) & SIO)) ? 0 : 1); | ||
170 | } | 172 | } |
173 | |||
171 | /*--------------------------------------------------------------------*/ | 174 | /*--------------------------------------------------------------------*/ |
172 | 175 | ||
173 | #include "spi-bitbang-txrx.h" | 176 | #include "spi-bitbang-txrx.h" |
@@ -196,11 +199,10 @@ static void spi_lm70llp_attach(struct parport *p) | |||
196 | struct spi_lm70llp *pp; | 199 | struct spi_lm70llp *pp; |
197 | struct spi_master *master; | 200 | struct spi_master *master; |
198 | int status; | 201 | int status; |
202 | struct pardev_cb lm70llp_cb; | ||
199 | 203 | ||
200 | if (lm70llp) { | 204 | if (lm70llp) { |
201 | printk(KERN_WARNING | 205 | pr_warn("spi_lm70llp instance already loaded. Aborting.\n"); |
202 | "%s: spi_lm70llp instance already loaded. Aborting.\n", | ||
203 | DRVNAME); | ||
204 | return; | 206 | return; |
205 | } | 207 | } |
206 | 208 | ||
@@ -227,9 +229,11 @@ static void spi_lm70llp_attach(struct parport *p) | |||
227 | * Parport hookup | 229 | * Parport hookup |
228 | */ | 230 | */ |
229 | pp->port = p; | 231 | pp->port = p; |
230 | pd = parport_register_device(p, DRVNAME, | 232 | memset(&lm70llp_cb, 0, sizeof(lm70llp_cb)); |
231 | NULL, NULL, NULL, | 233 | lm70llp_cb.private = pp; |
232 | PARPORT_FLAG_EXCL, pp); | 234 | lm70llp_cb.flags = PARPORT_FLAG_EXCL; |
235 | pd = parport_register_dev_model(p, DRVNAME, &lm70llp_cb, 0); | ||
236 | |||
233 | if (!pd) { | 237 | if (!pd) { |
234 | status = -ENOMEM; | 238 | status = -ENOMEM; |
235 | goto out_free_master; | 239 | goto out_free_master; |
@@ -245,9 +249,8 @@ static void spi_lm70llp_attach(struct parport *p) | |||
245 | */ | 249 | */ |
246 | status = spi_bitbang_start(&pp->bitbang); | 250 | status = spi_bitbang_start(&pp->bitbang); |
247 | if (status < 0) { | 251 | if (status < 0) { |
248 | printk(KERN_WARNING | 252 | dev_warn(&pd->dev, "spi_bitbang_start failed with status %d\n", |
249 | "%s: spi_bitbang_start failed with status %d\n", | 253 | status); |
250 | DRVNAME, status); | ||
251 | goto out_off_and_release; | 254 | goto out_off_and_release; |
252 | } | 255 | } |
253 | 256 | ||
@@ -272,9 +275,9 @@ static void spi_lm70llp_attach(struct parport *p) | |||
272 | pp->spidev_lm70 = spi_new_device(pp->bitbang.master, &pp->info); | 275 | pp->spidev_lm70 = spi_new_device(pp->bitbang.master, &pp->info); |
273 | if (pp->spidev_lm70) | 276 | if (pp->spidev_lm70) |
274 | dev_dbg(&pp->spidev_lm70->dev, "spidev_lm70 at %s\n", | 277 | dev_dbg(&pp->spidev_lm70->dev, "spidev_lm70 at %s\n", |
275 | dev_name(&pp->spidev_lm70->dev)); | 278 | dev_name(&pp->spidev_lm70->dev)); |
276 | else { | 279 | else { |
277 | printk(KERN_WARNING "%s: spi_new_device failed\n", DRVNAME); | 280 | dev_warn(&pd->dev, "spi_new_device failed\n"); |
278 | status = -ENODEV; | 281 | status = -ENODEV; |
279 | goto out_bitbang_stop; | 282 | goto out_bitbang_stop; |
280 | } | 283 | } |
@@ -293,9 +296,9 @@ out_off_and_release: | |||
293 | out_parport_unreg: | 296 | out_parport_unreg: |
294 | parport_unregister_device(pd); | 297 | parport_unregister_device(pd); |
295 | out_free_master: | 298 | out_free_master: |
296 | (void) spi_master_put(master); | 299 | spi_master_put(master); |
297 | out_fail: | 300 | out_fail: |
298 | pr_info("%s: spi_lm70llp probe fail, status %d\n", DRVNAME, status); | 301 | pr_info("spi_lm70llp probe fail, status %d\n", status); |
299 | } | 302 | } |
300 | 303 | ||
301 | static void spi_lm70llp_detach(struct parport *p) | 304 | static void spi_lm70llp_detach(struct parport *p) |
@@ -314,16 +317,16 @@ static void spi_lm70llp_detach(struct parport *p) | |||
314 | parport_release(pp->pd); | 317 | parport_release(pp->pd); |
315 | parport_unregister_device(pp->pd); | 318 | parport_unregister_device(pp->pd); |
316 | 319 | ||
317 | (void) spi_master_put(pp->bitbang.master); | 320 | spi_master_put(pp->bitbang.master); |
318 | 321 | ||
319 | lm70llp = NULL; | 322 | lm70llp = NULL; |
320 | } | 323 | } |
321 | 324 | ||
322 | |||
323 | static struct parport_driver spi_lm70llp_drv = { | 325 | static struct parport_driver spi_lm70llp_drv = { |
324 | .name = DRVNAME, | 326 | .name = DRVNAME, |
325 | .attach = spi_lm70llp_attach, | 327 | .match_port = spi_lm70llp_attach, |
326 | .detach = spi_lm70llp_detach, | 328 | .detach = spi_lm70llp_detach, |
329 | .devmodel = true, | ||
327 | }; | 330 | }; |
328 | 331 | ||
329 | static int __init init_spi_lm70llp(void) | 332 | static int __init init_spi_lm70llp(void) |
diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c new file mode 100644 index 000000000000..894616f687b0 --- /dev/null +++ b/drivers/spi/spi-loopback-test.c | |||
@@ -0,0 +1,1005 @@ | |||
1 | /* | ||
2 | * linux/drivers/spi/spi-loopback-test.c | ||
3 | * | ||
4 | * (c) Martin Sperl <kernel@martin.sperl.org> | ||
5 | * | ||
6 | * Loopback test driver to test several typical spi_message conditions | ||
7 | * that a spi_master driver may encounter | ||
8 | * this can also get used for regression testing | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | */ | ||
20 | |||
21 | #include <linux/delay.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/list_sort.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/of_device.h> | ||
27 | #include <linux/printk.h> | ||
28 | #include <linux/spi/spi.h> | ||
29 | |||
30 | #include "spi-test.h" | ||
31 | |||
32 | /* flag to only simulate transfers */ | ||
33 | int simulate_only; | ||
34 | module_param(simulate_only, int, 0); | ||
35 | MODULE_PARM_DESC(simulate_only, "if not 0 do not execute the spi message"); | ||
36 | |||
37 | /* dump spi messages */ | ||
38 | int dump_messages; | ||
39 | module_param(dump_messages, int, 0); | ||
40 | MODULE_PARM_DESC(dump_messages, | ||
41 | "=1 dump the basic spi_message_structure, " \ | ||
42 | "=2 dump the spi_message_structure including data, " \ | ||
43 | "=3 dump the spi_message structure before and after execution"); | ||
44 | /* the device is jumpered for loopback - enabling some rx_buf tests */ | ||
45 | int loopback; | ||
46 | module_param(loopback, int, 0); | ||
47 | MODULE_PARM_DESC(loopback, | ||
48 | "if set enable loopback mode, where the rx_buf " \ | ||
49 | "is checked to match tx_buf after the spi_message " \ | ||
50 | "is executed"); | ||
51 | |||
52 | /* run only a specific test */ | ||
53 | int run_only_test = -1; | ||
54 | module_param(run_only_test, int, 0); | ||
55 | MODULE_PARM_DESC(run_only_test, | ||
56 | "only run the test with this number (0-based !)"); | ||
57 | |||
58 | /* the actual tests to execute */ | ||
59 | static struct spi_test spi_tests[] = { | ||
60 | { | ||
61 | .description = "tx/rx-transfer - start of page", | ||
62 | .fill_option = FILL_COUNT_8, | ||
63 | .iterate_len = { ITERATE_MAX_LEN }, | ||
64 | .iterate_tx_align = ITERATE_ALIGN, | ||
65 | .iterate_rx_align = ITERATE_ALIGN, | ||
66 | .transfers = { | ||
67 | { | ||
68 | .len = 1, | ||
69 | .tx_buf = TX(0), | ||
70 | .rx_buf = RX(0), | ||
71 | }, | ||
72 | }, | ||
73 | }, | ||
74 | { | ||
75 | .description = "tx/rx-transfer - crossing PAGE_SIZE", | ||
76 | .fill_option = FILL_COUNT_8, | ||
77 | .iterate_len = { ITERATE_MAX_LEN }, | ||
78 | .iterate_tx_align = ITERATE_ALIGN, | ||
79 | .iterate_rx_align = ITERATE_ALIGN, | ||
80 | .transfers = { | ||
81 | { | ||
82 | .len = 1, | ||
83 | .tx_buf = TX(PAGE_SIZE - 4), | ||
84 | .rx_buf = RX(PAGE_SIZE - 4), | ||
85 | }, | ||
86 | }, | ||
87 | }, | ||
88 | { | ||
89 | .description = "tx-transfer - only", | ||
90 | .fill_option = FILL_COUNT_8, | ||
91 | .iterate_len = { ITERATE_MAX_LEN }, | ||
92 | .iterate_tx_align = ITERATE_ALIGN, | ||
93 | .transfers = { | ||
94 | { | ||
95 | .len = 1, | ||
96 | .tx_buf = TX(0), | ||
97 | }, | ||
98 | }, | ||
99 | }, | ||
100 | { | ||
101 | .description = "rx-transfer - only", | ||
102 | .fill_option = FILL_COUNT_8, | ||
103 | .iterate_len = { ITERATE_MAX_LEN }, | ||
104 | .iterate_rx_align = ITERATE_ALIGN, | ||
105 | .transfers = { | ||
106 | { | ||
107 | .len = 1, | ||
108 | .rx_buf = RX(0), | ||
109 | }, | ||
110 | }, | ||
111 | }, | ||
112 | { | ||
113 | .description = "two tx-transfers - alter both", | ||
114 | .fill_option = FILL_COUNT_8, | ||
115 | .iterate_len = { ITERATE_LEN }, | ||
116 | .iterate_tx_align = ITERATE_ALIGN, | ||
117 | .iterate_transfer_mask = BIT(0) | BIT(1), | ||
118 | .transfers = { | ||
119 | { | ||
120 | .len = 1, | ||
121 | .tx_buf = TX(0), | ||
122 | }, | ||
123 | { | ||
124 | .len = 1, | ||
125 | /* this is why we cant use ITERATE_MAX_LEN */ | ||
126 | .tx_buf = TX(SPI_TEST_MAX_SIZE_HALF), | ||
127 | }, | ||
128 | }, | ||
129 | }, | ||
130 | { | ||
131 | .description = "two tx-transfers - alter first", | ||
132 | .fill_option = FILL_COUNT_8, | ||
133 | .iterate_len = { ITERATE_MAX_LEN }, | ||
134 | .iterate_tx_align = ITERATE_ALIGN, | ||
135 | .iterate_transfer_mask = BIT(1), | ||
136 | .transfers = { | ||
137 | { | ||
138 | .len = 1, | ||
139 | .tx_buf = TX(64), | ||
140 | }, | ||
141 | { | ||
142 | .len = 1, | ||
143 | .tx_buf = TX(0), | ||
144 | }, | ||
145 | }, | ||
146 | }, | ||
147 | { | ||
148 | .description = "two tx-transfers - alter second", | ||
149 | .fill_option = FILL_COUNT_8, | ||
150 | .iterate_len = { ITERATE_MAX_LEN }, | ||
151 | .iterate_tx_align = ITERATE_ALIGN, | ||
152 | .iterate_transfer_mask = BIT(0), | ||
153 | .transfers = { | ||
154 | { | ||
155 | .len = 16, | ||
156 | .tx_buf = TX(0), | ||
157 | }, | ||
158 | { | ||
159 | .len = 1, | ||
160 | .tx_buf = TX(64), | ||
161 | }, | ||
162 | }, | ||
163 | }, | ||
164 | { | ||
165 | .description = "two transfers tx then rx - alter both", | ||
166 | .fill_option = FILL_COUNT_8, | ||
167 | .iterate_len = { ITERATE_MAX_LEN }, | ||
168 | .iterate_tx_align = ITERATE_ALIGN, | ||
169 | .iterate_transfer_mask = BIT(0) | BIT(1), | ||
170 | .transfers = { | ||
171 | { | ||
172 | .len = 1, | ||
173 | .tx_buf = TX(0), | ||
174 | }, | ||
175 | { | ||
176 | .len = 1, | ||
177 | .rx_buf = RX(0), | ||
178 | }, | ||
179 | }, | ||
180 | }, | ||
181 | { | ||
182 | .description = "two transfers tx then rx - alter tx", | ||
183 | .fill_option = FILL_COUNT_8, | ||
184 | .iterate_len = { ITERATE_MAX_LEN }, | ||
185 | .iterate_tx_align = ITERATE_ALIGN, | ||
186 | .iterate_transfer_mask = BIT(0), | ||
187 | .transfers = { | ||
188 | { | ||
189 | .len = 1, | ||
190 | .tx_buf = TX(0), | ||
191 | }, | ||
192 | { | ||
193 | .len = 1, | ||
194 | .rx_buf = RX(0), | ||
195 | }, | ||
196 | }, | ||
197 | }, | ||
198 | { | ||
199 | .description = "two transfers tx then rx - alter rx", | ||
200 | .fill_option = FILL_COUNT_8, | ||
201 | .iterate_len = { ITERATE_MAX_LEN }, | ||
202 | .iterate_tx_align = ITERATE_ALIGN, | ||
203 | .iterate_transfer_mask = BIT(1), | ||
204 | .transfers = { | ||
205 | { | ||
206 | .len = 1, | ||
207 | .tx_buf = TX(0), | ||
208 | }, | ||
209 | { | ||
210 | .len = 1, | ||
211 | .rx_buf = RX(0), | ||
212 | }, | ||
213 | }, | ||
214 | }, | ||
215 | { | ||
216 | .description = "two tx+rx transfers - alter both", | ||
217 | .fill_option = FILL_COUNT_8, | ||
218 | .iterate_len = { ITERATE_LEN }, | ||
219 | .iterate_tx_align = ITERATE_ALIGN, | ||
220 | .iterate_transfer_mask = BIT(0) | BIT(1), | ||
221 | .transfers = { | ||
222 | { | ||
223 | .len = 1, | ||
224 | .tx_buf = TX(0), | ||
225 | .rx_buf = RX(0), | ||
226 | }, | ||
227 | { | ||
228 | .len = 1, | ||
229 | /* making sure we align without overwrite | ||
230 | * the reason we can not use ITERATE_MAX_LEN | ||
231 | */ | ||
232 | .tx_buf = TX(SPI_TEST_MAX_SIZE_HALF), | ||
233 | .rx_buf = RX(SPI_TEST_MAX_SIZE_HALF), | ||
234 | }, | ||
235 | }, | ||
236 | }, | ||
237 | { | ||
238 | .description = "two tx+rx transfers - alter first", | ||
239 | .fill_option = FILL_COUNT_8, | ||
240 | .iterate_len = { ITERATE_MAX_LEN }, | ||
241 | .iterate_tx_align = ITERATE_ALIGN, | ||
242 | .iterate_transfer_mask = BIT(0), | ||
243 | .transfers = { | ||
244 | { | ||
245 | .len = 1, | ||
246 | /* making sure we align without overwrite */ | ||
247 | .tx_buf = TX(1024), | ||
248 | .rx_buf = RX(1024), | ||
249 | }, | ||
250 | { | ||
251 | .len = 1, | ||
252 | /* making sure we align without overwrite */ | ||
253 | .tx_buf = TX(0), | ||
254 | .rx_buf = RX(0), | ||
255 | }, | ||
256 | }, | ||
257 | }, | ||
258 | { | ||
259 | .description = "two tx+rx transfers - alter second", | ||
260 | .fill_option = FILL_COUNT_8, | ||
261 | .iterate_len = { ITERATE_MAX_LEN }, | ||
262 | .iterate_tx_align = ITERATE_ALIGN, | ||
263 | .iterate_transfer_mask = BIT(1), | ||
264 | .transfers = { | ||
265 | { | ||
266 | .len = 1, | ||
267 | .tx_buf = TX(0), | ||
268 | .rx_buf = RX(0), | ||
269 | }, | ||
270 | { | ||
271 | .len = 1, | ||
272 | /* making sure we align without overwrite */ | ||
273 | .tx_buf = TX(1024), | ||
274 | .rx_buf = RX(1024), | ||
275 | }, | ||
276 | }, | ||
277 | }, | ||
278 | |||
279 | { /* end of tests sequence */ } | ||
280 | }; | ||
281 | |||
282 | static int spi_loopback_test_probe(struct spi_device *spi) | ||
283 | { | ||
284 | int ret; | ||
285 | |||
286 | dev_info(&spi->dev, "Executing spi-loopback-tests\n"); | ||
287 | |||
288 | ret = spi_test_run_tests(spi, spi_tests); | ||
289 | |||
290 | dev_info(&spi->dev, "Finished spi-loopback-tests with return: %i\n", | ||
291 | ret); | ||
292 | |||
293 | return ret; | ||
294 | } | ||
295 | |||
296 | /* non const match table to permit to change via a module parameter */ | ||
297 | static struct of_device_id spi_loopback_test_of_match[] = { | ||
298 | { .compatible = "linux,spi-loopback-test", }, | ||
299 | { } | ||
300 | }; | ||
301 | |||
302 | /* allow to override the compatible string via a module_parameter */ | ||
303 | module_param_string(compatible, spi_loopback_test_of_match[0].compatible, | ||
304 | sizeof(spi_loopback_test_of_match[0].compatible), | ||
305 | 0000); | ||
306 | |||
307 | MODULE_DEVICE_TABLE(of, spi_loopback_test_of_match); | ||
308 | |||
309 | static struct spi_driver spi_loopback_test_driver = { | ||
310 | .driver = { | ||
311 | .name = "spi-loopback-test", | ||
312 | .owner = THIS_MODULE, | ||
313 | .of_match_table = spi_loopback_test_of_match, | ||
314 | }, | ||
315 | .probe = spi_loopback_test_probe, | ||
316 | }; | ||
317 | |||
318 | module_spi_driver(spi_loopback_test_driver); | ||
319 | |||
320 | MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>"); | ||
321 | MODULE_DESCRIPTION("test spi_driver to check core functionality"); | ||
322 | MODULE_LICENSE("GPL"); | ||
323 | |||
324 | /*-------------------------------------------------------------------------*/ | ||
325 | |||
326 | /* spi_test implementation */ | ||
327 | |||
328 | #define RANGE_CHECK(ptr, plen, start, slen) \ | ||
329 | ((ptr >= start) && (ptr + plen <= start + slen)) | ||
330 | |||
331 | /* we allocate one page more, to allow for offsets */ | ||
332 | #define SPI_TEST_MAX_SIZE_PLUS (SPI_TEST_MAX_SIZE + PAGE_SIZE) | ||
333 | |||
334 | static void spi_test_print_hex_dump(char *pre, const void *ptr, size_t len) | ||
335 | { | ||
336 | /* limit the hex_dump */ | ||
337 | if (len < 1024) { | ||
338 | print_hex_dump(KERN_INFO, pre, | ||
339 | DUMP_PREFIX_OFFSET, 16, 1, | ||
340 | ptr, len, 0); | ||
341 | return; | ||
342 | } | ||
343 | /* print head */ | ||
344 | print_hex_dump(KERN_INFO, pre, | ||
345 | DUMP_PREFIX_OFFSET, 16, 1, | ||
346 | ptr, 512, 0); | ||
347 | /* print tail */ | ||
348 | pr_info("%s truncated - continuing at offset %04zx\n", | ||
349 | pre, len - 512); | ||
350 | print_hex_dump(KERN_INFO, pre, | ||
351 | DUMP_PREFIX_OFFSET, 16, 1, | ||
352 | ptr + (len - 512), 512, 0); | ||
353 | } | ||
354 | |||
355 | static void spi_test_dump_message(struct spi_device *spi, | ||
356 | struct spi_message *msg, | ||
357 | bool dump_data) | ||
358 | { | ||
359 | struct spi_transfer *xfer; | ||
360 | int i; | ||
361 | u8 b; | ||
362 | |||
363 | dev_info(&spi->dev, " spi_msg@%pK\n", msg); | ||
364 | if (msg->status) | ||
365 | dev_info(&spi->dev, " status: %i\n", | ||
366 | msg->status); | ||
367 | dev_info(&spi->dev, " frame_length: %i\n", | ||
368 | msg->frame_length); | ||
369 | dev_info(&spi->dev, " actual_length: %i\n", | ||
370 | msg->actual_length); | ||
371 | |||
372 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | ||
373 | dev_info(&spi->dev, " spi_transfer@%pK\n", xfer); | ||
374 | dev_info(&spi->dev, " len: %i\n", xfer->len); | ||
375 | dev_info(&spi->dev, " tx_buf: %pK\n", xfer->tx_buf); | ||
376 | if (dump_data && xfer->tx_buf) | ||
377 | spi_test_print_hex_dump(" TX: ", | ||
378 | xfer->tx_buf, | ||
379 | xfer->len); | ||
380 | |||
381 | dev_info(&spi->dev, " rx_buf: %pK\n", xfer->rx_buf); | ||
382 | if (dump_data && xfer->rx_buf) | ||
383 | spi_test_print_hex_dump(" RX: ", | ||
384 | xfer->rx_buf, | ||
385 | xfer->len); | ||
386 | /* check for unwritten test pattern on rx_buf */ | ||
387 | if (xfer->rx_buf) { | ||
388 | for (i = 0 ; i < xfer->len ; i++) { | ||
389 | b = ((u8 *)xfer->rx_buf)[xfer->len - 1 - i]; | ||
390 | if (b != SPI_TEST_PATTERN_UNWRITTEN) | ||
391 | break; | ||
392 | } | ||
393 | if (i) | ||
394 | dev_info(&spi->dev, | ||
395 | " rx_buf filled with %02x starts at offset: %i\n", | ||
396 | SPI_TEST_PATTERN_UNWRITTEN, | ||
397 | xfer->len - i); | ||
398 | } | ||
399 | } | ||
400 | } | ||
401 | |||
402 | struct rx_ranges { | ||
403 | struct list_head list; | ||
404 | u8 *start; | ||
405 | u8 *end; | ||
406 | }; | ||
407 | |||
408 | int rx_ranges_cmp(void *priv, struct list_head *a, struct list_head *b) | ||
409 | { | ||
410 | struct rx_ranges *rx_a = list_entry(a, struct rx_ranges, list); | ||
411 | struct rx_ranges *rx_b = list_entry(b, struct rx_ranges, list); | ||
412 | |||
413 | if (rx_a->start > rx_b->start) | ||
414 | return 1; | ||
415 | if (rx_a->start < rx_b->start) | ||
416 | return -1; | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int spi_check_rx_ranges(struct spi_device *spi, | ||
421 | struct spi_message *msg, | ||
422 | void *rx) | ||
423 | { | ||
424 | struct spi_transfer *xfer; | ||
425 | struct rx_ranges ranges[SPI_TEST_MAX_TRANSFERS], *r; | ||
426 | int i = 0; | ||
427 | LIST_HEAD(ranges_list); | ||
428 | u8 *addr; | ||
429 | int ret = 0; | ||
430 | |||
431 | /* loop over all transfers to fill in the rx_ranges */ | ||
432 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | ||
433 | /* if there is no rx, then no check is needed */ | ||
434 | if (!xfer->rx_buf) | ||
435 | continue; | ||
436 | /* fill in the rx_range */ | ||
437 | if (RANGE_CHECK(xfer->rx_buf, xfer->len, | ||
438 | rx, SPI_TEST_MAX_SIZE_PLUS)) { | ||
439 | ranges[i].start = xfer->rx_buf; | ||
440 | ranges[i].end = xfer->rx_buf + xfer->len; | ||
441 | list_add(&ranges[i].list, &ranges_list); | ||
442 | i++; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | /* if no ranges, then we can return and avoid the checks...*/ | ||
447 | if (!i) | ||
448 | return 0; | ||
449 | |||
450 | /* sort the list */ | ||
451 | list_sort(NULL, &ranges_list, rx_ranges_cmp); | ||
452 | |||
453 | /* and iterate over all the rx addresses */ | ||
454 | for (addr = rx; addr < (u8 *)rx + SPI_TEST_MAX_SIZE_PLUS; addr++) { | ||
455 | /* if we are the DO not write pattern, | ||
456 | * then continue with the loop... | ||
457 | */ | ||
458 | if (*addr == SPI_TEST_PATTERN_DO_NOT_WRITE) | ||
459 | continue; | ||
460 | |||
461 | /* check if we are inside a range */ | ||
462 | list_for_each_entry(r, &ranges_list, list) { | ||
463 | /* if so then set to end... */ | ||
464 | if ((addr >= r->start) && (addr < r->end)) | ||
465 | addr = r->end; | ||
466 | } | ||
467 | /* second test after a (hopefull) translation */ | ||
468 | if (*addr == SPI_TEST_PATTERN_DO_NOT_WRITE) | ||
469 | continue; | ||
470 | |||
471 | /* if still not found then something has modified too much */ | ||
472 | /* we could list the "closest" transfer here... */ | ||
473 | dev_err(&spi->dev, | ||
474 | "loopback strangeness - rx changed outside of allowed range at: %pK\n", | ||
475 | addr); | ||
476 | /* do not return, only set ret, | ||
477 | * so that we list all addresses | ||
478 | */ | ||
479 | ret = -ERANGE; | ||
480 | } | ||
481 | |||
482 | return ret; | ||
483 | } | ||
484 | |||
485 | static int spi_test_check_loopback_result(struct spi_device *spi, | ||
486 | struct spi_message *msg, | ||
487 | void *tx, void *rx) | ||
488 | { | ||
489 | struct spi_transfer *xfer; | ||
490 | u8 rxb, txb; | ||
491 | size_t i; | ||
492 | int ret; | ||
493 | |||
494 | /* checks rx_buffer pattern are valid with loopback or without */ | ||
495 | ret = spi_check_rx_ranges(spi, msg, rx); | ||
496 | if (ret) | ||
497 | return ret; | ||
498 | |||
499 | /* if we run without loopback, then return now */ | ||
500 | if (!loopback) | ||
501 | return 0; | ||
502 | |||
503 | /* if applicable to transfer check that rx_buf is equal to tx_buf */ | ||
504 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | ||
505 | /* if there is no rx, then no check is needed */ | ||
506 | if (!xfer->rx_buf) | ||
507 | continue; | ||
508 | /* so depending on tx_buf we need to handle things */ | ||
509 | if (xfer->tx_buf) { | ||
510 | for (i = 1; i < xfer->len; i++) { | ||
511 | txb = ((u8 *)xfer->tx_buf)[i]; | ||
512 | rxb = ((u8 *)xfer->rx_buf)[i]; | ||
513 | if (txb != rxb) | ||
514 | goto mismatch_error; | ||
515 | } | ||
516 | } else { | ||
517 | /* first byte received */ | ||
518 | txb = ((u8 *)xfer->rx_buf)[0]; | ||
519 | /* first byte may be 0 or xff */ | ||
520 | if (!((txb == 0) || (txb == 0xff))) { | ||
521 | dev_err(&spi->dev, | ||
522 | "loopback strangeness - we expect 0x00 or 0xff, but not 0x%02x\n", | ||
523 | txb); | ||
524 | return -EINVAL; | ||
525 | } | ||
526 | /* check that all bytes are identical */ | ||
527 | for (i = 1; i < xfer->len; i++) { | ||
528 | rxb = ((u8 *)xfer->rx_buf)[i]; | ||
529 | if (rxb != txb) | ||
530 | goto mismatch_error; | ||
531 | } | ||
532 | } | ||
533 | } | ||
534 | |||
535 | return 0; | ||
536 | |||
537 | mismatch_error: | ||
538 | dev_err(&spi->dev, | ||
539 | "loopback strangeness - transfer missmatch on byte %04zx - expected 0x%02x, but got 0x%02x\n", | ||
540 | i, txb, rxb); | ||
541 | |||
542 | return -EINVAL; | ||
543 | } | ||
544 | |||
545 | static int spi_test_translate(struct spi_device *spi, | ||
546 | void **ptr, size_t len, | ||
547 | void *tx, void *rx) | ||
548 | { | ||
549 | size_t off; | ||
550 | |||
551 | /* return on null */ | ||
552 | if (!*ptr) | ||
553 | return 0; | ||
554 | |||
555 | /* in the MAX_SIZE_HALF case modify the pointer */ | ||
556 | if (((size_t)*ptr) & SPI_TEST_MAX_SIZE_HALF) | ||
557 | /* move the pointer to the correct range */ | ||
558 | *ptr += (SPI_TEST_MAX_SIZE_PLUS / 2) - | ||
559 | SPI_TEST_MAX_SIZE_HALF; | ||
560 | |||
561 | /* RX range | ||
562 | * - we check against MAX_SIZE_PLUS to allow for automated alignment | ||
563 | */ | ||
564 | if (RANGE_CHECK(*ptr, len, RX(0), SPI_TEST_MAX_SIZE_PLUS)) { | ||
565 | off = *ptr - RX(0); | ||
566 | *ptr = rx + off; | ||
567 | |||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | /* TX range */ | ||
572 | if (RANGE_CHECK(*ptr, len, TX(0), SPI_TEST_MAX_SIZE_PLUS)) { | ||
573 | off = *ptr - TX(0); | ||
574 | *ptr = tx + off; | ||
575 | |||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | dev_err(&spi->dev, | ||
580 | "PointerRange [%pK:%pK[ not in range [%pK:%pK[ or [%pK:%pK[\n", | ||
581 | *ptr, *ptr + len, | ||
582 | RX(0), RX(SPI_TEST_MAX_SIZE), | ||
583 | TX(0), TX(SPI_TEST_MAX_SIZE)); | ||
584 | |||
585 | return -EINVAL; | ||
586 | } | ||
587 | |||
588 | static int spi_test_fill_pattern(struct spi_device *spi, | ||
589 | struct spi_test *test) | ||
590 | { | ||
591 | struct spi_transfer *xfers = test->transfers; | ||
592 | u8 *tx_buf; | ||
593 | size_t count = 0; | ||
594 | int i, j; | ||
595 | |||
596 | #ifdef __BIG_ENDIAN | ||
597 | #define GET_VALUE_BYTE(value, index, bytes) \ | ||
598 | (value >> (8 * (bytes - 1 - count % bytes))) | ||
599 | #else | ||
600 | #define GET_VALUE_BYTE(value, index, bytes) \ | ||
601 | (value >> (8 * (count % bytes))) | ||
602 | #endif | ||
603 | |||
604 | /* fill all transfers with the pattern requested */ | ||
605 | for (i = 0; i < test->transfer_count; i++) { | ||
606 | /* fill rx_buf with SPI_TEST_PATTERN_UNWRITTEN */ | ||
607 | if (xfers[i].rx_buf) | ||
608 | memset(xfers[i].rx_buf, SPI_TEST_PATTERN_UNWRITTEN, | ||
609 | xfers[i].len); | ||
610 | /* if tx_buf is NULL then skip */ | ||
611 | tx_buf = (u8 *)xfers[i].tx_buf; | ||
612 | if (!tx_buf) | ||
613 | continue; | ||
614 | /* modify all the transfers */ | ||
615 | for (j = 0; j < xfers[i].len; j++, tx_buf++, count++) { | ||
616 | /* fill tx */ | ||
617 | switch (test->fill_option) { | ||
618 | case FILL_MEMSET_8: | ||
619 | *tx_buf = test->fill_pattern; | ||
620 | break; | ||
621 | case FILL_MEMSET_16: | ||
622 | *tx_buf = GET_VALUE_BYTE(test->fill_pattern, | ||
623 | count, 2); | ||
624 | break; | ||
625 | case FILL_MEMSET_24: | ||
626 | *tx_buf = GET_VALUE_BYTE(test->fill_pattern, | ||
627 | count, 3); | ||
628 | break; | ||
629 | case FILL_MEMSET_32: | ||
630 | *tx_buf = GET_VALUE_BYTE(test->fill_pattern, | ||
631 | count, 4); | ||
632 | break; | ||
633 | case FILL_COUNT_8: | ||
634 | *tx_buf = count; | ||
635 | break; | ||
636 | case FILL_COUNT_16: | ||
637 | *tx_buf = GET_VALUE_BYTE(count, count, 2); | ||
638 | break; | ||
639 | case FILL_COUNT_24: | ||
640 | *tx_buf = GET_VALUE_BYTE(count, count, 3); | ||
641 | break; | ||
642 | case FILL_COUNT_32: | ||
643 | *tx_buf = GET_VALUE_BYTE(count, count, 4); | ||
644 | break; | ||
645 | case FILL_TRANSFER_BYTE_8: | ||
646 | *tx_buf = j; | ||
647 | break; | ||
648 | case FILL_TRANSFER_BYTE_16: | ||
649 | *tx_buf = GET_VALUE_BYTE(j, j, 2); | ||
650 | break; | ||
651 | case FILL_TRANSFER_BYTE_24: | ||
652 | *tx_buf = GET_VALUE_BYTE(j, j, 3); | ||
653 | break; | ||
654 | case FILL_TRANSFER_BYTE_32: | ||
655 | *tx_buf = GET_VALUE_BYTE(j, j, 4); | ||
656 | break; | ||
657 | case FILL_TRANSFER_NUM: | ||
658 | *tx_buf = i; | ||
659 | break; | ||
660 | default: | ||
661 | dev_err(&spi->dev, | ||
662 | "unsupported fill_option: %i\n", | ||
663 | test->fill_option); | ||
664 | return -EINVAL; | ||
665 | } | ||
666 | } | ||
667 | } | ||
668 | |||
669 | return 0; | ||
670 | } | ||
671 | |||
672 | static int _spi_test_run_iter(struct spi_device *spi, | ||
673 | struct spi_test *test, | ||
674 | void *tx, void *rx) | ||
675 | { | ||
676 | struct spi_message *msg = &test->msg; | ||
677 | struct spi_transfer *x; | ||
678 | int i, ret; | ||
679 | |||
680 | /* initialize message - zero-filled via static initialization */ | ||
681 | spi_message_init_no_memset(msg); | ||
682 | |||
683 | /* fill rx with the DO_NOT_WRITE pattern */ | ||
684 | memset(rx, SPI_TEST_PATTERN_DO_NOT_WRITE, SPI_TEST_MAX_SIZE_PLUS); | ||
685 | |||
686 | /* add the individual transfers */ | ||
687 | for (i = 0; i < test->transfer_count; i++) { | ||
688 | x = &test->transfers[i]; | ||
689 | |||
690 | /* patch the values of tx_buf */ | ||
691 | ret = spi_test_translate(spi, (void **)&x->tx_buf, x->len, | ||
692 | (void *)tx, rx); | ||
693 | if (ret) | ||
694 | return ret; | ||
695 | |||
696 | /* patch the values of rx_buf */ | ||
697 | ret = spi_test_translate(spi, &x->rx_buf, x->len, | ||
698 | (void *)tx, rx); | ||
699 | if (ret) | ||
700 | return ret; | ||
701 | |||
702 | /* and add it to the list */ | ||
703 | spi_message_add_tail(x, msg); | ||
704 | } | ||
705 | |||
706 | /* fill in the transfer buffers with pattern */ | ||
707 | ret = spi_test_fill_pattern(spi, test); | ||
708 | if (ret) | ||
709 | return ret; | ||
710 | |||
711 | /* and execute */ | ||
712 | if (test->execute_msg) | ||
713 | ret = test->execute_msg(spi, test, tx, rx); | ||
714 | else | ||
715 | ret = spi_test_execute_msg(spi, test, tx, rx); | ||
716 | |||
717 | /* handle result */ | ||
718 | if (ret == test->expected_return) | ||
719 | return 0; | ||
720 | |||
721 | dev_err(&spi->dev, | ||
722 | "test failed - test returned %i, but we expect %i\n", | ||
723 | ret, test->expected_return); | ||
724 | |||
725 | if (ret) | ||
726 | return ret; | ||
727 | |||
728 | /* if it is 0, as we expected something else, | ||
729 | * then return something special | ||
730 | */ | ||
731 | return -EFAULT; | ||
732 | } | ||
733 | |||
734 | static int spi_test_run_iter(struct spi_device *spi, | ||
735 | const struct spi_test *testtemplate, | ||
736 | void *tx, void *rx, | ||
737 | size_t len, | ||
738 | size_t tx_off, | ||
739 | size_t rx_off | ||
740 | ) | ||
741 | { | ||
742 | struct spi_test test; | ||
743 | int i, tx_count, rx_count; | ||
744 | |||
745 | /* copy the test template to test */ | ||
746 | memcpy(&test, testtemplate, sizeof(test)); | ||
747 | |||
748 | /* set up test->transfers to the correct count */ | ||
749 | if (!test.transfer_count) { | ||
750 | for (i = 0; | ||
751 | (i < SPI_TEST_MAX_TRANSFERS) && test.transfers[i].len; | ||
752 | i++) { | ||
753 | test.transfer_count++; | ||
754 | } | ||
755 | } | ||
756 | |||
757 | /* if iterate_transfer_mask is not set, | ||
758 | * then set it to first transfer only | ||
759 | */ | ||
760 | if (!(test.iterate_transfer_mask & (BIT(test.transfer_count) - 1))) | ||
761 | test.iterate_transfer_mask = 1; | ||
762 | |||
763 | /* count number of transfers with tx/rx_buf != NULL */ | ||
764 | for (i = 0; i < test.transfer_count; i++) { | ||
765 | if (test.transfers[i].tx_buf) | ||
766 | tx_count++; | ||
767 | if (test.transfers[i].rx_buf) | ||
768 | rx_count++; | ||
769 | } | ||
770 | |||
771 | /* in some iteration cases warn and exit early, | ||
772 | * as there is nothing to do, that has not been tested already... | ||
773 | */ | ||
774 | if (tx_off && (!tx_count)) { | ||
775 | dev_warn_once(&spi->dev, | ||
776 | "%s: iterate_tx_off configured with tx_buf==NULL - ignoring\n", | ||
777 | test.description); | ||
778 | return 0; | ||
779 | } | ||
780 | if (rx_off && (!rx_count)) { | ||
781 | dev_warn_once(&spi->dev, | ||
782 | "%s: iterate_rx_off configured with rx_buf==NULL - ignoring\n", | ||
783 | test.description); | ||
784 | return 0; | ||
785 | } | ||
786 | |||
787 | /* write out info */ | ||
788 | if (!(len || tx_off || rx_off)) { | ||
789 | dev_info(&spi->dev, "Running test %s\n", test.description); | ||
790 | } else { | ||
791 | dev_info(&spi->dev, | ||
792 | " with iteration values: len = %zu, tx_off = %zu, rx_off = %zu\n", | ||
793 | len, tx_off, rx_off); | ||
794 | } | ||
795 | |||
796 | /* update in the values from iteration values */ | ||
797 | for (i = 0; i < test.transfer_count; i++) { | ||
798 | /* only when bit in transfer mask is set */ | ||
799 | if (!(test.iterate_transfer_mask & BIT(i))) | ||
800 | continue; | ||
801 | if (len) | ||
802 | test.transfers[i].len = len; | ||
803 | if (test.transfers[i].tx_buf) | ||
804 | test.transfers[i].tx_buf += tx_off; | ||
805 | if (test.transfers[i].tx_buf) | ||
806 | test.transfers[i].rx_buf += rx_off; | ||
807 | } | ||
808 | |||
809 | /* and execute */ | ||
810 | return _spi_test_run_iter(spi, &test, tx, rx); | ||
811 | } | ||
812 | |||
813 | /** | ||
814 | * spi_test_execute_msg - default implementation to run a test | ||
815 | * | ||
816 | * spi: @spi_device on which to run the @spi_message | ||
817 | * test: the test to execute, which already contains @msg | ||
818 | * tx: the tx buffer allocated for the test sequence | ||
819 | * rx: the rx buffer allocated for the test sequence | ||
820 | * | ||
821 | * Returns: error code of spi_sync as well as basic error checking | ||
822 | */ | ||
823 | int spi_test_execute_msg(struct spi_device *spi, struct spi_test *test, | ||
824 | void *tx, void *rx) | ||
825 | { | ||
826 | struct spi_message *msg = &test->msg; | ||
827 | int ret = 0; | ||
828 | int i; | ||
829 | |||
830 | /* only if we do not simulate */ | ||
831 | if (!simulate_only) { | ||
832 | /* dump the complete message before and after the transfer */ | ||
833 | if (dump_messages == 3) | ||
834 | spi_test_dump_message(spi, msg, true); | ||
835 | |||
836 | /* run spi message */ | ||
837 | ret = spi_sync(spi, msg); | ||
838 | if (ret == -ETIMEDOUT) { | ||
839 | dev_info(&spi->dev, | ||
840 | "spi-message timed out - reruning...\n"); | ||
841 | /* rerun after a few explicit schedules */ | ||
842 | for (i = 0; i < 16; i++) | ||
843 | schedule(); | ||
844 | ret = spi_sync(spi, msg); | ||
845 | } | ||
846 | if (ret) { | ||
847 | dev_err(&spi->dev, | ||
848 | "Failed to execute spi_message: %i\n", | ||
849 | ret); | ||
850 | goto exit; | ||
851 | } | ||
852 | |||
853 | /* do some extra error checks */ | ||
854 | if (msg->frame_length != msg->actual_length) { | ||
855 | dev_err(&spi->dev, | ||
856 | "actual length differs from expected\n"); | ||
857 | ret = -EIO; | ||
858 | goto exit; | ||
859 | } | ||
860 | |||
861 | /* run rx-buffer tests */ | ||
862 | ret = spi_test_check_loopback_result(spi, msg, tx, rx); | ||
863 | } | ||
864 | |||
865 | /* if requested or on error dump message (including data) */ | ||
866 | exit: | ||
867 | if (dump_messages || ret) | ||
868 | spi_test_dump_message(spi, msg, | ||
869 | (dump_messages >= 2) || (ret)); | ||
870 | |||
871 | return ret; | ||
872 | } | ||
873 | EXPORT_SYMBOL_GPL(spi_test_execute_msg); | ||
874 | |||
875 | /** | ||
876 | * spi_test_run_test - run an individual spi_test | ||
877 | * including all the relevant iterations on: | ||
878 | * length and buffer alignment | ||
879 | * | ||
880 | * spi: the spi_device to send the messages to | ||
881 | * test: the test which we need to execute | ||
882 | * tx: the tx buffer allocated for the test sequence | ||
883 | * rx: the rx buffer allocated for the test sequence | ||
884 | * | ||
885 | * Returns: status code of spi_sync or other failures | ||
886 | */ | ||
887 | |||
888 | int spi_test_run_test(struct spi_device *spi, const struct spi_test *test, | ||
889 | void *tx, void *rx) | ||
890 | { | ||
891 | int idx_len; | ||
892 | size_t len; | ||
893 | size_t tx_align, rx_align; | ||
894 | int ret; | ||
895 | |||
896 | /* test for transfer limits */ | ||
897 | if (test->transfer_count >= SPI_TEST_MAX_TRANSFERS) { | ||
898 | dev_err(&spi->dev, | ||
899 | "%s: Exceeded max number of transfers with %i\n", | ||
900 | test->description, test->transfer_count); | ||
901 | return -E2BIG; | ||
902 | } | ||
903 | |||
904 | /* setting up some values in spi_message | ||
905 | * based on some settings in spi_master | ||
906 | * some of this can also get done in the run() method | ||
907 | */ | ||
908 | |||
909 | /* iterate over all the iterable values using macros | ||
910 | * (to make it a bit more readable... | ||
911 | */ | ||
912 | #define FOR_EACH_ITERATE(var, defaultvalue) \ | ||
913 | for (idx_##var = -1, var = defaultvalue; \ | ||
914 | ((idx_##var < 0) || \ | ||
915 | ( \ | ||
916 | (idx_##var < SPI_TEST_MAX_ITERATE) && \ | ||
917 | (var = test->iterate_##var[idx_##var]) \ | ||
918 | ) \ | ||
919 | ); \ | ||
920 | idx_##var++) | ||
921 | #define FOR_EACH_ALIGNMENT(var) \ | ||
922 | for (var = 0; \ | ||
923 | var < (test->iterate_##var ? \ | ||
924 | (spi->master->dma_alignment ? \ | ||
925 | spi->master->dma_alignment : \ | ||
926 | test->iterate_##var) : \ | ||
927 | 1); \ | ||
928 | var++) | ||
929 | |||
930 | FOR_EACH_ITERATE(len, 0) { | ||
931 | FOR_EACH_ALIGNMENT(tx_align) { | ||
932 | FOR_EACH_ALIGNMENT(rx_align) { | ||
933 | /* and run the iteration */ | ||
934 | ret = spi_test_run_iter(spi, test, | ||
935 | tx, rx, | ||
936 | len, | ||
937 | tx_align, | ||
938 | rx_align); | ||
939 | if (ret) | ||
940 | return ret; | ||
941 | } | ||
942 | } | ||
943 | } | ||
944 | |||
945 | return 0; | ||
946 | } | ||
947 | EXPORT_SYMBOL_GPL(spi_test_run_test); | ||
948 | |||
949 | /** | ||
950 | * spi_test_run_tests - run an array of spi_messages tests | ||
951 | * @spi: the spi device on which to run the tests | ||
952 | * @tests: NULL-terminated array of @spi_test | ||
953 | * | ||
954 | * Returns: status errors as per @spi_test_run_test() | ||
955 | */ | ||
956 | |||
957 | int spi_test_run_tests(struct spi_device *spi, | ||
958 | struct spi_test *tests) | ||
959 | { | ||
960 | char *rx = NULL, *tx = NULL; | ||
961 | int ret = 0, count = 0; | ||
962 | struct spi_test *test; | ||
963 | |||
964 | /* allocate rx/tx buffers of 128kB size without devm | ||
965 | * in the hope that is on a page boundary | ||
966 | */ | ||
967 | rx = kzalloc(SPI_TEST_MAX_SIZE_PLUS, GFP_KERNEL); | ||
968 | if (!rx) { | ||
969 | ret = -ENOMEM; | ||
970 | goto out; | ||
971 | } | ||
972 | |||
973 | tx = kzalloc(SPI_TEST_MAX_SIZE_PLUS, GFP_KERNEL); | ||
974 | if (!tx) { | ||
975 | ret = -ENOMEM; | ||
976 | goto out; | ||
977 | } | ||
978 | |||
979 | /* now run the individual tests in the table */ | ||
980 | for (test = tests, count = 0; test->description[0]; | ||
981 | test++, count++) { | ||
982 | /* only run test if requested */ | ||
983 | if ((run_only_test > -1) && (count != run_only_test)) | ||
984 | continue; | ||
985 | /* run custom implementation */ | ||
986 | if (test->run_test) | ||
987 | ret = test->run_test(spi, test, tx, rx); | ||
988 | else | ||
989 | ret = spi_test_run_test(spi, test, tx, rx); | ||
990 | if (ret) | ||
991 | goto out; | ||
992 | /* add some delays so that we can easily | ||
993 | * detect the individual tests when using a logic analyzer | ||
994 | * we also add scheduling to avoid potential spi_timeouts... | ||
995 | */ | ||
996 | mdelay(100); | ||
997 | schedule(); | ||
998 | } | ||
999 | |||
1000 | out: | ||
1001 | kfree(rx); | ||
1002 | kfree(tx); | ||
1003 | return ret; | ||
1004 | } | ||
1005 | EXPORT_SYMBOL_GPL(spi_test_run_tests); | ||
diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 7840067062a8..0be89e052428 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c | |||
@@ -95,8 +95,7 @@ struct mtk_spi { | |||
95 | const struct mtk_spi_compatible *dev_comp; | 95 | const struct mtk_spi_compatible *dev_comp; |
96 | }; | 96 | }; |
97 | 97 | ||
98 | static const struct mtk_spi_compatible mt6589_compat; | 98 | static const struct mtk_spi_compatible mtk_common_compat; |
99 | static const struct mtk_spi_compatible mt8135_compat; | ||
100 | static const struct mtk_spi_compatible mt8173_compat = { | 99 | static const struct mtk_spi_compatible mt8173_compat = { |
101 | .need_pad_sel = true, | 100 | .need_pad_sel = true, |
102 | .must_tx = true, | 101 | .must_tx = true, |
@@ -112,9 +111,18 @@ static const struct mtk_chip_config mtk_default_chip_info = { | |||
112 | }; | 111 | }; |
113 | 112 | ||
114 | static const struct of_device_id mtk_spi_of_match[] = { | 113 | static const struct of_device_id mtk_spi_of_match[] = { |
115 | { .compatible = "mediatek,mt6589-spi", .data = (void *)&mt6589_compat }, | 114 | { .compatible = "mediatek,mt2701-spi", |
116 | { .compatible = "mediatek,mt8135-spi", .data = (void *)&mt8135_compat }, | 115 | .data = (void *)&mtk_common_compat, |
117 | { .compatible = "mediatek,mt8173-spi", .data = (void *)&mt8173_compat }, | 116 | }, |
117 | { .compatible = "mediatek,mt6589-spi", | ||
118 | .data = (void *)&mtk_common_compat, | ||
119 | }, | ||
120 | { .compatible = "mediatek,mt8135-spi", | ||
121 | .data = (void *)&mtk_common_compat, | ||
122 | }, | ||
123 | { .compatible = "mediatek,mt8173-spi", | ||
124 | .data = (void *)&mt8173_compat, | ||
125 | }, | ||
118 | {} | 126 | {} |
119 | }; | 127 | }; |
120 | MODULE_DEVICE_TABLE(of, mtk_spi_of_match); | 128 | MODULE_DEVICE_TABLE(of, mtk_spi_of_match); |
@@ -154,9 +162,6 @@ static int mtk_spi_prepare_message(struct spi_master *master, | |||
154 | reg_val |= SPI_CMD_CPOL; | 162 | reg_val |= SPI_CMD_CPOL; |
155 | else | 163 | else |
156 | reg_val &= ~SPI_CMD_CPOL; | 164 | reg_val &= ~SPI_CMD_CPOL; |
157 | writel(reg_val, mdata->base + SPI_CMD_REG); | ||
158 | |||
159 | reg_val = readl(mdata->base + SPI_CMD_REG); | ||
160 | 165 | ||
161 | /* set the mlsbx and mlsbtx */ | 166 | /* set the mlsbx and mlsbtx */ |
162 | if (chip_config->tx_mlsb) | 167 | if (chip_config->tx_mlsb) |
@@ -323,7 +328,8 @@ static int mtk_spi_fifo_transfer(struct spi_master *master, | |||
323 | struct spi_device *spi, | 328 | struct spi_device *spi, |
324 | struct spi_transfer *xfer) | 329 | struct spi_transfer *xfer) |
325 | { | 330 | { |
326 | int cnt; | 331 | int cnt, remainder; |
332 | u32 reg_val; | ||
327 | struct mtk_spi *mdata = spi_master_get_devdata(master); | 333 | struct mtk_spi *mdata = spi_master_get_devdata(master); |
328 | 334 | ||
329 | mdata->cur_transfer = xfer; | 335 | mdata->cur_transfer = xfer; |
@@ -331,12 +337,16 @@ static int mtk_spi_fifo_transfer(struct spi_master *master, | |||
331 | mtk_spi_prepare_transfer(master, xfer); | 337 | mtk_spi_prepare_transfer(master, xfer); |
332 | mtk_spi_setup_packet(master); | 338 | mtk_spi_setup_packet(master); |
333 | 339 | ||
334 | if (xfer->len % 4) | 340 | cnt = xfer->len / 4; |
335 | cnt = xfer->len / 4 + 1; | ||
336 | else | ||
337 | cnt = xfer->len / 4; | ||
338 | iowrite32_rep(mdata->base + SPI_TX_DATA_REG, xfer->tx_buf, cnt); | 341 | iowrite32_rep(mdata->base + SPI_TX_DATA_REG, xfer->tx_buf, cnt); |
339 | 342 | ||
343 | remainder = xfer->len % 4; | ||
344 | if (remainder > 0) { | ||
345 | reg_val = 0; | ||
346 | memcpy(®_val, xfer->tx_buf + (cnt * 4), remainder); | ||
347 | writel(reg_val, mdata->base + SPI_TX_DATA_REG); | ||
348 | } | ||
349 | |||
340 | mtk_spi_enable_transfer(master); | 350 | mtk_spi_enable_transfer(master); |
341 | 351 | ||
342 | return 1; | 352 | return 1; |
@@ -418,7 +428,7 @@ static int mtk_spi_setup(struct spi_device *spi) | |||
418 | 428 | ||
419 | static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) | 429 | static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) |
420 | { | 430 | { |
421 | u32 cmd, reg_val, cnt; | 431 | u32 cmd, reg_val, cnt, remainder; |
422 | struct spi_master *master = dev_id; | 432 | struct spi_master *master = dev_id; |
423 | struct mtk_spi *mdata = spi_master_get_devdata(master); | 433 | struct mtk_spi *mdata = spi_master_get_devdata(master); |
424 | struct spi_transfer *trans = mdata->cur_transfer; | 434 | struct spi_transfer *trans = mdata->cur_transfer; |
@@ -431,12 +441,15 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) | |||
431 | 441 | ||
432 | if (!master->can_dma(master, master->cur_msg->spi, trans)) { | 442 | if (!master->can_dma(master, master->cur_msg->spi, trans)) { |
433 | if (trans->rx_buf) { | 443 | if (trans->rx_buf) { |
434 | if (mdata->xfer_len % 4) | 444 | cnt = mdata->xfer_len / 4; |
435 | cnt = mdata->xfer_len / 4 + 1; | ||
436 | else | ||
437 | cnt = mdata->xfer_len / 4; | ||
438 | ioread32_rep(mdata->base + SPI_RX_DATA_REG, | 445 | ioread32_rep(mdata->base + SPI_RX_DATA_REG, |
439 | trans->rx_buf, cnt); | 446 | trans->rx_buf, cnt); |
447 | remainder = mdata->xfer_len % 4; | ||
448 | if (remainder > 0) { | ||
449 | reg_val = readl(mdata->base + SPI_RX_DATA_REG); | ||
450 | memcpy(trans->rx_buf + (cnt * 4), | ||
451 | ®_val, remainder); | ||
452 | } | ||
440 | } | 453 | } |
441 | spi_finalize_current_transfer(master); | 454 | spi_finalize_current_transfer(master); |
442 | return IRQ_HANDLED; | 455 | return IRQ_HANDLED; |
@@ -610,7 +623,8 @@ static int mtk_spi_probe(struct platform_device *pdev) | |||
610 | ret = clk_set_parent(mdata->sel_clk, mdata->parent_clk); | 623 | ret = clk_set_parent(mdata->sel_clk, mdata->parent_clk); |
611 | if (ret < 0) { | 624 | if (ret < 0) { |
612 | dev_err(&pdev->dev, "failed to clk_set_parent (%d)\n", ret); | 625 | dev_err(&pdev->dev, "failed to clk_set_parent (%d)\n", ret); |
613 | goto err_disable_clk; | 626 | clk_disable_unprepare(mdata->spi_clk); |
627 | goto err_put_master; | ||
614 | } | 628 | } |
615 | 629 | ||
616 | clk_disable_unprepare(mdata->spi_clk); | 630 | clk_disable_unprepare(mdata->spi_clk); |
@@ -620,7 +634,7 @@ static int mtk_spi_probe(struct platform_device *pdev) | |||
620 | ret = devm_spi_register_master(&pdev->dev, master); | 634 | ret = devm_spi_register_master(&pdev->dev, master); |
621 | if (ret) { | 635 | if (ret) { |
622 | dev_err(&pdev->dev, "failed to register master (%d)\n", ret); | 636 | dev_err(&pdev->dev, "failed to register master (%d)\n", ret); |
623 | goto err_put_master; | 637 | goto err_disable_runtime_pm; |
624 | } | 638 | } |
625 | 639 | ||
626 | if (mdata->dev_comp->need_pad_sel) { | 640 | if (mdata->dev_comp->need_pad_sel) { |
@@ -629,14 +643,14 @@ static int mtk_spi_probe(struct platform_device *pdev) | |||
629 | "pad_num does not match num_chipselect(%d != %d)\n", | 643 | "pad_num does not match num_chipselect(%d != %d)\n", |
630 | mdata->pad_num, master->num_chipselect); | 644 | mdata->pad_num, master->num_chipselect); |
631 | ret = -EINVAL; | 645 | ret = -EINVAL; |
632 | goto err_put_master; | 646 | goto err_disable_runtime_pm; |
633 | } | 647 | } |
634 | 648 | ||
635 | if (!master->cs_gpios && master->num_chipselect > 1) { | 649 | if (!master->cs_gpios && master->num_chipselect > 1) { |
636 | dev_err(&pdev->dev, | 650 | dev_err(&pdev->dev, |
637 | "cs_gpios not specified and num_chipselect > 1\n"); | 651 | "cs_gpios not specified and num_chipselect > 1\n"); |
638 | ret = -EINVAL; | 652 | ret = -EINVAL; |
639 | goto err_put_master; | 653 | goto err_disable_runtime_pm; |
640 | } | 654 | } |
641 | 655 | ||
642 | if (master->cs_gpios) { | 656 | if (master->cs_gpios) { |
@@ -647,7 +661,7 @@ static int mtk_spi_probe(struct platform_device *pdev) | |||
647 | if (ret) { | 661 | if (ret) { |
648 | dev_err(&pdev->dev, | 662 | dev_err(&pdev->dev, |
649 | "can't get CS GPIO %i\n", i); | 663 | "can't get CS GPIO %i\n", i); |
650 | goto err_put_master; | 664 | goto err_disable_runtime_pm; |
651 | } | 665 | } |
652 | } | 666 | } |
653 | } | 667 | } |
@@ -655,8 +669,8 @@ static int mtk_spi_probe(struct platform_device *pdev) | |||
655 | 669 | ||
656 | return 0; | 670 | return 0; |
657 | 671 | ||
658 | err_disable_clk: | 672 | err_disable_runtime_pm: |
659 | clk_disable_unprepare(mdata->spi_clk); | 673 | pm_runtime_disable(&pdev->dev); |
660 | err_put_master: | 674 | err_put_master: |
661 | spi_master_put(master); | 675 | spi_master_put(master); |
662 | 676 | ||
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 1f8903d356e5..7273820275e9 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/dma-mapping.h> | 24 | #include <linux/dma-mapping.h> |
25 | #include <linux/dmaengine.h> | 25 | #include <linux/dmaengine.h> |
26 | #include <linux/omap-dma.h> | 26 | #include <linux/omap-dma.h> |
27 | #include <linux/pinctrl/consumer.h> | ||
27 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
28 | #include <linux/err.h> | 29 | #include <linux/err.h> |
29 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
@@ -1024,6 +1025,16 @@ static int omap2_mcspi_setup(struct spi_device *spi) | |||
1024 | spi->controller_state = cs; | 1025 | spi->controller_state = cs; |
1025 | /* Link this to context save list */ | 1026 | /* Link this to context save list */ |
1026 | list_add_tail(&cs->node, &ctx->cs); | 1027 | list_add_tail(&cs->node, &ctx->cs); |
1028 | |||
1029 | if (gpio_is_valid(spi->cs_gpio)) { | ||
1030 | ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev)); | ||
1031 | if (ret) { | ||
1032 | dev_err(&spi->dev, "failed to request gpio\n"); | ||
1033 | return ret; | ||
1034 | } | ||
1035 | gpio_direction_output(spi->cs_gpio, | ||
1036 | !(spi->mode & SPI_CS_HIGH)); | ||
1037 | } | ||
1027 | } | 1038 | } |
1028 | 1039 | ||
1029 | if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) { | 1040 | if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) { |
@@ -1032,15 +1043,6 @@ static int omap2_mcspi_setup(struct spi_device *spi) | |||
1032 | return ret; | 1043 | return ret; |
1033 | } | 1044 | } |
1034 | 1045 | ||
1035 | if (gpio_is_valid(spi->cs_gpio)) { | ||
1036 | ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev)); | ||
1037 | if (ret) { | ||
1038 | dev_err(&spi->dev, "failed to request gpio\n"); | ||
1039 | return ret; | ||
1040 | } | ||
1041 | gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); | ||
1042 | } | ||
1043 | |||
1044 | ret = pm_runtime_get_sync(mcspi->dev); | 1046 | ret = pm_runtime_get_sync(mcspi->dev); |
1045 | if (ret < 0) | 1047 | if (ret < 0) |
1046 | return ret; | 1048 | return ret; |
@@ -1536,14 +1538,23 @@ static int omap2_mcspi_resume(struct device *dev) | |||
1536 | } | 1538 | } |
1537 | pm_runtime_mark_last_busy(mcspi->dev); | 1539 | pm_runtime_mark_last_busy(mcspi->dev); |
1538 | pm_runtime_put_autosuspend(mcspi->dev); | 1540 | pm_runtime_put_autosuspend(mcspi->dev); |
1539 | return 0; | 1541 | |
1542 | return pinctrl_pm_select_default_state(dev); | ||
1543 | } | ||
1544 | |||
1545 | static int omap2_mcspi_suspend(struct device *dev) | ||
1546 | { | ||
1547 | return pinctrl_pm_select_sleep_state(dev); | ||
1540 | } | 1548 | } |
1549 | |||
1541 | #else | 1550 | #else |
1551 | #define omap2_mcspi_suspend NULL | ||
1542 | #define omap2_mcspi_resume NULL | 1552 | #define omap2_mcspi_resume NULL |
1543 | #endif | 1553 | #endif |
1544 | 1554 | ||
1545 | static const struct dev_pm_ops omap2_mcspi_pm_ops = { | 1555 | static const struct dev_pm_ops omap2_mcspi_pm_ops = { |
1546 | .resume = omap2_mcspi_resume, | 1556 | .resume = omap2_mcspi_resume, |
1557 | .suspend = omap2_mcspi_suspend, | ||
1547 | .runtime_resume = omap_mcspi_runtime_resume, | 1558 | .runtime_resume = omap_mcspi_runtime_resume, |
1548 | }; | 1559 | }; |
1549 | 1560 | ||
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index b25dc71b0ea9..ab9914ad8365 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c | |||
@@ -1567,9 +1567,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) | |||
1567 | if (!is_quark_x1000_ssp(drv_data)) | 1567 | if (!is_quark_x1000_ssp(drv_data)) |
1568 | pxa2xx_spi_write(drv_data, SSPSP, 0); | 1568 | pxa2xx_spi_write(drv_data, SSPSP, 0); |
1569 | 1569 | ||
1570 | if (is_lpss_ssp(drv_data)) | ||
1571 | lpss_ssp_setup(drv_data); | ||
1572 | |||
1573 | if (is_lpss_ssp(drv_data)) { | 1570 | if (is_lpss_ssp(drv_data)) { |
1574 | lpss_ssp_setup(drv_data); | 1571 | lpss_ssp_setup(drv_data); |
1575 | config = lpss_get_config(drv_data); | 1572 | config = lpss_get_config(drv_data); |
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 8e86e7f6663a..5a76a50063b5 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c | |||
@@ -133,7 +133,6 @@ | |||
133 | struct s3c64xx_spi_dma_data { | 133 | struct s3c64xx_spi_dma_data { |
134 | struct dma_chan *ch; | 134 | struct dma_chan *ch; |
135 | enum dma_transfer_direction direction; | 135 | enum dma_transfer_direction direction; |
136 | unsigned int dmach; | ||
137 | }; | 136 | }; |
138 | 137 | ||
139 | /** | 138 | /** |
@@ -325,7 +324,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) | |||
325 | 324 | ||
326 | /* Acquire DMA channels */ | 325 | /* Acquire DMA channels */ |
327 | sdd->rx_dma.ch = dma_request_slave_channel_compat(mask, filter, | 326 | sdd->rx_dma.ch = dma_request_slave_channel_compat(mask, filter, |
328 | (void *)(long)sdd->rx_dma.dmach, dev, "rx"); | 327 | sdd->cntrlr_info->dma_rx, dev, "rx"); |
329 | if (!sdd->rx_dma.ch) { | 328 | if (!sdd->rx_dma.ch) { |
330 | dev_err(dev, "Failed to get RX DMA channel\n"); | 329 | dev_err(dev, "Failed to get RX DMA channel\n"); |
331 | ret = -EBUSY; | 330 | ret = -EBUSY; |
@@ -334,7 +333,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) | |||
334 | spi->dma_rx = sdd->rx_dma.ch; | 333 | spi->dma_rx = sdd->rx_dma.ch; |
335 | 334 | ||
336 | sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter, | 335 | sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter, |
337 | (void *)(long)sdd->tx_dma.dmach, dev, "tx"); | 336 | sdd->cntrlr_info->dma_tx, dev, "tx"); |
338 | if (!sdd->tx_dma.ch) { | 337 | if (!sdd->tx_dma.ch) { |
339 | dev_err(dev, "Failed to get TX DMA channel\n"); | 338 | dev_err(dev, "Failed to get TX DMA channel\n"); |
340 | ret = -EBUSY; | 339 | ret = -EBUSY; |
@@ -1028,7 +1027,6 @@ static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config( | |||
1028 | static int s3c64xx_spi_probe(struct platform_device *pdev) | 1027 | static int s3c64xx_spi_probe(struct platform_device *pdev) |
1029 | { | 1028 | { |
1030 | struct resource *mem_res; | 1029 | struct resource *mem_res; |
1031 | struct resource *res; | ||
1032 | struct s3c64xx_spi_driver_data *sdd; | 1030 | struct s3c64xx_spi_driver_data *sdd; |
1033 | struct s3c64xx_spi_info *sci = dev_get_platdata(&pdev->dev); | 1031 | struct s3c64xx_spi_info *sci = dev_get_platdata(&pdev->dev); |
1034 | struct spi_master *master; | 1032 | struct spi_master *master; |
@@ -1087,20 +1085,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) | |||
1087 | 1085 | ||
1088 | sdd->cur_bpw = 8; | 1086 | sdd->cur_bpw = 8; |
1089 | 1087 | ||
1090 | if (!sdd->pdev->dev.of_node) { | 1088 | if (!sdd->pdev->dev.of_node && (!sci->dma_tx || !sci->dma_rx)) { |
1091 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 1089 | dev_warn(&pdev->dev, "Unable to get SPI tx/rx DMA data. Switching to poll mode\n"); |
1092 | if (!res) { | 1090 | sdd->port_conf->quirks = S3C64XX_SPI_QUIRK_POLL; |
1093 | dev_warn(&pdev->dev, "Unable to get SPI tx dma resource. Switching to poll mode\n"); | ||
1094 | sdd->port_conf->quirks = S3C64XX_SPI_QUIRK_POLL; | ||
1095 | } else | ||
1096 | sdd->tx_dma.dmach = res->start; | ||
1097 | |||
1098 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
1099 | if (!res) { | ||
1100 | dev_warn(&pdev->dev, "Unable to get SPI rx dma resource. Switching to poll mode\n"); | ||
1101 | sdd->port_conf->quirks = S3C64XX_SPI_QUIRK_POLL; | ||
1102 | } else | ||
1103 | sdd->rx_dma.dmach = res->start; | ||
1104 | } | 1091 | } |
1105 | 1092 | ||
1106 | sdd->tx_dma.direction = DMA_MEM_TO_DEV; | 1093 | sdd->tx_dma.direction = DMA_MEM_TO_DEV; |
@@ -1197,9 +1184,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) | |||
1197 | 1184 | ||
1198 | dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n", | 1185 | dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n", |
1199 | sdd->port_id, master->num_chipselect); | 1186 | sdd->port_id, master->num_chipselect); |
1200 | dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tFIFO %dbytes\tDMA=[Rx-%d, Tx-%d]\n", | 1187 | dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tFIFO %dbytes\tDMA=[Rx-%p, Tx-%p]\n", |
1201 | mem_res, (FIFO_LVL_MASK(sdd) >> 1) + 1, | 1188 | mem_res, (FIFO_LVL_MASK(sdd) >> 1) + 1, |
1202 | sdd->rx_dma.dmach, sdd->tx_dma.dmach); | 1189 | sci->dma_rx, sci->dma_tx); |
1203 | 1190 | ||
1204 | pm_runtime_mark_last_busy(&pdev->dev); | 1191 | pm_runtime_mark_last_busy(&pdev->dev); |
1205 | pm_runtime_put_autosuspend(&pdev->dev); | 1192 | pm_runtime_put_autosuspend(&pdev->dev); |
@@ -1370,12 +1357,6 @@ static const struct platform_device_id s3c64xx_spi_driver_ids[] = { | |||
1370 | }, { | 1357 | }, { |
1371 | .name = "s3c6410-spi", | 1358 | .name = "s3c6410-spi", |
1372 | .driver_data = (kernel_ulong_t)&s3c6410_spi_port_config, | 1359 | .driver_data = (kernel_ulong_t)&s3c6410_spi_port_config, |
1373 | }, { | ||
1374 | .name = "s5pv210-spi", | ||
1375 | .driver_data = (kernel_ulong_t)&s5pv210_spi_port_config, | ||
1376 | }, { | ||
1377 | .name = "exynos4210-spi", | ||
1378 | .driver_data = (kernel_ulong_t)&exynos4_spi_port_config, | ||
1379 | }, | 1360 | }, |
1380 | { }, | 1361 | { }, |
1381 | }; | 1362 | }; |
diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index fbb0a4d74e91..1ddd9e2309b6 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c | |||
@@ -140,6 +140,9 @@ static void sun4i_spi_set_cs(struct spi_device *spi, bool enable) | |||
140 | reg &= ~SUN4I_CTL_CS_MASK; | 140 | reg &= ~SUN4I_CTL_CS_MASK; |
141 | reg |= SUN4I_CTL_CS(spi->chip_select); | 141 | reg |= SUN4I_CTL_CS(spi->chip_select); |
142 | 142 | ||
143 | /* We want to control the chip select manually */ | ||
144 | reg |= SUN4I_CTL_CS_MANUAL; | ||
145 | |||
143 | if (enable) | 146 | if (enable) |
144 | reg |= SUN4I_CTL_CS_LEVEL; | 147 | reg |= SUN4I_CTL_CS_LEVEL; |
145 | else | 148 | else |
@@ -222,15 +225,12 @@ static int sun4i_spi_transfer_one(struct spi_master *master, | |||
222 | else | 225 | else |
223 | reg |= SUN4I_CTL_DHB; | 226 | reg |= SUN4I_CTL_DHB; |
224 | 227 | ||
225 | /* We want to control the chip select manually */ | ||
226 | reg |= SUN4I_CTL_CS_MANUAL; | ||
227 | |||
228 | sun4i_spi_write(sspi, SUN4I_CTL_REG, reg); | 228 | sun4i_spi_write(sspi, SUN4I_CTL_REG, reg); |
229 | 229 | ||
230 | /* Ensure that we have a parent clock fast enough */ | 230 | /* Ensure that we have a parent clock fast enough */ |
231 | mclk_rate = clk_get_rate(sspi->mclk); | 231 | mclk_rate = clk_get_rate(sspi->mclk); |
232 | if (mclk_rate < (2 * spi->max_speed_hz)) { | 232 | if (mclk_rate < (2 * tfr->speed_hz)) { |
233 | clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz); | 233 | clk_set_rate(sspi->mclk, 2 * tfr->speed_hz); |
234 | mclk_rate = clk_get_rate(sspi->mclk); | 234 | mclk_rate = clk_get_rate(sspi->mclk); |
235 | } | 235 | } |
236 | 236 | ||
@@ -248,14 +248,14 @@ static int sun4i_spi_transfer_one(struct spi_master *master, | |||
248 | * First try CDR2, and if we can't reach the expected | 248 | * First try CDR2, and if we can't reach the expected |
249 | * frequency, fall back to CDR1. | 249 | * frequency, fall back to CDR1. |
250 | */ | 250 | */ |
251 | div = mclk_rate / (2 * spi->max_speed_hz); | 251 | div = mclk_rate / (2 * tfr->speed_hz); |
252 | if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) { | 252 | if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) { |
253 | if (div > 0) | 253 | if (div > 0) |
254 | div--; | 254 | div--; |
255 | 255 | ||
256 | reg = SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS; | 256 | reg = SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS; |
257 | } else { | 257 | } else { |
258 | div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz); | 258 | div = ilog2(mclk_rate) - ilog2(tfr->speed_hz); |
259 | reg = SUN4I_CLK_CTL_CDR1(div); | 259 | reg = SUN4I_CLK_CTL_CDR1(div); |
260 | } | 260 | } |
261 | 261 | ||
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index ac48f59705a8..42e2c4bd690a 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c | |||
@@ -217,8 +217,8 @@ static int sun6i_spi_transfer_one(struct spi_master *master, | |||
217 | 217 | ||
218 | /* Ensure that we have a parent clock fast enough */ | 218 | /* Ensure that we have a parent clock fast enough */ |
219 | mclk_rate = clk_get_rate(sspi->mclk); | 219 | mclk_rate = clk_get_rate(sspi->mclk); |
220 | if (mclk_rate < (2 * spi->max_speed_hz)) { | 220 | if (mclk_rate < (2 * tfr->speed_hz)) { |
221 | clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz); | 221 | clk_set_rate(sspi->mclk, 2 * tfr->speed_hz); |
222 | mclk_rate = clk_get_rate(sspi->mclk); | 222 | mclk_rate = clk_get_rate(sspi->mclk); |
223 | } | 223 | } |
224 | 224 | ||
@@ -236,14 +236,14 @@ static int sun6i_spi_transfer_one(struct spi_master *master, | |||
236 | * First try CDR2, and if we can't reach the expected | 236 | * First try CDR2, and if we can't reach the expected |
237 | * frequency, fall back to CDR1. | 237 | * frequency, fall back to CDR1. |
238 | */ | 238 | */ |
239 | div = mclk_rate / (2 * spi->max_speed_hz); | 239 | div = mclk_rate / (2 * tfr->speed_hz); |
240 | if (div <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) { | 240 | if (div <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) { |
241 | if (div > 0) | 241 | if (div > 0) |
242 | div--; | 242 | div--; |
243 | 243 | ||
244 | reg = SUN6I_CLK_CTL_CDR2(div) | SUN6I_CLK_CTL_DRS; | 244 | reg = SUN6I_CLK_CTL_CDR2(div) | SUN6I_CLK_CTL_DRS; |
245 | } else { | 245 | } else { |
246 | div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz); | 246 | div = ilog2(mclk_rate) - ilog2(tfr->speed_hz); |
247 | reg = SUN6I_CLK_CTL_CDR1(div); | 247 | reg = SUN6I_CLK_CTL_CDR1(div); |
248 | } | 248 | } |
249 | 249 | ||
diff --git a/drivers/spi/spi-test.h b/drivers/spi/spi-test.h new file mode 100644 index 000000000000..922c52833239 --- /dev/null +++ b/drivers/spi/spi-test.h | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * linux/drivers/spi/spi-test.h | ||
3 | * | ||
4 | * (c) Martin Sperl <kernel@martin.sperl.org> | ||
5 | * | ||
6 | * spi_test definitions | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #include <linux/spi/spi.h> | ||
20 | |||
21 | #define SPI_TEST_MAX_TRANSFERS 4 | ||
22 | #define SPI_TEST_MAX_SIZE (32 * PAGE_SIZE) | ||
23 | #define SPI_TEST_MAX_ITERATE 32 | ||
24 | |||
25 | /* the "dummy" start addresses used in spi_test | ||
26 | * these addresses get translated at a later stage | ||
27 | */ | ||
28 | #define RX_START BIT(30) | ||
29 | #define TX_START BIT(31) | ||
30 | #define RX(off) ((void *)(RX_START + off)) | ||
31 | #define TX(off) ((void *)(TX_START + off)) | ||
32 | |||
33 | /* some special defines for offsets */ | ||
34 | #define SPI_TEST_MAX_SIZE_HALF BIT(29) | ||
35 | |||
36 | /* detection pattern for unfinished reads... | ||
37 | * - 0x00 or 0xff could be valid levels for tx_buf = NULL, | ||
38 | * so we do not use either of them | ||
39 | */ | ||
40 | #define SPI_TEST_PATTERN_UNWRITTEN 0xAA | ||
41 | #define SPI_TEST_PATTERN_DO_NOT_WRITE 0x55 | ||
42 | #define SPI_TEST_CHECK_DO_NOT_WRITE 64 | ||
43 | |||
44 | /** | ||
45 | * struct spi_test - describes a specific (set of) tests to execute | ||
46 | * | ||
47 | * @description: description of the test | ||
48 | * | ||
49 | * @msg: a template @spi_message usedfor the default settings | ||
50 | * @transfers: array of @spi_transfers that are part of the | ||
51 | * resulting spi_message. The first transfer with len == 0 | ||
52 | * signifies the end of the list | ||
53 | * @transfer_count: normally computed number of transfers with len > 0 | ||
54 | * | ||
55 | * @run_test: run a specific spi_test - this allows to override | ||
56 | * the default implementation of @spi_test_run_transfer | ||
57 | * either to add some custom filters for a specific test | ||
58 | * or to effectively run some very custom tests... | ||
59 | * @execute_msg: run the spi_message for real - this allows to override | ||
60 | * @spi_test_execute_msg to apply final modifications | ||
61 | * on the spi_message | ||
62 | * @expected_return: the expected return code - in some cases we want to | ||
63 | * test also for error conditions | ||
64 | * | ||
65 | * @iterate_len: list of length to iterate on (in addition to the | ||
66 | * explicitly set @spi_transfer.len) | ||
67 | * @iterate_tx_align: change the alignment of @spi_transfer.tx_buf | ||
68 | * for all values in the below range if set. | ||
69 | * the ranges are: | ||
70 | * [0 : @spi_master.dma_alignment[ if set | ||
71 | * [0 : iterate_tx_align[ if unset | ||
72 | * @iterate_rx_align: change the alignment of @spi_transfer.rx_buf | ||
73 | * see @iterate_tx_align for details | ||
74 | * @iterate_transfer_mask: the bitmask of transfers to which the iterations | ||
75 | * apply - if 0, then it applies to all transfer | ||
76 | * | ||
77 | * @fill_option: define the way how tx_buf is filled | ||
78 | * @fill_pattern: fill pattern to apply to the tx_buf | ||
79 | * (used in some of the @fill_options) | ||
80 | */ | ||
81 | |||
82 | struct spi_test { | ||
83 | char description[64]; | ||
84 | struct spi_message msg; | ||
85 | struct spi_transfer transfers[SPI_TEST_MAX_TRANSFERS]; | ||
86 | unsigned int transfer_count; | ||
87 | int (*run_test)(struct spi_device *spi, struct spi_test *test, | ||
88 | void *tx, void *rx); | ||
89 | int (*execute_msg)(struct spi_device *spi, struct spi_test *test, | ||
90 | void *tx, void *rx); | ||
91 | int expected_return; | ||
92 | /* iterate over all the non-zero values */ | ||
93 | int iterate_len[SPI_TEST_MAX_ITERATE]; | ||
94 | int iterate_tx_align; | ||
95 | int iterate_rx_align; | ||
96 | u32 iterate_transfer_mask; | ||
97 | /* the tx-fill operation */ | ||
98 | u32 fill_option; | ||
99 | #define FILL_MEMSET_8 0 /* just memset with 8 bit */ | ||
100 | #define FILL_MEMSET_16 1 /* just memset with 16 bit */ | ||
101 | #define FILL_MEMSET_24 2 /* just memset with 24 bit */ | ||
102 | #define FILL_MEMSET_32 3 /* just memset with 32 bit */ | ||
103 | #define FILL_COUNT_8 4 /* fill with a 8 byte counter */ | ||
104 | #define FILL_COUNT_16 5 /* fill with a 16 bit counter */ | ||
105 | #define FILL_COUNT_24 6 /* fill with a 24 bit counter */ | ||
106 | #define FILL_COUNT_32 7 /* fill with a 32 bit counter */ | ||
107 | #define FILL_TRANSFER_BYTE_8 8 /* fill with the transfer byte - 8 bit */ | ||
108 | #define FILL_TRANSFER_BYTE_16 9 /* fill with the transfer byte - 16 bit */ | ||
109 | #define FILL_TRANSFER_BYTE_24 10 /* fill with the transfer byte - 24 bit */ | ||
110 | #define FILL_TRANSFER_BYTE_32 11 /* fill with the transfer byte - 32 bit */ | ||
111 | #define FILL_TRANSFER_NUM 16 /* fill with the transfer number */ | ||
112 | u32 fill_pattern; | ||
113 | }; | ||
114 | |||
115 | /* default implementation for @spi_test.run_test */ | ||
116 | int spi_test_run_test(struct spi_device *spi, | ||
117 | const struct spi_test *test, | ||
118 | void *tx, void *rx); | ||
119 | |||
120 | /* default implementation for @spi_test.execute_msg */ | ||
121 | int spi_test_execute_msg(struct spi_device *spi, | ||
122 | struct spi_test *test, | ||
123 | void *tx, void *rx); | ||
124 | |||
125 | /* function to execute a set of tests */ | ||
126 | int spi_test_run_tests(struct spi_device *spi, | ||
127 | struct spi_test *tests); | ||
128 | |||
129 | /* some of the default @spi_transfer.len to test */ | ||
130 | #define ITERATE_LEN 2, 3, 7, 11, 16, 31, 32, 64, 97, 128, 251, 256, \ | ||
131 | 1021, 1024, 1031, 4093, PAGE_SIZE, 4099, 65536, 65537 | ||
132 | |||
133 | #define ITERATE_MAX_LEN ITERATE_LEN, SPI_TEST_MAX_SIZE - 1, SPI_TEST_MAX_SIZE | ||
134 | |||
135 | /* the default alignment to test */ | ||
136 | #define ITERATE_ALIGN sizeof(int) | ||
diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index f23f36ebaf3d..aab9b492c627 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c | |||
@@ -917,9 +917,7 @@ static int zynqmp_qspi_start_transfer(struct spi_master *master, | |||
917 | */ | 917 | */ |
918 | static int __maybe_unused zynqmp_qspi_suspend(struct device *dev) | 918 | static int __maybe_unused zynqmp_qspi_suspend(struct device *dev) |
919 | { | 919 | { |
920 | struct platform_device *pdev = container_of(dev, | 920 | struct platform_device *pdev = to_platform_device(dev); |
921 | struct platform_device, | ||
922 | dev); | ||
923 | struct spi_master *master = platform_get_drvdata(pdev); | 921 | struct spi_master *master = platform_get_drvdata(pdev); |
924 | 922 | ||
925 | spi_master_suspend(master); | 923 | spi_master_suspend(master); |
@@ -940,9 +938,7 @@ static int __maybe_unused zynqmp_qspi_suspend(struct device *dev) | |||
940 | */ | 938 | */ |
941 | static int __maybe_unused zynqmp_qspi_resume(struct device *dev) | 939 | static int __maybe_unused zynqmp_qspi_resume(struct device *dev) |
942 | { | 940 | { |
943 | struct platform_device *pdev = container_of(dev, | 941 | struct platform_device *pdev = to_platform_device(dev); |
944 | struct platform_device, | ||
945 | dev); | ||
946 | struct spi_master *master = platform_get_drvdata(pdev); | 942 | struct spi_master *master = platform_get_drvdata(pdev); |
947 | struct zynqmp_qspi *xqspi = spi_master_get_devdata(master); | 943 | struct zynqmp_qspi *xqspi = spi_master_get_devdata(master); |
948 | int ret = 0; | 944 | int ret = 0; |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 151b01c25b40..47eff8012a77 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -84,8 +84,7 @@ static ssize_t spi_device_##field##_show(struct device *dev, \ | |||
84 | struct device_attribute *attr, \ | 84 | struct device_attribute *attr, \ |
85 | char *buf) \ | 85 | char *buf) \ |
86 | { \ | 86 | { \ |
87 | struct spi_device *spi = container_of(dev, \ | 87 | struct spi_device *spi = to_spi_device(dev); \ |
88 | struct spi_device, dev); \ | ||
89 | return spi_statistics_##field##_show(&spi->statistics, buf); \ | 88 | return spi_statistics_##field##_show(&spi->statistics, buf); \ |
90 | } \ | 89 | } \ |
91 | static struct device_attribute dev_attr_spi_device_##field = { \ | 90 | static struct device_attribute dev_attr_spi_device_##field = { \ |
@@ -605,6 +604,24 @@ struct spi_device *spi_new_device(struct spi_master *master, | |||
605 | } | 604 | } |
606 | EXPORT_SYMBOL_GPL(spi_new_device); | 605 | EXPORT_SYMBOL_GPL(spi_new_device); |
607 | 606 | ||
607 | /** | ||
608 | * spi_unregister_device - unregister a single SPI device | ||
609 | * @spi: spi_device to unregister | ||
610 | * | ||
611 | * Start making the passed SPI device vanish. Normally this would be handled | ||
612 | * by spi_unregister_master(). | ||
613 | */ | ||
614 | void spi_unregister_device(struct spi_device *spi) | ||
615 | { | ||
616 | if (!spi) | ||
617 | return; | ||
618 | |||
619 | if (spi->dev.of_node) | ||
620 | of_node_clear_flag(spi->dev.of_node, OF_POPULATED); | ||
621 | device_unregister(&spi->dev); | ||
622 | } | ||
623 | EXPORT_SYMBOL_GPL(spi_unregister_device); | ||
624 | |||
608 | static void spi_match_master_to_boardinfo(struct spi_master *master, | 625 | static void spi_match_master_to_boardinfo(struct spi_master *master, |
609 | struct spi_board_info *bi) | 626 | struct spi_board_info *bi) |
610 | { | 627 | { |
@@ -1548,6 +1565,8 @@ static void of_register_spi_devices(struct spi_master *master) | |||
1548 | return; | 1565 | return; |
1549 | 1566 | ||
1550 | for_each_available_child_of_node(master->dev.of_node, nc) { | 1567 | for_each_available_child_of_node(master->dev.of_node, nc) { |
1568 | if (of_node_test_and_set_flag(nc, OF_POPULATED)) | ||
1569 | continue; | ||
1551 | spi = of_register_spi_device(master, nc); | 1570 | spi = of_register_spi_device(master, nc); |
1552 | if (IS_ERR(spi)) | 1571 | if (IS_ERR(spi)) |
1553 | dev_warn(&master->dev, "Failed to create SPI device for %s\n", | 1572 | dev_warn(&master->dev, "Failed to create SPI device for %s\n", |
@@ -2636,6 +2655,11 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action, | |||
2636 | if (master == NULL) | 2655 | if (master == NULL) |
2637 | return NOTIFY_OK; /* not for us */ | 2656 | return NOTIFY_OK; /* not for us */ |
2638 | 2657 | ||
2658 | if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) { | ||
2659 | put_device(&master->dev); | ||
2660 | return NOTIFY_OK; | ||
2661 | } | ||
2662 | |||
2639 | spi = of_register_spi_device(master, rd->dn); | 2663 | spi = of_register_spi_device(master, rd->dn); |
2640 | put_device(&master->dev); | 2664 | put_device(&master->dev); |
2641 | 2665 | ||
@@ -2647,6 +2671,10 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action, | |||
2647 | break; | 2671 | break; |
2648 | 2672 | ||
2649 | case OF_RECONFIG_CHANGE_REMOVE: | 2673 | case OF_RECONFIG_CHANGE_REMOVE: |
2674 | /* already depopulated? */ | ||
2675 | if (!of_node_check_flag(rd->dn, OF_POPULATED)) | ||
2676 | return NOTIFY_OK; | ||
2677 | |||
2650 | /* find our device by node */ | 2678 | /* find our device by node */ |
2651 | spi = of_find_spi_device_by_node(rd->dn); | 2679 | spi = of_find_spi_device_by_node(rd->dn); |
2652 | if (spi == NULL) | 2680 | if (spi == NULL) |
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index d0e7dfc647cf..e3c19f30f591 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c | |||
@@ -284,7 +284,7 @@ static int spidev_message(struct spidev_data *spidev, | |||
284 | k_tmp->speed_hz = spidev->speed_hz; | 284 | k_tmp->speed_hz = spidev->speed_hz; |
285 | #ifdef VERBOSE | 285 | #ifdef VERBOSE |
286 | dev_dbg(&spidev->spi->dev, | 286 | dev_dbg(&spidev->spi->dev, |
287 | " xfer len %zd %s%s%s%dbits %u usec %uHz\n", | 287 | " xfer len %u %s%s%s%dbits %u usec %uHz\n", |
288 | u_tmp->len, | 288 | u_tmp->len, |
289 | u_tmp->rx_buf ? "rx " : "", | 289 | u_tmp->rx_buf ? "rx " : "", |
290 | u_tmp->tx_buf ? "tx " : "", | 290 | u_tmp->tx_buf ? "tx " : "", |