Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spidev_test utility

This is a simple utility used to test SPI functionality. It could stand
growing options to support using other test data patterns; this initial
version only issues full duplex transfers, which rules out 3WIRE or
Microwire links.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Anton Vorontsov and committed by
Linus Torvalds
22b238bd 6f166e38

+202
+202
Documentation/spi/spidev_test.c
··· 1 + /* 2 + * SPI testing utility (using spidev driver) 3 + * 4 + * Copyright (c) 2007 MontaVista Software, Inc. 5 + * 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 + * 11 + * Cross-compile with cross-gcc -I/path/to/cross-kernel/include 12 + */ 13 + 14 + #include <stdint.h> 15 + #include <unistd.h> 16 + #include <stdio.h> 17 + #include <stdlib.h> 18 + #include <getopt.h> 19 + #include <fcntl.h> 20 + #include <sys/ioctl.h> 21 + #include <linux/types.h> 22 + #include <linux/spi/spidev.h> 23 + 24 + #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 25 + 26 + static void pabort(const char *s) 27 + { 28 + perror(s); 29 + abort(); 30 + } 31 + 32 + static char *device = "/dev/spidev1.1"; 33 + static uint8_t mode; 34 + static uint8_t bits = 8; 35 + static uint32_t speed = 500000; 36 + static uint16_t delay; 37 + 38 + static void transfer(int fd) 39 + { 40 + int ret; 41 + uint8_t tx[] = { 42 + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 43 + 0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 44 + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 45 + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 46 + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 47 + 0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 48 + 0xF0, 0x0D, 49 + }; 50 + uint8_t rx[ARRAY_SIZE(tx)] = {0, }; 51 + struct spi_ioc_transfer tr = { 52 + .tx_buf = (unsigned long)tx, 53 + .rx_buf = (unsigned long)rx, 54 + .len = ARRAY_SIZE(tx), 55 + .delay_usecs = delay, 56 + .speed_hz = speed, 57 + .bits_per_word = bits, 58 + }; 59 + 60 + ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); 61 + if (ret == 1) 62 + pabort("can't send spi message"); 63 + 64 + for (ret = 0; ret < ARRAY_SIZE(tx); ret++) { 65 + if (!(ret % 6)) 66 + puts(""); 67 + printf("%.2X ", rx[ret]); 68 + } 69 + puts(""); 70 + } 71 + 72 + void print_usage(char *prog) 73 + { 74 + printf("Usage: %s [-DsbdlHOLC3]\n", prog); 75 + puts(" -D --device device to use (default /dev/spidev1.1)\n" 76 + " -s --speed max speed (Hz)\n" 77 + " -d --delay delay (usec)\n" 78 + " -b --bpw bits per word \n" 79 + " -l --loop loopback\n" 80 + " -H --cpha clock phase\n" 81 + " -O --cpol clock polarity\n" 82 + " -L --lsb least significant bit first\n" 83 + " -C --cs-high chip select active high\n" 84 + " -3 --3wire SI/SO signals shared\n"); 85 + exit(1); 86 + } 87 + 88 + void parse_opts(int argc, char *argv[]) 89 + { 90 + while (1) { 91 + static struct option lopts[] = { 92 + { "device", 1, 0, 'D' }, 93 + { "speed", 1, 0, 's' }, 94 + { "delay", 1, 0, 'd' }, 95 + { "bpw", 1, 0, 'b' }, 96 + { "loop", 0, 0, 'l' }, 97 + { "cpha", 0, 0, 'H' }, 98 + { "cpol", 0, 0, 'O' }, 99 + { "lsb", 0, 0, 'L' }, 100 + { "cs-high", 0, 0, 'C' }, 101 + { "3wire", 0, 0, '3' }, 102 + { NULL, 0, 0, 0 }, 103 + }; 104 + int c; 105 + 106 + c = getopt_long(argc, argv, "D:s:d:b:lHOLC3", lopts, NULL); 107 + 108 + if (c == -1) 109 + break; 110 + 111 + switch (c) { 112 + case 'D': 113 + device = optarg; 114 + break; 115 + case 's': 116 + speed = atoi(optarg); 117 + break; 118 + case 'd': 119 + delay = atoi(optarg); 120 + break; 121 + case 'b': 122 + bits = atoi(optarg); 123 + break; 124 + case 'l': 125 + mode |= SPI_LOOP; 126 + break; 127 + case 'H': 128 + mode |= SPI_CPHA; 129 + break; 130 + case 'O': 131 + mode |= SPI_CPOL; 132 + break; 133 + case 'L': 134 + mode |= SPI_LSB_FIRST; 135 + break; 136 + case 'C': 137 + mode |= SPI_CS_HIGH; 138 + break; 139 + case '3': 140 + mode |= SPI_3WIRE; 141 + break; 142 + default: 143 + print_usage(argv[0]); 144 + break; 145 + } 146 + } 147 + } 148 + 149 + int main(int argc, char *argv[]) 150 + { 151 + int ret = 0; 152 + int fd; 153 + 154 + parse_opts(argc, argv); 155 + 156 + fd = open(device, O_RDWR); 157 + if (fd < 0) 158 + pabort("can't open device"); 159 + 160 + /* 161 + * spi mode 162 + */ 163 + ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); 164 + if (ret == -1) 165 + pabort("can't set spi mode"); 166 + 167 + ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); 168 + if (ret == -1) 169 + pabort("can't get spi mode"); 170 + 171 + /* 172 + * bits per word 173 + */ 174 + ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); 175 + if (ret == -1) 176 + pabort("can't set bits per word"); 177 + 178 + ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); 179 + if (ret == -1) 180 + pabort("can't get bits per word"); 181 + 182 + /* 183 + * max speed hz 184 + */ 185 + ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); 186 + if (ret == -1) 187 + pabort("can't set max speed hz"); 188 + 189 + ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); 190 + if (ret == -1) 191 + pabort("can't get max speed hz"); 192 + 193 + printf("spi mode: %d\n", mode); 194 + printf("bits per word: %d\n", bits); 195 + printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); 196 + 197 + transfer(fd); 198 + 199 + close(fd); 200 + 201 + return ret; 202 + }