SPI: support DUAL and QUAD[patch v1]

yuhang wang wangyuhang2014 at gmail.com
Wed Jul 10 04:34:24 EDT 2013


Hi,

The patch below is to make spi framework support dual(2x) and quad(4x).
Bus the name of members may still look strange, so I need some suggestions.
Thanks.

>From f33f5935776aa0b44b01a36f88e47ba0cfe8fd21 Mon Sep 17 00:00:00 2001
From: wangyuhang <wangyuhang2014 at gmail.com>
Date: Wed, 10 Jul 2013 16:22:19 +0800
Subject: [PATCH] spi final patch v2 Signed-off-by: wangyuhang
 <wangyuhang2014 at gmail.com>

Signed-off-by: wangyuhang <wangyuhang2014 at gmail.com>
---
 drivers/spi/spi.c       |    6 ++++++
 include/linux/spi/spi.h |   31 +++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 004b10f..af28a62 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -452,6 +452,8 @@ struct spi_device *spi_new_device(struct spi_master *master,
  proxy->irq = chip->irq;
  strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
  proxy->dev.platform_data = (void *) chip->platform_data;
+ proxy->tx_nbits = chip->tx_nbits ? chip->tx_nbits : SPI_NBITS_SINGLE;
+ proxy->rx_nbits = chip->rx_nbits ? chip->rx_nbits : SPI_NBITS_SINGLE;
  proxy->controller_data = chip->controller_data;
  proxy->controller_state = NULL;

@@ -1376,6 +1378,10 @@ static int __spi_async(struct spi_device *spi,
struct spi_message *message)
  xfer->bits_per_word = spi->bits_per_word;
  if (!xfer->speed_hz)
  xfer->speed_hz = spi->max_speed_hz;
+ if (!xfer->tx_nbits)
+ xfer->tx_nbits = SPI_NBITS_SINGLE;
+ if (!xfer->rx_nbits)
+ xfer->rx_nbits = SPI_NBITS_SINGLE;
  }

  message->spi = spi;
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 38c2b92..d9b3746 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -59,6 +59,10 @@ extern struct bus_type spi_bus_type;
  * for driver coldplugging, and in uevents used for hotplugging
  * @cs_gpio: gpio number of the chipselect line (optional, -EINVAL when
  * when not using a GPIO line)
+ * @tx_nbits: number of bits used in tx, get from @spi_board_info
+ * (optional, 1bit as init value if not set in @spi_board_info)
+ * @rx_nbits: number of bits used in rx, get from @spi_board_info
+ * (optional, 1bit as init value if not set in @spi_board_info)
  *
  * A @spi_device is used to interchange data between an SPI slave
  * (usually a discrete chip) and CPU memory.
@@ -93,6 +97,8 @@ struct spi_device {
  void *controller_data;
  char modalias[SPI_NAME_SIZE];
  int cs_gpio; /* chip select gpio */
+ u8 tx_nbits; /* num of bits used in tx */
+ u8 rx_nbits; /* num of bits used in rx */

  /*
  * likely need more hooks for more protocol options affecting how
@@ -437,6 +443,10 @@ 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, if 0 default
+ * (SPI_NBITS_SINGLE = 0x01) is used.
+ * @rx_nbits: number of bits used for reading, if 0 default
+ * (SPI_NBITS_SINGLE = 0x01) is used.
  * @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 +501,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
@@ -510,6 +525,12 @@ struct spi_transfer {
  dma_addr_t tx_dma;
  dma_addr_t rx_dma;

+ u8 tx_nbits;
+ u8 rx_nbits;
+#define SPI_NBITS_SINGLE 0x01; /* 1bit transfer */
+#define SPI_NBITS_DUAL 0x02; /* 2bits transfer */
+#define SPI_NBITS_QUAD 0x03; /* 4bits transfer */
+
  unsigned cs_change:1;
  u8 bits_per_word;
  u16 delay_usecs;
@@ -815,6 +836,10 @@ static inline ssize_t spi_w8r16(struct spi_device
*spi, u8 cmd)
  * @mode: Initializes spi_device.mode; based on the chip datasheet, board
  * wiring (some devices support both 3WIRE and standard modes), and
  * possibly presence of an inverter in the chipselect path.
+ * @tx_nbits: Initializes spi_device.tx_nbits; depends on the number of bits
+ * the board used in tx.
+ * @rx_nbits: Initializes spi_device.rx_nbits; depends on the number of bits
+ * the board used in rx.
  *
  * When adding new SPI devices to the device tree, these structures serve
  * as a partial device template.  They hold information which can't always
@@ -859,6 +884,12 @@ struct spi_board_info {
  * where the default of SPI_CS_HIGH = 0 is wrong.
  */
  u8 mode;
+ /* tx_nbits initialized for spi_device.tx_nbits and
+ * rx_nbits initialized for spi_device.rx_nbits. These members
+ * used to describe the how many lines used in tx and rx.
+ */
+ u8 tx_nbits;
+ u8 rx_nbits;

  /* ... may need additional spi_device chip config data here.
  * avoid stuff protocol drivers can set; but include stuff
--
1.7.9.5

Best Regards.



More information about the linux-mtd mailing list