diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-03 22:31:39 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-03 22:31:39 +0300 |
commit | d25e436c4b68db2895185b24ad1f22499c2f87b0 (patch) | |
tree | dd66245410513f09d2439ef0b34cf1d131696bed /tools | |
parent | a90f0e9ebb88ba7b0efea4e7d9defc0c2b96f712 (diff) | |
parent | 282ec0ea65dab88fda51b5b9b649958ae42f4ac0 (diff) | |
download | linux-d25e436c4b68db2895185b24ad1f22499c2f87b0.tar.xz |
Merge tag 'spi-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
"There's quite a lot of small driver specific fixes and enhancements in
this release but the main activity has been around the loopback and
spidev test drivers which is good to see as it should hopefully help
improve the quality of all the drivers as people start to make use of
the new code:
- Additional tests in the loopback test driver for vmalloc()
compatibility and around delays together with fixes for existing
tests.
- Support for testing continuous data transfer for use in soak
testing.
- Device property support for board info platforms.
- Support for registering empty sets of devices via board info
(useful when writing code to enumerate hardware automatically)"
* tag 'spi-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (52 commits)
spi: cadence: Allow for GPIO pins to be used as chipselects
spi-imx: Implements handling of the SPI_READY mode flag.
spi: tegra: fix spelling mistake: "trasfer" -> "transfer"
spi: spi-ti-qspi: Use bounce buffer if read buffer is not DMA'ble
spi: Add can_dma like interface for spi_flash_read
spi: dw: Disable clock after unregistering the host
spi: double time out tolerance
spi: atmel: add deepest PM support to SAMA5D2
spi: atmel: factorize reusable code for SPI controller init
spi: orion: add LSB support
spi: pl022: don't use uninitialized variable
spi: loopback-test: fix spelling mistake: "minimam" -> "minimum"
spi: dynamycally allocated message initialization
spi: spi-ti-qspi: Remove unused dma_dev variable
spi: omap2-mcspi: poll OMAP2_MCSPI_CHSTAT_RXS for PIO transfer
spi: spi-ti-qspi: Use dma_engine wrapper for dma memcpy call
spi: spidev_test: add option to continuously transfer data
spi: loopback-test: fix potential integer overflow on multiple
spi: sun6i: update max transfer size reported
spi: pl022: Document property values
...
Diffstat (limited to 'tools')
-rw-r--r-- | tools/spi/spidev_test.c | 93 |
1 files changed, 88 insertions, 5 deletions
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c index 816f119c9b7b..8c590cd1171a 100644 --- a/tools/spi/spidev_test.c +++ b/tools/spi/spidev_test.c @@ -18,6 +18,7 @@ #include <string.h> #include <getopt.h> #include <fcntl.h> +#include <time.h> #include <sys/ioctl.h> #include <linux/ioctl.h> #include <sys/stat.h> @@ -40,6 +41,9 @@ static char *output_file; static uint32_t speed = 500000; static uint16_t delay; static int verbose; +static int transfer_size; +static int iterations; +static int interval = 5; /* interval in seconds for showing transfer rate */ uint8_t default_tx[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, @@ -156,13 +160,13 @@ static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len) close(out_fd); } - if (verbose || !output_file) + if (verbose) hex_dump(rx, len, 32, "RX"); } static void print_usage(const char *prog) { - printf("Usage: %s [-DsbdlHOLC3]\n", prog); + printf("Usage: %s [-DsbdlHOLC3vpNR24SI]\n", prog); puts(" -D --device device to use (default /dev/spidev1.1)\n" " -s --speed max speed (Hz)\n" " -d --delay delay (usec)\n" @@ -180,7 +184,9 @@ static void print_usage(const char *prog) " -N --no-cs no chip select\n" " -R --ready slave pulls low to pause\n" " -2 --dual dual transfer\n" - " -4 --quad quad transfer\n"); + " -4 --quad quad transfer\n" + " -S --size transfer size\n" + " -I --iter iterations\n"); exit(1); } @@ -205,11 +211,13 @@ static void parse_opts(int argc, char *argv[]) { "dual", 0, 0, '2' }, { "verbose", 0, 0, 'v' }, { "quad", 0, 0, '4' }, + { "size", 1, 0, 'S' }, + { "iter", 1, 0, 'I' }, { NULL, 0, 0, 0 }, }; int c; - c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3NR24p:v", + c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3NR24p:vS:I:", lopts, NULL); if (c == -1) @@ -270,6 +278,12 @@ static void parse_opts(int argc, char *argv[]) case '4': mode |= SPI_TX_QUAD; break; + case 'S': + transfer_size = atoi(optarg); + break; + case 'I': + iterations = atoi(optarg); + break; default: print_usage(argv[0]); break; @@ -336,6 +350,57 @@ static void transfer_file(int fd, char *filename) close(tx_fd); } +static uint64_t _read_count; +static uint64_t _write_count; + +static void show_transfer_rate(void) +{ + static uint64_t prev_read_count, prev_write_count; + double rx_rate, tx_rate; + + rx_rate = ((_read_count - prev_read_count) * 8) / (interval*1000.0); + tx_rate = ((_write_count - prev_write_count) * 8) / (interval*1000.0); + + printf("rate: tx %.1fkbps, rx %.1fkbps\n", rx_rate, tx_rate); + + prev_read_count = _read_count; + prev_write_count = _write_count; +} + +static void transfer_buf(int fd, int len) +{ + uint8_t *tx; + uint8_t *rx; + int i; + + tx = malloc(len); + if (!tx) + pabort("can't allocate tx buffer"); + for (i = 0; i < len; i++) + tx[i] = random(); + + rx = malloc(len); + if (!rx) + pabort("can't allocate rx buffer"); + + transfer(fd, tx, rx, len); + + _write_count += len; + _read_count += len; + + if (mode & SPI_LOOP) { + if (memcmp(tx, rx, len)) { + fprintf(stderr, "transfer error !\n"); + hex_dump(tx, len, 32, "TX"); + hex_dump(rx, len, 32, "RX"); + exit(1); + } + } + + free(rx); + free(tx); +} + int main(int argc, char *argv[]) { int ret = 0; @@ -391,7 +456,25 @@ int main(int argc, char *argv[]) transfer_escaped_string(fd, input_tx); else if (input_file) transfer_file(fd, input_file); - else + else if (transfer_size) { + struct timespec last_stat; + + clock_gettime(CLOCK_MONOTONIC, &last_stat); + + while (iterations-- > 0) { + struct timespec current; + + transfer_buf(fd, transfer_size); + + clock_gettime(CLOCK_MONOTONIC, ¤t); + if (current.tv_sec - last_stat.tv_sec > interval) { + show_transfer_rate(); + last_stat = current; + } + } + printf("total: tx %.1fKB, rx %.1fKB\n", + _write_count/1024.0, _read_count/1024.0); + } else transfer(fd, default_tx, default_rx, sizeof(default_tx)); close(fd); |