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