1 /******************************************************************************
\r
3 * Copyright (C) 2013 - 2015 Xilinx, Inc. All rights reserved.
\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
12 * The above copyright notice and this permission notice shall be included in
\r
13 * all copies or substantial portions of the Software.
\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
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
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
31 ******************************************************************************/
\r
32 /*****************************************************************************/
\r
36 * @addtogroup sdps_v2_5
\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
43 * MODIFICATION HISTORY:
\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
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
65 ******************************************************************************/
\r
67 /***************************** Include Files *********************************/
\r
69 #include "xsdps_info.h"
\r
70 #include "xil_cache.h"
\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
82 #ifdef __MICROBLAZE__
\r
84 #include "microblaze_sleep.h"
\r
88 #include <FreeRTOS.h>
\r
91 #include "FreeRTOSFATConfig.h"
\r
92 #include "uncached_memory.h"
\r
94 #include "hr_gettime.h"
\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
114 /* Note: Remove this once fixed */
\r
117 #ifndef ffconfigWRITE_PAUSE_USEC
\r
118 #define ffconfigWRITE_PAUSE_USEC 500UL
\r
121 /**************************** Type Definitions *******************************/
\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
131 static s32 XSdPs_Switch_Voltage(XSdPs *InstancePtr);
\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
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
145 #error Please define ffconfigSDIO_DRIVER_USES_INTERRUPT
\r
148 /*****************************************************************************/
\r
151 * Initializes a specific XSdPs instance such that the driver is ready to use.
\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
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
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
179 ******************************************************************************/
\r
180 s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
\r
186 Xil_AssertNonvoid(InstancePtr != NULL);
\r
187 Xil_AssertNonvoid(ConfigPtr != NULL);
\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
196 /* Disable bus power */
\r
197 XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
\r
198 XSDPS_POWER_CTRL_OFFSET, 0U);
\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
206 * Proceed with initialization only after reset is complete
\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
216 * Read capabilities register and update it in Instance pointer.
\r
217 * It is sufficient to read this once on power on.
\r
219 InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
\r
220 XSDPS_CAPS_OFFSET);
\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
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
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
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
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
258 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
\r
259 XSDPS_ERR_INTR_STS_EN_OFFSET,
\r
260 XSDPS_ERROR_INTR_ALL_MASK);
\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
269 * Transfer mode register - default value
\r
270 * DMA enabled, block count enabled, data direction card to host(read)
\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
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
281 Status = XST_SUCCESS;
\r
288 /*****************************************************************************/
\r
290 * SD initialization is done in this function
\r
293 * @param InstancePtr is a pointer to the instance to be worked on.
\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
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
312 ******************************************************************************/
\r
313 s32 XSdPs_SdCardInitialize(XSdPs *InstancePtr)
\r
315 u32 PresentStateReg;
\r
322 Xil_AssertNonvoid(InstancePtr != NULL);
\r
323 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
\r
325 if(InstancePtr->Config.CardDetect != 0U) {
\r
327 * Check the present state register to make sure
\r
328 * card is inserted and detected by host controller
\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
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
346 * CMD8; response expected
\r
347 * 0x1AA - Supply Voltage 2.7 - 3.6V and AA is pattern
\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
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
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
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
376 InstancePtr->Card_Version = XSDPS_SD_VER_2_0;
\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
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
393 /* 0x40300000 - Host High Capacity support & 3.3V window */
\r
394 Status = XSdPs_CmdTransfer(InstancePtr, ACMD41,
\r
396 if (Status != XST_SUCCESS) {
\r
397 Status = XST_FAILURE;
\r
401 /* Response with card capacity */
\r
402 RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
\r
403 XSDPS_RESP0_OFFSET);
\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
412 /* There is no support to switch to 1.8V and use UHS mode on 1.0 silicon */
\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
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
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
439 Status = XSdPs_CmdTransfer(InstancePtr, CMD3, 0U, 0U);
\r
440 if (Status != XST_SUCCESS) {
\r
441 Status = XST_FAILURE;
\r
446 * Relative card address is stored as the upper 16 bits
\r
447 * This is to avoid shifting when sending commands
\r
449 InstancePtr->RelCardAddr =
\r
450 XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
\r
451 XSDPS_RESP0_OFFSET) & 0xFFFF0000U;
\r
452 } while (InstancePtr->RelCardAddr == 0U);
\r
454 Status = XSdPs_CmdTransfer(InstancePtr, CMD9, (InstancePtr->RelCardAddr), 0U);
\r
455 if (Status != XST_SUCCESS) {
\r
456 Status = XST_FAILURE;
\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
472 sd_decode_csd( &myCSD, ( u32*) CSD );
\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
488 mmc_decode_cid( &myCSD, &myCID, resp );
\r
491 Status = XST_SUCCESS;
\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
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
511 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT == 0 )
\r
512 #define POLLCOUNT_MAX 0x800000
\r
515 /*****************************************************************************/
\r
518 * Initialize Card with Identification mode sequence
\r
521 * @param InstancePtr is a pointer to the instance to be worked on.
\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
532 ******************************************************************************/
\r
533 s32 XSdPs_CardInitialize(XSdPs *InstancePtr)
\r
536 #pragma data_alignment = 32
\r
537 static u8 ExtCsd[512];
\r
538 #pragma data_alignment = 4
\r
540 static u8 ExtCsd[512] __attribute__ ((aligned(32)));
\r
542 u8 SCR[8] = { 0U };
\r
543 u8 ReadBuff[64] = { 0U };
\r
546 Xil_AssertNonvoid(InstancePtr != NULL);
\r
547 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
\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
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
560 Status = XSdPs_IdentifyCard(InstancePtr);
\r
561 if (Status == XST_FAILURE) {
\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
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
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
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
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
603 Status = XST_FAILURE;
\r
607 Status = XSdPs_Select_Card(InstancePtr);
\r
608 if (Status != XST_SUCCESS) {
\r
609 Status = XST_FAILURE;
\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
621 Status = XSdPs_Get_BusWidth(InstancePtr, SCR);
\r
622 if (Status != XST_SUCCESS) {
\r
623 Status = XST_FAILURE;
\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
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
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
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
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
673 } else if ((InstancePtr->CardType == XSDPS_CARD_MMC) &&
\r
674 (InstancePtr->HC_Version == XSDPS_HC_SPEC_V2)) {
\r
676 Status = XSdPs_Change_BusWidth(InstancePtr);
\r
677 if (Status != XST_SUCCESS) {
\r
678 Status = XST_FAILURE;
\r
682 Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
\r
683 if (Status != XST_SUCCESS) {
\r
684 Status = XST_FAILURE;
\r
688 if (ExtCsd[EXT_CSD_BUS_WIDTH_BYTE] != EXT_CSD_BUS_WIDTH_4_BIT) {
\r
689 Status = XST_FAILURE;
\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
701 Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
\r
702 if (Status != XST_SUCCESS) {
\r
703 Status = XST_FAILURE;
\r
707 if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HIGH) {
\r
708 Status = XST_FAILURE;
\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
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
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
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
742 Status = XSdPs_Get_Mmc_ExtCsd(InstancePtr, ExtCsd);
\r
743 if (Status != XST_SUCCESS) {
\r
744 Status = XST_FAILURE;
\r
748 if (ExtCsd[EXT_CSD_HS_TIMING_BYTE] != EXT_CSD_HS_TIMING_HS200) {
\r
749 Status = XST_FAILURE;
\r
755 Status = XSdPs_SetBlkSize(InstancePtr, XSDPS_BLK_SIZE_512_MASK);
\r
756 if (Status != XST_SUCCESS) {
\r
757 Status = XST_FAILURE;
\r
765 /*****************************************************************************/
\r
768 * Identify type of card using CMD0 + CMD1 sequence
\r
771 * @param InstancePtr is a pointer to the XSdPs instance.
\r
773 ******************************************************************************/
\r
774 static s32 XSdPs_IdentifyCard(XSdPs *InstancePtr)
\r
779 Xil_AssertNonvoid(InstancePtr != NULL);
\r
780 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
\r
782 /* 74 CLK delay after card is powered up, before the first command. */
\r
783 #if defined (__arm__) || defined (__aarch64__)
\r
785 usleep(XSDPS_INIT_DELAY);
\r
789 #ifdef __MICROBLAZE__
\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
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
809 InstancePtr->CardType = XSDPS_CARD_MMC;
\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
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
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
829 Status = XST_SUCCESS;
\r
835 /*****************************************************************************/
\r
838 * Switches the SD card voltage from 3v3 to 1v8
\r
841 * @param InstancePtr is a pointer to the XSdPs instance.
\r
843 ******************************************************************************/
\r
845 static s32 XSdPs_Switch_Voltage(XSdPs *InstancePtr)
\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
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
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
873 /* Wait minimum 5mSec */
\r
874 #if defined (__arm__) || defined (__aarch64__)
\r
876 (void)usleep(5000U);
\r
880 #ifdef __MICROBLAZE__
\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
894 Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_400_KHZ);
\r
895 if (Status != XST_SUCCESS) {
\r
896 Status = XST_FAILURE;
\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
912 #endif /* UHS_BROKEN */
\r
914 s32 XSdPs_Wait_For(XSdPs *InstancePtr, u32 Mask, u32 Wait)
\r
916 s32 Status = XST_SUCCESS;
\r
918 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT == 0 )
\r
922 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
\r
923 StatusReg = XSdPs_WaitInterrupt( InstancePtr, XSDPS_INTR_ERR_MASK | Mask, Wait );
\r
925 if( ( StatusReg & Mask ) == 0 )
\r
927 Status = XST_FAILURE;
\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
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
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
954 /* Without some protection the code can easily
\r
955 get stuck here if the card is withdrawn. */
\r
957 if( ulPollCount == POLLCOUNT_MAX )
\r
959 Status = XST_FAILURE;
\r
964 #endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
\r
969 /*****************************************************************************/
\r
972 * This function does SD command generation.
\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
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
985 ******************************************************************************/
\r
986 s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt)
\r
988 u32 PresentStateReg;
\r
992 Xil_AssertNonvoid(InstancePtr != NULL);
\r
993 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
\r
996 * Check the command inhibit to make sure no other
\r
997 * command transfer is in progress
\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
1006 /* Write block count register */
\r
1007 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
\r
1008 XSDPS_BLK_CNT_OFFSET, (u16)BlkCnt);
\r
1010 XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
\r
1011 XSDPS_TIMEOUT_CTRL_OFFSET, 0xEU);
\r
1013 /* Write argument register */
\r
1014 XSdPs_WriteReg(InstancePtr->Config.BaseAddress,
\r
1015 XSDPS_ARGMT_OFFSET, Arg);
\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
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
1029 CommandReg = CommandReg & 0x3FFFU;
\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
1040 #if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
\r
1041 XSdPs_ClearInterrupt( InstancePtr );
\r
1043 XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CMD_OFFSET,
\r
1046 Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_CC_MASK, Cmd != CMD1);
\r
1054 /*****************************************************************************/
\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
1062 * @param Command to be sent.
\r
1064 * @return Command register value complete with response type and
\r
1065 * data, CRC and index related flags.
\r
1067 ******************************************************************************/
\r
1068 u32 XSdPs_FrameCmd(XSdPs *InstancePtr, u32 Cmd)
\r
1076 RetVal |= RESP_NONE;
\r
1079 RetVal |= RESP_R3;
\r
1082 RetVal |= RESP_R2;
\r
1085 RetVal |= RESP_R6;
\r
1088 RetVal |= RESP_NONE;
\r
1091 RetVal |= RESP_R1B;
\r
1094 if (InstancePtr->CardType == XSDPS_CARD_SD) {
\r
1095 RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
\r
1097 RetVal |= RESP_R1B;
\r
1101 RetVal |= RESP_R1;
\r
1104 RetVal |= RESP_R1;
\r
1107 if (InstancePtr->CardType == XSDPS_CARD_SD) {
\r
1108 RetVal |= RESP_R1;
\r
1110 RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
\r
1114 RetVal |= RESP_R2;
\r
1121 RetVal |= RESP_R1;
\r
1127 RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
\r
1133 RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
\r
1135 RetVal |= RESP_R3;
\r
1138 RetVal |= RESP_R1;
\r
1141 RetVal |= RESP_R1 | (u32)XSDPS_DAT_PRESENT_SEL_MASK;
\r
1145 RetVal |= RESP_R1;
\r
1157 /*****************************************************************************/
\r
1159 * This function performs SD read in polled mode.
\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
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
1172 ******************************************************************************/
\r
1173 s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
\r
1176 u32 PresentStateReg;
\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
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
1199 XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
\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
1207 if( ucIsCachedMemory( ( const uint8_t *)Buff ) != 0 )
\r
1209 Xil_DCacheInvalidateRange( ( unsigned )Buff, BlkCnt * XSDPS_BLK_SIZE_512_MASK);
\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
1219 Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);
\r
1220 if (Status != XST_SUCCESS) {
\r
1224 XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
\r
1225 XSDPS_RESP0_OFFSET);
\r
1231 /*****************************************************************************/
\r
1233 * This function performs SD write in polled mode.
\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
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
1246 ******************************************************************************/
\r
1248 uint32_t ulSDWritePause = ffconfigWRITE_PAUSE_USEC;
\r
1250 u32 XSdPs_ReadStatus(XSdPs *InstancePtr)
\r
1254 /* Send block write command */
\r
1255 Status = XSdPs_CmdTransfer(InstancePtr, CMD13, (InstancePtr->RelCardAddr), 0UL);
\r
1256 if (Status != XST_SUCCESS) {
\r
1260 Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
\r
1261 XSDPS_RESP0_OFFSET);
\r
1266 s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
\r
1269 u32 PresentStateReg;
\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
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
1293 XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
\r
1294 if( ucIsCachedMemory( ( const uint8_t *)Buff ) != 0 )
\r
1296 Xil_DCacheFlushRange( ( unsigned )Buff, BlkCnt * XSDPS_BLK_SIZE_512_MASK);
\r
1299 if( ulSDWritePause != 0ul )
\r
1301 /* Wait for halve a ms.
\r
1302 This 'solution' is still under contruction. */
\r
1303 uint64_t ullLastTime = ullGetHighResolutionTime();
\r
1306 XSdPs_ReadStatus(InstancePtr);
\r
1309 ullNow = ullGetHighResolutionTime();
\r
1310 if( ( ullNow - ullLastTime ) > ulSDWritePause )
\r
1312 ullLastTime = ullNow;
\r
1316 XSdPs_ReadStatus(InstancePtr);
\r
1317 // eventLogAdd("Wt %lx %lx%s", Status[0], Status[1], Status[0] != Status[1] ? " DIFF" : "");
\r
1321 u32 Status = XSdPs_ReadStatus(InstancePtr);
\r
1322 // eventLogAdd("Wt %lx", Status);
\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
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
1338 Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);
\r
1344 /*****************************************************************************/
\r
1347 * Selects card and sets default block size
\r
1350 * @param InstancePtr is a pointer to the XSdPs instance.
\r
1353 * - XST_SUCCESS if successful.
\r
1354 * - XST_FAILURE if fail.
\r
1358 ******************************************************************************/
\r
1359 s32 XSdPs_Select_Card (XSdPs *InstancePtr)
\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
1376 /*****************************************************************************/
\r
1379 * API to setup ADMA2 descriptor table
\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
1390 ******************************************************************************/
\r
1391 void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff)
\r
1393 u32 TotalDescLines = 0U;
\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
1402 if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) {
\r
1404 TotalDescLines = 1U;
\r
1408 TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH);
\r
1409 if (((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) != 0U) {
\r
1410 TotalDescLines += 1U;
\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
1425 InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Address =
\r
1426 (u32)(Buff + (DescNum*XSDPS_DESC_MAX_LENGTH));
\r
1428 InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Attribute =
\r
1429 XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID;
\r
1431 InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Length =
\r
1432 (BlkCnt*BlkSize) - (DescNum*XSDPS_DESC_MAX_LENGTH);
\r
1435 XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET,
\r
1436 (u32)&(InstancePtr->Adma2_DescrTbl[0]));
\r
1438 if( ucIsCachedMemory( ( const uint8_t *)InstancePtr->Adma2_DescrTbl ) != 0 )
\r
1440 Xil_DCacheFlushRange( ( unsigned ) &( InstancePtr->Adma2_DescrTbl[ 0 ] ),
\r
1441 sizeof(XSdPs_Adma2Descriptor) * 32);
\r
1445 /*****************************************************************************/
\r
1447 * Mmc initialization is done in this function
\r
1450 * @param InstancePtr is a pointer to the instance to be worked on.
\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
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
1467 ******************************************************************************/
\r
1468 s32 XSdPs_MmcCardInitialize(XSdPs *InstancePtr)
\r
1470 u32 PresentStateReg;
\r
1475 Xil_AssertNonvoid(InstancePtr != NULL);
\r
1476 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
\r
1478 if(InstancePtr->Config.CardDetect != 0U) {
\r
1480 * Check the present state register to make sure
\r
1481 * card is inserted and detected by host controller
\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
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
1499 /* Send CMD1 while card is still busy with power up */
\r
1500 while ((RespOCR & XSDPS_RESPOCR_READY) == 0U) {
\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
1510 /* Response with card capacity */
\r
1511 RespOCR = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
\r
1512 XSDPS_RESP0_OFFSET);
\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
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
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
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
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
1557 * Card specific data is read.
\r
1558 * Currently not used for any operation.
\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
1571 Status = XST_SUCCESS;
\r