in portable/Zynq.2019.3/xsdps.c [169:408]
u32 XSdPs_FrameCmd( XSdPs * InstancePtr,
u32 Cmd );
s32 XSdPs_CmdTransfer( XSdPs * InstancePtr,
u32 Cmd,
u32 Arg,
u32 BlkCnt );
void XSdPs_SetupADMA2DescTbl( XSdPs * InstancePtr,
u32 BlkCnt,
const u8 * Buff );
void XSdPs_SetupADMA2DescTbl64Bit( XSdPs * InstancePtr,
u32 BlkCnt );
extern s32 XSdPs_Uhs_ModeInit( XSdPs * InstancePtr,
u8 Mode );
static s32 XSdPs_IdentifyCard( XSdPs * InstancePtr );
static s32 XSdPs_Switch_Voltage( XSdPs * InstancePtr );
#if ( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
/* Declared in ff_sddisk.c :
* Function will sleep and get interrupted on a change of
* the status register. It will loop until:
* 1. Expected bit (ulMask) becomes high
* 2. Time-out reached (normally 2 seconds)
*/
extern u32 XSdPs_WaitInterrupt( XSdPs * InstancePtr,
u32 ulMask,
u32 ulWait );
/* Clear the interrupt before using it. */
extern void XSdPs_ClearInterrupt( XSdPs * InstancePtr );
#else
#error Please define ffconfigSDIO_DRIVER_USES_INTERRUPT
#endif
u16 TransferMode;
/*****************************************************************************/
/**
*
* Initializes a specific XSdPs instance such that the driver is ready to use.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param ConfigPtr is a reference to a structure containing information
* about a specific SD device. This function initializes an
* InstancePtr object for a specific device specified by the
* contents of Config.
* @param EffectiveAddr is the device base address in the virtual memory
* address space. The caller is responsible for keeping the address
* mapping from EffectiveAddr to the device physical base address
* unchanged once this function is invoked. Unexpected errors may
* occur if the address mapping changes after this function is
* called. If address translation is not used, use
* ConfigPtr->Config.BaseAddress for this device.
*
* @return
* - XST_SUCCESS if successful.
* - XST_DEVICE_IS_STARTED if the device is already started.
* It must be stopped to re-initialize.
*
* @note This function initializes the host controller.
* Initial clock of 400KHz is set.
* Voltage of 3.3V is selected as that is supported by host.
* Interrupts status is enabled and signal disabled by default.
* Default data direction is card to host and
* 32 bit ADMA2 is selected. Default Block size is 512 bytes.
*
******************************************************************************/
s32 XSdPs_CfgInitialize( XSdPs * InstancePtr,
XSdPs_Config * ConfigPtr,
u32 EffectiveAddr )
{
s32 Status;
u8 PowerLevel;
u8 ReadReg;
Xil_AssertNonvoid( InstancePtr != NULL );
Xil_AssertNonvoid( ConfigPtr != NULL );
/* Set some default values. */
InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
InstancePtr->Config.BaseAddress = EffectiveAddr;
InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
InstancePtr->Config.CardDetect = ConfigPtr->CardDetect;
InstancePtr->Config.WriteProtect = ConfigPtr->WriteProtect;
InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
InstancePtr->Config.BankNumber = ConfigPtr->BankNumber;
InstancePtr->Config.HasEMIO = ConfigPtr->HasEMIO;
InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent;
InstancePtr->SectorCount = 0U;
InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
InstancePtr->OTapDelay = 0U;
InstancePtr->ITapDelay = 0U;
InstancePtr->Dma64BitAddr = 0U;
/* Disable bus power and issue emmc hw reset */
if( ( XSdPs_ReadReg16( InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL_VER_OFFSET ) & XSDPS_HC_SPEC_VER_MASK ) ==
XSDPS_HC_SPEC_V3 )
{
XSdPs_WriteReg8( InstancePtr->Config.BaseAddress,
XSDPS_POWER_CTRL_OFFSET, XSDPS_PC_EMMC_HW_RST_MASK );
}
else
{
XSdPs_WriteReg8( InstancePtr->Config.BaseAddress,
XSDPS_POWER_CTRL_OFFSET, 0x0 );
}
/* Delay to poweroff card */
( void ) usleep( 1000U );
/* "Software reset for all" is initiated */
XSdPs_WriteReg8( InstancePtr->Config.BaseAddress, XSDPS_SW_RST_OFFSET,
XSDPS_SWRST_ALL_MASK );
/* Proceed with initialization only after reset is complete */
ReadReg = XSdPs_ReadReg8( InstancePtr->Config.BaseAddress,
XSDPS_SW_RST_OFFSET );
while( ( ReadReg & XSDPS_SWRST_ALL_MASK ) != 0U )
{
ReadReg = XSdPs_ReadReg8( InstancePtr->Config.BaseAddress,
XSDPS_SW_RST_OFFSET );
}
/* Host Controller version is read. */
InstancePtr->HC_Version =
( u8 ) ( XSdPs_ReadReg16( InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL_VER_OFFSET ) & XSDPS_HC_SPEC_VER_MASK );
/*
* Read capabilities register and update it in Instance pointer.
* It is sufficient to read this once on power on.
*/
InstancePtr->Host_Caps = XSdPs_ReadReg( InstancePtr->Config.BaseAddress,
XSDPS_CAPS_OFFSET );
/* Select voltage and enable bus power. */
if( InstancePtr->HC_Version == XSDPS_HC_SPEC_V3 )
{
XSdPs_WriteReg8( InstancePtr->Config.BaseAddress,
XSDPS_POWER_CTRL_OFFSET,
( XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK ) &
~XSDPS_PC_EMMC_HW_RST_MASK );
}
else
{
XSdPs_WriteReg8( InstancePtr->Config.BaseAddress,
XSDPS_POWER_CTRL_OFFSET,
XSDPS_PC_BUS_VSEL_3V3_MASK | XSDPS_PC_BUS_PWR_MASK );
}
/* Delay before issuing the command after emmc reset */
if( InstancePtr->HC_Version == XSDPS_HC_SPEC_V3 )
{
if( ( InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK ) ==
XSDPS_CAPS_EMB_SLOT )
{
usleep( 200 );
}
}
/* Change the clock frequency to 400 KHz */
Status = XSdPs_Change_ClkFreq( InstancePtr, XSDPS_CLK_400_KHZ );
if( Status != XST_SUCCESS )
{
Status = XST_FAILURE;
goto RETURN_PATH;
}
if( ( InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V3_MASK ) != 0U )
{
PowerLevel = XSDPS_PC_BUS_VSEL_3V3_MASK;
}
else if( ( InstancePtr->Host_Caps & XSDPS_CAP_VOLT_3V0_MASK ) != 0U )
{
PowerLevel = XSDPS_PC_BUS_VSEL_3V0_MASK;
}
else if( ( InstancePtr->Host_Caps & XSDPS_CAP_VOLT_1V8_MASK ) != 0U )
{
PowerLevel = XSDPS_PC_BUS_VSEL_1V8_MASK;
}
else
{
PowerLevel = 0U;
}
/* Select voltage based on capability and enable bus power. */
XSdPs_WriteReg8( InstancePtr->Config.BaseAddress,
XSDPS_POWER_CTRL_OFFSET,
PowerLevel | XSDPS_PC_BUS_PWR_MASK );
if( InstancePtr->HC_Version == XSDPS_HC_SPEC_V3 )
{
/* Enable ADMA2 in 64bit mode. */
XSdPs_WriteReg8( InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL1_OFFSET,
XSDPS_HC_DMA_ADMA2_64_MASK );
}
else
{
/* Enable ADMA2 in 32bit mode. */
XSdPs_WriteReg8( InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL1_OFFSET,
XSDPS_HC_DMA_ADMA2_32_MASK );
}
/* Enable all interrupt status except card interrupt initially */
XSdPs_WriteReg16( InstancePtr->Config.BaseAddress,
XSDPS_NORM_INTR_STS_EN_OFFSET,
XSDPS_NORM_INTR_ALL_MASK & ( ~XSDPS_INTR_CARD_MASK ) );
XSdPs_WriteReg16( InstancePtr->Config.BaseAddress,
XSDPS_ERR_INTR_STS_EN_OFFSET,
XSDPS_ERROR_INTR_ALL_MASK );
/* Disable all interrupt signals by default. */
XSdPs_WriteReg16( InstancePtr->Config.BaseAddress,
XSDPS_NORM_INTR_SIG_EN_OFFSET, 0x0U );
XSdPs_WriteReg16( InstancePtr->Config.BaseAddress,
XSDPS_ERR_INTR_SIG_EN_OFFSET, 0x0U );
/*
* Transfer mode register - default value
* DMA enabled, block count enabled, data direction card to host(read)
*/
TransferMode = XSDPS_TM_DMA_EN_MASK | XSDPS_TM_BLK_CNT_EN_MASK |
XSDPS_TM_DAT_DIR_SEL_MASK;
/* Set block size to 512 by default */
XSdPs_WriteReg16( InstancePtr->Config.BaseAddress,
XSDPS_BLK_SIZE_OFFSET, XSDPS_BLK_SIZE_512_MASK );
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}