All of lore.kernel.org
 help / color / mirror / Atom feed
From: yuhang wang <wangyuhang2014-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: "Gupta, Pekon" <pekon-l0cyMroinI0@public.gmane.org>
Cc: "thomas.langer-th3ZBGNqt+7QT0dZR+AlfA@public.gmane.org"
	<thomas.langer-th3ZBGNqt+7QT0dZR+AlfA@public.gmane.org>,
	Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	"linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org"
	<linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>,
	"spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org"
	<spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>,
	"Poddar, Sourav" <sourav.poddar-l0cyMroinI0@public.gmane.org>,
	Trent Piepho <tpiepho-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Subject: Re: support DUAL and QUAD[patch v1]
Date: Sat, 27 Jul 2013 19:35:02 +0800	[thread overview]
Message-ID: <CAHSAbzPehAjL81O3dOA8bqhH35Wh_VLp7O9Ok0_SwOUozZTqUw@mail.gmail.com> (raw)
In-Reply-To: <20980858CB6D3A4BAE95CA194937D5E73E9EC9B1-yXqyApvAXouIQmiDNMet8wC/G2K4zDHf@public.gmane.org>

2013/7/22 Gupta, Pekon <pekon-l0cyMroinI0@public.gmane.org>:
>>
>> > > Maybe it would make more sense to have a spi-rx-width and spi-tx-width
>> > > than can be set to 1, 2, 4, etc. bits instead of a bunch of properties
>> > > that are mutually exclusive?  Sooner or later someone is going to want
>> > > 8 bits.
>>
>> > Then it would not remain a serial interface (Serial Peripheral Interface),
>> > rather it would be more of parallel memory like interface.
>> > And you would not like to use SPI controller for it, instead you would use
>> > On-chip General Purpose External Interface controllers (like GPMC)
>> > because it gives you more options to tweak and configure.
>>
>> It's still not beyoond the bounds of possibility, and of course some
>> bright spark might decide to use 3 wires.  Unless it's expensive to do
>> so in some way it seems better to keep the interface as generic as
>> possible even if we've no expectation that some of the flexibility will
>> be used.
>>
> Ok.. Agreed,  I don't have any preference here between
> "rx-width , tx-width" v/s "mode".
> But please make sure that whichever implementation is chosen,
> it should allow dynamic changing of channel-width.
>
> Granularity should be based on following decisions:
> (a) struct spi_message: if all transfers of same message follow same
>  channel width. Example: All spi_messages from MTD layer would
> use Qual-SPI only (both flash-commands and data).
>
> (b) struct spi_transfer: if each transfer of same message need to be
> transferred at different width.         Example: Command @ Single-SPI
>  followed by Data @ Quad-SPI
>
>
> with regards, pekon


Hi,
 I corrected the previous patch as below.
 1:dual and quad is still as the attribute in mode. Just like SPI_3WIRE,
  dual and quad also can be regarded as a spi interface.
  Another point, master->mode_bits and spi_device->mode will be checked
  in spi_setup to prevend some mode that master dont support. It is
  better than add new member and do redundant check operation.
 2:To spidev, in order to backward compatible, still use
  SPI_IOC_RD_MODE to deal with user who use <u8 mode>. Add
  SPI_IOC_EXTRD_MODE to fix the <u16 mode>. And SPI_IOC_RD_LSB_FIRST
  seems a little redundant, so del it.

Signed-off-by: wangyuhang <wangyuhang2014-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
 ---
  drivers/spi/spi.c               |   14 ++++++++++++++
  drivers/spi/spidev.c            |   39 +++++++++++++--------------------------
  include/linux/spi/spi.h         |   20 ++++++++++++++++++--
  include/uapi/linux/spi/spidev.h |   20 +++++++++++++++-----
  4 files changed, 60 insertions(+), 33 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
 index 004b10f..dc6a7ba 100644
 --- a/drivers/spi/spi.c
 +++ b/drivers/spi/spi.c
 @@ -868,6 +868,14 @@ static void of_register_spi_devices(struct
spi_master *master)
                         spi->mode |= SPI_CS_HIGH;
                 if (of_find_property(nc, "spi-3wire", NULL))
                         spi->mode |= SPI_3WIRE;
 +               if (of_find_property(nc, "spi-tx-dual", NULL))
 +                       spi->mode |= SPI_TX_DUAL;
 +               if (of_find_property(nc, "spi-tx-quad", NULL))
 +                       spi->mode |= SPI_TX_QUAD;
 +               if (of_find_property(nc, "spi-rx-dual", NULL))
 +                       spi->mode |= SPI_RX_DUAL;
 +               if (of_find_property(nc, "spi-rx-quad", NULL))
 +                       spi->mode |= SPI_RX_QUAD;

                /* Device speed */
                 prop = of_get_property(nc, "spi-max-frequency", &len);
 @@ -1316,6 +1324,12 @@ int spi_setup(struct spi_device *spi)
         /* help drivers fail *cleanly* when they need options
          * that aren't supported with their current master
          */
 +       if (((spi->mode >> 8) & 0x03) == 0x03 ||
 +               ((spi->mode >> 10) & 0x03) == 0x03) {
 +               dev_err(&spi->dev,
 +               "setup: can not select dual and quad at the same time\n");
 +               return -EINVAL;
 +       }
         bad_bits = spi->mode & ~spi->master->mode_bits;
         if (bad_bits) {
                 dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
 diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
 index 2e0655d..be96cb5 100644
 --- a/drivers/spi/spidev.c
 +++ b/drivers/spi/spidev.c
 @@ -75,6 +75,9 @@ static DECLARE_BITMAP(minors, N_SPI_MINORS);
                                 | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \
                                 | SPI_NO_CS | SPI_READY)

+#define SPI_EXTMODE_MASK       (SPI_MODE_MASK | SPI_TX_DUAL \
 +                               | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)
 +
  struct spidev_data {
         dev_t                   devt;
         spinlock_t              spi_lock;
 @@ -268,6 +271,8 @@ static int spidev_message(struct spidev_data *spidev,
                 k_tmp->bits_per_word = u_tmp->bits_per_word;
                 k_tmp->delay_usecs = u_tmp->delay_usecs;
                 k_tmp->speed_hz = u_tmp->speed_hz;
 +               k_tmp->tx_nbits = u_tmp->tx_nbits;
 +               k_tmp->rx_nbits = u_tmp->rx_nbits;
  #ifdef VERBOSE
                 dev_dbg(&spidev->spi->dev,
                         "  xfer len %zd %s%s%s%dbits %u usec %uHz\n",
 @@ -359,10 +364,9 @@ spidev_ioctl(struct file *filp, unsigned int
cmd, unsigned long arg)
                 retval = __put_user(spi->mode & SPI_MODE_MASK,
                                         (__u8 __user *)arg);
                 break;
 -       case SPI_IOC_RD_LSB_FIRST:
 -               retval = __put_user((spi->mode & SPI_LSB_FIRST) ?  1 : 0,
 -                                       (__u8 __user *)arg);
 -               break;
 +       case SPI_IOC_EXTRD_MODE:
 +               retval = __put_user(spi->mode & SPI_EXTMODE_MASK,
 +                                       (__u16 __user *)arg);
         case SPI_IOC_RD_BITS_PER_WORD:
                 retval = __put_user(spi->bits_per_word, (__u8 __user *)arg);
                 break;
 @@ -372,17 +376,17 @@ spidev_ioctl(struct file *filp, unsigned int
cmd, unsigned long arg)

        /* write requests */
         case SPI_IOC_WR_MODE:
 -               retval = __get_user(tmp, (u8 __user *)arg);
 +               retval = __get_user(tmp, (u16 __user *)arg);
                 if (retval == 0) {
 -                       u8      save = spi->mode;
 +                       u16     save = spi->mode;

-                       if (tmp & ~SPI_MODE_MASK) {
 +                       if (tmp & ~SPI_EXTMODE_MASK) {
                                 retval = -EINVAL;
                                 break;
                         }

-                       tmp |= spi->mode & ~SPI_MODE_MASK;
 -                       spi->mode = (u8)tmp;
 +                       tmp |= spi->mode & ~SPI_EXTMODE_MASK;
 +                       spi->mode = (u16)tmp;
                         retval = spi_setup(spi);
                         if (retval < 0)
                                 spi->mode = save;
 @@ -390,23 +394,6 @@ spidev_ioctl(struct file *filp, unsigned int
cmd, unsigned long arg)
                                 dev_dbg(&spi->dev, "spi mode %02x\n", tmp);
                 }
                 break;
 -       case SPI_IOC_WR_LSB_FIRST:
 -               retval = __get_user(tmp, (__u8 __user *)arg);
 -               if (retval == 0) {
 -                       u8      save = spi->mode;
 -
 -                       if (tmp)
 -                               spi->mode |= SPI_LSB_FIRST;
 -                       else
 -                               spi->mode &= ~SPI_LSB_FIRST;
 -                       retval = spi_setup(spi);
 -                       if (retval < 0)
 -                               spi->mode = save;
 -                       else
 -                               dev_dbg(&spi->dev, "%csb first\n",
 -                                               tmp ? 'l' : 'm');
 -               }
 -               break;
         case SPI_IOC_WR_BITS_PER_WORD:
                 retval = __get_user(tmp, (__u8 __user *)arg);
                 if (retval == 0) {
 diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
 index 38c2b92..222e49e 100644
 --- a/include/linux/spi/spi.h
 +++ b/include/linux/spi/spi.h
 @@ -74,7 +74,7 @@ struct spi_device {
         struct spi_master       *master;
         u32                     max_speed_hz;
         u8                      chip_select;
 -       u8                      mode;
 +       u16                     mode;
  #define        SPI_CPHA        0x01                    /* clock phase */
  #define        SPI_CPOL        0x02                    /* clock polarity */
  #define        SPI_MODE_0      (0|0)                   /* (original
MicroWire) */
 @@ -87,6 +87,10 @@ struct spi_device {
  #define        SPI_LOOP        0x20                    /* loopback mode */
  #define        SPI_NO_CS       0x40                    /* 1 dev/bus,
no chipselect */
  #define        SPI_READY       0x80                    /* slave
pulls low to pause */
 +#define        SPI_TX_DUAL     0x100                   /* transmit
with 2 wires */
 +#define        SPI_TX_QUAD     0x200                   /* transmit
with 4 wires */
 +#define        SPI_RX_DUAL     0x400                   /* receive
with 2 wires */
 +#define        SPI_RX_QUAD     0x800                   /* receive
with 4 wires */
         u8                      bits_per_word;
         int                     irq;
         void                    *controller_state;
 @@ -437,6 +441,8 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
   * @rx_buf: data to be read (dma-safe memory), or NULL
   * @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped
   * @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped
 + * @tx_nbits: number of bits used for writting
 + * @rx_nbits: number of bits used for reading
   * @len: size of rx and tx buffers (in bytes)
   * @speed_hz: Select a speed other than the device default for this
   *      transfer. If 0 the default (from @spi_device) is used.
 @@ -491,6 +497,11 @@ extern struct spi_master
*spi_busnum_to_master(u16 busnum);
   * by the results of previous messages and where the whole transaction
   * ends when the chipselect goes intactive.
   *
 + * When SPI can transfer in 1x,2x or 4x. It can get this tranfer information
 + * from device through @tx_nbits and @rx_nbits. In Bi-direction, these
 + * two should both be set. User can set transfer mode with
SPI_NBITS_SINGLE(1x)
 + * SPI_NBITS_DUAL(2x) and SPI_NBITS_QUAD(4x) to support these three transfer.
 + *
   * The code that submits an spi_message (and its spi_transfers)
   * to the lower layers is responsible for managing its memory.
   * Zero-initialize every field you don't set up explicitly, to
 @@ -511,6 +522,11 @@ struct spi_transfer {
         dma_addr_t      rx_dma;

        unsigned        cs_change:1;
 +       u8              tx_nbits;
 +       u8              rx_nbits;
 +#define        SPI_NBITS_SINGLE        0x0; /* 1bit transfer */
 +#define        SPI_NBITS_DUAL          0x01; /* 2bits transfer */
 +#define        SPI_NBITS_QUAD          0x02; /* 4bits transfer */
         u8              bits_per_word;
         u16             delay_usecs;
         u32             speed_hz;
 @@ -858,7 +874,7 @@ struct spi_board_info {
         /* mode becomes spi_device.mode, and is essential for chips
          * where the default of SPI_CS_HIGH = 0 is wrong.
          */
 -       u8              mode;
 +       u16             mode;

        /* ... may need additional spi_device chip config data here.
          * avoid stuff protocol drivers can set; but include stuff
 diff --git a/include/uapi/linux/spi/spidev.h b/include/uapi/linux/spi/spidev.h
 index 52d9ed0..5dc1e95 100644
 --- a/include/uapi/linux/spi/spidev.h
 +++ b/include/uapi/linux/spi/spidev.h
 @@ -42,7 +42,14 @@
  #define SPI_LOOP               0x20
  #define SPI_NO_CS              0x40
  #define SPI_READY              0x80
 -
 +#define        SPI_TX_DUAL             0x100
 +#define        SPI_TX_QUAD             0x200
 +#define        SPI_RX_DUAL             0x400
 +#define        SPI_RX_QUAD             0x800
 +
 +#define        SPI_NBITS_SINGLE        0x0; /* 1bit transfer */
 +#define        SPI_NBITS_DUAL          0x01; /* 2bits transfer */
 +#define        SPI_NBITS_QUAD          0x02; /* 4bits transfer */
  /*---------------------------------------------------------------------------*/

 /* IOCTL commands */
 @@ -54,6 +61,8 @@
   * @tx_buf: Holds pointer to userspace buffer with transmit data, or null.
   *     If no data is provided, zeroes are shifted out.
   * @rx_buf: Holds pointer to userspace buffer for receive data, or null.
 + * @tx_nbits: number of bits used for writting.
 + * @rx_nbits: number of bits used for reading.
   * @len: Length of tx and rx buffers, in bytes.
   * @speed_hz: Temporary override of the device's bitrate.
   * @bits_per_word: Temporary override of the device's wordsize.
 @@ -85,6 +94,8 @@
  struct spi_ioc_transfer {
         __u64           tx_buf;
         __u64           rx_buf;
 +       __u8            tx_nbits;
 +       __u8            rx_nbits;

        __u32           len;
         __u32           speed_hz;
 @@ -112,11 +123,10 @@ struct spi_ioc_transfer {

 /* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) */
  #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, __u16)

-/* Read / Write SPI bit justification */
 -#define SPI_IOC_RD_LSB_FIRST           _IOR(SPI_IOC_MAGIC, 2, __u8)
 -#define SPI_IOC_WR_LSB_FIRST           _IOW(SPI_IOC_MAGIC, 2, __u8)
 +/* Read of SPI mode (including SPI DUAL/QUAD) */
 +#define SPI_IOC_EXTRD_MODE             _IOR(SPI_IOC_MAGIC, 2, __u16)

 /* Read / Write SPI device word length (1..N) */
  #define SPI_IOC_RD_BITS_PER_WORD       _IOR(SPI_IOC_MAGIC, 3, __u8)

------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk

WARNING: multiple messages have this Message-ID (diff)
From: yuhang wang <wangyuhang2014@gmail.com>
To: "Gupta, Pekon" <pekon@ti.com>
Cc: "thomas.langer@lantiq.com" <thomas.langer@lantiq.com>,
	Mark Brown <broonie@kernel.org>,
	"linux-mtd@lists.infradead.org" <linux-mtd@lists.infradead.org>,
	"spi-devel-general@lists.sourceforge.net"
	<spi-devel-general@lists.sourceforge.net>,
	"Poddar, Sourav" <sourav.poddar@ti.com>,
	Trent Piepho <tpiepho@gmail.com>
Subject: Re: support DUAL and QUAD[patch v1]
Date: Sat, 27 Jul 2013 19:35:02 +0800	[thread overview]
Message-ID: <CAHSAbzPehAjL81O3dOA8bqhH35Wh_VLp7O9Ok0_SwOUozZTqUw@mail.gmail.com> (raw)
In-Reply-To: <20980858CB6D3A4BAE95CA194937D5E73E9EC9B1@DBDE04.ent.ti.com>

2013/7/22 Gupta, Pekon <pekon@ti.com>:
>>
>> > > Maybe it would make more sense to have a spi-rx-width and spi-tx-width
>> > > than can be set to 1, 2, 4, etc. bits instead of a bunch of properties
>> > > that are mutually exclusive?  Sooner or later someone is going to want
>> > > 8 bits.
>>
>> > Then it would not remain a serial interface (Serial Peripheral Interface),
>> > rather it would be more of parallel memory like interface.
>> > And you would not like to use SPI controller for it, instead you would use
>> > On-chip General Purpose External Interface controllers (like GPMC)
>> > because it gives you more options to tweak and configure.
>>
>> It's still not beyoond the bounds of possibility, and of course some
>> bright spark might decide to use 3 wires.  Unless it's expensive to do
>> so in some way it seems better to keep the interface as generic as
>> possible even if we've no expectation that some of the flexibility will
>> be used.
>>
> Ok.. Agreed,  I don't have any preference here between
> "rx-width , tx-width" v/s "mode".
> But please make sure that whichever implementation is chosen,
> it should allow dynamic changing of channel-width.
>
> Granularity should be based on following decisions:
> (a) struct spi_message: if all transfers of same message follow same
>  channel width. Example: All spi_messages from MTD layer would
> use Qual-SPI only (both flash-commands and data).
>
> (b) struct spi_transfer: if each transfer of same message need to be
> transferred at different width.         Example: Command @ Single-SPI
>  followed by Data @ Quad-SPI
>
>
> with regards, pekon


Hi,
 I corrected the previous patch as below.
 1:dual and quad is still as the attribute in mode. Just like SPI_3WIRE,
  dual and quad also can be regarded as a spi interface.
  Another point, master->mode_bits and spi_device->mode will be checked
  in spi_setup to prevend some mode that master dont support. It is
  better than add new member and do redundant check operation.
 2:To spidev, in order to backward compatible, still use
  SPI_IOC_RD_MODE to deal with user who use <u8 mode>. Add
  SPI_IOC_EXTRD_MODE to fix the <u16 mode>. And SPI_IOC_RD_LSB_FIRST
  seems a little redundant, so del it.

Signed-off-by: wangyuhang <wangyuhang2014@gmail.com>
 ---
  drivers/spi/spi.c               |   14 ++++++++++++++
  drivers/spi/spidev.c            |   39 +++++++++++++--------------------------
  include/linux/spi/spi.h         |   20 ++++++++++++++++++--
  include/uapi/linux/spi/spidev.h |   20 +++++++++++++++-----
  4 files changed, 60 insertions(+), 33 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
 index 004b10f..dc6a7ba 100644
 --- a/drivers/spi/spi.c
 +++ b/drivers/spi/spi.c
 @@ -868,6 +868,14 @@ static void of_register_spi_devices(struct
spi_master *master)
                         spi->mode |= SPI_CS_HIGH;
                 if (of_find_property(nc, "spi-3wire", NULL))
                         spi->mode |= SPI_3WIRE;
 +               if (of_find_property(nc, "spi-tx-dual", NULL))
 +                       spi->mode |= SPI_TX_DUAL;
 +               if (of_find_property(nc, "spi-tx-quad", NULL))
 +                       spi->mode |= SPI_TX_QUAD;
 +               if (of_find_property(nc, "spi-rx-dual", NULL))
 +                       spi->mode |= SPI_RX_DUAL;
 +               if (of_find_property(nc, "spi-rx-quad", NULL))
 +                       spi->mode |= SPI_RX_QUAD;

                /* Device speed */
                 prop = of_get_property(nc, "spi-max-frequency", &len);
 @@ -1316,6 +1324,12 @@ int spi_setup(struct spi_device *spi)
         /* help drivers fail *cleanly* when they need options
          * that aren't supported with their current master
          */
 +       if (((spi->mode >> 8) & 0x03) == 0x03 ||
 +               ((spi->mode >> 10) & 0x03) == 0x03) {
 +               dev_err(&spi->dev,
 +               "setup: can not select dual and quad at the same time\n");
 +               return -EINVAL;
 +       }
         bad_bits = spi->mode & ~spi->master->mode_bits;
         if (bad_bits) {
                 dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
 diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
 index 2e0655d..be96cb5 100644
 --- a/drivers/spi/spidev.c
 +++ b/drivers/spi/spidev.c
 @@ -75,6 +75,9 @@ static DECLARE_BITMAP(minors, N_SPI_MINORS);
                                 | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \
                                 | SPI_NO_CS | SPI_READY)

+#define SPI_EXTMODE_MASK       (SPI_MODE_MASK | SPI_TX_DUAL \
 +                               | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)
 +
  struct spidev_data {
         dev_t                   devt;
         spinlock_t              spi_lock;
 @@ -268,6 +271,8 @@ static int spidev_message(struct spidev_data *spidev,
                 k_tmp->bits_per_word = u_tmp->bits_per_word;
                 k_tmp->delay_usecs = u_tmp->delay_usecs;
                 k_tmp->speed_hz = u_tmp->speed_hz;
 +               k_tmp->tx_nbits = u_tmp->tx_nbits;
 +               k_tmp->rx_nbits = u_tmp->rx_nbits;
  #ifdef VERBOSE
                 dev_dbg(&spidev->spi->dev,
                         "  xfer len %zd %s%s%s%dbits %u usec %uHz\n",
 @@ -359,10 +364,9 @@ spidev_ioctl(struct file *filp, unsigned int
cmd, unsigned long arg)
                 retval = __put_user(spi->mode & SPI_MODE_MASK,
                                         (__u8 __user *)arg);
                 break;
 -       case SPI_IOC_RD_LSB_FIRST:
 -               retval = __put_user((spi->mode & SPI_LSB_FIRST) ?  1 : 0,
 -                                       (__u8 __user *)arg);
 -               break;
 +       case SPI_IOC_EXTRD_MODE:
 +               retval = __put_user(spi->mode & SPI_EXTMODE_MASK,
 +                                       (__u16 __user *)arg);
         case SPI_IOC_RD_BITS_PER_WORD:
                 retval = __put_user(spi->bits_per_word, (__u8 __user *)arg);
                 break;
 @@ -372,17 +376,17 @@ spidev_ioctl(struct file *filp, unsigned int
cmd, unsigned long arg)

        /* write requests */
         case SPI_IOC_WR_MODE:
 -               retval = __get_user(tmp, (u8 __user *)arg);
 +               retval = __get_user(tmp, (u16 __user *)arg);
                 if (retval == 0) {
 -                       u8      save = spi->mode;
 +                       u16     save = spi->mode;

-                       if (tmp & ~SPI_MODE_MASK) {
 +                       if (tmp & ~SPI_EXTMODE_MASK) {
                                 retval = -EINVAL;
                                 break;
                         }

-                       tmp |= spi->mode & ~SPI_MODE_MASK;
 -                       spi->mode = (u8)tmp;
 +                       tmp |= spi->mode & ~SPI_EXTMODE_MASK;
 +                       spi->mode = (u16)tmp;
                         retval = spi_setup(spi);
                         if (retval < 0)
                                 spi->mode = save;
 @@ -390,23 +394,6 @@ spidev_ioctl(struct file *filp, unsigned int
cmd, unsigned long arg)
                                 dev_dbg(&spi->dev, "spi mode %02x\n", tmp);
                 }
                 break;
 -       case SPI_IOC_WR_LSB_FIRST:
 -               retval = __get_user(tmp, (__u8 __user *)arg);
 -               if (retval == 0) {
 -                       u8      save = spi->mode;
 -
 -                       if (tmp)
 -                               spi->mode |= SPI_LSB_FIRST;
 -                       else
 -                               spi->mode &= ~SPI_LSB_FIRST;
 -                       retval = spi_setup(spi);
 -                       if (retval < 0)
 -                               spi->mode = save;
 -                       else
 -                               dev_dbg(&spi->dev, "%csb first\n",
 -                                               tmp ? 'l' : 'm');
 -               }
 -               break;
         case SPI_IOC_WR_BITS_PER_WORD:
                 retval = __get_user(tmp, (__u8 __user *)arg);
                 if (retval == 0) {
 diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
 index 38c2b92..222e49e 100644
 --- a/include/linux/spi/spi.h
 +++ b/include/linux/spi/spi.h
 @@ -74,7 +74,7 @@ struct spi_device {
         struct spi_master       *master;
         u32                     max_speed_hz;
         u8                      chip_select;
 -       u8                      mode;
 +       u16                     mode;
  #define        SPI_CPHA        0x01                    /* clock phase */
  #define        SPI_CPOL        0x02                    /* clock polarity */
  #define        SPI_MODE_0      (0|0)                   /* (original
MicroWire) */
 @@ -87,6 +87,10 @@ struct spi_device {
  #define        SPI_LOOP        0x20                    /* loopback mode */
  #define        SPI_NO_CS       0x40                    /* 1 dev/bus,
no chipselect */
  #define        SPI_READY       0x80                    /* slave
pulls low to pause */
 +#define        SPI_TX_DUAL     0x100                   /* transmit
with 2 wires */
 +#define        SPI_TX_QUAD     0x200                   /* transmit
with 4 wires */
 +#define        SPI_RX_DUAL     0x400                   /* receive
with 2 wires */
 +#define        SPI_RX_QUAD     0x800                   /* receive
with 4 wires */
         u8                      bits_per_word;
         int                     irq;
         void                    *controller_state;
 @@ -437,6 +441,8 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
   * @rx_buf: data to be read (dma-safe memory), or NULL
   * @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped
   * @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped
 + * @tx_nbits: number of bits used for writting
 + * @rx_nbits: number of bits used for reading
   * @len: size of rx and tx buffers (in bytes)
   * @speed_hz: Select a speed other than the device default for this
   *      transfer. If 0 the default (from @spi_device) is used.
 @@ -491,6 +497,11 @@ extern struct spi_master
*spi_busnum_to_master(u16 busnum);
   * by the results of previous messages and where the whole transaction
   * ends when the chipselect goes intactive.
   *
 + * When SPI can transfer in 1x,2x or 4x. It can get this tranfer information
 + * from device through @tx_nbits and @rx_nbits. In Bi-direction, these
 + * two should both be set. User can set transfer mode with
SPI_NBITS_SINGLE(1x)
 + * SPI_NBITS_DUAL(2x) and SPI_NBITS_QUAD(4x) to support these three transfer.
 + *
   * The code that submits an spi_message (and its spi_transfers)
   * to the lower layers is responsible for managing its memory.
   * Zero-initialize every field you don't set up explicitly, to
 @@ -511,6 +522,11 @@ struct spi_transfer {
         dma_addr_t      rx_dma;

        unsigned        cs_change:1;
 +       u8              tx_nbits;
 +       u8              rx_nbits;
 +#define        SPI_NBITS_SINGLE        0x0; /* 1bit transfer */
 +#define        SPI_NBITS_DUAL          0x01; /* 2bits transfer */
 +#define        SPI_NBITS_QUAD          0x02; /* 4bits transfer */
         u8              bits_per_word;
         u16             delay_usecs;
         u32             speed_hz;
 @@ -858,7 +874,7 @@ struct spi_board_info {
         /* mode becomes spi_device.mode, and is essential for chips
          * where the default of SPI_CS_HIGH = 0 is wrong.
          */
 -       u8              mode;
 +       u16             mode;

        /* ... may need additional spi_device chip config data here.
          * avoid stuff protocol drivers can set; but include stuff
 diff --git a/include/uapi/linux/spi/spidev.h b/include/uapi/linux/spi/spidev.h
 index 52d9ed0..5dc1e95 100644
 --- a/include/uapi/linux/spi/spidev.h
 +++ b/include/uapi/linux/spi/spidev.h
 @@ -42,7 +42,14 @@
  #define SPI_LOOP               0x20
  #define SPI_NO_CS              0x40
  #define SPI_READY              0x80
 -
 +#define        SPI_TX_DUAL             0x100
 +#define        SPI_TX_QUAD             0x200
 +#define        SPI_RX_DUAL             0x400
 +#define        SPI_RX_QUAD             0x800
 +
 +#define        SPI_NBITS_SINGLE        0x0; /* 1bit transfer */
 +#define        SPI_NBITS_DUAL          0x01; /* 2bits transfer */
 +#define        SPI_NBITS_QUAD          0x02; /* 4bits transfer */
  /*---------------------------------------------------------------------------*/

 /* IOCTL commands */
 @@ -54,6 +61,8 @@
   * @tx_buf: Holds pointer to userspace buffer with transmit data, or null.
   *     If no data is provided, zeroes are shifted out.
   * @rx_buf: Holds pointer to userspace buffer for receive data, or null.
 + * @tx_nbits: number of bits used for writting.
 + * @rx_nbits: number of bits used for reading.
   * @len: Length of tx and rx buffers, in bytes.
   * @speed_hz: Temporary override of the device's bitrate.
   * @bits_per_word: Temporary override of the device's wordsize.
 @@ -85,6 +94,8 @@
  struct spi_ioc_transfer {
         __u64           tx_buf;
         __u64           rx_buf;
 +       __u8            tx_nbits;
 +       __u8            rx_nbits;

        __u32           len;
         __u32           speed_hz;
 @@ -112,11 +123,10 @@ struct spi_ioc_transfer {

 /* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) */
  #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, __u16)

-/* Read / Write SPI bit justification */
 -#define SPI_IOC_RD_LSB_FIRST           _IOR(SPI_IOC_MAGIC, 2, __u8)
 -#define SPI_IOC_WR_LSB_FIRST           _IOW(SPI_IOC_MAGIC, 2, __u8)
 +/* Read of SPI mode (including SPI DUAL/QUAD) */
 +#define SPI_IOC_EXTRD_MODE             _IOR(SPI_IOC_MAGIC, 2, __u16)

 /* Read / Write SPI device word length (1..N) */
  #define SPI_IOC_RD_BITS_PER_WORD       _IOR(SPI_IOC_MAGIC, 3, __u8)

  parent reply	other threads:[~2013-07-27 11:35 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-10  8:34 SPI: support DUAL and QUAD[patch v1] yuhang wang
2013-07-10  8:34 ` yuhang wang
     [not found] ` <CAHSAbzP0Nc1ahf_ra6yDuMvV998_+EGcUOGDv5ifKaagYf+NOg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2013-07-16  8:08   ` Gupta, Pekon
2013-07-16  8:08     ` Gupta, Pekon
     [not found]     ` <20980858CB6D3A4BAE95CA194937D5E73E9E84D2-yXqyApvAXouIQmiDNMet8wC/G2K4zDHf@public.gmane.org>
2013-07-16  8:59       ` yuhang wang
2013-07-16  8:59         ` yuhang wang
     [not found]         ` <CAHSAbzMDOWo5oBqUHqMxybuDwUjFbczYwN+85gH+rxZ9z8u2Pw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2013-07-16  9:11           ` Gupta, Pekon
2013-07-16  9:11             ` Gupta, Pekon
     [not found]             ` <20980858CB6D3A4BAE95CA194937D5E73E9E851E-yXqyApvAXouIQmiDNMet8wC/G2K4zDHf@public.gmane.org>
2013-07-16 10:12               ` thomas.langer-th3ZBGNqt+7QT0dZR+AlfA
2013-07-16 10:12                 ` thomas.langer
     [not found]                 ` <593AEF6C47F46446852B067021A273D6D93B49E1-6yu8tajIPx7U45ihrnOXy0EOCMrvLtNR@public.gmane.org>
2013-07-16 11:20                   ` Gupta, Pekon
2013-07-16 11:20                     ` Gupta, Pekon
     [not found]                     ` <20980858CB6D3A4BAE95CA194937D5E73E9E85D0-yXqyApvAXouIQmiDNMet8wC/G2K4zDHf@public.gmane.org>
2013-07-16 11:59                       ` yuhang wang
2013-07-16 11:59                         ` yuhang wang
2013-07-16 12:18                       ` thomas.langer-th3ZBGNqt+7QT0dZR+AlfA
2013-07-16 12:18                         ` thomas.langer
2013-07-18  1:58                       ` yuhang wang
2013-07-18  1:58                         ` yuhang wang
     [not found]                         ` <CAHSAbzP5jqHwCm0qhu=DiNzpP0swqWHsQ0=MnF+EKaSN22E5hg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2013-07-18  2:25                           ` Trent Piepho
2013-07-18  2:25                             ` Trent Piepho
     [not found]                             ` <CA+7tXihoZZhpoyvxj58c+Zi-Zy631kK5s-kDoSxPKq=ej0qyvA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2013-07-19  2:24                               ` yuhang wang
2013-07-19  2:24                                 ` yuhang wang
2013-07-19 19:34                               ` Gupta, Pekon
2013-07-19 19:34                                 ` Gupta, Pekon
2013-07-22  9:33                                 ` Mark Brown
2013-07-22  9:33                                   ` Mark Brown
     [not found]                                   ` <20130722093342.GJ9858-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2013-07-22  9:56                                     ` Gupta, Pekon
2013-07-22  9:56                                       ` Gupta, Pekon
2013-07-22 10:32                                       ` Huang Shijie
2013-07-22 10:32                                         ` Huang Shijie
     [not found]                                         ` <51ED0A57.4060105-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
2013-07-22 11:21                                           ` thomas.langer-th3ZBGNqt+7QT0dZR+AlfA
2013-07-22 11:21                                             ` thomas.langer
2013-07-22 12:55                                             ` Gupta, Pekon
2013-07-22 12:55                                               ` Gupta, Pekon
     [not found]                                               ` <20980858CB6D3A4BAE95CA194937D5E73E9ECAFC-yXqyApvAXouIQmiDNMet8wC/G2K4zDHf@public.gmane.org>
2013-07-23  2:24                                                 ` Huang Shijie
2013-07-23  2:24                                                   ` Huang Shijie
     [not found]                                       ` <20980858CB6D3A4BAE95CA194937D5E73E9EC9B1-yXqyApvAXouIQmiDNMet8wC/G2K4zDHf@public.gmane.org>
2013-07-27 11:35                                         ` yuhang wang [this message]
2013-07-27 11:35                                           ` yuhang wang
2013-07-16  9:29         ` Mark Brown
2013-07-16  9:29           ` Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAHSAbzPehAjL81O3dOA8bqhH35Wh_VLp7O9Ok0_SwOUozZTqUw@mail.gmail.com \
    --to=wangyuhang2014-re5jqeeqqe8avxtiumwx3w@public.gmane.org \
    --cc=broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=pekon-l0cyMroinI0@public.gmane.org \
    --cc=sourav.poddar-l0cyMroinI0@public.gmane.org \
    --cc=spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    --cc=thomas.langer-th3ZBGNqt+7QT0dZR+AlfA@public.gmane.org \
    --cc=tpiepho-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.