mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-03-30 10:55:03 +00:00
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>
This commit is contained in:
parent
e6456186ca
commit
dc64d39b54
3 changed files with 33 additions and 6 deletions
|
@ -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);
|
||||||
*/
|
*/
|
||||||
#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,
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
/* 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 @@
|
||||||
#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 {
|
||||||
__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 {
|
||||||
#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 {
|
||||||
#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 */
|
||||||
|
|
Loading…
Add table
Reference in a new issue