00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "board.h"
00042 #include "sdmmc.h"
00043
00044 #include <assert.h>
00045
00046
00047
00048
00049
00050
00051
00052
00053 #define MCI_ENABLE(pMciHw) HSMCI_Enable(pMciHw)
00054
00055 #define MCI_DISABLE(pMciHw) HSMCI_Disable(pMciHw)
00056
00057 #define MCI_RESET(pMciHw) HSMCI_Reset(pMciHw, 0)
00058
00059
00060 #define toHWCOUNT(byteCnt) (((byteCnt)&0x1) ? (((byteCnt)/2)+1) : ((byteCnt)/2))
00061
00062 #define toWCOUNT(byteCnt) (((byteCnt)&0x3) ? (((byteCnt)/4)+1) : ((byteCnt)/4))
00063
00064
00065
00066 #define STATUS_ERRORS ((uint32_t)(HSMCI_SR_UNRE \
00067 | HSMCI_SR_OVRE \
00068 | HSMCI_SR_ACKRCVE \
00069 | HSMCI_SR_CSTOE \
00070 | HSMCI_SR_DTOE \
00071 | HSMCI_SR_DCRCE \
00072 | HSMCI_SR_RTOE \
00073 | HSMCI_SR_RENDE \
00074 | HSMCI_SR_RCRCE \
00075 | HSMCI_SR_RDIRE \
00076 | HSMCI_SR_RINDE))
00077
00078
00079 #define STATUS_ERRORS_RESP ((uint32_t)(HSMCI_SR_CSTOE \
00080 | HSMCI_SR_RTOE \
00081 | HSMCI_SR_RENDE \
00082 | HSMCI_SR_RCRCE \
00083 | HSMCI_SR_RDIRE \
00084 | HSMCI_SR_RINDE))
00085
00086
00087 #define STATUS_ERRORS_DATA ((uint32_t)(HSMCI_SR_UNRE \
00088 | HSMCI_SR_OVRE \
00089 | HSMCI_SR_DTOE \
00090 | HSMCI_SR_DCRCE))
00091
00092
00093 #define MAX_DMA_SIZE (XDMAC_MAX_BT_SIZE & 0xFFFFFF00)
00094
00095
00096 #define _CMDR_SDMEM_SINGLE \
00097 (HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_SINGLE)
00098
00099 #define _CMDR_SDMEM_MULTI \
00100 (HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_MULTIPLE)
00101
00102 #define _CMDR_SDIO_BYTE \
00103 (HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_BYTE)
00104
00105 #define _CMDR_SDIO_BLOCK \
00106 (HSMCI_CMDR_TRCMD_START_DATA | HSMCI_CMDR_TRTYP_BLOCK)
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 static sSdHalFunctions sdHal = {
00122 (fSdmmcLock)MCID_Lock,
00123 (fSdmmcRelease)MCID_Release,
00124 (fSdmmcSendCommand)MCID_SendCmd,
00125 (fSdmmcIOCtrl)MCID_IOCtrl
00126 };
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 static uint8_t _PeripheralEnable(uint32_t id)
00140 {
00141 if (PMC_IsPeriphEnabled(id)) return 0;
00142 PMC_EnablePeripheral(id);
00143 return 1;
00144 }
00145
00146
00147
00148
00149 static uint32_t _MciDMAPrepare(sMcid *pMcid, uint8_t bRd)
00150 {
00151 sXdmad *pXdmad = pMcid->pXdmad;
00152
00153 if (bRd) {
00154 pMcid->dwDmaCh = XDMAD_AllocateChannel
00155 (pXdmad, pMcid->bID, XDMAD_TRANSFER_MEMORY);
00156 } else {
00157 pMcid->dwDmaCh = XDMAD_AllocateChannel
00158 (pXdmad, XDMAD_TRANSFER_MEMORY, pMcid->bID);
00159 }
00160 if (pMcid->dwDmaCh == XDMAD_ALLOC_FAILED) {
00161 return SDMMC_ERROR_BUSY;
00162 }
00163 XDMAD_SetCallback(pXdmad, pMcid->dwDmaCh, NULL, NULL);
00164 XDMAD_PrepareChannel( pXdmad, pMcid->dwDmaCh );
00165 return SDMMC_SUCCESS;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174 static LinkedListDescriporView1 dmaLinkList[256];
00175
00176 static uint32_t _MciDMA(sMcid *pMcid, uint32_t bFByte, uint8_t bRd)
00177 {
00178 Hsmci *pHw = pMcid->pMciHw;
00179 sXdmad *pXdmad = pMcid->pXdmad;
00180 sSdmmcCommand *pCmd = pMcid->pCmd;
00181 sXdmadCfg xdmadRxCfg,xdmadTxCfg;
00182 uint32_t xdmaCndc, xdmaInt;
00183 uint32_t hsmciId;
00184 uint8_t i;
00185 uint32_t totalSize = pCmd->wNbBlocks * pCmd->wBlockSize;
00186 uint32_t maxXSize;
00187 uint32_t memAddress;
00188 uint8_t bMByte;
00189
00190 if (pMcid->dwXfrNdx >= totalSize) return 0;
00191
00192 if(pCmd->wBlockSize != 1) {
00193 pMcid->dwXSize = totalSize - pMcid->dwXfrNdx;
00194 hsmciId = ID_HSMCI;
00195 if (bRd) {
00196 for ( i = 0; i < pCmd->wNbBlocks; i++) {
00197 dmaLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1
00198 | (( i == pCmd->wNbBlocks - 1) ? 0: XDMA_UBC_NDE_FETCH_EN)
00199 | XDMA_UBC_NDEN_UPDATED
00200 | pCmd->wBlockSize /4 ;
00201 dmaLinkList[i].mbr_sa = (uint32_t)&(pHw->HSMCI_FIFO[i]);
00202 dmaLinkList[i].mbr_da = (uint32_t)&pCmd->pData[i * pCmd->wBlockSize];
00203 if ( i == pCmd->wNbBlocks - 1)
00204 dmaLinkList[i].mbr_nda = 0;
00205 else
00206 dmaLinkList[i].mbr_nda = (uint32_t)&dmaLinkList[ i + 1 ];
00207 }
00208 xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN
00209 | XDMAC_CC_MBSIZE_SINGLE
00210 | XDMAC_CC_DSYNC_PER2MEM
00211 | XDMAC_CC_CSIZE_CHK_1
00212 | XDMAC_CC_DWIDTH_WORD
00213 | XDMAC_CC_SIF_AHB_IF1
00214 | XDMAC_CC_DIF_AHB_IF0
00215 | XDMAC_CC_SAM_FIXED_AM
00216 | XDMAC_CC_DAM_INCREMENTED_AM
00217 | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber
00218 (hsmciId, XDMAD_TRANSFER_RX ));
00219 xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1
00220 | XDMAC_CNDC_NDE_DSCR_FETCH_EN
00221 | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED
00222 | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED ;
00223
00224
00225 if (XDMAD_ConfigureTransfer( pXdmad, pMcid->dwDmaCh,
00226 &xdmadRxCfg, xdmaCndc, (uint32_t)&dmaLinkList[0],
00227 XDMAC_CIE_LIE)) {
00228 return 0;
00229 }
00230
00231 SCB_CleanInvalidateDCache();
00232
00233 if (XDMAD_StartTransfer(pXdmad,pMcid->dwDmaCh)) {
00234 return 0;
00235 }
00236
00237 } else {
00238 for ( i = 0; i < pCmd->wNbBlocks; i++){
00239 dmaLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1
00240 |(( i == pCmd->wNbBlocks - 1) ? 0: XDMA_UBC_NDE_FETCH_EN)
00241 | XDMA_UBC_NDEN_UPDATED
00242 | pCmd->wBlockSize /4 ;
00243 dmaLinkList[i].mbr_sa = (uint32_t)&pCmd->pData[i * pCmd->wBlockSize];
00244 dmaLinkList[i].mbr_da = (uint32_t)&(pHw->HSMCI_FIFO[i]);
00245
00246 SCB_CleanDCache_by_Addr((uint32_t *)&pCmd->pData[i * pCmd->wBlockSize],pCmd->wBlockSize);
00247 if ( i == pCmd->wNbBlocks - 1) dmaLinkList[i].mbr_nda = 0;
00248 else dmaLinkList[i].mbr_nda = (uint32_t)&dmaLinkList[ i + 1 ];
00249 }
00250 xdmadTxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN
00251 | XDMAC_CC_MBSIZE_SINGLE
00252 | XDMAC_CC_DSYNC_MEM2PER
00253 | XDMAC_CC_CSIZE_CHK_1
00254 | XDMAC_CC_DWIDTH_WORD
00255 | XDMAC_CC_SIF_AHB_IF0
00256 | XDMAC_CC_DIF_AHB_IF1
00257 | XDMAC_CC_SAM_INCREMENTED_AM
00258 | XDMAC_CC_DAM_FIXED_AM
00259 | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(hsmciId, XDMAD_TRANSFER_TX ));
00260 xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1
00261 | XDMAC_CNDC_NDE_DSCR_FETCH_EN
00262 | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED
00263 | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED ;
00264 if(XDMAD_ConfigureTransfer( pXdmad, pMcid->dwDmaCh,
00265 &xdmadTxCfg, xdmaCndc, (uint32_t)&dmaLinkList[0],
00266 XDMAC_CIE_LIE)){
00267 return 0;
00268 }
00269
00270 if (XDMAD_StartTransfer(pXdmad,pMcid->dwDmaCh)) {
00271 return 0;
00272 }
00273 }
00274 } else {
00275
00276 memAddress = (uint32_t)&pCmd->pData[pMcid->dwXfrNdx];
00277 bMByte = bFByte ? 1 : (((memAddress & 0x3) || (totalSize & 0x3)));
00278
00279 if (bRd) {
00280 maxXSize = bFByte ? MAX_DMA_SIZE : (MAX_DMA_SIZE * 4);
00281 } else {
00282
00283 maxXSize = bMByte ? MAX_DMA_SIZE : (MAX_DMA_SIZE * 4);
00284 }
00285
00286 pMcid->dwXSize = totalSize - pMcid->dwXfrNdx;
00287 if (pMcid->dwXSize > maxXSize) {
00288 pMcid->dwXSize = maxXSize;
00289 }
00290
00291 if (bRd) {
00292 xdmadRxCfg.mbr_ubc = bFByte ? pMcid->dwXSize : toWCOUNT(pMcid->dwXSize);
00293 xdmadRxCfg.mbr_sa = (uint32_t)&(pHw->HSMCI_RDR);
00294 xdmadRxCfg.mbr_da = (uint32_t)memAddress;
00295 xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
00296 XDMAC_CC_MEMSET_NORMAL_MODE |
00297 XDMAC_CC_DSYNC_PER2MEM|
00298 XDMAC_CC_CSIZE_CHK_1 |
00299 (bFByte ? XDMAC_CC_DWIDTH_BYTE : XDMAC_CC_DWIDTH_WORD) |
00300 XDMAC_CC_SIF_AHB_IF1 |
00301 XDMAC_CC_DIF_AHB_IF0 |
00302 XDMAC_CC_SAM_FIXED_AM |
00303 XDMAC_CC_DAM_INCREMENTED_AM;
00304 xdmadRxCfg.mbr_bc = 0;
00305 xdmaInt = (XDMAC_CIE_BIE |
00306 XDMAC_CIE_DIE |
00307 XDMAC_CIE_FIE |
00308 XDMAC_CIE_RBIE |
00309 XDMAC_CIE_WBIE |
00310 XDMAC_CIE_ROIE);
00311
00312 XDMAD_ConfigureTransfer( pXdmad, pMcid->dwDmaCh, &xdmadRxCfg,
00313 0, 0, xdmaInt);
00314 } else {
00315 xdmadTxCfg.mbr_ubc = toWCOUNT(pMcid->dwXSize);
00316 xdmadTxCfg.mbr_sa = (uint32_t)memAddress;
00317 xdmadTxCfg.mbr_da = (uint32_t)&(pHw->HSMCI_TDR);
00318 xdmadTxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
00319 XDMAC_CC_MEMSET_NORMAL_MODE |
00320 XDMAC_CC_DSYNC_MEM2PER |
00321 XDMAC_CC_CSIZE_CHK_1 |
00322 (bFByte ? XDMAC_CC_DWIDTH_BYTE : XDMAC_CC_DWIDTH_WORD) |
00323 XDMAC_CC_SIF_AHB_IF0 |
00324 XDMAC_CC_DIF_AHB_IF1 |
00325 XDMAC_CC_SAM_INCREMENTED_AM |
00326 XDMAC_CC_DAM_FIXED_AM;
00327 xdmadTxCfg.mbr_bc = 0;
00328
00329 xdmaInt = (XDMAC_CIE_BIE |
00330 XDMAC_CIE_DIE |
00331 XDMAC_CIE_FIE |
00332 XDMAC_CIE_RBIE |
00333 XDMAC_CIE_WBIE |
00334 XDMAC_CIE_ROIE);
00335
00336 XDMAD_ConfigureTransfer( pXdmad, pMcid->dwDmaCh, &xdmadTxCfg,
00337 0, 0, xdmaInt);
00338 }
00339 SCB_CleanInvalidateDCache();
00340 XDMAD_StartTransfer(pXdmad, pMcid->dwDmaCh);
00341 }
00342 return 1;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 static void MCI_Reset(sMcid *pMci, uint8_t keepSettings)
00355 {
00356 Hsmci *pMciHw = pMci->pMciHw;
00357
00358 assert(pMci);
00359 assert(pMci->pMciHw);
00360
00361 HSMCI_Reset( pMciHw, keepSettings );
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 static uint32_t MCI_SetSpeed( sMcid* pMci, uint32_t mciSpeed, uint32_t mck )
00373 {
00374 Hsmci *pMciHw = pMci->pMciHw;
00375 uint32_t clkdiv;
00376 assert(pMci);
00377 assert(pMciHw);
00378
00379 if((mck % mciSpeed) == 0) {
00380 clkdiv = mck /mciSpeed;
00381 } else {
00382 clkdiv = ((mck + mciSpeed)/mciSpeed);
00383 }
00384 mciSpeed = mck / clkdiv;
00385
00386
00387 HSMCI_DivCtrl( pMciHw, clkdiv, 0x7);
00388 return (mciSpeed);
00389 }
00390
00391
00392
00393 static void _FinishCmd( sMcid* pMcid, uint8_t bStatus )
00394 {
00395 sSdmmcCommand *pCmd = pMcid->pCmd;
00396 sXdmad *pXdmad = pMcid->pXdmad;
00397
00398
00399 if (pMcid->dwDmaCh != XDMAD_ALLOC_FAILED) {
00400 if (XDMAD_FreeChannel(pXdmad, pMcid->dwDmaCh)) {
00401 TRACE_ERROR(" Can't free channel \n\r" );
00402 TRACE_DEBUG(" Channel is in %d state\n\r",
00403 pXdmad->XdmaChannels[pMcid->dwDmaCh].state );
00404 }
00405 pMcid->dwDmaCh = XDMAD_ALLOC_FAILED;
00406 }
00407
00408 pMcid->pCmd = NULL;
00409 pMcid->bState = MCID_LOCKED;
00410 pCmd->bStatus = bStatus;
00411
00412 if (pCmd->fCallback) {
00413 (pCmd->fCallback)(pCmd->bStatus, pCmd->pArg);
00414 }
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424 void MCID_SetSlot(Hsmci *pMci, uint8_t slot)
00425
00426 {
00427 HSMCI_SetSlot(pMci, slot);
00428 }
00429
00430
00431
00432
00433 void MCID_Init(sMcid *pMcid,
00434 Hsmci *pMci, uint8_t bID, uint32_t dwMck,
00435 sXdmad *pXdmad,
00436 uint8_t bPolling)
00437 {
00438 uint16_t clkDiv;
00439
00440 assert(pMcid);
00441 assert(pMci);
00442
00443
00444 pMcid->pMciHw = pMci;
00445 pMcid->pCmd = NULL;
00446
00447 pMcid->pXdmad = pXdmad;
00448 pMcid->dwDmaCh = XDMAD_ALLOC_FAILED;
00449 pMcid->dwXfrNdx = 0;
00450
00451 pMcid->dwMck = dwMck;
00452
00453 pMcid->bID = bID;
00454 pMcid->bPolling = bPolling;
00455 pMcid->bState = MCID_IDLE;
00456
00457 _PeripheralEnable( bID );
00458
00459 MCI_RESET( pMci );
00460 MCI_DISABLE ( pMci );
00461 HSMCI_DisableIt( pMci, 0xFFFFFFFF );
00462 HSMCI_ConfigureDataTO( pMci, HSMCI_DTOR_DTOCYC(0xFF)
00463 |HSMCI_DTOR_DTOMUL_1048576 );
00464 HSMCI_ConfigureCompletionTO( pMci , HSMCI_CSTOR_CSTOCYC(0xFF)
00465 |HSMCI_CSTOR_CSTOMUL_1048576 );
00466
00467 clkDiv = (dwMck / (MCI_INITIAL_SPEED << 1)) - 1;
00468 HSMCI_ConfigureMode( pMci, (clkDiv | HSMCI_MR_PWSDIV(0x7)) );
00469
00470 HSMCI_Enable( pMci );
00471 HSMCI_Configure( pMci, HSMCI_CFG_FIFOMODE | HSMCI_CFG_FERRCTRL );
00472
00473 HSMCI_EnableDma( pMci, 1 );
00474
00475 }
00476
00477
00478
00479
00480 uint32_t MCID_Lock(sMcid *pMcid, uint8_t bSlot)
00481 {
00482 Hsmci *pHw = pMcid->pMciHw;
00483 uint32_t sdcr;
00484
00485 assert(pMcid);
00486 assert(pMcid->pMciHw);
00487
00488 if (bSlot > 0) {
00489 return SDMMC_ERROR_PARAM;
00490 }
00491 if (pMcid->bState >= MCID_LOCKED) {
00492 return SDMMC_ERROR_LOCKED;
00493 }
00494 pMcid->bState = MCID_LOCKED;
00495 sdcr = pHw->HSMCI_SDCR & ~(uint32_t)HSMCI_SDCR_SDCSEL_Msk;
00496 pHw->HSMCI_SDCR = sdcr | (bSlot << HSMCI_SDCR_SDCSEL_Pos);
00497 return SDMMC_OK;
00498 }
00499
00500
00501
00502
00503 uint32_t MCID_Release(sMcid *pMcid)
00504 {
00505 assert(pMcid);
00506
00507 if (pMcid->bState >= MCID_CMD) {
00508 return SDMMC_ERROR_BUSY;
00509 }
00510 pMcid->bState = MCID_IDLE;
00511 return SDMMC_OK;
00512 }
00513
00514
00515
00516
00517 uint32_t MCID_SendCmd(sMcid *pMcid, void *pCommand)
00518 {
00519 Hsmci *pHw = pMcid->pMciHw;
00520 sSdmmcCommand *pCmd = pCommand;
00521 uint32_t mr, ier;
00522 uint32_t cmdr;
00523
00524 assert(pMcid);
00525 assert(pMcid->pMciHw);
00526 assert(pCmd);
00527
00528 if (!MCID_IsCmdCompleted(pMcid))
00529 {
00530 return SDMMC_ERROR_BUSY;
00531 }
00532 pMcid->bState = MCID_CMD;
00533 pMcid->pCmd = pCmd;
00534
00535
00536 MCI_DISABLE(pHw);
00537 mr = HSMCI_GetMode(pHw) & (~(uint32_t)(HSMCI_MR_WRPROOF |
00538 HSMCI_MR_RDPROOF |HSMCI_MR_FBYTE));
00539
00540 if (pCmd->cmdOp.wVal == SDMMC_CMD_POWERONINIT){
00541 HSMCI_ConfigureMode(pHw, mr);
00542 ier = HSMCI_IER_XFRDONE;
00543 } else if (pCmd->cmdOp.bmBits.xfrData == SDMMC_CMD_STOPXFR) {
00544
00545 HSMCI_ConfigureMode(pHw, mr);
00546 ier = HSMCI_IER_XFRDONE | STATUS_ERRORS_RESP;
00547 }
00548
00549 else if ((pCmd->cmdOp.wVal & SDMMC_CMD_CNODATA(0xF)) == SDMMC_CMD_CNODATA(0)) {
00550 ier = HSMCI_IER_XFRDONE | STATUS_ERRORS_RESP;
00551
00552 if (pCmd->cmdOp.bmBits.respType == 3) {
00553 ier &= ~(uint32_t)HSMCI_IER_RCRCE;
00554 }
00555 } else if (pCmd->wNbBlocks == 0 || pCmd->pData == 0) {
00556
00557 HSMCI_ConfigureMode(pHw, mr | HSMCI_MR_WRPROOF
00558 | HSMCI_MR_RDPROOF);
00559 HSMCI_ConfigureTransfer(pHw, pCmd->wBlockSize, pCmd->wNbBlocks);
00560 ier = HSMCI_IER_CMDRDY | STATUS_ERRORS_RESP;
00561 } else {
00562
00563
00564 if (pCmd->cmdOp.bmBits.sendCmd) {
00565 HSMCI_ConfigureTransfer(pHw, pCmd->wBlockSize, pCmd->wNbBlocks);
00566 }
00567
00568 if (pCmd->wBlockSize == 0)
00569 pCmd->wBlockSize = 1;
00570
00571
00572 if (pCmd->wBlockSize & 0x3) {
00573 mr |= HSMCI_MR_FBYTE;
00574 }
00575
00576 HSMCI_ConfigureMode(pHw, mr | HSMCI_MR_WRPROOF
00577 | HSMCI_MR_RDPROOF
00578 | (pCmd->wBlockSize << 16));
00579
00580 if (pCmd->cmdOp.bmBits.xfrData == SDMMC_CMD_TX) {
00581 if (_MciDMAPrepare(pMcid, 0)) {
00582 _FinishCmd(pMcid, SDMMC_ERROR_BUSY);
00583 return SDMMC_ERROR_BUSY;
00584 }
00585 _MciDMA(pMcid, (mr & HSMCI_MR_FBYTE),0);
00586 ier = HSMCI_IER_XFRDONE | STATUS_ERRORS_DATA;
00587 if( pCmd->wNbBlocks > 1 ) ier |= HSMCI_IER_FIFOEMPTY;
00588 } else {
00589 if (_MciDMAPrepare(pMcid, 1)) {
00590 _FinishCmd(pMcid, SDMMC_ERROR_BUSY);
00591 return SDMMC_ERROR_BUSY;
00592 }
00593 _MciDMA(pMcid, (mr & HSMCI_MR_FBYTE),1);
00594 ier = HSMCI_IER_XFRDONE | STATUS_ERRORS_DATA;
00595 if( pCmd->wNbBlocks > 1 ) ier |= HSMCI_IER_FIFOEMPTY;
00596 }
00597 }
00598 MCI_ENABLE(pHw);
00599 if (pCmd->cmdOp.wVal & (SDMMC_CMD_bmPOWERON | SDMMC_CMD_bmCOMMAND)) {
00600 cmdr = pCmd->bCmd;
00601
00602 if (pCmd->cmdOp.bmBits.powerON) {
00603 cmdr |= (HSMCI_CMDR_OPDCMD | HSMCI_CMDR_SPCMD_INIT);
00604 }
00605 if (pCmd->cmdOp.bmBits.odON) {
00606 cmdr |= HSMCI_CMDR_OPDCMD;
00607 }
00608 if (pCmd->cmdOp.bmBits.sendCmd) {
00609 cmdr |= HSMCI_CMDR_MAXLAT;
00610 }
00611 switch(pCmd->cmdOp.bmBits.xfrData) {
00612 case SDMMC_CMD_TX:
00613 if (pCmd->cmdOp.bmBits.ioCmd) {
00614 cmdr |= (pCmd->wBlockSize == 1) ?
00615 _CMDR_SDIO_BYTE :
00616 _CMDR_SDIO_BLOCK;
00617 } else {
00618 cmdr |= (pCmd->wNbBlocks == 1) ?
00619 _CMDR_SDMEM_SINGLE :
00620 _CMDR_SDMEM_MULTI;
00621 }
00622 break;
00623
00624 case SDMMC_CMD_RX:
00625 if (pCmd->cmdOp.bmBits.ioCmd) {
00626 cmdr |= HSMCI_CMDR_TRDIR_READ
00627 |((pCmd->wBlockSize == 1) ?
00628 _CMDR_SDIO_BYTE :
00629 _CMDR_SDIO_BLOCK) ;
00630 } else {
00631 cmdr |= HSMCI_CMDR_TRDIR_READ
00632 |((pCmd->wNbBlocks == 1) ?
00633 _CMDR_SDMEM_SINGLE :
00634 _CMDR_SDMEM_MULTI) ;
00635 }
00636 break;
00637
00638 case SDMMC_CMD_STOPXFR:
00639 cmdr |= HSMCI_CMDR_TRCMD_STOP_DATA;
00640 break;
00641 }
00642
00643 switch(pCmd->cmdOp.bmBits.respType) {
00644 case 3: case 4:
00645
00646 ier &= ~(uint32_t)HSMCI_IER_RCRCE;
00647 case 1: case 5: case 6: case 7:
00648 cmdr |= HSMCI_CMDR_RSPTYP_48_BIT;
00649 break;
00650 case 2:
00651 cmdr |= HSMCI_CMDR_RSPTYP_136_BIT;
00652 break;
00653
00654 default:
00655 ier &= ~(uint32_t)HSMCI_IER_RTOE;
00656 }
00657
00658 pHw->HSMCI_ARGR = pCmd->dwArg;
00659 pHw->HSMCI_CMDR = cmdr;
00660 }
00661
00662
00663 if (pCmd->cmdOp.bmBits.xfrData == SDMMC_CMD_STOPXFR) {
00664 ier &= ~STATUS_ERRORS_DATA;
00665 }
00666
00667 HSMCI_EnableIt(pHw, ier);
00668 return SDMMC_OK;
00669 }
00670
00671 static uint32_t dwMsk;
00672
00673
00674
00675 void MCID_Handler(sMcid *pMcid)
00676 {
00677 Hsmci *pHw = pMcid->pMciHw;
00678 sSdmmcCommand *pCmd = pMcid->pCmd;
00679
00680 uint32_t dwSr, dwMaskedSr;
00681 assert(pMcid);
00682 assert(pMcid->pMciHw);
00683
00684
00685 if (pCmd == NULL) {
00686 if (pMcid->bState >= MCID_CMD) {
00687 pMcid->bState = MCID_LOCKED;
00688 }
00689 return;
00690 }
00691
00692
00693 dwSr = HSMCI_GetStatus(pHw);
00694 dwMsk = HSMCI_GetItMask(pHw);
00695 dwMaskedSr = dwSr & dwMsk;
00696
00697 if (dwMaskedSr & STATUS_ERRORS) {
00698 if (dwMaskedSr & HSMCI_SR_RTOE) {
00699 pCmd->bStatus = SDMMC_ERROR_NORESPONSE;
00700 }
00701 if (pCmd->bCmd != 12) pMcid->bState = MCID_ERROR;
00702
00703 }
00704 dwMsk &= ~STATUS_ERRORS;
00705
00706
00707 if (dwMaskedSr & HSMCI_SR_CMDRDY) {
00708 TRACE_DEBUG("HSMCI_SR_CMDRDY \n\r");
00709 HSMCI_DisableIt(pHw, HSMCI_IDR_CMDRDY);
00710 dwMsk &= ~(uint32_t)HSMCI_IMR_CMDRDY;
00711 }
00712
00713
00714 if (dwMaskedSr & HSMCI_SR_NOTBUSY) {
00715 TRACE_DEBUG("NOTBUSY ");
00716 HSMCI_DisableIt(pHw, HSMCI_IDR_NOTBUSY);
00717 dwMsk &= ~(uint32_t)HSMCI_IMR_NOTBUSY;
00718 }
00719
00720 if (dwMaskedSr & HSMCI_SR_TXRDY) {
00721 TRACE_DEBUG("TXRDY ");
00722 dwMsk &= ~(uint32_t)HSMCI_IMR_TXRDY;
00723 }
00724
00725 if (dwMaskedSr & HSMCI_SR_FIFOEMPTY) {
00726
00727 HSMCI_DisableIt(pHw, HSMCI_IDR_FIFOEMPTY);
00728 dwMsk &= ~(uint32_t)HSMCI_IMR_FIFOEMPTY;
00729 TRACE_DEBUG("FIFOEMPTY %x \n\r",dwMsk);
00730 }
00731
00732
00733 if (dwMaskedSr & HSMCI_SR_XFRDONE) {
00734 HSMCI_DisableIt(pHw, HSMCI_IDR_XFRDONE);
00735 dwMsk &= ~(uint32_t)HSMCI_IMR_XFRDONE;
00736 TRACE_DEBUG("HSMCI_SR_XFRDONE %x \n\r",dwMsk);
00737 }
00738
00739
00740 if (0 == dwMsk || pMcid->bState == MCID_ERROR) {
00741
00742 if (pMcid->bState == MCID_ERROR) {
00743 MCI_Reset(pMcid, 1);
00744 } else {
00745 pCmd->bStatus = SDMMC_SUCCESS;
00746
00747 if (pCmd->pResp) {
00748 uint8_t bRspSize, i;
00749 switch(pCmd->cmdOp.bmBits.respType) {
00750 case 1: case 3: case 4: case 5: case 6: case 7:
00751 bRspSize = 1;
00752 break;
00753
00754 case 2:
00755 bRspSize = 4;
00756 break;
00757
00758 default:
00759 bRspSize = 0;
00760 }
00761 for (i = 0; i < bRspSize; i ++) {
00762 pCmd->pResp[i] = HSMCI_GetResponse(pHw);
00763 }
00764 }
00765 }
00766
00767 HSMCI_DisableIt(pHw, HSMCI_GetItMask(pHw));
00768
00769
00770
00771 _FinishCmd(pMcid, pCmd->bStatus);
00772 }
00773 }
00774
00775
00776
00777
00778 uint32_t MCID_CancelCmd(sMcid *pMcid)
00779 {
00780 if (pMcid->bState == MCID_IDLE) {
00781 return SDMMC_ERROR_STATE;
00782 }
00783 if (pMcid->bState == MCID_CMD) {
00784
00785 MCI_Reset(pMcid, 1);
00786
00787 _FinishCmd(pMcid, SDMMC_ERROR_USER_CANCEL);
00788 }
00789 return SDMMC_OK;
00790 }
00791
00792
00793
00794
00795 void MCID_Reset(sMcid * pMcid)
00796 {
00797 Hsmci *pHw = pMcid->pMciHw;
00798
00799 MCID_CancelCmd(pMcid);
00800
00801
00802
00803
00804 MCI_DISABLE(pHw);
00805
00806 HSMCI_ConfigureMode(pHw, HSMCI_GetMode(pHw) & (HSMCI_MR_CLKDIV_Msk
00807 | HSMCI_MR_PWSDIV_Msk));
00808
00809 HSMCI_ConfigureTransfer(pHw, 0, 0);
00810
00811
00812 MCI_Reset(pMcid, 1);
00813
00814
00815 if (pMcid->bState == MCID_CMD) {
00816
00817 _FinishCmd(pMcid, SDMMC_ERROR_USER_CANCEL);
00818 }
00819 }
00820
00821
00822
00823
00824 uint32_t MCID_IsCmdCompleted(sMcid *pMcid)
00825 {
00826 sSdmmcCommand *pCmd = pMcid->pCmd;
00827
00828 if (pMcid->bPolling) {
00829 MCID_Handler(pMcid);
00830 }
00831 if (pMcid->bState == MCID_CMD) {
00832 return 0;
00833 }
00834 if (pCmd) {
00835 return 0;
00836 }
00837 return 1;
00838 }
00839
00840
00841
00842
00843 uint32_t MCID_IOCtrl(sMcid *pMcid, uint32_t bCtl, uint32_t param)
00844 {
00845 Hsmci *pMciHw = pMcid->pMciHw;
00846 assert(pMcid);
00847 assert(pMcid->pMciHw);
00848
00849
00850
00851 switch (bCtl) {
00852 case SDMMC_IOCTL_BUSY_CHECK:
00853 *(uint32_t*)param = !MCID_IsCmdCompleted(pMcid);
00854 break;
00855
00856 case SDMMC_IOCTL_POWER:
00857 return SDMMC_ERROR_NOT_SUPPORT;
00858
00859 case SDMMC_IOCTL_RESET:
00860 MCID_Reset(pMcid);
00861 return SDMMC_SUCCESS;
00862
00863 case SDMMC_IOCTL_CANCEL_CMD:
00864 return MCID_CancelCmd(pMcid);
00865
00866 case SDMMC_IOCTL_SET_CLOCK:
00867 *(uint32_t*)param = MCI_SetSpeed(pMcid,
00868 *(uint32_t*)param,
00869 pMcid->dwMck);
00870 break;
00871
00872 case SDMMC_IOCTL_SET_HSMODE:
00873 HSMCI_HsEnable( pMciHw, *(uint32_t*)param );
00874 *(uint32_t*)param = HSMCI_IsHsEnabled( pMciHw );
00875
00876 break;
00877
00878 case SDMMC_IOCTL_SET_BUSMODE:
00879 HSMCI_SetBusWidth( pMciHw, *(uint32_t*)param );
00880 break;
00881
00882 case SDMMC_IOCTL_GET_BUSMODE:
00883
00884 break;
00885
00886 case SDMMC_IOCTL_GET_HSMODE:
00887 *(uint32_t*)param = 1;
00888 break;
00889
00890 default:
00891 return SDMMC_ERROR_NOT_SUPPORT;
00892 }
00893 return SDMMC_OK;
00894 }
00895
00896
00897
00898
00899
00900 void SDD_InitializeSdmmcMode(sSdCard * pSd,void * pDrv,uint8_t bSlot)
00901 {
00902 SDD_Initialize(pSd, pDrv, bSlot, &sdHal);
00903 }
00904
00905