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