in portable/Zynq/xsdps.c [338:550]
s32 XSdPs_SdCardInitialize( XSdPs * InstancePtr )
{
u32 PresentStateReg;
s32 Status;
u32 RespOCR;
u32 CSD[ 4 ];
u32 Arg;
u8 ReadReg;
Xil_AssertNonvoid( InstancePtr != NULL );
Xil_AssertNonvoid( InstancePtr->IsReady == XIL_COMPONENT_IS_READY );
if( InstancePtr->Config.CardDetect != 0U )
{
/*
* Check the present state register to make sure
* card is inserted and detected by host controller
*/
PresentStateReg = XSdPs_ReadReg( InstancePtr->Config.BaseAddress,
XSDPS_PRES_STATE_OFFSET );
if( ( PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK ) == 0U )
{
Status = XST_FAILURE;
goto RETURN_PATH;
}
}
/* CMD0 no response expected */
Status = XSdPs_CmdTransfer( InstancePtr, ( u32 ) CMD0, 0U, 0U );
if( Status != XST_SUCCESS )
{
Status = XST_FAILURE;
goto RETURN_PATH;
}
/*
* CMD8; response expected
* 0x1AA - Supply Voltage 2.7 - 3.6V and AA is pattern
*/
Status = XSdPs_CmdTransfer( InstancePtr, CMD8,
XSDPS_CMD8_VOL_PATTERN, 0U );
if( ( Status != XST_SUCCESS ) && ( Status != XSDPS_CT_ERROR ) )
{
Status = XST_FAILURE;
goto RETURN_PATH;
}
if( Status == XSDPS_CT_ERROR )
{
/* "Software reset for all" is initiated */
XSdPs_WriteReg8( InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET,
XSDPS_SWRST_CMD_LINE_MASK );
/* Proceed with initialization only after reset is complete */
ReadReg = XSdPs_ReadReg8( InstancePtr->Config.BaseAddress,
XSDPS_SW_RST_OFFSET );
while( ( ReadReg & XSDPS_SWRST_CMD_LINE_MASK ) != 0U )
{
ReadReg = XSdPs_ReadReg8( InstancePtr->Config.BaseAddress,
XSDPS_SW_RST_OFFSET );
}
}
RespOCR = XSdPs_ReadReg( InstancePtr->Config.BaseAddress,
XSDPS_RESP0_OFFSET );
if( RespOCR != XSDPS_CMD8_VOL_PATTERN )
{
InstancePtr->Card_Version = XSDPS_SD_VER_1_0;
}
else
{
InstancePtr->Card_Version = XSDPS_SD_VER_2_0;
}
RespOCR = 0U;
/* Send ACMD41 while card is still busy with power up */
while( ( RespOCR & XSDPS_RESPOCR_READY ) == 0U )
{
Status = XSdPs_CmdTransfer( InstancePtr, CMD55, 0U, 0U );
if( Status != XST_SUCCESS )
{
Status = XST_FAILURE;
goto RETURN_PATH;
}
Arg = XSDPS_ACMD41_HCS | XSDPS_ACMD41_3V3 | ( 0x1FFU << 15U );
if( InstancePtr->HC_Version == XSDPS_HC_SPEC_V3 )
{
Arg |= XSDPS_OCR_S18;
}
/* 0x40300000 - Host High Capacity support & 3.3V window */
Status = XSdPs_CmdTransfer( InstancePtr, ACMD41,
Arg, 0U );
if( Status != XST_SUCCESS )
{
Status = XST_FAILURE;
goto RETURN_PATH;
}
/* Response with card capacity */
RespOCR = XSdPs_ReadReg( InstancePtr->Config.BaseAddress,
XSDPS_RESP0_OFFSET );
}
/* Update HCS support flag based on card capacity response */
if( ( RespOCR & XSDPS_ACMD41_HCS ) != 0U )
{
InstancePtr->HCS = 1U;
}
/* There is no support to switch to 1.8V and use UHS mode on 1.0 silicon */
#ifndef UHS_BROKEN
if( ( RespOCR & XSDPS_OCR_S18 ) != 0U )
{
InstancePtr->Switch1v8 = 1U;
Status = XSdPs_Switch_Voltage( InstancePtr );
if( Status != XST_SUCCESS )
{
Status = XST_FAILURE;
goto RETURN_PATH;
}
}
#endif /* ifndef UHS_BROKEN */
/* CMD2 for Card ID */
Status = XSdPs_CmdTransfer( InstancePtr, CMD2, 0U, 0U );
if( Status != XST_SUCCESS )
{
Status = XST_FAILURE;
goto RETURN_PATH;
}
InstancePtr->CardID[ 0 ] = XSdPs_ReadReg( InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET );
InstancePtr->CardID[ 1 ] = XSdPs_ReadReg( InstancePtr->Config.BaseAddress, XSDPS_RESP1_OFFSET );
InstancePtr->CardID[ 2 ] = XSdPs_ReadReg( InstancePtr->Config.BaseAddress, XSDPS_RESP2_OFFSET );
InstancePtr->CardID[ 3 ] = XSdPs_ReadReg( InstancePtr->Config.BaseAddress, XSDPS_RESP3_OFFSET );
do
{
Status = XSdPs_CmdTransfer( InstancePtr, CMD3, 0U, 0U );
if( Status != XST_SUCCESS )
{
Status = XST_FAILURE;
goto RETURN_PATH;
}
/*
* Relative card address is stored as the upper 16 bits
* This is to avoid shifting when sending commands
*/
InstancePtr->RelCardAddr =
XSdPs_ReadReg( InstancePtr->Config.BaseAddress,
XSDPS_RESP0_OFFSET ) & 0xFFFF0000U;
} while( InstancePtr->RelCardAddr == 0U );
Status = XSdPs_CmdTransfer( InstancePtr, CMD9, ( InstancePtr->RelCardAddr ), 0U );
if( Status != XST_SUCCESS )
{
Status = XST_FAILURE;
goto RETURN_PATH;
}
{
u32 resp[ 4 ];
/* Put the CSD data in a standard order and analyse them */
resp[ 0 ] = XSdPs_ReadReg( InstancePtr->Config.BaseAddress, XSDPS_RESP0_OFFSET );
resp[ 1 ] = XSdPs_ReadReg( InstancePtr->Config.BaseAddress, XSDPS_RESP1_OFFSET );
resp[ 2 ] = XSdPs_ReadReg( InstancePtr->Config.BaseAddress, XSDPS_RESP2_OFFSET );
resp[ 3 ] = XSdPs_ReadReg( InstancePtr->Config.BaseAddress, XSDPS_RESP3_OFFSET );
CSD[ 0 ] = ( resp[ 3 ] << 8 ) | ( resp[ 2 ] >> 24 );
CSD[ 1 ] = ( resp[ 2 ] << 8 ) | ( resp[ 1 ] >> 24 );
CSD[ 2 ] = ( resp[ 1 ] << 8 ) | ( resp[ 0 ] >> 24 );
CSD[ 3 ] = ( resp[ 0 ] << 8 );
FF_PRINTF( "CSD %08lX %08lX %08lX %08lX\n", CSD[ 0 ], CSD[ 1 ], CSD[ 2 ], CSD[ 3 ] );
sd_decode_csd( &myCSD, ( u32 * ) CSD );
}
{
u32 resp[ 4 ];
/* When analysing the Card ID (CID), a field in CSD must be known: mmca_vsn. */
resp[ 0 ] = ( InstancePtr->CardID[ 3 ] >> 8 );
resp[ 1 ] = ( InstancePtr->CardID[ 3 ] << 24 ) | ( InstancePtr->CardID[ 2 ] >> 8 );
resp[ 2 ] = ( InstancePtr->CardID[ 2 ] << 24 ) | ( InstancePtr->CardID[ 1 ] >> 8 );
resp[ 3 ] = ( InstancePtr->CardID[ 1 ] << 24 ) | ( InstancePtr->CardID[ 0 ] >> 8 );
FF_PRINTF( "CID %08X %08X %08X %08X\n",
( unsigned ) resp[ 0 ],
( unsigned ) resp[ 1 ],
( unsigned ) resp[ 2 ],
( unsigned ) resp[ 3 ] );
mmc_decode_cid( &myCSD, &myCID, resp );
}
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}