aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/spi/spi-imx.c9
-rw-r--r--drivers/spi/spidev.c3
-rw-r--r--include/uapi/linux/spi/spi.h3
-rw-r--r--tools/spi/spidev_test.c107
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;