Blame view

tools/spi/spidev_test.c 10.3 KB
84a14ae8c   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
22b238bdb   Anton Vorontsov   spidev_test utility
2
3
4
5
6
7
  /*
   * SPI testing utility (using spidev driver)
   *
   * Copyright (c) 2007  MontaVista Software, Inc.
   * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com>
   *
22b238bdb   Anton Vorontsov   spidev_test utility
8
9
10
11
12
13
14
   * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
   */
  
  #include <stdint.h>
  #include <unistd.h>
  #include <stdio.h>
  #include <stdlib.h>
b78ce7ed5   Adrian Remonda   spi: spidev_test:...
15
  #include <string.h>
470a072e1   Tiezhu Yang   spi: spidev_test:...
16
  #include <errno.h>
22b238bdb   Anton Vorontsov   spidev_test utility
17
18
  #include <getopt.h>
  #include <fcntl.h>
9006a7b32   Frode Isaksen   spi: spidev_test:...
19
  #include <time.h>
22b238bdb   Anton Vorontsov   spidev_test utility
20
  #include <sys/ioctl.h>
8736f8022   Baruch Siach   spi: spidev_test:...
21
  #include <linux/ioctl.h>
7af475a5b   Joshua Clayton   spi: spidev_test:...
22
  #include <sys/stat.h>
22b238bdb   Anton Vorontsov   spidev_test utility
23
24
25
26
27
28
29
  #include <linux/types.h>
  #include <linux/spi/spidev.h>
  
  #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
  
  static void pabort(const char *s)
  {
470a072e1   Tiezhu Yang   spi: spidev_test:...
30
31
32
33
34
  	if (errno != 0)
  		perror(s);
  	else
  		printf("%s
  ", s);
22b238bdb   Anton Vorontsov   spidev_test utility
35
36
  	abort();
  }
cd58310d7   WANG Cong   Documentation/spi...
37
  static const char *device = "/dev/spidev1.1";
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
38
  static uint32_t mode;
22b238bdb   Anton Vorontsov   spidev_test utility
39
  static uint8_t bits = 8;
7af475a5b   Joshua Clayton   spi: spidev_test:...
40
  static char *input_file;
983b27886   Joshua Clayton   spi: spidev_test:...
41
  static char *output_file;
22b238bdb   Anton Vorontsov   spidev_test utility
42
43
  static uint32_t speed = 500000;
  static uint16_t delay;
31a5c5a72   Adrian Remonda   spi: spidev_test:...
44
  static int verbose;
9006a7b32   Frode Isaksen   spi: spidev_test:...
45
46
47
  static int transfer_size;
  static int iterations;
  static int interval = 5; /* interval in seconds for showing transfer rate */
22b238bdb   Anton Vorontsov   spidev_test utility
48

bd2077915   Qing Zhang   spi: tools: Make ...
49
  static uint8_t default_tx[] = {
30061915b   Adrian Remonda   spi: spidev_test:...
50
51
52
53
54
55
56
  	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  	0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
  	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  	0xF0, 0x0D,
  };
bd2077915   Qing Zhang   spi: tools: Make ...
57
58
  static uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, };
  static char *input_tx;
30061915b   Adrian Remonda   spi: spidev_test:...
59

b2cfc9042   Joshua Clayton   spi: spidev_test:...
60
61
  static void hex_dump(const void *src, size_t length, size_t line_size,
  		     char *prefix)
b78ce7ed5   Adrian Remonda   spi: spidev_test:...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  {
  	int i = 0;
  	const unsigned char *address = src;
  	const unsigned char *line = address;
  	unsigned char c;
  
  	printf("%s | ", prefix);
  	while (length-- > 0) {
  		printf("%02X ", *address++);
  		if (!(++i % line_size) || (length == 0 && i % line_size)) {
  			if (length == 0) {
  				while (i++ % line_size)
  					printf("__ ");
  			}
35386dfd1   Geert Uytterhoeven   spi: spidev_test:...
76
  			printf(" |");
b78ce7ed5   Adrian Remonda   spi: spidev_test:...
77
78
  			while (line < address) {
  				c = *line++;
35386dfd1   Geert Uytterhoeven   spi: spidev_test:...
79
  				printf("%c", (c < 32 || c > 126) ? '.' : c);
b78ce7ed5   Adrian Remonda   spi: spidev_test:...
80
  			}
35386dfd1   Geert Uytterhoeven   spi: spidev_test:...
81
82
  			printf("|
  ");
b78ce7ed5   Adrian Remonda   spi: spidev_test:...
83
84
85
86
87
  			if (length > 0)
  				printf("%s | ", prefix);
  		}
  	}
  }
30061915b   Adrian Remonda   spi: spidev_test:...
88
89
90
91
  /*
   *  Unescape - process hexadecimal escape character
   *      converts shell input "\x23" -> 0x23
   */
07eec628f   Andrew Morton   Documentation/spi...
92
  static int unescape(char *_dst, char *_src, size_t len)
30061915b   Adrian Remonda   spi: spidev_test:...
93
94
  {
  	int ret = 0;
a20874f78   Joshua Clayton   spi: spidev_test:...
95
  	int match;
30061915b   Adrian Remonda   spi: spidev_test:...
96
97
98
99
100
101
  	char *src = _src;
  	char *dst = _dst;
  	unsigned int ch;
  
  	while (*src) {
  		if (*src == '\\' && *(src+1) == 'x') {
a20874f78   Joshua Clayton   spi: spidev_test:...
102
103
104
  			match = sscanf(src + 2, "%2x", &ch);
  			if (!match)
  				pabort("malformed input string");
30061915b   Adrian Remonda   spi: spidev_test:...
105
106
107
108
109
110
111
112
113
114
115
  			src += 4;
  			*dst++ = (unsigned char)ch;
  		} else {
  			*dst++ = *src++;
  		}
  		ret++;
  	}
  	return ret;
  }
  
  static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
22b238bdb   Anton Vorontsov   spidev_test utility
116
117
  {
  	int ret;
983b27886   Joshua Clayton   spi: spidev_test:...
118
  	int out_fd;
22b238bdb   Anton Vorontsov   spidev_test utility
119
120
121
  	struct spi_ioc_transfer tr = {
  		.tx_buf = (unsigned long)tx,
  		.rx_buf = (unsigned long)rx,
30061915b   Adrian Remonda   spi: spidev_test:...
122
  		.len = len,
22b238bdb   Anton Vorontsov   spidev_test utility
123
124
125
126
  		.delay_usecs = delay,
  		.speed_hz = speed,
  		.bits_per_word = bits,
  	};
896fa7350   Geert Uytterhoeven   spi: spidev_test:...
127
128
129
  	if (mode & SPI_TX_OCTAL)
  		tr.tx_nbits = 8;
  	else if (mode & SPI_TX_QUAD)
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
130
131
132
  		tr.tx_nbits = 4;
  	else if (mode & SPI_TX_DUAL)
  		tr.tx_nbits = 2;
896fa7350   Geert Uytterhoeven   spi: spidev_test:...
133
134
135
  	if (mode & SPI_RX_OCTAL)
  		tr.rx_nbits = 8;
  	else if (mode & SPI_RX_QUAD)
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
136
137
138
139
  		tr.rx_nbits = 4;
  	else if (mode & SPI_RX_DUAL)
  		tr.rx_nbits = 2;
  	if (!(mode & SPI_LOOP)) {
896fa7350   Geert Uytterhoeven   spi: spidev_test:...
140
  		if (mode & (SPI_TX_OCTAL | SPI_TX_QUAD | SPI_TX_DUAL))
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
141
  			tr.rx_buf = 0;
896fa7350   Geert Uytterhoeven   spi: spidev_test:...
142
  		else if (mode & (SPI_RX_OCTAL | SPI_RX_QUAD | SPI_RX_DUAL))
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
143
144
  			tr.tx_buf = 0;
  	}
22b238bdb   Anton Vorontsov   spidev_test utility
145
  	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
95b1ed2ac   Hector Palacios   spi: spidev_test ...
146
  	if (ret < 1)
22b238bdb   Anton Vorontsov   spidev_test utility
147
  		pabort("can't send spi message");
31a5c5a72   Adrian Remonda   spi: spidev_test:...
148
  	if (verbose)
30061915b   Adrian Remonda   spi: spidev_test:...
149
  		hex_dump(tx, len, 32, "TX");
983b27886   Joshua Clayton   spi: spidev_test:...
150
151
152
153
154
155
156
157
  
  	if (output_file) {
  		out_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  		if (out_fd < 0)
  			pabort("could not open output file");
  
  		ret = write(out_fd, rx, len);
  		if (ret != len)
edd3899c8   Fabio Estevam   spi: spidev_test:...
158
  			pabort("not all bytes written to output file");
983b27886   Joshua Clayton   spi: spidev_test:...
159
160
161
  
  		close(out_fd);
  	}
9006a7b32   Frode Isaksen   spi: spidev_test:...
162
  	if (verbose)
983b27886   Joshua Clayton   spi: spidev_test:...
163
  		hex_dump(rx, len, 32, "RX");
22b238bdb   Anton Vorontsov   spidev_test utility
164
  }
b7ed698cc   Ladinu Chandrasinghe   Documentation/: f...
165
  static void print_usage(const char *prog)
22b238bdb   Anton Vorontsov   spidev_test utility
166
  {
9006a7b32   Frode Isaksen   spi: spidev_test:...
167
168
  	printf("Usage: %s [-DsbdlHOLC3vpNR24SI]
  ", prog);
22b238bdb   Anton Vorontsov   spidev_test utility
169
170
171
172
173
174
  	puts("  -D --device   device to use (default /dev/spidev1.1)
  "
  	     "  -s --speed    max speed (Hz)
  "
  	     "  -d --delay    delay (usec)
  "
b2cfc9042   Joshua Clayton   spi: spidev_test:...
175
176
  	     "  -b --bpw      bits per word
  "
7af475a5b   Joshua Clayton   spi: spidev_test:...
177
178
  	     "  -i --input    input data from a file (e.g. \"test.bin\")
  "
983b27886   Joshua Clayton   spi: spidev_test:...
179
180
  	     "  -o --output   output data to a file (e.g. \"results.bin\")
  "
22b238bdb   Anton Vorontsov   spidev_test utility
181
182
183
184
185
186
187
188
189
190
  	     "  -l --loop     loopback
  "
  	     "  -H --cpha     clock phase
  "
  	     "  -O --cpol     clock polarity
  "
  	     "  -L --lsb      least significant bit first
  "
  	     "  -C --cs-high  chip select active high
  "
925d16a20   Geert Uytterhoeven   spi/spidev_test: ...
191
192
  	     "  -3 --3wire    SI/SO signals shared
  "
31a5c5a72   Adrian Remonda   spi: spidev_test:...
193
194
  	     "  -v --verbose  Verbose (show tx buffer)
  "
30061915b   Adrian Remonda   spi: spidev_test:...
195
196
  	     "  -p            Send data (e.g. \"1234\\xde\\xad\")
  "
925d16a20   Geert Uytterhoeven   spi/spidev_test: ...
197
198
  	     "  -N --no-cs    no chip select
  "
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
199
200
201
202
  	     "  -R --ready    slave pulls low to pause
  "
  	     "  -2 --dual     dual transfer
  "
9006a7b32   Frode Isaksen   spi: spidev_test:...
203
204
  	     "  -4 --quad     quad transfer
  "
896fa7350   Geert Uytterhoeven   spi: spidev_test:...
205
206
  	     "  -8 --octal    octal transfer
  "
9006a7b32   Frode Isaksen   spi: spidev_test:...
207
208
209
210
  	     "  -S --size     transfer size
  "
  	     "  -I --iter     iterations
  ");
22b238bdb   Anton Vorontsov   spidev_test utility
211
212
  	exit(1);
  }
b7ed698cc   Ladinu Chandrasinghe   Documentation/: f...
213
  static void parse_opts(int argc, char *argv[])
22b238bdb   Anton Vorontsov   spidev_test utility
214
215
  {
  	while (1) {
cd58310d7   WANG Cong   Documentation/spi...
216
  		static const struct option lopts[] = {
22b238bdb   Anton Vorontsov   spidev_test utility
217
218
219
220
  			{ "device",  1, 0, 'D' },
  			{ "speed",   1, 0, 's' },
  			{ "delay",   1, 0, 'd' },
  			{ "bpw",     1, 0, 'b' },
7af475a5b   Joshua Clayton   spi: spidev_test:...
221
  			{ "input",   1, 0, 'i' },
983b27886   Joshua Clayton   spi: spidev_test:...
222
  			{ "output",  1, 0, 'o' },
22b238bdb   Anton Vorontsov   spidev_test utility
223
224
225
226
227
228
  			{ "loop",    0, 0, 'l' },
  			{ "cpha",    0, 0, 'H' },
  			{ "cpol",    0, 0, 'O' },
  			{ "lsb",     0, 0, 'L' },
  			{ "cs-high", 0, 0, 'C' },
  			{ "3wire",   0, 0, '3' },
b55f627fe   David Brownell   spi: new spi->mod...
229
230
  			{ "no-cs",   0, 0, 'N' },
  			{ "ready",   0, 0, 'R' },
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
231
  			{ "dual",    0, 0, '2' },
31a5c5a72   Adrian Remonda   spi: spidev_test:...
232
  			{ "verbose", 0, 0, 'v' },
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
233
  			{ "quad",    0, 0, '4' },
896fa7350   Geert Uytterhoeven   spi: spidev_test:...
234
  			{ "octal",   0, 0, '8' },
9006a7b32   Frode Isaksen   spi: spidev_test:...
235
236
  			{ "size",    1, 0, 'S' },
  			{ "iter",    1, 0, 'I' },
22b238bdb   Anton Vorontsov   spidev_test utility
237
238
239
  			{ NULL, 0, 0, 0 },
  		};
  		int c;
896fa7350   Geert Uytterhoeven   spi: spidev_test:...
240
  		c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3NR248p:vS:I:",
7af475a5b   Joshua Clayton   spi: spidev_test:...
241
  				lopts, NULL);
22b238bdb   Anton Vorontsov   spidev_test utility
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  
  		if (c == -1)
  			break;
  
  		switch (c) {
  		case 'D':
  			device = optarg;
  			break;
  		case 's':
  			speed = atoi(optarg);
  			break;
  		case 'd':
  			delay = atoi(optarg);
  			break;
  		case 'b':
  			bits = atoi(optarg);
  			break;
7af475a5b   Joshua Clayton   spi: spidev_test:...
259
260
261
  		case 'i':
  			input_file = optarg;
  			break;
983b27886   Joshua Clayton   spi: spidev_test:...
262
263
264
  		case 'o':
  			output_file = optarg;
  			break;
22b238bdb   Anton Vorontsov   spidev_test utility
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
  		case 'l':
  			mode |= SPI_LOOP;
  			break;
  		case 'H':
  			mode |= SPI_CPHA;
  			break;
  		case 'O':
  			mode |= SPI_CPOL;
  			break;
  		case 'L':
  			mode |= SPI_LSB_FIRST;
  			break;
  		case 'C':
  			mode |= SPI_CS_HIGH;
  			break;
  		case '3':
  			mode |= SPI_3WIRE;
  			break;
b55f627fe   David Brownell   spi: new spi->mod...
283
284
285
  		case 'N':
  			mode |= SPI_NO_CS;
  			break;
31a5c5a72   Adrian Remonda   spi: spidev_test:...
286
287
288
  		case 'v':
  			verbose = 1;
  			break;
b55f627fe   David Brownell   spi: new spi->mod...
289
290
291
  		case 'R':
  			mode |= SPI_READY;
  			break;
30061915b   Adrian Remonda   spi: spidev_test:...
292
293
294
  		case 'p':
  			input_tx = optarg;
  			break;
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
295
296
297
298
299
300
  		case '2':
  			mode |= SPI_TX_DUAL;
  			break;
  		case '4':
  			mode |= SPI_TX_QUAD;
  			break;
896fa7350   Geert Uytterhoeven   spi: spidev_test:...
301
302
303
  		case '8':
  			mode |= SPI_TX_OCTAL;
  			break;
9006a7b32   Frode Isaksen   spi: spidev_test:...
304
305
306
307
308
309
  		case 'S':
  			transfer_size = atoi(optarg);
  			break;
  		case 'I':
  			iterations = atoi(optarg);
  			break;
22b238bdb   Anton Vorontsov   spidev_test utility
310
311
  		default:
  			print_usage(argv[0]);
22b238bdb   Anton Vorontsov   spidev_test utility
312
313
  		}
  	}
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
314
315
316
317
318
  	if (mode & SPI_LOOP) {
  		if (mode & SPI_TX_DUAL)
  			mode |= SPI_RX_DUAL;
  		if (mode & SPI_TX_QUAD)
  			mode |= SPI_RX_QUAD;
896fa7350   Geert Uytterhoeven   spi: spidev_test:...
319
320
  		if (mode & SPI_TX_OCTAL)
  			mode |= SPI_RX_OCTAL;
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
321
  	}
22b238bdb   Anton Vorontsov   spidev_test utility
322
  }
5c437a401   Joshua Clayton   spi: spidev_test:...
323
324
  static void transfer_escaped_string(int fd, char *str)
  {
0278b34bf   Geert Uytterhoeven   spi: spidev_test:...
325
  	size_t size = strlen(str);
5c437a401   Joshua Clayton   spi: spidev_test:...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  	uint8_t *tx;
  	uint8_t *rx;
  
  	tx = malloc(size);
  	if (!tx)
  		pabort("can't allocate tx buffer");
  
  	rx = malloc(size);
  	if (!rx)
  		pabort("can't allocate rx buffer");
  
  	size = unescape((char *)tx, str, size);
  	transfer(fd, tx, rx, size);
  	free(rx);
  	free(tx);
  }
7af475a5b   Joshua Clayton   spi: spidev_test:...
342
343
344
345
346
347
348
349
350
351
352
353
  static void transfer_file(int fd, char *filename)
  {
  	ssize_t bytes;
  	struct stat sb;
  	int tx_fd;
  	uint8_t *tx;
  	uint8_t *rx;
  
  	if (stat(filename, &sb) == -1)
  		pabort("can't stat input file");
  
  	tx_fd = open(filename, O_RDONLY);
e634b76ca   Michal Vokáč   spi: spidev_test:...
354
  	if (tx_fd < 0)
7af475a5b   Joshua Clayton   spi: spidev_test:...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
  		pabort("can't open input file");
  
  	tx = malloc(sb.st_size);
  	if (!tx)
  		pabort("can't allocate tx buffer");
  
  	rx = malloc(sb.st_size);
  	if (!rx)
  		pabort("can't allocate rx buffer");
  
  	bytes = read(tx_fd, tx, sb.st_size);
  	if (bytes != sb.st_size)
  		pabort("failed to read input file");
  
  	transfer(fd, tx, rx, sb.st_size);
  	free(rx);
  	free(tx);
  	close(tx_fd);
  }
9006a7b32   Frode Isaksen   spi: spidev_test:...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  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
  ", 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 !
  ");
  			hex_dump(tx, len, 32, "TX");
  			hex_dump(rx, len, 32, "RX");
  			exit(1);
  		}
  	}
  
  	free(rx);
  	free(tx);
  }
22b238bdb   Anton Vorontsov   spidev_test utility
426
427
428
429
430
431
  int main(int argc, char *argv[])
  {
  	int ret = 0;
  	int fd;
  
  	parse_opts(argc, argv);
1f3c36328   Tiezhu Yang   spi: spidev_test:...
432
433
  	if (input_tx && input_file)
  		pabort("only one of -p and --input may be selected");
22b238bdb   Anton Vorontsov   spidev_test utility
434
435
436
437
438
439
440
  	fd = open(device, O_RDWR);
  	if (fd < 0)
  		pabort("can't open device");
  
  	/*
  	 * spi mode
  	 */
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
441
  	ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
22b238bdb   Anton Vorontsov   spidev_test utility
442
443
  	if (ret == -1)
  		pabort("can't set spi mode");
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
444
  	ret = ioctl(fd, SPI_IOC_RD_MODE32, &mode);
22b238bdb   Anton Vorontsov   spidev_test utility
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  	if (ret == -1)
  		pabort("can't get spi mode");
  
  	/*
  	 * bits per word
  	 */
  	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
  	if (ret == -1)
  		pabort("can't set bits per word");
  
  	ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
  	if (ret == -1)
  		pabort("can't get bits per word");
  
  	/*
  	 * max speed hz
  	 */
  	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
  	if (ret == -1)
  		pabort("can't set max speed hz");
  
  	ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
  	if (ret == -1)
  		pabort("can't get max speed hz");
c2e78c34e   Geert Uytterhoeven   spi: spidev_test:...
469
470
  	printf("spi mode: 0x%x
  ", mode);
9ec8ade81   Geert Uytterhoeven   spi: spidev_test:...
471
472
473
474
  	printf("bits per word: %u
  ", bits);
  	printf("max speed: %u Hz (%u kHz)
  ", speed, speed/1000);
22b238bdb   Anton Vorontsov   spidev_test utility
475

5c437a401   Joshua Clayton   spi: spidev_test:...
476
477
  	if (input_tx)
  		transfer_escaped_string(fd, input_tx);
7af475a5b   Joshua Clayton   spi: spidev_test:...
478
479
  	else if (input_file)
  		transfer_file(fd, input_file);
9006a7b32   Frode Isaksen   spi: spidev_test:...
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
  	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, &current);
  			if (current.tv_sec - last_stat.tv_sec > interval) {
  				show_transfer_rate();
  				last_stat = current;
  			}
  		}
  		printf("total: tx %.1fKB, rx %.1fKB
  ",
  		       _write_count/1024.0, _read_count/1024.0);
  	} else
30061915b   Adrian Remonda   spi: spidev_test:...
500
  		transfer(fd, default_tx, default_rx, sizeof(default_tx));
22b238bdb   Anton Vorontsov   spidev_test utility
501
502
503
504
505
  
  	close(fd);
  
  	return ret;
  }