| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * SPI testing utility (using spidev driver) |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2007 MontaVista Software, Inc. |
|---|
| 5 | 6 | * Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - * the Free Software Foundation; either version 2 of the License. |
|---|
| 10 | 7 | * |
|---|
| 11 | 8 | * Cross-compile with cross-gcc -I/path/to/cross-kernel/include |
|---|
| 12 | 9 | */ |
|---|
| .. | .. |
|---|
| 16 | 13 | #include <stdio.h> |
|---|
| 17 | 14 | #include <stdlib.h> |
|---|
| 18 | 15 | #include <string.h> |
|---|
| 16 | +#include <errno.h> |
|---|
| 19 | 17 | #include <getopt.h> |
|---|
| 20 | 18 | #include <fcntl.h> |
|---|
| 21 | 19 | #include <time.h> |
|---|
| .. | .. |
|---|
| 29 | 27 | |
|---|
| 30 | 28 | static void pabort(const char *s) |
|---|
| 31 | 29 | { |
|---|
| 32 | | - perror(s); |
|---|
| 30 | + if (errno != 0) |
|---|
| 31 | + perror(s); |
|---|
| 32 | + else |
|---|
| 33 | + printf("%s\n", s); |
|---|
| 34 | + |
|---|
| 33 | 35 | abort(); |
|---|
| 34 | 36 | } |
|---|
| 35 | 37 | |
|---|
| .. | .. |
|---|
| 45 | 47 | static int iterations; |
|---|
| 46 | 48 | static int interval = 5; /* interval in seconds for showing transfer rate */ |
|---|
| 47 | 49 | |
|---|
| 48 | | -uint8_t default_tx[] = { |
|---|
| 50 | +static uint8_t default_tx[] = { |
|---|
| 49 | 51 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
|---|
| 50 | 52 | 0x40, 0x00, 0x00, 0x00, 0x00, 0x95, |
|---|
| 51 | 53 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
|---|
| .. | .. |
|---|
| 54 | 56 | 0xF0, 0x0D, |
|---|
| 55 | 57 | }; |
|---|
| 56 | 58 | |
|---|
| 57 | | -uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, }; |
|---|
| 58 | | -char *input_tx; |
|---|
| 59 | +static uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, }; |
|---|
| 60 | +static char *input_tx; |
|---|
| 59 | 61 | |
|---|
| 60 | 62 | static void hex_dump(const void *src, size_t length, size_t line_size, |
|---|
| 61 | 63 | char *prefix) |
|---|
| .. | .. |
|---|
| 73 | 75 | while (i++ % line_size) |
|---|
| 74 | 76 | printf("__ "); |
|---|
| 75 | 77 | } |
|---|
| 76 | | - printf(" | "); /* right close */ |
|---|
| 78 | + printf(" |"); |
|---|
| 77 | 79 | while (line < address) { |
|---|
| 78 | 80 | c = *line++; |
|---|
| 79 | | - printf("%c", (c < 33 || c == 255) ? 0x2E : c); |
|---|
| 81 | + printf("%c", (c < 32 || c > 126) ? '.' : c); |
|---|
| 80 | 82 | } |
|---|
| 81 | | - printf("\n"); |
|---|
| 83 | + printf("|\n"); |
|---|
| 82 | 84 | if (length > 0) |
|---|
| 83 | 85 | printf("%s | ", prefix); |
|---|
| 84 | 86 | } |
|---|
| .. | .. |
|---|
| 126 | 128 | .bits_per_word = bits, |
|---|
| 127 | 129 | }; |
|---|
| 128 | 130 | |
|---|
| 129 | | - if (mode & SPI_TX_QUAD) |
|---|
| 131 | + if (mode & SPI_TX_OCTAL) |
|---|
| 132 | + tr.tx_nbits = 8; |
|---|
| 133 | + else if (mode & SPI_TX_QUAD) |
|---|
| 130 | 134 | tr.tx_nbits = 4; |
|---|
| 131 | 135 | else if (mode & SPI_TX_DUAL) |
|---|
| 132 | 136 | tr.tx_nbits = 2; |
|---|
| 133 | | - if (mode & SPI_RX_QUAD) |
|---|
| 137 | + if (mode & SPI_RX_OCTAL) |
|---|
| 138 | + tr.rx_nbits = 8; |
|---|
| 139 | + else if (mode & SPI_RX_QUAD) |
|---|
| 134 | 140 | tr.rx_nbits = 4; |
|---|
| 135 | 141 | else if (mode & SPI_RX_DUAL) |
|---|
| 136 | 142 | tr.rx_nbits = 2; |
|---|
| 137 | 143 | if (!(mode & SPI_LOOP)) { |
|---|
| 138 | | - if (mode & (SPI_TX_QUAD | SPI_TX_DUAL)) |
|---|
| 144 | + if (mode & (SPI_TX_OCTAL | SPI_TX_QUAD | SPI_TX_DUAL)) |
|---|
| 139 | 145 | tr.rx_buf = 0; |
|---|
| 140 | | - else if (mode & (SPI_RX_QUAD | SPI_RX_DUAL)) |
|---|
| 146 | + else if (mode & (SPI_RX_OCTAL | SPI_RX_QUAD | SPI_RX_DUAL)) |
|---|
| 141 | 147 | tr.tx_buf = 0; |
|---|
| 142 | 148 | } |
|---|
| 143 | 149 | |
|---|
| .. | .. |
|---|
| 185 | 191 | " -R --ready slave pulls low to pause\n" |
|---|
| 186 | 192 | " -2 --dual dual transfer\n" |
|---|
| 187 | 193 | " -4 --quad quad transfer\n" |
|---|
| 194 | + " -8 --octal octal transfer\n" |
|---|
| 188 | 195 | " -S --size transfer size\n" |
|---|
| 189 | 196 | " -I --iter iterations\n"); |
|---|
| 190 | 197 | exit(1); |
|---|
| .. | .. |
|---|
| 211 | 218 | { "dual", 0, 0, '2' }, |
|---|
| 212 | 219 | { "verbose", 0, 0, 'v' }, |
|---|
| 213 | 220 | { "quad", 0, 0, '4' }, |
|---|
| 221 | + { "octal", 0, 0, '8' }, |
|---|
| 214 | 222 | { "size", 1, 0, 'S' }, |
|---|
| 215 | 223 | { "iter", 1, 0, 'I' }, |
|---|
| 216 | 224 | { NULL, 0, 0, 0 }, |
|---|
| 217 | 225 | }; |
|---|
| 218 | 226 | int c; |
|---|
| 219 | 227 | |
|---|
| 220 | | - c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3NR24p:vS:I:", |
|---|
| 228 | + c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3NR248p:vS:I:", |
|---|
| 221 | 229 | lopts, NULL); |
|---|
| 222 | 230 | |
|---|
| 223 | 231 | if (c == -1) |
|---|
| .. | .. |
|---|
| 278 | 286 | case '4': |
|---|
| 279 | 287 | mode |= SPI_TX_QUAD; |
|---|
| 280 | 288 | break; |
|---|
| 289 | + case '8': |
|---|
| 290 | + mode |= SPI_TX_OCTAL; |
|---|
| 291 | + break; |
|---|
| 281 | 292 | case 'S': |
|---|
| 282 | 293 | transfer_size = atoi(optarg); |
|---|
| 283 | 294 | break; |
|---|
| .. | .. |
|---|
| 286 | 297 | break; |
|---|
| 287 | 298 | default: |
|---|
| 288 | 299 | print_usage(argv[0]); |
|---|
| 289 | | - break; |
|---|
| 290 | 300 | } |
|---|
| 291 | 301 | } |
|---|
| 292 | 302 | if (mode & SPI_LOOP) { |
|---|
| .. | .. |
|---|
| 294 | 304 | mode |= SPI_RX_DUAL; |
|---|
| 295 | 305 | if (mode & SPI_TX_QUAD) |
|---|
| 296 | 306 | mode |= SPI_RX_QUAD; |
|---|
| 307 | + if (mode & SPI_TX_OCTAL) |
|---|
| 308 | + mode |= SPI_RX_OCTAL; |
|---|
| 297 | 309 | } |
|---|
| 298 | 310 | } |
|---|
| 299 | 311 | |
|---|
| .. | .. |
|---|
| 408 | 420 | |
|---|
| 409 | 421 | parse_opts(argc, argv); |
|---|
| 410 | 422 | |
|---|
| 423 | + if (input_tx && input_file) |
|---|
| 424 | + pabort("only one of -p and --input may be selected"); |
|---|
| 425 | + |
|---|
| 411 | 426 | fd = open(device, O_RDWR); |
|---|
| 412 | 427 | if (fd < 0) |
|---|
| 413 | 428 | pabort("can't open device"); |
|---|
| .. | .. |
|---|
| 446 | 461 | pabort("can't get max speed hz"); |
|---|
| 447 | 462 | |
|---|
| 448 | 463 | printf("spi mode: 0x%x\n", mode); |
|---|
| 449 | | - printf("bits per word: %d\n", bits); |
|---|
| 450 | | - printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); |
|---|
| 451 | | - |
|---|
| 452 | | - if (input_tx && input_file) |
|---|
| 453 | | - pabort("only one of -p and --input may be selected"); |
|---|
| 464 | + printf("bits per word: %u\n", bits); |
|---|
| 465 | + printf("max speed: %u Hz (%u kHz)\n", speed, speed/1000); |
|---|
| 454 | 466 | |
|---|
| 455 | 467 | if (input_tx) |
|---|
| 456 | 468 | transfer_escaped_string(fd, input_tx); |
|---|