aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert+renesas@linux-m68k.org>2014-02-25 05:40:17 -0500
committerMark Brown <broonie@linaro.org>2014-02-26 23:51:29 -0500
commitdc64d39b54c1e9db97a6fb1ca52598c981728157 (patch)
tree4e68275a6ecd75f7ea65bd9d7d66c4007e1b1754
parente6456186cae76f80446ba911f77eb2f85d3d927e (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/spidev6
-rw-r--r--drivers/spi/spidev.c19
-rw-r--r--include/uapi/linux/spi/spidev.h14
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
78struct spidev_data { 79struct 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 */