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 //  sdhost.c
36 //
37 //  Driver for the SD Host (SDHost) Interface
38 //
39 //*****************************************************************************
40 
41 //*****************************************************************************
42 //
43 //! \addtogroup Secure_Digital_Host_api
44 //! @{
45 //
46 //*****************************************************************************
47 
48 #include "inc/hw_types.h"
49 #include "inc/hw_memmap.h"
50 #include "inc/hw_mmchs.h"
51 #include "inc/hw_ints.h"
52 #include "inc/hw_apps_config.h"
53 #include "interrupt.h"
54 #include "sdhost.h"
55 
56 
57 //*****************************************************************************
58 //
59 //! Configures SDHost module.
60 //!
61 //! \param ulBase is the base address of SDHost module.
62 //!
63 //! This function configures the SDHost module, enabling internal sub-modules.
64 //!
65 //! \return None.
66 //
67 //*****************************************************************************
68 void
SDHostInit(unsigned long ulBase)69 SDHostInit(unsigned long ulBase)
70 {
71   //
72   // Assert module reset
73   //
74   HWREG(ulBase + MMCHS_O_SYSCONFIG) = 0x2;
75 
76   //
77   // Wait for soft reset to complete
78   //
79   while( !(HWREG(ulBase + MMCHS_O_SYSCONFIG) & 0x1) )
80   {
81 
82   }
83 
84   //
85   // Assert internal reset
86   //
87   HWREG(ulBase + MMCHS_O_SYSCTL) |= (1 << 24);
88 
89   //
90   // Wait for Reset to complete
91   //
92   while( (HWREG(ulBase + MMCHS_O_SYSCTL) & (0x1 << 24)) )
93   {
94 
95   }
96 
97   //
98   // Set capability register, 1.8 and 3.0 V
99   //
100   HWREG(ulBase + MMCHS_O_CAPA) = (0x7 <<24);
101 
102   //
103   // Select bus voltage, 3.0 V
104   //
105   HWREG(ulBase + MMCHS_O_HCTL) |= 0x7 << 9;
106 
107   //
108   // Power up the bus
109   //
110   HWREG(ulBase + MMCHS_O_HCTL) |= 1 << 8;
111 
112   //
113   // Wait for power on
114   //
115   while( !(HWREG(ulBase + MMCHS_O_HCTL) & (1<<8)) )
116   {
117 
118   }
119 
120   HWREG(ulBase + MMCHS_O_CON) |= 1 << 21;
121 
122   //
123   // Un-mask all events
124   //
125   HWREG(ulBase + MMCHS_O_IE) = 0xFFFFFFFF;
126 }
127 
128 
129 //*****************************************************************************
130 //
131 //! Resets SDHost command line
132 //!
133 //! \param ulBase is the base address of SDHost module.
134 //!
135 //! This function assers a soft reset for the command line
136 //!
137 //! \return None.
138 //
139 //*****************************************************************************
140 void
SDHostCmdReset(unsigned long ulBase)141 SDHostCmdReset(unsigned long ulBase)
142 {
143   HWREG(ulBase + MMCHS_O_SYSCTL) |= 1 << 25;
144   while( (HWREG(ulBase + MMCHS_O_SYSCTL) & (1 << 25)) )
145   {
146 
147   }
148 }
149 
150 //*****************************************************************************
151 //
152 //! Sends command over SDHost interface
153 //!
154 //! \param ulBase is the base address of SDHost module.
155 //! \param ulCmd is the command to send.
156 //! \param ulArg is the argument for the command.
157 //!
158 //! This function send command to the attached card over the SDHost interface.
159 //!
160 //! The \e ulCmd parameter can be one of \b SDHOST_CMD_0 to \b SDHOST_CMD_63.
161 //! It can be logically ORed with one or more of the following:
162 //! - \b SDHOST_MULTI_BLK for multi-block transfer
163 //! - \b SDHOST_WR_CMD          if command is followed by write data
164 //! - \b SDHOST_RD_CMD          if command is followed by read data
165 //! - \b SDHOST_DMA_EN          if SDHost need to generate DMA request.
166 //! - \b SDHOST_RESP_LEN_136    if 136 bit response is expected
167 //! - \b SDHOST_RESP_LEN_48     if 48 bit response is expected
168 //! - \b SDHOST_RESP_LEN_48B    if 48 bit response with busy bit is expected
169 //!
170 //! The parameter \e ulArg is the argument for the command
171 //!
172 //! \return Returns 0 on success, -1 otherwise.
173 //
174 //*****************************************************************************
175 long
SDHostCmdSend(unsigned long ulBase,unsigned long ulCmd,unsigned ulArg)176 SDHostCmdSend(unsigned long ulBase, unsigned long ulCmd, unsigned ulArg)
177 {
178   //
179   // Set Data Timeout
180   //
181   HWREG(ulBase + MMCHS_O_SYSCTL) |= 0x000E0000;
182 
183   //
184   // Check for cmd inhabit
185   //
186   if( (HWREG(ulBase + MMCHS_O_PSTATE) & 0x1))
187   {
188     return -1;
189   }
190 
191   //
192   // Set the argument
193   //
194   HWREG(ulBase + MMCHS_O_ARG) = ulArg;
195 
196   //
197   // Send the command
198   //
199   HWREG(ulBase + MMCHS_O_CMD) = ulCmd;
200 
201   return 0;
202 }
203 
204 //*****************************************************************************
205 //
206 //! Writes a data word into the SDHost write buffer.
207 //!
208 //! \param ulBase is the base address of SDHost module.
209 //! \param ulData is data word to be transfered.
210 //!
211 //! This function writes a single data word into the SDHost write buffer. The
212 //! function returns \b true if there was a space available in the buffer else
213 //! returns \b false.
214 //!
215 //! \return Return \b true on success, \b false otherwise.
216 //
217 //*****************************************************************************
218 tBoolean
SDHostDataNonBlockingWrite(unsigned long ulBase,unsigned long ulData)219 SDHostDataNonBlockingWrite(unsigned long ulBase, unsigned long ulData)
220 {
221 
222   //
223   // See if there is a space in the write buffer
224   //
225   if( (HWREG(ulBase + MMCHS_O_PSTATE) & (1<<10)) )
226   {
227     //
228     // Write the data into the buffer
229     //
230     HWREG(ulBase + MMCHS_O_DATA) = ulData;
231 
232     //
233     // Success.
234     //
235     return(true);
236   }
237   else
238   {
239     //
240     // No free sapce, failure.
241     //
242     return(false);
243   }
244 }
245 
246 //*****************************************************************************
247 //
248 //! Waits to write a data word into the SDHost write buffer.
249 //!
250 //! \param ulBase is the base address of SDHost module.
251 //! \param ulData is data word to be transfered.
252 //!
253 //! This function writes \e ulData into the SDHost write buffer. If there is no
254 //! space in the write buffer this function waits until there is a space
255 //! available before returning.
256 //!
257 //! \return None.
258 //
259 //*****************************************************************************
260 void
SDHostDataWrite(unsigned long ulBase,unsigned long ulData)261 SDHostDataWrite(unsigned long ulBase, unsigned long ulData)
262 {
263   //
264   // Wait until space is available
265   //
266   while( !(HWREG(ulBase + MMCHS_O_PSTATE) & (1<<10)) )
267   {
268 
269   }
270 
271   //
272   // Write the data
273   //
274   HWREG(ulBase + MMCHS_O_DATA) = ulData;
275 }
276 
277 
278 //*****************************************************************************
279 //
280 //! Waits for a data word from the SDHost read buffer
281 //!
282 //! \param ulBase is the base address of SDHost module.
283 //! \param pulData is pointer to read data variable.
284 //!
285 //! This function reads a single data word from the SDHost read buffer. If there
286 //! is no data available in the buffer the function will wait until a data
287 //! word is received before returning.
288 //!
289 //! \return None.
290 //
291 //*****************************************************************************
292 void
SDHostDataRead(unsigned long ulBase,unsigned long * pulData)293 SDHostDataRead(unsigned long ulBase, unsigned long *pulData)
294 {
295   //
296   // Wait until data is available
297   //
298   while( !(HWREG(ulBase + MMCHS_O_PSTATE) & (1<<11)) )
299   {
300 
301   }
302 
303   //
304   // Read the data
305   //
306   *pulData = HWREG(ulBase + MMCHS_O_DATA);
307 }
308 
309 //*****************************************************************************
310 //
311 //! Reads single data word from the SDHost read buffer
312 //!
313 //! \param ulBase is the base address of SDHost module.
314 //! \param pulData is pointer to read data variable.
315 //!
316 //! This function reads a data word from the SDHost read buffer. The
317 //! function returns \b true if there was data available in to buffer else
318 //! returns \b false.
319 //!
320 //! \return Return \b true on success, \b false otherwise.
321 //
322 //*****************************************************************************
323 tBoolean
SDHostDataNonBlockingRead(unsigned long ulBase,unsigned long * pulData)324 SDHostDataNonBlockingRead(unsigned long ulBase, unsigned long *pulData)
325 {
326 
327   //
328   // See if there is any data in the read buffer.
329   //
330   if( (HWREG(ulBase + MMCHS_O_PSTATE) & (1<<11)) )
331   {
332     //
333     // Read the data word.
334     //
335     *pulData = HWREG(ulBase + MMCHS_O_DATA);
336 
337     //
338     // Success
339     //
340     return(true);
341   }
342   else
343   {
344     //
345     // No data available, failure.
346     //
347     return(false);
348   }
349 }
350 
351 
352 //*****************************************************************************
353 //
354 //! Registers the interrupt handler for SDHost interrupt
355 //!
356 //! \param ulBase is the base address of SDHost module
357 //! \param pfnHandler is a pointer to the function to be called when the
358 //! SDHost interrupt occurs.
359 //!
360 //! This function does the actual registering of the interrupt handler.  This
361 //! function enables the global interrupt in the interrupt controller; specific
362 //! SDHost interrupts must be enabled via SDHostIntEnable(). It is the
363 //! interrupt handler's responsibility to clear the interrupt source.
364 //!
365 //! \sa IntRegister() for important information about registering interrupt
366 //! handlers.
367 //!
368 //! \return None.
369 //
370 //*****************************************************************************
371 void
SDHostIntRegister(unsigned long ulBase,void (* pfnHandler)(void))372 SDHostIntRegister(unsigned long ulBase, void (*pfnHandler)(void))
373 {
374   //
375   // Register the interrupt handler.
376   //
377   IntRegister(INT_MMCHS, pfnHandler);
378 
379   //
380   // Enable the SDHost interrupt.
381   //
382   IntEnable(INT_MMCHS);
383 }
384 
385 //*****************************************************************************
386 //
387 //! Unregisters the interrupt handler for SDHost interrupt
388 //!
389 //! \param ulBase is the base address of SDHost module
390 //!
391 //! This function does the actual unregistering of the interrupt handler.  It
392 //! clears the handler to be called when a SDHost interrupt occurs.  This
393 //! function also masks off the interrupt in the interrupt controller so that
394 //! the interrupt handler no longer is called.
395 //!
396 //! \sa IntRegister() for important information about registering interrupt
397 //! handlers.
398 //!
399 //! \return None.
400 //
401 //*****************************************************************************
402 void
SDHostIntUnregister(unsigned long ulBase)403 SDHostIntUnregister(unsigned long ulBase)
404 {
405   //
406   // Disable the SDHost interrupt.
407   //
408   IntDisable(INT_MMCHS);
409 
410   //
411   // Unregister the interrupt handler.
412   //
413   IntUnregister(INT_MMCHS);
414 }
415 
416 //*****************************************************************************
417 //
418 //! Enable individual interrupt source for the specified SDHost
419 //!
420 //! \param ulBase is the base address of SDHost module.
421 //! \param ulIntFlags is a bit mask of the interrupt sources to be enabled.
422 //!
423 //! This function enables the indicated SDHost interrupt sources.  Only the
424 //! sources that are enabled can be reflected to the processor interrupt;
425 //! disabled sources have no effect on the processor.
426 //!
427 //! The \e ulIntFlags parameter is the logical OR of any of the following:
428 //! - \b SDHOST_INT_CC    Command Complete interrupt
429 //! - \b SDHOST_INT_TC    Transfer Complete interrupt
430 //! - \b SDHOST_INT_BWR   Buffer Write Ready interrupt
431 //! - \b SDHOST_INT_BRR   Buffer Read Ready interrupt
432 //! - \b SDHOST_INT_ERRI  Error interrupt
433 //! - \b SDHOST_INT_CTO   Command Timeout error interrupt
434 //! - \b SDHOST_INT_CEB   Command End Bit error interrupt
435 //! - \b SDHOST_INT_DTO   Data Timeout error interrupt
436 //! - \b SDHOST_INT_DCRC  Data CRC error interrupt
437 //! - \b SDHOST_INT_DEB   Data End Bit error
438 //! - \b SDHOST_INT_CERR  Cart Status Error interrupt
439 //! - \b SDHOST_INT_BADA  Bad Data error interrupt
440 //! - \b SDHOST_INT_DMARD Read DMA done interrupt
441 //! - \b SDHOST_INT_DMAWR Write DMA done interrupt
442 //!
443 //!     Note that SDHOST_INT_ERRI can only be used with \sa SDHostIntStatus()
444 //! and is internally logical OR of all error status bits. Setting this bit
445 //! alone as \e ulIntFlags doesn't generates any interrupt.
446 //!
447 //! \return None.
448 //
449 //*****************************************************************************
450 void
SDHostIntEnable(unsigned long ulBase,unsigned long ulIntFlags)451 SDHostIntEnable(unsigned long ulBase,unsigned long ulIntFlags)
452 {
453   //
454   // Enable DMA done interrupts
455   //
456   HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR) =
457                                                           (ulIntFlags >> 30);
458 
459   //
460   // Enable the individual interrupt sources
461   //
462   HWREG(ulBase + MMCHS_O_ISE) |= (ulIntFlags & 0x3FFFFFFF);
463 }
464 
465 //*****************************************************************************
466 //
467 //! Enable individual interrupt source for the specified SDHost
468 //!
469 //! \param ulBase is the base address of SDHost module.
470 //! \param ulIntFlags is a bit mask of the interrupt sources to be enabled.
471 //!
472 //! This function disables the indicated SDHost interrupt sources.  Only the
473 //! sources that are enabled can be reflected to the processor interrupt;
474 //! disabled sources have no effect on the processor.
475 //!
476 //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags
477 //! parameter to SDHostIntEnable().
478 //!
479 //! \return None.
480 //
481 //*****************************************************************************
482 void
SDHostIntDisable(unsigned long ulBase,unsigned long ulIntFlags)483 SDHostIntDisable(unsigned long ulBase,unsigned long ulIntFlags)
484 {
485   //
486   // Disable DMA done interrupts
487   //
488   HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) =
489                                                           (ulIntFlags >> 30);
490   //
491   // Disable the individual interrupt sources
492   //
493   HWREG(ulBase + MMCHS_O_ISE) &= ~(ulIntFlags & 0x3FFFFFFF);
494 }
495 
496 //*****************************************************************************
497 //
498 //! Gets the current interrupt status.
499 //!
500 //! \param ulBase is the base address of SDHost module.
501 //!
502 //! This function returns the interrupt status for the specified SDHost.
503 //!
504 //! \return Returns the current interrupt status, enumerated as a bit field of
505 //! values described in SDHostIntEnable().
506 //
507 //*****************************************************************************
508 unsigned long
SDHostIntStatus(unsigned long ulBase)509 SDHostIntStatus(unsigned long ulBase)
510 {
511   unsigned long ulIntStatus;
512 
513   //
514   // Get DMA done interrupt status
515   //
516   ulIntStatus = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_RAW);
517   ulIntStatus = (ulIntStatus << 30);
518 
519   //
520   // Return the status of individual interrupt sources
521   //
522   ulIntStatus |= (HWREG(ulBase + MMCHS_O_STAT) & 0x3FFFFFFF);
523 
524   return(ulIntStatus);
525 }
526 
527 //*****************************************************************************
528 //
529 //! Clears the individual interrupt sources.
530 //!
531 //! \param ulBase is the base address of SDHost module.
532 //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared.
533 //!
534 //! The specified SDHost interrupt sources are cleared, so that they no longer
535 //! assert.  This function must be called in the interrupt handler to keep the
536 //! interrupt from being recognized again immediately upon exit.
537 //!
538 //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags
539 //! parameter to SDHostIntEnable().
540 //!
541 //! \return None.
542 //
543 //*****************************************************************************
544 void
SDHostIntClear(unsigned long ulBase,unsigned long ulIntFlags)545 SDHostIntClear(unsigned long ulBase,unsigned long ulIntFlags)
546 {
547   //
548   // Clear DMA done interrupts
549   //
550   HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) =
551                                                           (ulIntFlags >> 30);
552   //
553   // Clear the individual interrupt sources
554   //
555   HWREG(ulBase + MMCHS_O_STAT) = (ulIntFlags & 0x3FFFFFFF);
556 }
557 
558 //*****************************************************************************
559 //
560 //! Sets the card status error mask.
561 //!
562 //! \param ulBase is the base address of SDHost module
563 //! \param ulErrMask is the bit mask of card status errors to be enabled
564 //!
565 //! This function sets the card status error mask for response type R1, R1b,
566 //! R5, R5b and R6 response. The parameter \e ulErrMask is the bit mask of card
567 //! status errors to be enabled, if the corresponding bits in the 'card status'
568 //! field of a respose are set then the host controller indicates a card error
569 //! interrupt status. Only bits referenced as type E (error) in status field in
570 //! the response can set a card status error.
571 //!
572 //! \return None
573 //
574 //*****************************************************************************
575 void
SDHostCardErrorMaskSet(unsigned long ulBase,unsigned long ulErrMask)576 SDHostCardErrorMaskSet(unsigned long ulBase, unsigned long ulErrMask)
577 {
578   //
579   // Set the card status error mask
580   //
581   HWREG(ulBase + MMCHS_O_CSRE) = ulErrMask;
582 }
583 
584 
585 //*****************************************************************************
586 //
587 //! Gets the card status error mask.
588 //!
589 //! \param ulBase is the base address of SDHost module
590 //!
591 //! This function gets the card status error mask for response type R1, R1b,
592 //! R5, R5b and R6 response.
593 //!
594 //! \return Returns the current card status error.
595 //
596 //*****************************************************************************
597 unsigned long
SDHostCardErrorMaskGet(unsigned long ulBase)598 SDHostCardErrorMaskGet(unsigned long ulBase)
599 {
600   //
601   // Return the card status error mask
602   //
603   return(HWREG(ulBase + MMCHS_O_CSRE));
604 }
605 
606 //*****************************************************************************
607 //
608 //! Sets the SD Card clock.
609 //!
610 //! \param ulBase is the base address of SDHost module
611 //! \param ulSDHostClk is the rate of clock supplied to SDHost module
612 //! \param ulCardClk is the required SD interface clock
613 //!
614 //! This function configures the SDHost interface to supply the specified clock
615 //! to the connected card.
616 //!
617 //! \return None.
618 //
619 //*****************************************************************************
620 void
SDHostSetExpClk(unsigned long ulBase,unsigned long ulSDHostClk,unsigned long ulCardClk)621 SDHostSetExpClk(unsigned long ulBase, unsigned long ulSDHostClk,
622              unsigned long ulCardClk)
623 {
624   unsigned long ulDiv;
625 
626   //
627   // Disable card clock
628   //
629   HWREG(ulBase + MMCHS_O_SYSCTL) &= ~0x4;
630 
631   //
632   // Enable internal clock
633   //
634   HWREG(ulBase + MMCHS_O_SYSCTL) |= 0x1;
635 
636   ulDiv = ((ulSDHostClk/ulCardClk) & 0x3FF);
637 
638   //
639   // Set clock divider,
640   //
641   HWREG(ulBase + MMCHS_O_SYSCTL) = ((HWREG(ulBase + MMCHS_O_SYSCTL) &
642                                      ~0x0000FFC0)| (ulDiv) << 6);
643 
644   //
645   // Wait for clock to stablize
646   //
647   while( !(HWREG(ulBase + MMCHS_O_SYSCTL) & 0x2) )
648   {
649 
650   }
651 
652   //
653   // Enable card clock
654   //
655   HWREG(ulBase + MMCHS_O_SYSCTL) |= 0x4;
656 }
657 
658 //*****************************************************************************
659 //
660 //! Get the response for the last command.
661 //!
662 //! \param ulBase is the base address of SDHost module
663 //! \param ulRespnse is 128-bit response.
664 //!
665 //! This function gets the response from the SD card for the last command
666 //! send.
667 //!
668 //! \return None.
669 //
670 //*****************************************************************************
671 void
SDHostRespGet(unsigned long ulBase,unsigned long ulRespnse[4])672 SDHostRespGet(unsigned long ulBase, unsigned long ulRespnse[4])
673 {
674 
675   //
676   // Read the responses.
677   //
678   ulRespnse[0] = HWREG(ulBase + MMCHS_O_RSP10);
679   ulRespnse[1] = HWREG(ulBase + MMCHS_O_RSP32);
680   ulRespnse[2] = HWREG(ulBase + MMCHS_O_RSP54);
681   ulRespnse[3] = HWREG(ulBase + MMCHS_O_RSP76);
682 
683 }
684 
685 //*****************************************************************************
686 //
687 //! Set the block size for data transfer
688 //!
689 //! \param ulBase is the base address of SDHost module
690 //! \param ulBlkSize is the transfer block size in bytes
691 //!
692 //! This function sets the block size the data transfer.
693 //!
694 //! The parameter \e ulBlkSize is size of each data block in bytes.
695 //! This should be in range 0 - 2^10.
696 //!
697 //! \return None.
698 //
699 //*****************************************************************************
700 void
SDHostBlockSizeSet(unsigned long ulBase,unsigned short ulBlkSize)701 SDHostBlockSizeSet(unsigned long ulBase, unsigned short ulBlkSize)
702 {
703   //
704   // Set the block size
705   //
706   HWREG(ulBase + MMCHS_O_BLK) = ((HWREG(ulBase + MMCHS_O_BLK) & 0x00000FFF)|
707                                   (ulBlkSize & 0xFFF));
708 }
709 
710 //*****************************************************************************
711 //
712 //! Set the block size and count for data transfer
713 //!
714 //! \param ulBase is the base address of SDHost module
715 //! \param ulBlkCount is the number of blocks
716 //!
717 //! This function sets block count for the data transfer. This needs to be set
718 //! for each block transfer. \sa SDHostBlockSizeSet()
719 //!
720 //! \return None.
721 //
722 //*****************************************************************************
723 void
SDHostBlockCountSet(unsigned long ulBase,unsigned short ulBlkCount)724 SDHostBlockCountSet(unsigned long ulBase, unsigned short ulBlkCount)
725 {
726   unsigned long ulRegVal;
727 
728   //
729   // Read the current value
730   //
731   ulRegVal = HWREG(ulBase + MMCHS_O_BLK);
732 
733   //
734   // Set the number of blocks
735   //
736   HWREG(ulBase + MMCHS_O_BLK) = ((ulRegVal & 0x0000FFFF)|
737                                   (ulBlkCount << 16));
738 }
739 
740 //*****************************************************************************
741 //
742 // Close the Doxygen group.
743 //! @}
744 //
745 //*****************************************************************************
746