]> git.sur5r.net Git - freertos/blob
c4c66f6f14c87c99f3a898f012d99089ccba377e
[freertos] /
1 /******************************************************************************
2 *
3 * Copyright (C) 2013 - 2015 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 *
35 * @file xsdps.c
36 *
37 * Contains the interface functions of the XSdPs driver.
38 * See xsdps.h for a detailed description of the device and driver.
39 *
40 * <pre>
41 * MODIFICATION HISTORY:
42 *
43 * Ver   Who    Date     Changes
44 * ----- ---    -------- -----------------------------------------------
45 * 1.00a hk/sg  10/17/13 Initial release
46 * 2.0   hk     12/13/13 Added check for arm to use sleep.h and its API's
47 * 2.1   hk     04/18/14 Add sleep for microblaze designs. CR# 781117.
48 * 2.2   hk     07/28/14 Make changes to enable use of data cache.
49 * 2.3   sk     09/23/14 Send command for relative card address
50 *                       when re-initialization is done.CR# 819614.
51 *                                               Use XSdPs_Change_ClkFreq API whenever changing
52 *                                               clock.CR# 816586.
53 * 2.4   sk         12/04/14 Added support for micro SD without
54 *                                               WP/CD. CR# 810655.
55 *                                               Checked for DAT Inhibit mask instead of CMD
56 *                                               Inhibit mask in Cmd Transfer API.
57 *                                               Added Support for SD Card v1.0
58 *
59 * </pre>
60 *
61 ******************************************************************************/
62
63 /***************************** Include Files *********************************/
64 #include "xsdps.h"
65 /*
66  * The header sleep.h and API usleep() can only be used with an arm design.
67  * MB_Sleep() is used for microblaze design.
68  */
69 #ifdef __arm__
70
71 #include "sleep.h"
72
73 #endif
74
75 #ifdef __MICROBLAZE__
76
77 #include "microblaze_sleep.h"
78
79 #endif
80
81 /************************** Constant Definitions *****************************/
82 #define XSDPS_CMD8_VOL_PATTERN  0x1AA
83 #define XSDPS_RESPOCR_READY     0x80000000
84 #define XSDPS_ACMD41_HCS        0x40000000
85 #define XSDPS_ACMD41_3V3        0x00300000
86 #define XSDPS_CMD1_HIGH_VOL     0x00FF8000
87 #define XSDPS_CMD1_DUAL_VOL     0x00FF8010
88
89 /**************************** Type Definitions *******************************/
90
91 /***************** Macros (Inline Functions) Definitions *********************/
92
93 #define XSDPS_INIT_DELAY        2000
94
95 /************************** Function Prototypes ******************************/
96 u32 XSdPs_FrameCmd(u32 Cmd);
97 int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt);
98 void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff);
99
100 /*****************************************************************************/
101 /**
102 *
103 * Initializes a specific XSdPs instance such that the driver is ready to use.
104 *
105 *
106 * @param        InstancePtr is a pointer to the XSdPs instance.
107 * @param        ConfigPtr is a reference to a structure containing information
108 *               about a specific SD device. This function initializes an
109 *               InstancePtr object for a specific device specified by the
110 *               contents of Config.
111 * @param        EffectiveAddr is the device base address in the virtual memory
112 *               address space. The caller is responsible for keeping the address
113 *               mapping from EffectiveAddr to the device physical base address
114 *               unchanged once this function is invoked. Unexpected errors may
115 *               occur if the address mapping changes after this function is
116 *               called. If address translation is not used, use
117 *               ConfigPtr->Config.BaseAddress for this device.
118 *
119 * @return
120 *               - XST_SUCCESS if successful.
121 *               - XST_DEVICE_IS_STARTED if the device is already started.
122 *               It must be stopped to re-initialize.
123 *
124 * @note         This function initializes the host controller.
125 *               Initial clock of 400KHz is set.
126 *               Voltage of 3.3V is selected as that is supported by host.
127 *               Interrupts status is enabled and signal disabled by default.
128 *               Default data direction is card to host and
129 *               32 bit ADMA2 is selected. Defualt Block size is 512 bytes.
130 *
131 ******************************************************************************/
132 int XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
133                                 u32 EffectiveAddr)
134 {
135         u32 ClockReg;
136         u32 Status;
137
138         Xil_AssertNonvoid(InstancePtr != NULL);
139         Xil_AssertNonvoid(ConfigPtr != NULL);
140
141         /*
142          * Set some default values.
143          */
144         InstancePtr->Config.BaseAddress = EffectiveAddr;
145         InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
146         InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
147         InstancePtr->Config.CardDetect =  ConfigPtr->CardDetect;
148         InstancePtr->Config.WriteProtect =  ConfigPtr->WriteProtect;
149
150         /*
151          * "Software reset for all" is initiated
152          */
153         XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET,
154                         XSDPS_SWRST_ALL_MASK);
155
156         /*
157          * Proceed with initialization only after reset is complete
158          */
159         while (XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
160                         XSDPS_SW_RST_OFFSET) & XSDPS_SWRST_ALL_MASK);
161
162         /*
163          * Read capabilities register and update it in Instance pointer.
164          * It is sufficient to read this once on power on.
165          */
166         InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
167                                                 XSDPS_CAPS_OFFSET);
168
169         /*
170          * Select voltage and enable bus power.
171          */
172         XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
173                         XSDPS_POWER_CTRL_OFFSET,
174                         XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK);
175
176         /*
177          * Change the clock frequency to 400 KHz
178          */
179         Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_400_KHZ);
180         if (Status != XST_SUCCESS) {
181                 Status = XST_FAILURE;
182                 goto RETURN_PATH ;
183         }
184
185         XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
186                         XSDPS_HOST_CTRL1_OFFSET,
187                         XSDPS_HC_DMA_ADMA2_32_MASK);
188
189         /*
190          * Enable all interrupt status except card interrupt initially
191          */
192         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
193                         XSDPS_NORM_INTR_STS_EN_OFFSET,
194                         XSDPS_NORM_INTR_ALL_MASK & (~XSDPS_INTR_CARD_MASK));
195
196         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
197                         XSDPS_ERR_INTR_STS_EN_OFFSET,
198                         XSDPS_ERROR_INTR_ALL_MASK);
199
200         /*
201          * Disable all interrupt signals by default.
202          */
203         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
204                         XSDPS_NORM_INTR_SIG_EN_OFFSET, 0x0);
205         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
206                         XSDPS_ERR_INTR_SIG_EN_OFFSET, 0x0);
207
208         /*
209          * Transfer mode register - default value
210          * DMA enabled, block count enabled, data direction card to host(read)
211          */
212         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
213                         XSDPS_XFER_MODE_OFFSET,
214                         XSDPS_TM_DMA_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK |
215                         XSDPS_TM_DAT_DIR_SEL_MASK);
216
217         /*
218          * Set block size to 512 by default
219          */
220         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
221                         XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK);
222
223         Status = XST_SUCCESS;
224
225 RETURN_PATH:
226         return Status;
227
228 }
229
230 /*****************************************************************************/
231 /**
232 * SD initialization is done in this function
233 *
234 *
235 * @param        InstancePtr is a pointer to the instance to be worked on.
236 *
237 * @return
238 *               - XST_SUCCESS if initialization was successful
239 *               - XST_FAILURE if failure - could be because
240 *                       a) SD is already initialized
241 *                       b) There is no card inserted
242 *                       c) One of the steps (commands) in the
243                            initialization cycle failed
244 *
245 * @note         This function initializes the SD card by following its
246 *               initialization and identification state diagram.
247 *               CMD0 is sent to reset card.
248 *               CMD8 and ACDM41 are sent to identify voltage and
249 *               high capacity support
250 *               CMD2 and CMD3 are sent to obtain Card ID and
251 *               Relative card address respectively.
252 *               CMD9 is sent to read the card specific data.
253 *
254 ******************************************************************************/
255 int XSdPs_SdCardInitialize(XSdPs *InstancePtr)
256 {
257         u32 PresentStateReg;
258         u32 Status;
259         u32 RespOCR = 0x0;
260         u32 CSD[4];
261
262         Xil_AssertNonvoid(InstancePtr != NULL);
263         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
264
265         if(InstancePtr->Config.CardDetect) {
266                 /*
267                  * Check the present state register to make sure
268                  * card is inserted and detected by host controller
269                  */
270                 PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
271                                 XSDPS_PRES_STATE_OFFSET);
272                 if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0) {
273                         Status = XST_FAILURE;
274                         goto RETURN_PATH;
275                 }
276         }
277
278         /*
279          * 74 CLK delay after card is powered up, before the first command.
280          */
281
282 #ifdef __arm__
283
284         usleep(XSDPS_INIT_DELAY);
285
286 #endif
287
288 #ifdef __MICROBLAZE__
289
290         /* 2 msec delay */
291         MB_Sleep(2);
292
293 #endif
294
295         /*
296          * CMD0 no response expected
297          */
298         Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0, 0);
299         if (Status != XST_SUCCESS) {
300                 Status = XST_FAILURE;
301                 goto RETURN_PATH;
302         }
303
304         /*
305          * CMD8; response expected
306          * 0x1AA - Supply Voltage 2.7 - 3.6V and AA is pattern
307          */
308         Status = XSdPs_CmdTransfer(InstancePtr, CMD8,
309                         XSDPS_CMD8_VOL_PATTERN, 0);
310         if (Status != XST_SUCCESS) {
311                 Status = XST_FAILURE;
312                 goto RETURN_PATH;
313         }
314
315         RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
316                                                 XSDPS_RESP0_OFFSET);
317         if (RespOCR != XSDPS_CMD8_VOL_PATTERN) {
318                 InstancePtr->CardType = CT_SD1;
319         }
320         else {
321                 InstancePtr->CardType = CT_SD2;
322         }
323
324         RespOCR = 0;
325         /*
326          * Send ACMD41 while card is still busy with power up
327          */
328         while ((RespOCR & XSDPS_RESPOCR_READY) == 0) {
329                 Status = XSdPs_CmdTransfer(InstancePtr, CMD55, 0, 0);
330                 if (Status != XST_SUCCESS) {
331                         Status = XST_FAILURE;
332                         goto RETURN_PATH;
333                 }
334
335                 /*
336                  * 0x40300000 - Host High Capacity support & 3.3V window
337                  */
338                 Status = XSdPs_CmdTransfer(InstancePtr, ACMD41,
339                                 (XSDPS_ACMD41_HCS | XSDPS_ACMD41_3V3), 0);
340                 if (Status != XST_SUCCESS) {
341                         Status = XST_FAILURE;
342                         goto RETURN_PATH;
343                 }
344
345                 /*
346                  * Response with card capacity
347                  */
348                 RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
349                                 XSDPS_RESP0_OFFSET);
350
351         }
352
353         /*
354          * Update HCS support flag based on card capacity response
355          */
356         if (RespOCR & XSDPS_ACMD41_HCS)
357                 InstancePtr->HCS = 1;
358
359         /*
360          * CMD2 for Card ID
361          */
362         Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0, 0);
363         if (Status != XST_SUCCESS) {
364                 Status = XST_FAILURE;
365                 goto RETURN_PATH;
366         }
367
368         InstancePtr->CardID[0] =
369                         XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
370                         XSDPS_RESP0_OFFSET);
371         InstancePtr->CardID[1] =
372                         XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
373                         XSDPS_RESP1_OFFSET);
374         InstancePtr->CardID[2] =
375                         XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
376                         XSDPS_RESP2_OFFSET);
377         InstancePtr->CardID[3] =
378                         XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
379                         XSDPS_RESP3_OFFSET);
380         do {
381                 Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0, 0);
382                 if (Status != XST_SUCCESS) {
383                         Status = XST_FAILURE;
384                         goto RETURN_PATH;
385                 }
386
387                 /*
388                  * Relative card address is stored as the upper 16 bits
389                  * This is to avoid shifting when sending commands
390                  */
391                 InstancePtr->RelCardAddr =
392                                 XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
393                                         XSDPS_RESP0_OFFSET) & 0xFFFF0000;
394         } while (InstancePtr->RelCardAddr == 0);
395
396         Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0);
397         if (Status != XST_SUCCESS) {
398                 Status = XST_FAILURE;
399                 goto RETURN_PATH;
400         }
401
402         /*
403          * Card specific data is read.
404          * Currently not used for any operation.
405          */
406         CSD[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
407                         XSDPS_RESP0_OFFSET);
408         CSD[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
409                         XSDPS_RESP1_OFFSET);
410         CSD[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
411                         XSDPS_RESP2_OFFSET);
412         CSD[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
413                         XSDPS_RESP3_OFFSET);
414
415         Status = XST_SUCCESS;
416
417 RETURN_PATH:
418         return Status;
419
420 }
421
422 /*****************************************************************************/
423 /**
424 * This function does SD command generation.
425 *
426 * @param        InstancePtr is a pointer to the instance to be worked on.
427 * @param        Cmd is the command to be sent.
428 * @param        Arg is the argument to be sent along with the command.
429 *               This could be address or any other information
430 * @param        BlkCnt - Block count passed by the user.
431 *
432 * @return
433 *               - XST_SUCCESS if initialization was successful
434 *               - XST_FAILURE if failure - could be because another transfer
435 *                       is in progress or command or data inhibit is set
436 *
437 ******************************************************************************/
438 int XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt)
439 {
440         u32 PresentStateReg;
441         u32 CommandReg;
442         u32 StatusReg;
443         u32 Status;
444
445         Xil_AssertNonvoid(InstancePtr != NULL);
446         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
447
448         /*
449          * Check the command inhibit to make sure no other
450          * command transfer is in progress
451          */
452         PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
453                         XSDPS_PRES_STATE_OFFSET);
454         if (PresentStateReg & XSDPS_PSR_INHIBIT_CMD_MASK) {
455                 Status = XST_FAILURE;
456                 goto RETURN_PATH;
457         }
458
459         /*
460          * Write block count register
461          */
462         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
463                         XSDPS_BLK_CNT_OFFSET, BlkCnt);
464
465         XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
466                         XSDPS_TIMEOUT_CTRL_OFFSET, 0xE);
467
468         /*
469          * Write argument register
470          */
471         XSdPs_WriteReg(InstancePtr->Config.BaseAddress,
472                         XSDPS_ARGMT_OFFSET, Arg);
473
474         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
475                         XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);
476         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
477                         XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);
478         /*
479          * Command register is set to trigger transfer of command
480          */
481         CommandReg = XSdPs_FrameCmd(Cmd);
482
483         /*
484          * Mask to avoid writing to reserved bits 31-30
485          * This is necessary because 0x80000000 is used  by this software to
486          * distinguish between ACMD and CMD of same number
487          */
488         CommandReg = CommandReg & 0x3FFF;
489
490         /*
491          * Check for data inhibit in case of command using DAT lines
492          */
493         PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
494                         XSDPS_PRES_STATE_OFFSET);
495         if ((PresentStateReg & XSDPS_PSR_INHIBIT_DAT_MASK) &&
496                         (CommandReg & XSDPS_DAT_PRESENT_SEL_MASK)) {
497                 Status = XST_FAILURE;
498                 goto RETURN_PATH;
499         }
500
501         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CMD_OFFSET,
502                         CommandReg);
503
504         /*
505          * Polling for response for now
506          */
507         do {
508                 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
509                                         XSDPS_NORM_INTR_STS_OFFSET);
510
511                 if (StatusReg & XSDPS_INTR_ERR_MASK) {
512
513                         /*
514                          * Write to clear error bits
515                          */
516                         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
517                                         XSDPS_ERR_INTR_STS_OFFSET,
518                                         XSDPS_ERROR_INTR_ALL_MASK);
519                         Status = XST_FAILURE;
520                         goto RETURN_PATH;
521                 }
522         } while((StatusReg & XSDPS_INTR_CC_MASK) == 0);
523         /*
524          * Write to clear bit
525          */
526         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
527                         XSDPS_NORM_INTR_STS_OFFSET,
528                         XSDPS_INTR_CC_MASK);
529
530         Status = XST_SUCCESS;
531
532         RETURN_PATH:
533                 return Status;
534
535 }
536
537 /*****************************************************************************/
538 /**
539 * This function frames the Command register for a particular command.
540 * Note that this generates only the command register value i.e.
541 * the upper 16 bits of the transfer mode and command register.
542 * This value is already shifted to be upper 16 bits and can be directly
543 * OR'ed with transfer mode register value.
544 *
545 * @param        Command to be sent.
546 *
547 * @return       Command register value complete with response type and
548 *               data, CRC and index related flags.
549 *
550 ******************************************************************************/
551 u32 XSdPs_FrameCmd(u32 Cmd)
552 {
553                 u32 RetVal;
554
555                 RetVal = Cmd;
556
557                 switch(Cmd) {
558                 case CMD0:
559                         RetVal |= RESP_NONE;
560                 break;
561                 case CMD1:
562                         RetVal |= RESP_R3;
563                 break;
564                 case CMD2:
565                         RetVal |= RESP_R2;
566                 break;
567                 case CMD3:
568                         RetVal |= RESP_R6;
569                 break;
570                 case CMD4:
571                         RetVal |= RESP_NONE;
572                         break;
573                 case CMD5:
574                         RetVal |= RESP_R1B;
575                 break;
576
577 #ifndef MMC_CARD
578                 case CMD6:
579                         RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK;
580                         break;
581 #else
582                 case CMD6:
583                         RetVal |= RESP_R1B;
584                         break;
585 #endif
586
587                 case ACMD6:
588                         RetVal |= RESP_R1;
589                 break;
590                 case CMD7:
591                         RetVal |= RESP_R1;
592                 break;
593
594 #ifndef MMC_CARD
595                 case CMD8:
596                         RetVal |= RESP_R1;
597                         break;
598 #else
599                 case CMD8:
600                         RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK;
601                         break;
602 #endif
603
604                 case CMD9:
605                         RetVal |= RESP_R2;
606                 break;
607                 case CMD10:
608                 case CMD12:
609                 case ACMD13:
610                 case CMD16:
611                         RetVal |= RESP_R1;
612                 break;
613                 case CMD17:
614                 case CMD18:
615                         RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK;
616                 break;
617                 case CMD23:
618                 case ACMD23:
619                 case CMD24:
620                 case CMD25:
621                         RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK;
622                 case ACMD41:
623                         RetVal |= RESP_R3;
624                 break;
625                 case ACMD42:
626                         RetVal |= RESP_R1;
627                 break;
628                 case ACMD51:
629                         RetVal |= RESP_R1 | XSDPS_DAT_PRESENT_SEL_MASK;
630                 break;
631                 case CMD52:
632                 case CMD55:
633                         RetVal |= RESP_R1;
634                 break;
635                 case CMD58:
636                 break;
637                 }
638
639                 return RetVal;
640 }
641
642 /*****************************************************************************/
643 /**
644 * This function performs SD read in polled mode.
645 *
646 * @param        InstancePtr is a pointer to the instance to be worked on.
647 * @param        Arg is the address passed by the user that is to be sent as
648 *               argument along with the command.
649 * @param        BlkCnt - Block count passed by the user.
650 * @param        Buff - Pointer to the data buffer for a DMA transfer.
651 *
652 * @return
653 *               - XST_SUCCESS if initialization was successful
654 *               - XST_FAILURE if failure - could be because another transfer
655 *               is in progress or command or data inhibit is set
656 *
657 ******************************************************************************/
658 int XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
659 {
660         u32 Status;
661         u32 PresentStateReg;
662         u32 StatusReg;
663
664         if(InstancePtr->Config.CardDetect) {
665                 /*
666                  * Check status to ensure card is initialized
667                  */
668                 PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
669                                 XSDPS_PRES_STATE_OFFSET);
670                 if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0) {
671                         Status = XST_FAILURE;
672                         goto RETURN_PATH;
673                 }
674         }
675
676         /*
677          * Set block size to 512 if not already set
678          */
679         if( XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
680                         XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {
681                 Status = XSdPs_SetBlkSize(InstancePtr,
682                         XSDPS_BLK_SIZE_512_MASK);
683                 if (Status != XST_SUCCESS) {
684                         Status = XST_FAILURE;
685                         goto RETURN_PATH;
686                 }
687         }
688
689         XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
690
691         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
692                         XSDPS_XFER_MODE_OFFSET,
693                         XSDPS_TM_AUTO_CMD12_EN_MASK |
694                         XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_DAT_DIR_SEL_MASK |
695                         XSDPS_TM_DMA_EN_MASK | XSDPS_TM_MUL_SIN_BLK_SEL_MASK);
696
697         Xil_DCacheInvalidateRange(Buff, BlkCnt * XSDPS_BLK_SIZE_512_MASK);
698
699         /*
700          * Send block read command
701          */
702         Status = XSdPs_CmdTransfer(InstancePtr, CMD18, Arg, BlkCnt);
703         if (Status != XST_SUCCESS) {
704                 Status = XST_FAILURE;
705                 goto RETURN_PATH;
706         }
707
708         /*
709          * Check for transfer complete
710          */
711         do {
712                 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
713                                         XSDPS_NORM_INTR_STS_OFFSET);
714                 if (StatusReg & XSDPS_INTR_ERR_MASK) {
715                         /*
716                          * Write to clear error bits
717                          */
718                         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
719                                         XSDPS_ERR_INTR_STS_OFFSET,
720                                         XSDPS_ERROR_INTR_ALL_MASK);
721                         Status = XST_FAILURE;
722                         goto RETURN_PATH;
723                 }
724         } while((StatusReg & XSDPS_INTR_TC_MASK) == 0);
725
726         /*
727          * Write to clear bit
728          */
729         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
730                         XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
731         Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
732                         XSDPS_RESP0_OFFSET);
733
734         Status = XST_SUCCESS;
735
736         RETURN_PATH:
737         return Status;
738 }
739
740 /*****************************************************************************/
741 /**
742 * This function performs SD write in polled mode.
743 *
744 * @param        InstancePtr is a pointer to the instance to be worked on.
745 * @param        Arg is the address passed by the user that is to be sent as
746 *               argument along with the command.
747 * @param        BlkCnt - Block count passed by the user.
748 * @param        Buff - Pointer to the data buffer for a DMA transfer.
749 *
750 * @return
751 *               - XST_SUCCESS if initialization was successful
752 *               - XST_FAILURE if failure - could be because another transfer
753 *               is in progress or command or data inhibit is set
754 *
755 ******************************************************************************/
756 int XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
757 {
758         u32 Status;
759         u32 PresentStateReg;
760         u32 StatusReg;
761
762         if(InstancePtr->Config.CardDetect) {
763                 /*
764                  * Check status to ensure card is initialized
765                  */
766                 PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
767                                 XSDPS_PRES_STATE_OFFSET);
768                 if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0) {
769                         Status = XST_FAILURE;
770                         goto RETURN_PATH;
771                 }
772         }
773
774         /*
775          * Set block size to 512 if not already set
776          */
777         if( XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
778                         XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {
779                 Status = XSdPs_SetBlkSize(InstancePtr,
780                         XSDPS_BLK_SIZE_512_MASK);
781                 if (Status != XST_SUCCESS) {
782                         Status = XST_FAILURE;
783                         goto RETURN_PATH;
784                 }
785
786         }
787
788         XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
789         Xil_DCacheFlushRange(Buff, BlkCnt * XSDPS_BLK_SIZE_512_MASK);
790
791         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
792                         XSDPS_XFER_MODE_OFFSET,
793                         XSDPS_TM_AUTO_CMD12_EN_MASK |
794                         XSDPS_TM_BLK_CNT_EN_MASK |
795                         XSDPS_TM_MUL_SIN_BLK_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
796
797         /*
798          * Send block write command
799          */
800         Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, BlkCnt);
801         if (Status != XST_SUCCESS) {
802                 Status = XST_FAILURE;
803                 goto RETURN_PATH;
804         }
805
806         /*
807          * Check for transfer complete
808          * Polling for response for now
809          */
810         do {
811                 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
812                                         XSDPS_NORM_INTR_STS_OFFSET);
813                 if (StatusReg & XSDPS_INTR_ERR_MASK) {
814                         /*
815                          * Write to clear error bits
816                          */
817                         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
818                                         XSDPS_ERR_INTR_STS_OFFSET,
819                                         XSDPS_ERROR_INTR_ALL_MASK);
820                         Status = XST_FAILURE;
821                         goto RETURN_PATH;
822                 }
823         } while((StatusReg & XSDPS_INTR_TC_MASK) == 0);
824
825         /*
826          * Write to clear bit
827          */
828         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
829                         XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
830
831         Status = XST_SUCCESS;
832
833         RETURN_PATH:
834                 return Status;
835 }
836
837 /*****************************************************************************/
838 /**
839 *
840 * Selects card and sets default block size
841 *
842 *
843 * @param        InstancePtr is a pointer to the XSdPs instance.
844 *
845 * @return
846 *               - XST_SUCCESS if successful.
847 *               - XST_FAILURE if fail.
848 *
849 * @note         None.
850 *
851 ******************************************************************************/
852 int XSdPs_Select_Card (XSdPs *InstancePtr)
853 {
854         u32 Status = 0;
855
856         /*
857          * Send CMD7 - Select card
858          */
859         Status = XSdPs_CmdTransfer(InstancePtr, CMD7,
860                         InstancePtr->RelCardAddr, 0);
861         if (Status != XST_SUCCESS) {
862                 Status = XST_FAILURE;
863                 goto RETURN_PATH;
864         }
865
866         Status = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
867                         XSDPS_RESP0_OFFSET);
868
869         /*
870          * Set default block size
871          */
872         Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK);
873         if (Status != XST_SUCCESS) {
874                 Status = XST_FAILURE;
875                 goto RETURN_PATH;
876         }
877
878         Status = XST_SUCCESS;
879
880         RETURN_PATH:
881                 return Status;
882
883 }
884
885 /*****************************************************************************/
886 /**
887 *
888 * API to setup ADMA2 descriptor table
889 *
890 *
891 * @param        InstancePtr is a pointer to the XSdPs instance.
892 * @param        BlkCnt - block count.
893 * @param        Buff pointer to data buffer.
894 *
895 * @return       None
896 *
897 * @note         None.
898 *
899 ******************************************************************************/
900 void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
901 {
902         u32 TotalDescLines = 0;
903         u32 DescNum = 0;
904         u32 BlkSize = 0;
905
906         /*
907          * Setup ADMA2 - Write descriptor table and point ADMA SAR to it
908          */
909         BlkSize = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
910                                         XSDPS_BLK_SIZE_OFFSET);
911         BlkSize = BlkSize & XSDPS_BLK_SIZE_MASK;
912
913         if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
914
915                 TotalDescLines = 1;
916
917         }else {
918
919                 TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
920                 if ((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH)
921                         TotalDescLines += 1;
922
923         }
924
925         for (DescNum = 0; DescNum < (TotalDescLines-1); DescNum++) {
926                 InstancePtr->Adma2_DescrTbl[DescNum].Address =
927                                 (u32)(Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
928                 InstancePtr->Adma2_DescrTbl[DescNum].Attribute =
929                                 XSDPS_DESC_TRAN | XSDPS_DESC_VALID;
930                 /*
931                  * This will write '0' to length field which indicates 65536
932                  */
933                 InstancePtr->Adma2_DescrTbl[DescNum].Length =
934                                 (u16)XSDPS_DESC_MAX_LENGTH;
935         }
936
937         InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Address =
938                         (u32)(Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
939
940         InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Attribute =
941                         XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
942
943         InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Length =
944                         (BlkCnt*BlkSize) - (DescNum*XSDPS_DESC_MAX_LENGTH);
945
946
947         XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
948                         (u32)&(InstancePtr->Adma2_DescrTbl[0]));
949
950         Xil_DCacheFlushRange(&(InstancePtr->Adma2_DescrTbl[0]),
951                         sizeof(XSdPs_Adma2Descriptor) * 32);
952
953 }
954
955 /*****************************************************************************/
956 /**
957 * Mmc initialization is done in this function
958 *
959 *
960 * @param        InstancePtr is a pointer to the instance to be worked on.
961 *
962 * @return
963 *               - XST_SUCCESS if initialization was successful
964 *               - XST_FAILURE if failure - could be because
965 *                       a) MMC is already initialized
966 *                       b) There is no card inserted
967 *                       c) One of the steps (commands) in the initialization
968 *                          cycle failed
969 * @note         This function initializes the SD card by following its
970 *               initialization and identification state diagram.
971 *               CMD0 is sent to reset card.
972 *               CMD1 sent to identify voltage and high capacity support
973 *               CMD2 and CMD3 are sent to obtain Card ID and
974 *               Relative card address respectively.
975 *               CMD9 is sent to read the card specific data.
976 *
977 ******************************************************************************/
978 int XSdPs_MmcCardInitialize(XSdPs *InstancePtr)
979 {
980         u32 PresentStateReg;
981         u32 Status;
982         u32 RespOCR = 0x0;
983         u32 CSD[4];
984
985         Xil_AssertNonvoid(InstancePtr != NULL);
986         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
987
988         if(InstancePtr->Config.CardDetect) {
989                 /*
990                  * Check the present state register to make sure
991                  * card is inserted and detected by host controller
992                  */
993                 PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
994                                 XSDPS_PRES_STATE_OFFSET);
995                 if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0) {
996                         Status = XST_FAILURE;
997                         goto RETURN_PATH;
998                 }
999         }
1000
1001         /*
1002          * 74 CLK delay after card is powered up, before the first command.
1003          */
1004
1005 #ifdef __arm__
1006
1007         usleep(XSDPS_INIT_DELAY);
1008
1009 #endif
1010
1011 #ifdef __MICROBLAZE__
1012
1013         /* 2 msec delay */
1014         MB_Sleep(2);
1015
1016 #endif
1017
1018         /*
1019          * CMD0 no response expected
1020          */
1021         Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0, 0);
1022         if (Status != XST_SUCCESS) {
1023                 Status = XST_FAILURE;
1024                 goto RETURN_PATH;
1025         }
1026
1027         InstancePtr->CardType = CT_MMC;
1028         RespOCR = 0;
1029         /*
1030          * Send CMD1 while card is still busy with power up
1031          */
1032         while ((RespOCR & XSDPS_RESPOCR_READY) == 0) {
1033
1034                 /*
1035                  * Host High Capacity support & High volage window
1036                  */
1037                 Status = XSdPs_CmdTransfer(InstancePtr, CMD1,
1038                                 XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0);
1039                 if (Status != XST_SUCCESS) {
1040                         Status = XST_FAILURE;
1041                         goto RETURN_PATH;
1042                 }
1043
1044                 /*
1045                  * Response with card capacity
1046                  */
1047                 RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
1048                                 XSDPS_RESP0_OFFSET);
1049
1050         }
1051
1052         /*
1053          * Update HCS support flag based on card capacity response
1054          */
1055         if (RespOCR & XSDPS_ACMD41_HCS)
1056                 InstancePtr->HCS = 1;
1057
1058         /*
1059          * CMD2 for Card ID
1060          */
1061         Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0, 0);
1062         if (Status != XST_SUCCESS) {
1063                 Status = XST_FAILURE;
1064                 goto RETURN_PATH;
1065         }
1066
1067         InstancePtr->CardID[0] =
1068                         XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1069                         XSDPS_RESP0_OFFSET);
1070         InstancePtr->CardID[1] =
1071                         XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1072                         XSDPS_RESP1_OFFSET);
1073         InstancePtr->CardID[2] =
1074                         XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1075                         XSDPS_RESP2_OFFSET);
1076         InstancePtr->CardID[3] =
1077                         XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
1078                         XSDPS_RESP3_OFFSET);
1079
1080         Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0, 0);
1081         if (Status != XST_SUCCESS) {
1082                 Status = XST_FAILURE;
1083                 goto RETURN_PATH;
1084         }
1085
1086         /*
1087          * Relative card address is stored as the upper 16 bits
1088          * This is to avoid shifting when sending commands
1089          */
1090         InstancePtr->RelCardAddr =
1091                         XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
1092                                 XSDPS_RESP0_OFFSET) & 0xFFFF0000;
1093
1094         Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0);
1095         if (Status != XST_SUCCESS) {
1096                 Status = XST_FAILURE;
1097                 goto RETURN_PATH;
1098         }
1099
1100         /*
1101          * Card specific data is read.
1102          * Currently not used for any operation.
1103          */
1104         CSD[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
1105                         XSDPS_RESP0_OFFSET);
1106         CSD[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
1107                         XSDPS_RESP1_OFFSET);
1108         CSD[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
1109                         XSDPS_RESP2_OFFSET);
1110         CSD[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
1111                         XSDPS_RESP3_OFFSET);
1112
1113         Status = XST_SUCCESS;
1114
1115 RETURN_PATH:
1116         return Status;
1117
1118 }