Enable using PCS of Kinetis' PUSHR register to select the periphery for
the SPI communication. There are two things we need to do for that:

1. When writing PUSHR register, write both -- command information (upper
   16 bit) and data (lower 16 bit) at once.

2. We need a way to set the `pcs` member (used when writing to PUSHR
   register) of the private `kinetis_spidev_s` structure from the
   board specific `kinetis_spi[n]select` procedure.
---
 arch/arm/src/kinetis/kinetis_spi.c | 51 +++++++++++++++++++++++++++++-
 arch/arm/src/kinetis/kinetis_spi.h | 30 ++++++++++++++++++
 2 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/arch/arm/src/kinetis/kinetis_spi.c 
b/arch/arm/src/kinetis/kinetis_spi.c
index f74a24325a..c757189746 100644
--- a/arch/arm/src/kinetis/kinetis_spi.c
+++ b/arch/arm/src/kinetis/kinetis_spi.c
@@ -104,6 +104,7 @@ struct kinetis_spidev_s
   uint8_t           nbits;      /* Width of word in bits (8 to 16) */
   uint8_t           mode;       /* Mode 0,1,2,3 */
   uint8_t           ctarsel;    /* Which CTAR */
+  int8_t            pcs;        /* Which PCS (0-5) to use or -1. */
 #ifdef CONFIG_KINETIS_SPI_DMA
   volatile uint32_t rxresult;   /* Result of the RX DMA */
   volatile uint32_t txresult;   /* Result of the TX DMA */
@@ -233,6 +234,7 @@ static struct kinetis_spidev_s g_spi0dev =
   .spibase  = KINETIS_SPI0_BASE,
   .lock     = NXMUTEX_INITIALIZER,
   .ctarsel  = KINETIS_SPI_CTAR0_OFFSET,
+  .pcs      = -1,
 #ifdef CONFIG_KINETIS_SPI_DMA
 #  ifdef CONFIG_KINETIS_SPI0_DMA
   .rxch     = KINETIS_DMA_REQUEST_SRC_SPI0_RX,
@@ -288,6 +290,7 @@ static struct kinetis_spidev_s g_spi1dev =
   .spibase  = KINETIS_SPI1_BASE,
   .lock     = NXMUTEX_INITIALIZER,
   .ctarsel  = KINETIS_SPI_CTAR0_OFFSET,
+  .pcs      = -1,
 #ifdef CONFIG_KINETIS_SPI_DMA
 #  ifdef CONFIG_KINETIS_SPI1_DMA
   .rxch     = KINETIS_DMA_REQUEST_SRC_SPI1_RX,
@@ -343,6 +346,7 @@ static struct kinetis_spidev_s g_spi2dev =
   .spibase  = KINETIS_SPI2_BASE,
   .lock     = NXMUTEX_INITIALIZER,
   .ctarsel  = KINETIS_SPI_CTAR0_OFFSET,
+  .pcs      = -1,
 #ifdef CONFIG_KINETIS_SPI_DMA
 #  ifdef CONFIG_KINETIS_SPI2_DMA
   .rxch     = KINETIS_DMA_REQUEST_SRC_FTM3_CH6__SPI2_RX,
@@ -1116,7 +1120,15 @@ static uint16_t spi_send_data(struct kinetis_spidev_s 
*priv, uint16_t wd,
 
   /* Write the data to transmitted to the SPI Data Register */
 
-  spi_putreg16(priv, KINETIS_SPI_PUSHR_OFFSET, SPI_PUSHR_TXDATA(wd));
+  if (0 <= priv->pcs)
+    {
+      spi_putreg(priv, KINETIS_SPI_PUSHR_OFFSET,
+                 SPI_PUSHR_PCS(priv->pcs) | SPI_PUSHR_TXDATA(wd));
+    }
+  else
+    {
+      spi_putreg16(priv, KINETIS_SPI_PUSHR_OFFSET, SPI_PUSHR_TXDATA(wd));
+    }
 
   /* Wait until transfer completes and the data is in the RX FIFO */
 
@@ -1822,4 +1834,41 @@ struct spi_dev_s *kinetis_spibus_initialize(int port)
   return &priv->spidev;
 }
 
+/****************************************************************************
+ * Name: kinetis_spisetpcs
+ *
+ * Description:
+ *   Set which Periphery Chip Select (PCS, 0-5) to use for the given SPI dev.
+ *
+ * Rationale:
+ *   We can use PCS field of the Kinetis' PUSHR register to select periphery
+ *   chips, provided that the relevant PIN is set with the appropriate ALT
+ *   configuration.
+ *
+ *   However, both, command information and data, must be write to the PUSHR
+ *   at once. Therefore, kinetis_spidev_s contains pcs member that store
+ *   information about which PCS to use. But kinetis_spidev_s is private and
+ *   so we need some public way to set pcs.
+ *
+ *   kinetis_spisetpcs is to be used from within the kinetis_spi[n]select
+ *   procedures when Kinetis' PCS are to be used.
+ *
+ * Input Parameters:
+ *   dev    - Device-specific state data
+ *   which  - Which Periphery Chip Select (PCS, 0-5) to use or -1.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void kinetis_spisetpcs(struct spi_dev_s *dev, int8_t which)
+{
+  struct kinetis_spidev_s *priv = (struct kinetis_spidev_s *)dev;
+
+  DEBUGASSERT(which <= 5);
+
+  priv->pcs = which;
+}
+
 #endif /* CONFIG_KINETIS_SPI0 || CONFIG_KINETIS_SPI1 ||  CONFIG_KINETIS_SPI2 */
diff --git a/arch/arm/src/kinetis/kinetis_spi.h 
b/arch/arm/src/kinetis/kinetis_spi.h
index 972d35b1c6..c21bd3641d 100644
--- a/arch/arm/src/kinetis/kinetis_spi.h
+++ b/arch/arm/src/kinetis/kinetis_spi.h
@@ -72,6 +72,36 @@ struct spi_dev_s;
 
 struct spi_dev_s *kinetis_spibus_initialize(int bus);
 
+/****************************************************************************
+ * Name: kinetis_spisetpcs
+ *
+ * Description:
+ *   Set which Periphery Chip Select (PCS, 0-5) to use for the given SPI dev.
+ *
+ * Rationale:
+ *   We can use PCS field of the Kinetis' PUSHR register to select periphery
+ *   chips, provided that the relevant PIN is set with the appropriate ALT
+ *   configuration.
+ *
+ *   However, both, command information and data, must be write to the PUSHR
+ *   at once. Therefore, kinetis_spidev_s contains pcs member that store
+ *   information about which PCS to use. But kinetis_spidev_s is private and
+ *   so we need some public way to set pcs.
+ *
+ *   kinetis_spisetpcs is to be used from within the kinetis_spi[n]select
+ *   procedures when Kinetis' PCS are to be used.
+ *
+ * Input Parameters:
+ *   dev    - Device-specific state data
+ *   which  - Which Periphery Chip Select (PCS, 0-5) to use or -1.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void kinetis_spisetpcs(struct spi_dev_s *dev, int8_t which);
+
 /****************************************************************************
  * Name:
  *   kinetis_spi[n]select, kinetis_spi[n]status, and kinetis_spi[n]cmddata
-- 
2.47.3

Reply via email to