s32 XSdPs_CardInitialize()

in portable/Zynq.2019.3/xsdps.c [733:1205]


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

    Xil_AssertNonvoid( InstancePtr != NULL );
    Xil_AssertNonvoid( InstancePtr->IsReady == XIL_COMPONENT_IS_READY );
    FF_PRINTF( "XSdPs_CardInitialize\n" );
    /* 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 */

        /*
         * SD default speed mode timing should be closed at 19 MHz.
         * The reason for this is SD requires a voltage level shifter.
         * This limitation applies to ZynqMPSoC.
         */
        if( InstancePtr->HC_Version == XSDPS_HC_SPEC_V3 )
        {
            InstancePtr->BusSpeed = SD_CLK_19_MHZ;
        }
        else
        {
            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;
            }
        }

        /* Get speed supported by device */
        Status = XSdPs_Get_BusSpeed( InstancePtr, ReadBuff );

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

        if( ( ( SCR[ 2 ] & SCR_SPEC_VER_3 ) != 0U ) &&
            ( ReadBuff[ 13 ] >= UHS_SDR50_SUPPORT ) &&
            ( InstancePtr->Config.BusWidth == XSDPS_WIDTH_8 ) &&
            #if defined( ARMR5 ) || ( __aarch64__ ) || ( ARMA53_32 ) || ( PSU_PMU )
                ( XGetPSVersion_Info() > ( u32 ) XPS_VERSION_1 ) &&
            #endif
            ( InstancePtr->Switch1v8 == 0U ) )
        {
            u16 CtrlReg, ClockReg;

            /* Stop the clock */
            CtrlReg = XSdPs_ReadReg16( InstancePtr->Config.BaseAddress,
                                       XSDPS_CLK_CTRL_OFFSET );
            CtrlReg &= ~( XSDPS_CC_SD_CLK_EN_MASK | XSDPS_CC_INT_CLK_EN_MASK );
            XSdPs_WriteReg16( InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET,
                              CtrlReg );

            /* Enabling 1.8V in controller */
            CtrlReg = XSdPs_ReadReg16( InstancePtr->Config.BaseAddress,
                                       XSDPS_HOST_CTRL2_OFFSET );
            CtrlReg |= XSDPS_HC2_1V8_EN_MASK;
            XSdPs_WriteReg16( InstancePtr->Config.BaseAddress, XSDPS_HOST_CTRL2_OFFSET,
                              CtrlReg );

            /* Wait minimum 5mSec */
            ( void ) usleep( 5000U );

            /* Check for 1.8V signal enable bit is cleared by Host */
            CtrlReg = XSdPs_ReadReg16( InstancePtr->Config.BaseAddress,
                                       XSDPS_HOST_CTRL2_OFFSET );

            if( ( CtrlReg & XSDPS_HC2_1V8_EN_MASK ) == 0U )
            {
                Status = XST_FAILURE;
                goto RETURN_PATH;
            }

            /* Wait for internal clock to stabilize */
            ClockReg = XSdPs_ReadReg16( InstancePtr->Config.BaseAddress,
                                        XSDPS_CLK_CTRL_OFFSET );
            XSdPs_WriteReg16( InstancePtr->Config.BaseAddress,
                              XSDPS_CLK_CTRL_OFFSET,
                              ClockReg | XSDPS_CC_INT_CLK_EN_MASK );
            ClockReg = XSdPs_ReadReg16( InstancePtr->Config.BaseAddress,
                                        XSDPS_CLK_CTRL_OFFSET );

            while( ( ClockReg & XSDPS_CC_INT_CLK_STABLE_MASK ) == 0U )
            {
                ClockReg = XSdPs_ReadReg16( InstancePtr->Config.BaseAddress,
                                            XSDPS_CLK_CTRL_OFFSET );
            }

            /* Enable SD clock */
            ClockReg = XSdPs_ReadReg16( InstancePtr->Config.BaseAddress,
                                        XSDPS_CLK_CTRL_OFFSET );
            XSdPs_WriteReg16( InstancePtr->Config.BaseAddress,
                              XSDPS_CLK_CTRL_OFFSET,
                              ClockReg | XSDPS_CC_SD_CLK_EN_MASK );

            /* Wait for 1mSec */
            ( void ) usleep( 1000U );

            InstancePtr->Switch1v8 = 1U;
        }

        #if defined( ARMR5 ) || defined( __aarch64__ ) || defined( ARMA53_32 ) || defined( __MICROBLAZE__ )
            if( InstancePtr->Switch1v8 != 0U )
            {
                /* Identify the UHS mode supported by card */
                XSdPs_Identify_UhsMode( InstancePtr, ReadBuff );

                /* Set UHS-I SDR104 mode */
                Status = XSdPs_Uhs_ModeInit( InstancePtr, ( u8 ) InstancePtr->Mode );

                if( Status != XST_SUCCESS )
                {
                    goto RETURN_PATH;
                }
            }
            else
            {
        #endif /* if defined( ARMR5 ) || defined( __aarch64__ ) || defined( ARMA53_32 ) || defined( __MICROBLAZE__ ) */

        /*
         * 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 )
        {
            /* Check for high speed support */
            if( ( ( ReadBuff[ 13 ] & HIGH_SPEED_SUPPORT ) != 0U ) &&
                ( InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH ) )
            {
                InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
                #if defined( ARMR5 ) || defined( __aarch64__ ) || defined( ARMA53_32 ) || defined( __MICROBLAZE__ )
                    InstancePtr->OTapDelay = SD_OTAPDLYSEL_SD_HSD;
                    InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
                #endif
                Status = XSdPs_Change_BusSpeed( InstancePtr );

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

        #if defined( ARMR5 ) || defined( __aarch64__ ) || defined( ARMA53_32 ) || defined( __MICROBLAZE__ )
    }
        #endif
    }
    else if( ( ( InstancePtr->CardType == XSDPS_CARD_MMC ) &&
               ( InstancePtr->Card_Version > CSD_SPEC_VER_3 ) ) &&
             ( 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;
        }

        InstancePtr->SectorCount = ( ( u32 ) ExtCsd[ EXT_CSD_SEC_COUNT_BYTE4 ] ) << 24;
        InstancePtr->SectorCount |= ( u32 ) ExtCsd[ EXT_CSD_SEC_COUNT_BYTE3 ] << 16;
        InstancePtr->SectorCount |= ( u32 ) ExtCsd[ EXT_CSD_SEC_COUNT_BYTE2 ] << 8;
        InstancePtr->SectorCount |= ( u32 ) ExtCsd[ EXT_CSD_SEC_COUNT_BYTE1 ];

        if( ( ( ExtCsd[ EXT_CSD_DEVICE_TYPE_BYTE ] &
                EXT_CSD_DEVICE_TYPE_HIGH_SPEED ) != 0U ) &&
            ( InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH ) )
        {
            InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
            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;
        }

        InstancePtr->SectorCount = ( ( u32 ) ExtCsd[ EXT_CSD_SEC_COUNT_BYTE4 ] ) << 24;
        InstancePtr->SectorCount |= ( u32 ) ExtCsd[ EXT_CSD_SEC_COUNT_BYTE3 ] << 16;
        InstancePtr->SectorCount |= ( u32 ) ExtCsd[ EXT_CSD_SEC_COUNT_BYTE2 ] << 8;
        InstancePtr->SectorCount |= ( u32 ) ExtCsd[ EXT_CSD_SEC_COUNT_BYTE1 ];

        /* Check for card supported speed */
        if( ( ( ExtCsd[ EXT_CSD_DEVICE_TYPE_BYTE ] &
                ( EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200 |
                  EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200 ) ) != 0U ) &&
            ( InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH ) )
        {
            InstancePtr->Mode = XSDPS_HS200_MODE;
            #if defined( ARMR5 ) || defined( __aarch64__ ) || defined( ARMA53_32 ) || defined( __MICROBLAZE__ )
                if( InstancePtr->Config.BankNumber == 2U )
                {
                    InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B2;
                }
                else
                {
                    InstancePtr->OTapDelay = SD_OTAPDLYSEL_HS200_B0;
                }
            #endif
        }
        else if( ( ( ExtCsd[ EXT_CSD_DEVICE_TYPE_BYTE ] &
                     ( EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED |
                       EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED ) ) != 0U ) &&
                 ( InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH ) )
        {
            InstancePtr->Mode = XSDPS_DDR52_MODE;
            #if defined( ARMR5 ) || defined( __aarch64__ ) || defined( ARMA53_32 ) || defined( __MICROBLAZE__ )
                InstancePtr->OTapDelay = SD_ITAPDLYSEL_EMMC_DDR50;
                InstancePtr->ITapDelay = SD_ITAPDLYSEL_EMMC_DDR50;
            #endif
        }
        else if( ( ( ExtCsd[ EXT_CSD_DEVICE_TYPE_BYTE ] &
                     EXT_CSD_DEVICE_TYPE_HIGH_SPEED ) != 0U ) &&
                 ( InstancePtr->BusWidth >= XSDPS_4_BIT_WIDTH ) )
        {
            InstancePtr->Mode = XSDPS_HIGH_SPEED_MODE;
            #if defined( ARMR5 ) || defined( __aarch64__ ) || defined( ARMA53_32 ) || defined( __MICROBLAZE__ )
                InstancePtr->OTapDelay = SD_OTAPDLYSEL_EMMC_HSD;
                InstancePtr->ITapDelay = SD_ITAPDLYSEL_HSD;
            #endif
        }
        else
        {
            InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
        }

        if( InstancePtr->Mode != XSDPS_DEFAULT_SPEED_MODE )
        {
            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( InstancePtr->Mode == XSDPS_HS200_MODE )
            {
                if( ExtCsd[ EXT_CSD_HS_TIMING_BYTE ] != EXT_CSD_HS_TIMING_HS200 )
                {
                    Status = XST_FAILURE;
                    goto RETURN_PATH;
                }
            }

            if( ( InstancePtr->Mode == XSDPS_HIGH_SPEED_MODE ) ||
                ( InstancePtr->Mode == XSDPS_DDR52_MODE ) )
            {
                if( ExtCsd[ EXT_CSD_HS_TIMING_BYTE ] != EXT_CSD_HS_TIMING_HIGH )
                {
                    Status = XST_FAILURE;
                    goto RETURN_PATH;
                }

                if( InstancePtr->Mode == XSDPS_DDR52_MODE )
                {
                    Status = XSdPs_Change_BusWidth( InstancePtr );

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

        /* Enable Rst_n_Fun bit if it is disabled */
        if( ExtCsd[ EXT_CSD_RST_N_FUN_BYTE ] == EXT_CSD_RST_N_FUN_TEMP_DIS )
        {
            Arg = XSDPS_MMC_RST_FUN_EN_ARG;
            Status = XSdPs_Set_Mmc_ExtCsd( InstancePtr, Arg );

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

    if( ( InstancePtr->Mode != XSDPS_DDR52_MODE ) ||
        ( InstancePtr->CardType == XSDPS_CARD_SD ) )
    {
        Status = XSdPs_SetBlkSize( InstancePtr, XSDPS_BLK_SIZE_512_MASK );

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

RETURN_PATH:
    return Status;
}