diff options
| author | Geert Uytterhoeven <geert+renesas@linux-m68k.org> | 2014-02-25 05:40:17 -0500 |
|---|---|---|
| committer | Mark Brown <broonie@linaro.org> | 2014-02-26 23:51:29 -0500 |
| commit | dc64d39b54c1e9db97a6fb1ca52598c981728157 (patch) | |
| tree | 4e68275a6ecd75f7ea65bd9d7d66c4007e1b1754 | |
| parent | e6456186cae76f80446ba911f77eb2f85d3d927e (diff) | |
spi: spidev: Add support for Dual/Quad SPI Transfers
Add support for Dual/Quad SPI Transfers to the spidev API.
As this uses SPI mode bits that don't fit in a single byte, two new
ioctls (SPI_IOC_RD_MODE32 and SPI_IOC_WR_MODE32) are introduced.
Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
| -rw-r--r-- | Documentation/spi/spidev | 6 | ||||
| -rw-r--r-- | drivers/spi/spidev.c | 19 | ||||
| -rw-r--r-- | include/uapi/linux/spi/spidev.h | 14 |
3 files changed, 33 insertions, 6 deletions
diff --git a/Documentation/spi/spidev b/Documentation/spi/spidev index ed2da5e5b28a..3d14035b1766 100644 --- a/Documentation/spi/spidev +++ b/Documentation/spi/spidev | |||
| @@ -85,6 +85,12 @@ settings for data transfer parameters: | |||
| 85 | SPI_MODE_0..SPI_MODE_3; or if you prefer you can combine SPI_CPOL | 85 | SPI_MODE_0..SPI_MODE_3; or if you prefer you can combine SPI_CPOL |
| 86 | (clock polarity, idle high iff this is set) or SPI_CPHA (clock phase, | 86 | (clock polarity, idle high iff this is set) or SPI_CPHA (clock phase, |
| 87 | sample on trailing edge iff this is set) flags. | 87 | sample on trailing edge iff this is set) flags. |
| 88 | Note that this request is limited to SPI mode flags that fit in a | ||
| 89 | single byte. | ||
| 90 | |||
| 91 | SPI_IOC_RD_MODE32, SPI_IOC_WR_MODE32 ... pass a pointer to a uin32_t | ||
| 92 | which will return (RD) or assign (WR) the full SPI transfer mode, | ||
| 93 | not limited to the bits that fit in one byte. | ||
| 88 | 94 | ||
| 89 | SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST ... pass a pointer to a byte | 95 | SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST ... pass a pointer to a byte |
| 90 | which will return (RD) or assign (WR) the bit justification used to | 96 | which will return (RD) or assign (WR) the bit justification used to |
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 2abc0f5a82be..e3bc23bb5883 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c | |||
| @@ -73,7 +73,8 @@ static DECLARE_BITMAP(minors, N_SPI_MINORS); | |||
| 73 | */ | 73 | */ |
| 74 | #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ | 74 | #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ |
| 75 | | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ | 75 | | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ |
| 76 | | SPI_NO_CS | SPI_READY) | 76 | | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \ |
| 77 | | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD) | ||
| 77 | 78 | ||
| 78 | struct spidev_data { | 79 | struct spidev_data { |
| 79 | dev_t devt; | 80 | dev_t devt; |
| @@ -265,6 +266,8 @@ static int spidev_message(struct spidev_data *spidev, | |||
| 265 | buf += k_tmp->len; | 266 | buf += k_tmp->len; |
| 266 | 267 | ||
| 267 | k_tmp->cs_change = !!u_tmp->cs_change; | 268 | k_tmp->cs_change = !!u_tmp->cs_change; |
| 269 | k_tmp->tx_nbits = u_tmp->tx_nbits; | ||
| 270 | k_tmp->rx_nbits = u_tmp->rx_nbits; | ||
| 268 | k_tmp->bits_per_word = u_tmp->bits_per_word; | 271 | k_tmp->bits_per_word = u_tmp->bits_per_word; |
| 269 | k_tmp->delay_usecs = u_tmp->delay_usecs; | 272 | k_tmp->delay_usecs = u_tmp->delay_usecs; |
| 270 | k_tmp->speed_hz = u_tmp->speed_hz; | 273 | k_tmp->speed_hz = u_tmp->speed_hz; |
| @@ -359,6 +362,10 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 359 | retval = __put_user(spi->mode & SPI_MODE_MASK, | 362 | retval = __put_user(spi->mode & SPI_MODE_MASK, |
| 360 | (__u8 __user *)arg); | 363 | (__u8 __user *)arg); |
| 361 | break; | 364 | break; |
| 365 | case SPI_IOC_RD_MODE32: | ||
| 366 | retval = __put_user(spi->mode & SPI_MODE_MASK, | ||
| 367 | (__u32 __user *)arg); | ||
| 368 | break; | ||
| 362 | case SPI_IOC_RD_LSB_FIRST: | 369 | case SPI_IOC_RD_LSB_FIRST: |
| 363 | retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, | 370 | retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, |
| 364 | (__u8 __user *)arg); | 371 | (__u8 __user *)arg); |
| @@ -372,7 +379,11 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 372 | 379 | ||
| 373 | /* write requests */ | 380 | /* write requests */ |
| 374 | case SPI_IOC_WR_MODE: | 381 | case SPI_IOC_WR_MODE: |
| 375 | retval = __get_user(tmp, (u8 __user *)arg); | 382 | case SPI_IOC_WR_MODE32: |
| 383 | if (cmd == SPI_IOC_WR_MODE) | ||
| 384 | retval = __get_user(tmp, (u8 __user *)arg); | ||
| 385 | else | ||
| 386 | retval = __get_user(tmp, (u32 __user *)arg); | ||
| 376 | if (retval == 0) { | 387 | if (retval == 0) { |
| 377 | u32 save = spi->mode; | 388 | u32 save = spi->mode; |
| 378 | 389 | ||
| @@ -382,12 +393,12 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 382 | } | 393 | } |
| 383 | 394 | ||
| 384 | tmp |= spi->mode & ~SPI_MODE_MASK; | 395 | tmp |= spi->mode & ~SPI_MODE_MASK; |
| 385 | spi->mode = (u8)tmp; | 396 | spi->mode = (u16)tmp; |
| 386 | retval = spi_setup(spi); | 397 | retval = spi_setup(spi); |
| 387 | if (retval < 0) | 398 | if (retval < 0) |
| 388 | spi->mode = save; | 399 | spi->mode = save; |
| 389 | else | 400 | else |
| 390 | dev_dbg(&spi->dev, "spi mode %02x\n", tmp); | 401 | dev_dbg(&spi->dev, "spi mode %x\n", tmp); |
| 391 | } | 402 | } |
| 392 | break; | 403 | break; |
| 393 | case SPI_IOC_WR_LSB_FIRST: | 404 | case SPI_IOC_WR_LSB_FIRST: |
diff --git a/include/uapi/linux/spi/spidev.h b/include/uapi/linux/spi/spidev.h index 52d9ed01855f..dd5f21e75805 100644 --- a/include/uapi/linux/spi/spidev.h +++ b/include/uapi/linux/spi/spidev.h | |||
| @@ -42,6 +42,10 @@ | |||
| 42 | #define SPI_LOOP 0x20 | 42 | #define SPI_LOOP 0x20 |
| 43 | #define SPI_NO_CS 0x40 | 43 | #define SPI_NO_CS 0x40 |
| 44 | #define SPI_READY 0x80 | 44 | #define SPI_READY 0x80 |
| 45 | #define SPI_TX_DUAL 0x100 | ||
| 46 | #define SPI_TX_QUAD 0x200 | ||
| 47 | #define SPI_RX_DUAL 0x400 | ||
| 48 | #define SPI_RX_QUAD 0x800 | ||
| 45 | 49 | ||
| 46 | /*---------------------------------------------------------------------------*/ | 50 | /*---------------------------------------------------------------------------*/ |
| 47 | 51 | ||
| @@ -92,7 +96,9 @@ struct spi_ioc_transfer { | |||
| 92 | __u16 delay_usecs; | 96 | __u16 delay_usecs; |
| 93 | __u8 bits_per_word; | 97 | __u8 bits_per_word; |
| 94 | __u8 cs_change; | 98 | __u8 cs_change; |
| 95 | __u32 pad; | 99 | __u8 tx_nbits; |
| 100 | __u8 rx_nbits; | ||
| 101 | __u16 pad; | ||
| 96 | 102 | ||
| 97 | /* If the contents of 'struct spi_ioc_transfer' ever change | 103 | /* If the contents of 'struct spi_ioc_transfer' ever change |
| 98 | * incompatibly, then the ioctl number (currently 0) must change; | 104 | * incompatibly, then the ioctl number (currently 0) must change; |
| @@ -110,7 +116,7 @@ struct spi_ioc_transfer { | |||
| 110 | #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) | 116 | #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) |
| 111 | 117 | ||
| 112 | 118 | ||
| 113 | /* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) */ | 119 | /* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) (limited to 8 bits) */ |
| 114 | #define SPI_IOC_RD_MODE _IOR(SPI_IOC_MAGIC, 1, __u8) | 120 | #define SPI_IOC_RD_MODE _IOR(SPI_IOC_MAGIC, 1, __u8) |
| 115 | #define SPI_IOC_WR_MODE _IOW(SPI_IOC_MAGIC, 1, __u8) | 121 | #define SPI_IOC_WR_MODE _IOW(SPI_IOC_MAGIC, 1, __u8) |
| 116 | 122 | ||
| @@ -126,6 +132,10 @@ struct spi_ioc_transfer { | |||
| 126 | #define SPI_IOC_RD_MAX_SPEED_HZ _IOR(SPI_IOC_MAGIC, 4, __u32) | 132 | #define SPI_IOC_RD_MAX_SPEED_HZ _IOR(SPI_IOC_MAGIC, 4, __u32) |
| 127 | #define SPI_IOC_WR_MAX_SPEED_HZ _IOW(SPI_IOC_MAGIC, 4, __u32) | 133 | #define SPI_IOC_WR_MAX_SPEED_HZ _IOW(SPI_IOC_MAGIC, 4, __u32) |
| 128 | 134 | ||
| 135 | /* Read / Write of the SPI mode field */ | ||
| 136 | #define SPI_IOC_RD_MODE32 _IOR(SPI_IOC_MAGIC, 5, __u32) | ||
| 137 | #define SPI_IOC_WR_MODE32 _IOW(SPI_IOC_MAGIC, 5, __u32) | ||
| 138 | |||
| 129 | 139 | ||
| 130 | 140 | ||
| 131 | #endif /* SPIDEV_H */ | 141 | #endif /* SPIDEV_H */ |
