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