summaryrefslogtreecommitdiff
path: root/tools/spi/spidev_fdx.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-13 22:38:27 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-13 22:38:27 +0300
commit50ae833e471fe1a1a906a0342bdaa690e69fcc19 (patch)
tree15f4871eff7574f5677ce80a4faa2bf865d733d8 /tools/spi/spidev_fdx.c
parentac53b2e053fffc74372da94e734b92f37e70d32c (diff)
parentcabeea980879c2c701b0bd03f145c9f7dae17a63 (diff)
downloadlinux-50ae833e471fe1a1a906a0342bdaa690e69fcc19.tar.xz
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 'tools/spi/spidev_fdx.c')
-rw-r--r--tools/spi/spidev_fdx.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/tools/spi/spidev_fdx.c b/tools/spi/spidev_fdx.c
new file mode 100644
index 000000000000..0ea3e51292fc
--- /dev/null
+++ b/tools/spi/spidev_fdx.c
@@ -0,0 +1,158 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <linux/types.h>
+#include <linux/spi/spidev.h>
+
+
+static int verbose;
+
+static void do_read(int fd, int len)
+{
+ unsigned char buf[32], *bp;
+ int status;
+
+ /* read at least 2 bytes, no more than 32 */
+ if (len < 2)
+ len = 2;
+ else if (len > sizeof(buf))
+ len = sizeof(buf);
+ memset(buf, 0, sizeof buf);
+
+ status = read(fd, buf, len);
+ if (status < 0) {
+ perror("read");
+ return;
+ }
+ if (status != len) {
+ fprintf(stderr, "short read\n");
+ return;
+ }
+
+ printf("read(%2d, %2d): %02x %02x,", len, status,
+ buf[0], buf[1]);
+ status -= 2;
+ bp = buf + 2;
+ while (status-- > 0)
+ printf(" %02x", *bp++);
+ printf("\n");
+}
+
+static void do_msg(int fd, int len)
+{
+ struct spi_ioc_transfer xfer[2];
+ unsigned char buf[32], *bp;
+ int status;
+
+ memset(xfer, 0, sizeof xfer);
+ memset(buf, 0, sizeof buf);
+
+ if (len > sizeof buf)
+ len = sizeof buf;
+
+ buf[0] = 0xaa;
+ xfer[0].tx_buf = (unsigned long)buf;
+ xfer[0].len = 1;
+
+ xfer[1].rx_buf = (unsigned long) buf;
+ xfer[1].len = len;
+
+ status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);
+ if (status < 0) {
+ perror("SPI_IOC_MESSAGE");
+ return;
+ }
+
+ printf("response(%2d, %2d): ", len, status);
+ for (bp = buf; len; len--)
+ printf(" %02x", *bp++);
+ printf("\n");
+}
+
+static void dumpstat(const char *name, int fd)
+{
+ __u8 lsb, bits;
+ __u32 mode, speed;
+
+ if (ioctl(fd, SPI_IOC_RD_MODE32, &mode) < 0) {
+ perror("SPI rd_mode");
+ return;
+ }
+ if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) {
+ perror("SPI rd_lsb_fist");
+ return;
+ }
+ if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) {
+ perror("SPI bits_per_word");
+ return;
+ }
+ if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) {
+ perror("SPI max_speed_hz");
+ return;
+ }
+
+ printf("%s: spi mode 0x%x, %d bits %sper word, %d Hz max\n",
+ name, mode, bits, lsb ? "(lsb first) " : "", speed);
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+ int readcount = 0;
+ int msglen = 0;
+ int fd;
+ const char *name;
+
+ while ((c = getopt(argc, argv, "hm:r:v")) != EOF) {
+ switch (c) {
+ case 'm':
+ msglen = atoi(optarg);
+ if (msglen < 0)
+ goto usage;
+ continue;
+ case 'r':
+ readcount = atoi(optarg);
+ if (readcount < 0)
+ goto usage;
+ continue;
+ case 'v':
+ verbose++;
+ continue;
+ case 'h':
+ case '?':
+usage:
+ fprintf(stderr,
+ "usage: %s [-h] [-m N] [-r N] /dev/spidevB.D\n",
+ argv[0]);
+ return 1;
+ }
+ }
+
+ if ((optind + 1) != argc)
+ goto usage;
+ name = argv[optind];
+
+ fd = open(name, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+
+ dumpstat(name, fd);
+
+ if (msglen)
+ do_msg(fd, msglen);
+
+ if (readcount)
+ do_read(fd, readcount);
+
+ close(fd);
+ return 0;
+}