in portable/Zynq.2019.3/xsdps.c [436:712]
s32 XSdPs_SdCardInitialize( XSdPs * InstancePtr )
{
u32 PresentStateReg;
s32 Status;
u32 RespOCR;
u32 CSD[ 4 ];
u32 Arg;
u8 ReadReg;
u32 BlkLen, DeviceSize, Mult;
Xil_AssertNonvoid( InstancePtr != NULL );
Xil_AssertNonvoid( InstancePtr->IsReady == XIL_COMPONENT_IS_READY );
FF_PRINTF( "XSdPs_SdCardInitialize\n" );
#ifndef UHS_MODE_ENABLE
InstancePtr->Config.BusWidth = XSDPS_WIDTH_4;
#endif
if( ( InstancePtr->HC_Version != XSDPS_HC_SPEC_V3 ) ||
( ( InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK )
!= XSDPS_CAPS_EMB_SLOT ) )
{
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;
}
FF_PRINTF( "CMD0 : %d\n", Status );
/*
* CMD8; response expected
* 0x1AA - Supply Voltage 2.7 - 3.6V and AA is pattern
*/
Status = XSdPs_CmdTransfer( InstancePtr, CMD8,
XSDPS_CMD8_VOL_PATTERN, 0U );
FF_PRINTF( "CMD8 : %d\n", Status );
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;
}
FF_PRINTF( "Card_Version %d\n", InstancePtr->Card_Version );
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 );
/*
* There is no support to switch to 1.8V and use UHS mode on
* 1.0 silicon
*/
if( ( InstancePtr->HC_Version == XSDPS_HC_SPEC_V3 ) &&
#if defined( ARMR5 ) || ( __aarch64__ ) || ( ARMA53_32 ) || ( PSU_PMU )
( XGetPSVersion_Info() > ( u32 ) XPS_VERSION_1 ) &&
#endif
( InstancePtr->Config.BusWidth == XSDPS_WIDTH_8 ) )
{
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;
}
if( ( RespOCR & XSDPS_OCR_S18 ) != 0U )
{
InstancePtr->Switch1v8 = 1U;
Status = XSdPs_Switch_Voltage( InstancePtr );
if( Status != XST_SUCCESS )
{
Status = XST_FAILURE;
goto RETURN_PATH;
}
}
/* 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_ReadReg16( InstancePtr->Config.BaseAddress,
XSDPS_RESP0_OFFSET );
InstancePtr->CardID[ 1 ] =
XSdPs_ReadReg16( InstancePtr->Config.BaseAddress,
XSDPS_RESP1_OFFSET );
InstancePtr->CardID[ 2 ] =
XSdPs_ReadReg16( InstancePtr->Config.BaseAddress,
XSDPS_RESP2_OFFSET );
InstancePtr->CardID[ 3 ] =
XSdPs_ReadReg16( 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 );
}
/*
* Card specific data is read.
* Currently not used for any operation.
*/
#if 0
CSD[ 0 ] = XSdPs_ReadReg( InstancePtr->Config.BaseAddress,
XSDPS_RESP0_OFFSET );
CSD[ 1 ] = XSdPs_ReadReg( InstancePtr->Config.BaseAddress,
XSDPS_RESP1_OFFSET );
CSD[ 2 ] = XSdPs_ReadReg( InstancePtr->Config.BaseAddress,
XSDPS_RESP2_OFFSET );
CSD[ 3 ] = XSdPs_ReadReg( InstancePtr->Config.BaseAddress,
XSDPS_RESP3_OFFSET );
if( ( ( CSD[ 3 ] & CSD_STRUCT_MASK ) >> 22U ) == 0U )
{
BlkLen = 1U << ( ( u32 ) ( CSD[ 2 ] & READ_BLK_LEN_MASK ) >> 8U );
Mult = 1U << ( ( u32 ) ( ( CSD[ 1 ] & C_SIZE_MULT_MASK ) >> 7U ) + 2U );
DeviceSize = ( CSD[ 1 ] & C_SIZE_LOWER_MASK ) >> 22U;
DeviceSize |= ( CSD[ 2 ] & C_SIZE_UPPER_MASK ) << 10U;
DeviceSize = ( DeviceSize + 1U ) * Mult;
DeviceSize = DeviceSize * BlkLen;
InstancePtr->SectorCount = ( DeviceSize / XSDPS_BLK_SIZE_512_MASK );
}
else if( ( ( CSD[ 3 ] & CSD_STRUCT_MASK ) >> 22U ) == 1U )
{
InstancePtr->SectorCount = ( ( ( CSD[ 1 ] & CSD_V2_C_SIZE_MASK ) >> 8U ) +
1U ) * 1024U;
}
else
{
Status = XST_FAILURE;
goto RETURN_PATH;
}
#endif /* 0 */
FF_PRINTF( "Sector count %lu\n", InstancePtr->SectorCount );
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}