Greg,

Here's a patch^h^h^h^h^htxt which allows the use of a generic spi interface for controlling an LCD display.  It has been tested with the ili9341 but should work with others without too much pain...hopefully this will be useful to Ben, who I know has been looking for such a thing.

To use it;

1) include nuttx/lcd/lcddrv_spiif.h

2) Create an spi device;

struct spi_dev_s *g_bound_spi  = imxrt_spi_register(2);

3) Instantiate the interface;

struct lcddrv_lcd_s *dev = lcddrv_spiif_initialize( g_bound_spi );

4) Bind the interface to the lcd;

g_lcd = ili9341_initialize((struct ili9341_lcd_s *)dev, CONFIG_IMXRT_VB_ILI9341_LCDDEVICE);

You should then be able to use the lcd as normal. Comments and brickbats welcome.

Regards

DAVE


diff --git a/arch/arm/src/imxrt/imxrt_lpspi.c b/arch/arm/src/imxrt/imxrt_lpspi.c
index b33cee894f..8c8838662a 100644
--- a/arch/arm/src/imxrt/imxrt_lpspi.c
+++ b/arch/arm/src/imxrt/imxrt_lpspi.c
@@ -1,4 +1,4 @@
-/************************************************************************************
+/*****************************************************************************
  * arm/arm/src/imxrt/imxrt_lpspi.c
  *
  *   Copyright (C) 2018 Gregory Nutt. All rights reserved.
@@ -32,34 +32,35 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
-/************************************************************************************
- * The external functions, imxrt_lpspi1/2/3/4select and 
imxrt_lpspi1/2/3/4status
- * must be provided by board-specific logic.  They are implementations of the 
select
- * and status methods of the SPI interface defined by struct imxrt_lpspi_ops_s 
(see
- * include/nuttx/spi/spi.h). All other methods (including 
imxrt_lpspibus_initialize())
- * are provided by common IMXRT logic.  To use this common SPI logic on your
- * board:
+/*****************************************************************************
+ * The external functions, imxrt_lpspi1/2/3/4select and
+ * imxrt_lpspi1/2/3/4status must be provided by board-specific logic.
+ * They are implementations of the select and status methods of the SPI
+ * interface defined by struct imxrt_lpspi_ops_s (see
+ * include/nuttx/spi/spi.h). All other methods (including
+ * imxrt_lpspibus_initialize()) are provided by common IMXRT logic.
+ * To use this common SPI logic on your board:
  *
  *   1. Provide logic in imxrt_boardinitialize() to configure SPI chip select
  *      pins.
  *   2. Provide imxrt_lpspi1/2/3/4select() and imxrt_lpspi1/2/3/4status()
- *      functions in your board-specific logic.  These functions will perform 
chip
- *      selection and status operations using GPIOs in the way your board is
- *      configured.
- *   3. Add a calls to imxrt_lpspibus_initialize() in your low level 
application
- *      initialization logic
- *   4. The handle returned by imxrt_lpspibus_initialize() may then be used to 
bind the
- *      SPI driver to higher level logic (e.g., calling
+ *      functions in your board-specific logic.  These functions will perform
+ *      chip selection and status operations using GPIOs in the way your board
+ *      is configured.
+ *   3. Add a calls to imxrt_lpspibus_initialize() in your low level
+ *      application initialization logic
+ *   4. The handle returned by imxrt_lpspibus_initialize() may then be used to
+ *      bind the SPI driver to higher level logic (e.g., calling
  *      mmcsd_lpspislotinitialize(), for example, will bind the SPI driver to
  *      the SPI MMC/SD driver).
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
-/************************************************************************************
+/*****************************************************************************
  * Included Files
- 
************************************************************************************/
+ *****************************************************************************/
 
 #include <nuttx/config.h>
 
@@ -94,11 +95,11 @@
 #if defined(CONFIG_IMXRT_LPSPI1) || defined(CONFIG_IMXRT_LPSPI2) || \
     defined(CONFIG_IMXRT_LPSPI3) || defined(CONFIG_IMXRT_LPSPI4)
 
-/************************************************************************************
+/*****************************************************************************
  * Pre-processor Definitions
- 
************************************************************************************/
+ ****************************************************************************/
 
-/* Configuration 
********************************************************************/
+/* Configuration ************************************************************/
 
 /* SPI interrupts */
 
@@ -116,9 +117,9 @@
 #  error "Cannot enable both interrupt mode and DMA mode for SPI"
 #endif
 
-/************************************************************************************
+/*****************************************************************************
  * Private Types
- 
************************************************************************************/
+ ****************************************************************************/
 
 struct imxrt_lpspidev_s
 {
@@ -141,9 +142,9 @@ enum imxrt_delay_e
   LPSPI_BETWEEN_TRANSFER      /* Delay between transfers. */
 };
 
-/************************************************************************************
+/*****************************************************************************
  * Private Function Prototypes
- 
************************************************************************************/
+ ****************************************************************************/
 
 /* Helpers */
 
@@ -151,17 +152,19 @@ static inline uint32_t imxrt_lpspi_getreg32(FAR struct 
imxrt_lpspidev_s *priv,
                                             uint8_t offset);
 static inline void imxrt_lpspi_putreg32(FAR struct imxrt_lpspidev_s *priv,
                                         uint8_t offset, uint32_t value);
-static inline uint16_t imxrt_lpspi_readword(FAR struct imxrt_lpspidev_s *priv);
+static inline uint16_t imxrt_lpspi_readword(
+                          FAR struct imxrt_lpspidev_s *priv);
 static inline void imxrt_lpspi_writeword(FAR struct imxrt_lpspidev_s *priv,
                                          uint16_t byte);
-static inline bool imxrt_lpspi_9to16bitmode(FAR struct imxrt_lpspidev_s *priv);
+static inline bool imxrt_lpspi_9to16bitmode(
+                          FAR struct imxrt_lpspidev_s *priv);
 static inline void imxrt_lpspi_master_set_delays(FAR struct imxrt_lpspidev_s
                                                  *priv, uint32_t delay_ns,
                                                  enum imxrt_delay_e type);
-static inline void imxrt_lpspi_master_set_delay_scaler(FAR struct
-                                                       imxrt_lpspidev_s *priv,
-                                                       uint32_t scaler,
-                                                       enum imxrt_delay_e 
type);
+static inline void imxrt_lpspi_master_set_delay_scaler(
+                          FAR struct imxrt_lpspidev_s *priv,
+                          uint32_t scaler,
+                          enum imxrt_delay_e type);
 
 /* SPI methods */
 
@@ -182,7 +185,8 @@ static void imxrt_lpspi_exchange(FAR struct spi_dev_s *dev,
 #ifndef CONFIG_SPI_EXCHANGE
 static void imxrt_lpspi_sndblock(FAR struct spi_dev_s *dev,
                                  FAR const void *txbuffer, size_t nwords);
-static void imxrt_lpspi_recvblock(FAR struct spi_dev_s *dev, FAR void 
*rxbuffer,
+static void imxrt_lpspi_recvblock(FAR struct spi_dev_s *dev,
+                                  FAR void *rxbuffer,
                                   size_t nwords);
 #endif
 
@@ -190,9 +194,9 @@ static void imxrt_lpspi_recvblock(FAR struct spi_dev_s 
*dev, FAR void *rxbuffer,
 
 static void imxrt_lpspi_bus_initialize(FAR struct imxrt_lpspidev_s *priv);
 
-/************************************************************************************
+/*****************************************************************************
  * Private Data
- 
************************************************************************************/
+ *****************************************************************************/
 
 #ifdef CONFIG_IMXRT_LPSPI1
 static const struct spi_ops_s g_spi1ops =
@@ -378,11 +382,11 @@ static struct imxrt_lpspidev_s g_lpspi4dev =
 };
 #endif
 
-/************************************************************************************
+/*****************************************************************************
  * Private Functions
- 
************************************************************************************/
+ *****************************************************************************/
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_getreg8
  *
  * Description:
@@ -395,7 +399,7 @@ static struct imxrt_lpspidev_s g_lpspi4dev =
  * Returned Value:
  *   The contents of the 8-bit register
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static inline uint8_t imxrt_lpspi_getreg8(FAR struct imxrt_lpspidev_s *priv,
                                           uint8_t offset)
@@ -403,7 +407,7 @@ static inline uint8_t imxrt_lpspi_getreg8(FAR struct 
imxrt_lpspidev_s *priv,
   return getreg8(priv->spibase + offset);
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_putreg8
  *
  * Description:
@@ -414,7 +418,7 @@ static inline uint8_t imxrt_lpspi_getreg8(FAR struct 
imxrt_lpspidev_s *priv,
  *   offset - offset to the register of interest
  *   value  - the 8-bit value to be written
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static inline void imxrt_lpspi_putreg8(FAR struct imxrt_lpspidev_s *priv,
                                        uint8_t offset, uint8_t value)
@@ -422,7 +426,7 @@ static inline void imxrt_lpspi_putreg8(FAR struct 
imxrt_lpspidev_s *priv,
   putreg8(value, priv->spibase + offset);
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_getreg
  *
  * Description:
@@ -435,7 +439,7 @@ static inline void imxrt_lpspi_putreg8(FAR struct 
imxrt_lpspidev_s *priv,
  * Returned Value:
  *   The contents of the 32-bit register
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static inline uint32_t imxrt_lpspi_getreg32(FAR struct imxrt_lpspidev_s *priv,
                                             uint8_t offset)
@@ -443,7 +447,7 @@ static inline uint32_t imxrt_lpspi_getreg32(FAR struct 
imxrt_lpspidev_s *priv,
   return getreg32(priv->spibase + offset);
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_putreg
  *
  * Description:
@@ -457,7 +461,7 @@ static inline uint32_t imxrt_lpspi_getreg32(FAR struct 
imxrt_lpspidev_s *priv,
  * Returned Value:
  *   The contents of the 32-bit register
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static inline void imxrt_lpspi_putreg32(FAR struct imxrt_lpspidev_s *priv,
                                         uint8_t offset, uint32_t value)
@@ -465,7 +469,7 @@ static inline void imxrt_lpspi_putreg32(FAR struct 
imxrt_lpspidev_s *priv,
   putreg32(value, priv->spibase + offset);
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_readword
  *
  * Description:
@@ -477,20 +481,21 @@ static inline void imxrt_lpspi_putreg32(FAR struct 
imxrt_lpspidev_s *priv,
  * Returned Value:
  *   word as read
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static inline uint16_t imxrt_lpspi_readword(FAR struct imxrt_lpspidev_s *priv)
 {
   /* Wait until the receive buffer is not empty */
 
-  while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET) & LPSPI_SR_RDF) == 
0);
+  while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET)
+                      & LPSPI_SR_RDF) == 0);
 
   /* Then return the received byte */
 
   return (uint16_t) imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_RDR_OFFSET);
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_writeword
  *
  * Description:
@@ -503,21 +508,22 @@ static inline uint16_t imxrt_lpspi_readword(FAR struct 
imxrt_lpspidev_s *priv)
  * Returned Value:
  *   None
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static inline void imxrt_lpspi_writeword(FAR struct imxrt_lpspidev_s *priv,
                                          uint16_t word)
 {
   /* Wait until the transmit buffer is empty */
 
-  while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET) & LPSPI_SR_TDF) == 
0);
+  while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET)
+                       & LPSPI_SR_TDF) == 0);
 
   /* Then send the word */
 
   imxrt_lpspi_putreg32(priv, IMXRT_LPSPI_TDR_OFFSET, word);
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_readbyte
  *
  * Description:
@@ -529,20 +535,21 @@ static inline void imxrt_lpspi_writeword(FAR struct 
imxrt_lpspidev_s *priv,
  * Returned Value:
  *   Byte as read
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static inline uint8_t imxrt_lpspi_readbyte(FAR struct imxrt_lpspidev_s *priv)
 {
   /* Wait until the receive buffer is not empty */
 
-  while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET) & LPSPI_SR_RDF) == 
0);
+  while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET)
+                       & LPSPI_SR_RDF) == 0);
 
   /* Then return the received byte */
 
   return imxrt_lpspi_getreg8(priv, IMXRT_LPSPI_RDR_OFFSET);
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_writebyte
  *
  * Description:
@@ -555,21 +562,22 @@ static inline uint8_t imxrt_lpspi_readbyte(FAR struct 
imxrt_lpspidev_s *priv)
  * Returned Value:
  *   None
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static inline void imxrt_lpspi_writebyte(FAR struct imxrt_lpspidev_s *priv,
                                          uint8_t byte)
 {
   /* Wait until the transmit buffer is empty */
 
-  while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET) & LPSPI_SR_TDF) == 
0);
+  while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET)
+                           & LPSPI_SR_TDF) == 0);
 
   /* Then send the byte */
 
   imxrt_lpspi_putreg8(priv, IMXRT_LPSPI_TDR_OFFSET, byte);
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_9to16bitmode
  *
  * Description:
@@ -581,7 +589,7 @@ static inline void imxrt_lpspi_writebyte(FAR struct 
imxrt_lpspidev_s *priv,
  * Returned Value:
  *   true: >8 bit mode-bit mode, false: <= 8-bit mode
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static inline bool imxrt_lpspi_9to16bitmode(FAR struct imxrt_lpspidev_s *priv)
 {
@@ -600,7 +608,7 @@ static inline bool imxrt_lpspi_9to16bitmode(FAR struct 
imxrt_lpspidev_s *priv)
   return ret;
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_modifyreg
  *
  * Description:
@@ -615,7 +623,7 @@ static inline bool imxrt_lpspi_9to16bitmode(FAR struct 
imxrt_lpspidev_s *priv)
  * Returned Value:
  *   None
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static void imxrt_lpspi_modifyreg32(FAR struct imxrt_lpspidev_s *priv,
                                     uint8_t offset, uint32_t clrbits,
@@ -624,7 +632,7 @@ static void imxrt_lpspi_modifyreg32(FAR struct 
imxrt_lpspidev_s *priv,
   modifyreg32(priv->spibase + offset, clrbits, setbits);
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_master_set_delays
  *
  * Description:
@@ -638,11 +646,12 @@ static void imxrt_lpspi_modifyreg32(FAR struct 
imxrt_lpspidev_s *priv,
  * Returned Value:
  *   None
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
-static inline void imxrt_lpspi_master_set_delay_scaler(FAR struct 
imxrt_lpspidev_s *priv,
-                                                       uint32_t scaler,
-                                                       enum imxrt_delay_e type)
+static inline void imxrt_lpspi_master_set_delay_scaler(
+                          FAR struct imxrt_lpspidev_s *priv,
+                          uint32_t scaler,
+                          enum imxrt_delay_e type)
 {
   switch (type)
     {
@@ -661,15 +670,15 @@ static inline void 
imxrt_lpspi_master_set_delay_scaler(FAR struct imxrt_lpspidev
       break;
 
     case LPSPI_BETWEEN_TRANSFER:
-      imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CCR_OFFSET, LPSPI_CCR_DBT_MASK,
-                              0);
+      imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CCR_OFFSET,
+                                    LPSPI_CCR_DBT_MASK, 0);
       imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CCR_OFFSET, 0,
                               LPSPI_CCR_DBT(scaler));
       break;
     }
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_master_set_delays
  *
  * Description:
@@ -683,10 +692,12 @@ static inline void 
imxrt_lpspi_master_set_delay_scaler(FAR struct imxrt_lpspidev
  * Returned Value:
  *   None
  *
- 
************************************************************************************/
-static inline void imxrt_lpspi_master_set_delays(FAR struct imxrt_lpspidev_s 
*priv,
-                                                 uint32_t delay_ns,
-                                                 enum imxrt_delay_e type)
+ *****************************************************************************/
+
+static inline void imxrt_lpspi_master_set_delays(
+                             FAR struct imxrt_lpspidev_s *priv,
+                             uint32_t delay_ns,
+                             enum imxrt_delay_e type)
 {
   uint32_t pll3_div;
   uint32_t pll_freq;
@@ -719,8 +730,9 @@ static inline void imxrt_lpspi_master_set_delays(FAR struct 
imxrt_lpspidev_s *pr
    */
 
   src_freq  = pll_freq /
-              ((getreg32(IMXRT_CCM_ANALOG_PFD_480) & 
CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >>
-              CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT);
+              ((getreg32(IMXRT_CCM_ANALOG_PFD_480)
+                         & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >>
+                         CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT);
   src_freq *= 18;
   src_freq /= ((getreg32(IMXRT_CCM_CBCMR) & CCM_CBCMR_LPSPI_PODF_MASK) >>
                CCM_CBCMR_LPSPI_PODF_SHIFT) + 1;
@@ -797,9 +809,9 @@ static inline void imxrt_lpspi_master_set_delays(FAR struct 
imxrt_lpspidev_s *pr
       for (scaler = 0; (scaler < 256) && min_diff; scaler++)
         {
           /* Calculate the real delay value as we cycle through the scaler
-           * values. Due to large size of calculated values (uint64_t), we need
-           * to break up the calculation into several steps to ensure accurate
-           * calculated results
+           * values. Due to large size of calculated values (uint64_t),
+           * we need to break up the calculation into several steps to
+           * ensure accurate calculated results
            */
 
           real_delay  = 1000000000U;
@@ -829,7 +841,7 @@ static inline void imxrt_lpspi_master_set_delays(FAR struct 
imxrt_lpspidev_s *pr
     }
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_lock
  *
  * Description:
@@ -848,7 +860,7 @@ static inline void imxrt_lpspi_master_set_delays(FAR struct 
imxrt_lpspidev_s *pr
  * Returned Value:
  *   None
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static int imxrt_lpspi_lock(FAR struct spi_dev_s *dev, bool lock)
 {
@@ -867,7 +879,7 @@ static int imxrt_lpspi_lock(FAR struct spi_dev_s *dev, bool 
lock)
   return ret;
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_setfrequency
  *
  * Description:
@@ -880,7 +892,7 @@ static int imxrt_lpspi_lock(FAR struct spi_dev_s *dev, bool 
lock)
  * Returned Value:
  *   Returns the actual frequency selected
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static uint32_t imxrt_lpspi_setfrequency(FAR struct spi_dev_s *dev,
                                          uint32_t frequency)
@@ -909,7 +921,8 @@ static uint32_t imxrt_lpspi_setfrequency(FAR struct 
spi_dev_s *dev,
       men = imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN;
       if (men)
         {
-          imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, LPSPI_CR_MEN, 
0);
+          imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET,
+                                        LPSPI_CR_MEN, 0);
         }
 
       if ((getreg32(IMXRT_CCM_ANALOG_PLL_USB1) &
@@ -930,8 +943,9 @@ static uint32_t imxrt_lpspi_setfrequency(FAR struct 
spi_dev_s *dev,
        */
 
       src_freq  = pll_freq /
-                  ((getreg32(IMXRT_CCM_ANALOG_PFD_480) & 
CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >>
-                  CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT);
+                  ((getreg32(IMXRT_CCM_ANALOG_PFD_480)
+                    & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >>
+                      CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT);
       src_freq *= 18;
       src_freq /= ((getreg32(IMXRT_CCM_CBCMR) & CCM_CBCMR_LPSPI_PODF_MASK) >>
                    CCM_CBCMR_LPSPI_PODF_SHIFT) + 1;
@@ -994,14 +1008,15 @@ static uint32_t imxrt_lpspi_setfrequency(FAR struct 
spi_dev_s *dev,
 
       if (men)
         {
-          imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0, 
LPSPI_CR_MEN);
+          imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0,
+                                        LPSPI_CR_MEN);
         }
     }
 
   return priv->actual;
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_setmode
  *
  * Description:
@@ -1014,9 +1029,10 @@ static uint32_t imxrt_lpspi_setfrequency(FAR struct 
spi_dev_s *dev,
  * Returned Value:
  *   Returns the actual frequency selected
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
-static void imxrt_lpspi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e 
mode)
+static void imxrt_lpspi_setmode(FAR struct spi_dev_s *dev,
+                                enum spi_mode_e mode)
 {
   FAR struct imxrt_lpspidev_s *priv = (FAR struct imxrt_lpspidev_s *)dev;
   uint32_t setbits;
@@ -1034,7 +1050,8 @@ static void imxrt_lpspi_setmode(FAR struct spi_dev_s 
*dev, enum spi_mode_e mode)
       men = imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN;
       if (men)
         {
-          imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, LPSPI_CR_MEN, 
0);
+          imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET,
+                                        LPSPI_CR_MEN, 0);
         }
 
       switch (mode)
@@ -1081,12 +1098,13 @@ static void imxrt_lpspi_setmode(FAR struct spi_dev_s 
*dev, enum spi_mode_e mode)
 
       if (men)
         {
-          imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0, 
LPSPI_CR_MEN);
+          imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0,
+                                        LPSPI_CR_MEN);
         }
     }
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_setbits
  *
  * Description:
@@ -1099,7 +1117,7 @@ static void imxrt_lpspi_setmode(FAR struct spi_dev_s 
*dev, enum spi_mode_e mode)
  * Returned Value:
  *   None
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static void imxrt_lpspi_setbits(FAR struct spi_dev_s *dev, int nbits)
 {
@@ -1113,7 +1131,6 @@ static void imxrt_lpspi_setbits(FAR struct spi_dev_s 
*dev, int nbits)
 
   if (nbits != priv->nbits)
     {
-
       if (nbits < 2 || nbits > 4096)
         {
           return;
@@ -1124,14 +1141,17 @@ static void imxrt_lpspi_setbits(FAR struct spi_dev_s 
*dev, int nbits)
       men = imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN;
       if (men)
         {
-          imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, LPSPI_CR_MEN, 
0);
+          imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET,
+                                        LPSPI_CR_MEN, 0);
         }
 
       imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_TCR_OFFSET,
                               LPSPI_TCR_FRAMESZ_MASK,
                               LPSPI_TCR_FRAMESZ(nbits - 1));
 
-      /* Save the selection so the subsequence re-configurations will be 
faster */
+      /* Save the selection so the subsequence re-configurations
+       * will be faster
+       */
 
       priv->nbits = savbits;    /* nbits has been clobbered... save the signed
                                  * value. */
@@ -1140,12 +1160,13 @@ static void imxrt_lpspi_setbits(FAR struct spi_dev_s 
*dev, int nbits)
 
       if (men)
         {
-          imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0, 
LPSPI_CR_MEN);
+          imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0,
+                                        LPSPI_CR_MEN);
         }
     }
 }
 
-/****************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_hwfeatures
  *
  * Description:
@@ -1197,7 +1218,7 @@ static int imxrt_lpspi_hwfeatures(FAR struct spi_dev_s 
*dev,
 }
 #endif
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_send
  *
  * Description:
@@ -1211,7 +1232,7 @@ static int imxrt_lpspi_hwfeatures(FAR struct spi_dev_s 
*dev,
  * Returned Value:
  *   response
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static uint16_t imxrt_lpspi_send(FAR struct spi_dev_s *dev, uint16_t wd)
 {
@@ -1240,7 +1261,7 @@ static uint16_t imxrt_lpspi_send(FAR struct spi_dev_s 
*dev, uint16_t wd)
   return ret;
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_exchange (no DMA).  aka imxrt_lpspi_exchange_nodma
  *
  * Description:
@@ -1253,12 +1274,13 @@ static uint16_t imxrt_lpspi_send(FAR struct spi_dev_s 
*dev, uint16_t wd)
  *   nwords   - the length of data to be exchaned in units of words.
  *              The wordsize is determined by the number of bits-per-word
  *              selected for the SPI interface.  If nbits <= 8, the data is
- *              packed into uint8_t's; if nbits >8, the data is packed into 
uint16_t's
+ *              packed into uint8_t's; if nbits >8, the data is packed
+ *              into uint16_t's
  *
  * Returned Value:
  *   None
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 #if !defined(CONFIG_IMXRT_LPSPI_DMA) || defined(CONFIG_IMXRT_DMACAPABLE)
 #if !defined(CONFIG_IMXRT_LPSPI_DMA)
@@ -1359,12 +1381,13 @@ static void imxrt_lpspi_exchange_nodma(FAR struct 
spi_dev_s *dev,
  *   nwords   - the length of data to send from the buffer in number of words.
  *              The wordsize is determined by the number of bits-per-word
  *              selected for the SPI interface.  If nbits <= 8, the data is
- *              packed into uint8_t's; if nbits >8, the data is packed into 
uint16_t's
+ *              packed into uint8_t's; if nbits >8, the data is packed into
+ *              uint16_t's
  *
  * Returned Value:
  *   None
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 #ifndef CONFIG_SPI_EXCHANGE
 static void imxrt_lpspi_sndblock(FAR struct spi_dev_s *dev,
@@ -1375,7 +1398,7 @@ static void imxrt_lpspi_sndblock(FAR struct spi_dev_s 
*dev,
 }
 #endif
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_recvblock
  *
  * Description:
@@ -1384,32 +1407,33 @@ static void imxrt_lpspi_sndblock(FAR struct spi_dev_s 
*dev,
  * Input Parameters:
  *   dev      - Device-specific state data
  *   rxbuffer - A pointer to the buffer in which to receive data
- *   nwords   - the length of data that can be received in the buffer in number
- *              of words.  The wordsize is determined by the number of 
bits-per-word
- *              selected for the SPI interface.  If nbits <= 8, the data is
- *              packed into uint8_t's; if nbits >8, the data is packed into 
uint16_t's
+ *   nwords   - the length of data that can be received in the buffer in
+ *              number of words.  The wordsize is determined by the number of
+ *              bits-per-word selected for the SPI interface.  If
+ *              nbits <= 8, the data is packed into uint8_t's;
+ *              if nbits >8, the data is packed into uint16_t's
  *
  * Returned Value:
  *   None
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 #ifndef CONFIG_SPI_EXCHANGE
-static void imxrt_lpspi_recvblock(FAR struct spi_dev_s *dev, FAR void 
*rxbuffer,
-                                  size_t nwords)
+static void imxrt_lpspi_recvblock(FAR struct spi_dev_s *dev,
+                                  FAR void *rxbuffer, size_t nwords)
 {
   spiinfo("rxbuffer=%p nwords=%d\n", rxbuffer, nwords);
   return imxrt_lpspi_exchange(dev, NULL, rxbuffer, nwords);
 }
 #endif
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_clock_enable
  *
  * Description:
  *   Ungate LPSPI clock
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 void imxrt_lpspi_clock_enable(uint32_t base)
 {
@@ -1431,13 +1455,13 @@ void imxrt_lpspi_clock_enable(uint32_t base)
     }
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_clock_disable
  *
  * Description:
  *   Gate LPSPI clock
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 void imxrt_lpspi_clock_disable(uint32_t base)
 {
@@ -1459,11 +1483,12 @@ void imxrt_lpspi_clock_disable(uint32_t base)
     }
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspi_bus_initialize
  *
  * Description:
- *   Initialize the selected SPI bus in its default state (Master, 8-bit, mode 
0, etc.)
+ *   Initialize the selected SPI bus in its default state
+ *   (Master, 8-bit, mode 0, etc.)
  *
  * Input Parameters:
  *   priv   - private SPI device structure
@@ -1471,7 +1496,7 @@ void imxrt_lpspi_clock_disable(uint32_t base)
  * Returned Value:
  *   None
  *
- 
************************************************************************************/
+ *****************************************************************************/
 
 static void imxrt_lpspi_bus_initialize(struct imxrt_lpspidev_s *priv)
 {
@@ -1493,13 +1518,15 @@ static void imxrt_lpspi_bus_initialize(struct 
imxrt_lpspidev_s *priv)
   imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CFGR1_OFFSET, 0,
                           LPSPI_CFGR1_MASTER);
 
-  /* Set specific PCS to active high or low */
-  /* TODO: Not needed for now */
+  /* Set specific PCS to active high or low
+   * TODO: Not needed for now
+   */
 
   /* Set Configuration Register 1 related setting. */
 
   reg = imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CFGR1_OFFSET);
-  reg &= ~(LPSPI_CFGR1_OUTCFG | LPSPI_CFGR1_PINCFG_MASK | LPSPI_CFGR1_NOSTALL);
+  reg &= ~(LPSPI_CFGR1_OUTCFG | LPSPI_CFGR1_PINCFG_MASK
+           | LPSPI_CFGR1_NOSTALL);
   reg |= LPSPI_CFGR1_OUTCFG_RETAIN | LPSPI_CFGR1_PINCFG_SIN_SOUT;
   imxrt_lpspi_putreg32(priv, IMXRT_LPSPI_CFGR1_OFFSET, reg);
 
@@ -1527,11 +1554,11 @@ static void imxrt_lpspi_bus_initialize(struct 
imxrt_lpspidev_s *priv)
   imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0, LPSPI_CR_MEN);
 }
 
-/************************************************************************************
+/*****************************************************************************
  * Public Functions
- 
************************************************************************************/
+ *****************************************************************************/
 
-/************************************************************************************
+/*****************************************************************************
  * Name: imxrt_lpspibus_initialize
  *
  * Description:
@@ -1543,7 +1570,7 @@ static void imxrt_lpspi_bus_initialize(struct 
imxrt_lpspidev_s *priv)
  * Returned Value:
  *   Valid SPI device structure reference on success; a NULL on failure
  *
- 
************************************************************************************/
+ ****************************************************************************/
 
 FAR struct spi_dev_s *imxrt_lpspibus_initialize(int bus)
 {
@@ -1560,13 +1587,20 @@ FAR struct spi_dev_s *imxrt_lpspibus_initialize(int bus)
 
       /* Only configure if the bus is not already configured */
 
-      if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN) 
== 0)
+      if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET)
+           & LPSPI_CR_MEN) == 0)
         {
           /* Configure SPI1 pins: SCK, MISO, and MOSI */
 
           imxrt_config_gpio(GPIO_LPSPI1_SCK);
           imxrt_config_gpio(GPIO_LPSPI1_MISO);
           imxrt_config_gpio(GPIO_LPSPI1_MOSI);
+#ifdef GPIO_LPSPI1_CS
+          imxrt_config_gpio(GPIO_LPSPI1_CS);
+#endif
+#if defined(GPIO_LPSPI1_DC) && defined(CONFIG_SPI_CMDDATA)
+          imxrt_config_gpio(GPIO_LPSPI1_DC);
+#endif
 
           /* Set up default configuration: Master, 8-bit, etc. */
 
@@ -1584,13 +1618,20 @@ FAR struct spi_dev_s *imxrt_lpspibus_initialize(int bus)
 
       /* Only configure if the bus is not already configured */
 
-      if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN) 
== 0)
+      if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET)
+           & LPSPI_CR_MEN) == 0)
         {
           /* Configure SPI2 pins: SCK, MISO, and MOSI */
 
           imxrt_config_gpio(GPIO_LPSPI2_SCK);
           imxrt_config_gpio(GPIO_LPSPI2_MISO);
           imxrt_config_gpio(GPIO_LPSPI2_MOSI);
+#ifdef GPIO_LPSPI2_CS
+          imxrt_config_gpio(GPIO_LPSPI2_CS);
+#endif
+#if defined(GPIO_LPSPI2_DC) && defined(CONFIG_SPI_CMDDATA)
+          imxrt_config_gpio(GPIO_LPSPI2_DC);
+#endif
 
           /* Set up default configuration: Master, 8-bit, etc. */
 
@@ -1608,13 +1649,20 @@ FAR struct spi_dev_s *imxrt_lpspibus_initialize(int bus)
 
       /* Only configure if the bus is not already configured */
 
-      if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN) 
== 0)
+      if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET)
+           & LPSPI_CR_MEN) == 0)
         {
           /* Configure SPI3 pins: SCK, MISO, and MOSI */
 
           imxrt_config_gpio(GPIO_LPSPI3_SCK);
           imxrt_config_gpio(GPIO_LPSPI3_MISO);
           imxrt_config_gpio(GPIO_LPSPI3_MOSI);
+#ifdef GPIO_LPSPI3_CS
+          imxrt_config_gpio(GPIO_LPSPI3_CS);
+#endif
+#if defined(GPIO_LPSPI3_DC) && defined(CONFIG_SPI_CMDDATA)
+          imxrt_config_gpio(GPIO_LPSPI3_DC);
+#endif
 
           /* Set up default configuration: Master, 8-bit, etc. */
 
@@ -1632,13 +1680,20 @@ FAR struct spi_dev_s *imxrt_lpspibus_initialize(int bus)
 
       /* Only configure if the bus is not already configured */
 
-      if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET) & LPSPI_CR_MEN) 
== 0)
+      if ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CR_OFFSET)
+           & LPSPI_CR_MEN) == 0)
         {
           /* Configure SPI4 pins: SCK, MISO, and MOSI */
 
           imxrt_config_gpio(GPIO_LPSPI4_SCK);
           imxrt_config_gpio(GPIO_LPSPI4_MISO);
           imxrt_config_gpio(GPIO_LPSPI4_MOSI);
+#ifdef GPIO_LPSPI4_CS
+          imxrt_config_gpio(GPIO_LPSPI4_CS);
+#endif
+#if defined(GPIO_LPSPI4_DC) && defined(CONFIG_SPI_CMDDATA)
+          imxrt_config_gpio(GPIO_LPSPI4_DC);
+#endif
 
           /* Set up default configuration: Master, 8-bit, etc. */
 
diff --git a/drivers/lcd/Kconfig b/drivers/lcd/Kconfig
index 9bc3ac284b..88a9f5a4d5 100644
--- a/drivers/lcd/Kconfig
+++ b/drivers/lcd/Kconfig
@@ -1134,6 +1134,23 @@ config LCD_ILI9341_IFACE1_RGB565
 endchoice
 endif
 
+config LCD_LCDDRV_SPIIF
+       bool "Generic SPI Interface Driver (for ILI9341 or others)"
+       default n
+       depends on LCD_ILI9341
+       ---help---
+               SPI Interface shim to allow LCD and ePaper to be bound to
+               a normal SPI port.
+
+config LCD_LCDDRV_SPEED
+        int "Generic SPI Interface speed"
+       default 10000000
+       depends on LCD_LCDDRV_SPIIF
+       ---help---
+               SPI Interface speed. According to the specification this is 
generally
+               quite limited, but people have had success with much faster
+               speeds than the spec sheets say. YMMV.
+
 config LCD_RA8875
        bool "RA8875 LCD Display Controller"
        default n
diff --git a/drivers/lcd/Make.defs b/drivers/lcd/Make.defs
index bfc50baed8..b40aca2b33 100644
--- a/drivers/lcd/Make.defs
+++ b/drivers/lcd/Make.defs
@@ -124,6 +124,10 @@ ifeq ($(CONFIG_LCD_ILI9341),y)
   CSRCS += ili9341.c
 endif
 
+ifeq ($(CONFIG_LCD_LCDDRV_SPIIF),y)
+  CSRCS += lcddrv_spiif.c
+endif
+
 ifeq ($(CONFIG_LCD_RA8875),y)
   CSRCS += ra8875.c
 endif
diff --git a/drivers/lcd/lcddrv_spiif.c b/drivers/lcd/lcddrv_spiif.c
new file mode 100644
index 0000000000..0f60caa828
--- /dev/null
+++ b/drivers/lcd/lcddrv_spiif.c
@@ -0,0 +1,349 @@
+/****************************************************************************
+ * drivers/lcd/lcddrv_spiif.c
+ *
+ * Generic Driver interface for the Single Chip LCD driver connected
+ * via spi driver
+ *
+ *   Copyright (C) 2019 Greg Nutt. All rights reserved.
+ *   Author: Dave Marples <d...@marples.net>
+ *           Based on work from Marco Krahl <ocram.lh...@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior writen permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <debug.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <nuttx/kmalloc.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/spi/spi.h>
+#include <nuttx/lcd/lcddrv_spiif.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Type Definition
+ ****************************************************************************/
+
+struct lcddrv_spiif_lcd_s
+{
+  /* Publically visible device structure */
+
+  struct lcddrv_lcd_s dev;
+
+  /* Reference to spi device structure */
+
+  struct spi_dev_s *spi;
+};
+
+/****************************************************************************
+ * Private Function Protototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lcddrv_spiif_backlight
+ *
+ * Description:
+ *   Set the backlight level of the connected display.
+ *
+ * Input Parameters:
+ *   spi   - Reference to the public driver structure
+ *   level - backlight level
+ *
+ * Returned Value:
+ *   OK - On Success
+ *
+ ****************************************************************************/
+
+static int lcddrv_spiif_backlight(struct lcddrv_lcd_s *lcd, int level)
+
+{
+  return spiif_backlight(lcd, level);
+}
+
+/****************************************************************************
+ * Name: lcddrv_spiif_select
+ *
+ * Description:
+ *   Select the SPI, locking and re-configuring if necessary
+ *
+ * Input Parameters:
+ *   spi  - Reference to the public driver structure
+ *   isCommand - Flag indicating is command mode
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static void lcddrv_spiif_select(FAR struct lcddrv_lcd_s *lcd)
+{
+  FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+  SPI_LOCK(priv->spi, true);
+  SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), true);
+}
+
+/****************************************************************************
+ * Name: lcddrv_spiif_deselect
+ *
+ * Description:
+ *   De-select the SPI
+ *
+ * Input Parameters:
+ *   spi  - Reference to the public driver structure
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static void lcddrv_spiif_deselect(FAR struct lcddrv_lcd_s *lcd)
+{
+  FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+  SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), false);
+  SPI_SELECT(priv->spi, SPIDEV_DISPLAY(0), false);
+  SPI_LOCK(priv->spi, false);
+}
+
+/****************************************************************************
+ * Name: lcddrv_spiif_sendmulti
+ *
+ * Description:
+ *   Send a number of pixel words to the lcd driver gram.
+ *
+ * Input Parameters:
+ *   lcd    - Reference to the lcddrv_lcd_s driver structure
+ *   wd     - Reference to the words to send
+ *   nwords - number of words to send
+ *
+ * Returned Value:
+ *   OK - On Success
+ *
+ ****************************************************************************/
+
+static int lcddrv_spiif_sendmulti(FAR struct lcddrv_lcd_s *lcd,
+                          const uint16_t *wd, uint32_t nwords)
+{
+  FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+  SPI_SETBITS(priv->spi, 16);
+  for (uint32_t t = 0; t < nwords; t++)
+    {
+      SPI_SEND(priv->spi, *wd++);
+    }
+
+  SPI_SETBITS(priv->spi, 8);
+
+  return OK;
+};
+
+/****************************************************************************
+ * Name: lcddrv_spiif_recv
+ *
+ * Description:
+ *   Receive a parameter from the lcd driver.
+ *
+ * Input Parameters:
+ *   lcd    - Reference to the lcddrv_lcd_s driver structure
+ *   param  - Reference to where parameter receive
+ *
+ * Returned Value:
+ *   OK - On Success
+ *
+ ****************************************************************************/
+
+static int lcddrv_spiif_recv(FAR struct lcddrv_lcd_s *lcd,
+                                        uint8_t *param)
+{
+  FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+  lcdinfo("param=%04x\n", param);
+  SPI_RECVBLOCK(priv->spi, param, 1);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: lcddrv_spiif_send
+ *
+ * Description:
+ *   Send to the lcd
+ *
+ * Input Parameters:
+ *   lcd    - Reference to the lcddrv_lcd_s driver structure
+ *   param  - Reference to where parameter to send is located
+ *
+ * Returned Value:
+ *   OK - On Success
+ *
+ ****************************************************************************/
+
+static int lcddrv_spiif_send(FAR struct lcddrv_lcd_s *lcd,
+                             const uint8_t param)
+{
+  uint8_t r;
+  FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+  r = SPI_SEND(priv->spi, param);
+  return r;
+}
+
+/****************************************************************************
+ * Name: lcddrv_spiif_sendcmd
+ *
+ * Description:
+ *   Send command to the lcd
+ *
+ * Input Parameters:
+ *   lcd    - Reference to the lcddrv_lcd_s driver structure
+ *   param  - Reference to where parameter to send is located
+ *
+ * Returned Value:
+ *   OK - On Success
+ *
+ ****************************************************************************/
+
+static int lcddrv_spiif_sendcmd(FAR struct lcddrv_lcd_s *lcd,
+                                const uint8_t param)
+{
+  uint8_t r;
+  FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+  lcdinfo("param=%04x\n", param);
+  SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), true);
+  r = SPI_SEND(priv->spi, param);
+  SPI_CMDDATA(priv->spi, SPIDEV_DISPLAY(0), false);
+  return r;
+}
+
+/****************************************************************************
+ * Name: lcddrv_spiif_recvmulti
+ *
+ * Description:
+ *   Receive pixel words from the lcd driver gram.
+ *
+ * Input Parameters:
+ *   lcd    - Reference to the public driver structure
+ *   wd     - Reference to where the pixel words receive
+ *   nwords - number of pixel words to receive
+ *
+ * Returned Value:
+ *   OK - On Success
+ *
+ ****************************************************************************/
+
+static int lcddrv_spiif_recvmulti(FAR struct lcddrv_lcd_s *lcd,
+                                    uint16_t *wd, uint32_t nwords)
+{
+  FAR struct lcddrv_spiif_lcd_s *priv = (FAR struct lcddrv_spiif_lcd_s *)lcd;
+
+  lcdinfo("wd=%p, nwords=%d\n", wd, nwords);
+  SPI_SETBITS(priv->spi, 16);
+  SPI_RECVBLOCK(priv->spi, wd, nwords);
+  SPI_SETBITS(priv->spi, 8);
+  return OK;
+}
+
+/****************************************************************************
+ * Name:  FAR struct lcddrv_lcd_s *lcddrv_spiif_initialize
+ *
+ * Description:
+ *   Initialize the device structure to control the LCD Single chip driver.
+ *
+ * Input Parameters:
+ *   spi : handle to the spi to use
+ *
+ * Returned Value:
+ *   On success, this function returns a reference to the LCD control object
+ *   for the specified LCDDRV LCD Single chip driver.
+ *   NULL is returned on failure.
+ *
+ ****************************************************************************/
+
+FAR struct lcddrv_lcd_s *lcddrv_spiif_initialize(struct spi_dev_s *spi)
+
+{
+  FAR struct lcddrv_spiif_lcd_s *priv =
+  (struct lcddrv_spiif_lcd_s *)kmm_zalloc(sizeof(struct lcddrv_spiif_lcd_s));
+
+  if (!priv)
+    {
+      return NULL;
+    }
+
+  lcdinfo("initialize lcddrv spi subdriver\n");
+
+  priv->spi = spi;
+
+  if (!priv->spi)
+    {
+      kmm_free(priv);
+      return 0;
+    }
+
+  SPI_SETFREQUENCY(spi, CONFIG_LCD_LCDDRV_SPEED);
+  SPI_SETBITS(spi, 8);
+
+  /* Hook in our driver routines */
+
+  priv->dev.select      = lcddrv_spiif_select;
+  priv->dev.deselect    = lcddrv_spiif_deselect;
+  priv->dev.sendparam   = lcddrv_spiif_send;
+  priv->dev.sendcmd     = lcddrv_spiif_sendcmd;
+  priv->dev.recvparam   = lcddrv_spiif_recv;
+  priv->dev.sendgram    = lcddrv_spiif_sendmulti;
+  priv->dev.recvgram    = lcddrv_spiif_recvmulti;
+  priv->dev.backlight   = lcddrv_spiif_backlight;
+
+  return &priv->dev;
+}
diff --git a/include/nuttx/lcd/lcddrv_spiif.h b/include/nuttx/lcd/lcddrv_spiif.h
new file mode 100644
index 0000000000..398bc0fa39
--- /dev/null
+++ b/include/nuttx/lcd/lcddrv_spiif.h
@@ -0,0 +1,144 @@
+/*****************************************************************************
+ * include/nuttx/lcd/lcddrv_spiif.h
+ *
+ *   Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ *   Authors: Gregory Nutt <gn...@nuttx.org>
+ *            Dave Marples <d...@marples.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_LCD_LCDDRV_SPIIF_H
+#define __INCLUDE_NUTTX_LCD_LCDDRV_SPIIF_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/spi/spi.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct lcddrv_lcd_s
+{
+  /* Interface to control the ILI9341 lcd driver
+   *
+   *  - select      Select the device (as neccessary) before performing
+   *                any operations.
+   *  - deselect    Deselect the device (as necessary).
+   *  - send        Send specific parameter to the LCD driver.
+   *  - recv        Receive specific parameter from the LCD driver.
+   *  - sendmulti   Send pixel data to the LCD drivers gram.
+   *  - recvmulti   Receive pixel data from the LCD drivers gram.
+   *  - backlight   Change the backlight level of the connected display.
+   *                In the context of the ili9341 that means change the
+   *                backlight level of the connected LED driver.
+   *                The implementation in detail is part of the platform
+   *                specific sub driver.
+   */
+
+  void (*select)(FAR struct lcddrv_lcd_s *lcd);
+  void (*deselect)(FAR struct lcddrv_lcd_s *lcd);
+  int (*sendcmd)(FAR struct lcddrv_lcd_s *lcd, const uint8_t cmd);
+  int (*sendparam)(FAR struct lcddrv_lcd_s *lcd, const uint8_t param);
+  int (*recvparam)(FAR struct lcddrv_lcd_s *lcd, uint8_t *param);
+  int (*recvgram)(FAR struct lcddrv_lcd_s *lcd,
+                  uint16_t *wd, uint32_t nwords);
+  int (*sendgram)(FAR struct lcddrv_lcd_s *lcd,
+                  const uint16_t *wd, uint32_t nwords);
+  int (*backlight)(FAR struct lcddrv_lcd_s *lcd, int level);
+
+  /* mcu interface specific data following */
+};
+
+/*****************************************************************************
+ * Public Data
+ *****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/*****************************************************************************
+ * Public Function Prototypes
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: spiif_backlight
+ *       (Provided by integrating platform)
+ *
+ * Description:
+ *   Set the backlight level of the connected display.
+ *
+ * Input Parameters:
+ *   spi   - Reference to the public driver structure
+ *   level - backlight level
+ *
+ * Returned Value:
+ *   OK - On Success
+ *
+ ****************************************************************************/
+
+extern int spiif_backlight(struct lcddrv_lcd_s *lcd, int level);
+
+/****************************************************************************
+ * Name:  FAR struct lcddrv_lcd_s *lcddrv_spiif_initialize
+ *
+ * Description:
+ *   Initialize the device structure to control the LCD Single chip driver.
+ *
+ * Input Parameters:
+ *   path : path to spi device to use
+ *
+ * Returned Value:
+ *   On success, this function returns a reference to the LCD control object
+ *   for the specified LCDDRV LCD Single chip driver.
+ *   NULL is returned on failure.
+ *
+ ****************************************************************************/
+
+FAR struct lcddrv_lcd_s *lcddrv_spiif_initialize(struct spi_dev_s *spi);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_LCD_LCDDRV_SPIIF_H */

Reply via email to