diff options
-rw-r--r-- | drivers/spi/spi-imx.c | 9 | ||||
-rw-r--r-- | drivers/spi/spidev.c | 3 | ||||
-rw-r--r-- | include/uapi/linux/spi/spi.h | 3 | ||||
-rw-r--r-- | tools/spi/spidev_test.c | 107 |
4 files changed, 76 insertions, 46 deletions
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index bd6ddb142b13..6f4d3cb81fdf 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -281,6 +281,7 @@ static bool spi_imx_can_dma(struct spi_controller *controller, struct spi_device #define MX51_ECSPI_CONFIG_SCLKPOL(cs) (1 << ((cs & 3) + 4)) #define MX51_ECSPI_CONFIG_SBBCTRL(cs) (1 << ((cs & 3) + 8)) #define MX51_ECSPI_CONFIG_SSBPOL(cs) (1 << ((cs & 3) + 12)) +#define MX51_ECSPI_CONFIG_DATACTL(cs) (1 << ((cs & 3) + 16)) #define MX51_ECSPI_CONFIG_SCLKCTL(cs) (1 << ((cs & 3) + 20)) #define MX51_ECSPI_INT 0x10 @@ -573,6 +574,11 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi_get_chipselect(spi, 0)); } + if (spi->mode & SPI_MOSI_IDLE_LOW) + cfg |= MX51_ECSPI_CONFIG_DATACTL(spi_get_chipselect(spi, 0)); + else + cfg &= ~MX51_ECSPI_CONFIG_DATACTL(spi_get_chipselect(spi, 0)); + if (spi->mode & SPI_CS_HIGH) cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi_get_chipselect(spi, 0)); else @@ -1743,7 +1749,8 @@ static int spi_imx_probe(struct platform_device *pdev) controller->prepare_message = spi_imx_prepare_message; controller->unprepare_message = spi_imx_unprepare_message; controller->slave_abort = spi_imx_slave_abort; - controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS; + controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS | + SPI_MOSI_IDLE_LOW; if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) || is_imx53_ecspi(spi_imx)) diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 39d94c850839..c8b938e0f342 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -64,7 +64,8 @@ static_assert(N_SPI_MINORS > 0 && N_SPI_MINORS <= 256); | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \ | SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL \ | SPI_RX_QUAD | SPI_RX_OCTAL \ - | SPI_RX_CPHA_FLIP) + | SPI_RX_CPHA_FLIP | SPI_3WIRE_HIZ \ + | SPI_MOSI_IDLE_LOW) struct spidev_data { dev_t devt; diff --git a/include/uapi/linux/spi/spi.h b/include/uapi/linux/spi/spi.h index 9d5f58059703..ca56e477d161 100644 --- a/include/uapi/linux/spi/spi.h +++ b/include/uapi/linux/spi/spi.h @@ -28,6 +28,7 @@ #define SPI_RX_OCTAL _BITUL(14) /* receive with 8 wires */ #define SPI_3WIRE_HIZ _BITUL(15) /* high impedance turnaround */ #define SPI_RX_CPHA_FLIP _BITUL(16) /* flip CPHA on Rx only xfer */ +#define SPI_MOSI_IDLE_LOW _BITUL(17) /* leave mosi line low when idle */ /* * All the bits defined above should be covered by SPI_MODE_USER_MASK. @@ -37,6 +38,6 @@ * These bits must not overlap. A static assert check should make sure of that. * If adding extra bits, make sure to increase the bit index below as well. */ -#define SPI_MODE_USER_MASK (_BITUL(17) - 1) +#define SPI_MODE_USER_MASK (_BITUL(18) - 1) #endif /* _UAPI_SPI_H */ diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c index b0ca44c70e83..9179942d7f15 100644 --- a/tools/spi/spidev_test.c +++ b/tools/spi/spidev_test.c @@ -172,28 +172,37 @@ static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len) static void print_usage(const char *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" - " -b --bpw bits per word\n" - " -i --input input data from a file (e.g. \"test.bin\")\n" - " -o --output output data to a file (e.g. \"results.bin\")\n" - " -l --loop loopback\n" - " -H --cpha clock phase\n" - " -O --cpol clock polarity\n" - " -L --lsb least significant bit first\n" - " -C --cs-high chip select active high\n" - " -3 --3wire SI/SO signals shared\n" - " -v --verbose Verbose (show tx buffer)\n" - " -p Send data (e.g. \"1234\\xde\\xad\")\n" - " -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" - " -8 --octal octal transfer\n" - " -S --size transfer size\n" - " -I --iter iterations\n"); + printf("Usage: %s [-2348CDFHILMNORSZbdilopsv]\n", prog); + puts("general device settings:\n" + " -D --device device to use (default /dev/spidev1.1)\n" + " -s --speed max speed (Hz)\n" + " -d --delay delay (usec)\n" + " -l --loop loopback\n" + "spi mode:\n" + " -H --cpha clock phase\n" + " -O --cpol clock polarity\n" + " -F --rx-cpha-flip flip CPHA on Rx only xfer\n" + "number of wires for transmission:\n" + " -2 --dual dual transfer\n" + " -4 --quad quad transfer\n" + " -8 --octal octal transfer\n" + " -3 --3wire SI/SO signals shared\n" + " -Z --3wire-hiz high impedance turnaround\n" + "data:\n" + " -i --input input data from a file (e.g. \"test.bin\")\n" + " -o --output output data to a file (e.g. \"results.bin\")\n" + " -p Send data (e.g. \"1234\\xde\\xad\")\n" + " -S --size transfer size\n" + " -I --iter iterations\n" + "additional parameters:\n" + " -b --bpw bits per word\n" + " -L --lsb least significant bit first\n" + " -C --cs-high chip select active high\n" + " -N --no-cs no chip select\n" + " -R --ready slave pulls low to pause\n" + " -M --mosi-idle-low leave mosi line low when idle\n" + "misc:\n" + " -v --verbose Verbose (show tx buffer)\n"); exit(1); } @@ -201,31 +210,34 @@ static void parse_opts(int argc, char *argv[]) { while (1) { static const struct option lopts[] = { - { "device", 1, 0, 'D' }, - { "speed", 1, 0, 's' }, - { "delay", 1, 0, 'd' }, - { "bpw", 1, 0, 'b' }, - { "input", 1, 0, 'i' }, - { "output", 1, 0, 'o' }, - { "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' }, - { "no-cs", 0, 0, 'N' }, - { "ready", 0, 0, 'R' }, - { "dual", 0, 0, '2' }, - { "verbose", 0, 0, 'v' }, - { "quad", 0, 0, '4' }, - { "octal", 0, 0, '8' }, - { "size", 1, 0, 'S' }, - { "iter", 1, 0, 'I' }, + { "device", 1, 0, 'D' }, + { "speed", 1, 0, 's' }, + { "delay", 1, 0, 'd' }, + { "loop", 0, 0, 'l' }, + { "cpha", 0, 0, 'H' }, + { "cpol", 0, 0, 'O' }, + { "rx-cpha-flip", 0, 0, 'F' }, + { "dual", 0, 0, '2' }, + { "quad", 0, 0, '4' }, + { "octal", 0, 0, '8' }, + { "3wire", 0, 0, '3' }, + { "3wire-hiz", 0, 0, 'Z' }, + { "input", 1, 0, 'i' }, + { "output", 1, 0, 'o' }, + { "size", 1, 0, 'S' }, + { "iter", 1, 0, 'I' }, + { "bpw", 1, 0, 'b' }, + { "lsb", 0, 0, 'L' }, + { "cs-high", 0, 0, 'C' }, + { "no-cs", 0, 0, 'N' }, + { "ready", 0, 0, 'R' }, + { "mosi-idle-low", 0, 0, 'M' }, + { "verbose", 0, 0, 'v' }, { NULL, 0, 0, 0 }, }; int c; - c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3NR248p:vS:I:", + c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3ZFMNR248p:vS:I:", lopts, NULL); if (c == -1) @@ -268,6 +280,15 @@ static void parse_opts(int argc, char *argv[]) case '3': mode |= SPI_3WIRE; break; + case 'Z': + mode |= SPI_3WIRE_HIZ; + break; + case 'F': + mode |= SPI_RX_CPHA_FLIP; + break; + case 'M': + mode |= SPI_MOSI_IDLE_LOW; + break; case 'N': mode |= SPI_NO_CS; break; |