]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/Zynq/xsdps.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-Plus-FAT / portable / Zynq / xsdps.c
1 /******************************************************************************\r
2 *\r
3 * Copyright (C) 2013 - 2015 Xilinx, Inc.  All rights reserved.\r
4 *\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy\r
6 * of this software and associated documentation files (the "Software"), to deal\r
7 * in the Software without restriction, including without limitation the rights\r
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
9 * copies of the Software, and to permit persons to whom the Software is\r
10 * furnished to do so, subject to the following conditions:\r
11 *\r
12 * The above copyright notice and this permission notice shall be included in\r
13 * all copies or substantial portions of the Software.\r
14 *\r
15 * Use of the Software is limited solely to applications:\r
16 * (a) running on a Xilinx device, or\r
17 * (b) that interact with a Xilinx device through a bus or interconnect.\r
18 *\r
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\r
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF\r
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
25 * SOFTWARE.\r
26 *\r
27 * Except as contained in this notice, the name of the Xilinx shall not be used\r
28 * in advertising or otherwise to promote the sale, use or other dealings in\r
29 * this Software without prior written authorization from Xilinx.\r
30 *\r
31 ******************************************************************************/\r
32 /*****************************************************************************/\r
33 /**\r
34 *\r
35 * @file xsdps.c\r
36 * @addtogroup sdps_v2_5\r
37 * @{\r
38 *\r
39 * Contains the interface functions of the XSdPs driver.\r
40 * See xsdps.h for a detailed description of the device and driver.\r
41 *\r
42 * <pre>\r
43 * MODIFICATION HISTORY:\r
44 *\r
45 * Ver   Who    Date     Changes\r
46 * ----- ---    -------- -----------------------------------------------\r
47 * 1.00a hk/sg  10/17/13 Initial release\r
48 * 2.0   hk     12/13/13 Added check for arm to use sleep.h and its API's\r
49 * 2.1   hk     04/18/14 Add sleep for microblaze designs. CR# 781117.\r
50 * 2.2   hk     07/28/14 Make changes to enable use of data cache.\r
51 * 2.3   sk     09/23/14 Send command for relative card address\r
52 *                       when re-initialization is done.CR# 819614.\r
53 *                                               Use XSdPs_Change_ClkFreq API whenever changing\r
54 *                                               clock.CR# 816586.\r
55 * 2.4   sk         12/04/14 Added support for micro SD without\r
56 *                                               WP/CD. CR# 810655.\r
57 *                                               Checked for DAT Inhibit mask instead of CMD\r
58 *                                               Inhibit mask in Cmd Transfer API.\r
59 *                                               Added Support for SD Card v1.0\r
60 * 2.5   sg         07/09/15 Added SD 3.0 features\r
61 *       kvn    07/15/15 Modified the code according to MISRAC-2012.\r
62 * 2.6   sk     10/12/15 Added support for SD card v1.0 CR# 840601.\r
63 * </pre>\r
64 *\r
65 ******************************************************************************/\r
66 \r
67 /***************************** Include Files *********************************/\r
68 #include "xsdps.h"\r
69 #include "xsdps_info.h"\r
70 #include "xil_cache.h"\r
71 \r
72 /*\r
73  * The header sleep.h and API usleep() can only be used with an arm design.\r
74  * MB_Sleep() is used for microblaze design.\r
75  */\r
76 #ifdef __arm__\r
77 \r
78 #include "sleep.h"\r
79 \r
80 #endif\r
81 \r
82 #ifdef __MICROBLAZE__\r
83 \r
84 #include "microblaze_sleep.h"\r
85 \r
86 #endif\r
87 \r
88 #include <FreeRTOS.h>\r
89 #include "task.h"\r
90 \r
91 #include "FreeRTOSFATConfig.h"\r
92 #include "uncached_memory.h"\r
93 \r
94 #include "hr_gettime.h"\r
95 \r
96 /************************** Constant Definitions *****************************/\r
97 #define XSDPS_CMD8_VOL_PATTERN  0x1AAU\r
98 #define XSDPS_RESPOCR_READY     0x80000000U\r
99 #define XSDPS_ACMD41_HCS        0x40000000U\r
100 #define XSDPS_ACMD41_3V3        0x00300000U\r
101 #define XSDPS_CMD1_HIGH_VOL     0x00FF8000U\r
102 #define XSDPS_CMD1_DUAL_VOL     0x00FF8010U\r
103 #define HIGH_SPEED_SUPPORT      0x2U\r
104 #define WIDTH_4_BIT_SUPPORT     0x4U\r
105 #define SD_CLK_25_MHZ           25000000U\r
106 #define SD_CLK_26_MHZ           26000000U\r
107 #define EXT_CSD_DEVICE_TYPE_BYTE        196U\r
108 #define EXT_CSD_DEVICE_TYPE_HIGH_SPEED                  0x2U\r
109 #define EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED  0x4U\r
110 #define EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED  0x8U\r
111 #define EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200               0x10U\r
112 #define EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200               0x20U\r
113 \r
114 /* Note: Remove this once fixed */\r
115 #define UHS_BROKEN\r
116 \r
117 #ifndef ffconfigWRITE_PAUSE_USEC\r
118         #define ffconfigWRITE_PAUSE_USEC        500UL\r
119 #endif\r
120 \r
121 /**************************** Type Definitions *******************************/\r
122 \r
123 \r
124 /************************** Function Prototypes ******************************/\r
125 u32 XSdPs_FrameCmd(XSdPs *InstancePtr, u32 Cmd);\r
126 s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt);\r
127 void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff);\r
128 extern s32 XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode);\r
129 static s32 XSdPs_IdentifyCard(XSdPs *InstancePtr);\r
130 #ifndef UHS_BROKEN\r
131         static s32 XSdPs_Switch_Voltage(XSdPs *InstancePtr);\r
132 #endif\r
133 \r
134 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )\r
135         /* Declared in ff_sddisk.c :\r
136         Function will sleep and get interrupted on a change of\r
137         the status register.  It will loop until:\r
138                 1. Expected bit (ulMask) becomes high\r
139                 2. Time-out reached (normally 2 seconds)\r
140         */\r
141         extern u32 XSdPs_WaitInterrupt( XSdPs *InstancePtr, u32 ulMask, u32 ulWait );\r
142         /* Clear the interrupt before using it. */\r
143         extern void XSdPs_ClearInterrupt( XSdPs *InstancePtr );\r
144 #else\r
145         #error Please define ffconfigSDIO_DRIVER_USES_INTERRUPT\r
146 #endif\r
147 \r
148 /*****************************************************************************/\r
149 /**\r
150 *\r
151 * Initializes a specific XSdPs instance such that the driver is ready to use.\r
152 *\r
153 *\r
154 * @param        InstancePtr is a pointer to the XSdPs instance.\r
155 * @param        ConfigPtr is a reference to a structure containing information\r
156 *               about a specific SD device. This function initializes an\r
157 *               InstancePtr object for a specific device specified by the\r
158 *               contents of Config.\r
159 * @param        EffectiveAddr is the device base address in the virtual memory\r
160 *               address space. The caller is responsible for keeping the address\r
161 *               mapping from EffectiveAddr to the device physical base address\r
162 *               unchanged once this function is invoked. Unexpected errors may\r
163 *               occur if the address mapping changes after this function is\r
164 *               called. If address translation is not used, use\r
165 *               ConfigPtr->Config.BaseAddress for this device.\r
166 *\r
167 * @return\r
168 *               - XST_SUCCESS if successful.\r
169 *               - XST_DEVICE_IS_STARTED if the device is already started.\r
170 *               It must be stopped to re-initialize.\r
171 *\r
172 * @note         This function initializes the host controller.\r
173 *               Initial clock of 400KHz is set.\r
174 *               Voltage of 3.3V is selected as that is supported by host.\r
175 *               Interrupts status is enabled and signal disabled by default.\r
176 *               Default data direction is card to host and\r
177 *               32 bit ADMA2 is selected. Defualt Block size is 512 bytes.\r
178 *\r
179 ******************************************************************************/\r
180 s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,\r
181                                 u32 EffectiveAddr)\r
182 {\r
183         s32 Status;\r
184         u8 PowerLevel;\r
185 \r
186         Xil_AssertNonvoid(InstancePtr != NULL);\r
187         Xil_AssertNonvoid(ConfigPtr != NULL);\r
188 \r
189         /* Set some default values. */\r
190         InstancePtr->Config.BaseAddress = EffectiveAddr;\r
191         InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;\r
192         InstancePtr->IsReady = XIL_COMPONENT_IS_READY;\r
193         InstancePtr->Config.CardDetect =  ConfigPtr->CardDetect;\r
194         InstancePtr->Config.WriteProtect =  ConfigPtr->WriteProtect;\r
195 \r
196         /* Disable bus power */\r
197         XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,\r
198                         XSDPS_POWER_CTRL_OFFSET, 0U);\r
199 \r
200         vTaskDelay( pdMS_TO_TICKS( 1000UL ) );\r
201         /* "Software reset for all" is initiated */\r
202         XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET,\r
203                         XSDPS_SWRST_ALL_MASK);\r
204 \r
205         /*\r
206          * Proceed with initialization only after reset is complete\r
207          */\r
208         while (XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,\r
209                         XSDPS_SW_RST_OFFSET) & XSDPS_SWRST_ALL_MASK);\r
210         /* Host Controller version is read. */\r
211          InstancePtr->HC_Version =\r
212                         (u8)(XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,\r
213                         XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK);\r
214 \r
215         /*\r
216          * Read capabilities register and update it in Instance pointer.\r
217          * It is sufficient to read this once on power on.\r
218          */\r
219         InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
220                                                 XSDPS_CAPS_OFFSET);\r
221 \r
222         /* Select voltage and enable bus power. */\r
223         XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,\r
224                         XSDPS_POWER_CTRL_OFFSET,\r
225                         XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK);\r
226 \r
227         /* Change the clock frequency to 400 KHz */\r
228         Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_400_KHZ);\r
229         if (Status != XST_SUCCESS) {\r
230                 Status = XST_FAILURE;\r
231                 goto RETURN_PATH ;\r
232         }\r
233 \r
234     if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V3_MASK) != 0U) {\r
235                 PowerLevel = XSDPS_PC_BUS_VSEL_3V3_MASK;\r
236         } else if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V0_MASK) != 0U) {\r
237                 PowerLevel = XSDPS_PC_BUS_VSEL_3V0_MASK;\r
238         } else if ((InstancePtr->Host_Caps & XSDPS_CAP_VOLT_1V8_MASK) != 0U) {\r
239                 PowerLevel = XSDPS_PC_BUS_VSEL_1V8_MASK;\r
240         } else {\r
241                 PowerLevel = 0U;\r
242         }\r
243 \r
244         /* Select voltage based on capability and enable bus power. */\r
245         XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,\r
246                         XSDPS_POWER_CTRL_OFFSET,\r
247                         PowerLevel | XSDPS_PC_BUS_PWR_MASK);\r
248         /* Enable ADMA2 in 64bit mode. */\r
249         XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,\r
250                         XSDPS_HOST_CTRL1_OFFSET,\r
251                         XSDPS_HC_DMA_ADMA2_32_MASK);\r
252 \r
253         /* Enable all interrupt status except card interrupt initially */\r
254         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
255                         XSDPS_NORM_INTR_STS_EN_OFFSET,\r
256                         XSDPS_NORM_INTR_ALL_MASK & (~XSDPS_INTR_CARD_MASK));\r
257 \r
258         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
259                         XSDPS_ERR_INTR_STS_EN_OFFSET,\r
260                         XSDPS_ERROR_INTR_ALL_MASK);\r
261 \r
262         /* Disable all interrupt signals by default. */\r
263         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
264                         XSDPS_NORM_INTR_SIG_EN_OFFSET, 0x0U);\r
265         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
266                         XSDPS_ERR_INTR_SIG_EN_OFFSET, 0x0U);\r
267 \r
268         /*\r
269          * Transfer mode register - default value\r
270          * DMA enabled, block count enabled, data direction card to host(read)\r
271          */\r
272         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
273                         XSDPS_XFER_MODE_OFFSET,\r
274                         XSDPS_TM_DMA_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK |\r
275                         XSDPS_TM_DAT_DIR_SEL_MASK);\r
276 \r
277         /* Set block size to 512 by default */\r
278         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
279                         XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK);\r
280 \r
281         Status = XST_SUCCESS;\r
282 \r
283 RETURN_PATH:\r
284         return Status;\r
285 \r
286 }\r
287 \r
288 /*****************************************************************************/\r
289 /**\r
290 * SD initialization is done in this function\r
291 *\r
292 *\r
293 * @param        InstancePtr is a pointer to the instance to be worked on.\r
294 *\r
295 * @return\r
296 *               - XST_SUCCESS if initialization was successful\r
297 *               - XST_FAILURE if failure - could be because\r
298 *                       a) SD is already initialized\r
299 *                       b) There is no card inserted\r
300 *                       c) One of the steps (commands) in the\r
301                            initialization cycle failed\r
302 *\r
303 * @note         This function initializes the SD card by following its\r
304 *               initialization and identification state diagram.\r
305 *               CMD0 is sent to reset card.\r
306 *               CMD8 and ACDM41 are sent to identify voltage and\r
307 *               high capacity support\r
308 *               CMD2 and CMD3 are sent to obtain Card ID and\r
309 *               Relative card address respectively.\r
310 *               CMD9 is sent to read the card specific data.\r
311 *\r
312 ******************************************************************************/\r
313 s32 XSdPs_SdCardInitialize(XSdPs *InstancePtr)\r
314 {\r
315         u32 PresentStateReg;\r
316         s32 Status;\r
317         u32 RespOCR;\r
318         u32 CSD[4];\r
319         u32 Arg;\r
320         u8 ReadReg;\r
321 \r
322         Xil_AssertNonvoid(InstancePtr != NULL);\r
323         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);\r
324 \r
325         if(InstancePtr->Config.CardDetect != 0U) {\r
326                 /*\r
327                  * Check the present state register to make sure\r
328                  * card is inserted and detected by host controller\r
329                  */\r
330                 PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
331                                 XSDPS_PRES_STATE_OFFSET);\r
332                 if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0U)        {\r
333                         Status = XST_FAILURE;\r
334                         goto RETURN_PATH;\r
335                 }\r
336         }\r
337 \r
338         /* CMD0 no response expected */\r
339         Status = XSdPs_CmdTransfer(InstancePtr, (u32)CMD0, 0U, 0U);\r
340         if (Status != XST_SUCCESS) {\r
341                 Status = XST_FAILURE;\r
342                 goto RETURN_PATH;\r
343         }\r
344 \r
345         /*\r
346          * CMD8; response expected\r
347          * 0x1AA - Supply Voltage 2.7 - 3.6V and AA is pattern\r
348          */\r
349         Status = XSdPs_CmdTransfer(InstancePtr, CMD8,\r
350                         XSDPS_CMD8_VOL_PATTERN, 0U);\r
351         if ((Status != XST_SUCCESS) && (Status != XSDPS_CT_ERROR)) {\r
352                 Status = XST_FAILURE;\r
353                 goto RETURN_PATH;\r
354         }\r
355 \r
356         if (Status == XSDPS_CT_ERROR) {\r
357                  /* "Software reset for all" is initiated */\r
358                 XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET,\r
359                                 XSDPS_SWRST_CMD_LINE_MASK);\r
360 \r
361                 /* Proceed with initialization only after reset is complete */\r
362                 ReadReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,\r
363                                                 XSDPS_SW_RST_OFFSET);\r
364                 while ((ReadReg & XSDPS_SWRST_CMD_LINE_MASK) != 0U) {\r
365                         ReadReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,\r
366                                                 XSDPS_SW_RST_OFFSET);\r
367                 }\r
368         }\r
369 \r
370         RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
371                                                 XSDPS_RESP0_OFFSET);\r
372         if (RespOCR != XSDPS_CMD8_VOL_PATTERN) {\r
373                 InstancePtr->Card_Version = XSDPS_SD_VER_1_0;\r
374         }\r
375         else {\r
376                 InstancePtr->Card_Version = XSDPS_SD_VER_2_0;\r
377         }\r
378 \r
379         RespOCR = 0U;\r
380         /* Send ACMD41 while card is still busy with power up */\r
381         while ((RespOCR & XSDPS_RESPOCR_READY) == 0U) {\r
382                 Status = XSdPs_CmdTransfer(InstancePtr, CMD55, 0U, 0U);\r
383                 if (Status != XST_SUCCESS) {\r
384                         Status = XST_FAILURE;\r
385                         goto RETURN_PATH;\r
386                 }\r
387 \r
388         Arg = XSDPS_ACMD41_HCS | XSDPS_ACMD41_3V3 | (0x1FFU << 15U);\r
389                 if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {\r
390                     Arg |= XSDPS_OCR_S18;\r
391                 }\r
392 \r
393                 /* 0x40300000 - Host High Capacity support & 3.3V window */\r
394                 Status = XSdPs_CmdTransfer(InstancePtr, ACMD41,\r
395                                 Arg, 0U);\r
396                 if (Status != XST_SUCCESS) {\r
397                         Status = XST_FAILURE;\r
398                         goto RETURN_PATH;\r
399                 }\r
400 \r
401                 /* Response with card capacity */\r
402                 RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
403                                 XSDPS_RESP0_OFFSET);\r
404 \r
405         }\r
406 \r
407         /* Update HCS support flag based on card capacity response */\r
408         if ((RespOCR & XSDPS_ACMD41_HCS) != 0U) {\r
409                 InstancePtr->HCS = 1U;\r
410         }\r
411 \r
412         /* There is no support to switch to 1.8V and use UHS mode on 1.0 silicon */\r
413 #ifndef UHS_BROKEN\r
414     if ((RespOCR & XSDPS_OCR_S18) != 0U) {\r
415                 InstancePtr->Switch1v8 = 1U;\r
416                 Status = XSdPs_Switch_Voltage(InstancePtr);\r
417                 if (Status != XST_SUCCESS) {\r
418                         Status = XST_FAILURE;\r
419                         goto RETURN_PATH;\r
420                 }\r
421 \r
422         }\r
423 #endif\r
424 \r
425         /* CMD2 for Card ID */\r
426         Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0U, 0U);\r
427         if (Status != XST_SUCCESS) {\r
428                 Status = XST_FAILURE;\r
429                 goto RETURN_PATH;\r
430         }\r
431 \r
432         InstancePtr->CardID[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET);\r
433         InstancePtr->CardID[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP1_OFFSET);\r
434         InstancePtr->CardID[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP2_OFFSET);\r
435         InstancePtr->CardID[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP3_OFFSET);\r
436 \r
437         do\r
438         {\r
439                 Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0U, 0U);\r
440                 if (Status != XST_SUCCESS) {\r
441                         Status = XST_FAILURE;\r
442                         goto RETURN_PATH;\r
443                 }\r
444 \r
445                 /*\r
446                  * Relative card address is stored as the upper 16 bits\r
447                  * This is to avoid shifting when sending commands\r
448                  */\r
449                 InstancePtr->RelCardAddr =\r
450                                 XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
451                                         XSDPS_RESP0_OFFSET) & 0xFFFF0000U;\r
452         } while (InstancePtr->RelCardAddr == 0U);\r
453 \r
454         Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0U);\r
455         if (Status != XST_SUCCESS) {\r
456                 Status = XST_FAILURE;\r
457                 goto RETURN_PATH;\r
458         }\r
459         {\r
460         u32 resp[4];\r
461                 /* Put the CSD data in a standard order and analyse them */\r
462                 resp[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET);\r
463                 resp[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP1_OFFSET);\r
464                 resp[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP2_OFFSET);\r
465                 resp[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_RESP3_OFFSET);\r
466                 CSD[0] = ( resp[3] << 8 ) | ( resp[2] >> 24 );\r
467                 CSD[1] = ( resp[2] << 8 ) | ( resp[1] >> 24 );\r
468                 CSD[2] = ( resp[1] << 8 ) | ( resp[0] >> 24 );\r
469                 CSD[3] = ( resp[0] << 8 );\r
470                 FF_PRINTF( "CSD %08lX %08lX %08lX %08lX\n", CSD[0], CSD[1], CSD[2], CSD[3]);\r
471 \r
472                 sd_decode_csd( &myCSD, ( u32*) CSD );\r
473         }\r
474 \r
475         {\r
476         u32 resp[4];\r
477                 /* When analysing the Card ID (CID), a field in CSD must be known: mmca_vsn. */\r
478                 resp[0] = ( InstancePtr->CardID[3] >> 8 );\r
479                 resp[1] = ( InstancePtr->CardID[3] << 24 ) | ( InstancePtr->CardID[2] >> 8 );\r
480                 resp[2] = ( InstancePtr->CardID[2] << 24 ) | ( InstancePtr->CardID[1] >> 8 );\r
481                 resp[3] = ( InstancePtr->CardID[1] << 24 ) | ( InstancePtr->CardID[0] >> 8 );\r
482                 FF_PRINTF( "CID %08X %08X %08X %08X\n",\r
483                         ( unsigned )resp[0],\r
484                         ( unsigned )resp[1],\r
485                         ( unsigned )resp[2],\r
486                         ( unsigned )resp[3]);\r
487 \r
488                 mmc_decode_cid( &myCSD, &myCID, resp );\r
489         }\r
490 \r
491         Status = XST_SUCCESS;\r
492 \r
493 RETURN_PATH:\r
494         return Status;\r
495 \r
496 }\r
497 \r
498 /*\r
499  * This driver will hang if the SD-card gets extracted while doing i/o.\r
500  * The driver waits for either 'XSDPS_INTR_CC_MASK', 'XSDPS_INTR_TC_MASK',\r
501  * or 'XSDPS_INTR_ERR_MASK'.\r
502  * None of the bits will ever get set and the program gets stuck here.\r
503  * The number of polls will be counted, and when a high number is reached,\r
504  * an error will be returned.\r
505  * This time-out will happen after about 2 seconds.\r
506  *\r
507  * A better solution is to define 'ffconfigSDIO_DRIVER_USES_INTERRUPT'. The CPU\r
508  * won't poll and the task will block while the MMC peripheral is working.\r
509  */\r
510 \r
511 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT == 0 )\r
512         #define POLLCOUNT_MAX   0x800000\r
513 #endif\r
514 \r
515 /*****************************************************************************/\r
516 /**\r
517 *\r
518 * Initialize Card with Identification mode sequence\r
519 *\r
520 *\r
521 * @param        InstancePtr is a pointer to the instance to be worked on.\r
522 *\r
523 * @return\r
524 *               - XST_SUCCESS if initialization was successful\r
525 *               - XST_FAILURE if failure - could be because\r
526 *                       a) SD is already initialized\r
527 *                       b) There is no card inserted\r
528 *                       c) One of the steps (commands) in the\r
529 *                          initialization cycle failed\r
530 *\r
531 *\r
532 ******************************************************************************/\r
533 s32 XSdPs_CardInitialize(XSdPs *InstancePtr)\r
534 {\r
535 #ifdef __ICCARM__\r
536 #pragma data_alignment = 32\r
537 static u8 ExtCsd[512];\r
538 #pragma data_alignment = 4\r
539 #else\r
540 static u8 ExtCsd[512] __attribute__ ((aligned(32)));\r
541 #endif\r
542         u8 SCR[8] = { 0U };\r
543         u8 ReadBuff[64] = { 0U };\r
544         s32 Status;\r
545 \r
546         Xil_AssertNonvoid(InstancePtr != NULL);\r
547         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);\r
548 \r
549         /* Default settings */\r
550         InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;\r
551         InstancePtr->CardType = XSDPS_CARD_SD;\r
552         InstancePtr->Switch1v8 = 0U;\r
553         InstancePtr->BusSpeed = XSDPS_CLK_400_KHZ;\r
554 \r
555         if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&\r
556                         ((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)\r
557                         == XSDPS_CAPS_EMB_SLOT)) {\r
558                 InstancePtr->CardType = XSDPS_CHIP_EMMC;\r
559         } else {\r
560                 Status = XSdPs_IdentifyCard(InstancePtr);\r
561                 if (Status == XST_FAILURE) {\r
562                         goto RETURN_PATH;\r
563                 }\r
564         }\r
565 \r
566         if ((InstancePtr->CardType != XSDPS_CARD_SD) &&\r
567                 (InstancePtr->CardType != XSDPS_CARD_MMC) &&\r
568                 (InstancePtr->CardType != XSDPS_CHIP_EMMC)) {\r
569                 Status = XST_FAILURE;\r
570                 goto RETURN_PATH;\r
571         }\r
572 \r
573         if (InstancePtr->CardType == XSDPS_CARD_SD) {\r
574                 Status = XSdPs_SdCardInitialize(InstancePtr);\r
575                 if (Status != XST_SUCCESS) {\r
576                         Status = XST_FAILURE;\r
577                         goto RETURN_PATH;\r
578                 }\r
579 \r
580                 /* Change clock to default clock 25MHz */\r
581                 InstancePtr->BusSpeed = SD_CLK_25_MHZ;\r
582                 Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);\r
583                 if (Status != XST_SUCCESS) {\r
584                         Status = XST_FAILURE;\r
585                         goto RETURN_PATH;\r
586                 }\r
587 \r
588         } else if ((InstancePtr->CardType == XSDPS_CARD_MMC)\r
589                         || (InstancePtr->CardType == XSDPS_CHIP_EMMC)) {\r
590                 Status = XSdPs_MmcCardInitialize(InstancePtr);\r
591                 if (Status != XST_SUCCESS) {\r
592                         Status = XST_FAILURE;\r
593                         goto RETURN_PATH;\r
594                 }\r
595                 /* Change clock to default clock 26MHz */\r
596                 InstancePtr->BusSpeed = SD_CLK_26_MHZ;\r
597                 Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);\r
598                 if (Status != XST_SUCCESS) {\r
599                         Status = XST_FAILURE;\r
600                         goto RETURN_PATH;\r
601                 }\r
602         } else {\r
603                 Status = XST_FAILURE;\r
604                 goto RETURN_PATH;\r
605         }\r
606 \r
607         Status = XSdPs_Select_Card(InstancePtr);\r
608         if (Status != XST_SUCCESS) {\r
609                 Status = XST_FAILURE;\r
610                 goto RETURN_PATH;\r
611         }\r
612 \r
613         if (InstancePtr->CardType == XSDPS_CARD_SD) {\r
614                 /* Pull-up disconnected during data transfer */\r
615                 Status = XSdPs_Pullup(InstancePtr);\r
616                 if (Status != XST_SUCCESS) {\r
617                         Status = XST_FAILURE;\r
618                         goto RETURN_PATH;\r
619                 }\r
620 \r
621                 Status = XSdPs_Get_BusWidth(InstancePtr, SCR);\r
622                 if (Status != XST_SUCCESS) {\r
623                         Status = XST_FAILURE;\r
624                         goto RETURN_PATH;\r
625                 }\r
626 \r
627                 if ((SCR[1] & WIDTH_4_BIT_SUPPORT) != 0U) {\r
628                         Status = XSdPs_Change_BusWidth(InstancePtr);\r
629                         if (Status != XST_SUCCESS) {\r
630                                 Status = XST_FAILURE;\r
631                                 goto RETURN_PATH;\r
632                         }\r
633                 }\r
634 \r
635                 if ((InstancePtr->Switch1v8 != 0U) &&\r
636                                 (InstancePtr->BusWidth == XSDPS_4_BIT_WIDTH)) {\r
637                         /* Set UHS-I SDR104 mode */\r
638                         Status = XSdPs_Uhs_ModeInit(InstancePtr,\r
639                                         XSDPS_UHS_SPEED_MODE_SDR104);\r
640                         if (Status != XST_SUCCESS) {\r
641                                 Status = XST_FAILURE;\r
642                                 goto RETURN_PATH;\r
643                         }\r
644 \r
645                 } else {\r
646 \r
647                         /*\r
648                          * card supports CMD6 when SD_SPEC field in SCR register\r
649                          * indicates that the Physical Layer Specification Version\r
650                          * is 1.10 or later. So for SD v1.0 cmd6 is not supported.\r
651                          */\r
652                         if (SCR[0] != 0U) {\r
653                                 /* Get speed supported by device */\r
654                                 Status = XSdPs_Get_BusSpeed(InstancePtr, ReadBuff);\r
655                                 if (Status != XST_SUCCESS) {\r
656                                         Status = XST_FAILURE;\r
657                                         FF_PRINTF( "SD-card seems OK but 4-bits doesn't work. Dirty contacts ?\n" );\r
658                                         FF_PRINTF( "Or: SD-card has version v1.0 which does not support cmd6 ?\n" );\r
659                                         goto RETURN_PATH;\r
660                                 }\r
661 \r
662                                 /* Check for high speed support */\r
663                                 if ((ReadBuff[13] & HIGH_SPEED_SUPPORT) != 0U) {\r
664                                         Status = XSdPs_Change_BusSpeed(InstancePtr);\r
665                                         if (Status != XST_SUCCESS) {\r
666                                                 Status = XST_FAILURE;\r
667                                                 goto RETURN_PATH;\r
668                                         }\r
669                                 }\r
670                         }\r
671                 }\r
672 \r
673         } else if ((InstancePtr->CardType == XSDPS_CARD_MMC) &&\r
674                                 (InstancePtr->HC_Version == XSDPS_HC_SPEC_V2)) {\r
675 \r
676                 Status = XSdPs_Change_BusWidth(InstancePtr);\r
677                 if (Status != XST_SUCCESS) {\r
678                         Status = XST_FAILURE;\r
679                         goto RETURN_PATH;\r
680                 }\r
681 \r
682                 Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);\r
683                 if (Status != XST_SUCCESS) {\r
684                         Status = XST_FAILURE;\r
685                         goto RETURN_PATH;\r
686                 }\r
687 \r
688                 if (ExtCsd[EXT_CSD_BUS_WIDTH_BYTE] != EXT_CSD_BUS_WIDTH_4_BIT) {\r
689                         Status = XST_FAILURE;\r
690                         goto RETURN_PATH;\r
691                 }\r
692 \r
693                 if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &\r
694                                 EXT_CSD_DEVICE_TYPE_HIGH_SPEED) != 0U) {\r
695                         Status = XSdPs_Change_BusSpeed(InstancePtr);\r
696                         if (Status != XST_SUCCESS) {\r
697                                 Status = XST_FAILURE;\r
698                                 goto RETURN_PATH;\r
699                         }\r
700 \r
701                         Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);\r
702                         if (Status != XST_SUCCESS) {\r
703                                 Status = XST_FAILURE;\r
704                                 goto RETURN_PATH;\r
705                         }\r
706 \r
707                         if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) {\r
708                                 Status = XST_FAILURE;\r
709                                 goto RETURN_PATH;\r
710                         }\r
711                 }\r
712         } else if (InstancePtr->CardType == XSDPS_CHIP_EMMC){\r
713                 /* Change bus width to 8-bit */\r
714                 Status = XSdPs_Change_BusWidth(InstancePtr);\r
715                 if (Status != XST_SUCCESS) {\r
716                         Status = XST_FAILURE;\r
717                         goto RETURN_PATH;\r
718                 }\r
719 \r
720                 /* Get Extended CSD */\r
721                 Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);\r
722                 if (Status != XST_SUCCESS) {\r
723                         Status = XST_FAILURE;\r
724                         goto RETURN_PATH;\r
725                 }\r
726 \r
727                 /* Check for 8-bit support */\r
728                 if (ExtCsd[EXT_CSD_BUS_WIDTH_BYTE] != EXT_CSD_BUS_WIDTH_8_BIT) {\r
729                         Status = XST_FAILURE;\r
730                         goto RETURN_PATH;\r
731                 }\r
732 \r
733                 if ((ExtCsd[EXT_CSD_DEVICE_TYPE_BYTE] &\r
734                                 (EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200 |\r
735                                 EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200)) != 0U) {\r
736                         Status = XSdPs_Change_BusSpeed(InstancePtr);\r
737                         if (Status != XST_SUCCESS) {\r
738                                 Status = XST_FAILURE;\r
739                                 goto RETURN_PATH;\r
740                         }\r
741 \r
742                         Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);\r
743                         if (Status != XST_SUCCESS) {\r
744                                 Status = XST_FAILURE;\r
745                                 goto RETURN_PATH;\r
746                         }\r
747 \r
748                         if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HS200) {\r
749                                 Status = XST_FAILURE;\r
750                                 goto RETURN_PATH;\r
751                         }\r
752                 }\r
753         }\r
754 \r
755         Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK);\r
756         if (Status != XST_SUCCESS) {\r
757                 Status = XST_FAILURE;\r
758                 goto RETURN_PATH;\r
759         }\r
760 \r
761 RETURN_PATH:\r
762         return Status;\r
763 }\r
764 \r
765 /*****************************************************************************/\r
766 /**\r
767 *\r
768 * Identify type of card using CMD0 + CMD1 sequence\r
769 *\r
770 *\r
771 * @param        InstancePtr is a pointer to the XSdPs instance.\r
772 *\r
773 ******************************************************************************/\r
774 static s32 XSdPs_IdentifyCard(XSdPs *InstancePtr)\r
775 {\r
776         s32 Status;\r
777         u8 ReadReg;\r
778 \r
779         Xil_AssertNonvoid(InstancePtr != NULL);\r
780         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);\r
781 \r
782         /* 74 CLK delay after card is powered up, before the first command. */\r
783 #if defined (__arm__) || defined (__aarch64__)\r
784 \r
785         usleep(XSDPS_INIT_DELAY);\r
786 \r
787 #endif\r
788 \r
789 #ifdef __MICROBLAZE__\r
790 \r
791         /* 2 msec delay */\r
792         MB_Sleep(2);\r
793 \r
794 #endif\r
795 \r
796         /* CMD0 no response expected */\r
797         Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0U, 0U);\r
798         if (Status != XST_SUCCESS) {\r
799                 Status = XST_FAILURE;\r
800                 goto RETURN_PATH;\r
801         }\r
802 \r
803         /* Host High Capacity support & High voltage window */\r
804         Status = XSdPs_CmdTransfer(InstancePtr, CMD1,\r
805                         XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);\r
806         if (Status != XST_SUCCESS) {\r
807                 InstancePtr->CardType = XSDPS_CARD_SD;\r
808         } else {\r
809                 InstancePtr->CardType = XSDPS_CARD_MMC;\r
810         }\r
811 \r
812         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
813                         XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);\r
814         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
815                         XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);\r
816 \r
817         /* "Software reset for all" is initiated */\r
818         XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET,\r
819                         XSDPS_SWRST_CMD_LINE_MASK);\r
820 \r
821         /* Proceed with initialization only after reset is complete */\r
822         ReadReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,\r
823                                         XSDPS_SW_RST_OFFSET);\r
824         while ((ReadReg & XSDPS_SWRST_CMD_LINE_MASK) != 0U) {\r
825                 ReadReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,\r
826                                         XSDPS_SW_RST_OFFSET);\r
827         }\r
828 \r
829         Status = XST_SUCCESS;\r
830 \r
831 RETURN_PATH:\r
832         return Status;\r
833 }\r
834 \r
835 /*****************************************************************************/\r
836 /**\r
837 *\r
838 * Switches the SD card voltage from 3v3 to 1v8\r
839 *\r
840 *\r
841 * @param        InstancePtr is a pointer to the XSdPs instance.\r
842 *\r
843 ******************************************************************************/\r
844 #ifndef UHS_BROKEN\r
845 static s32 XSdPs_Switch_Voltage(XSdPs *InstancePtr)\r
846 {\r
847         s32 Status;\r
848         u16 CtrlReg;\r
849         u32 ReadReg;\r
850 \r
851         /* Send switch voltage command */\r
852         Status = XSdPs_CmdTransfer(InstancePtr, CMD11, 0U, 0U);\r
853         if (Status != XST_SUCCESS) {\r
854                 Status = XST_FAILURE;\r
855         }\r
856 \r
857         /* Wait for CMD and DATA line to go low */\r
858         ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
859                                 XSDPS_PRES_STATE_OFFSET);\r
860         while ((ReadReg & (XSDPS_PSR_CMD_SG_LVL_MASK |\r
861                                         XSDPS_PSR_DAT30_SG_LVL_MASK)) != 0U) {\r
862                 ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
863                                         XSDPS_PRES_STATE_OFFSET);\r
864         }\r
865 \r
866         /* Stop the clock */\r
867         CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,\r
868                         XSDPS_CLK_CTRL_OFFSET);\r
869         CtrlReg &= ~(XSDPS_CC_SD_CLK_EN_MASK | XSDPS_CC_INT_CLK_EN_MASK);\r
870         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET,\r
871                         CtrlReg);\r
872 \r
873         /* Wait minimum 5mSec */\r
874 #if defined (__arm__) || defined (__aarch64__)\r
875 \r
876         (void)usleep(5000U);\r
877 \r
878 #endif\r
879 \r
880 #ifdef __MICROBLAZE__\r
881 \r
882         MB_Sleep(5U);\r
883 \r
884 #endif\r
885 \r
886         /* Enabling 1.8V in controller */\r
887         CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,\r
888                         XSDPS_HOST_CTRL2_OFFSET);\r
889         CtrlReg |= XSDPS_HC2_1V8_EN_MASK;\r
890         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_HOST_CTRL2_OFFSET,\r
891                         CtrlReg);\r
892 \r
893         /* Start clock */\r
894         Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_400_KHZ);\r
895         if (Status != XST_SUCCESS) {\r
896                 Status = XST_FAILURE;\r
897                 goto RETURN_PATH;\r
898         }\r
899 \r
900         /* Wait for CMD and DATA line to go high */\r
901         ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
902                                 XSDPS_PRES_STATE_OFFSET);\r
903         while ((ReadReg & (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK))\r
904                         != (XSDPS_PSR_CMD_SG_LVL_MASK | XSDPS_PSR_DAT30_SG_LVL_MASK)) {\r
905                 ReadReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
906                                         XSDPS_PRES_STATE_OFFSET);\r
907         }\r
908 \r
909 RETURN_PATH:\r
910         return Status;\r
911 }\r
912 #endif /* UHS_BROKEN */\r
913 \r
914 s32 XSdPs_Wait_For(XSdPs *InstancePtr, u32 Mask, u32 Wait)\r
915 {\r
916         s32 Status = XST_SUCCESS;\r
917         u32 StatusReg;\r
918 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT == 0 )\r
919         u32 ulPollCount;\r
920 #endif\r
921 \r
922 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )\r
923         StatusReg = XSdPs_WaitInterrupt( InstancePtr, XSDPS_INTR_ERR_MASK | Mask, Wait );\r
924 \r
925         if( ( StatusReg & Mask ) == 0 )\r
926         {\r
927                 Status = XST_FAILURE;\r
928         }\r
929 #else\r
930         /*\r
931          * Check for transfer complete\r
932          * Polling for response for now\r
933          * Limit the time spent here with a simpler counter 'ulPollCount'\r
934          */\r
935         ulPollCount = 0;\r
936         for ( ;; ) {\r
937                 StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,\r
938                                         XSDPS_NORM_INTR_STS_OFFSET);\r
939                 if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {\r
940                         /* Write to clear error bits */\r
941                         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
942                                         XSDPS_ERR_INTR_STS_OFFSET,\r
943                                         XSDPS_ERROR_INTR_ALL_MASK);\r
944                         Status = XST_FAILURE;\r
945                         break;\r
946                 }\r
947                 if((StatusReg & Mask) != 0U) {\r
948                         /* Write to clear bit */\r
949                         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
950                                         XSDPS_NORM_INTR_STS_OFFSET, Mask);\r
951                         /* successful exit */\r
952                         break;\r
953                 }\r
954                 /* Without some protection the code can easily\r
955                 get stuck here if the card is withdrawn. */\r
956                 ulPollCount++;\r
957                 if( ulPollCount == POLLCOUNT_MAX )\r
958                 {\r
959                         Status = XST_FAILURE;\r
960                         break;\r
961                 }\r
962         }\r
963 \r
964 #endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */\r
965 \r
966         return Status;\r
967 }\r
968 \r
969 /*****************************************************************************/\r
970 /**\r
971 \r
972 * This function does SD command generation.\r
973 *\r
974 * @param        InstancePtr is a pointer to the instance to be worked on.\r
975 * @param        Cmd is the command to be sent.\r
976 * @param        Arg is the argument to be sent along with the command.\r
977 *               This could be address or any other information\r
978 * @param        BlkCnt - Block count passed by the user.\r
979 *\r
980 * @return\r
981 *               - XST_SUCCESS if initialization was successful\r
982 *               - XST_FAILURE if failure - could be because another transfer\r
983 *                       is in progress or command or data inhibit is set\r
984 *\r
985 ******************************************************************************/\r
986 s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt)\r
987 {\r
988         u32 PresentStateReg;\r
989         u32 CommandReg;\r
990         s32 Status;\r
991 \r
992         Xil_AssertNonvoid(InstancePtr != NULL);\r
993         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);\r
994 \r
995         /*\r
996          * Check the command inhibit to make sure no other\r
997          * command transfer is in progress\r
998          */\r
999         PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1000                         XSDPS_PRES_STATE_OFFSET);\r
1001         if ((PresentStateReg & XSDPS_PSR_INHIBIT_CMD_MASK) != 0U) {\r
1002                 Status = XST_FAILURE;\r
1003                 goto RETURN_PATH;\r
1004         }\r
1005 \r
1006         /* Write block count register */\r
1007         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
1008                         XSDPS_BLK_CNT_OFFSET, (u16)BlkCnt);\r
1009 \r
1010         XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,\r
1011                         XSDPS_TIMEOUT_CTRL_OFFSET, 0xEU);\r
1012 \r
1013         /* Write argument register */\r
1014         XSdPs_WriteReg(InstancePtr->Config.BaseAddress,\r
1015                         XSDPS_ARGMT_OFFSET, Arg);\r
1016 \r
1017         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
1018                         XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK);\r
1019         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
1020                         XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK);\r
1021         /* Command register is set to trigger transfer of command */\r
1022         CommandReg = XSdPs_FrameCmd(InstancePtr, Cmd);\r
1023 \r
1024         /*\r
1025          * Mask to avoid writing to reserved bits 31-30\r
1026          * This is necessary because 0x80000000 is used  by this software to\r
1027          * distinguish between ACMD and CMD of same number\r
1028          */\r
1029         CommandReg = CommandReg & 0x3FFFU;\r
1030 \r
1031         /* Check for data inhibit in case of command using DAT lines */\r
1032         PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1033                         XSDPS_PRES_STATE_OFFSET);\r
1034         if (((PresentStateReg & (XSDPS_PSR_INHIBIT_DAT_MASK | XSDPS_PSR_INHIBIT_DAT_MASK)) != 0U) &&\r
1035                         ((CommandReg & XSDPS_DAT_PRESENT_SEL_MASK) != 0U)) {\r
1036                 Status = XST_FAILURE;\r
1037                 goto RETURN_PATH;\r
1038         }\r
1039 \r
1040 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )\r
1041         XSdPs_ClearInterrupt( InstancePtr );\r
1042 #endif\r
1043         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CMD_OFFSET,\r
1044                         (u16)CommandReg);\r
1045 \r
1046         Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_CC_MASK, Cmd != CMD1);\r
1047 \r
1048 RETURN_PATH:\r
1049 \r
1050         return Status;\r
1051 \r
1052 }\r
1053 \r
1054 /*****************************************************************************/\r
1055 /**\r
1056 * This function frames the Command register for a particular command.\r
1057 * Note that this generates only the command register value i.e.\r
1058 * the upper 16 bits of the transfer mode and command register.\r
1059 * This value is already shifted to be upper 16 bits and can be directly\r
1060 * OR'ed with transfer mode register value.\r
1061 *\r
1062 * @param        Command to be sent.\r
1063 *\r
1064 * @return       Command register value complete with response type and\r
1065 *               data, CRC and index related flags.\r
1066 *\r
1067 ******************************************************************************/\r
1068 u32 XSdPs_FrameCmd(XSdPs *InstancePtr, u32 Cmd)\r
1069 {\r
1070                 u32 RetVal;\r
1071 \r
1072                 RetVal = Cmd;\r
1073 \r
1074                 switch(Cmd) {\r
1075                 case CMD0:\r
1076                         RetVal |= RESP_NONE;\r
1077                 break;\r
1078                 case CMD1:\r
1079                         RetVal |= RESP_R3;\r
1080                 break;\r
1081                 case CMD2:\r
1082                         RetVal |= RESP_R2;\r
1083                 break;\r
1084                 case CMD3:\r
1085                         RetVal |= RESP_R6;\r
1086                 break;\r
1087                 case CMD4:\r
1088                         RetVal |= RESP_NONE;\r
1089                         break;\r
1090                 case CMD5:\r
1091                         RetVal |= RESP_R1B;\r
1092                 break;\r
1093                 case CMD6:\r
1094                         if (InstancePtr->CardType == XSDPS_CARD_SD) {\r
1095                                 RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;\r
1096                         } else {\r
1097                                 RetVal |= RESP_R1B;\r
1098                         }\r
1099                         break;\r
1100                 case ACMD6:\r
1101                         RetVal |= RESP_R1;\r
1102                 break;\r
1103                 case CMD7:\r
1104                         RetVal |= RESP_R1;\r
1105                 break;\r
1106                 case CMD8:\r
1107                         if (InstancePtr->CardType == XSDPS_CARD_SD) {\r
1108                                 RetVal |= RESP_R1;\r
1109                         } else {\r
1110                                 RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;\r
1111                         }\r
1112                         break;\r
1113                 case CMD9:\r
1114                         RetVal |= RESP_R2;\r
1115                 break;\r
1116                 case CMD11:\r
1117                 case CMD10:\r
1118                 case CMD12:\r
1119                 case ACMD13:\r
1120                 case CMD16:\r
1121                         RetVal |= RESP_R1;\r
1122                 break;\r
1123                 case CMD17:\r
1124                 case CMD18:\r
1125                 case CMD19:\r
1126                 case CMD21:\r
1127                         RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;\r
1128                 break;\r
1129                 case CMD23:\r
1130                 case ACMD23:\r
1131                 case CMD24:\r
1132                 case CMD25:\r
1133                         RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;\r
1134                 case ACMD41:\r
1135                         RetVal |= RESP_R3;\r
1136                 break;\r
1137                 case ACMD42:\r
1138                         RetVal |= RESP_R1;\r
1139                 break;\r
1140                 case ACMD51:\r
1141                         RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;\r
1142                 break;\r
1143                 case CMD52:\r
1144                 case CMD55:\r
1145                         RetVal |= RESP_R1;\r
1146                 break;\r
1147                 case CMD58:\r
1148                 break;\r
1149                 default :\r
1150                         RetVal |= Cmd;\r
1151                 break;\r
1152                 }\r
1153 \r
1154                 return RetVal;\r
1155 }\r
1156 \r
1157 /*****************************************************************************/\r
1158 /**\r
1159 * This function performs SD read in polled mode.\r
1160 *\r
1161 * @param        InstancePtr is a pointer to the instance to be worked on.\r
1162 * @param        Arg is the address passed by the user that is to be sent as\r
1163 *               argument along with the command.\r
1164 * @param        BlkCnt - Block count passed by the user.\r
1165 * @param        Buff - Pointer to the data buffer for a DMA transfer.\r
1166 *\r
1167 * @return\r
1168 *               - XST_SUCCESS if initialization was successful\r
1169 *               - XST_FAILURE if failure - could be because another transfer\r
1170 *               is in progress or command or data inhibit is set\r
1171 *\r
1172 ******************************************************************************/\r
1173 s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)\r
1174 {\r
1175         s32 Status;\r
1176         u32 PresentStateReg;\r
1177 \r
1178         if(InstancePtr->Config.CardDetect != 0U) {\r
1179                 /* Check status to ensure card is initialized */\r
1180                 PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1181                                 XSDPS_PRES_STATE_OFFSET);\r
1182                 if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0U) {\r
1183                         Status = XST_FAILURE;\r
1184                         goto RETURN_PATH;\r
1185                 }\r
1186         }\r
1187 \r
1188         /* Set block size to 512 if not already set */\r
1189         if( XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1190                         XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {\r
1191                 Status = XSdPs_SetBlkSize(InstancePtr,\r
1192                         XSDPS_BLK_SIZE_512_MASK);\r
1193                 if (Status != XST_SUCCESS) {\r
1194                         Status = XST_FAILURE;\r
1195                         goto RETURN_PATH;\r
1196                 }\r
1197         }\r
1198 \r
1199         XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);\r
1200 \r
1201         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
1202                         XSDPS_XFER_MODE_OFFSET,\r
1203                         XSDPS_TM_AUTO_CMD12_EN_MASK |\r
1204                         XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_DAT_DIR_SEL_MASK |\r
1205                         XSDPS_TM_DMA_EN_MASK | XSDPS_TM_MUL_SIN_BLK_SEL_MASK);\r
1206 \r
1207         if( ucIsCachedMemory( ( const uint8_t *)Buff ) != 0 )\r
1208         {\r
1209                 Xil_DCacheInvalidateRange( ( unsigned )Buff, BlkCnt * XSDPS_BLK_SIZE_512_MASK);\r
1210         }\r
1211 \r
1212         /* Send block read command */\r
1213         Status = XSdPs_CmdTransfer(InstancePtr, CMD18, Arg, BlkCnt);\r
1214         if (Status != XST_SUCCESS) {\r
1215                 Status = XST_FAILURE;\r
1216                 goto RETURN_PATH;\r
1217         }\r
1218 \r
1219         Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);\r
1220         if (Status != XST_SUCCESS) {\r
1221                 goto RETURN_PATH;\r
1222         }\r
1223 \r
1224         XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1225                 XSDPS_RESP0_OFFSET);\r
1226 \r
1227 RETURN_PATH:\r
1228         return Status;\r
1229 }\r
1230 \r
1231 /*****************************************************************************/\r
1232 /**\r
1233 * This function performs SD write in polled mode.\r
1234 *\r
1235 * @param        InstancePtr is a pointer to the instance to be worked on.\r
1236 * @param        Arg is the address passed by the user that is to be sent as\r
1237 *               argument along with the command.\r
1238 * @param        BlkCnt - Block count passed by the user.\r
1239 * @param        Buff - Pointer to the data buffer for a DMA transfer.\r
1240 *\r
1241 * @return\r
1242 *               - XST_SUCCESS if initialization was successful\r
1243 *               - XST_FAILURE if failure - could be because another transfer\r
1244 *               is in progress or command or data inhibit is set\r
1245 *\r
1246 ******************************************************************************/\r
1247 \r
1248 uint32_t ulSDWritePause = ffconfigWRITE_PAUSE_USEC;\r
1249 \r
1250 u32 XSdPs_ReadStatus(XSdPs *InstancePtr)\r
1251 {\r
1252 u32 Status;\r
1253 \r
1254         /* Send block write command */\r
1255         Status = XSdPs_CmdTransfer(InstancePtr, CMD13, (InstancePtr->RelCardAddr), 0UL);\r
1256         if (Status != XST_SUCCESS) {\r
1257                 Status = 0x00UL;\r
1258                 goto RETURN_PATH;\r
1259         }\r
1260         Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1261                         XSDPS_RESP0_OFFSET);\r
1262 RETURN_PATH:\r
1263         return Status;\r
1264 }\r
1265 \r
1266 s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)\r
1267 {\r
1268         s32 Status;\r
1269         u32 PresentStateReg;\r
1270 \r
1271         if(InstancePtr->Config.CardDetect != 0U) {\r
1272                 /* Check status to ensure card is initialized */\r
1273                 PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1274                                 XSDPS_PRES_STATE_OFFSET);\r
1275                 if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0U) {\r
1276                         Status = XST_FAILURE;\r
1277                         goto RETURN_PATH;\r
1278                 }\r
1279         }\r
1280 \r
1281         /* Set block size to 512 if not already set */\r
1282         if( XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1283                         XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {\r
1284                 Status = XSdPs_SetBlkSize(InstancePtr,\r
1285                         XSDPS_BLK_SIZE_512_MASK);\r
1286                 if (Status != XST_SUCCESS) {\r
1287                         Status = XST_FAILURE;\r
1288                         goto RETURN_PATH;\r
1289                 }\r
1290 \r
1291         }\r
1292 \r
1293         XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);\r
1294         if( ucIsCachedMemory( ( const uint8_t *)Buff ) != 0 )\r
1295         {\r
1296                 Xil_DCacheFlushRange( ( unsigned )Buff, BlkCnt * XSDPS_BLK_SIZE_512_MASK);\r
1297         }\r
1298 \r
1299         if( ulSDWritePause != 0ul )\r
1300         {\r
1301         /* Wait for halve a ms.\r
1302         This 'solution' is still under contruction. */\r
1303         uint64_t ullLastTime = ullGetHighResolutionTime();\r
1304         uint64_t ullNow;\r
1305 \r
1306                 XSdPs_ReadStatus(InstancePtr);\r
1307                 for( ;; )\r
1308                 {\r
1309                         ullNow = ullGetHighResolutionTime();\r
1310                         if( ( ullNow - ullLastTime ) > ulSDWritePause )\r
1311                         {\r
1312                                 ullLastTime = ullNow;\r
1313                                 break;\r
1314                         }\r
1315                 }\r
1316                 XSdPs_ReadStatus(InstancePtr);\r
1317 //              eventLogAdd("Wt %lx %lx%s", Status[0], Status[1], Status[0] != Status[1] ? " DIFF" : "");\r
1318         }\r
1319         else\r
1320         {\r
1321         u32 Status = XSdPs_ReadStatus(InstancePtr);\r
1322 //              eventLogAdd("Wt %lx", Status);\r
1323         }\r
1324 \r
1325         XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,\r
1326                         XSDPS_XFER_MODE_OFFSET,\r
1327                         XSDPS_TM_AUTO_CMD12_EN_MASK |\r
1328                         XSDPS_TM_BLK_CNT_EN_MASK |\r
1329                         XSDPS_TM_MUL_SIN_BLK_SEL_MASK | XSDPS_TM_DMA_EN_MASK);\r
1330 \r
1331         /* Send block write command */\r
1332         Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, BlkCnt);\r
1333         if (Status != XST_SUCCESS) {\r
1334                 Status = XST_FAILURE;\r
1335                 goto RETURN_PATH;\r
1336         }\r
1337 \r
1338         Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);\r
1339 \r
1340 RETURN_PATH:\r
1341         return Status;\r
1342 }\r
1343 \r
1344 /*****************************************************************************/\r
1345 /**\r
1346 *\r
1347 * Selects card and sets default block size\r
1348 *\r
1349 *\r
1350 * @param        InstancePtr is a pointer to the XSdPs instance.\r
1351 *\r
1352 * @return\r
1353 *               - XST_SUCCESS if successful.\r
1354 *               - XST_FAILURE if fail.\r
1355 *\r
1356 * @note         None.\r
1357 *\r
1358 ******************************************************************************/\r
1359 s32 XSdPs_Select_Card (XSdPs *InstancePtr)\r
1360 {\r
1361         s32 Status = 0;\r
1362 \r
1363         /* Send CMD7 - Select card */\r
1364         Status = XSdPs_CmdTransfer(InstancePtr, CMD7,\r
1365                         InstancePtr->RelCardAddr, 0U);\r
1366         if (Status != XST_SUCCESS) {\r
1367                 Status = XST_FAILURE;\r
1368                 goto RETURN_PATH;\r
1369         }\r
1370 \r
1371 RETURN_PATH:\r
1372                 return Status;\r
1373 \r
1374 }\r
1375 \r
1376 /*****************************************************************************/\r
1377 /**\r
1378 *\r
1379 * API to setup ADMA2 descriptor table\r
1380 *\r
1381 *\r
1382 * @param        InstancePtr is a pointer to the XSdPs instance.\r
1383 * @param        BlkCnt - block count.\r
1384 * @param        Buff pointer to data buffer.\r
1385 *\r
1386 * @return       None\r
1387 *\r
1388 * @note         None.\r
1389 *\r
1390 ******************************************************************************/\r
1391 void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)\r
1392 {\r
1393         u32 TotalDescLines = 0U;\r
1394         u32 DescNum = 0U;\r
1395         u32 BlkSize = 0U;\r
1396 \r
1397         /* Setup ADMA2 - Write descriptor table and point ADMA SAR to it */\r
1398         BlkSize = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,\r
1399                                         XSDPS_BLK_SIZE_OFFSET);\r
1400         BlkSize = BlkSize & XSDPS_BLK_SIZE_MASK;\r
1401 \r
1402         if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {\r
1403 \r
1404                 TotalDescLines = 1U;\r
1405 \r
1406         }else {\r
1407 \r
1408                 TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);\r
1409                 if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {\r
1410                         TotalDescLines += 1U;\r
1411                 }\r
1412 \r
1413         }\r
1414 \r
1415         for (DescNum = 0U; DescNum < (TotalDescLines-1); DescNum++) {\r
1416                 InstancePtr->Adma2_DescrTbl[DescNum].Address =\r
1417                                 (u32)(Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));\r
1418                 InstancePtr->Adma2_DescrTbl[DescNum].Attribute =\r
1419                                 XSDPS_DESC_TRAN | XSDPS_DESC_VALID;\r
1420                 /* This will write '0' to length field which indicates 65536 */\r
1421                 InstancePtr->Adma2_DescrTbl[DescNum].Length =\r
1422                                 (u16)XSDPS_DESC_MAX_LENGTH;\r
1423         }\r
1424 \r
1425         InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Address =\r
1426                         (u32)(Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));\r
1427 \r
1428         InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Attribute =\r
1429                         XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;\r
1430 \r
1431         InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Length =\r
1432                         (BlkCnt*BlkSize) - (DescNum*XSDPS_DESC_MAX_LENGTH);\r
1433 \r
1434 \r
1435         XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,\r
1436                         (u32)&(InstancePtr->Adma2_DescrTbl[0]));\r
1437 \r
1438         if( ucIsCachedMemory( ( const uint8_t *)InstancePtr->Adma2_DescrTbl ) != 0 )\r
1439         {\r
1440                 Xil_DCacheFlushRange( ( unsigned ) &( InstancePtr->Adma2_DescrTbl[ 0 ] ),\r
1441                         sizeof(XSdPs_Adma2Descriptor) * 32);\r
1442         }\r
1443 }\r
1444 \r
1445 /*****************************************************************************/\r
1446 /**\r
1447 * Mmc initialization is done in this function\r
1448 *\r
1449 *\r
1450 * @param        InstancePtr is a pointer to the instance to be worked on.\r
1451 *\r
1452 * @return\r
1453 *               - XST_SUCCESS if initialization was successful\r
1454 *               - XST_FAILURE if failure - could be because\r
1455 *                       a) MMC is already initialized\r
1456 *                       b) There is no card inserted\r
1457 *                       c) One of the steps (commands) in the initialization\r
1458 *                          cycle failed\r
1459 * @note         This function initializes the SD card by following its\r
1460 *               initialization and identification state diagram.\r
1461 *               CMD0 is sent to reset card.\r
1462 *               CMD1 sent to identify voltage and high capacity support\r
1463 *               CMD2 and CMD3 are sent to obtain Card ID and\r
1464 *               Relative card address respectively.\r
1465 *               CMD9 is sent to read the card specific data.\r
1466 *\r
1467 ******************************************************************************/\r
1468 s32 XSdPs_MmcCardInitialize(XSdPs *InstancePtr)\r
1469 {\r
1470         u32 PresentStateReg;\r
1471         s32 Status;\r
1472         u32 RespOCR;\r
1473         u32 CSD[4];\r
1474 \r
1475         Xil_AssertNonvoid(InstancePtr != NULL);\r
1476         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);\r
1477 \r
1478         if(InstancePtr->Config.CardDetect != 0U) {\r
1479                 /*\r
1480                  * Check the present state register to make sure\r
1481                  * card is inserted and detected by host controller\r
1482                  */\r
1483                 PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1484                                 XSDPS_PRES_STATE_OFFSET);\r
1485                 if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0U)        {\r
1486                         Status = XST_FAILURE;\r
1487                         goto RETURN_PATH;\r
1488                 }\r
1489         }\r
1490 \r
1491         /* CMD0 no response expected */\r
1492         Status = XSdPs_CmdTransfer(InstancePtr, CMD0, 0U, 0U);\r
1493         if (Status != XST_SUCCESS) {\r
1494                 Status = XST_FAILURE;\r
1495                 goto RETURN_PATH;\r
1496         }\r
1497 \r
1498         RespOCR = 0U;\r
1499         /* Send CMD1 while card is still busy with power up */\r
1500         while ((RespOCR & XSDPS_RESPOCR_READY) == 0U) {\r
1501 \r
1502                 /* Host High Capacity support & High volage window */\r
1503                 Status = XSdPs_CmdTransfer(InstancePtr, CMD1,\r
1504                                 XSDPS_ACMD41_HCS | XSDPS_CMD1_HIGH_VOL, 0U);\r
1505                 if (Status != XST_SUCCESS) {\r
1506                         Status = XST_FAILURE;\r
1507                         goto RETURN_PATH;\r
1508                 }\r
1509 \r
1510                 /* Response with card capacity */\r
1511                 RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1512                                 XSDPS_RESP0_OFFSET);\r
1513 \r
1514         }\r
1515 \r
1516         /* Update HCS support flag based on card capacity response */\r
1517         if ((RespOCR & XSDPS_ACMD41_HCS) != 0U) {\r
1518                 InstancePtr->HCS = 1U;\r
1519         }\r
1520 \r
1521         /* CMD2 for Card ID */\r
1522         Status = XSdPs_CmdTransfer(InstancePtr, CMD2, 0U, 0U);\r
1523         if (Status != XST_SUCCESS) {\r
1524                 Status = XST_FAILURE;\r
1525                 goto RETURN_PATH;\r
1526         }\r
1527 \r
1528         InstancePtr->CardID[0] =\r
1529                         XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,\r
1530                         XSDPS_RESP0_OFFSET);\r
1531         InstancePtr->CardID[1] =\r
1532                         XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,\r
1533                         XSDPS_RESP1_OFFSET);\r
1534         InstancePtr->CardID[2] =\r
1535                         XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,\r
1536                         XSDPS_RESP2_OFFSET);\r
1537         InstancePtr->CardID[3] =\r
1538                         XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,\r
1539                         XSDPS_RESP3_OFFSET);\r
1540 \r
1541         /* Set relative card address */\r
1542         InstancePtr->RelCardAddr = 0x12340000U;\r
1543         Status = XSdPs_CmdTransfer(InstancePtr, CMD3, (InstancePtr->RelCardAddr), 0U);\r
1544         if (Status != XST_SUCCESS) {\r
1545                 Status = XST_FAILURE;\r
1546                 goto RETURN_PATH;\r
1547         }\r
1548 \r
1549         /* Read Card specific data. */\r
1550         Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0U);\r
1551         if (Status != XST_SUCCESS) {\r
1552                 Status = XST_FAILURE;\r
1553                 goto RETURN_PATH;\r
1554         }\r
1555 \r
1556         /*\r
1557          * Card specific data is read.\r
1558          * Currently not used for any operation.\r
1559          */\r
1560         CSD[0] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1561                         XSDPS_RESP0_OFFSET);\r
1562         CSD[1] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1563                         XSDPS_RESP1_OFFSET);\r
1564         CSD[2] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1565                         XSDPS_RESP2_OFFSET);\r
1566         CSD[3] = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,\r
1567                         XSDPS_RESP3_OFFSET);\r
1568 \r
1569         ( void ) CSD[0];\r
1570 \r
1571         Status = XST_SUCCESS;\r
1572 \r
1573 RETURN_PATH:\r
1574         return Status;\r
1575 \r
1576 }\r
1577 /** @} */\r