Commit dc64d39b authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Mark Brown

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: default avatarGeert Uytterhoeven <geert+renesas@linux-m68k.org>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent e6456186
...@@ -85,6 +85,12 @@ settings for data transfer parameters: ...@@ -85,6 +85,12 @@ settings for data transfer parameters:
SPI_MODE_0..SPI_MODE_3; or if you prefer you can combine SPI_CPOL SPI_MODE_0..SPI_MODE_3; or if you prefer you can combine SPI_CPOL
(clock polarity, idle high iff this is set) or SPI_CPHA (clock phase, (clock polarity, idle high iff this is set) or SPI_CPHA (clock phase,
sample on trailing edge iff this is set) flags. sample on trailing edge iff this is set) flags.
Note that this request is limited to SPI mode flags that fit in a
single byte.
SPI_IOC_RD_MODE32, SPI_IOC_WR_MODE32 ... pass a pointer to a uin32_t
which will return (RD) or assign (WR) the full SPI transfer mode,
not limited to the bits that fit in one byte.
SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST ... pass a pointer to a byte SPI_IOC_RD_LSB_FIRST, SPI_IOC_WR_LSB_FIRST ... pass a pointer to a byte
which will return (RD) or assign (WR) the bit justification used to which will return (RD) or assign (WR) the bit justification used to
......
...@@ -73,7 +73,8 @@ static DECLARE_BITMAP(minors, N_SPI_MINORS); ...@@ -73,7 +73,8 @@ static DECLARE_BITMAP(minors, N_SPI_MINORS);
*/ */
#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ #define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \
| SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \
| SPI_NO_CS | SPI_READY) | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \
| SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)
struct spidev_data { struct spidev_data {
dev_t devt; dev_t devt;
...@@ -265,6 +266,8 @@ static int spidev_message(struct spidev_data *spidev, ...@@ -265,6 +266,8 @@ static int spidev_message(struct spidev_data *spidev,
buf += k_tmp->len; buf += k_tmp->len;
k_tmp->cs_change = !!u_tmp->cs_change; k_tmp->cs_change = !!u_tmp->cs_change;
k_tmp->tx_nbits = u_tmp->tx_nbits;
k_tmp->rx_nbits = u_tmp->rx_nbits;
k_tmp->bits_per_word = u_tmp->bits_per_word; k_tmp->bits_per_word = u_tmp->bits_per_word;
k_tmp->delay_usecs = u_tmp->delay_usecs; k_tmp->delay_usecs = u_tmp->delay_usecs;
k_tmp->speed_hz = u_tmp->speed_hz; k_tmp->speed_hz = u_tmp->speed_hz;
...@@ -359,6 +362,10 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -359,6 +362,10 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
retval = __put_user(spi->mode & SPI_MODE_MASK, retval = __put_user(spi->mode & SPI_MODE_MASK,
(__u8 __user *)arg); (__u8 __user *)arg);
break; break;
case SPI_IOC_RD_MODE32:
retval = __put_user(spi->mode & SPI_MODE_MASK,
(__u32 __user *)arg);
break;
case SPI_IOC_RD_LSB_FIRST: case SPI_IOC_RD_LSB_FIRST:
retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0,
(__u8 __user *)arg); (__u8 __user *)arg);
...@@ -372,7 +379,11 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -372,7 +379,11 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
/* write requests */ /* write requests */
case SPI_IOC_WR_MODE: case SPI_IOC_WR_MODE:
retval = __get_user(tmp, (u8 __user *)arg); case SPI_IOC_WR_MODE32:
if (cmd == SPI_IOC_WR_MODE)
retval = __get_user(tmp, (u8 __user *)arg);
else
retval = __get_user(tmp, (u32 __user *)arg);
if (retval == 0) { if (retval == 0) {
u32 save = spi->mode; u32 save = spi->mode;
...@@ -382,12 +393,12 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -382,12 +393,12 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
} }
tmp |= spi->mode & ~SPI_MODE_MASK; tmp |= spi->mode & ~SPI_MODE_MASK;
spi->mode = (u8)tmp; spi->mode = (u16)tmp;
retval = spi_setup(spi); retval = spi_setup(spi);
if (retval < 0) if (retval < 0)
spi->mode = save; spi->mode = save;
else else
dev_dbg(&spi->dev, "spi mode %02x\n", tmp); dev_dbg(&spi->dev, "spi mode %x\n", tmp);
} }
break; break;
case SPI_IOC_WR_LSB_FIRST: case SPI_IOC_WR_LSB_FIRST:
......
...@@ -42,6 +42,10 @@ ...@@ -42,6 +42,10 @@
#define SPI_LOOP 0x20 #define SPI_LOOP 0x20
#define SPI_NO_CS 0x40 #define SPI_NO_CS 0x40
#define SPI_READY 0x80 #define SPI_READY 0x80
#define SPI_TX_DUAL 0x100
#define SPI_TX_QUAD 0x200
#define SPI_RX_DUAL 0x400
#define SPI_RX_QUAD 0x800
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
...@@ -92,7 +96,9 @@ struct spi_ioc_transfer { ...@@ -92,7 +96,9 @@ struct spi_ioc_transfer {
__u16 delay_usecs; __u16 delay_usecs;
__u8 bits_per_word; __u8 bits_per_word;
__u8 cs_change; __u8 cs_change;
__u32 pad; __u8 tx_nbits;
__u8 rx_nbits;
__u16 pad;
/* If the contents of 'struct spi_ioc_transfer' ever change /* If the contents of 'struct spi_ioc_transfer' ever change
* incompatibly, then the ioctl number (currently 0) must change; * incompatibly, then the ioctl number (currently 0) must change;
...@@ -110,7 +116,7 @@ struct spi_ioc_transfer { ...@@ -110,7 +116,7 @@ struct spi_ioc_transfer {
#define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
/* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) */ /* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) (limited to 8 bits) */
#define SPI_IOC_RD_MODE _IOR(SPI_IOC_MAGIC, 1, __u8) #define SPI_IOC_RD_MODE _IOR(SPI_IOC_MAGIC, 1, __u8)
#define SPI_IOC_WR_MODE _IOW(SPI_IOC_MAGIC, 1, __u8) #define SPI_IOC_WR_MODE _IOW(SPI_IOC_MAGIC, 1, __u8)
...@@ -126,6 +132,10 @@ struct spi_ioc_transfer { ...@@ -126,6 +132,10 @@ struct spi_ioc_transfer {
#define SPI_IOC_RD_MAX_SPEED_HZ _IOR(SPI_IOC_MAGIC, 4, __u32) #define SPI_IOC_RD_MAX_SPEED_HZ _IOR(SPI_IOC_MAGIC, 4, __u32)
#define SPI_IOC_WR_MAX_SPEED_HZ _IOW(SPI_IOC_MAGIC, 4, __u32) #define SPI_IOC_WR_MAX_SPEED_HZ _IOW(SPI_IOC_MAGIC, 4, __u32)
/* Read / Write of the SPI mode field */
#define SPI_IOC_RD_MODE32 _IOR(SPI_IOC_MAGIC, 5, __u32)
#define SPI_IOC_WR_MODE32 _IOW(SPI_IOC_MAGIC, 5, __u32)
#endif /* SPIDEV_H */ #endif /* SPIDEV_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment