]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M4_SimpleLink_CC3220SF_CCS/ti/devices/cc32xx/driverlib/spi.c
Add SimpleLink CC3220SF demo.
[freertos] / FreeRTOS / Demo / CORTEX_M4_SimpleLink_CC3220SF_CCS / ti / devices / cc32xx / driverlib / spi.c
1 /*
2  * -------------------------------------------
3  *    CC3220 SDK - v0.10.00.00 
4  * -------------------------------------------
5  *
6  *  Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ 
7  *  
8  *  Redistribution and use in source and binary forms, with or without 
9  *  modification, are permitted provided that the following conditions 
10  *  are met:
11  *
12  *    Redistributions of source code must retain the above copyright 
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  *    Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the 
17  *    documentation and/or other materials provided with the   
18  *    distribution.
19  *
20  *    Neither the name of Texas Instruments Incorporated nor the names of
21  *    its contributors may be used to endorse or promote products derived
22  *    from this software without specific prior written permission.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
25  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
26  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
28  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
29  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
30  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
33  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
34  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *  
36  */
37 //*****************************************************************************
38 //
39 //  spi.c
40 //
41 //  Driver for the SPI.
42 //
43 //*****************************************************************************
44
45 //*****************************************************************************
46 //
47 //! \addtogroup SPI_Serial_Peripheral_Interface_api
48 //! @{
49 //
50 //*****************************************************************************
51
52
53 #include "inc/hw_ints.h"
54 #include "inc/hw_types.h"
55 #include "inc/hw_memmap.h"
56 #include "inc/hw_mcspi.h"
57 #include "inc/hw_apps_config.h"
58 #include "interrupt.h"
59 #include "spi.h"
60
61
62 //*****************************************************************************
63 //
64 // A mapping of SPI base address to interupt number.
65 //
66 //*****************************************************************************
67 static const unsigned long g_ppulSPIIntMap[][3] =
68 {
69     { SSPI_BASE, INT_SSPI }, // Shared SPI
70     { GSPI_BASE, INT_GSPI }, // Generic SPI
71     { LSPI_BASE, INT_LSPI }, // LINK SPI
72 };
73
74 //*****************************************************************************
75 //
76 // A mapping of SPI base address to DMA done interrupt mask bit(s).
77 //
78 //*****************************************************************************
79 static const unsigned long g_ulSPIDmaMaskMap[][2]=
80 {
81   {SSPI_BASE,APPS_CONFIG_DMA_DONE_INT_MASK_SHSPI_WR_DMA_DONE_INT_MASK},
82   {LSPI_BASE,APPS_CONFIG_DMA_DONE_INT_MASK_HOSTSPI_WR_DMA_DONE_INT_MASK},
83   {GSPI_BASE,APPS_CONFIG_DMA_DONE_INT_MASK_APPS_SPI_WR_DMA_DONE_INT_MASK},
84 };
85
86 //*****************************************************************************
87 //
88 //! \internal
89 //! Transfer bytes over SPI channel
90 //!
91 //! \param ulBase is the base address of SPI module
92 //! \param ucDout is the pointer to Tx data buffer or 0.
93 //! \param ucDin is pointer to Rx data buffer or 0
94 //! \param ulCount is the size of data in bytes.
95 //!
96 //! This function transfers \e ulCount bytes of data over SPI channel.
97 //!
98 //! The function will not return until data has been transmitted
99 //!
100 //! \return Returns 0 on success, -1 otherwise.
101 //
102 //*****************************************************************************
103 static long SPITransfer8(unsigned long ulBase, unsigned char *ucDout,
104                    unsigned char *ucDin, unsigned long ulCount,
105                    unsigned long ulFlags)
106 {
107   unsigned long ulReadReg;
108   unsigned long ulWriteReg;
109   unsigned long ulStatReg;
110   unsigned long ulOutIncr;
111   unsigned long ulInIncr;
112   unsigned long ulTxDummy;
113   unsigned long ulRxDummy;
114
115   //
116   // Initialize the variables
117   //
118   ulOutIncr = 1;
119   ulInIncr  = 1;
120
121   //
122   // Check if output buffer pointer is 0
123   //
124   if(ucDout == 0)
125   {
126     ulOutIncr = 0;
127     ulTxDummy = 0xFFFFFFFF;
128     ucDout = (unsigned char *)&ulTxDummy;
129   }
130
131   //
132   // Check if input buffer pointer is 0
133   //
134   if(ucDin == 0)
135   {
136     ulInIncr = 0;
137     ucDin = (unsigned char *)&ulRxDummy;
138   }
139
140   //
141   // Load the register addresses.
142   //
143   ulReadReg  = (ulBase + MCSPI_O_RX0);
144   ulWriteReg = (ulBase + MCSPI_O_TX0);
145   ulStatReg  = (ulBase + MCSPI_O_CH0STAT);
146
147   //
148   // Enable CS based on Flag
149   //
150   if( ulFlags & SPI_CS_ENABLE)
151   {
152     HWREG( ulBase + MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE;
153   }
154
155   while(ulCount)
156   {
157     //
158     // Wait for space in output register/FIFO.
159     //
160     while( !(HWREG(ulStatReg) & MCSPI_CH0STAT_TXS) )
161     {
162     }
163
164     //
165     // Write the data
166     //
167     HWREG(ulWriteReg) = *ucDout;
168
169     //
170     // Wait for data in input register/FIFO.
171     //
172     while( !( HWREG(ulStatReg) & MCSPI_CH0STAT_RXS) )
173     {
174     }
175
176     //
177     // Read the data
178     //
179     *ucDin = HWREG(ulReadReg);
180
181     //
182     // Increment pointers.
183     //
184     ucDout = ucDout + ulOutIncr;
185     ucDin  = ucDin  + ulInIncr;
186
187     //
188     // Decrement the count.
189     //
190     ulCount--;
191   }
192
193   //
194   // Disable CS based on Flag
195   //
196   if( ulFlags & SPI_CS_DISABLE)
197   {
198     HWREG( ulBase + MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE;
199   }
200
201   return 0;
202 }
203
204 //*****************************************************************************
205 //
206 //! \internal
207 //! Transfer half-words over SPI channel
208 //!
209 //! \param ulBase is the base address of SPI module
210 //! \param usDout is the pointer to Tx data buffer or 0.
211 //! \param usDin is pointer to Rx data buffer or 0
212 //! \param ulCount is the size of data in bytes.
213 //!
214 //! This function transfers \e ulCount bytes of data over SPI channel. Since
215 //! the API sends a half-word at a time \e ulCount should be a multiple
216 //! of two.
217 //!
218 //! The function will not return until data has been transmitted
219 //!
220 //! \return Returns 0 on success, -1 otherwise.
221 //
222 //*****************************************************************************
223 static long SPITransfer16(unsigned long ulBase, unsigned short *usDout,
224                    unsigned short *usDin, unsigned long ulCount,
225                    unsigned long ulFlags)
226 {
227   unsigned long ulReadReg;
228   unsigned long ulWriteReg;
229   unsigned long ulStatReg;
230   unsigned long ulOutIncr;
231   unsigned long ulInIncr;
232   unsigned long ulTxDummy;
233   unsigned long ulRxDummy;
234
235   //
236   // Initialize the variables.
237   //
238   ulOutIncr = 1;
239   ulInIncr  = 1;
240
241   //
242   // Check if count is multiple of half-word
243   //
244   if(ulCount%2)
245   {
246     return -1;
247   }
248
249   //
250   // Compute number of half words.
251   //
252   ulCount = ulCount/2;
253
254   //
255   // Check if output buffer pointer is 0
256   //
257   if(usDout == 0)
258   {
259     ulOutIncr = 0;
260     ulTxDummy = 0xFFFFFFFF;
261     usDout = (unsigned short *)&ulTxDummy;
262   }
263
264   //
265   // Check if input buffer pointer is 0
266   //
267   if(usDin == 0)
268   {
269     ulInIncr = 0;
270     usDin = (unsigned short *)&ulRxDummy;
271   }
272
273   //
274   // Load the register addresses.
275   //
276   ulReadReg  = (ulBase + MCSPI_O_RX0);
277   ulWriteReg = (ulBase + MCSPI_O_TX0);
278   ulStatReg  = (ulBase + MCSPI_O_CH0STAT);
279
280   //
281   // Enable CS based on Flag
282   //
283   if( ulFlags & SPI_CS_ENABLE)
284   {
285     HWREG( ulBase + MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE;
286   }
287
288   while(ulCount)
289   {
290     //
291     // Wait for space in output register/FIFO.
292     //
293     while( !(HWREG(ulStatReg) & MCSPI_CH0STAT_TXS) )
294     {
295     }
296
297     //
298     // Write the data
299     //
300     HWREG(ulWriteReg) = *usDout;
301
302     //
303     // Wait for data in input register/FIFO.
304     //
305     while( !( HWREG(ulStatReg) & MCSPI_CH0STAT_RXS) )
306     {
307     }
308
309     //
310     // Read the data
311     //
312     *usDin = HWREG(ulReadReg);
313
314     //
315     // Increment pointers.
316     //
317     usDout = usDout + ulOutIncr;
318     usDin  = usDin  + ulInIncr;
319
320     //
321     // Decrement the count.
322     //
323     ulCount--;
324   }
325
326   //
327   // Disable CS based on Flag
328   //
329   if( ulFlags & SPI_CS_DISABLE)
330   {
331     HWREG( ulBase + MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE;
332   }
333
334   return 0;
335 }
336
337 //*****************************************************************************
338 //
339 //! \internal
340 //! Transfer words over SPI channel
341 //!
342 //! \param ulBase is the base address of SPI module
343 //! \param ulDout is the pointer to Tx data buffer or 0.
344 //! \param ulDin is pointer to Rx data buffer or 0
345 //! \param ulCount is the size of data in bytes.
346 //!
347 //! This function transfers \e ulCount bytes of data over SPI channel. Since
348 //! the API sends a word at a time \e ulCount should be a multiple of four.
349 //!
350 //! The function will not return until data has been transmitted
351 //!
352 //! \return Returns 0 on success, -1 otherwise.
353 //
354 //*****************************************************************************
355 static long SPITransfer32(unsigned long ulBase, unsigned long *ulDout,
356                    unsigned long *ulDin, unsigned long ulCount,
357                    unsigned long ulFlags)
358 {
359   unsigned long ulReadReg;
360   unsigned long ulWriteReg;
361   unsigned long ulStatReg;
362   unsigned long ulOutIncr;
363   unsigned long ulInIncr;
364   unsigned long ulTxDummy;
365   unsigned long ulRxDummy;
366
367   //
368   // Initialize the variables.
369   //
370   ulOutIncr = 1;
371   ulInIncr  = 1;
372
373   //
374   // Check if count is multiple of word
375   //
376   if(ulCount%4)
377   {
378     return -1;
379   }
380
381   //
382   // Compute the number of words to be transferd
383   //
384   ulCount = ulCount/4;
385
386   //
387   // Check if output buffer pointer is 0
388   //
389   if(ulDout == 0)
390   {
391     ulOutIncr = 0;
392     ulTxDummy = 0xFFFFFFFF;
393     ulDout = &ulTxDummy;
394   }
395
396   //
397   // Check if input buffer pointer is 0
398   //
399   if(ulDin == 0)
400   {
401     ulInIncr = 0;
402     ulDin = &ulRxDummy;
403   }
404
405
406   //
407   // Load the register addresses.
408   //
409   ulReadReg  = (ulBase + MCSPI_O_RX0);
410   ulWriteReg = (ulBase + MCSPI_O_TX0);
411   ulStatReg  = (ulBase + MCSPI_O_CH0STAT);
412
413   //
414   // Enable CS based on Flag
415   //
416   if( ulFlags & SPI_CS_ENABLE)
417   {
418     HWREG( ulBase + MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE;
419   }
420
421   while(ulCount)
422   {
423     //
424     // Wait for space in output register/FIFO.
425     //
426     while( !(HWREG(ulStatReg) & MCSPI_CH0STAT_TXS) )
427     {
428     }
429
430     //
431     // Write the data
432     //
433     HWREG(ulWriteReg) = *ulDout;
434
435     //
436     // Wait for data in input register/FIFO.
437     //
438     while( !( HWREG(ulStatReg) & MCSPI_CH0STAT_RXS) )
439     {
440     }
441
442     //
443     // Read the data
444     //
445     *ulDin = HWREG(ulReadReg);
446
447     //
448     // Increment pointers.
449     //
450     ulDout = ulDout + ulOutIncr;
451     ulDin  = ulDin  + ulInIncr;
452
453     //
454     // Decrement the count.
455     //
456     ulCount--;
457   }
458
459   //
460   // Disable CS based on Flag
461   //
462   if( ulFlags & SPI_CS_DISABLE)
463   {
464     HWREG( ulBase + MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE;
465   }
466
467   return 0;
468 }
469
470 //*****************************************************************************
471 //
472 //! \internal
473 //! Gets the SPI interrupt number.
474 //!
475 //! \param ulBase is the base address of the SPI module
476 //!
477 //! Given a SPI base address, returns the corresponding interrupt number.
478 //!
479 //! \return Returns a SPI interrupt number, or -1 if \e ulBase is invalid.
480 //
481 //*****************************************************************************
482 static long
483 SPIIntNumberGet(unsigned long ulBase)
484 {
485     unsigned long ulIdx;
486
487     //
488     // Loop through the table that maps SPI base addresses to interrupt
489     // numbers.
490     //
491     for(ulIdx = 0; ulIdx < (sizeof(g_ppulSPIIntMap) /
492                             sizeof(g_ppulSPIIntMap[0])); ulIdx++)
493     {
494         //
495         // See if this base address matches.
496         //
497         if(g_ppulSPIIntMap[ulIdx][0] == ulBase)
498         {
499             //
500             // Return the corresponding interrupt number.
501             //
502             return(g_ppulSPIIntMap[ulIdx][1]);
503         }
504     }
505
506     //
507     // The base address could not be found, so return an error.
508     //
509     return(-1);
510 }
511
512 //*****************************************************************************
513 //
514 //! \internal
515 //! Gets the SPI DMA interrupt mask bit.
516 //!
517 //! \param ulBase is the base address of the SPI module
518 //!
519 //! Given a SPI base address, DMA interrupt mask bit.
520 //!
521 //! \return Returns a DMA interrupt mask bit, or -1 if \e ulBase is invalid.
522 //
523 //*****************************************************************************
524 static long
525 SPIDmaMaskGet(unsigned long ulBase)
526 {
527     unsigned long ulIdx;
528
529     //
530     // Loop through the table that maps SPI base addresses to interrupt
531     // numbers.
532     //
533     for(ulIdx = 0; ulIdx < (sizeof(g_ulSPIDmaMaskMap) /
534                             sizeof(g_ulSPIDmaMaskMap[0])); ulIdx++)
535     {
536         //
537         // See if this base address matches.
538         //
539         if(g_ulSPIDmaMaskMap[ulIdx][0] == ulBase)
540         {
541             //
542             // Return the corresponding interrupt number.
543             //
544             return(g_ulSPIDmaMaskMap[ulIdx][1]);
545         }
546     }
547
548     //
549     // The base address could not be found, so return an error.
550     //
551     return(-1);
552 }
553
554 //*****************************************************************************
555 //
556 //! Enables transmitting and receiving.
557 //!
558 //! \param ulBase is the base address of the SPI module
559 //!
560 //! This function enables the SPI channel for transmitting and receiving.
561 //!
562 //! \return None
563 //!
564 //
565 //*****************************************************************************
566 void
567 SPIEnable(unsigned long ulBase)
568 {
569   //
570   // Set Channel Enable Bit
571   //
572   HWREG(ulBase + MCSPI_O_CH0CTRL) |= MCSPI_CH0CTRL_EN;
573 }
574
575 //*****************************************************************************
576 //
577 //! Disables the transmitting and receiving.
578 //!
579 //! \param ulBase is the base address of the SPI module
580 //!
581 //! This function disables the SPI channel for transmitting and receiving.
582 //!
583 //! \return None
584 //!
585 //
586 //*****************************************************************************
587 void
588 SPIDisable(unsigned long ulBase)
589 {
590   //
591   // Reset Channel Enable Bit
592   //
593   HWREG(ulBase + MCSPI_O_CH0CTRL) &= ~MCSPI_CH0CTRL_EN;
594 }
595
596
597 //*****************************************************************************
598 //
599 //! Enables the SPI DMA operation for transmitting and/or receving.
600 //!
601 //! \param ulBase is the base address of the SPI module
602 //! \param ulFlags selectes the DMA signal for transmit and/or receive.
603 //!
604 //! This function enables transmit and/or receive DMA request based on the
605 //! \e ulFlags parameter.
606 //!
607 //! The parameter \e ulFlags is the logical OR of one or more of
608 //! the following :
609 //! - \b SPI_RX_DMA
610 //! - \b SPI_TX_DMA
611 //!
612 //! \return None.
613 //
614 //*****************************************************************************
615 void
616 SPIDmaEnable(unsigned long ulBase, unsigned long ulFlags)
617 {
618   //
619   // Enable DMA based on ulFlags
620   //
621   HWREG(ulBase + MCSPI_O_CH0CONF) |= ulFlags;
622 }
623
624 //*****************************************************************************
625 //
626 //! Disables the SPI DMA operation for transmitting and/or receving.
627 //!
628 //! \param ulBase is the base address of the SPI module
629 //! \param ulFlags selectes the DMA signal for transmit and/or receive.
630 //!
631 //! This function disables transmit and/or receive DMA request based on the
632 //! \e ulFlags parameter.
633 //!
634 //! The parameter \e ulFlags is the logical OR of one or more of
635 //! the following :
636 //! - \b SPI_RX_DMA
637 //! - \b SPI_TX_DMA
638 //!
639 //! \return None.
640 //
641 //*****************************************************************************
642 void
643 SPIDmaDisable(unsigned long ulBase, unsigned long ulFlags)
644 {
645   //
646   // Disable DMA based on ulFlags
647   //
648   HWREG(ulBase + MCSPI_O_CH0CONF) &= ~ulFlags;
649 }
650
651 //*****************************************************************************
652 //
653 //! Performs a software reset of the specified SPI module
654 //!
655 //! \param ulBase is the base address of the SPI module
656 //!
657 //! This function performs a software reset of the specified SPI module
658 //!
659 //! \return None.
660 //
661 //*****************************************************************************
662 void
663 SPIReset(unsigned long ulBase)
664 {
665
666   //
667   // Assert soft reset (auto clear)
668   //
669   HWREG(ulBase + MCSPI_O_SYSCONFIG) |= MCSPI_SYSCONFIG_SOFTRESET;
670
671   //
672   // wait until reset is done
673   //
674   while(!(HWREG(ulBase + MCSPI_O_SYSSTATUS)& MCSPI_SYSSTATUS_RESETDONE))
675   {
676   }
677 }
678
679 //*****************************************************************************
680 //
681 //! Sets the configuration of a SPI module
682 //!
683 //! \param ulBase is the base address of the SPI module
684 //! \param ulSPIClk is the rate of clock supplied to the SPI module.
685 //! \param ulBitRate is the desired bit rate.(master mode)
686 //! \param ulMode is the mode of operation.
687 //! \param ulSubMode is one of the valid sub-modes.
688 //! \param ulConfig is logical OR of configuration paramaters.
689 //!
690 //! This function configures SPI port for operation in specified sub-mode and
691 //! required bit rated as specified by \e ulMode and \e ulBitRate parameters
692 //! respectively.
693 //!
694 //! The SPI module can operate in either master or slave mode. The parameter
695 //! \e ulMode can be one of the following
696 //! -\b SPI_MODE_MASTER
697 //! -\b SPI_MODE_SLAVE
698 //!
699 //! The SPI module supports 4 sub modes based on SPI clock polarity and phase.
700 //!
701 //! <pre>
702 //! Polarity Phase  Sub-Mode
703 //!   0       0        0
704 //!   0       1        1
705 //!   1       0        2
706 //!   1       1        3
707 //! </pre>
708 //!
709 //! Required sub mode can be select by setting \e ulSubMode parameter to one
710 //! of the following
711 //! - \b SPI_SUB_MODE_0
712 //! - \b SPI_SUB_MODE_1
713 //! - \b SPI_SUB_MODE_2
714 //! - \b SPI_SUB_MODE_3
715 //!
716 //! The parameter \e ulConfig is logical OR of five values: the word length,
717 //! active level for chip select, software or hardware controled chip select,
718 //! 3 or 4 pin mode and turbo mode.
719 //! mode.
720 //!
721 //! SPI support 8, 16 and 32 bit word lengths defined by:-
722 //! - \b SPI_WL_8
723 //! - \b SPI_WL_16
724 //! - \b SPI_WL_32
725 //!
726 //! Active state of Chip[ Selece can be defined by:-
727 //! - \b SPI_CS_ACTIVELOW
728 //! - \b SPI_CS_ACTIVEHIGH
729 //!
730 //! SPI chip select can be configured to be controlled either by hardware or
731 //! software:-
732 //! - \b SPI_SW_CS
733 //! - \b SPI_HW_CS
734 //!
735 //! The module can work in 3 or 4 pin mode defined by:-
736 //! - \b SPI_3PIN_MODE
737 //! - \b SPI_4PIN_MODE
738 //!
739 //! Turbo mode can be set on or turned off using:-
740 //! - \b SPI_TURBO_MODE_ON
741 //! - \b SPI_TURBO_MODE_OFF
742 //!
743 //! \return None.
744 //
745 //*****************************************************************************
746 void
747 SPIConfigSetExpClk(unsigned long ulBase,unsigned long ulSPIClk,
748             unsigned long ulBitRate, unsigned long ulMode,
749             unsigned long ulSubMode, unsigned long ulConfig)
750 {
751
752   unsigned long ulRegData;
753   unsigned long ulDivider;
754
755   //
756   // Read MODULCTRL register
757   //
758   ulRegData = HWREG(ulBase + MCSPI_O_MODULCTRL);
759
760   //
761   // Set Master mode with h/w chip select
762   //
763   ulRegData &= ~(MCSPI_MODULCTRL_MS |
764                  MCSPI_MODULCTRL_SINGLE);
765
766   //
767   // Enable software control Chip Select, Init delay
768   // and 3-pin mode
769   //
770   ulRegData |= (((ulConfig >> 24) | ulMode) & 0xFF);
771
772   //
773   // Write the configuration
774   //
775   HWREG(ulBase + MCSPI_O_MODULCTRL) = ulRegData;
776
777   //
778   // Set IS, DPE0, DPE1 based on master or slave mode
779   //
780   if(ulMode == SPI_MODE_MASTER)
781   {
782     ulRegData = 0x1 << 16;
783   }
784   else
785   {
786     ulRegData = 0x6 << 16;
787   }
788
789   //
790   // Mask the configurations and set clock divider granularity
791   // to 1 cycle
792   //
793   ulRegData = (ulRegData & ~(MCSPI_CH0CONF_WL_M |
794                              MCSPI_CH0CONF_EPOL |
795                              MCSPI_CH0CONF_POL  |
796                              MCSPI_CH0CONF_PHA  |
797                              MCSPI_CH0CONF_TURBO ) |
798                MCSPI_CH0CONF_CLKG);
799
800   //
801   // Get the divider value
802   //
803   ulDivider = ((ulSPIClk/ulBitRate) - 1);
804
805   //
806   // The least significant four bits of the divider is used fo configure
807   // CLKD in MCSPI_CHCONF next eight least significant bits are used to
808   // configure the EXTCLK in MCSPI_CHCTRL
809   //
810   ulRegData |= ((ulDivider & 0x0000000F) << 2);
811   HWREG(ulBase + MCSPI_O_CH0CTRL) = ((ulDivider & 0x00000FF0) << 4);
812
813   //
814   // Set the protocol, CS polarity, word length
815   // and turbo mode
816   //
817   ulRegData = ((ulRegData  |
818                 ulSubMode) | (ulConfig & 0x0008FFFF));
819
820   //
821   // Write back the CONF register
822   //
823   HWREG(ulBase + MCSPI_O_CH0CONF) = ulRegData;
824
825 }
826
827 //*****************************************************************************
828 //
829 //! Receives a word from the specified port.
830 //!
831 //! \param ulBase is the base address of the SPI module.
832 //! \param pulData is pointer to receive data variable.
833 //!
834 //! This function gets a SPI word from the receive FIFO for the specified
835 //! port.
836 //!
837 //! \return Returns the number of elements read from the receive FIFO.
838 //
839 //*****************************************************************************
840 long
841 SPIDataGetNonBlocking(unsigned long ulBase, unsigned long *pulData)
842 {
843   unsigned long ulRegVal;
844
845   //
846   // Read register status register
847   //
848   ulRegVal = HWREG(ulBase + MCSPI_O_CH0STAT);
849
850   //
851   // Check is data is available
852   //
853   if(ulRegVal & MCSPI_CH0STAT_RXS)
854   {
855     *pulData = HWREG(ulBase + MCSPI_O_RX0);
856     return(1);
857   }
858
859    return(0);
860 }
861
862 //*****************************************************************************
863 //
864 //! Waits for the word to be received on the specified port.
865 //!
866 //! \param ulBase is the base address of the SPI module.
867 //! \param pulData is pointer to receive data variable.
868 //!
869 //! This function gets a SPI word from the receive FIFO for the specified
870 //! port.  If there is no word available, this function waits until a
871 //! word is received before returning.
872 //!
873 //! \return Returns the word read from the specified port, cast as an
874 //! \e unsigned long.
875 //
876 //*****************************************************************************
877 void
878 SPIDataGet(unsigned long ulBase, unsigned long *pulData)
879 {
880   //
881   // Wait for Rx data
882   //
883   while(!(HWREG(ulBase + MCSPI_O_CH0STAT) & MCSPI_CH0STAT_RXS))
884   {
885   }
886
887   //
888   // Read the value
889   //
890   *pulData = HWREG(ulBase + MCSPI_O_RX0);
891 }
892
893 //*****************************************************************************
894 //
895 //! Transmits a word on the specified port.
896 //!
897 //! \param ulBase is the base address of the SPI module
898 //! \param ulData is data to be transmitted.
899 //!
900 //! This function transmits a SPI word on the transmit FIFO for the specified
901 //! port.
902 //!
903 //! \return  Returns the number of elements written to the transmit FIFO.
904 //!
905 //*****************************************************************************
906 long
907 SPIDataPutNonBlocking(unsigned long ulBase, unsigned long ulData)
908 {
909     unsigned long ulRegVal;
910
911     //
912     // Read status register
913     //
914     ulRegVal = HWREG(ulBase + MCSPI_O_CH0STAT);
915
916     //
917     // Write value into Tx register/FIFO
918     // if space is available
919     //
920     if(ulRegVal & MCSPI_CH0STAT_TXS)
921     {
922       HWREG(ulBase + MCSPI_O_TX0) = ulData;
923       return(1);
924     }
925
926     return(0);
927 }
928
929 //*****************************************************************************
930 //
931 //! Waits until the word is transmitted on the specified port.
932 //!
933 //! \param ulBase is the base address of the SPI module
934 //! \param ulData is data to be transmitted.
935 //!
936 //! This function transmits a SPI word on the transmit FIFO for the specified
937 //! port. This function waits until the space is available on transmit FIFO
938 //!
939 //! \return None
940 //!
941 //*****************************************************************************
942 void
943 SPIDataPut(unsigned long ulBase, unsigned long ulData)
944 {
945   //
946   // Wait for space in FIFO
947   //
948   while(!(HWREG(ulBase + MCSPI_O_CH0STAT)&MCSPI_CH0STAT_TXS))
949   {
950   }
951
952   //
953   // Write the data
954   //
955   HWREG(ulBase + MCSPI_O_TX0) = ulData;
956 }
957
958 //*****************************************************************************
959 //
960 //! Enables the transmit and/or receive FIFOs.
961 //!
962 //! \param ulBase is the base address of the SPI module
963 //! \param ulFlags selects the FIFO(s) to be enabled
964 //!
965 //! This function enables the transmit and/or receive FIFOs as specified by
966 //! \e ulFlags.
967 //! The parameter \e ulFlags shoulde be logical OR of one or more of the
968 //! following:
969 //! - \b SPI_TX_FIFO
970 //! - \b SPI_RX_FIFO
971 //!
972 //! \return None.
973 //
974 //*****************************************************************************
975 void
976 SPIFIFOEnable(unsigned long ulBase, unsigned long ulFlags)
977 {
978   //
979   // Set FIFO enable bits.
980   //
981   HWREG(ulBase + MCSPI_O_CH0CONF) |= ulFlags;
982 }
983
984 //*****************************************************************************
985 //
986 //! Disables the transmit and/or receive FIFOs.
987 //!
988 //! \param ulBase is the base address of the SPI module
989 //! \param ulFlags selects the FIFO(s) to be enabled
990 //!
991 //! This function disables transmit and/or receive FIFOs. as specified by
992 //! \e ulFlags.
993 //! The parameter \e ulFlags shoulde be logical OR of one or more of the
994 //! following:
995 //! - \b SPI_TX_FIFO
996 //! - \b SPI_RX_FIFO
997 //!
998 //! \return None.
999 //
1000 //*****************************************************************************
1001 void
1002 SPIFIFODisable(unsigned long ulBase, unsigned long ulFlags)
1003 {
1004   //
1005   // Reset FIFO Enable bits.
1006   //
1007   HWREG(ulBase + MCSPI_O_CH0CONF) &= ~(ulFlags);
1008 }
1009
1010 //*****************************************************************************
1011 //
1012 //! Sets the FIFO level at which DMA requests or interrupts are generated.
1013 //!
1014 //! \param ulBase is the base address of the SPI module
1015 //! \param ulTxLevel is the Almost Empty Level for transmit FIFO.
1016 //! \param ulRxLevel is the Almost Full Level for the receive FIFO.
1017 //!
1018 //! This function Sets the FIFO level at which DMA requests or interrupts
1019 //! are generated.
1020 //!
1021 //! \return None.
1022 //
1023 //*****************************************************************************
1024 void SPIFIFOLevelSet(unsigned long ulBase, unsigned long ulTxLevel,
1025                    unsigned long ulRxLevel)
1026 {
1027   unsigned long ulRegVal;
1028
1029   //
1030   // Read the current configuration
1031   //
1032   ulRegVal = HWREG(ulBase + MCSPI_O_XFERLEVEL);
1033
1034   //
1035   // Mask and set new FIFO thresholds.
1036   //
1037   ulRegVal = ((ulRegVal & 0xFFFF0000) | (((ulRxLevel-1) << 8) | (ulTxLevel-1)));
1038
1039   //
1040   // Set the transmit and receive FIFO thresholds.
1041   //
1042   HWREG(ulBase + MCSPI_O_XFERLEVEL) = ulRegVal;
1043
1044 }
1045
1046 //*****************************************************************************
1047 //
1048 //! Gets the FIFO level at which DMA requests or interrupts are generated.
1049 //!
1050 //! \param ulBase is the base address of the SPI module
1051 //! \param pulTxLevel is a pointer to storage for the transmit FIFO level
1052 //! \param pulRxLevel is a pointer to storage for the receive FIFO level
1053 //!
1054 //! This function gets the FIFO level at which DMA requests or interrupts
1055 //! are generated.
1056 //!
1057 //! \return None.
1058 //
1059 //*****************************************************************************
1060 void
1061 SPIFIFOLevelGet(unsigned long ulBase, unsigned long *pulTxLevel,
1062                  unsigned long *pulRxLevel)
1063 {
1064   unsigned long ulRegVal;
1065
1066   //
1067   // Read the current configuration
1068   //
1069   ulRegVal = HWREG(ulBase + MCSPI_O_XFERLEVEL);
1070
1071   *pulTxLevel = (ulRegVal & 0xFF);
1072
1073   *pulRxLevel = ((ulRegVal >> 8) & 0xFF);
1074
1075 }
1076
1077 //*****************************************************************************
1078 //
1079 //! Sets the word count.
1080 //!
1081 //! \param ulBase is the base address of the SPI module
1082 //! \param ulWordCount is number of SPI words to be transmitted.
1083 //!
1084 //! This function sets the word count, which is the number of SPI word to
1085 //! be transferred on channel when using the FIFO buffer.
1086 //!
1087 //! \return None.
1088 //
1089 //*****************************************************************************
1090 void
1091 SPIWordCountSet(unsigned long ulBase, unsigned long ulWordCount)
1092 {
1093   unsigned long ulRegVal;
1094
1095   //
1096   // Read the current configuration
1097   //
1098   ulRegVal = HWREG(ulBase + MCSPI_O_XFERLEVEL);
1099
1100   //
1101   // Mask and set the word count
1102   //
1103   HWREG(ulBase + MCSPI_O_XFERLEVEL) = ((ulRegVal & 0x0000FFFF)|
1104                                       (ulWordCount & 0xFFFF) << 16);
1105 }
1106
1107 //*****************************************************************************
1108 //
1109 //! Registers an interrupt handler for a SPI interrupt.
1110 //!
1111 //! \param ulBase is the base address of the SPI module
1112 //! \param pfnHandler is a pointer to the function to be called when the
1113 //! SPI interrupt occurs.
1114 //!
1115 //! This function does the actual registering of the interrupt handler.  This
1116 //! function enables the global interrupt in the interrupt controller; specific
1117 //! SPI interrupts must be enabled via SPIIntEnable(). It is the interrupt
1118 //! handler's responsibility to clear the interrupt source.
1119 //!
1120 //! \sa IntRegister() for important information about registering interrupt
1121 //! handlers.
1122 //!
1123 //! \return None.
1124 //
1125 //*****************************************************************************
1126 void
1127 SPIIntRegister(unsigned long ulBase, void(*pfnHandler)(void))
1128 {
1129     unsigned long ulInt;
1130
1131     //
1132     // Determine the interrupt number based on the SPI module
1133     //
1134     ulInt = SPIIntNumberGet(ulBase);
1135
1136     //
1137     // Register the interrupt handler.
1138     //
1139     IntRegister(ulInt, pfnHandler);
1140
1141     //
1142     // Enable the SPI interrupt.
1143     //
1144     IntEnable(ulInt);
1145 }
1146
1147 //*****************************************************************************
1148 //
1149 //! Unregisters an interrupt handler for a SPI interrupt.
1150 //!
1151 //! \param ulBase is the base address of the SPI module
1152 //!
1153 //! This function does the actual unregistering of the interrupt handler.  It
1154 //! clears the handler to be called when a SPI interrupt occurs.  This
1155 //! function also masks off the interrupt in the interrupt controller so that
1156 //! the interrupt handler no longer is called.
1157 //!
1158 //! \sa IntRegister() for important information about registering interrupt
1159 //! handlers.
1160 //!
1161 //! \return None.
1162 //
1163 //*****************************************************************************
1164 void
1165 SPIIntUnregister(unsigned long ulBase)
1166 {
1167     unsigned long ulInt;
1168
1169     //
1170     // Determine the interrupt number based on the SPI module
1171     //
1172     ulInt = SPIIntNumberGet(ulBase);
1173
1174     //
1175     // Disable the interrupt.
1176     //
1177     IntDisable(ulInt);
1178
1179     //
1180     // Unregister the interrupt handler.
1181     //
1182     IntUnregister(ulInt);
1183 }
1184
1185 //*****************************************************************************
1186 //
1187 //! Enables individual SPI interrupt sources.
1188 //!
1189 //! \param ulBase is the base address of the SPI module
1190 //! \param ulIntFlags is the bit mask of the interrupt sources to be enabled.
1191 //!
1192 //! This function enables the indicated SPI interrupt sources.  Only the
1193 //! sources that are enabled can be reflected to the processor interrupt;
1194 //! disabled sources have no effect on the processor.
1195 //!
1196 //! The \e ulIntFlags parameter is the logical OR of any of the following:
1197 //!
1198 //! - \b SPI_INT_DMATX
1199 //! - \b SPI_INT_DMARX
1200 //! - \b SPI_INT_EOW
1201 //! - \b SPI_INT_RX_OVRFLOW
1202 //! - \b SPI_INT_RX_FULL
1203 //! - \b SPI_INT_TX_UDRFLOW
1204 //! - \b SPI_INT_TX_EMPTY
1205 //!
1206 //! \return None.
1207 //
1208 //*****************************************************************************
1209 void
1210 SPIIntEnable(unsigned long ulBase, unsigned long ulIntFlags)
1211 {
1212   unsigned long ulDmaMsk;
1213
1214   //
1215   // Enable DMA  Tx Interrupt
1216   //
1217   if(ulIntFlags & SPI_INT_DMATX)
1218   {
1219       ulDmaMsk = SPIDmaMaskGet(ulBase);
1220       HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR) = ulDmaMsk;
1221   }
1222
1223   //
1224   // Enable DMA  Rx Interrupt
1225   //
1226   if(ulIntFlags & SPI_INT_DMARX)
1227   {
1228       ulDmaMsk = (SPIDmaMaskGet(ulBase) >> 1);
1229       HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR) = ulDmaMsk;
1230   }
1231
1232   //
1233   // Enable the specific Interrupts
1234   //
1235   HWREG(ulBase + MCSPI_O_IRQENABLE) |= (ulIntFlags & 0x0003000F);
1236 }
1237
1238
1239 //*****************************************************************************
1240 //
1241 //! Disables individual SPI interrupt sources.
1242 //!
1243 //! \param ulBase is the base address of the SPI module
1244 //! \param ulIntFlags is the bit mask of the interrupt sources to be disabled.
1245 //!
1246 //! This function disables the indicated SPI interrupt sources.  Only the
1247 //! sources that are enabled can be reflected to the processor interrupt;
1248 //! disabled sources have no effect on the processor.
1249 //!
1250 //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags
1251 //! parameter to SPIIntEnable().
1252 //!
1253 //! \return None.
1254 //
1255 //*****************************************************************************
1256 void
1257 SPIIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
1258 {
1259   unsigned long ulDmaMsk;
1260
1261   //
1262   // Disable DMA  Tx Interrupt
1263   //
1264   if(ulIntFlags & SPI_INT_DMATX)
1265   {
1266       ulDmaMsk = SPIDmaMaskGet(ulBase);
1267       HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) = ulDmaMsk;
1268   }
1269
1270   //
1271   // Disable DMA  Tx Interrupt
1272   //
1273   if(ulIntFlags & SPI_INT_DMARX)
1274   {
1275       ulDmaMsk = (SPIDmaMaskGet(ulBase) >> 1);
1276       HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) = ulDmaMsk;
1277   }
1278
1279   //
1280   // Disable the specific Interrupts
1281   //
1282   HWREG(ulBase + MCSPI_O_IRQENABLE) &= ~(ulIntFlags & 0x0003000F);
1283 }
1284
1285 //*****************************************************************************
1286 //
1287 //! Gets the current interrupt status.
1288 //!
1289 //! \param ulBase is the base address of the SPI module
1290 //! \param bMasked is \b false if the raw interrupt status is required and
1291 //! \b true if the masked interrupt status is required.
1292 //!
1293 //! This function returns the interrupt status for the specified SPI.
1294 //! The status of interrupts that are allowed to reflect to the processor can
1295 //! be returned.
1296 //!
1297 //! \return Returns the current interrupt status, enumerated as a bit field of
1298 //! values described in SPIIntEnable().
1299 //
1300 //*****************************************************************************
1301 unsigned long
1302 SPIIntStatus(unsigned long ulBase, tBoolean bMasked)
1303 {
1304   unsigned long ulIntStat;
1305   unsigned long ulIntFlag;
1306   unsigned long ulDmaMsk;
1307
1308   //
1309   // Get SPI interrupt status
1310   //
1311   ulIntFlag = HWREG(ulBase + MCSPI_O_IRQSTATUS) & 0x0003000F;
1312
1313   if(bMasked)
1314   {
1315      ulIntFlag &= HWREG(ulBase + MCSPI_O_IRQENABLE);
1316   }
1317
1318   //
1319   // Get the interrupt bit
1320   //
1321   ulDmaMsk = SPIDmaMaskGet(ulBase);
1322
1323   //
1324   // Get the DMA interrupt status
1325   //
1326   if(bMasked)
1327   {
1328     ulIntStat = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_MASKED);
1329   }
1330   else
1331   {
1332     ulIntStat = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_RAW);
1333   }
1334
1335   //
1336   // Get SPI Tx DMA done status
1337   //
1338   if(ulIntStat & ulDmaMsk)
1339   {
1340      ulIntFlag |= SPI_INT_DMATX;
1341   }
1342
1343   //
1344   // Get SPI Rx DMA done status
1345   //
1346   if(ulIntStat & (ulDmaMsk >> 1))
1347   {
1348      ulIntFlag |= SPI_INT_DMARX;
1349   }
1350
1351   //
1352   // Return status
1353   //
1354   return(ulIntFlag);
1355 }
1356
1357 //*****************************************************************************
1358 //
1359 //! Clears SPI interrupt sources.
1360 //!
1361 //! \param ulBase is the base address of the SPI module
1362 //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared.
1363 //!
1364 //! The specified SPI interrupt sources are cleared, so that they no longer
1365 //! assert.  This function must be called in the interrupt handler to keep the
1366 //! interrupt from being recognized again immediately upon exit.
1367 //!
1368 //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags
1369 //! parameter to SPIIntEnable().
1370 //!
1371 //! \return None.
1372 //
1373 //*****************************************************************************
1374 void
1375 SPIIntClear(unsigned long ulBase, unsigned long ulIntFlags)
1376 {
1377   unsigned long ulDmaMsk;
1378
1379   //
1380   // Disable DMA  Tx Interrupt
1381   //
1382   if(ulIntFlags & SPI_INT_DMATX)
1383   {
1384       ulDmaMsk = SPIDmaMaskGet(ulBase);
1385       HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) = ulDmaMsk;
1386   }
1387
1388   //
1389   // Disable DMA  Tx Interrupt
1390   //
1391   if(ulIntFlags & SPI_INT_DMARX)
1392   {
1393       ulDmaMsk = (SPIDmaMaskGet(ulBase) >> 1);
1394       HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) = ulDmaMsk;
1395   }
1396
1397   //
1398   // Clear Interrupts
1399   //
1400   HWREG(ulBase + MCSPI_O_IRQSTATUS) = (ulIntFlags & 0x0003000F);
1401 }
1402
1403 //*****************************************************************************
1404 //
1405 //! Enables the chip select in software controlled mode
1406 //!
1407 //! \param ulBase is the base address of the SPI module.
1408 //!
1409 //! This function enables the Chip select in software controlled mode. The
1410 //! active state of CS will depend on the configuration done via
1411 //! \sa SPIConfigExpClkSet().
1412 //!
1413 //! \return None.
1414 //
1415 //*****************************************************************************
1416 void SPICSEnable(unsigned long ulBase)
1417 {
1418   //
1419   // Set Chip Select enable bit.
1420   //
1421   HWREG( ulBase+MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE;
1422 }
1423
1424 //*****************************************************************************
1425 //
1426 //! Disables the chip select in software controlled mode
1427 //!
1428 //! \param ulBase is the base address of the SPI module.
1429 //!
1430 //! This function disables the Chip select in software controlled mode. The
1431 //! active state of CS will depend on the configuration done via
1432 //! sa SPIConfigSetExpClk().
1433 //!
1434 //! \return None.
1435 //
1436 //*****************************************************************************
1437 void SPICSDisable(unsigned long ulBase)
1438 {
1439   //
1440   // Reset Chip Select enable bit.
1441   //
1442   HWREG( ulBase+MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE;
1443 }
1444
1445 //*****************************************************************************
1446 //
1447 //! Send/Receive data buffer over SPI channel
1448 //!
1449 //! \param ulBase is the base address of SPI module
1450 //! \param ucDout is the pointer to Tx data buffer or 0.
1451 //! \param ucDin is pointer to Rx data buffer or 0
1452 //! \param ulCount is the size of data in bytes.
1453 //! \param ulFlags controlls chip select toggling.
1454 //!
1455 //! This function transfers \e ulCount bytes of data over SPI channel. Since
1456 //! the API sends a SPI word at a time \e ulCount should be a multiple of
1457 //! word length set using SPIConfigSetExpClk().
1458 //!
1459 //! If the \e ucDout parameter is set to 0, the function will send 0xFF over
1460 //! the SPI MOSI line.
1461 //!
1462 //! If the \e ucDin parameter is set to 0, the function will ignore data on SPI
1463 //! MISO line.
1464 //!
1465 //! The parameter \e ulFlags is logical OR of one or more of the following
1466 //!
1467 //! - \b SPI_CS_ENABLE if CS needs to be enabled at start of transfer.
1468 //! - \b SPI_CS_DISABLE if CS need to be disabled at the end of transfer.
1469 //!
1470 //! This function will not return until data has been transmitted
1471 //!
1472 //! \return Returns 0 on success, -1 otherwise.
1473 //
1474 //*****************************************************************************
1475 long SPITransfer(unsigned long ulBase, unsigned char *ucDout,
1476                    unsigned char *ucDin, unsigned long ulCount,
1477                    unsigned long ulFlags)
1478 {
1479   unsigned long ulWordLength;
1480   long lRet;
1481
1482   //
1483   // Get the word length
1484   //
1485   ulWordLength = (HWREG(ulBase + MCSPI_O_CH0CONF) & MCSPI_CH0CONF_WL_M);
1486
1487   //
1488   // Check for word length.
1489   //
1490   if( !((ulWordLength == SPI_WL_8) || (ulWordLength == SPI_WL_16) ||
1491      (ulWordLength == SPI_WL_32)) )
1492   {
1493     return -1;
1494   }
1495
1496   if( ulWordLength == SPI_WL_8 )
1497   {
1498     //
1499     // Do byte transfer
1500     //
1501     lRet = SPITransfer8(ulBase,ucDout,ucDin,ulCount,ulFlags);
1502   }
1503   else if( ulWordLength == SPI_WL_16 )
1504   {
1505
1506     //
1507     // Do half-word transfer
1508     //
1509     lRet = SPITransfer16(ulBase,(unsigned short *)ucDout,
1510                   (unsigned short *)ucDin,ulCount,ulFlags);
1511   }
1512   else
1513   {
1514     //
1515     // Do word transfer
1516     //
1517     lRet = SPITransfer32(ulBase,(unsigned long *)ucDout,
1518                   (unsigned long *)ucDin,ulCount,ulFlags);
1519   }
1520
1521   //
1522   // return
1523   //
1524   return lRet;
1525
1526 }
1527 //*****************************************************************************
1528 //
1529 // Close the Doxygen group.
1530 //! @}
1531 //
1532 //*****************************************************************************