changeset 3222:99686efcd5ba

Optimised receiving of messages that fit in FIFO. Add clock gating. Fix race condition bug in dspi_transaction_end(). [ Bugzilla 1001815 ]
author vae
date Sun, 07 Apr 2013 16:33:02 +0000
parents fff0cdf83b21
children 4486b48763e2
files packages/devs/spi/freescale/dspi/current/ChangeLog packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi.h packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_buses.inl packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_io.h packages/devs/spi/freescale/dspi/current/src/spi_freescale_dspi.c
diffstat 5 files changed, 56 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/packages/devs/spi/freescale/dspi/current/ChangeLog
+++ b/packages/devs/spi/freescale/dspi/current/ChangeLog
@@ -1,9 +1,19 @@
-2013-02-06  Stefan Singer <stefan.singer@freescale.com>
-		+ Ilija Kocho <ilijak@siva.com.mk>
+2013-04-01  Ilija Kocho <ilijak@siva.com.mk>
+
+	* include/spi_freescale_dspi.h, include/spi_freescale_busses.inl
+	* include/spi_freescale_dspi_io.h, src/spi_freescale_dspi.c:
+	Optimised receiving of messages that fit in FIFO. Add clock gating.
+	Fix race condition bug in dspi_transaction_end(). [ Bugzilla 1001815 ]
 
-	* enhanced endianness support for devices with big and little endian
-	* added support for MPC5xxx in addition to Kinetis
-	* extended support for up to 8 DSPIs
+2013-02-06  Stefan Singer <stefan.singer@freescale.com>
+		    Ilija Kocho <ilijak@siva.com.mk>
+
+	* include/spi_freescale_dspi.h, include/spi_freescale_busses.inl
+	* include/spi_freescale_dspi_io.h, include/spi_freescale_dspi_bd.h,
+	* src/spi_freescale_dspi.c:
+	enhanced endianness support for devices with big and little endian
+	added support for MPC5xxx in addition to Kinetis
+	extended support for up to 8 DSPIs
 	(see Bugzilla 1001752).
 
 2012-12-28  Ilija Kocho <ilijak@siva.com.mk>
--- a/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi.h
+++ b/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi.h
@@ -123,6 +123,7 @@ typedef struct cyg_spi_freescale_dspi_bu
     cyg_uint32                      mcr_opt ;        // Module Configuratyon Register options
     const cyg_uint32*               spi_pin_list_p;  // List of GPIOs used by the SPI interface.
     const cyg_uint32*               cs_pin_list_p;   // List of GPIOs used as chip selects.
+    cyg_uint16                      clk_gate;        // Clock gate
     cyg_uint8                       cs_pin_num;      // Number of chip selects for this bus.
 } cyg_spi_freescale_dspi_bus_setup_t;
 
--- a/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_buses.inl
+++ b/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_buses.inl
@@ -157,6 +157,7 @@ static const cyg_spi_freescale_dspi_bus_
     .intr_prio       = CYGNUM_DEVS_SPI_FREESCALE_DSPI ## __bus ## _ISR_PRI,   \
     .spi_pin_list_p  = spi ## __bus ## _pins,                                 \
     .cs_pin_list_p   = spi ## __bus ## _cs_pins,                              \
+    .clk_gate        = CYGHWR_IO_FREESCALE_DSPI ## __bus ## _CLK,             \
     .cs_pin_num      = sizeof(spi ## __bus ## _cs_pins)/                      \
                        sizeof(spi ## __bus ## _cs_pins[0]),                   \
     .mcr_opt         = CYGHWR_FREESCALE_DSPI ## __bus ## _MCR_PCSSE |         \
--- a/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_io.h
+++ b/packages/devs/spi/freescale/dspi/current/include/spi_freescale_dspi_io.h
@@ -275,9 +275,10 @@ CYG_MACRO_END
 
 // Borrow following macros from HAL
 
-// CYGADDR_IO_SPI_FREESCALE_DSPI0_P
-// CYGADDR_IO_SPI_FREESCALE_DSPI1_P
-// CYGADDR_IO_SPI_FREESCALE_DSPI2_P
+// CYGADDR_IO_SPI_FREESCALE_DSPIx_P
+
+// CYGHWR_IO_CLOCK_ENABLE(__clkgate)
+// CYGHWR_IO_FREESCALE_DSPIx_CLK
 
 // CYGHWR_IO_FREESCALE_DSPI_PIN(__pin)
 
--- a/packages/devs/spi/freescale/dspi/current/src/spi_freescale_dspi.c
+++ b/packages/devs/spi/freescale/dspi/current/src/spi_freescale_dspi.c
@@ -155,12 +155,14 @@ dspi_status_clear(cyghwr_devs_freescale_
 static inline void
 dspi_fifo_clear(cyghwr_devs_freescale_dspi_t* dspi_p)
 {
+    DEBUG2_PRINTF("  Fifo Clear\n");
     dspi_p->mcr |= FREESCALE_DSPI_MCR_CLR_RXF_M | FREESCALE_DSPI_MCR_CLR_TXF_M;
 }
 
 static inline void
 dspi_fifo_drain(cyghwr_devs_freescale_dspi_t* dspi_p)
 {
+    DEBUG2_PRINTF("  Fifo Drain\n");
     dspi_p->sr |= FREESCALE_DSPI_SR_RFDF_M;
 }
 
@@ -207,7 +209,7 @@ static cyg_uint32 dspi_dma_ISR(cyg_vecto
     edma_p = dma_set_p->edma_p;
 
     cyg_drv_isr_lock();
-
+    
     // Disable the Tx DMA channel and DSPI IRQ.
     hal_freescale_edma_erq_disable(edma_p, SPI_DMA_CHAN_I(dma_set_p, TX));
     DSPI_IRQ_DISABLE(dspi_p);
@@ -412,7 +414,8 @@ static void dspi_bus_setup(cyg_spi_frees
     cyghwr_hal_freescale_edma_t* edma_p;
     cyg_uint32 dma_chan_i;
 
-    // Get the clock frequency from HAL.
+    // Set up the clocking.
+    CYGHWR_IO_CLOCK_ENABLE(spi_bus_p->setup_p->clk_gate);    
     spi_bus_p->clock_freq = CYGHWR_IO_SPI_FREESCALE_DSPI_CLOCK;
     DEBUG1_PRINTF("DSPI BUS %p: SysClk=%d\n", spi_bus_p, spi_bus_p->clock_freq);
 
@@ -750,11 +753,16 @@ static void spi_transaction_do (cyg_spi_
     DEBUG2_PRINTF("DSPI: transaction: count=%d drop_cs=%d\n", count, drop_cs);
 
     // Set up peripheral CS field. DSPI automatically asserts and deasserts CS
-    pushr = dspi_chip_select_set(
+    pushr =
+#ifndef CYGOPT_DEVS_SPI_FREESCALE_DSPI_TICK_ONLY_DROPS_CS
+          // Compatibility option
+          // eCos Reference Manual states that CS should drop prior to sending
+          // ticks, but other SPI drivers do not touch the CS.
+          tick_only ? dspi_p->pushr & 0x87FF0000 : 
+#endif
+          dspi_chip_select_set(
 #ifdef CYGOPT_DEVS_SPI_FREESCALE_DSPI_TICK_ONLY_DROPS_CS
-                                 // eCos Reference Manual states that CS should
-                                 // drop prior to send ticks, but other drivers
-                                 // (so far do not) touch the CS.
+                               // Compatibility option. See comment above.
                                  tick_only ? -1 :
 #endif
                                  dspi_device->dev_num,
@@ -767,8 +775,18 @@ static void spi_transaction_do (cyg_spi_
     pushque_n = dspi_bus->pushque_n;
     if(bus_16bit)
         txfifo_n *= 2;
-
-    if((dma_set_p=dspi_bus->setup_p->dma_set_p)) {
+    
+    if(count <= txfifo_n){
+        // If byte count fits in the FIFO don't bother with DMA.
+        if((dma_set_p = dspi_bus->setup_p->dma_set_p)) {
+            edma_p = dma_set_p->edma_p;
+            hal_freescale_edma_erq_disable(edma_p, SPI_DMA_CHAN_I(dma_set_p, RX));
+        }
+        dma_set_p = NULL;
+    } else {
+        dma_set_p = dspi_bus->setup_p->dma_set_p;
+    }
+    if(dma_set_p) {
         edma_p = dma_set_p->edma_p;
         // Set up the DMA channels.
         dma_chan_rx_i = SPI_DMA_CHAN_I(dma_set_p, RX);
@@ -841,19 +859,24 @@ static void spi_transaction_do (cyg_spi_
                 while((dspi_p->sr & FREESCALE_DSPI_SR_RFDF_M));
         } else {
             // No DMA - "manually" drain Rx FIFO
-            DEBUG2_PRINTF("DSPI FIFO: 'Manually' drain Rx fifo\n");
+            DEBUG2_PRINTF("DSPI FIFO: 'Manually' drain Rx fifo rx_data=%p bus_16bit=%d\n",
+                          rx_data, bus_16bit);
 #if DEBUG_SPI >= 3
             cyghwr_devs_freescale_dspi_diag(dspi_bus);
 #endif
             if(rx_data) {
                 if(bus_16bit) {
                     cyg_uint16* rx_data16 = (cyg_uint16*) rx_data;
-                    while(dspi_p->sr & FREESCALE_DSPI_SR_RXCTR_M)
+                    while(dspi_p->sr & FREESCALE_DSPI_SR_RXCTR_M) {
+                        DEBUG2_PRINTF("  Fifo Pull16\n");
                         *rx_data16++ = dspi_p->popr;
+                    }
                     rx_data = (cyg_uint8*) rx_data16;
                 } else {
-                    while(dspi_p->sr & FREESCALE_DSPI_SR_RXCTR_M)
+                    while(dspi_p->sr & FREESCALE_DSPI_SR_RXCTR_M) {
+                        DEBUG2_PRINTF("  Fifo Pull\n");
                         *rx_data++ = dspi_p->popr;
+                    }
                 }
             } else {
                 dspi_fifo_drain(dspi_p);
@@ -995,9 +1018,9 @@ static void dspi_transaction_end(cyg_spi
 
     if(dspi_device->chip_sel){
         // Clear peripheral CS by executing a dummy 4 bit transfer.
+        DSPI_EOQ_CLEAR(dspi_p);
         dspi_p->pushr = PUSHR_NULL | FREESCALE_DSPI_PUSHR_EOQ_M |
                         FREESCALE_DSPI_PUSHR_CTAS(1);
-        DSPI_EOQ_CLEAR(dspi_p);
         while(!(dspi_p->sr & FREESCALE_DSPI_SR_EOQF_M));
         dspi_device->chip_sel = 0;
     }