s32 XSdPs_CardInitialize()

in portable/Zynq/xsdps.c [588:882]


s32 XSdPs_CardInitialize( XSdPs * InstancePtr )
{
    #ifdef __ICCARM__
    #pragma data_alignment = 32
        static u8 ExtCsd[ 512 ];
    #pragma data_alignment = 4
    #else
        static u8 ExtCsd[ 512 ] __attribute__( ( aligned( 32 ) ) );
    #endif
    u8 SCR[ 8 ] = { 0U };
    u8 ReadBuff[ 64 ] = { 0U };
    s32 Status;

    Xil_AssertNonvoid( InstancePtr != NULL );
    Xil_AssertNonvoid( InstancePtr->IsReady == XIL_COMPONENT_IS_READY );

    /* Default settings */
    InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;
    InstancePtr->CardType = XSDPS_CARD_SD;
    InstancePtr->Switch1v8 = 0U;
    InstancePtr->BusSpeed = XSDPS_CLK_400_KHZ;

    if( ( InstancePtr->HC_Version == XSDPS_HC_SPEC_V3 ) &&
        ( ( InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK )
          == XSDPS_CAPS_EMB_SLOT ) )
    {
        InstancePtr->CardType = XSDPS_CHIP_EMMC;
    }
    else
    {
        Status = XSdPs_IdentifyCard( InstancePtr );

        if( Status == XST_FAILURE )
        {
            goto RETURN_PATH;
        }
    }

    if( ( InstancePtr->CardType != XSDPS_CARD_SD ) &&
        ( InstancePtr->CardType != XSDPS_CARD_MMC ) &&
        ( InstancePtr->CardType != XSDPS_CHIP_EMMC ) )
    {
        Status = XST_FAILURE;
        goto RETURN_PATH;
    }

    if( InstancePtr->CardType == XSDPS_CARD_SD )
    {
        Status = XSdPs_SdCardInitialize( InstancePtr );

        if( Status != XST_SUCCESS )
        {
            Status = XST_FAILURE;
            goto RETURN_PATH;
        }

        /* Change clock to default clock 25MHz */
        InstancePtr->BusSpeed = SD_CLK_25_MHZ;
        Status = XSdPs_Change_ClkFreq( InstancePtr, InstancePtr->BusSpeed );

        if( Status != XST_SUCCESS )
        {
            Status = XST_FAILURE;
            goto RETURN_PATH;
        }
    }
    else if( ( InstancePtr->CardType == XSDPS_CARD_MMC ) ||
             ( InstancePtr->CardType == XSDPS_CHIP_EMMC ) )
    {
        Status = XSdPs_MmcCardInitialize( InstancePtr );

        if( Status != XST_SUCCESS )
        {
            Status = XST_FAILURE;
            goto RETURN_PATH;
        }

        /* Change clock to default clock 26MHz */
        InstancePtr->BusSpeed = SD_CLK_26_MHZ;
        Status = XSdPs_Change_ClkFreq( InstancePtr, InstancePtr->BusSpeed );

        if( Status != XST_SUCCESS )
        {
            Status = XST_FAILURE;
            goto RETURN_PATH;
        }
    }
    else
    {
        Status = XST_FAILURE;
        goto RETURN_PATH;
    }

    Status = XSdPs_Select_Card( InstancePtr );

    if( Status != XST_SUCCESS )
    {
        Status = XST_FAILURE;
        goto RETURN_PATH;
    }

    if( InstancePtr->CardType == XSDPS_CARD_SD )
    {
        /* Pull-up disconnected during data transfer */
        Status = XSdPs_Pullup( InstancePtr );

        if( Status != XST_SUCCESS )
        {
            Status = XST_FAILURE;
            goto RETURN_PATH;
        }

        Status = XSdPs_Get_BusWidth( InstancePtr, SCR );

        if( Status != XST_SUCCESS )
        {
            Status = XST_FAILURE;
            goto RETURN_PATH;
        }

        if( ( SCR[ 1 ] & WIDTH_4_BIT_SUPPORT ) != 0U )
        {
            Status = XSdPs_Change_BusWidth( InstancePtr );

            if( Status != XST_SUCCESS )
            {
                Status = XST_FAILURE;
                goto RETURN_PATH;
            }
        }

        if( ( InstancePtr->Switch1v8 != 0U ) &&
            ( InstancePtr->BusWidth == XSDPS_4_BIT_WIDTH ) )
        {
            /* Set UHS-I SDR104 mode */
            Status = XSdPs_Uhs_ModeInit( InstancePtr,
                                         XSDPS_UHS_SPEED_MODE_SDR104 );

            if( Status != XST_SUCCESS )
            {
                Status = XST_FAILURE;
                goto RETURN_PATH;
            }
        }
        else
        {
            /*
             * card supports CMD6 when SD_SPEC field in SCR register
             * indicates that the Physical Layer Specification Version
             * is 1.10 or later. So for SD v1.0 cmd6 is not supported.
             */
            if( SCR[ 0 ] != 0U )
            {
                /* Get speed supported by device */
                Status = XSdPs_Get_BusSpeed( InstancePtr, ReadBuff );

                if( Status != XST_SUCCESS )
                {
                    Status = XST_FAILURE;
                    FF_PRINTF( "SD-card seems OK but 4-bits doesn't work. Dirty contacts ?\n" );
                    FF_PRINTF( "Or: SD-card has version v1.0 which does not support cmd6 ?\n" );
                    goto RETURN_PATH;
                }

                /* Check for high speed support */
                if( ( ReadBuff[ 13 ] & HIGH_SPEED_SUPPORT ) != 0U )
                {
                    Status = XSdPs_Change_BusSpeed( InstancePtr );

                    if( Status != XST_SUCCESS )
                    {
                        Status = XST_FAILURE;
                        goto RETURN_PATH;
                    }
                }
            }
        }
    }
    else if( ( InstancePtr->CardType == XSDPS_CARD_MMC ) &&
             ( InstancePtr->HC_Version == XSDPS_HC_SPEC_V2 ) )
    {
        Status = XSdPs_Change_BusWidth( InstancePtr );

        if( Status != XST_SUCCESS )
        {
            Status = XST_FAILURE;
            goto RETURN_PATH;
        }

        Status = XSdPs_Get_Mmc_ExtCsd( InstancePtr, ExtCsd );

        if( Status != XST_SUCCESS )
        {
            Status = XST_FAILURE;
            goto RETURN_PATH;
        }

        if( ExtCsd[ EXT_CSD_BUS_WIDTH_BYTE ] != EXT_CSD_BUS_WIDTH_4_BIT )
        {
            Status = XST_FAILURE;
            goto RETURN_PATH;
        }

        if( ( ExtCsd[ EXT_CSD_DEVICE_TYPE_BYTE ] &
              EXT_CSD_DEVICE_TYPE_HIGH_SPEED ) != 0U )
        {
            Status = XSdPs_Change_BusSpeed( InstancePtr );

            if( Status != XST_SUCCESS )
            {
                Status = XST_FAILURE;
                goto RETURN_PATH;
            }

            Status = XSdPs_Get_Mmc_ExtCsd( InstancePtr, ExtCsd );

            if( Status != XST_SUCCESS )
            {
                Status = XST_FAILURE;
                goto RETURN_PATH;
            }

            if( ExtCsd[ EXT_CSD_HS_TIMING_BYTE ] != EXT_CSD_HS_TIMING_HIGH )
            {
                Status = XST_FAILURE;
                goto RETURN_PATH;
            }
        }
    }
    else if( InstancePtr->CardType == XSDPS_CHIP_EMMC )
    {
        /* Change bus width to 8-bit */
        Status = XSdPs_Change_BusWidth( InstancePtr );

        if( Status != XST_SUCCESS )
        {
            Status = XST_FAILURE;
            goto RETURN_PATH;
        }

        /* Get Extended CSD */
        Status = XSdPs_Get_Mmc_ExtCsd( InstancePtr, ExtCsd );

        if( Status != XST_SUCCESS )
        {
            Status = XST_FAILURE;
            goto RETURN_PATH;
        }

        /* Check for 8-bit support */
        if( ExtCsd[ EXT_CSD_BUS_WIDTH_BYTE ] != EXT_CSD_BUS_WIDTH_8_BIT )
        {
            Status = XST_FAILURE;
            goto RETURN_PATH;
        }

        if( ( ExtCsd[ EXT_CSD_DEVICE_TYPE_BYTE ] &
              ( EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200 |
                EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200 ) ) != 0U )
        {
            Status = XSdPs_Change_BusSpeed( InstancePtr );

            if( Status != XST_SUCCESS )
            {
                Status = XST_FAILURE;
                goto RETURN_PATH;
            }

            Status = XSdPs_Get_Mmc_ExtCsd( InstancePtr, ExtCsd );

            if( Status != XST_SUCCESS )
            {
                Status = XST_FAILURE;
                goto RETURN_PATH;
            }

            if( ExtCsd[ EXT_CSD_HS_TIMING_BYTE ] != EXT_CSD_HS_TIMING_HS200 )
            {
                Status = XST_FAILURE;
                goto RETURN_PATH;
            }
        }
    }

    Status = XSdPs_SetBlkSize( InstancePtr, XSDPS_BLK_SIZE_512_MASK );

    if( Status != XST_SUCCESS )
    {
        Status = XST_FAILURE;
        goto RETURN_PATH;
    }

RETURN_PATH:
    return Status;
}