File indexing completed on 2025-05-11 08:23:02
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "fsl_usdhc.h"
0010 #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
0011 #include "fsl_cache.h"
0012 #endif
0013 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
0014 #include "fsl_memory.h"
0015 #endif
0016
0017
0018
0019
0020
0021 #ifndef FSL_COMPONENT_ID
0022 #define FSL_COMPONENT_ID "platform.drivers.usdhc"
0023 #endif
0024
0025
0026
0027 #define USDHC_MAX_DVS ((USDHC_SYS_CTRL_DVS_MASK >> USDHC_SYS_CTRL_DVS_SHIFT) + 1U)
0028 #define USDHC_MAX_CLKFS ((USDHC_SYS_CTRL_SDCLKFS_MASK >> USDHC_SYS_CTRL_SDCLKFS_SHIFT) + 1U)
0029 #define USDHC_PREV_DVS(x) ((x) -= 1U)
0030 #define USDHC_PREV_CLKFS(x, y) ((x) >>= (y))
0031
0032 #define USDHC_ADMA_TABLE_ADDRESS_ALIGN (4U)
0033
0034
0035 typedef void (*usdhc_isr_t)(USDHC_Type *base, usdhc_handle_t *handle);
0036
0037 #define IS_USDHC_FLAG_SET(reg, flag) (((reg) & ((uint32_t)flag)) != 0UL)
0038
0039
0040 enum _usdhc_transfer_flags
0041 {
0042 kUSDHC_CommandOnly = 1U,
0043 kUSDHC_CommandAndTxData = 2U,
0044 kUSDHC_CommandAndRxData = 4U,
0045 kUSDHC_DataWithAutoCmd12 = 8U,
0046 kUSDHC_DataWithAutoCmd23 = 16U,
0047 kUSDHC_BootData = 32U,
0048 kUSDHC_BootDataContinuous = 64U,
0049 };
0050
0051 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
0052 #define USDHC_ADDR_CPU_2_DMA(addr) (MEMORY_ConvertMemoryMapAddress((addr), kMEMORY_Local2DMA))
0053 #else
0054 #define USDHC_ADDR_CPU_2_DMA(addr) (addr)
0055 #endif
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 static uint32_t USDHC_GetInstance(USDHC_Type *base);
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 static status_t USDHC_SetTransferConfig(USDHC_Type *base,
0076 uint32_t transferFlags,
0077 size_t blockSize,
0078 uint32_t blockCount);
0079
0080
0081
0082
0083
0084
0085
0086 static status_t USDHC_ReceiveCommandResponse(USDHC_Type *base, usdhc_command_t *command);
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 static uint32_t USDHC_ReadDataPort(USDHC_Type *base, usdhc_data_t *data, uint32_t transferredWords);
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 static status_t USDHC_ReadByDataPortBlocking(USDHC_Type *base, usdhc_data_t *data);
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116 static uint32_t USDHC_WriteDataPort(USDHC_Type *base, usdhc_data_t *data, uint32_t transferredWords);
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 static status_t USDHC_WriteByDataPortBlocking(USDHC_Type *base, usdhc_data_t *data);
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138 static status_t USDHC_TransferDataBlocking(USDHC_Type *base, usdhc_data_t *data, bool enDMA);
0139
0140
0141
0142
0143
0144
0145
0146
0147 static status_t USDHC_WaitCommandDone(USDHC_Type *base, usdhc_command_t *command, bool pollingCmdDone);
0148
0149
0150
0151
0152
0153
0154
0155
0156 static void USDHC_TransferHandleCardDetect(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags);
0157
0158
0159
0160
0161
0162
0163
0164
0165 static void USDHC_TransferHandleCommand(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags);
0166
0167
0168
0169
0170
0171
0172
0173
0174 static void USDHC_TransferHandleData(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags);
0175
0176
0177
0178
0179
0180
0181
0182 static void USDHC_TransferHandleSdioInterrupt(USDHC_Type *base, usdhc_handle_t *handle);
0183
0184
0185
0186
0187
0188
0189
0190 static void USDHC_TransferHandleBlockGap(USDHC_Type *base, usdhc_handle_t *handle);
0191
0192 #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (FSL_FEATURE_USDHC_HAS_SDR50_MODE)
0193
0194
0195
0196
0197
0198
0199
0200 static void USDHC_TransferHandleReTuning(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags);
0201 #endif
0202
0203
0204
0205
0206 static USDHC_Type *const s_usdhcBase[] = USDHC_BASE_PTRS;
0207
0208
0209 static usdhc_handle_t *s_usdhcHandle[ARRAY_SIZE(s_usdhcBase)] = {0};
0210
0211
0212 static const IRQn_Type s_usdhcIRQ[] = USDHC_IRQS;
0213
0214 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0215
0216 static const clock_ip_name_t s_usdhcClock[] = USDHC_CLOCKS;
0217 #endif
0218
0219 #if (defined(FSL_FEATURE_USDHC_HAS_RESET) && FSL_FEATURE_USDHC_HAS_RESET)
0220
0221 static const reset_ip_name_t s_usdhcResets[] = USDHC_RSTS;
0222 #endif
0223
0224
0225 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
0226 static usdhc_isr_t s_usdhcIsr = (usdhc_isr_t)DefaultISR;
0227 #else
0228 static usdhc_isr_t s_usdhcIsr;
0229 #endif
0230
0231 AT_NONCACHEABLE_SECTION_ALIGN(static uint32_t s_usdhcBootDummy, USDHC_ADMA2_ADDRESS_ALIGN);
0232
0233
0234
0235
0236 static uint32_t USDHC_GetInstance(USDHC_Type *base)
0237 {
0238 uint8_t instance = 0;
0239
0240 while ((instance < ARRAY_SIZE(s_usdhcBase)) && (s_usdhcBase[instance] != base))
0241 {
0242 instance++;
0243 }
0244
0245 assert(instance < ARRAY_SIZE(s_usdhcBase));
0246
0247 return instance;
0248 }
0249
0250 static status_t USDHC_SetTransferConfig(USDHC_Type *base, uint32_t transferFlags, size_t blockSize, uint32_t blockCount)
0251 {
0252 uint32_t mixCtrl = base->MIX_CTRL;
0253
0254 if (((uint32_t)kUSDHC_CommandOnly & transferFlags) != 0U)
0255 {
0256
0257 mixCtrl &= ~(USDHC_MIX_CTRL_MSBSEL_MASK | USDHC_MIX_CTRL_BCEN_MASK | USDHC_MIX_CTRL_DTDSEL_MASK |
0258 USDHC_MIX_CTRL_AC12EN_MASK | USDHC_MIX_CTRL_AC23EN_MASK);
0259
0260 if (IS_USDHC_FLAG_SET(base->PRES_STATE, kUSDHC_CommandInhibitFlag))
0261 {
0262 return kStatus_USDHC_BusyTransferring;
0263 }
0264 }
0265 else
0266 {
0267
0268 if ((transferFlags & (uint32_t)kUSDHC_BootDataContinuous) != 0U)
0269 {
0270
0271 base->PROT_CTRL &= ~USDHC_PROT_CTRL_SABGREQ_MASK;
0272
0273 base->PROT_CTRL |= USDHC_PROT_CTRL_CREQ_MASK;
0274 return kStatus_Success;
0275 }
0276
0277
0278 if (IS_USDHC_FLAG_SET(base->PRES_STATE, kUSDHC_DataInhibitFlag))
0279 {
0280 return kStatus_USDHC_BusyTransferring;
0281 }
0282
0283 if ((blockCount > USDHC_MAX_BLOCK_COUNT))
0284 {
0285 return kStatus_InvalidArgument;
0286 }
0287
0288
0289 mixCtrl &= ~(USDHC_MIX_CTRL_MSBSEL_MASK | USDHC_MIX_CTRL_BCEN_MASK | USDHC_MIX_CTRL_DTDSEL_MASK |
0290 USDHC_MIX_CTRL_AC12EN_MASK);
0291
0292 if ((transferFlags & (uint32_t)kUSDHC_CommandAndRxData) != 0U)
0293 {
0294 mixCtrl |= USDHC_MIX_CTRL_DTDSEL_MASK;
0295 }
0296
0297 if (blockCount > 1U)
0298 {
0299 mixCtrl |= USDHC_MIX_CTRL_MSBSEL_MASK | USDHC_MIX_CTRL_BCEN_MASK;
0300
0301 if ((transferFlags & (uint32_t)kUSDHC_DataWithAutoCmd12) != 0U)
0302 {
0303 mixCtrl |= USDHC_MIX_CTRL_AC12EN_MASK;
0304 }
0305 }
0306
0307
0308 if ((transferFlags & (uint32_t)kUSDHC_DataWithAutoCmd23) != 0U)
0309 {
0310 mixCtrl |= USDHC_MIX_CTRL_AC23EN_MASK;
0311 base->VEND_SPEC2 |= USDHC_VEND_SPEC2_ACMD23_ARGU2_EN_MASK;
0312
0313 base->DS_ADDR = blockCount;
0314 }
0315 else
0316 {
0317 mixCtrl &= ~USDHC_MIX_CTRL_AC23EN_MASK;
0318 base->VEND_SPEC2 &= ~USDHC_VEND_SPEC2_ACMD23_ARGU2_EN_MASK;
0319 }
0320
0321
0322 if ((transferFlags & (uint32_t)kUSDHC_BootData) == 0U)
0323 {
0324
0325 base->BLK_ATT = ((base->BLK_ATT & ~(USDHC_BLK_ATT_BLKSIZE_MASK | USDHC_BLK_ATT_BLKCNT_MASK)) |
0326 (USDHC_BLK_ATT_BLKSIZE(blockSize) | USDHC_BLK_ATT_BLKCNT(blockCount)));
0327 }
0328 else
0329 {
0330 mixCtrl |= USDHC_MIX_CTRL_MSBSEL_MASK | USDHC_MIX_CTRL_BCEN_MASK;
0331 base->PROT_CTRL |= USDHC_PROT_CTRL_RD_DONE_NO_8CLK_MASK;
0332 }
0333 }
0334
0335 base->MIX_CTRL = mixCtrl;
0336
0337 return kStatus_Success;
0338 }
0339
0340 void USDHC_SetDataConfig(USDHC_Type *base,
0341 usdhc_transfer_direction_t dataDirection,
0342 uint32_t blockCount,
0343 uint32_t blockSize)
0344 {
0345 assert(blockCount <= USDHC_MAX_BLOCK_COUNT);
0346
0347 uint32_t mixCtrl = base->MIX_CTRL;
0348
0349
0350 base->BLK_ATT = ((base->BLK_ATT & ~(USDHC_BLK_ATT_BLKSIZE_MASK | USDHC_BLK_ATT_BLKCNT_MASK)) |
0351 (USDHC_BLK_ATT_BLKSIZE(blockSize) | USDHC_BLK_ATT_BLKCNT(blockCount)));
0352
0353
0354 mixCtrl &= ~(USDHC_MIX_CTRL_MSBSEL_MASK | USDHC_MIX_CTRL_BCEN_MASK | USDHC_MIX_CTRL_DTDSEL_MASK);
0355
0356 mixCtrl |= USDHC_MIX_CTRL_DTDSEL(dataDirection) | (blockCount > 1U ? USDHC_MIX_CTRL_MSBSEL_MASK : 0U);
0357
0358 base->MIX_CTRL = mixCtrl;
0359 }
0360
0361 static status_t USDHC_ReceiveCommandResponse(USDHC_Type *base, usdhc_command_t *command)
0362 {
0363 assert(command != NULL);
0364
0365 uint32_t response0 = base->CMD_RSP0;
0366 uint32_t response1 = base->CMD_RSP1;
0367 uint32_t response2 = base->CMD_RSP2;
0368
0369 if (command->responseType != kCARD_ResponseTypeNone)
0370 {
0371 command->response[0U] = response0;
0372 if (command->responseType == kCARD_ResponseTypeR2)
0373 {
0374
0375
0376 command->response[0U] <<= 8U;
0377 command->response[1U] = (response1 << 8U) | ((response0 & 0xFF000000U) >> 24U);
0378 command->response[2U] = (response2 << 8U) | ((response1 & 0xFF000000U) >> 24U);
0379 command->response[3U] = (base->CMD_RSP3 << 8U) | ((response2 & 0xFF000000U) >> 24U);
0380 }
0381 }
0382
0383
0384 if ((command->responseErrorFlags != 0U) &&
0385 ((command->responseType == kCARD_ResponseTypeR1) || (command->responseType == kCARD_ResponseTypeR1b) ||
0386 (command->responseType == kCARD_ResponseTypeR6) || (command->responseType == kCARD_ResponseTypeR5)))
0387 {
0388 if (((command->responseErrorFlags) & (command->response[0U])) != 0U)
0389 {
0390 return kStatus_USDHC_SendCommandFailed;
0391 }
0392 }
0393
0394 return kStatus_Success;
0395 }
0396
0397 static uint32_t USDHC_ReadDataPort(USDHC_Type *base, usdhc_data_t *data, uint32_t transferredWords)
0398 {
0399 uint32_t i;
0400 uint32_t totalWords;
0401 uint32_t wordsCanBeRead;
0402 uint32_t readWatermark = ((base->WTMK_LVL & USDHC_WTMK_LVL_RD_WML_MASK) >> USDHC_WTMK_LVL_RD_WML_SHIFT);
0403
0404
0405 if ((base->MIX_CTRL & USDHC_MIX_CTRL_DMAEN_MASK) == 0U)
0406 {
0407
0408
0409
0410
0411
0412 if (data->blockSize % sizeof(uint32_t) != 0U)
0413 {
0414 data->blockSize +=
0415 sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t));
0416 }
0417
0418 totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
0419
0420
0421 if (readWatermark >= totalWords)
0422 {
0423 wordsCanBeRead = totalWords;
0424 }
0425
0426
0427 else if ((readWatermark < totalWords) && ((totalWords - transferredWords) >= readWatermark))
0428 {
0429 wordsCanBeRead = readWatermark;
0430 }
0431
0432
0433
0434 else
0435 {
0436 wordsCanBeRead = (totalWords - transferredWords);
0437 }
0438
0439 i = 0U;
0440 while (i < wordsCanBeRead)
0441 {
0442 data->rxData[transferredWords++] = USDHC_ReadData(base);
0443 i++;
0444 }
0445 }
0446
0447 return transferredWords;
0448 }
0449
0450 static status_t USDHC_ReadByDataPortBlocking(USDHC_Type *base, usdhc_data_t *data)
0451 {
0452 uint32_t totalWords;
0453 uint32_t transferredWords = 0U, interruptStatus = 0U;
0454 status_t error = kStatus_Success;
0455
0456
0457
0458
0459
0460
0461 if (data->blockSize % sizeof(uint32_t) != 0U)
0462 {
0463 data->blockSize +=
0464 sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t));
0465 }
0466
0467 totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
0468
0469 while ((error == kStatus_Success) && (transferredWords < totalWords))
0470 {
0471 while (
0472 !(IS_USDHC_FLAG_SET(interruptStatus, ((uint32_t)kUSDHC_BufferReadReadyFlag |
0473 (uint32_t)kUSDHC_DataErrorFlag | (uint32_t)kUSDHC_TuningErrorFlag))))
0474 {
0475 interruptStatus = USDHC_GetInterruptStatusFlags(base);
0476 }
0477
0478
0479 if ((data->dataType == (uint32_t)kUSDHC_TransferDataTuning) &&
0480 (IS_USDHC_FLAG_SET(interruptStatus, kUSDHC_BufferReadReadyFlag)))
0481 {
0482 USDHC_ClearInterruptStatusFlags(base, kUSDHC_BufferReadReadyFlag);
0483
0484 return kStatus_Success;
0485 }
0486 #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (FSL_FEATURE_USDHC_HAS_SDR50_MODE)
0487 else if (IS_USDHC_FLAG_SET(interruptStatus, kUSDHC_TuningErrorFlag))
0488 {
0489 USDHC_ClearInterruptStatusFlags(base, kUSDHC_TuningErrorFlag);
0490
0491 error = kStatus_USDHC_TuningError;
0492 }
0493 #endif
0494 else if (IS_USDHC_FLAG_SET(interruptStatus, kUSDHC_DataErrorFlag))
0495 {
0496 if (!(data->enableIgnoreError))
0497 {
0498 error = kStatus_Fail;
0499 }
0500
0501 USDHC_ClearInterruptStatusFlags(base, kUSDHC_DataErrorFlag);
0502 }
0503 else
0504 {
0505
0506 }
0507
0508 if (error == kStatus_Success)
0509 {
0510 transferredWords = USDHC_ReadDataPort(base, data, transferredWords);
0511
0512 USDHC_ClearInterruptStatusFlags(base, kUSDHC_BufferReadReadyFlag);
0513 interruptStatus = 0U;
0514 }
0515 }
0516
0517
0518 USDHC_ClearInterruptStatusFlags(base, kUSDHC_DataCompleteFlag);
0519
0520 return error;
0521 }
0522
0523 static uint32_t USDHC_WriteDataPort(USDHC_Type *base, usdhc_data_t *data, uint32_t transferredWords)
0524 {
0525 uint32_t i;
0526 uint32_t totalWords;
0527 uint32_t wordsCanBeWrote;
0528 uint32_t writeWatermark = ((base->WTMK_LVL & USDHC_WTMK_LVL_WR_WML_MASK) >> USDHC_WTMK_LVL_WR_WML_SHIFT);
0529
0530
0531 if ((base->MIX_CTRL & USDHC_MIX_CTRL_DMAEN_MASK) == 0U)
0532 {
0533
0534
0535
0536
0537
0538 if (data->blockSize % sizeof(uint32_t) != 0U)
0539 {
0540 data->blockSize +=
0541 sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t));
0542 }
0543
0544 totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
0545
0546
0547 if (writeWatermark >= totalWords)
0548 {
0549 wordsCanBeWrote = totalWords;
0550 }
0551
0552
0553 else if ((writeWatermark < totalWords) && ((totalWords - transferredWords) >= writeWatermark))
0554 {
0555 wordsCanBeWrote = writeWatermark;
0556 }
0557
0558
0559 else
0560 {
0561 wordsCanBeWrote = (totalWords - transferredWords);
0562 }
0563
0564 i = 0U;
0565 while (i < wordsCanBeWrote)
0566 {
0567 USDHC_WriteData(base, data->txData[transferredWords++]);
0568 i++;
0569 }
0570 }
0571
0572 return transferredWords;
0573 }
0574
0575 static status_t USDHC_WriteByDataPortBlocking(USDHC_Type *base, usdhc_data_t *data)
0576 {
0577 uint32_t totalWords;
0578
0579 uint32_t transferredWords = 0U, interruptStatus = 0U;
0580 status_t error = kStatus_Success;
0581
0582
0583
0584
0585
0586
0587 if (data->blockSize % sizeof(uint32_t) != 0U)
0588 {
0589 data->blockSize +=
0590 sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t));
0591 }
0592
0593 totalWords = (data->blockCount * data->blockSize) / sizeof(uint32_t);
0594
0595 while ((error == kStatus_Success) && (transferredWords < totalWords))
0596 {
0597 while (!(IS_USDHC_FLAG_SET(interruptStatus, (uint32_t)kUSDHC_BufferWriteReadyFlag |
0598 (uint32_t)kUSDHC_DataErrorFlag |
0599 (uint32_t)kUSDHC_TuningErrorFlag)))
0600 {
0601 interruptStatus = USDHC_GetInterruptStatusFlags(base);
0602 }
0603 #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (FSL_FEATURE_USDHC_HAS_SDR50_MODE)
0604 if (IS_USDHC_FLAG_SET(interruptStatus, kUSDHC_TuningErrorFlag))
0605 {
0606 USDHC_ClearInterruptStatusFlags(base, kUSDHC_TuningErrorFlag);
0607
0608 return kStatus_USDHC_TuningError;
0609 }
0610 else
0611 #endif
0612 if (IS_USDHC_FLAG_SET(interruptStatus, kUSDHC_DataErrorFlag))
0613 {
0614 if (!(data->enableIgnoreError))
0615 {
0616 error = kStatus_Fail;
0617 }
0618
0619 USDHC_ClearInterruptStatusFlags(base, kUSDHC_DataErrorFlag);
0620 }
0621 else
0622 {
0623
0624 }
0625
0626 if (error == kStatus_Success)
0627 {
0628 transferredWords = USDHC_WriteDataPort(base, data, transferredWords);
0629
0630 USDHC_ClearInterruptStatusFlags(base, kUSDHC_BufferWriteReadyFlag);
0631 interruptStatus = 0U;
0632 }
0633 }
0634
0635
0636 while (!(IS_USDHC_FLAG_SET(interruptStatus, (uint32_t)kUSDHC_DataCompleteFlag | (uint32_t)kUSDHC_DataErrorFlag)))
0637 {
0638 interruptStatus = USDHC_GetInterruptStatusFlags(base);
0639 }
0640
0641 if ((interruptStatus & (uint32_t)kUSDHC_DataErrorFlag) != 0UL)
0642 {
0643 if (!(data->enableIgnoreError))
0644 {
0645 error = kStatus_Fail;
0646 }
0647 }
0648 USDHC_ClearInterruptStatusFlags(base, ((uint32_t)kUSDHC_DataCompleteFlag | (uint32_t)kUSDHC_DataErrorFlag));
0649
0650 return error;
0651 }
0652
0653
0654
0655
0656
0657
0658
0659 void USDHC_SendCommand(USDHC_Type *base, usdhc_command_t *command)
0660 {
0661 assert(NULL != command);
0662
0663 uint32_t xferType = base->CMD_XFR_TYP, flags = command->flags;
0664
0665 if (((base->PRES_STATE & (uint32_t)kUSDHC_CommandInhibitFlag) == 0U) && (command->type != kCARD_CommandTypeEmpty))
0666 {
0667 if ((command->responseType == kCARD_ResponseTypeR1) || (command->responseType == kCARD_ResponseTypeR5) ||
0668 (command->responseType == kCARD_ResponseTypeR6) || (command->responseType == kCARD_ResponseTypeR7))
0669 {
0670 flags |= ((uint32_t)kUSDHC_ResponseLength48Flag | (uint32_t)kUSDHC_EnableCrcCheckFlag |
0671 (uint32_t)kUSDHC_EnableIndexCheckFlag);
0672 }
0673 else if ((command->responseType == kCARD_ResponseTypeR1b) || (command->responseType == kCARD_ResponseTypeR5b))
0674 {
0675 flags |= ((uint32_t)kUSDHC_ResponseLength48BusyFlag | (uint32_t)kUSDHC_EnableCrcCheckFlag |
0676 (uint32_t)kUSDHC_EnableIndexCheckFlag);
0677 }
0678 else if (command->responseType == kCARD_ResponseTypeR2)
0679 {
0680 flags |= ((uint32_t)kUSDHC_ResponseLength136Flag | (uint32_t)kUSDHC_EnableCrcCheckFlag);
0681 }
0682 else if ((command->responseType == kCARD_ResponseTypeR3) || (command->responseType == kCARD_ResponseTypeR4))
0683 {
0684 flags |= ((uint32_t)kUSDHC_ResponseLength48Flag);
0685 }
0686 else
0687 {
0688
0689 }
0690
0691 if (command->type == kCARD_CommandTypeAbort)
0692 {
0693 flags |= (uint32_t)kUSDHC_CommandTypeAbortFlag;
0694 }
0695
0696
0697 xferType &= ~(USDHC_CMD_XFR_TYP_CMDINX_MASK | USDHC_CMD_XFR_TYP_CMDTYP_MASK | USDHC_CMD_XFR_TYP_CICEN_MASK |
0698 USDHC_CMD_XFR_TYP_CCCEN_MASK | USDHC_CMD_XFR_TYP_RSPTYP_MASK | USDHC_CMD_XFR_TYP_DPSEL_MASK);
0699
0700 xferType |=
0701 (((command->index << USDHC_CMD_XFR_TYP_CMDINX_SHIFT) & USDHC_CMD_XFR_TYP_CMDINX_MASK) |
0702 ((flags) & (USDHC_CMD_XFR_TYP_CMDTYP_MASK | USDHC_CMD_XFR_TYP_CICEN_MASK | USDHC_CMD_XFR_TYP_CCCEN_MASK |
0703 USDHC_CMD_XFR_TYP_RSPTYP_MASK | USDHC_CMD_XFR_TYP_DPSEL_MASK)));
0704
0705
0706 base->CMD_ARG = command->argument;
0707 base->CMD_XFR_TYP = xferType;
0708 }
0709
0710 if (command->type == kCARD_CommandTypeEmpty)
0711 {
0712
0713 base->INT_SIGNAL_EN &= ~USDHC_INT_SIGNAL_EN_CCIEN_MASK;
0714 }
0715 }
0716
0717 static status_t USDHC_WaitCommandDone(USDHC_Type *base, usdhc_command_t *command, bool pollingCmdDone)
0718 {
0719 assert(NULL != command);
0720
0721 status_t error = kStatus_Success;
0722 uint32_t interruptStatus = 0U;
0723
0724 if (pollingCmdDone)
0725 {
0726
0727 while (!(IS_USDHC_FLAG_SET(interruptStatus, kUSDHC_CommandFlag)))
0728 {
0729 interruptStatus = USDHC_GetInterruptStatusFlags(base);
0730 }
0731
0732 if ((interruptStatus & (uint32_t)kUSDHC_CommandErrorFlag) != 0UL)
0733 {
0734 error = kStatus_Fail;
0735 }
0736
0737
0738 if (error == kStatus_Success)
0739 {
0740 error = USDHC_ReceiveCommandResponse(base, command);
0741 }
0742
0743 USDHC_ClearInterruptStatusFlags(base, kUSDHC_CommandFlag);
0744 }
0745
0746 return error;
0747 }
0748
0749 static status_t USDHC_TransferDataBlocking(USDHC_Type *base, usdhc_data_t *data, bool enDMA)
0750 {
0751 status_t error = kStatus_Success;
0752 uint32_t interruptStatus = 0U;
0753
0754 if (enDMA)
0755 {
0756
0757 while (!(IS_USDHC_FLAG_SET(interruptStatus, ((uint32_t)kUSDHC_DataDMAFlag | (uint32_t)kUSDHC_TuningErrorFlag))))
0758 {
0759 interruptStatus = USDHC_GetInterruptStatusFlags(base);
0760 }
0761
0762 #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (FSL_FEATURE_USDHC_HAS_SDR50_MODE)
0763 if (IS_USDHC_FLAG_SET(interruptStatus, kUSDHC_TuningErrorFlag))
0764 {
0765 error = kStatus_USDHC_TuningError;
0766 }
0767 else
0768 #endif
0769 if (IS_USDHC_FLAG_SET(interruptStatus, ((uint32_t)kUSDHC_DataErrorFlag | (uint32_t)kUSDHC_DmaErrorFlag)))
0770 {
0771 if ((!(data->enableIgnoreError)) || (IS_USDHC_FLAG_SET(interruptStatus, kUSDHC_DataTimeoutFlag)))
0772 {
0773 error = kStatus_USDHC_TransferDataFailed;
0774 }
0775 }
0776 else
0777 {
0778
0779 }
0780
0781 if ((data->dataType == (uint32_t)kUSDHC_TransferDataBootcontinous) && (error == kStatus_Success))
0782 {
0783 *(data->rxData) = s_usdhcBootDummy;
0784 }
0785
0786 USDHC_ClearInterruptStatusFlags(base, ((uint32_t)kUSDHC_DataDMAFlag | (uint32_t)kUSDHC_TuningErrorFlag));
0787 }
0788 else
0789 {
0790 if (data->rxData != NULL)
0791 {
0792 error = USDHC_ReadByDataPortBlocking(base, data);
0793 if (error != kStatus_Success)
0794 {
0795 return error;
0796 }
0797 }
0798 else
0799 {
0800 error = USDHC_WriteByDataPortBlocking(base, data);
0801 if (error != kStatus_Success)
0802 {
0803 return error;
0804 }
0805 }
0806 }
0807
0808 return error;
0809 }
0810
0811
0812
0813
0814
0815
0816
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831 void USDHC_Init(USDHC_Type *base, const usdhc_config_t *config)
0832 {
0833 assert(config != NULL);
0834 assert((config->writeWatermarkLevel >= 1U) && (config->writeWatermarkLevel <= 128U));
0835 assert((config->readWatermarkLevel >= 1U) && (config->readWatermarkLevel <= 128U));
0836 #if !(defined(FSL_FEATURE_USDHC_HAS_NO_RW_BURST_LEN) && FSL_FEATURE_USDHC_HAS_NO_RW_BURST_LEN)
0837 assert(config->writeBurstLen <= 16U);
0838 #endif
0839 uint32_t proctl, sysctl, wml;
0840
0841 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0842
0843 CLOCK_EnableClock(s_usdhcClock[USDHC_GetInstance(base)]);
0844 #endif
0845
0846 #if (defined(FSL_FEATURE_USDHC_HAS_RESET) && FSL_FEATURE_USDHC_HAS_RESET)
0847
0848 RESET_PeripheralReset(s_usdhcResets[USDHC_GetInstance(base)]);
0849 #endif
0850
0851
0852 base->SYS_CTRL |= USDHC_SYS_CTRL_RSTA_MASK | USDHC_SYS_CTRL_RSTC_MASK | USDHC_SYS_CTRL_RSTD_MASK;
0853
0854 proctl = base->PROT_CTRL;
0855 wml = base->WTMK_LVL;
0856 sysctl = base->SYS_CTRL;
0857
0858 proctl &= ~(USDHC_PROT_CTRL_EMODE_MASK | USDHC_PROT_CTRL_DMASEL_MASK);
0859
0860 proctl |= USDHC_PROT_CTRL_EMODE(config->endianMode);
0861
0862 #if (defined(FSL_FEATURE_USDHC_HAS_NO_RW_BURST_LEN) && FSL_FEATURE_USDHC_HAS_NO_RW_BURST_LEN)
0863
0864 wml &= ~(USDHC_WTMK_LVL_RD_WML_MASK | USDHC_WTMK_LVL_WR_WML_MASK);
0865 wml |= (USDHC_WTMK_LVL_RD_WML(config->readWatermarkLevel) | USDHC_WTMK_LVL_WR_WML(config->writeWatermarkLevel));
0866 #else
0867
0868 wml &= ~(USDHC_WTMK_LVL_RD_WML_MASK | USDHC_WTMK_LVL_WR_WML_MASK | USDHC_WTMK_LVL_RD_BRST_LEN_MASK |
0869 USDHC_WTMK_LVL_WR_BRST_LEN_MASK);
0870 wml |= (USDHC_WTMK_LVL_RD_WML(config->readWatermarkLevel) | USDHC_WTMK_LVL_WR_WML(config->writeWatermarkLevel) |
0871 USDHC_WTMK_LVL_RD_BRST_LEN(config->readBurstLen) | USDHC_WTMK_LVL_WR_BRST_LEN(config->writeBurstLen));
0872 #endif
0873
0874
0875 sysctl &= ~USDHC_SYS_CTRL_DTOCV_MASK;
0876 sysctl |= USDHC_SYS_CTRL_DTOCV(config->dataTimeout);
0877
0878 base->SYS_CTRL = sysctl;
0879 base->WTMK_LVL = wml;
0880 base->PROT_CTRL = proctl;
0881
0882 #if FSL_FEATURE_USDHC_HAS_EXT_DMA
0883
0884 base->VEND_SPEC &= ~USDHC_VEND_SPEC_EXT_DMA_EN_MASK;
0885 #endif
0886
0887 base->MIX_CTRL &= ~(USDHC_MIX_CTRL_DMAEN_MASK | USDHC_MIX_CTRL_DDR_EN_MASK);
0888
0889 base->INT_STATUS_EN = kUSDHC_AllInterruptFlags;
0890 base->INT_SIGNAL_EN = 0UL;
0891 base->INT_STATUS = kUSDHC_AllInterruptFlags;
0892 }
0893
0894
0895
0896
0897
0898
0899 void USDHC_Deinit(USDHC_Type *base)
0900 {
0901 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0902
0903 CLOCK_DisableClock(s_usdhcClock[USDHC_GetInstance(base)]);
0904 #endif
0905 }
0906
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916 bool USDHC_Reset(USDHC_Type *base, uint32_t mask, uint32_t timeout)
0917 {
0918 base->SYS_CTRL |= (mask & (USDHC_SYS_CTRL_RSTA_MASK | USDHC_SYS_CTRL_RSTC_MASK | USDHC_SYS_CTRL_RSTD_MASK
0919 #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (FSL_FEATURE_USDHC_HAS_SDR50_MODE)
0920 | USDHC_SYS_CTRL_RSTT_MASK
0921 #endif
0922 ));
0923
0924 while (IS_USDHC_FLAG_SET(base->SYS_CTRL, mask))
0925 {
0926 if (timeout == 0UL)
0927 {
0928 break;
0929 }
0930 timeout--;
0931 }
0932
0933 return ((0UL == timeout) ? false : true);
0934 }
0935
0936
0937
0938
0939
0940
0941
0942 void USDHC_GetCapability(USDHC_Type *base, usdhc_capability_t *capability)
0943 {
0944 assert(capability != NULL);
0945
0946 uint32_t htCapability;
0947 uint32_t maxBlockLength;
0948
0949 htCapability = base->HOST_CTRL_CAP;
0950
0951
0952 maxBlockLength = ((htCapability & USDHC_HOST_CTRL_CAP_MBL_MASK) >> USDHC_HOST_CTRL_CAP_MBL_SHIFT);
0953 capability->maxBlockLength = (512UL << maxBlockLength);
0954
0955 capability->maxBlockCount = USDHC_MAX_BLOCK_COUNT;
0956 capability->flags =
0957 (htCapability & (USDHC_HOST_CTRL_CAP_ADMAS_MASK | USDHC_HOST_CTRL_CAP_HSS_MASK | USDHC_HOST_CTRL_CAP_DMAS_MASK |
0958 USDHC_HOST_CTRL_CAP_SRS_MASK | USDHC_HOST_CTRL_CAP_VS33_MASK));
0959 capability->flags |= htCapability & USDHC_HOST_CTRL_CAP_VS30_MASK;
0960 capability->flags |= htCapability & USDHC_HOST_CTRL_CAP_VS18_MASK;
0961 capability->flags |= htCapability & USDHC_HOST_CTRL_CAP_DDR50_SUPPORT_MASK;
0962 #if defined(FSL_FEATURE_USDHC_HAS_SDR104_MODE) && FSL_FEATURE_USDHC_HAS_SDR104_MODE
0963 capability->flags |= USDHC_HOST_CTRL_CAP_SDR104_SUPPORT_MASK;
0964 #endif
0965
0966 #if defined(FSL_FEATURE_USDHC_HAS_SDR104_MODE) && FSL_FEATURE_USDHC_HAS_SDR50_MODE
0967 capability->flags |= USDHC_HOST_CTRL_CAP_SDR50_SUPPORT_MASK;
0968 #endif
0969
0970 capability->flags |= (USDHC_HOST_CTRL_CAP_MBL_SHIFT << 0UL) | (USDHC_HOST_CTRL_CAP_MBL_SHIFT << 1UL);
0971 }
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982 uint32_t USDHC_SetSdClock(USDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz)
0983 {
0984 assert(srcClock_Hz != 0U);
0985 assert(busClock_Hz != 0U);
0986
0987 uint32_t totalDiv = 0UL;
0988 uint32_t divisor = 0UL;
0989 uint32_t prescaler = 0UL;
0990 uint32_t sysctl = 0UL;
0991 uint32_t nearestFrequency = 0UL;
0992
0993 if (busClock_Hz > srcClock_Hz)
0994 {
0995 busClock_Hz = srcClock_Hz;
0996 }
0997
0998 totalDiv = srcClock_Hz / busClock_Hz;
0999
1000
1001 if (totalDiv > (USDHC_MAX_CLKFS * USDHC_MAX_DVS))
1002 {
1003 return 0UL;
1004 }
1005
1006 if (totalDiv != 0UL)
1007 {
1008
1009 if ((srcClock_Hz / totalDiv) > busClock_Hz)
1010 {
1011 totalDiv++;
1012 }
1013
1014
1015 if (totalDiv > USDHC_MAX_DVS)
1016 {
1017 prescaler = totalDiv / USDHC_MAX_DVS;
1018
1019 while (((USDHC_MAX_CLKFS % prescaler) != 0UL) || (prescaler == 1UL))
1020 {
1021 prescaler++;
1022 }
1023
1024 divisor = totalDiv / prescaler;
1025
1026 while ((divisor * prescaler) < totalDiv)
1027 {
1028 divisor++;
1029 if (divisor > USDHC_MAX_DVS)
1030 {
1031 prescaler <<= 1UL;
1032 if (prescaler > USDHC_MAX_CLKFS)
1033 {
1034 return 0UL;
1035 }
1036 divisor = totalDiv / prescaler;
1037 }
1038 }
1039 }
1040 else
1041 {
1042
1043
1044 if (((totalDiv % 2UL) != 0UL) && (totalDiv != 1UL))
1045 {
1046 divisor = totalDiv;
1047 prescaler = 1UL;
1048 }
1049 else
1050 {
1051 divisor = 1UL;
1052 prescaler = totalDiv;
1053 }
1054 }
1055 nearestFrequency = srcClock_Hz / (divisor == 0UL ? 1UL : divisor) / prescaler;
1056 }
1057
1058 else
1059 {
1060
1061
1062 divisor = 0UL;
1063 prescaler = 0UL;
1064 nearestFrequency = srcClock_Hz;
1065 }
1066
1067
1068 if (divisor != 0UL)
1069 {
1070 USDHC_PREV_DVS(divisor);
1071 }
1072
1073 if (prescaler != 0UL)
1074 {
1075 USDHC_PREV_CLKFS(prescaler, 1UL);
1076 }
1077
1078
1079 sysctl = base->SYS_CTRL;
1080 sysctl &= ~(USDHC_SYS_CTRL_DVS_MASK | USDHC_SYS_CTRL_SDCLKFS_MASK);
1081 sysctl |= (USDHC_SYS_CTRL_DVS(divisor) | USDHC_SYS_CTRL_SDCLKFS(prescaler));
1082 base->SYS_CTRL = sysctl;
1083
1084
1085 while (!IS_USDHC_FLAG_SET(base->PRES_STATE, USDHC_PRES_STATE_SDSTB_MASK))
1086 {
1087 }
1088
1089 return nearestFrequency;
1090 }
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103 bool USDHC_SetCardActive(USDHC_Type *base, uint32_t timeout)
1104 {
1105 base->SYS_CTRL |= USDHC_SYS_CTRL_INITA_MASK;
1106
1107 while (IS_USDHC_FLAG_SET(base->SYS_CTRL, USDHC_SYS_CTRL_INITA_MASK))
1108 {
1109 if (0UL == timeout)
1110 {
1111 break;
1112 }
1113 timeout--;
1114 }
1115
1116 return ((0UL == timeout) ? false : true);
1117 }
1118
1119
1120
1121
1122
1123
1124
1125
1126 void USDHC_EnableDDRMode(USDHC_Type *base, bool enable, uint32_t nibblePos)
1127 {
1128 uint32_t prescaler = (base->SYS_CTRL & USDHC_SYS_CTRL_SDCLKFS_MASK) >> USDHC_SYS_CTRL_SDCLKFS_SHIFT;
1129
1130 if (enable)
1131 {
1132 base->MIX_CTRL &= ~USDHC_MIX_CTRL_NIBBLE_POS_MASK;
1133 base->MIX_CTRL |= (USDHC_MIX_CTRL_DDR_EN_MASK | USDHC_MIX_CTRL_NIBBLE_POS(nibblePos));
1134 prescaler >>= 1UL;
1135 }
1136 else
1137 {
1138 base->MIX_CTRL &= ~USDHC_MIX_CTRL_DDR_EN_MASK;
1139
1140 if (prescaler == 0UL)
1141 {
1142 prescaler += 1UL;
1143 }
1144 else
1145 {
1146 prescaler <<= 1UL;
1147 }
1148 }
1149
1150 base->SYS_CTRL = (base->SYS_CTRL & (~USDHC_SYS_CTRL_SDCLKFS_MASK)) | USDHC_SYS_CTRL_SDCLKFS(prescaler);
1151 }
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171 void USDHC_SetMmcBootConfig(USDHC_Type *base, const usdhc_boot_config_t *config)
1172 {
1173 assert(config != NULL);
1174 assert(config->ackTimeoutCount <= (USDHC_MMC_BOOT_DTOCV_ACK_MASK >> USDHC_MMC_BOOT_DTOCV_ACK_SHIFT));
1175 assert(config->blockCount <= (USDHC_MMC_BOOT_BOOT_BLK_CNT_MASK >> USDHC_MMC_BOOT_BOOT_BLK_CNT_SHIFT));
1176
1177 uint32_t mmcboot = base->MMC_BOOT;
1178
1179 mmcboot &= ~(USDHC_MMC_BOOT_DTOCV_ACK_MASK | USDHC_MMC_BOOT_BOOT_MODE_MASK | USDHC_MMC_BOOT_BOOT_BLK_CNT_MASK);
1180 mmcboot |= USDHC_MMC_BOOT_DTOCV_ACK(config->ackTimeoutCount) | USDHC_MMC_BOOT_BOOT_MODE(config->bootMode);
1181
1182 if (config->enableBootAck)
1183 {
1184 mmcboot |= USDHC_MMC_BOOT_BOOT_ACK_MASK;
1185 }
1186 if (config->enableAutoStopAtBlockGap)
1187 {
1188 mmcboot |=
1189 USDHC_MMC_BOOT_AUTO_SABG_EN_MASK | USDHC_MMC_BOOT_BOOT_BLK_CNT(USDHC_MAX_BLOCK_COUNT - config->blockCount);
1190
1191 base->BLK_ATT = ((base->BLK_ATT & ~(USDHC_BLK_ATT_BLKSIZE_MASK | USDHC_BLK_ATT_BLKCNT_MASK)) |
1192 (USDHC_BLK_ATT_BLKSIZE(config->blockSize) | USDHC_BLK_ATT_BLKCNT(USDHC_MAX_BLOCK_COUNT)));
1193 }
1194 else
1195 {
1196 base->BLK_ATT = ((base->BLK_ATT & ~(USDHC_BLK_ATT_BLKSIZE_MASK | USDHC_BLK_ATT_BLKCNT_MASK)) |
1197 (USDHC_BLK_ATT_BLKSIZE(config->blockSize) | USDHC_BLK_ATT_BLKCNT(config->blockCount)));
1198 }
1199
1200 base->MMC_BOOT = mmcboot;
1201 }
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215 status_t USDHC_SetADMA1Descriptor(
1216 uint32_t *admaTable, uint32_t admaTableWords, const uint32_t *dataBufferAddr, uint32_t dataBytes, uint32_t flags)
1217 {
1218 assert(NULL != admaTable);
1219 assert(NULL != dataBufferAddr);
1220
1221 uint32_t miniEntries, startEntries = 0UL,
1222 maxEntries = (admaTableWords * sizeof(uint32_t)) / sizeof(usdhc_adma1_descriptor_t);
1223 usdhc_adma1_descriptor_t *adma1EntryAddress = (usdhc_adma1_descriptor_t *)(uint32_t)(admaTable);
1224 uint32_t i, dmaBufferLen = 0UL;
1225 const uint32_t *data = dataBufferAddr;
1226
1227 if (((uint32_t)data % USDHC_ADMA1_ADDRESS_ALIGN) != 0UL)
1228 {
1229 return kStatus_USDHC_DMADataAddrNotAlign;
1230 }
1231
1232 if (flags == (uint32_t)kUSDHC_AdmaDescriptorMultipleFlag)
1233 {
1234 return kStatus_USDHC_NotSupport;
1235 }
1236
1237
1238
1239
1240
1241 if (dataBytes % sizeof(uint32_t) != 0UL)
1242 {
1243
1244 dataBytes += sizeof(uint32_t) - (dataBytes % sizeof(uint32_t));
1245 }
1246
1247
1248 if ((dataBytes % USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) == 0UL)
1249 {
1250 miniEntries = dataBytes / USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY;
1251 }
1252 else
1253 {
1254 miniEntries = ((dataBytes / USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1UL);
1255 }
1256
1257
1258 miniEntries <<= 1UL;
1259
1260 if (miniEntries + startEntries > maxEntries)
1261 {
1262 return kStatus_OutOfRange;
1263 }
1264
1265 for (i = startEntries; i < (miniEntries + startEntries); i += 2UL)
1266 {
1267 if (dataBytes > USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY)
1268 {
1269 dmaBufferLen = USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY;
1270 }
1271 else
1272 {
1273 dmaBufferLen = dataBytes;
1274 }
1275
1276 adma1EntryAddress[i] = (dmaBufferLen << USDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT);
1277 adma1EntryAddress[i] |= (uint32_t)kUSDHC_Adma1DescriptorTypeSetLength;
1278 adma1EntryAddress[i + 1UL] = (uint32_t)(data);
1279 adma1EntryAddress[i + 1UL] |=
1280 (uint32_t)kUSDHC_Adma1DescriptorTypeTransfer | (uint32_t)kUSDHC_Adma1DescriptorInterrupFlag;
1281 data = (uint32_t *)((uint32_t)data + dmaBufferLen);
1282 dataBytes -= dmaBufferLen;
1283 }
1284
1285 adma1EntryAddress[i - 1UL] |= (uint32_t)kUSDHC_Adma1DescriptorEndFlag;
1286
1287 return kStatus_Success;
1288 }
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302 status_t USDHC_SetADMA2Descriptor(
1303 uint32_t *admaTable, uint32_t admaTableWords, const uint32_t *dataBufferAddr, uint32_t dataBytes, uint32_t flags)
1304 {
1305 assert(NULL != admaTable);
1306 assert(NULL != dataBufferAddr);
1307
1308 uint32_t miniEntries, startEntries = 0UL,
1309 maxEntries = (admaTableWords * sizeof(uint32_t)) / sizeof(usdhc_adma2_descriptor_t);
1310 usdhc_adma2_descriptor_t *adma2EntryAddress = (usdhc_adma2_descriptor_t *)(uint32_t)(admaTable);
1311 uint32_t i, dmaBufferLen = 0UL;
1312 const uint32_t *data = dataBufferAddr;
1313
1314 if (((uint32_t)data % USDHC_ADMA2_ADDRESS_ALIGN) != 0UL)
1315 {
1316 return kStatus_USDHC_DMADataAddrNotAlign;
1317 }
1318
1319
1320
1321
1322
1323 if (dataBytes % sizeof(uint32_t) != 0UL)
1324 {
1325
1326 dataBytes += sizeof(uint32_t) - (dataBytes % sizeof(uint32_t));
1327 }
1328
1329
1330 if ((dataBytes % USDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) == 0UL)
1331 {
1332 miniEntries = dataBytes / USDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY;
1333 }
1334 else
1335 {
1336 miniEntries = ((dataBytes / USDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1UL);
1337 }
1338
1339
1340 if (flags == (uint32_t)kUSDHC_AdmaDescriptorMultipleFlag)
1341 {
1342 for (i = 0UL; i < maxEntries; i++)
1343 {
1344 if ((adma2EntryAddress[i].attribute & (uint32_t)kUSDHC_Adma2DescriptorValidFlag) == 0UL)
1345 {
1346 break;
1347 }
1348 }
1349 startEntries = i;
1350
1351 miniEntries += 1UL;
1352 }
1353
1354 if ((miniEntries + startEntries) > maxEntries)
1355 {
1356 return kStatus_OutOfRange;
1357 }
1358
1359 for (i = startEntries; i < (miniEntries + startEntries); i++)
1360 {
1361 if (dataBytes > USDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY)
1362 {
1363 dmaBufferLen = USDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY;
1364 }
1365 else
1366 {
1367 dmaBufferLen = (dataBytes == 0UL ? sizeof(uint32_t) :
1368 dataBytes);
1369 }
1370
1371
1372 adma2EntryAddress[i].address = (dataBytes == 0UL) ? &s_usdhcBootDummy : data;
1373 adma2EntryAddress[i].attribute = (dmaBufferLen << USDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT);
1374 adma2EntryAddress[i].attribute |=
1375 (dataBytes == 0UL) ?
1376 0UL :
1377 ((uint32_t)kUSDHC_Adma2DescriptorTypeTransfer | (uint32_t)kUSDHC_Adma2DescriptorInterruptFlag);
1378 data = (uint32_t *)((uint32_t)data + dmaBufferLen);
1379
1380 if (dataBytes != 0UL)
1381 {
1382 dataBytes -= dmaBufferLen;
1383 }
1384 }
1385
1386
1387
1388
1389 if (flags == (uint32_t)kUSDHC_AdmaDescriptorMultipleFlag)
1390 {
1391 adma2EntryAddress[startEntries + 1UL].attribute |= (uint32_t)kUSDHC_Adma2DescriptorTypeTransfer;
1392 }
1393 else
1394 {
1395
1396 adma2EntryAddress[i - 1UL].attribute |= (uint32_t)kUSDHC_Adma2DescriptorEndFlag;
1397 }
1398
1399 return kStatus_Success;
1400 }
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413 status_t USDHC_SetInternalDmaConfig(USDHC_Type *base,
1414 usdhc_adma_config_t *dmaConfig,
1415 const uint32_t *dataAddr,
1416 bool enAutoCmd23)
1417 {
1418 assert(dmaConfig != NULL);
1419 assert(dataAddr != NULL);
1420 assert((NULL != dmaConfig->admaTable) &&
1421 (((USDHC_ADMA_TABLE_ADDRESS_ALIGN - 1U) & (uint32_t)dmaConfig->admaTable) == 0UL));
1422
1423 #if FSL_FEATURE_USDHC_HAS_EXT_DMA
1424
1425 base->VEND_SPEC &= ~USDHC_VEND_SPEC_EXT_DMA_EN_MASK;
1426 #endif
1427
1428 if (dmaConfig->dmaMode == kUSDHC_DmaModeSimple)
1429 {
1430
1431 if (((uint32_t)dataAddr % USDHC_ADMA2_ADDRESS_ALIGN) != 0UL)
1432 {
1433 return kStatus_USDHC_DMADataAddrNotAlign;
1434 }
1435
1436
1437 if (enAutoCmd23)
1438 {
1439 base->ADMA_SYS_ADDR = USDHC_ADDR_CPU_2_DMA((uint32_t)dataAddr);
1440 }
1441 else
1442 {
1443 base->DS_ADDR = USDHC_ADDR_CPU_2_DMA((uint32_t)dataAddr);
1444 }
1445 }
1446 else
1447 {
1448
1449 base->DS_ADDR = 0UL;
1450 base->ADMA_SYS_ADDR = USDHC_ADDR_CPU_2_DMA((uint32_t)(dmaConfig->admaTable));
1451 }
1452
1453 #if (defined(FSL_FEATURE_USDHC_HAS_NO_RW_BURST_LEN) && FSL_FEATURE_USDHC_HAS_NO_RW_BURST_LEN)
1454
1455 base->PROT_CTRL &= ~(USDHC_PROT_CTRL_DMASEL_MASK);
1456 base->PROT_CTRL |= USDHC_PROT_CTRL_DMASEL(dmaConfig->dmaMode);
1457 #else
1458
1459 base->PROT_CTRL &= ~(USDHC_PROT_CTRL_DMASEL_MASK | USDHC_PROT_CTRL_BURST_LEN_EN_MASK);
1460 base->PROT_CTRL |= USDHC_PROT_CTRL_DMASEL(dmaConfig->dmaMode) | USDHC_PROT_CTRL_BURST_LEN_EN(dmaConfig->burstLen);
1461 #endif
1462
1463 base->MIX_CTRL |= USDHC_MIX_CTRL_DMAEN_MASK;
1464
1465 return kStatus_Success;
1466 }
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479 status_t USDHC_SetAdmaTableConfig(USDHC_Type *base,
1480 usdhc_adma_config_t *dmaConfig,
1481 usdhc_data_t *dataConfig,
1482 uint32_t flags)
1483 {
1484 assert(NULL != dmaConfig);
1485 assert((NULL != dmaConfig->admaTable) &&
1486 (((USDHC_ADMA_TABLE_ADDRESS_ALIGN - 1U) & (uint32_t)dmaConfig->admaTable) == 0UL));
1487 assert(NULL != dataConfig);
1488
1489 status_t error = kStatus_Fail;
1490 uint32_t bootDummyOffset =
1491 dataConfig->dataType == (uint32_t)kUSDHC_TransferDataBootcontinous ? sizeof(uint32_t) : 0UL;
1492 const uint32_t *data = (const uint32_t *)USDHC_ADDR_CPU_2_DMA((uint32_t)(
1493 (uint32_t)((dataConfig->rxData == NULL) ? dataConfig->txData : dataConfig->rxData) + bootDummyOffset));
1494 uint32_t blockSize = dataConfig->blockSize * dataConfig->blockCount - bootDummyOffset;
1495
1496 #if FSL_FEATURE_USDHC_HAS_EXT_DMA
1497 if (dmaConfig->dmaMode == kUSDHC_ExternalDMA)
1498 {
1499
1500 base->VEND_SPEC |= USDHC_VEND_SPEC_EXT_DMA_EN_MASK;
1501 }
1502 else
1503 #endif
1504 if (dmaConfig->dmaMode == kUSDHC_DmaModeSimple)
1505 {
1506 error = kStatus_Success;
1507 }
1508 else if (dmaConfig->dmaMode == kUSDHC_DmaModeAdma1)
1509 {
1510 error = USDHC_SetADMA1Descriptor(dmaConfig->admaTable, dmaConfig->admaTableWords, data, blockSize, flags);
1511 }
1512
1513 else
1514 {
1515 error = USDHC_SetADMA2Descriptor(dmaConfig->admaTable, dmaConfig->admaTableWords, data, blockSize, flags);
1516 }
1517
1518
1519
1520 if ((dmaConfig->dmaMode != kUSDHC_ExternalDMA) && (error == kStatus_Success) &&
1521 (dataConfig->dataType != (uint32_t)kUSDHC_TransferDataBootcontinous))
1522 {
1523 error = USDHC_SetInternalDmaConfig(base, dmaConfig, data, dataConfig->enableAutoCommand23);
1524 }
1525
1526 return error;
1527 }
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549 status_t USDHC_TransferBlocking(USDHC_Type *base, usdhc_adma_config_t *dmaConfig, usdhc_transfer_t *transfer)
1550 {
1551 assert(transfer != NULL);
1552
1553 status_t error = kStatus_Fail;
1554 usdhc_command_t *command = transfer->command;
1555 usdhc_data_t *data = transfer->data;
1556 bool enDMA = true;
1557 bool executeTuning = ((data == NULL) ? false : data->dataType == (uint32_t)kUSDHC_TransferDataTuning);
1558 uint32_t transferFlags = (uint32_t)kUSDHC_CommandOnly;
1559 size_t blockSize = 0U;
1560 size_t blockCount = 0U;
1561
1562 #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (FSL_FEATURE_USDHC_HAS_SDR50_MODE)
1563
1564 if ((USDHC_GetInterruptStatusFlags(base) & (uint32_t)kUSDHC_ReTuningEventFlag) != 0UL)
1565 {
1566 USDHC_ClearInterruptStatusFlags(base, kUSDHC_ReTuningEventFlag);
1567 return kStatus_USDHC_ReTuningRequest;
1568 }
1569 #endif
1570
1571 if (data != NULL)
1572 {
1573
1574 if ((dmaConfig != NULL) && (!executeTuning))
1575 {
1576 error = USDHC_SetAdmaTableConfig(base, dmaConfig, data,
1577 (uint32_t)(IS_USDHC_FLAG_SET(data->dataType, kUSDHC_TransferDataBoot) ?
1578 kUSDHC_AdmaDescriptorMultipleFlag :
1579 kUSDHC_AdmaDescriptorSingleFlag));
1580 }
1581 blockSize = data->blockSize;
1582 blockCount = data->blockCount;
1583 transferFlags = data->enableAutoCommand12 ? (uint32_t)kUSDHC_DataWithAutoCmd12 : 0U;
1584 transferFlags |= data->enableAutoCommand23 ? (uint32_t)kUSDHC_DataWithAutoCmd23 : 0U;
1585 transferFlags |= data->txData != NULL ? (uint32_t)kUSDHC_CommandAndTxData : (uint32_t)kUSDHC_CommandAndRxData;
1586 transferFlags |= data->dataType == (uint8_t)kUSDHC_TransferDataBoot ? (uint32_t)kUSDHC_BootData : 0U;
1587 transferFlags |=
1588 data->dataType == (uint8_t)kUSDHC_TransferDataBootcontinous ? (uint32_t)kUSDHC_BootDataContinuous : 0U;
1589
1590 command->flags |= (uint32_t)kUSDHC_DataPresentFlag;
1591 }
1592
1593
1594 if (error != kStatus_Success)
1595 {
1596 enDMA = false;
1597
1598 USDHC_EnableInternalDMA(base, false);
1599 }
1600 #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
1601 else
1602 {
1603 if (data->txData != NULL)
1604 {
1605
1606 DCACHE_CleanByRange((uint32_t)data->txData, (data->blockSize) * (data->blockCount));
1607 }
1608 else
1609 {
1610
1611 DCACHE_CleanInvalidateByRange((uint32_t)data->rxData, (data->blockSize) * (data->blockCount));
1612 }
1613 }
1614 #endif
1615
1616
1617 error = USDHC_SetTransferConfig(base, transferFlags, blockSize, blockCount);
1618 if (error != kStatus_Success)
1619 {
1620 return error;
1621 }
1622
1623 USDHC_SendCommand(base, command);
1624
1625 error =
1626 USDHC_WaitCommandDone(base, command, (data == NULL) || (data->dataType == (uint32_t)kUSDHC_TransferDataNormal));
1627 if (kStatus_Success != error)
1628 {
1629 return kStatus_USDHC_SendCommandFailed;
1630 }
1631
1632
1633 if (data != NULL)
1634 {
1635 error = USDHC_TransferDataBlocking(base, data, enDMA);
1636 if (kStatus_Success != error)
1637 {
1638 return error;
1639 }
1640 }
1641
1642 return kStatus_Success;
1643 }
1644
1645 #if (defined FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER) && FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
1646 static status_t USDHC_SetScatterGatherAdmaTableConfig(USDHC_Type *base,
1647 usdhc_adma_config_t *dmaConfig,
1648 usdhc_scatter_gather_data_t *dataConfig,
1649 uint32_t *totalTransferSize)
1650 {
1651 assert(NULL != dmaConfig);
1652 assert((NULL != dmaConfig->admaTable) &&
1653 (((USDHC_ADMA_TABLE_ADDRESS_ALIGN - 1U) & (uint32_t)dmaConfig->admaTable) == 0UL));
1654 assert(NULL != dataConfig);
1655
1656 status_t error = kStatus_Fail;
1657 uint32_t *admaDesBuffer = dmaConfig->admaTable;
1658 uint32_t admaDesLen = dmaConfig->admaTableWords;
1659 usdhc_scatter_gather_data_list_t *sgDataList = &dataConfig->sgData;
1660 uint32_t oneDescriptorMaxTransferSize = dmaConfig->dmaMode == kUSDHC_DmaModeAdma1 ?
1661 USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY :
1662 USDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY;
1663 uint32_t miniEntries = 0U;
1664
1665 while (sgDataList != NULL)
1666 {
1667 if (dmaConfig->dmaMode == kUSDHC_DmaModeAdma1)
1668 {
1669 error = USDHC_SetADMA1Descriptor(admaDesBuffer, admaDesLen, sgDataList->dataAddr, sgDataList->dataSize, 0U);
1670 }
1671
1672 else
1673 {
1674 error = USDHC_SetADMA2Descriptor(admaDesBuffer, admaDesLen, sgDataList->dataAddr, sgDataList->dataSize, 0U);
1675 }
1676
1677 if (error != kStatus_Success)
1678 {
1679 return kStatus_USDHC_PrepareAdmaDescriptorFailed;
1680 }
1681
1682 #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
1683 if (dataConfig->dataDirection == kUSDHC_TransferDirectionSend)
1684 {
1685
1686 DCACHE_CleanByRange((uint32_t)sgDataList->dataAddr, sgDataList->dataSize);
1687 }
1688 else
1689 {
1690
1691 DCACHE_CleanInvalidateByRange((uint32_t)sgDataList->dataAddr, sgDataList->dataSize);
1692 }
1693 #endif
1694
1695 *totalTransferSize += sgDataList->dataSize;
1696 if (sgDataList->dataList != NULL)
1697 {
1698 if ((sgDataList->dataSize % oneDescriptorMaxTransferSize) == 0UL)
1699 {
1700 miniEntries = sgDataList->dataSize / oneDescriptorMaxTransferSize;
1701 }
1702 else
1703 {
1704 miniEntries = ((sgDataList->dataSize / oneDescriptorMaxTransferSize) + 1UL);
1705 }
1706 if (dmaConfig->dmaMode == kUSDHC_DmaModeAdma1)
1707 {
1708 admaDesBuffer[miniEntries * 2U - 1U] &= ~kUSDHC_Adma1DescriptorEndFlag;
1709 }
1710 else
1711 {
1712 admaDesBuffer[miniEntries * 2U - 2U] &= ~kUSDHC_Adma2DescriptorEndFlag;
1713 }
1714 admaDesBuffer += miniEntries * 2U;
1715 admaDesLen -= miniEntries * 2U;
1716 }
1717
1718 sgDataList = sgDataList->dataList;
1719 }
1720
1721 base->DS_ADDR = 0UL;
1722 base->ADMA_SYS_ADDR = (uint32_t)(dmaConfig->admaTable);
1723
1724
1725 base->PROT_CTRL &= ~(USDHC_PROT_CTRL_DMASEL_MASK);
1726 base->PROT_CTRL |= USDHC_PROT_CTRL_DMASEL(dmaConfig->dmaMode);
1727
1728
1729 base->MIX_CTRL |= USDHC_MIX_CTRL_DMAEN_MASK;
1730
1731 return error;
1732 }
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755 status_t USDHC_TransferScatterGatherADMANonBlocking(USDHC_Type *base,
1756 usdhc_handle_t *handle,
1757 usdhc_adma_config_t *dmaConfig,
1758 usdhc_scatter_gather_transfer_t *transfer)
1759 {
1760 assert(handle != NULL);
1761 assert(transfer != NULL);
1762 assert(dmaConfig != NULL);
1763
1764 status_t error = kStatus_Fail;
1765 usdhc_command_t *command = transfer->command;
1766 uint32_t totalTransferSize = 0U;
1767 uint32_t transferFlags = kUSDHC_CommandOnly;
1768 size_t blockSize = 0U;
1769 size_t blockCount = 0U;
1770 usdhc_scatter_gather_data_t *scatterGatherData = transfer->data;
1771 bool enDMA = false;
1772
1773
1774 if (IS_USDHC_FLAG_SET(base->PRES_STATE, kUSDHC_CommandInhibitFlag))
1775 {
1776 return kStatus_USDHC_BusyTransferring;
1777 }
1778
1779 handle->command = command;
1780 handle->data = scatterGatherData;
1781
1782 handle->transferredWords = 0UL;
1783
1784
1785 if (scatterGatherData != NULL)
1786 {
1787 if (scatterGatherData->sgData.dataAddr == NULL)
1788 {
1789 return kStatus_InvalidArgument;
1790 }
1791
1792 if (scatterGatherData->dataType != (uint32_t)kUSDHC_TransferDataTuning)
1793 {
1794 if (USDHC_SetScatterGatherAdmaTableConfig(base, dmaConfig, transfer->data, &totalTransferSize) !=
1795 kStatus_Success)
1796 {
1797 return kStatus_USDHC_PrepareAdmaDescriptorFailed;
1798 }
1799
1800 enDMA = true;
1801 }
1802 blockSize = scatterGatherData->blockSize;
1803 blockCount = totalTransferSize / scatterGatherData->blockSize;
1804 transferFlags = scatterGatherData->enableAutoCommand12 ? kUSDHC_DataWithAutoCmd12 : 0U;
1805 transferFlags |= scatterGatherData->enableAutoCommand23 ? kUSDHC_DataWithAutoCmd23 : 0U;
1806 transferFlags |= scatterGatherData->dataDirection == kUSDHC_TransferDirectionSend ? kUSDHC_CommandAndTxData :
1807 kUSDHC_CommandAndRxData;
1808 command->flags |= kUSDHC_DataPresentFlag;
1809 }
1810
1811 error = USDHC_SetTransferConfig(base, transferFlags, blockSize, blockCount);
1812 if (error != kStatus_Success)
1813 {
1814 return error;
1815 }
1816
1817
1818 if (scatterGatherData != NULL)
1819 {
1820 USDHC_ClearInterruptStatusFlags(
1821 base, (uint32_t)(enDMA == false ? kUSDHC_DataFlag : kUSDHC_DataDMAFlag | kUSDHC_DmaCompleteFlag) |
1822 (uint32_t)kUSDHC_CommandFlag);
1823 USDHC_EnableInterruptSignal(
1824 base, (uint32_t)(enDMA == false ? kUSDHC_DataFlag : kUSDHC_DataDMAFlag | kUSDHC_DmaCompleteFlag) |
1825 (uint32_t)kUSDHC_CommandFlag);
1826 }
1827 else
1828 {
1829 USDHC_ClearInterruptStatusFlags(base, kUSDHC_CommandFlag);
1830 USDHC_EnableInterruptSignal(base, kUSDHC_CommandFlag);
1831 }
1832
1833
1834 USDHC_SendCommand(base, command);
1835
1836 return kStatus_Success;
1837 }
1838 #else
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858 status_t USDHC_TransferNonBlocking(USDHC_Type *base,
1859 usdhc_handle_t *handle,
1860 usdhc_adma_config_t *dmaConfig,
1861 usdhc_transfer_t *transfer)
1862 {
1863 assert(handle != NULL);
1864 assert(transfer != NULL);
1865
1866 status_t error = kStatus_Fail;
1867 usdhc_command_t *command = transfer->command;
1868 usdhc_data_t *data = transfer->data;
1869 bool executeTuning = ((data == NULL) ? false : data->dataType == (uint32_t)kUSDHC_TransferDataTuning);
1870 bool enDMA = true;
1871 uint32_t transferFlags = (uint32_t)kUSDHC_CommandOnly;
1872 size_t blockSize = 0U;
1873 size_t blockCount = 0U;
1874
1875 #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (FSL_FEATURE_USDHC_HAS_SDR50_MODE)
1876
1877 if ((USDHC_GetInterruptStatusFlags(base) & ((uint32_t)kUSDHC_ReTuningEventFlag)) != 0UL)
1878 {
1879 USDHC_ClearInterruptStatusFlags(base, kUSDHC_ReTuningEventFlag);
1880 return kStatus_USDHC_ReTuningRequest;
1881 }
1882 #endif
1883
1884
1885 handle->command = command;
1886 handle->data = data;
1887
1888 handle->transferredWords = 0UL;
1889
1890 if (data != NULL)
1891 {
1892
1893 if ((dmaConfig != NULL) && (!executeTuning))
1894 {
1895 error = USDHC_SetAdmaTableConfig(
1896 base, dmaConfig, data,
1897 (uint32_t)(IS_USDHC_FLAG_SET(data->dataType, (uint32_t)kUSDHC_TransferDataBoot) ?
1898 kUSDHC_AdmaDescriptorMultipleFlag :
1899 kUSDHC_AdmaDescriptorSingleFlag));
1900 }
1901
1902 blockSize = data->blockSize;
1903 blockCount = data->blockCount;
1904 transferFlags = data->enableAutoCommand12 ? (uint32_t)kUSDHC_DataWithAutoCmd12 : 0U;
1905 transferFlags |= data->enableAutoCommand23 ? (uint32_t)kUSDHC_DataWithAutoCmd23 : 0U;
1906 transferFlags |= data->txData != NULL ? (uint32_t)kUSDHC_CommandAndTxData : (uint32_t)kUSDHC_CommandAndRxData;
1907 transferFlags |= data->dataType == (uint8_t)kUSDHC_TransferDataBoot ? (uint32_t)kUSDHC_BootData : 0U;
1908 transferFlags |=
1909 data->dataType == (uint8_t)kUSDHC_TransferDataBootcontinous ? (uint32_t)kUSDHC_BootDataContinuous : 0U;
1910
1911 command->flags |= (uint32_t)kUSDHC_DataPresentFlag;
1912 }
1913
1914
1915 if (error != kStatus_Success)
1916 {
1917
1918 USDHC_EnableInternalDMA(base, false);
1919 enDMA = false;
1920 }
1921 #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
1922 else
1923 {
1924 if (data->txData != NULL)
1925 {
1926
1927 DCACHE_CleanByRange((uint32_t)data->txData, (data->blockSize) * (data->blockCount));
1928 }
1929 else
1930 {
1931
1932 DCACHE_CleanInvalidateByRange((uint32_t)data->rxData, (data->blockSize) * (data->blockCount));
1933 }
1934 }
1935 #endif
1936
1937
1938 error = USDHC_SetTransferConfig(base, transferFlags, blockSize, blockCount);
1939 if (error != kStatus_Success)
1940 {
1941 return error;
1942 }
1943
1944
1945 if (handle->data != NULL)
1946 {
1947 USDHC_ClearInterruptStatusFlags(
1948 base, (uint32_t)(enDMA == false ? kUSDHC_DataFlag : kUSDHC_DataDMAFlag) | (uint32_t)kUSDHC_CommandFlag |
1949 (uint32_t)(data->dataType == (uint8_t)kUSDHC_TransferDataBootcontinous ?
1950 (uint32_t)kUSDHC_DmaCompleteFlag :
1951 0U));
1952 USDHC_EnableInterruptSignal(base, (uint32_t)(enDMA == false ? kUSDHC_DataFlag : kUSDHC_DataDMAFlag) |
1953 (uint32_t)kUSDHC_CommandFlag |
1954 (uint32_t)(data->dataType == (uint8_t)kUSDHC_TransferDataBootcontinous ?
1955 (uint32_t)kUSDHC_DmaCompleteFlag :
1956 0U));
1957 }
1958 else
1959 {
1960 USDHC_ClearInterruptStatusFlags(base, kUSDHC_CommandFlag);
1961 USDHC_EnableInterruptSignal(base, kUSDHC_CommandFlag);
1962 }
1963
1964
1965 USDHC_SendCommand(base, command);
1966
1967 return kStatus_Success;
1968 }
1969 #endif
1970
1971 #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (FSL_FEATURE_USDHC_HAS_SDR50_MODE)
1972
1973
1974
1975
1976
1977
1978
1979
1980 void USDHC_EnableManualTuning(USDHC_Type *base, bool enable)
1981 {
1982 if (enable)
1983 {
1984
1985 base->TUNING_CTRL &= ~USDHC_TUNING_CTRL_STD_TUNING_EN_MASK;
1986
1987 base->MIX_CTRL &= ~USDHC_MIX_CTRL_AUTO_TUNE_EN_MASK;
1988
1989 base->MIX_CTRL |= USDHC_MIX_CTRL_EXE_TUNE_MASK | USDHC_MIX_CTRL_SMP_CLK_SEL_MASK;
1990 }
1991 else
1992 {
1993 base->MIX_CTRL &= ~USDHC_MIX_CTRL_EXE_TUNE_MASK;
1994 }
1995 }
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005 status_t USDHC_AdjustDelayForManualTuning(USDHC_Type *base, uint32_t delay)
2006 {
2007 uint32_t clkTuneCtrl = 0UL;
2008
2009 clkTuneCtrl = base->CLK_TUNE_CTRL_STATUS;
2010
2011 clkTuneCtrl &= ~USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK;
2012
2013 clkTuneCtrl |= USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE(delay);
2014
2015
2016 base->CLK_TUNE_CTRL_STATUS = clkTuneCtrl;
2017
2018 if (IS_USDHC_FLAG_SET(base->CLK_TUNE_CTRL_STATUS,
2019 USDHC_CLK_TUNE_CTRL_STATUS_PRE_ERR_MASK | USDHC_CLK_TUNE_CTRL_STATUS_NXT_ERR_MASK))
2020 {
2021 return kStatus_Fail;
2022 }
2023
2024 return kStatus_Success;
2025 }
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037 status_t USDHC_SetTuningDelay(USDHC_Type *base, uint32_t preDelay, uint32_t outDelay, uint32_t postDelay)
2038 {
2039 assert(preDelay <=
2040 (USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK >> USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_SHIFT));
2041 assert(outDelay <=
2042 (USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_OUT_MASK >> USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_OUT_SHIFT));
2043 assert(postDelay <=
2044 (USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_POST_MASK >> USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_POST_SHIFT));
2045
2046 uint32_t clkTuneCtrl = 0UL;
2047
2048 clkTuneCtrl = base->CLK_TUNE_CTRL_STATUS;
2049
2050 clkTuneCtrl &=
2051 ~(USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK | USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_OUT_MASK |
2052 USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_POST_MASK);
2053
2054 clkTuneCtrl |= USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE(preDelay) |
2055 USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_OUT(outDelay) |
2056 USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_POST(postDelay);
2057
2058
2059 base->CLK_TUNE_CTRL_STATUS = clkTuneCtrl;
2060
2061 if (IS_USDHC_FLAG_SET(base->CLK_TUNE_CTRL_STATUS,
2062 USDHC_CLK_TUNE_CTRL_STATUS_PRE_ERR_MASK | USDHC_CLK_TUNE_CTRL_STATUS_NXT_ERR_MASK))
2063 {
2064 return kStatus_Fail;
2065 }
2066
2067 return kStatus_Success;
2068 }
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080 void USDHC_EnableStandardTuning(USDHC_Type *base, uint32_t tuningStartTap, uint32_t step, bool enable)
2081 {
2082 uint32_t tuningCtrl = 0UL;
2083
2084 if (enable)
2085 {
2086
2087 base->MIX_CTRL |= USDHC_MIX_CTRL_FBCLK_SEL_MASK;
2088
2089 tuningCtrl = base->TUNING_CTRL;
2090 tuningCtrl &= ~(USDHC_TUNING_CTRL_TUNING_START_TAP_MASK | USDHC_TUNING_CTRL_TUNING_STEP_MASK);
2091 tuningCtrl |= (USDHC_TUNING_CTRL_TUNING_START_TAP(tuningStartTap) | USDHC_TUNING_CTRL_TUNING_STEP(step) |
2092 USDHC_TUNING_CTRL_STD_TUNING_EN_MASK);
2093 base->TUNING_CTRL = tuningCtrl;
2094
2095
2096 base->AUTOCMD12_ERR_STATUS |=
2097 (USDHC_AUTOCMD12_ERR_STATUS_EXECUTE_TUNING_MASK | USDHC_AUTOCMD12_ERR_STATUS_SMP_CLK_SEL_MASK);
2098 }
2099 else
2100 {
2101
2102 base->TUNING_CTRL &= ~USDHC_TUNING_CTRL_STD_TUNING_EN_MASK;
2103
2104 base->AUTOCMD12_ERR_STATUS &=
2105 ~(USDHC_AUTOCMD12_ERR_STATUS_EXECUTE_TUNING_MASK | USDHC_AUTOCMD12_ERR_STATUS_SMP_CLK_SEL_MASK);
2106 }
2107 }
2108
2109 #if FSL_FEATURE_USDHC_HAS_HS400_MODE
2110
2111
2112
2113
2114
2115
2116
2117 void USDHC_ConfigStrobeDLL(USDHC_Type *base, uint32_t delayTarget, uint32_t updateInterval)
2118 {
2119 assert(delayTarget <= (USDHC_STROBE_DLL_CTRL_STROBE_DLL_CTRL_SLV_DLY_TARGET_MASK >>
2120 USDHC_STROBE_DLL_CTRL_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT));
2121
2122
2123 base->STROBE_DLL_CTRL |= USDHC_STROBE_DLL_CTRL_STROBE_DLL_CTRL_RESET_MASK;
2124
2125 base->STROBE_DLL_CTRL = 0;
2126
2127 base->STROBE_DLL_CTRL |= USDHC_STROBE_DLL_CTRL_STROBE_DLL_CTRL_ENABLE_MASK |
2128 USDHC_STROBE_DLL_CTRL_STROBE_DLL_CTRL_SLV_UPDATE_INT(updateInterval) |
2129 USDHC_STROBE_DLL_CTRL_STROBE_DLL_CTRL_SLV_DLY_TARGET(delayTarget);
2130
2131 while (
2132 (USDHC_GetStrobeDLLStatus(base) & (USDHC_STROBE_DLL_STATUS_STROBE_DLL_STS_SLV_LOCK_MASK |
2133 USDHC_STROBE_DLL_STATUS_STROBE_DLL_STS_REF_LOCK_MASK)) !=
2134 ((USDHC_STROBE_DLL_STATUS_STROBE_DLL_STS_SLV_LOCK_MASK | USDHC_STROBE_DLL_STATUS_STROBE_DLL_STS_REF_LOCK_MASK)))
2135 {
2136 }
2137 }
2138 #endif
2139
2140
2141
2142
2143
2144
2145 void USDHC_EnableAutoTuningForCmdAndData(USDHC_Type *base)
2146 {
2147 uint32_t busWidth = (base->PROT_CTRL & USDHC_PROT_CTRL_DTW_MASK) >> USDHC_PROT_CTRL_DTW_SHIFT;
2148
2149 base->VEND_SPEC2 |= USDHC_VEND_SPEC2_TUNING_CMD_EN_MASK;
2150
2151
2152 if (busWidth == 0UL)
2153 {
2154 base->VEND_SPEC2 &= ~USDHC_VEND_SPEC2_TUNING_8bit_EN_MASK;
2155 base->VEND_SPEC2 |= USDHC_VEND_SPEC2_TUNING_1bit_EN_MASK;
2156 }
2157
2158 else if (busWidth == 1UL)
2159 {
2160 base->VEND_SPEC2 &= ~USDHC_VEND_SPEC2_TUNING_8bit_EN_MASK;
2161 base->VEND_SPEC2 &= ~USDHC_VEND_SPEC2_TUNING_1bit_EN_MASK;
2162 }
2163
2164 else
2165 {
2166 base->VEND_SPEC2 |= USDHC_VEND_SPEC2_TUNING_8bit_EN_MASK;
2167 base->VEND_SPEC2 &= ~USDHC_VEND_SPEC2_TUNING_1bit_EN_MASK;
2168 }
2169 }
2170 #endif
2171
2172 static void USDHC_TransferHandleCardDetect(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags)
2173 {
2174 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_CardInsertionFlag))
2175 {
2176 if (handle->callback.CardInserted != NULL)
2177 {
2178 handle->callback.CardInserted(base, handle->userData);
2179 }
2180 }
2181 else
2182 {
2183 if (handle->callback.CardRemoved != NULL)
2184 {
2185 handle->callback.CardRemoved(base, handle->userData);
2186 }
2187 }
2188 }
2189
2190 static void USDHC_TransferHandleCommand(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags)
2191 {
2192 assert(handle->command != NULL);
2193
2194 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_CommandErrorFlag))
2195 {
2196 if (handle->callback.TransferComplete != NULL)
2197 {
2198 handle->callback.TransferComplete(base, handle, kStatus_USDHC_SendCommandFailed, handle->userData);
2199 }
2200 }
2201 else
2202 {
2203
2204 if (kStatus_Success != USDHC_ReceiveCommandResponse(base, handle->command))
2205 {
2206 if (handle->callback.TransferComplete != NULL)
2207 {
2208 handle->callback.TransferComplete(base, handle, kStatus_USDHC_SendCommandFailed, handle->userData);
2209 }
2210 }
2211 else
2212 {
2213 if (handle->callback.TransferComplete != NULL)
2214 {
2215 handle->callback.TransferComplete(base, handle, kStatus_USDHC_SendCommandSuccess, handle->userData);
2216 }
2217 }
2218 }
2219
2220 USDHC_DisableInterruptSignal(base, kUSDHC_CommandFlag);
2221 handle->command = NULL;
2222 }
2223
2224 #if (defined FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER) && FSL_USDHC_ENABLE_SCATTER_GATHER_TRANSFER
2225 static void USDHC_TransferHandleData(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags)
2226 {
2227 assert(handle->data != NULL);
2228
2229 status_t transferStatus = kStatus_USDHC_BusyTransferring;
2230
2231 if ((!(handle->data->enableIgnoreError)) &&
2232 (IS_USDHC_FLAG_SET(interruptFlags, (uint32_t)kUSDHC_DataErrorFlag | (uint32_t)kUSDHC_DmaErrorFlag)))
2233 {
2234 transferStatus = kStatus_USDHC_TransferDataFailed;
2235 }
2236 else
2237 {
2238 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_BufferReadReadyFlag))
2239 {
2240
2241 if (handle->data->dataType == (uint32_t)kUSDHC_TransferDataTuning)
2242 {
2243 transferStatus = kStatus_USDHC_TransferDataComplete;
2244 }
2245 }
2246 else
2247 {
2248 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_DmaCompleteFlag))
2249 {
2250 transferStatus = kStatus_USDHC_TransferDMAComplete;
2251 }
2252
2253 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_DataCompleteFlag))
2254 {
2255 transferStatus = kStatus_USDHC_TransferDataComplete;
2256
2257 #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
2258 if (handle->data->dataDirection == kUSDHC_TransferDirectionReceive)
2259 {
2260 usdhc_scatter_gather_data_list_t *sgDataList = &handle->data->sgData;
2261 while (sgDataList != NULL)
2262 {
2263 DCACHE_InvalidateByRange((uint32_t)sgDataList->dataAddr, sgDataList->dataSize);
2264 sgDataList = sgDataList->dataList;
2265 }
2266 }
2267 #endif
2268 }
2269 }
2270 }
2271
2272 if ((handle->callback.TransferComplete != NULL) && (transferStatus != kStatus_USDHC_BusyTransferring))
2273 {
2274 handle->callback.TransferComplete(base, handle, transferStatus, handle->userData);
2275 USDHC_DisableInterruptSignal(
2276 base, (uint32_t)kUSDHC_DataFlag | (uint32_t)kUSDHC_DataDMAFlag | (uint32_t)kUSDHC_DmaCompleteFlag);
2277 handle->data = NULL;
2278 }
2279 }
2280
2281 #else
2282 static void USDHC_TransferHandleData(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags)
2283 {
2284 assert(handle->data != NULL);
2285
2286 status_t transferStatus = kStatus_USDHC_BusyTransferring;
2287 uint32_t transferredWords = handle->transferredWords;
2288
2289 if ((!(handle->data->enableIgnoreError)) &&
2290 (IS_USDHC_FLAG_SET(interruptFlags, (uint32_t)kUSDHC_DataErrorFlag | (uint32_t)kUSDHC_DmaErrorFlag)))
2291 {
2292 transferStatus = kStatus_USDHC_TransferDataFailed;
2293 }
2294 else
2295 {
2296 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_BufferReadReadyFlag))
2297 {
2298
2299 if (handle->data->dataType == (uint32_t)kUSDHC_TransferDataTuning)
2300 {
2301 transferStatus = kStatus_USDHC_TransferDataComplete;
2302 }
2303 else
2304 {
2305 handle->transferredWords = USDHC_ReadDataPort(base, handle->data, transferredWords);
2306 }
2307 }
2308 else if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_BufferWriteReadyFlag))
2309 {
2310 handle->transferredWords = USDHC_WriteDataPort(base, handle->data, transferredWords);
2311 }
2312 else
2313 {
2314 if ((IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_DmaCompleteFlag)) &&
2315 (handle->data->dataType == (uint32_t)kUSDHC_TransferDataBootcontinous))
2316 {
2317 *(handle->data->rxData) = s_usdhcBootDummy;
2318 }
2319
2320 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_DataCompleteFlag))
2321 {
2322 transferStatus = kStatus_USDHC_TransferDataComplete;
2323
2324 #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
2325 if (handle->data->rxData != NULL)
2326 {
2327 DCACHE_InvalidateByRange((uint32_t)(handle->data->rxData),
2328 (handle->data->blockSize) * (handle->data->blockCount));
2329 }
2330 #endif
2331 }
2332 }
2333 }
2334
2335 if ((handle->callback.TransferComplete != NULL) && (transferStatus != kStatus_USDHC_BusyTransferring))
2336 {
2337 handle->callback.TransferComplete(base, handle, transferStatus, handle->userData);
2338 USDHC_DisableInterruptSignal(base, (uint32_t)kUSDHC_DataFlag | (uint32_t)kUSDHC_DataDMAFlag);
2339 handle->data = NULL;
2340 }
2341 }
2342 #endif
2343
2344 static void USDHC_TransferHandleSdioInterrupt(USDHC_Type *base, usdhc_handle_t *handle)
2345 {
2346 if (handle->callback.SdioInterrupt != NULL)
2347 {
2348 handle->callback.SdioInterrupt(base, handle->userData);
2349 }
2350 }
2351
2352 #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (FSL_FEATURE_USDHC_HAS_SDR50_MODE)
2353 static void USDHC_TransferHandleReTuning(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags)
2354 {
2355 assert(handle->callback.ReTuning != NULL);
2356
2357 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_TuningErrorFlag))
2358 {
2359 handle->callback.ReTuning(base, handle->userData);
2360 }
2361 }
2362 #endif
2363
2364 static void USDHC_TransferHandleBlockGap(USDHC_Type *base, usdhc_handle_t *handle)
2365 {
2366 if (handle->callback.BlockGap != NULL)
2367 {
2368 handle->callback.BlockGap(base, handle->userData);
2369 }
2370 }
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380 void USDHC_TransferCreateHandle(USDHC_Type *base,
2381 usdhc_handle_t *handle,
2382 const usdhc_transfer_callback_t *callback,
2383 void *userData)
2384 {
2385 assert(handle != NULL);
2386 assert(callback != NULL);
2387
2388
2389 (void)memset(handle, 0, sizeof(*handle));
2390
2391
2392 handle->callback.CardInserted = callback->CardInserted;
2393 handle->callback.CardRemoved = callback->CardRemoved;
2394 handle->callback.SdioInterrupt = callback->SdioInterrupt;
2395 handle->callback.BlockGap = callback->BlockGap;
2396 handle->callback.TransferComplete = callback->TransferComplete;
2397 handle->callback.ReTuning = callback->ReTuning;
2398 handle->userData = userData;
2399
2400
2401 s_usdhcHandle[USDHC_GetInstance(base)] = handle;
2402
2403
2404 s_usdhcIsr = USDHC_TransferHandleIRQ;
2405
2406 (void)EnableIRQ(s_usdhcIRQ[USDHC_GetInstance(base)]);
2407 }
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417 void USDHC_TransferHandleIRQ(USDHC_Type *base, usdhc_handle_t *handle)
2418 {
2419 assert(handle != NULL);
2420
2421 uint32_t interruptFlags;
2422
2423 interruptFlags = USDHC_GetEnabledInterruptStatusFlags(base);
2424
2425 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_CardDetectFlag))
2426 {
2427 USDHC_TransferHandleCardDetect(base, handle, interruptFlags);
2428 }
2429 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_CommandFlag))
2430 {
2431 USDHC_TransferHandleCommand(base, handle, interruptFlags);
2432 }
2433 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_DataFlag))
2434 {
2435 USDHC_TransferHandleData(base, handle, interruptFlags);
2436 }
2437 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_CardInterruptFlag))
2438 {
2439 USDHC_TransferHandleSdioInterrupt(base, handle);
2440 }
2441 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_BlockGapEventFlag))
2442 {
2443 USDHC_TransferHandleBlockGap(base, handle);
2444 }
2445 #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (FSL_FEATURE_USDHC_HAS_SDR50_MODE)
2446 if (IS_USDHC_FLAG_SET(interruptFlags, kUSDHC_SDR104TuningFlag))
2447 {
2448 USDHC_TransferHandleReTuning(base, handle, interruptFlags);
2449 }
2450 #endif
2451 USDHC_ClearInterruptStatusFlags(base, interruptFlags);
2452 }
2453
2454 #ifdef USDHC0
2455 void USDHC0_DriverIRQHandler(void);
2456 void USDHC0_DriverIRQHandler(void)
2457 {
2458 s_usdhcIsr(s_usdhcBase[0U], s_usdhcHandle[0U]);
2459 SDK_ISR_EXIT_BARRIER;
2460 }
2461 #endif
2462
2463 #ifdef USDHC1
2464 void USDHC1_DriverIRQHandler(void);
2465 void USDHC1_DriverIRQHandler(void)
2466 {
2467 s_usdhcIsr(s_usdhcBase[1U], s_usdhcHandle[1U]);
2468 SDK_ISR_EXIT_BARRIER;
2469 }
2470 #endif
2471
2472 #ifdef USDHC2
2473 void USDHC2_DriverIRQHandler(void);
2474 void USDHC2_DriverIRQHandler(void)
2475 {
2476 s_usdhcIsr(s_usdhcBase[2U], s_usdhcHandle[2U]);
2477 SDK_ISR_EXIT_BARRIER;
2478 }
2479
2480 #endif