📄 sdio_bus_misc.c
字号:
UINT32 tplAddr; struct SDIO_FUNC_EXT_COMMON_TPL func0ext; UINT8 scrRegister[SD_SCR_BYTES]; SD_BUSCLOCK_RATE cardReportedRate = 0; PSDREQUEST pReq = NULL; BOOL spiMode = FALSE; if (SDCONFIG_GET_BUSWIDTH(pBusMode->BusModeFlags) == SDCONFIG_BUS_WIDTH_SPI) { spiMode = TRUE; } if (!spiMode) { /* set highest bus mode bus driver is allowing (non-SPI), the code below will * adjust to lower or equal settings */ pBusMode->BusModeFlags = pBusContext->DefaultBusMode; } /* set operational parameters */ pBusMode->ClockRate = pBusContext->DefaultOperClock; pHcd->CardProperties.OperBlockLenLimit = pBusContext->DefaultOperBlockLen; pHcd->CardProperties.OperBlockCountLimit = pBusContext->DefaultOperBlockCount; /* adjust operational block counts and length to match HCD */ ADJUST_OPER_BLOCK_LEN(&pHcd->CardProperties,pHcd->MaxBytesPerBlock); ADJUST_OPER_BLOCK_COUNT(&pHcd->CardProperties,pHcd->MaxBlocksPerTrans); /* limit operational clock to the max clock rate */ ADJUST_OPER_CLOCK(pBusMode,pHcd->MaxClockRate); if (!spiMode) { /* check HCD bus mode */ if (!(pHcd->Attributes & SDHCD_ATTRIB_BUS_4BIT) || ((pHcd->CardProperties.Flags & CARD_SDIO) && (pHcd->Attributes & SDHCD_ATTRIB_NO_4BIT_IRQ)) ) { if (pHcd->Attributes & SDHCD_ATTRIB_BUS_4BIT) { DBG_PRINT(SDDBG_WARN, ("SDIO Card Detected, but host does not support IRQs in 4 bit mode - dropping to 1 bit. \n")); } /* force to 1 bit mode */ SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT); } } /* now do various card inquiries to drop the bus mode or clock * none of these checks can raise the bus mode or clock higher that what * was initialized above */ do {#ifndef CT_CONFIG_NO_SDMMC if (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC)) { /* allocate a request for response data we'll need */ pReq = AllocateRequest(); if (NULL == pReq) { status = SDIO_STATUS_NO_RESOURCES; break; } } if (!spiMode && (pHcd->CardProperties.Flags & CARD_MMC)) { /* MMC cards all run in 1 bit mode */ SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT); } if (pHcd->CardProperties.Flags & CARD_SD) { DBG_ASSERT(pReq != NULL); DBG_PRINT(SDDBG_TRACE, ("Getting SCR from SD Card..\n")); /* read SCR (requires data transfer) to get supported modes */ status = _IssueBusRequestBd(pHcd,ACMD51,0, SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_APP_CMD | SDREQ_FLAGS_DATA_TRANS, pReq,&scrRegister,SD_SCR_BYTES); if (!SDIO_SUCCESS(status)) { DBG_PRINT(SDDBG_WARN, ("SD card does not have SCR. \n")); if (!spiMode) { /* switch it to 1 bit mode */ SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT); } status = SDIO_STATUS_SUCCESS; } else { /* we have to reorder this buffer since the SCR is sent MSB first on the data * data bus */ ReorderBuffer(scrRegister,SD_SCR_BYTES); /* got the SCR */ DBG_PRINT(SDDBG_TRACE, ("SD SCR StructRev:0x%X, Flags:0x%X \n", GET_SD_SCR_STRUCT_VER(scrRegister), GET_SD_SCR_BUSWIDTHS_FLAGS(scrRegister))); /* set the revision */ switch (GET_SD_SCR_SDSPEC_VER(scrRegister)) { case SCR_SD_SPEC_1_00: DBG_PRINT(SDDBG_TRACE, ("SD Spec Revision 1.01 \n")); pHcd->CardProperties.SD_MMC_Revision = SD_REVISION_1_01; break; case SCR_SD_SPEC_1_10: DBG_PRINT(SDDBG_TRACE, ("SD Spec Revision 1.10 \n")); pHcd->CardProperties.SD_MMC_Revision = SD_REVISION_1_10; break; default: DBG_PRINT(SDDBG_WARN, ("SD Spec Revision is greater than 1.10 \n")); pHcd->CardProperties.SD_MMC_Revision = SD_REVISION_1_10; break; } if (!(GET_SD_SCR_BUSWIDTHS(scrRegister) & SCR_BUS_SUPPORTS_4_BIT)) { if (!spiMode) { DBG_PRINT(SDDBG_WARN, ("SD SCR reports 1bit only Mode \n")); /* switch it to 1 bit mode */ SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_1_BIT); } } } } if (pHcd->CardProperties.Flags & (CARD_SD | CARD_MMC)) { DBG_ASSERT(pReq != NULL); /* de-select the card in order to get the CSD */ status = SelectDeselectCard(pHcd,FALSE); if (!SDIO_SUCCESS(status)) { DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to deselect card before getting CSD \n")); break; } /* Get CSD for SD or MMC cards */ if (spiMode) { /* in SPI mode, getting the CSD requires a read data transfer */ status = _IssueBusRequestBd(pHcd,CMD9,0, SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS, pReq, pHcd->CardProperties.CardCSD, MAX_CSD_CID_BYTES); if (SDIO_SUCCESS(status)) { /* when the CSD is sent over in SPI data mode, it comes to us in MSB first * and thus is not ordered correctly as defined in the SD spec */ ReorderBuffer(pHcd->CardProperties.CardCSD,MAX_CSD_CID_BYTES); } } else { status = _IssueSimpleBusRequest(pHcd, CMD9, (pHcd->CardProperties.RCA << 16), SDREQ_FLAGS_RESP_R2, pReq); if (SDIO_SUCCESS(status)) { /* save the CSD */ memcpy(pHcd->CardProperties.CardCSD,pReq->Response,MAX_CARD_RESPONSE_BYTES); } } if (!SDIO_SUCCESS(status)) { DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get CSD, Err:%d \n", status)); break; } /* for MMC cards, the spec version is in the CSD */ if (pHcd->CardProperties.Flags & CARD_MMC) { DBG_PRINT(SDDBG_TRACE, ("MMC Spec version : (0x%2.2X) \n", GET_MMC_SPEC_VERSION(pHcd->CardProperties.CardCSD))); switch (GET_MMC_SPEC_VERSION(pHcd->CardProperties.CardCSD)) { case MMC_SPEC_1_0_TO_1_2: case MMC_SPEC_1_4: case MMC_SPEC_2_0_TO_2_2: DBG_PRINT(SDDBG_WARN, ("MMC Spec version less than 3.1 \n")); pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_1_0_2_2; break; case MMC_SPEC_3_1: DBG_PRINT(SDDBG_TRACE, ("MMC Spec version 3.1 \n")); pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_3_1; break; case MMC_SPEC_4_0_TO_4_1: DBG_PRINT(SDDBG_TRACE, ("MMC Spec version 4.0-4.1 \n")); pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_4_0; break; default: pHcd->CardProperties.SD_MMC_Revision = MMC_REVISION_3_1; DBG_PRINT(SDDBG_WARN, ("MMC Spec version greater than 4.1\n")); break; } } /* re-select the card */ status = SelectDeselectCard(pHcd,TRUE); if (!SDIO_SUCCESS(status)) { DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to re-select card after getting CSD \n")); break; } }#endif // CT_CONFIG_NO_SDMMC#ifndef CT_CONFIG_NO_SDMMC if ((pHcd->CardProperties.Flags & CARD_SD) && !(pHcd->CardProperties.Flags & CARD_SDIO) && SDDEVICE_IS_SD_REV_GTEQ_1_10(pHcd->pPseudoDev) && (pHcd->Attributes & SDHCD_ATTRIB_SD_HIGH_SPEED) && !spiMode) { UINT32 arg; PUINT8 pSwitchStatusBlock = KernelAlloc(SD_SWITCH_FUNC_STATUS_BLOCK_BYTES); if (NULL == pSwitchStatusBlock) { status = SDIO_STATUS_NO_RESOURCES; break; } arg = SD_SWITCH_FUNC_ARG_GROUP_CHECK(SD_SWITCH_HIGH_SPEED_GROUP, SD_SWITCH_HIGH_SPEED_FUNC_NO); /* for 1.10 SD cards, check if high speed mode is supported */ DBG_PRINT(SDDBG_TRACE, ("SDIO Bus Driver: Checking SD Card for switchable functions (CMD6 arg:0x%X)\n",arg)); /* issue simple data transfer request to read the switch status */ status = _IssueBusRequestBd(pHcd, CMD6, arg, SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS, pReq, pSwitchStatusBlock, SD_SWITCH_FUNC_STATUS_BLOCK_BYTES); if (SDIO_SUCCESS(status)) { UINT16 switchGroupMask; /* need to reorder this since cards send this MSB first */ ReorderBuffer(pSwitchStatusBlock,SD_SWITCH_FUNC_STATUS_BLOCK_BYTES); switchGroupMask = SD_SWITCH_FUNC_STATUS_GET_GRP_BIT_MASK(pSwitchStatusBlock,SD_SWITCH_HIGH_SPEED_GROUP); DBG_PRINT(SDDBG_TRACE, ("SD Card Switch Status Group1 Mask:0x%X Max Current:%d\n", switchGroupMask, SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pSwitchStatusBlock) )); if (SD_SWITCH_FUNC_STATUS_GET_MAX_CURRENT(pSwitchStatusBlock) == 0) { DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: SD Switch Status block has zero max current \n")); SDLIB_PrintBuffer(pSwitchStatusBlock, SD_SWITCH_FUNC_STATUS_BLOCK_BYTES, "SDIO Bus Driver: SD Switch Status Block Error"); } else { /* check HS support */ if (switchGroupMask & (1 << SD_SWITCH_HIGH_SPEED_FUNC_NO)) { DBG_PRINT(SDDBG_TRACE, ("SD Card Supports High Speed Mode\n")); /* set the rate, this will override the CSD value */ cardReportedRate = SD_HS_MAX_BUS_CLOCK; pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_SD_HS; } } } else { DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get SD Switch Status block (%d)\n", status)); /* just fall through, we'll handle this like a normal SD card */ status = SDIO_STATUS_SUCCESS; } KernelFree(pSwitchStatusBlock); }#endif // CT_CONFIG_NO_SDMMC#ifndef CT_CONFIG_NO_SDMMC if ((pHcd->CardProperties.Flags & CARD_MMC) && SDDEVICE_IS_MMC_REV_GTEQ_4_0(pHcd->pPseudoDev) && (pHcd->Attributes & SDHCD_ATTRIB_MMC_HIGH_SPEED) && !spiMode) { /* for MMC cards, get the Extended CSD to get the High speed and * wide bus paramaters */ PUINT8 pExtData = KernelAlloc(MMC_EXT_CSD_SIZE); if (NULL == pExtData) { status = SDIO_STATUS_NO_RESOURCES; break; } /* issue simple data transfer request to read the extended CSD */ status = _IssueBusRequestBd(pHcd,MMC_CMD8,0, SDREQ_FLAGS_RESP_R1 | SDREQ_FLAGS_DATA_TRANS, pReq, pExtData, MMC_EXT_CSD_SIZE); if (SDIO_SUCCESS(status)) { DBG_PRINT(SDDBG_TRACE, ("MMC Ext CSD Version: 0x%X Card Type: 0x%X\n", pExtData[MMC_EXT_VER_OFFSET],pExtData[MMC_EXT_CARD_TYPE_OFFSET])); /* check HS support */ if (pExtData[MMC_EXT_CARD_TYPE_OFFSET] & MMC_EXT_CARD_TYPE_HS_52) { /* try 52 Mhz */ cardReportedRate = 52000000; pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_MMC_HS; } else if (pExtData[MMC_EXT_CARD_TYPE_OFFSET] & MMC_EXT_CARD_TYPE_HS_26) { /* try 26MHZ */ cardReportedRate = 26000000; pBusMode->BusModeFlags |= SDCONFIG_BUS_MODE_MMC_HS; } else { /* doesn't report high speed capable */ cardReportedRate = 0; } if (cardReportedRate && !spiMode) { /* figure out the bus mode */ if (pHcd->Attributes & SDHCD_ATTRIB_BUS_MMC8BIT) { SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_MMC8_BIT); } else if (pHcd->Attributes & SDHCD_ATTRIB_BUS_4BIT) { SDCONFIG_SET_BUS_WIDTH(pBusMode->BusModeFlags, SDCONFIG_BUS_WIDTH_4_BIT); } else { /* we leave it to default to 1 bit mode */ } } } else { DBG_PRINT(SDDBG_ERROR, ("SDIO Bus Driver: Failed to get MMC Extended CSD \n")); /* just fall through, we'll do without the extended information * and run it like a legacy MMC card */ status = SDIO_STATUS_SUCCESS; } KernelFree(pExtData); }#endif // CT_CONFIG_NO_SDMMC#ifndef CT_CONFIG_NO_SDMMC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -