SPI and I2C LLD slave support.
authorChitresh Gupta <chitresh.g@pathpartnertech.com>
Thu, 15 Sep 2016 13:15:41 +0000 (18:45 +0530)
committerFrank Livingston <frank-livingston@ti.com>
Wed, 5 Oct 2016 18:02:01 +0000 (13:02 -0500)
psdk_cust/pdk_k2g_1_0_1_0_eng/packages/ti/drv/i2c/I2C.h
psdk_cust/pdk_k2g_1_0_1_0_eng/packages/ti/drv/i2c/src/I2C_drv.c
psdk_cust/pdk_k2g_1_0_1_0_eng/packages/ti/drv/i2c/src/v0/I2C_lld_v0.c
psdk_cust/pdk_k2g_1_0_1_0_eng/packages/ti/drv/i2c/src/v0/I2C_lld_v0.h
psdk_cust/pdk_k2g_1_0_1_0_eng/packages/ti/drv/i2c/src/v0/I2C_v0.c
psdk_cust/pdk_k2g_1_0_1_0_eng/packages/ti/drv/i2c/src/v0/I2C_v0.h
psdk_cust/pdk_k2g_1_0_1_0_eng/packages/ti/drv/spi/src/v0/SPI_lld_v0.c
psdk_cust/pdk_k2g_1_0_1_0_eng/packages/ti/drv/spi/src/v0/SPI_lld_v0.h
psdk_cust/pdk_k2g_1_0_1_0_eng/packages/ti/drv/spi/src/v0/SPI_v0.c
psdk_cust/pdk_k2g_1_0_1_0_eng/packages/ti/drv/spi/src/v0/SPI_v0.h

index 5f45dd333dbb0f0cd09c3912dacaf3a9c8ad2c3a..94b9ec5e43befc6f0390d8dd2bf49173311b8723 100644 (file)
@@ -264,6 +264,17 @@ typedef enum I2C_BitRate_e {
     I2C_3P4Mhz = 2
 } I2C_BitRate;
 
+/*!
+ *  @brief  I2C Master/Slave Mode
+ *
+ *  Specify one of the I2C mode of communications.
+ *  The default is MASTER.
+ */
+typedef enum I2C_MS_mode_e {
+    I2C_MASTER = 0,
+    I2C_SLAVE = 1
+} I2C_MS_mode;
+
 /*!
  *  @brief  I2C Parameters
  *
@@ -293,6 +304,7 @@ typedef struct I2C_Params_s {
     I2C_BitRate         bitRate; /*!< I2C bus bit rate */
     void               *custom;  /*!< Custom argument used by driver
                                       implementation */
+    I2C_MS_mode        isSlave;  /* Master = 0, Slave = 1 */
 } I2C_Params;
 
 /*!
index f5d990a0bef8c9946d6e440d35e743515894aab0..3ec3c775a3062592eb0ec5adf8e4e7876a2c67c3 100644 (file)
@@ -57,7 +57,8 @@ const I2C_Params I2C_defaultParams = {
     I2C_MODE_BLOCKING,  /* transferMode */
     NULL,               /* transferCallbackFxn */
     I2C_100kHz,          /* bitRate */
-    NULL
+    NULL,
+    I2C_MASTER
 };
 
 /*
index e0aee8a6905f32d517041f8606621d0d42812c84..526e5910d673c830d199a580f97242d1e7bf8495 100644 (file)
@@ -104,6 +104,29 @@ void I2CMasterEnable(uint32_t baseAdd)
     i2cRegs->ICMDR |= CSL_I2C_ICMDR_IRS_MASK;
 }
 
+/**
+ * \brief   Enables the I2C module.This will bring the I2C module out of reset.
+ *
+ * \param   baseAdd   It is the Memory address of the I2C instance used.
+ *
+ * \return  None.
+ *
+ **/
+void I2CSlaveEnable(uint32_t baseAdd)
+{
+    CSL_I2cRegsOvly i2cRegs = (CSL_I2cRegsOvly)baseAdd;
+
+    /* Set Own Address */
+    i2cRegs->ICOAR = 0x11; // testI2C_OWN_ADDR;
+
+    /* Enable SLAVE mode */
+    i2cRegs->ICMDR &= ~CSL_I2C_ICMDR_MST_MASK;
+    i2cRegs->ICMDR |= CSL_I2C_ICMDR_FREE_MASK;
+
+    /* Bring I2C out of reset */
+    i2cRegs->ICMDR |= CSL_I2C_ICMDR_IRS_MASK;
+}
+
 /**
  * \brief   Disables the I2C Module.This will put the I2C module in reset.
  *          Only Tx and Rx are cleared,status bits are set their default
@@ -171,6 +194,20 @@ uint32_t I2CMasterErr(uint32_t baseAdd)
     return (I2CMasterIntStatusEx(baseAdd, errMask));
 }
 
+uint32_t I2CSlaveErr(uint32_t baseAdd)
+{
+    uint32_t errMask;
+
+    errMask = I2C_INT_ARBITRATION_LOST    |
+              I2C_INT_NO_ACK              |
+              I2C_INT_STOP_CONDITION      |
+              I2C_INT_ADRR_ZERO           |
+              I2C_INT_RECV_OVER_RUN       ;
+
+    return (I2CMasterIntStatusEx(baseAdd, errMask));
+}
+
+
 /**
  * \brief   This API configure I2C in different modes of operation.
  *
@@ -193,6 +230,16 @@ void I2CMasterControl(uint32_t baseAdd, uint32_t ctrlMask, uint32_t ctrlCmds)
     i2cRegs->ICMDR = i2cMdr;
 }
 
+void I2CSlaveControl(uint32_t baseAdd, uint32_t ctrlMask, uint32_t ctrlCmds)
+{
+    CSL_I2cRegsOvly i2cRegs = (CSL_I2cRegsOvly)baseAdd;
+    uint32_t i2cMdr = i2cRegs->ICMDR;
+
+    i2cMdr &= ~(ctrlMask | CSL_I2C_ICMDR_MST_MASK);
+    i2cMdr |= (ctrlCmds);
+    i2cRegs->ICMDR = i2cMdr;
+}
+
 /**
  * \brief   This API starts a I2C transaction on the bus. This API must
  *          be called after all the configuration for the i2c module is
@@ -209,6 +256,14 @@ void I2CMasterStart(uint32_t baseAdd)
     i2cRegs->ICMDR |= (CSL_I2C_ICMDR_MST_MASK | CSL_I2C_ICMDR_STT_MASK);
 }
 
+void I2CSlaveStart(uint32_t baseAdd)
+{
+    CSL_I2cRegsOvly i2cRegs = (CSL_I2cRegsOvly)baseAdd;
+
+    i2cRegs->ICMDR &= ~CSL_I2C_ICMDR_MST_MASK;
+    i2cRegs->ICMDR |= (CSL_I2C_ICMDR_STT_MASK);
+}
+
 /**
  * \brief  This API stops a I2C transaction on the bus.
  *         This API must be used in case a deliberate STOP needs to be sent
@@ -225,6 +280,13 @@ void I2CMasterStop(uint32_t baseAdd)
     i2cRegs->ICMDR |= (CSL_I2C_ICMDR_MST_MASK | CSL_I2C_ICMDR_STP_MASK);
 }
 
+void I2CSlaveStop(uint32_t baseAdd)
+{
+    CSL_I2cRegsOvly i2cRegs = (CSL_I2cRegsOvly)baseAdd;
+
+    i2cRegs->ICMDR &= ~CSL_I2C_ICMDR_MST_MASK;
+    i2cRegs->ICMDR |= (CSL_I2C_ICMDR_STP_MASK);
+}
 /**
  * \brief  This API enables only specified I2C interrupts in master mode.
  *
index 20533374c3777404674046b01b30316a71201f39..bada1c4fcf5f275d28dc9bfd940f908a7c5a232c 100644 (file)
@@ -120,14 +120,19 @@ extern "C" {
 
 /* I2C AM57x hardware register read/write functions */
 extern  void I2CMasterStop(uint32_t baseAdd);
+extern  void I2CSlaveStop(uint32_t baseAdd);
 extern  void I2CMasterStart(uint32_t baseAdd);
+extern  void I2CSlaveStart(uint32_t baseAdd);
 extern  void I2CMasterEnable(uint32_t baseAdd);
+extern  void I2CSlaveEnable(uint32_t baseAdd);
 extern  void I2CMasterDisable(uint32_t baseAdd);
 extern  uint32_t I2CMasterErr(uint32_t baseAdd);
+extern  uint32_t I2CSlaveErr(uint32_t baseAdd);
 extern  uint32_t I2CDataCountGet(uint32_t baseAdd);
 extern  uint8_t I2CMasterDataGet(uint32_t baseAdd);
 extern  bool I2CMasterBusBusy(uint32_t baseAdd);
 extern  void I2CMasterControl(uint32_t baseAdd, uint32_t ctrlMask, uint32_t ctrlCmds);
+extern  void I2CSlaveControl(uint32_t baseAdd, uint32_t ctrlMask, uint32_t ctrlCmds);
 extern  void I2CSetDataCount(uint32_t baseAdd, uint32_t count);
 extern  void I2CMasterDataPut(uint32_t baseAdd, uint8_t data);
 extern  void I2CMasterInitExpClk(uint32_t baseAdd, uint32_t sysClk,
index b9ddce8ea69327f24eec17836cf93a4625f15cf9..0d70bb221530ddfbf48eee7a372ae349c452c53a 100644 (file)
@@ -153,20 +153,37 @@ static void I2C_v0_hwiFxn(uintptr_t arg)
     }
 
     /* Check for I2C Errors */
-    errStatus = I2CMasterErr(hwAttrs->baseAddr);
+    if (object->isSlave != 1)
+    {
+        errStatus = I2CMasterErr(hwAttrs->baseAddr);
+    }
+    else
+    {
+        errStatus = I2CSlaveErr(hwAttrs->baseAddr);
+    }
     if (errStatus & I2C_INT_STOP_CONDITION)
     {
         if ((object->writeCountIdx == 0U) && (object->readCountIdx == 0U))
         {
-                   /* End of transfer stop condition, not an error */
-                   errStatus &= ~I2C_INT_STOP_CONDITION;
+            /* End of transfer stop condition, not an error */
+            errStatus &= ~I2C_INT_STOP_CONDITION;
         }
+        else if (object->isSlave == 1)
+        {
+            /* End of transfer stop condition, not an error */
+            errStatus &= ~I2C_INT_STOP_CONDITION;
+            // Change mode to exit
+            object->mode = I2C_ERROR;
+        }
+
     }
 
-    if ((errStatus == I2C_MASTER_ERR_NONE) || (object->mode == I2C_ERROR)) {
+    if ((errStatus == I2C_MASTER_ERR_NONE) || (object->mode == I2C_ERROR))
+    {
 
         /* No errors, now check what we need to do next */
-        switch (object->mode) {
+        switch (object->mode)
+        {
             /*
              * ERROR case is OK because if an Error is detected, a STOP bit is
              * sent; which in turn will call another interrupt. This interrupt
@@ -242,16 +259,34 @@ static void I2C_v0_hwiFxn(uintptr_t arg)
                         /* Set number of bytes to receive */
                         I2CSetDataCount(hwAttrs->baseAddr, object->readCountIdx);
 
-                        /* Configure peripheral for I2C Receive mode with stop */
-                        I2CMasterControl(hwAttrs->baseAddr,
-                                         I2C_CFG_MASK_RX | I2C_CFG_MASK_REPEAT_MODE,
-                                         I2C_CFG_CMD_RX | I2C_CFG_CMD_REPEAT_MODE_OFF);
+                        if (object->isSlave != 1)
+                        {
+                            /* Configure peripheral for I2C Receive mode with stop */
+                            I2CMasterControl(hwAttrs->baseAddr,
+                                             I2C_CFG_MASK_RX | I2C_CFG_MASK_REPEAT_MODE,
+                                             I2C_CFG_CMD_RX | I2C_CFG_CMD_REPEAT_MODE_OFF);
+                        }
+                        else
+                        {
+                            /* Configure peripheral for I2C Receive mode with stop */
+                            I2CSlaveControl(hwAttrs->baseAddr,
+                                             I2C_CFG_MASK_RX | I2C_CFG_MASK_REPEAT_MODE,
+                                             I2C_CFG_CMD_RX | I2C_CFG_CMD_REPEAT_MODE_OFF);
+                        }
 
                         /* Enable RX interrupt to handle data received */
                         I2CMasterIntEnableEx(hwAttrs->baseAddr, I2C_INT_RECV_READY);
 
-                        /* Start I2C peripheral in RX mode */
-                        I2CMasterStart(hwAttrs->baseAddr);
+                        if (object->isSlave != 1)
+                        {
+                            /* Start I2C peripheral in RX mode */
+                            I2CMasterStart(hwAttrs->baseAddr);
+                        }
+                        else
+                        {
+                            /* Start I2C peripheral in RX mode */
+                            I2CSlaveStart(hwAttrs->baseAddr);
+                        }
                     }
                 }
                 break;
@@ -270,8 +305,15 @@ static void I2C_v0_hwiFxn(uintptr_t arg)
                     /* Disable RX interrupt, next interrupt will be from STOP */
                     I2CMasterIntDisableEx(hwAttrs->baseAddr,
                                           I2C_INT_RECV_READY);
-                    /* Send stop */
-                    I2CMasterStop(hwAttrs->baseAddr);
+                    if (object->isSlave != 1)
+                    {
+                        /* Send stop */
+                        I2CMasterStop(hwAttrs->baseAddr);
+                    }
+                    else
+                    {
+                        I2CSlaveStop(hwAttrs->baseAddr);
+                    }
                 }
                 break;
 
@@ -284,8 +326,15 @@ static void I2C_v0_hwiFxn(uintptr_t arg)
         /* Some sort of error happened! */
         object->mode = I2C_ERROR;
 
-        /* Try to send a STOP bit to end all I2C communications immediately */
-        I2CMasterStop(hwAttrs->baseAddr);
+        if (object->isSlave != 1)
+        {
+            /* Try to send a STOP bit to end all I2C communications immediately */
+            I2CMasterStop(hwAttrs->baseAddr);
+        }
+        else
+        {
+            I2CSlaveStop(hwAttrs->baseAddr);
+        }
     }
 
     if (hwAttrs->intcMuxNum != INVALID_INTC_MUX_NUM)
@@ -356,6 +405,7 @@ static I2C_Handle I2C_open_v0(I2C_Handle handle, const I2C_Params *params)
         else {
             /* Copy the params contents */
             object->i2cParams = *params;
+            object->isSlave = params->isSlave;
         }
 
         /* extract operational mode from i2cparams and hardware attributes */
@@ -379,7 +429,7 @@ static I2C_Handle I2C_open_v0(I2C_Handle handle, const I2C_Params *params)
         {
             if (hwAttrs->intcMuxNum != INVALID_INTC_MUX_NUM)
             {
-                           /* Setup Chip Interrupt Controller */
+                /* Setup Chip Interrupt Controller */
                 muxInParams.arg         = (uintptr_t)handle;
                 muxInParams.muxNum      = hwAttrs->intcMuxNum;
                 muxInParams.muxInEvent  = hwAttrs->intcMuxInEvent;
@@ -501,8 +551,15 @@ static I2C_Handle I2C_open_v0(I2C_Handle handle, const I2C_Params *params)
             /* Mask off all interrupts */
             I2CMasterIntDisableEx(hwAttrs->baseAddr, I2C_ALL_INTS);
 
-            /* Enable the I2C Master for operation */
-            I2CMasterEnable(hwAttrs->baseAddr);
+            if (object->isSlave != 1)
+            {
+                /* Enable the I2C Master for operation */
+                I2CMasterEnable(hwAttrs->baseAddr);
+            }
+            else
+            {
+                I2CSlaveEnable(hwAttrs->baseAddr);
+            }
         }
     }
     /* Return the address of the i2cObjectArray[i] configuration struct */
@@ -546,12 +603,99 @@ static void I2C_primeTransfer_v0(I2C_Handle handle,
         /* clear all interrupts */
         I2CMasterIntClearEx(hwAttrs->baseAddr, I2C_ALL_INTS);
 
+
         /* Enable interrupts on stop and error bits */
         I2CMasterIntEnableEx(hwAttrs->baseAddr,
                              I2C_INT_ARBITRATION_LOST |
                              I2C_INT_NO_ACK           |
                              I2C_INT_STOP_CONDITION);
 
+
+        if (object->isSlave == 1)
+        {
+
+            /* Start transfer in Receive mode */
+           if (object->readCountIdx)
+           {
+                object->mode = I2C_READ_MODE;
+
+                /* set number of bytes to read */
+                I2CSetDataCount(hwAttrs->baseAddr, object->readCountIdx);
+
+                /* set to Slave receiver mode */
+                I2CSlaveControl(hwAttrs->baseAddr,
+                                 I2C_CFG_MASK_RX | I2C_CFG_MASK_REPEAT_MODE,
+                                 I2C_CFG_CMD_RX | I2C_CFG_CMD_REPEAT_MODE_OFF);
+
+                /* Enable RX interrupts */
+                I2CMasterIntEnableEx(hwAttrs->baseAddr, I2C_INT_RECV_READY);
+
+                /* Send start bit */
+                I2CSlaveStart(hwAttrs->baseAddr);
+
+                I2C_drv_log1("\n I2C:(0x%x) I2C_IDLE_MODE: -> I2C_READ_MODE; Reading w/ NACK \n",
+                    hwAttrs->baseAddr);
+            }
+
+            /* Start transfer in Transmit mode */
+           else /*if (object->writeCountIdx)*/ {
+                /* Set number of bytes to be transmitting */
+                I2CSetDataCount(hwAttrs->baseAddr, object->writeCountIdx);
+
+                /*
+                 * Configure the I2C transfer to be in master transmitter mode,
+                 * and to automatically send stop when done.
+                 */
+                I2CSlaveControl(hwAttrs->baseAddr,
+                                 I2C_CFG_MASK_TX | I2C_CFG_MASK_REPEAT_MODE,
+                                 I2C_CFG_CMD_TX | I2C_CFG_CMD_REPEAT_MODE_OFF);
+
+                /* Log the transaction */
+                I2C_drv_log3("\n I2C:(0x%x) I2C_IDLE_MODE: Data to write: 0x%x; To Slave: 0x%x \n",
+                        hwAttrs->baseAddr, *(object->writeBufIdx),
+                        object->currentTransaction->slaveAddress);
+
+                /* Write data into transmit FIFO */
+                I2CMasterDataPut(hwAttrs->baseAddr, *(object->writeBufIdx));
+                (object->writeBufIdx)++;
+
+                /* Decrement write index */
+                object->writeCountIdx--;
+
+                if ((object->writeCountIdx != 0U) || (object->readCountIdx != 0U)) {
+                    /* We will have more data to process */
+                    object->mode = I2C_WRITE_MODE;
+                }
+                else {
+                    /*
+                     * We will be able to transmit all our data without any
+                     * intervention from the ISR. Set mode = idle so when we send a
+                     * stop bit, all the ISR does is post the semaphore.
+                     */
+                    object->mode = I2C_IDLE_MODE;
+                }
+
+                if (object->writeCountIdx) {
+                    /*
+                     * We were not able to transmit all the data, enable
+                     * transmit interrupt to re-fill Data transmit register on
+                     * under-run condition.
+                     */
+                    I2CMasterIntEnableEx(hwAttrs->baseAddr, I2C_INT_TRANSMIT_READY);
+                }
+
+
+                /* Start the I2C transfer in master transmit mode */
+                I2CSlaveStart(hwAttrs->baseAddr);
+
+                I2C_drv_log1("\n I2C:(0x%x) I2C_IDLE_MODE: -> I2C_WRITE_MODE; Writing w/ START \n",
+                    hwAttrs->baseAddr);
+            }
+
+        }
+        else
+        {
+
         /* Start transfer in Transmit mode */
         if (object->writeCountIdx) {
             /* Set number of bytes to be transmitting */
@@ -639,6 +783,7 @@ static void I2C_primeTransfer_v0(I2C_Handle handle,
             I2C_drv_log1("\n I2C:(0x%x) I2C_IDLE_MODE: -> I2C_READ_MODE; Reading w/ NACK \n",
                 hwAttrs->baseAddr);
         }
+        }
     }
     else  /* POLLING MODE */
     {
index 5ac9a2133424bdceed01d11dd072cf10ab929313..6af7bc57064b789b663241fc996613a2a68d7ff8 100644 (file)
@@ -141,6 +141,7 @@ typedef struct I2C_v0_Object_s {
     I2C_Transaction    *tailPtr;            /* Tail ptr for queued transactions */
 
     bool                isOpen;             /* flag to indicate module is open */
+    bool                isSlave;            /* flag to indicate module is Master or Slave */
 } I2C_v0_Object;
 
 /* Invalid Intc Mux number, intc Mux not used if assigned INVALID_INTC_MUX_NUM */
index 96011e418c9c91a497dc0fb52295733a4c9216db..71c870ffdbc5610e8e03f193584d679518fe8ebb 100644 (file)
@@ -326,10 +326,10 @@ void SPIIntStatusClear(uint32_t baseAdd, uint32_t intFlags)
 void SPITransmitData(uint32_t baseAdd, uint32_t csHold, uint32_t txData)
 {
     uint32_t temp_addr = baseAdd + CSL_SPI_SPIDAT1;
-       uint32_t spidat1 = HWREG(temp_addr);
+    uint32_t spidat1 = HWREG(temp_addr);
 
-       spidat1 &= ~(CSL_SPI_SPIDAT1_TXDATA_MASK | CSL_SPI_SPIDAT1_CSHOLD_MASK);
-       spidat1 |= (csHold << CSL_SPI_SPIDAT1_CSHOLD_SHIFT) | txData;
+    spidat1 &= ~(CSL_SPI_SPIDAT1_TXDATA_MASK | CSL_SPI_SPIDAT1_CSHOLD_MASK);
+    spidat1 |= (csHold << CSL_SPI_SPIDAT1_CSHOLD_SHIFT) | txData;
 
     /* Load the SPI_TX register with the data to be transmitted */
     HWREG(temp_addr) = spidat1;
@@ -377,7 +377,7 @@ void SPIGlobalControlSetup(uint32_t baseAdd, uint32_t loopback,
     uint32_t temp_addr = baseAdd + CSL_SPI_SPIGCR1;
     HWREG(temp_addr) = (loopback << CSL_SPI_SPIGCR1_LOOPBACK_SHIFT) | \
                                        (powerdown << CSL_SPI_SPIGCR1_POWERDOWN_SHIFT) | \
-                                       (SPI_MASTER_MODE << CSL_SPI_SPIGCR1_MASTER_SHIFT);
+                                       (clk_master << CSL_SPI_SPIGCR1_MASTER_SHIFT);
 }
 
 /**
@@ -418,6 +418,24 @@ void SPIDataFormatSetup(uint32_t baseAdd, uint32_t df_sel, uint32_t inputClkFreq
         (df_sel << CSL_SPI_SPIDAT1_DFSEL_SHIFT);
 }
 
+
+void SPIDataFormatSetupSlave(uint32_t baseAdd, uint32_t df_sel, uint32_t inputClkFreq,
+                        uint32_t spiOutClk, uint32_t clockMode, uint32_t charLen)
+{
+    uint32_t temp_addr = baseAdd + CSL_SPI_SPIFMT(df_sel);
+
+    /* Clear the DFSEL field of SPI_SPIDAT1 register. */
+    HWREG(temp_addr) = \
+        ((charLen << CSL_SPI_SPIFMT_CHARLEN_SHIFT) & CSL_SPI_SPIFMT_CHARLEN_MASK);
+
+    temp_addr = baseAdd + CSL_SPI_SPIDAT1;
+    /* Clear the DFSEL field of SPI_SPIDAT1 register. */
+    HWREG(temp_addr) &= ~CSL_SPI_SPIDAT1_DFSEL_MASK;
+
+    /* Set the DFSEL field with the user sent value. */
+    HWREG(temp_addr) |=
+        (df_sel << CSL_SPI_SPIDAT1_DFSEL_SHIFT);
+}
 /**
  * \brief  This call will setup the chip select delays
  *         of the SPI peripheral.
@@ -436,11 +454,11 @@ void SPIDelaySetup(uint32_t baseAdd, uint32_t c2tDelay, uint32_t t2cDelay)
         ((t2cDelay << CSL_SPI_SPIDELAY_T2CDELAY_SHIFT) & CSL_SPI_SPIDELAY_T2CDELAY_MASK);
 
     temp_addr = baseAdd + CSL_SPI_SPIFMT(0);
-       if ((c2tDelay != 0U) && (t2cDelay != 0U))
-       {
+    if ((c2tDelay != 0U) && (t2cDelay != 0U))
+    {
         HWREG(temp_addr) &= ~CSL_SPI_SPIFMT_DISCSTIMERS_MASK;
-       }
-       else
+    }
+    else
     {
         HWREG(temp_addr) |= CSL_SPI_SPIFMT_DISCSTIMERS_MASK;
     }
@@ -459,11 +477,11 @@ void SPIDelaySetup(uint32_t baseAdd, uint32_t c2tDelay, uint32_t t2cDelay)
 void SPISetShiftDir(uint32_t baseAdd, uint32_t shift_dir)
 {
     uint32_t temp_addr = baseAdd + CSL_SPI_SPIFMT(0);
-       if (shift_dir)
-       {
+    if (shift_dir)
+    {
         HWREG(temp_addr) |= CSL_SPI_SPIFMT_SHIFTDIR_MASK;
-       }
-       else
+    }
+    else
     {
         HWREG(temp_addr) &= ~CSL_SPI_SPIFMT_SHIFTDIR_MASK;
     }
index 7b0d678612aab4bc38b4fdd0d1adf6f7f2164464..06103e2039df923f661903d4f5a78c4e4089cd21 100644 (file)
@@ -95,6 +95,7 @@ extern "C" {
 #define SPI_POWERDOWN_ON     (CSL_SPI_SPIGCR1_POWERDOWN_ENABLE)
 #define SPI_POWERDOWN_OFF    (CSL_SPI_SPIGCR1_POWERDOWN_DISABLE)
 #define SPI_MASTER_MODE      (3U)    /* Master mode, SPICLK is an output */
+#define SPI_SLAVE_MODE       (0U)    /* Slave mode, SPICLK is an input */
 
 /*
 ** Values used to configure the SPI Pin Control Register 0 (SPIPC0)
@@ -158,6 +159,8 @@ extern void SPIPinControlSetup(uint32_t baseAdd, uint32_t somiFun,
                          uint32_t simoFun, uint32_t clkFun);
 extern void SPIDataFormatSetup(uint32_t baseAdd, uint32_t df_sel, uint32_t inputClkFreq,
                          uint32_t spiOutClk, uint32_t clockMode, uint32_t charLen);
+extern void SPIDataFormatSetupSlave(uint32_t baseAdd, uint32_t df_sel, uint32_t inputClkFreq,
+        uint32_t spiOutClk, uint32_t clockMode, uint32_t charLen);
 extern void SPIDelaySetup(uint32_t baseAdd, uint32_t c2tDelay, uint32_t t2cDelay);
 extern void SPIData1Setup(uint32_t baseAdd, uint32_t delay_enable, uint32_t cs);
 extern Bool SPIRxFull(uint32_t baseAdd);
index f27b832b1aa3d0f347fd96140e5dddf4a090cf0d..4e04e88288a55ca9d980e8b88edcef7615be8f4e 100644 (file)
@@ -136,7 +136,7 @@ static void SPI_primeTransfer_v0(SPI_Handle handle,
 
     /* Clear out any pending read data */
     do {
-               SPIReceiveData(hwAttrs->baseAddr);
+        SPIReceiveData(hwAttrs->baseAddr);
     } while(SPIRxFull(hwAttrs->baseAddr));
 
     if(object->operMode != SPI_OPER_MODE_POLLING)
@@ -157,11 +157,11 @@ static void SPI_primeTransfer_v0(SPI_Handle handle,
                 csHold = SPI_CSHOLD_OFF;
             }
 
-                       /* Wait until TX buffer is empty */
+            /* Wait until TX buffer is empty */
             while (SPITxEmpty(hwAttrs->baseAddr) == false)
             {}
 
-                       /* Write data to TX buffer, if no write data, write 0 */
+            /* Write data to TX buffer, if no write data, write 0 */
             if (object->writeBufIdx)
             {
                 SPITransmitData(hwAttrs->baseAddr, csHold, (uint32_t)(*object->writeBufIdx));
@@ -177,7 +177,7 @@ static void SPI_primeTransfer_v0(SPI_Handle handle,
             {}
 
             rxData = SPIReceiveData(hwAttrs->baseAddr);
-                       if (object->readBufIdx)
+            if (object->readBufIdx)
             {
                 *object->readBufIdx = (uint8_t)rxData;
                 object->readBufIdx++;
@@ -219,6 +219,26 @@ static void SPI_v0_hwiFxn (void* arg)
 
     intCode = SPIIntStatusGet(hwAttrs->baseAddr);
 
+    /* RX FIFO is full, empty the FIFO to receive more data if necessary */
+    if (intCode & SPI_INT_RX_FULL) {
+        rxData = SPIReceiveData(hwAttrs->baseAddr);
+        if (object->readCountIdx)
+        {
+            /* Read from the SPIBUF */
+            if (object->readBufIdx)
+            {
+                *object->readBufIdx = (uint8_t)rxData;
+                object->readBufIdx++;
+            }
+
+            object->readCountIdx--;
+        }
+
+        SPIIntStatusClear(hwAttrs->baseAddr, SPI_INT_RX_FULL);
+
+        intCode = intCode & ~SPI_INT_RX_FULL;
+    }
+
     /*
      * Refill the TX FIFO if an TX-empty interrupt has occurred & there is more
      * data to transmit.
@@ -228,11 +248,11 @@ static void SPI_v0_hwiFxn (void* arg)
         if (object->writeCountIdx)
         {
             /* For the last write byte, release the hold if no data read */
-            if ((object->writeCountIdx == 1U) && (terminateXfer != 0U))
+            if ((object->writeCountIdx == 1U) && (terminateXfer != 0U) && (object->isSlave == false))
             {
                 csHold = SPI_CSHOLD_OFF;
             }
-                       /* Write data to TX buffer, if no write data, write 0 */
+            /* Write data to TX buffer, if no write data, write 0 */
             if (object->writeBufIdx)
             {
                 SPITransmitData(hwAttrs->baseAddr, csHold, (uint32_t)(*object->writeBufIdx));
@@ -249,25 +269,7 @@ static void SPI_v0_hwiFxn (void* arg)
         intCode = intCode & ~SPI_INT_TX_EMPTY;
     }
 
-    /* RX FIFO is full, empty the FIFO to receive more data if necessary */
-    if (intCode & SPI_INT_RX_FULL) {
-        rxData = SPIReceiveData(hwAttrs->baseAddr);
-        if (object->readCountIdx)
-        {
-            /* Read from the SPIBUF */
-                       if (object->readBufIdx)
-            {
-                *object->readBufIdx = (uint8_t)rxData;
-                object->readBufIdx++;
-            }
-
-            object->readCountIdx--;
-        }
-
-        SPIIntStatusClear(hwAttrs->baseAddr, SPI_INT_RX_FULL);
 
-        intCode = intCode & ~SPI_INT_RX_FULL;
-    }
 
     /* RX overrun, read SPIBUF twice to get to the overrun buffer */
     if (intCode & SPI_INT_RX_OVERRUN)
@@ -276,7 +278,7 @@ static void SPI_v0_hwiFxn (void* arg)
         rxData = SPIReceiveData(hwAttrs->baseAddr);
         if (object->readCountIdx)
         {
-                       if (object->readBufIdx)
+            if (object->readBufIdx)
             {
                 *(object->readBufIdx) = (uint8_t)rxData;
                 (object->readBufIdx)++;
@@ -294,12 +296,20 @@ static void SPI_v0_hwiFxn (void* arg)
         SPIXferDisable(hwAttrs->baseAddr);
         SPIIntInit(hwAttrs->baseAddr);
         object->transferCallbackFxn((SPI_Handle)arg, object->transaction);
+        if (object->operMode == SPI_OPER_MODE_CALLBACK)
+        {
+            object->transaction = NULL;
+        }
     }
 
-    if ((object->readCountIdx == 0U) && (object->readCountIdx == 0U))
+    if ((object->readCountIdx == 0U) && (object->writeCountIdx == 0U))
     {
         SPIIntInit(hwAttrs->baseAddr);
         object->transferCallbackFxn((SPI_Handle)arg, object->transaction);
+        if (object->operMode == SPI_OPER_MODE_CALLBACK)
+        {
+            object->transaction = NULL;
+        }
     }
 
     if (hwAttrs->intcMuxNum != INVALID_INTC_MUX_NUM)
@@ -390,14 +400,8 @@ static SPI_Handle SPI_open_v0(SPI_Handle handle, const SPI_Params *params)
         }
 
 
-        /* Extract actual mode */
-        if(SPI_MASTER != params->mode)
-        {
-            /* Does not support slave mode */
-            SPI_close_v0(handle);
-            ret_flag = 1U;
-            handle = NULL;
-        }
+        object->isSlave = (bool)(params->mode == 1 ? true : false);
+
 
         if(ret_flag == 0U)
         {
@@ -500,8 +504,13 @@ static SPI_Handle SPI_open_v0(SPI_Handle handle, const SPI_Params *params)
             SPIReset(hwAttrs->baseAddr);
 
             /* Setup global control */
-            SPIGlobalControlSetup(hwAttrs->baseAddr, SPI_LOOPBACK_OFF,
-                                  SPI_POWERDOWN_OFF, SPI_MASTER_MODE);
+            if(SPI_MASTER == params->mode)
+                SPIGlobalControlSetup(hwAttrs->baseAddr, SPI_LOOPBACK_OFF,
+                                      SPI_POWERDOWN_OFF, SPI_MASTER_MODE);
+            else
+                SPIGlobalControlSetup(hwAttrs->baseAddr, SPI_LOOPBACK_OFF,
+                                       SPI_POWERDOWN_OFF, SPI_SLAVE_MODE);
+
             SPIXferDisable(hwAttrs->baseAddr);
 
             /* Initialize SPI interrupts, by default all disabled */
@@ -523,16 +532,27 @@ static SPI_Handle SPI_open_v0(SPI_Handle handle, const SPI_Params *params)
             }
 
             /* Configure data format */
+            if(SPI_MASTER == params->mode)
             SPIDataFormatSetup(hwAttrs->baseAddr,
                                SPI_DFSEL_0,
                                hwAttrs->inputClkFreq,
                                params->bitRate,
                                object->clockMode,
                                params->dataSize);
+            else
+                SPIDataFormatSetupSlave(hwAttrs->baseAddr,
+                                               SPI_DFSEL_0,
+                                               hwAttrs->inputClkFreq,
+                                               params->bitRate,
+                                               object->clockMode,
+                                               params->dataSize);
 
-            SPIDelaySetup(hwAttrs->baseAddr, SPI_C2TDELAY(8U), SPI_T2CDELAY(8U));
 
-            SPIData1Setup(hwAttrs->baseAddr, SPI_DELAY_ON, hwAttrs->csNum);
+            if(SPI_MASTER == params->mode)
+            {
+                SPIDelaySetup(hwAttrs->baseAddr, SPI_C2TDELAY(8U), SPI_T2CDELAY(8U));
+                SPIData1Setup(hwAttrs->baseAddr, SPI_DELAY_ON, hwAttrs->csNum);
+            }
         }
     }
     return (handle);
@@ -580,7 +600,10 @@ static bool SPI_transfer_v0(SPI_Handle handle, SPI_Transaction *transaction)
             /* Release the lock for this particular I2C handle */
             SPI_osalPostLock(object->mutex);
 
-            object->transaction = NULL;
+            if (object->operMode != SPI_OPER_MODE_CALLBACK) {
+                object->transaction = NULL;
+            }
+
             ret = (bool)true;
         }        
     }
index 37b69103531b3b4e38b0d51146cceddd9c21347e..6f26d8d81f8d7a9d5c97097c3e1ffe20ec1d7131 100644 (file)
@@ -216,6 +216,7 @@ typedef struct SPI_v0_Object_s {
     uint32_t              readCountIdx;        /* Internal dec. readCounter */
 
     bool                  isOpen;              /* flag to indicate module is open */
+    bool                  isSlave;             /* flag to indicate module is Master or Slave */
 } SPI_v0_Object, *SPI_v0_Handle;
 
 /* Invalid Intc Mux number, intc Mux not used if assigned INVALID_INTC_MUX_NUM */