/** * * API to setup ADMA2 descriptor table * * * @param InstancePtr is a pointer to the XSdPs instance. * @param BlkCnt - block count. * @param Buff pointer to data buffer. * * @return None * * @note None. * ******************************************************************************/ void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff) { u32 TotalDescLines = 0; u32 DescNum = 0; u32 BlkSize = 0; /* * Setup ADMA2 - Write descriptor table and point ADMA SAR to it */ BlkSize = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET); BlkSize = BlkSize & XSDPS_BLK_SIZE_MASK; if((BlkCnt*BlkSize) < XSDPS_DESC_MAX_LENGTH) { TotalDescLines = 1; }else { TotalDescLines = ((BlkCnt*BlkSize) / XSDPS_DESC_MAX_LENGTH); if ((BlkCnt * BlkSize) % XSDPS_DESC_MAX_LENGTH) TotalDescLines += 1; } for (DescNum = 0; DescNum < (TotalDescLines-1); DescNum++) { InstancePtr->Adma2_DescrTbl[DescNum].Address = (u32)(Buff + (DescNum*XSDPS_DESC_MAX_LENGTH)); InstancePtr->Adma2_DescrTbl[DescNum].Attribute = XSDPS_DESC_TRAN | XSDPS_DESC_VALID; /* * This will write '0' to length field which indicates 65536 */ InstancePtr->Adma2_DescrTbl[DescNum].Length = (u16)XSDPS_DESC_MAX_LENGTH; } InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Address = (u32)(Buff + (DescNum*XSDPS_DESC_MAX_LENGTH)); InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Attribute = XSDPS_DESC_TRAN | XSDPS_DESC_END | XSDPS_DESC_VALID; InstancePtr->Adma2_DescrTbl[TotalDescLines-1].Length = (BlkCnt*BlkSize) - (DescNum*XSDPS_DESC_MAX_LENGTH); XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ADMA_SAR_OFFSET, (u32)&(InstancePtr->Adma2_DescrTbl[0])); Xil_DCacheFlushRange(&(InstancePtr->Adma2_DescrTbl[0]), sizeof(XSdPs_Adma2Descriptor) * 32); }
/** * This function does SD command generation. * * @param InstancePtr is a pointer to the instance to be worked on. * @param Cmd is the command to be sent. * @param Arg is the argument to be sent along with the command. * This could be address or any other information * @param BlkCnt - Block count passed by the user. * * @return * - XST_SUCCESS if initialization was successful * - XST_FAILURE if failure - could be because another transfer * is in progress or command or data inhibit is set * ******************************************************************************/ s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt) { u32 PresentStateReg; u32 CommandReg; u32 StatusReg; s32 Status; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Check the command inhibit to make sure no other * command transfer is in progress */ PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_PRES_STATE_OFFSET); if ((PresentStateReg & XSDPS_PSR_INHIBIT_CMD_MASK) != 0U) { Status = XST_FAILURE; goto RETURN_PATH; } /* Write block count register */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_CNT_OFFSET, (u16)BlkCnt); XSdPs_WriteReg8(InstancePtr->Config.BaseAddress, XSDPS_TIMEOUT_CTRL_OFFSET, 0xEU); /* Write argument register */ XSdPs_WriteReg(InstancePtr->Config.BaseAddress, XSDPS_ARGMT_OFFSET, Arg); XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET, XSDPS_NORM_INTR_ALL_MASK); XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK); /* Command register is set to trigger transfer of command */ CommandReg = XSdPs_FrameCmd(InstancePtr, Cmd); /* * Mask to avoid writing to reserved bits 31-30 * This is necessary because 0x80000000 is used by this software to * distinguish between ACMD and CMD of same number */ CommandReg = CommandReg & 0x3FFFU; /* * Check for data inhibit in case of command using DAT lines. * For Tuning Commands DAT lines check can be ignored. */ if ((Cmd != CMD21) && (Cmd != CMD19)) { PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress, XSDPS_PRES_STATE_OFFSET); if (((PresentStateReg & (XSDPS_PSR_INHIBIT_DAT_MASK | XSDPS_PSR_INHIBIT_DAT_MASK)) != 0U) && ((CommandReg & XSDPS_DAT_PRESENT_SEL_MASK) != 0U)) { Status = XST_FAILURE; goto RETURN_PATH; } } XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CMD_OFFSET, (u16)CommandReg); /* Polling for response for now */ do { StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET); if ((Cmd == CMD21) || (Cmd == CMD19)) { if ((XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET) & XSDPS_INTR_BRR_MASK) != 0U){ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_BRR_MASK); break; } } if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) { Status = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress, XSDPS_ERR_INTR_STS_OFFSET); if ((Status & ~XSDPS_INTR_ERR_CT_MASK) == 0) { Status = XSDPS_CT_ERROR; } /* Write to clear error bits */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_ERR_INTR_STS_OFFSET, XSDPS_ERROR_INTR_ALL_MASK); goto RETURN_PATH; } } while((StatusReg & XSDPS_INTR_CC_MASK) == 0U); /* Write to clear bit */ XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_CC_MASK); Status = XST_SUCCESS; RETURN_PATH: return Status; }