fsl_usdhc.c 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654
  1. /*
  2. * Copyright (c) 2016, Freescale Semiconductor, Inc.
  3. * Copyright 2016-2017 NXP
  4. *
  5. * Redistribution and use in source and binary forms, with or without modification,
  6. * are permitted provided that the following conditions are met:
  7. *
  8. * o Redistributions of source code must retain the above copyright notice, this list
  9. * of conditions and the following disclaimer.
  10. *
  11. * o Redistributions in binary form must reproduce the above copyright notice, this
  12. * list of conditions and the following disclaimer in the documentation and/or
  13. * other materials provided with the distribution.
  14. *
  15. * o Neither the name of the copyright holder nor the names of its
  16. * contributors may be used to endorse or promote products derived from this
  17. * software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  23. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  26. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include "fsl_usdhc.h"
  31. #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
  32. #include "fsl_cache.h"
  33. #endif /* FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL */
  34. #ifdef RT_USING_SMART
  35. #include "imx6ull.h"
  36. #endif
  37. /*******************************************************************************
  38. * Definitions
  39. ******************************************************************************/
  40. /*! @brief Clock setting */
  41. /* Max SD clock divisor from base clock */
  42. #define USDHC_MAX_DVS ((USDHC_SYS_CTRL_DVS_MASK >> USDHC_SYS_CTRL_DVS_SHIFT) + 1U)
  43. #define USDHC_PREV_DVS(x) ((x) -= 1U)
  44. #define USDHC_PREV_CLKFS(x, y) ((x) >>= (y))
  45. /* Typedef for interrupt handler. */
  46. typedef void (*usdhc_isr_t)(USDHC_Type *base, usdhc_handle_t *handle);
  47. /*******************************************************************************
  48. * Prototypes
  49. ******************************************************************************/
  50. /*!
  51. * @brief Get the instance.
  52. *
  53. * @param base USDHC peripheral base address.
  54. * @return Instance number.
  55. */
  56. static uint32_t USDHC_GetInstance(USDHC_Type *base);
  57. /*!
  58. * @brief Set transfer interrupt.
  59. *
  60. * @param base USDHC peripheral base address.
  61. * @param usingInterruptSignal True to use IRQ signal.
  62. */
  63. static void USDHC_SetTransferInterrupt(USDHC_Type *base, bool usingInterruptSignal);
  64. /*!
  65. * @brief Start transfer according to current transfer state
  66. *
  67. * @param base USDHC peripheral base address.
  68. * @param command Command to be sent.
  69. * @param data Data to be transferred.
  70. */
  71. static status_t USDHC_SetTransferConfig(USDHC_Type *base, usdhc_command_t *command, usdhc_data_t *data);
  72. /*!
  73. * @brief Receive command response
  74. *
  75. * @param base USDHC peripheral base address.
  76. * @param command Command to be sent.
  77. */
  78. static status_t USDHC_ReceiveCommandResponse(USDHC_Type *base, usdhc_command_t *command);
  79. /*!
  80. * @brief Read DATAPORT when buffer enable bit is set.
  81. *
  82. * @param base USDHC peripheral base address.
  83. * @param data Data to be read.
  84. * @param transferredWords The number of data words have been transferred last time transaction.
  85. * @return The number of total data words have been transferred after this time transaction.
  86. */
  87. static uint32_t USDHC_ReadDataPort(USDHC_Type *base, usdhc_data_t *data, uint32_t transferredWords);
  88. /*!
  89. * @brief Read data by using DATAPORT polling way.
  90. *
  91. * @param base USDHC peripheral base address.
  92. * @param data Data to be read.
  93. * @retval kStatus_Fail Read DATAPORT failed.
  94. * @retval kStatus_Success Operate successfully.
  95. */
  96. static status_t USDHC_ReadByDataPortBlocking(USDHC_Type *base, usdhc_data_t *data);
  97. /*!
  98. * @brief Write DATAPORT when buffer enable bit is set.
  99. *
  100. * @param base USDHC peripheral base address.
  101. * @param data Data to be read.
  102. * @param transferredWords The number of data words have been transferred last time.
  103. * @return The number of total data words have been transferred after this time transaction.
  104. */
  105. static uint32_t USDHC_WriteDataPort(USDHC_Type *base, usdhc_data_t *data, uint32_t transferredWords);
  106. /*!
  107. * @brief Write data by using DATAPORT polling way.
  108. *
  109. * @param base USDHC peripheral base address.
  110. * @param data Data to be transferred.
  111. * @retval kStatus_Fail Write DATAPORT failed.
  112. * @retval kStatus_Success Operate successfully.
  113. */
  114. static status_t USDHC_WriteByDataPortBlocking(USDHC_Type *base, usdhc_data_t *data);
  115. /*!
  116. * @brief Transfer data by polling way.
  117. *
  118. * @param base USDHC peripheral base address.
  119. * @param data Data to be transferred.
  120. * @param use DMA flag.
  121. * @retval kStatus_Fail Transfer data failed.
  122. * @retval kStatus_InvalidArgument Argument is invalid.
  123. * @retval kStatus_Success Operate successfully.
  124. */
  125. static status_t USDHC_TransferDataBlocking(USDHC_Type *base, usdhc_data_t *data, bool enDMA);
  126. /*!
  127. * @brief Handle card detect interrupt.
  128. *
  129. * @param handle USDHC handle.
  130. * @param interruptFlags Card detect related interrupt flags.
  131. */
  132. static void USDHC_TransferHandleCardDetect(usdhc_handle_t *handle, uint32_t interruptFlags);
  133. /*!
  134. * @brief Handle command interrupt.
  135. *
  136. * @param base USDHC peripheral base address.
  137. * @param handle USDHC handle.
  138. * @param interruptFlags Command related interrupt flags.
  139. */
  140. static void USDHC_TransferHandleCommand(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags);
  141. /*!
  142. * @brief Handle data interrupt.
  143. *
  144. * @param base USDHC peripheral base address.
  145. * @param handle USDHC handle.
  146. * @param interruptFlags Data related interrupt flags.
  147. */
  148. static void USDHC_TransferHandleData(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags);
  149. /*!
  150. * @brief Handle SDIO card interrupt signal.
  151. *
  152. * @param handle USDHC handle.
  153. */
  154. static void USDHC_TransferHandleSdioInterrupt(usdhc_handle_t *handle);
  155. /*!
  156. * @brief Handle SDIO block gap event.
  157. *
  158. * @param handle USDHC handle.
  159. */
  160. static void USDHC_TransferHandleSdioBlockGap(usdhc_handle_t *handle);
  161. /*!
  162. * @brief Handle retuning
  163. *
  164. * @param interrupt flags
  165. */
  166. static void USDHC_TransferHandleReTuning(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags);
  167. /*!
  168. * @brief wait command done
  169. *
  170. * @param base USDHC peripheral base address.
  171. * @param command configuration
  172. * @param execute tuning flag
  173. */
  174. static status_t USDHC_WaitCommandDone(USDHC_Type *base, usdhc_command_t *command, bool executeTuning);
  175. /*******************************************************************************
  176. * Variables
  177. ******************************************************************************/
  178. /*! @brief USDHC base pointer array */
  179. static USDHC_Type *const s_usdhcBase[] = USDHC_BASE_PTRS;
  180. /*! @brief USDHC internal handle pointer array */
  181. static usdhc_handle_t *s_usdhcHandle[ARRAY_SIZE(s_usdhcBase)] = {NULL};
  182. /*! @brief USDHC IRQ name array */
  183. static const IRQn_Type s_usdhcIRQ[] = USDHC_IRQS;
  184. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  185. /*! @brief USDHC clock array name */
  186. static const clock_ip_name_t s_usdhcClock[] = USDHC_CLOCKS;
  187. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  188. /* USDHC ISR for transactional APIs. */
  189. static usdhc_isr_t s_usdhcIsr;
  190. /*******************************************************************************
  191. * Code
  192. ******************************************************************************/
  193. static uint32_t USDHC_GetInstance(USDHC_Type *base)
  194. {
  195. uint8_t instance = 0;
  196. #ifdef RT_USING_SMART
  197. while ((instance < ARRAY_SIZE(s_usdhcBase)) && (s_usdhcBase[instance] != rt_kmem_v2p(base)))
  198. #else
  199. while ((instance < ARRAY_SIZE(s_usdhcBase)) && (s_usdhcBase[instance] != base))
  200. #endif
  201. {
  202. instance++;
  203. }
  204. assert(instance < ARRAY_SIZE(s_usdhcBase));
  205. return instance;
  206. }
  207. static void USDHC_SetTransferInterrupt(USDHC_Type *base, bool usingInterruptSignal)
  208. {
  209. uint32_t interruptEnabled; /* The Interrupt status flags to be enabled */
  210. /* Disable all interrupts */
  211. USDHC_DisableInterruptStatus(base, (uint32_t)kUSDHC_AllInterruptFlags);
  212. USDHC_DisableInterruptSignal(base, (uint32_t)kUSDHC_AllInterruptFlags);
  213. DisableIRQ(s_usdhcIRQ[USDHC_GetInstance(base)]);
  214. interruptEnabled = (kUSDHC_CommandFlag | kUSDHC_CardInsertionFlag | kUSDHC_DataFlag | kUSDHC_CardRemovalFlag |
  215. kUSDHC_SDR104TuningFlag);
  216. USDHC_EnableInterruptStatus(base, interruptEnabled);
  217. if (usingInterruptSignal)
  218. {
  219. USDHC_EnableInterruptSignal(base, interruptEnabled);
  220. }
  221. }
  222. static status_t USDHC_SetTransferConfig(USDHC_Type *base, usdhc_command_t *command, usdhc_data_t *data)
  223. {
  224. assert(NULL != command);
  225. if ((data != NULL) && (data->blockCount > USDHC_MAX_BLOCK_COUNT))
  226. {
  227. return kStatus_InvalidArgument;
  228. }
  229. /* Define the flag corresponding to each response type. */
  230. switch (command->responseType)
  231. {
  232. case kCARD_ResponseTypeNone:
  233. break;
  234. case kCARD_ResponseTypeR1: /* Response 1 */
  235. case kCARD_ResponseTypeR5: /* Response 5 */
  236. case kCARD_ResponseTypeR6: /* Response 6 */
  237. case kCARD_ResponseTypeR7: /* Response 7 */
  238. command->flags |= (kUSDHC_ResponseLength48Flag | kUSDHC_EnableCrcCheckFlag | kUSDHC_EnableIndexCheckFlag);
  239. break;
  240. case kCARD_ResponseTypeR1b: /* Response 1 with busy */
  241. case kCARD_ResponseTypeR5b: /* Response 5 with busy */
  242. command->flags |=
  243. (kUSDHC_ResponseLength48BusyFlag | kUSDHC_EnableCrcCheckFlag | kUSDHC_EnableIndexCheckFlag);
  244. break;
  245. case kCARD_ResponseTypeR2: /* Response 2 */
  246. command->flags |= (kUSDHC_ResponseLength136Flag | kUSDHC_EnableCrcCheckFlag);
  247. break;
  248. case kCARD_ResponseTypeR3: /* Response 3 */
  249. case kCARD_ResponseTypeR4: /* Response 4 */
  250. command->flags |= (kUSDHC_ResponseLength48Flag);
  251. break;
  252. default:
  253. break;
  254. }
  255. if (command->type == kCARD_CommandTypeAbort)
  256. {
  257. command->flags |= kUSDHC_CommandTypeAbortFlag;
  258. }
  259. if (data)
  260. {
  261. command->flags |= kUSDHC_DataPresentFlag;
  262. if (data->rxData)
  263. {
  264. command->flags |= kUSDHC_DataReadFlag;
  265. }
  266. if (data->blockCount > 1U)
  267. {
  268. command->flags |= (kUSDHC_MultipleBlockFlag | kUSDHC_EnableBlockCountFlag);
  269. /* auto command 12 */
  270. if (data->enableAutoCommand12)
  271. {
  272. /* Enable Auto command 12. */
  273. command->flags |= kUSDHC_EnableAutoCommand12Flag;
  274. }
  275. /* auto command 23 */
  276. if (data->enableAutoCommand23)
  277. {
  278. command->flags |= kUSDHC_EnableAutoCommand23Flag;
  279. }
  280. }
  281. /* config data block size/block count */
  282. base->BLK_ATT = ((base->BLK_ATT & ~(USDHC_BLK_ATT_BLKSIZE_MASK | USDHC_BLK_ATT_BLKCNT_MASK)) |
  283. (USDHC_BLK_ATT_BLKSIZE(data->blockSize) | USDHC_BLK_ATT_BLKCNT(data->blockCount)));
  284. /* auto command 23, auto send set block count cmd before multiple read/write */
  285. if (((command->flags & kUSDHC_EnableAutoCommand23Flag) != 0U))
  286. {
  287. base->MIX_CTRL |= USDHC_MIX_CTRL_AC23EN_MASK;
  288. base->VEND_SPEC2 |= USDHC_VEND_SPEC2_ACMD23_ARGU2_EN_MASK;
  289. /* config the block count to DS_ADDR */
  290. base->DS_ADDR = data->blockCount;
  291. }
  292. else
  293. {
  294. base->MIX_CTRL &= ~USDHC_MIX_CTRL_AC23EN_MASK;
  295. base->VEND_SPEC2 &= ~USDHC_VEND_SPEC2_ACMD23_ARGU2_EN_MASK;
  296. }
  297. }
  298. return kStatus_Success;
  299. }
  300. static status_t USDHC_ReceiveCommandResponse(USDHC_Type *base, usdhc_command_t *command)
  301. {
  302. uint32_t i;
  303. if (command->responseType != kCARD_ResponseTypeNone)
  304. {
  305. command->response[0U] = base->CMD_RSP0;
  306. if (command->responseType == kCARD_ResponseTypeR2)
  307. {
  308. command->response[1U] = base->CMD_RSP1;
  309. command->response[2U] = base->CMD_RSP2;
  310. command->response[3U] = base->CMD_RSP3;
  311. i = 4U;
  312. /* R3-R2-R1-R0(lowest 8 bit is invalid bit) has the same format as R2 format in SD specification document
  313. after removed internal CRC7 and end bit. */
  314. do
  315. {
  316. command->response[i - 1U] <<= 8U;
  317. if (i > 1U)
  318. {
  319. command->response[i - 1U] |= ((command->response[i - 2U] & 0xFF000000U) >> 24U);
  320. }
  321. } while (i--);
  322. }
  323. }
  324. /* check response error flag */
  325. if ((command->responseErrorFlags != 0U) &&
  326. ((command->responseType == kCARD_ResponseTypeR1) || (command->responseType == kCARD_ResponseTypeR1b) ||
  327. (command->responseType == kCARD_ResponseTypeR6) || (command->responseType == kCARD_ResponseTypeR5)))
  328. {
  329. if (((command->responseErrorFlags) & (command->response[0U])) != 0U)
  330. {
  331. return kStatus_USDHC_SendCommandFailed;
  332. }
  333. }
  334. return kStatus_Success;
  335. }
  336. static uint32_t USDHC_ReadDataPort(USDHC_Type *base, usdhc_data_t *data, uint32_t transferredWords)
  337. {
  338. uint32_t i;
  339. uint32_t totalWords;
  340. uint32_t wordsCanBeRead; /* The words can be read at this time. */
  341. uint32_t readWatermark = ((base->WTMK_LVL & USDHC_WTMK_LVL_RD_WML_MASK) >> USDHC_WTMK_LVL_RD_WML_SHIFT);
  342. /*
  343. * Add non aligned access support ,user need make sure your buffer size is big
  344. * enough to hold the data,in other words,user need make sure the buffer size
  345. * is 4 byte aligned
  346. */
  347. if (data->blockSize % sizeof(uint32_t) != 0U)
  348. {
  349. data->blockSize +=
  350. sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
  351. }
  352. totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
  353. /* If watermark level is equal or bigger than totalWords, transfers totalWords data. */
  354. if (readWatermark >= totalWords)
  355. {
  356. wordsCanBeRead = totalWords;
  357. }
  358. /* If watermark level is less than totalWords and left words to be sent is equal or bigger than readWatermark,
  359. transfers watermark level words. */
  360. else if ((readWatermark < totalWords) && ((totalWords - transferredWords) >= readWatermark))
  361. {
  362. wordsCanBeRead = readWatermark;
  363. }
  364. /* If watermark level is less than totalWords and left words to be sent is less than readWatermark, transfers left
  365. words. */
  366. else
  367. {
  368. wordsCanBeRead = (totalWords - transferredWords);
  369. }
  370. i = 0U;
  371. while (i < wordsCanBeRead)
  372. {
  373. data->rxData[transferredWords++] = USDHC_ReadData(base);
  374. i++;
  375. }
  376. return transferredWords;
  377. }
  378. static status_t USDHC_ReadByDataPortBlocking(USDHC_Type *base, usdhc_data_t *data)
  379. {
  380. uint32_t totalWords;
  381. uint32_t transferredWords = 0U, interruptStatus = 0U;
  382. status_t error = kStatus_Success;
  383. /*
  384. * Add non aligned access support ,user need make sure your buffer size is big
  385. * enough to hold the data,in other words,user need make sure the buffer size
  386. * is 4 byte aligned
  387. */
  388. if (data->blockSize % sizeof(uint32_t) != 0U)
  389. {
  390. data->blockSize +=
  391. sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
  392. }
  393. totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
  394. while ((error == kStatus_Success) && (transferredWords < totalWords))
  395. {
  396. while (!(USDHC_GetInterruptStatusFlags(base) &
  397. (kUSDHC_BufferReadReadyFlag | kUSDHC_DataErrorFlag | kUSDHC_TuningErrorFlag)))
  398. {
  399. }
  400. interruptStatus = USDHC_GetInterruptStatusFlags(base);
  401. /* during std tuning process, software do not need to read data, but wait BRR is enough */
  402. if ((data->executeTuning) && (interruptStatus & kUSDHC_BufferReadReadyFlag))
  403. {
  404. USDHC_ClearInterruptStatusFlags(base, kUSDHC_BufferReadReadyFlag | kUSDHC_TuningPassFlag);
  405. return kStatus_Success;
  406. }
  407. else if ((interruptStatus & kUSDHC_TuningErrorFlag) != 0U)
  408. {
  409. USDHC_ClearInterruptStatusFlags(base, kUSDHC_TuningErrorFlag);
  410. /* if tuning error occur ,return directly */
  411. error = kStatus_USDHC_TuningError;
  412. }
  413. else if ((interruptStatus & kUSDHC_DataErrorFlag) != 0U)
  414. {
  415. if (!(data->enableIgnoreError))
  416. {
  417. error = kStatus_Fail;
  418. }
  419. /* clear data error flag */
  420. USDHC_ClearInterruptStatusFlags(base, kUSDHC_DataErrorFlag);
  421. }
  422. else
  423. {
  424. }
  425. if (error == kStatus_Success)
  426. {
  427. transferredWords = USDHC_ReadDataPort(base, data, transferredWords);
  428. /* clear buffer read ready */
  429. USDHC_ClearInterruptStatusFlags(base, kUSDHC_BufferReadReadyFlag);
  430. }
  431. }
  432. /* Clear data complete flag after the last read operation. */
  433. USDHC_ClearInterruptStatusFlags(base, kUSDHC_DataCompleteFlag);
  434. return error;
  435. }
  436. static uint32_t USDHC_WriteDataPort(USDHC_Type *base, usdhc_data_t *data, uint32_t transferredWords)
  437. {
  438. uint32_t i;
  439. uint32_t totalWords;
  440. uint32_t wordsCanBeWrote; /* Words can be wrote at this time. */
  441. uint32_t writeWatermark = ((base->WTMK_LVL & USDHC_WTMK_LVL_WR_WML_MASK) >> USDHC_WTMK_LVL_WR_WML_SHIFT);
  442. /*
  443. * Add non aligned access support ,user need make sure your buffer size is big
  444. * enough to hold the data,in other words,user need make sure the buffer size
  445. * is 4 byte aligned
  446. */
  447. if (data->blockSize % sizeof(uint32_t) != 0U)
  448. {
  449. data->blockSize +=
  450. sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
  451. }
  452. totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
  453. /* If watermark level is equal or bigger than totalWords, transfers totalWords data.*/
  454. if (writeWatermark >= totalWords)
  455. {
  456. wordsCanBeWrote = totalWords;
  457. }
  458. /* If watermark level is less than totalWords and left words to be sent is equal or bigger than watermark,
  459. transfers watermark level words. */
  460. else if ((writeWatermark < totalWords) && ((totalWords - transferredWords) >= writeWatermark))
  461. {
  462. wordsCanBeWrote = writeWatermark;
  463. }
  464. /* If watermark level is less than totalWords and left words to be sent is less than watermark, transfers left
  465. words. */
  466. else
  467. {
  468. wordsCanBeWrote = (totalWords - transferredWords);
  469. }
  470. i = 0U;
  471. while (i < wordsCanBeWrote)
  472. {
  473. USDHC_WriteData(base, data->txData[transferredWords++]);
  474. i++;
  475. }
  476. return transferredWords;
  477. }
  478. static status_t USDHC_WriteByDataPortBlocking(USDHC_Type *base, usdhc_data_t *data)
  479. {
  480. uint32_t totalWords;
  481. uint32_t transferredWords = 0U, interruptStatus = 0U;
  482. status_t error = kStatus_Success;
  483. /*
  484. * Add non aligned access support ,user need make sure your buffer size is big
  485. * enough to hold the data,in other words,user need make sure the buffer size
  486. * is 4 byte aligned
  487. */
  488. if (data->blockSize % sizeof(uint32_t) != 0U)
  489. {
  490. data->blockSize +=
  491. sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
  492. }
  493. totalWords = (data->blockCount * data->blockSize) / sizeof(uint32_t);
  494. while ((error == kStatus_Success) && (transferredWords < totalWords))
  495. {
  496. while (!(USDHC_GetInterruptStatusFlags(base) &
  497. (kUSDHC_BufferWriteReadyFlag | kUSDHC_DataErrorFlag | kUSDHC_TuningErrorFlag)))
  498. {
  499. }
  500. interruptStatus = USDHC_GetInterruptStatusFlags(base);
  501. if ((interruptStatus & kUSDHC_TuningErrorFlag) != 0U)
  502. {
  503. USDHC_ClearInterruptStatusFlags(base, kUSDHC_TuningErrorFlag);
  504. /* if tuning error occur ,return directly */
  505. return kStatus_USDHC_TuningError;
  506. }
  507. else if ((interruptStatus & kUSDHC_DataErrorFlag) != 0U)
  508. {
  509. if (!(data->enableIgnoreError))
  510. {
  511. error = kStatus_Fail;
  512. }
  513. /* clear data error flag */
  514. USDHC_ClearInterruptStatusFlags(base, kUSDHC_DataErrorFlag);
  515. }
  516. else
  517. {
  518. }
  519. if (error == kStatus_Success)
  520. {
  521. transferredWords = USDHC_WriteDataPort(base, data, transferredWords);
  522. /* clear buffer write ready */
  523. USDHC_ClearInterruptStatusFlags(base, kUSDHC_BufferWriteReadyFlag);
  524. }
  525. }
  526. /* Wait write data complete or data transfer error after the last writing operation. */
  527. while (!(USDHC_GetInterruptStatusFlags(base) & (kUSDHC_DataCompleteFlag | kUSDHC_DataErrorFlag)))
  528. {
  529. }
  530. if ((USDHC_GetInterruptStatusFlags(base) & kUSDHC_DataErrorFlag) != 0U)
  531. {
  532. if (!(data->enableIgnoreError))
  533. {
  534. error = kStatus_Fail;
  535. }
  536. }
  537. USDHC_ClearInterruptStatusFlags(base, (kUSDHC_DataCompleteFlag | kUSDHC_DataErrorFlag));
  538. return error;
  539. }
  540. void USDHC_SendCommand(USDHC_Type *base, usdhc_command_t *command)
  541. {
  542. assert(NULL != command);
  543. uint32_t mixCtrl, xferType;
  544. mixCtrl = base->MIX_CTRL;
  545. xferType = base->CMD_XFR_TYP;
  546. /* config mix parameter */
  547. mixCtrl &= ~(USDHC_MIX_CTRL_MSBSEL_MASK | USDHC_MIX_CTRL_BCEN_MASK | USDHC_MIX_CTRL_DTDSEL_MASK |
  548. USDHC_MIX_CTRL_AC12EN_MASK);
  549. mixCtrl |= ((command->flags) & (USDHC_MIX_CTRL_MSBSEL_MASK | USDHC_MIX_CTRL_BCEN_MASK | USDHC_MIX_CTRL_DTDSEL_MASK |
  550. USDHC_MIX_CTRL_AC12EN_MASK));
  551. /* config cmd index */
  552. xferType &= ~(USDHC_CMD_XFR_TYP_CMDINX_MASK | USDHC_CMD_XFR_TYP_DPSEL_MASK | USDHC_CMD_XFR_TYP_CMDTYP_MASK |
  553. USDHC_CMD_XFR_TYP_CICEN_MASK | USDHC_CMD_XFR_TYP_CCCEN_MASK | USDHC_CMD_XFR_TYP_RSPTYP_MASK);
  554. xferType = (((command->index << USDHC_CMD_XFR_TYP_CMDINX_SHIFT) & USDHC_CMD_XFR_TYP_CMDINX_MASK) |
  555. ((command->flags) &
  556. (USDHC_CMD_XFR_TYP_DPSEL_MASK | USDHC_CMD_XFR_TYP_CMDTYP_MASK | USDHC_CMD_XFR_TYP_CICEN_MASK |
  557. USDHC_CMD_XFR_TYP_CCCEN_MASK | USDHC_CMD_XFR_TYP_RSPTYP_MASK)));
  558. /* config the mix parameter */
  559. base->MIX_CTRL = mixCtrl;
  560. /* config the command xfertype and argument */
  561. base->CMD_ARG = command->argument;
  562. base->CMD_XFR_TYP = xferType;
  563. }
  564. static status_t USDHC_WaitCommandDone(USDHC_Type *base, usdhc_command_t *command, bool executeTuning)
  565. {
  566. assert(NULL != command);
  567. status_t error = kStatus_Success;
  568. uint32_t interruptStatus = 0U;
  569. /* tuning cmd do not need to wait command done */
  570. if (!executeTuning)
  571. {
  572. /* Wait command complete or USDHC encounters error. */
  573. while (!(USDHC_GetInterruptStatusFlags(base) & (kUSDHC_CommandCompleteFlag | kUSDHC_CommandErrorFlag)))
  574. {
  575. }
  576. interruptStatus = USDHC_GetInterruptStatusFlags(base);
  577. if ((interruptStatus & kUSDHC_TuningErrorFlag) != 0U)
  578. {
  579. error = kStatus_USDHC_TuningError;
  580. }
  581. else if ((interruptStatus & kUSDHC_CommandErrorFlag) != 0U)
  582. {
  583. error = kStatus_Fail;
  584. }
  585. else
  586. {
  587. }
  588. /* Receive response when command completes successfully. */
  589. if (error == kStatus_Success)
  590. {
  591. error = USDHC_ReceiveCommandResponse(base, command);
  592. }
  593. USDHC_ClearInterruptStatusFlags(
  594. base, (kUSDHC_CommandCompleteFlag | kUSDHC_CommandErrorFlag | kUSDHC_TuningErrorFlag));
  595. }
  596. return error;
  597. }
  598. static status_t USDHC_TransferDataBlocking(USDHC_Type *base, usdhc_data_t *data, bool enDMA)
  599. {
  600. status_t error = kStatus_Success;
  601. uint32_t interruptStatus = 0U;
  602. if (enDMA)
  603. {
  604. /* Wait data complete or USDHC encounters error. */
  605. while (!(USDHC_GetInterruptStatusFlags(base) &
  606. (kUSDHC_DataCompleteFlag | kUSDHC_DataErrorFlag | kUSDHC_DmaErrorFlag | kUSDHC_TuningErrorFlag)))
  607. {
  608. }
  609. interruptStatus = USDHC_GetInterruptStatusFlags(base);
  610. if ((interruptStatus & kUSDHC_TuningErrorFlag) != 0U)
  611. {
  612. error = kStatus_USDHC_TuningError;
  613. }
  614. else if ((interruptStatus & (kUSDHC_DataErrorFlag | kUSDHC_DmaErrorFlag)) != 0U)
  615. {
  616. if (!(data->enableIgnoreError) || (interruptStatus & kUSDHC_DataTimeoutFlag))
  617. {
  618. error = kStatus_Fail;
  619. }
  620. }
  621. else
  622. {
  623. }
  624. USDHC_ClearInterruptStatusFlags(base, (kUSDHC_DataCompleteFlag | kUSDHC_DataErrorFlag | kUSDHC_DmaErrorFlag |
  625. kUSDHC_TuningPassFlag | kUSDHC_TuningErrorFlag));
  626. }
  627. else
  628. {
  629. if (data->rxData)
  630. {
  631. error = USDHC_ReadByDataPortBlocking(base, data);
  632. }
  633. else
  634. {
  635. error = USDHC_WriteByDataPortBlocking(base, data);
  636. }
  637. }
  638. #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
  639. /* invalidate cache for read */
  640. if ((data != NULL) && (data->rxData != NULL))
  641. {
  642. /* invalidate the DCACHE */
  643. DCACHE_InvalidateByRange((uint32_t)data->rxData, (data->blockSize) * (data->blockCount));
  644. }
  645. #endif
  646. return error;
  647. }
  648. void USDHC_Init(USDHC_Type *base, const usdhc_config_t *config)
  649. {
  650. assert(config);
  651. assert((config->writeWatermarkLevel >= 1U) && (config->writeWatermarkLevel <= 128U));
  652. assert((config->readWatermarkLevel >= 1U) && (config->readWatermarkLevel <= 128U));
  653. assert(config->writeBurstLen <= 16U);
  654. uint32_t proctl, sysctl, wml;
  655. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  656. /* Enable USDHC clock. */
  657. CLOCK_EnableClock(s_usdhcClock[USDHC_GetInstance(base)]);
  658. #endif
  659. /* Reset USDHC. */
  660. USDHC_Reset(base, kUSDHC_ResetAll, 100U);
  661. proctl = base->PROT_CTRL;
  662. wml = base->WTMK_LVL;
  663. sysctl = base->SYS_CTRL;
  664. proctl &= ~(USDHC_PROT_CTRL_EMODE_MASK | USDHC_PROT_CTRL_DMASEL_MASK);
  665. /* Endian mode*/
  666. proctl |= USDHC_PROT_CTRL_EMODE(config->endianMode);
  667. /* Watermark level */
  668. wml &= ~(USDHC_WTMK_LVL_RD_WML_MASK | USDHC_WTMK_LVL_WR_WML_MASK | USDHC_WTMK_LVL_RD_BRST_LEN_MASK |
  669. USDHC_WTMK_LVL_WR_BRST_LEN_MASK);
  670. wml |= (USDHC_WTMK_LVL_RD_WML(config->readWatermarkLevel) | USDHC_WTMK_LVL_WR_WML(config->writeWatermarkLevel) |
  671. USDHC_WTMK_LVL_RD_BRST_LEN(config->readBurstLen) | USDHC_WTMK_LVL_WR_BRST_LEN(config->writeBurstLen));
  672. /* config the data timeout value */
  673. sysctl &= ~USDHC_SYS_CTRL_DTOCV_MASK;
  674. sysctl |= USDHC_SYS_CTRL_DTOCV(config->dataTimeout);
  675. base->SYS_CTRL = sysctl;
  676. base->WTMK_LVL = wml;
  677. base->PROT_CTRL = proctl;
  678. #if FSL_FEATURE_USDHC_HAS_EXT_DMA
  679. /* disable external DMA */
  680. base->VEND_SPEC &= ~USDHC_VEND_SPEC_EXT_DMA_EN_MASK;
  681. #endif
  682. /* disable internal DMA */
  683. base->MIX_CTRL &= ~USDHC_MIX_CTRL_DMAEN_MASK;
  684. /* Enable interrupt status but doesn't enable interrupt signal. */
  685. USDHC_SetTransferInterrupt(base, false);
  686. }
  687. void USDHC_Deinit(USDHC_Type *base)
  688. {
  689. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  690. /* Disable clock. */
  691. CLOCK_DisableClock(s_usdhcClock[USDHC_GetInstance(base)]);
  692. #endif
  693. }
  694. bool USDHC_Reset(USDHC_Type *base, uint32_t mask, uint32_t timeout)
  695. {
  696. base->SYS_CTRL |= (mask & (USDHC_SYS_CTRL_RSTA_MASK | USDHC_SYS_CTRL_RSTC_MASK | USDHC_SYS_CTRL_RSTD_MASK));
  697. /* Delay some time to wait reset success. */
  698. while ((base->SYS_CTRL & mask) != 0U)
  699. {
  700. if (timeout == 0U)
  701. {
  702. break;
  703. }
  704. timeout--;
  705. }
  706. return ((!timeout) ? false : true);
  707. }
  708. void USDHC_GetCapability(USDHC_Type *base, usdhc_capability_t *capability)
  709. {
  710. assert(capability);
  711. uint32_t htCapability;
  712. uint32_t maxBlockLength;
  713. htCapability = base->HOST_CTRL_CAP;
  714. /* Get the capability of USDHC. */
  715. maxBlockLength = ((htCapability & USDHC_HOST_CTRL_CAP_MBL_MASK) >> USDHC_HOST_CTRL_CAP_MBL_SHIFT);
  716. capability->maxBlockLength = (512U << maxBlockLength);
  717. /* Other attributes not in HTCAPBLT register. */
  718. capability->maxBlockCount = USDHC_MAX_BLOCK_COUNT;
  719. capability->flags = (htCapability & (kUSDHC_SupportAdmaFlag | kUSDHC_SupportHighSpeedFlag | kUSDHC_SupportDmaFlag |
  720. kUSDHC_SupportSuspendResumeFlag | kUSDHC_SupportV330Flag));
  721. capability->flags |= (htCapability & kUSDHC_SupportV300Flag);
  722. capability->flags |= (htCapability & kUSDHC_SupportV180Flag);
  723. capability->flags |=
  724. (htCapability & (kUSDHC_SupportDDR50Flag | kUSDHC_SupportSDR104Flag | kUSDHC_SupportSDR50Flag));
  725. /* USDHC support 4/8 bit data bus width. */
  726. capability->flags |= (kUSDHC_Support4BitFlag | kUSDHC_Support8BitFlag);
  727. }
  728. uint32_t USDHC_SetSdClock(USDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz)
  729. {
  730. assert(srcClock_Hz != 0U);
  731. assert((busClock_Hz != 0U) && (busClock_Hz <= srcClock_Hz));
  732. uint32_t totalDiv = 0U;
  733. uint32_t divisor = 0U;
  734. uint32_t prescaler = 0U;
  735. uint32_t sysctl = 0U;
  736. uint32_t nearestFrequency = 0U;
  737. uint32_t maxClKFS = ((USDHC_SYS_CTRL_SDCLKFS_MASK >> USDHC_SYS_CTRL_SDCLKFS_SHIFT) + 1U);
  738. bool enDDR = false;
  739. /* DDR mode max clkfs can reach 512 */
  740. if ((base->MIX_CTRL & USDHC_MIX_CTRL_DDR_EN_MASK) != 0U)
  741. {
  742. enDDR = true;
  743. maxClKFS *= 2U;
  744. }
  745. /* calucate total divisor first */
  746. totalDiv = srcClock_Hz / busClock_Hz;
  747. if (totalDiv != 0U)
  748. {
  749. /* calucate the divisor (srcClock_Hz / divisor) <= busClock_Hz */
  750. if ((srcClock_Hz / totalDiv) > busClock_Hz)
  751. {
  752. totalDiv++;
  753. }
  754. /* divide the total divisor to div and prescaler */
  755. if (totalDiv > USDHC_MAX_DVS)
  756. {
  757. prescaler = totalDiv / USDHC_MAX_DVS;
  758. /* prescaler must be a value which equal 2^n and smaller than SDHC_MAX_CLKFS */
  759. while (((maxClKFS % prescaler) != 0U) || (prescaler == 1U))
  760. {
  761. prescaler++;
  762. }
  763. /* calucate the divisor */
  764. divisor = totalDiv / prescaler;
  765. /* fine tuning the divisor until divisor * prescaler >= totalDiv */
  766. while ((divisor * prescaler) < totalDiv)
  767. {
  768. divisor++;
  769. }
  770. nearestFrequency = srcClock_Hz / divisor / prescaler;
  771. }
  772. else
  773. {
  774. /* in this situation , divsior and SDCLKFS can generate same clock
  775. use SDCLKFS*/
  776. if ((USDHC_MAX_DVS % totalDiv) == 0U)
  777. {
  778. divisor = 0U;
  779. prescaler = totalDiv;
  780. }
  781. else
  782. {
  783. divisor = totalDiv;
  784. prescaler = 0U;
  785. }
  786. nearestFrequency = srcClock_Hz / totalDiv;
  787. }
  788. }
  789. /* in this condition , srcClock_Hz = busClock_Hz, */
  790. else
  791. {
  792. /* in DDR mode , set SDCLKFS to 0, divisor = 0, actually the
  793. totoal divider = 2U */
  794. divisor = 0U;
  795. prescaler = 0U;
  796. nearestFrequency = srcClock_Hz;
  797. }
  798. /* calucate the value write to register */
  799. if (divisor != 0U)
  800. {
  801. USDHC_PREV_DVS(divisor);
  802. }
  803. /* calucate the value write to register */
  804. if (prescaler != 0U)
  805. {
  806. USDHC_PREV_CLKFS(prescaler, (enDDR ? 2U : 1U));
  807. }
  808. /* Set the SD clock frequency divisor, SD clock frequency select, data timeout counter value. */
  809. sysctl = base->SYS_CTRL;
  810. sysctl &= ~(USDHC_SYS_CTRL_DVS_MASK | USDHC_SYS_CTRL_SDCLKFS_MASK);
  811. sysctl |= (USDHC_SYS_CTRL_DVS(divisor) | USDHC_SYS_CTRL_SDCLKFS(prescaler));
  812. base->SYS_CTRL = sysctl;
  813. /* Wait until the SD clock is stable. */
  814. while (!(base->PRES_STATE & USDHC_PRES_STATE_SDSTB_MASK))
  815. {
  816. }
  817. return nearestFrequency;
  818. }
  819. bool USDHC_SetCardActive(USDHC_Type *base, uint32_t timeout)
  820. {
  821. base->SYS_CTRL |= USDHC_SYS_CTRL_INITA_MASK;
  822. /* Delay some time to wait card become active state. */
  823. while ((base->SYS_CTRL & USDHC_SYS_CTRL_INITA_MASK) == USDHC_SYS_CTRL_INITA_MASK)
  824. {
  825. if (!timeout)
  826. {
  827. break;
  828. }
  829. timeout--;
  830. }
  831. return ((!timeout) ? false : true);
  832. }
  833. void USDHC_SetMmcBootConfig(USDHC_Type *base, const usdhc_boot_config_t *config)
  834. {
  835. assert(config);
  836. assert(config->ackTimeoutCount <= (USDHC_MMC_BOOT_DTOCV_ACK_MASK >> USDHC_MMC_BOOT_DTOCV_ACK_SHIFT));
  837. assert(config->blockCount <= (USDHC_MMC_BOOT_BOOT_BLK_CNT_MASK >> USDHC_MMC_BOOT_BOOT_BLK_CNT_SHIFT));
  838. uint32_t mmcboot = 0U;
  839. mmcboot = (USDHC_MMC_BOOT_DTOCV_ACK(config->ackTimeoutCount) | USDHC_MMC_BOOT_BOOT_MODE(config->bootMode) |
  840. USDHC_MMC_BOOT_BOOT_BLK_CNT(config->blockCount));
  841. if (config->enableBootAck)
  842. {
  843. mmcboot |= USDHC_MMC_BOOT_BOOT_ACK_MASK;
  844. }
  845. if (config->enableBoot)
  846. {
  847. mmcboot |= USDHC_MMC_BOOT_BOOT_EN_MASK;
  848. }
  849. if (config->enableAutoStopAtBlockGap)
  850. {
  851. mmcboot |= USDHC_MMC_BOOT_AUTO_SABG_EN_MASK;
  852. }
  853. base->MMC_BOOT = mmcboot;
  854. }
  855. status_t USDHC_SetAdmaTableConfig(USDHC_Type *base,
  856. usdhc_adma_config_t *dmaConfig,
  857. usdhc_data_t *dataConfig,
  858. uint32_t flags)
  859. {
  860. assert(NULL != dmaConfig);
  861. assert(NULL != dmaConfig->admaTable);
  862. assert(NULL != dataConfig);
  863. const uint32_t *startAddress;
  864. uint32_t entries;
  865. uint32_t i, dmaBufferLen = 0U;
  866. usdhc_adma1_descriptor_t *adma1EntryAddress;
  867. usdhc_adma2_descriptor_t *adma2EntryAddress;
  868. uint32_t dataBytes = dataConfig->blockSize * dataConfig->blockCount;
  869. const uint32_t *data = (dataConfig->rxData == NULL) ? dataConfig->txData : dataConfig->rxData;
  870. /* check DMA data buffer address align or not */
  871. if (((dmaConfig->dmaMode == kUSDHC_DmaModeAdma1) && (((uint32_t)data % USDHC_ADMA1_ADDRESS_ALIGN) != 0U)) ||
  872. ((dmaConfig->dmaMode == kUSDHC_DmaModeAdma2) && (((uint32_t)data % USDHC_ADMA2_ADDRESS_ALIGN) != 0U)) ||
  873. ((dmaConfig->dmaMode == kUSDHC_DmaModeSimple) && (((uint32_t)data % USDHC_ADMA2_ADDRESS_ALIGN) != 0U)))
  874. {
  875. return kStatus_USDHC_DMADataAddrNotAlign;
  876. }
  877. /*
  878. * Add non aligned access support ,user need make sure your buffer size is big
  879. * enough to hold the data,in other words,user need make sure the buffer size
  880. * is 4 byte aligned
  881. */
  882. if (dataBytes % sizeof(uint32_t) != 0U)
  883. {
  884. /* make the data length as word-aligned */
  885. dataBytes += sizeof(uint32_t) - (dataBytes % sizeof(uint32_t));
  886. }
  887. startAddress = data;
  888. switch (dmaConfig->dmaMode)
  889. {
  890. #if FSL_FEATURE_USDHC_HAS_EXT_DMA
  891. case kUSDHC_ExternalDMA:
  892. /* enable the external DMA */
  893. base->VEND_SPEC |= USDHC_VEND_SPEC_EXT_DMA_EN_MASK;
  894. break;
  895. #endif
  896. case kUSDHC_DmaModeSimple:
  897. /* in simple DMA mode if use auto CMD23, address should load to ADMA addr,
  898. and block count should load to DS_ADDR*/
  899. if ((flags & kUSDHC_EnableAutoCommand23Flag) != 0U)
  900. {
  901. base->ADMA_SYS_ADDR = (uint32_t)data;
  902. }
  903. else
  904. {
  905. base->DS_ADDR = (uint32_t)data;
  906. }
  907. break;
  908. case kUSDHC_DmaModeAdma1:
  909. /* Check if ADMA descriptor's number is enough. */
  910. if ((dataBytes % USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) == 0U)
  911. {
  912. entries = dataBytes / USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY;
  913. }
  914. else
  915. {
  916. entries = ((dataBytes / USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U);
  917. }
  918. /* ADMA1 needs two descriptors to finish a transfer */
  919. entries <<= 1U;
  920. if (entries > ((dmaConfig->admaTableWords * sizeof(uint32_t)) / sizeof(usdhc_adma1_descriptor_t)))
  921. {
  922. return kStatus_OutOfRange;
  923. }
  924. adma1EntryAddress = (usdhc_adma1_descriptor_t *)(dmaConfig->admaTable);
  925. for (i = 0U; i < entries; i += 2U)
  926. {
  927. if (dataBytes > USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY)
  928. {
  929. dmaBufferLen = USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY;
  930. dataBytes -= dmaBufferLen;
  931. }
  932. else
  933. {
  934. dmaBufferLen = dataBytes;
  935. }
  936. adma1EntryAddress[i] = (dmaBufferLen << USDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT);
  937. adma1EntryAddress[i] |= kUSDHC_Adma1DescriptorTypeSetLength;
  938. adma1EntryAddress[i + 1U] = ((uint32_t)(startAddress) << USDHC_ADMA1_DESCRIPTOR_ADDRESS_SHIFT);
  939. adma1EntryAddress[i + 1U] |= kUSDHC_Adma1DescriptorTypeTransfer;
  940. startAddress += dmaBufferLen / sizeof(uint32_t);
  941. }
  942. /* the end of the descriptor */
  943. adma1EntryAddress[i - 1U] |= kUSDHC_Adma1DescriptorEndFlag;
  944. /* When use ADMA, disable simple DMA */
  945. base->DS_ADDR = 0U;
  946. base->ADMA_SYS_ADDR = (uint32_t)(dmaConfig->admaTable);
  947. break;
  948. case kUSDHC_DmaModeAdma2:
  949. /* Check if ADMA descriptor's number is enough. */
  950. if ((dataBytes % USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) == 0U)
  951. {
  952. entries = dataBytes / USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY;
  953. }
  954. else
  955. {
  956. entries = ((dataBytes / USDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U);
  957. }
  958. if (entries > ((dmaConfig->admaTableWords * sizeof(uint32_t)) / sizeof(usdhc_adma2_descriptor_t)))
  959. {
  960. return kStatus_OutOfRange;
  961. }
  962. adma2EntryAddress = (usdhc_adma2_descriptor_t *)(dmaConfig->admaTable);
  963. for (i = 0U; i < entries; i++)
  964. {
  965. if (dataBytes > USDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY)
  966. {
  967. dmaBufferLen = USDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY;
  968. dataBytes -= dmaBufferLen;
  969. }
  970. else
  971. {
  972. dmaBufferLen = dataBytes;
  973. }
  974. /* Each descriptor for ADMA2 is 64-bit in length */
  975. adma2EntryAddress[i].address = startAddress;
  976. adma2EntryAddress[i].attribute = (dmaBufferLen << USDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT);
  977. adma2EntryAddress[i].attribute |= kUSDHC_Adma2DescriptorTypeTransfer;
  978. startAddress += (dmaBufferLen / sizeof(uint32_t));
  979. }
  980. /* set the end bit */
  981. adma2EntryAddress[i - 1U].attribute |= kUSDHC_Adma2DescriptorEndFlag;
  982. /* When use ADMA, disable simple DMA */
  983. base->DS_ADDR = 0U;
  984. base->ADMA_SYS_ADDR = (uint32_t)(dmaConfig->admaTable);
  985. break;
  986. default:
  987. return kStatus_USDHC_PrepareAdmaDescriptorFailed;
  988. }
  989. /* for external dma */
  990. if (dmaConfig->dmaMode != kUSDHC_ExternalDMA)
  991. {
  992. #if FSL_FEATURE_USDHC_HAS_EXT_DMA
  993. /* disable the external DMA if support */
  994. base->VEND_SPEC &= ~USDHC_VEND_SPEC_EXT_DMA_EN_MASK;
  995. #endif
  996. /* select DMA mode and config the burst length */
  997. base->PROT_CTRL &= ~(USDHC_PROT_CTRL_DMASEL_MASK | USDHC_PROT_CTRL_BURST_LEN_EN_MASK);
  998. base->PROT_CTRL |=
  999. USDHC_PROT_CTRL_DMASEL(dmaConfig->dmaMode) | USDHC_PROT_CTRL_BURST_LEN_EN(dmaConfig->burstLen);
  1000. /* enable DMA */
  1001. base->MIX_CTRL |= USDHC_MIX_CTRL_DMAEN_MASK;
  1002. }
  1003. /* disable the interrupt signal for interrupt mode */
  1004. USDHC_DisableInterruptSignal(base, kUSDHC_BufferReadReadyFlag | kUSDHC_BufferWriteReadyFlag);
  1005. return kStatus_Success;
  1006. }
  1007. status_t USDHC_TransferBlocking(USDHC_Type *base, usdhc_adma_config_t *dmaConfig, usdhc_transfer_t *transfer)
  1008. {
  1009. assert(transfer);
  1010. status_t error = kStatus_Success;
  1011. usdhc_command_t *command = transfer->command;
  1012. usdhc_data_t *data = transfer->data;
  1013. bool enDMA = false;
  1014. /* Wait until command/data bus out of busy status. */
  1015. while (USDHC_GetPresentStatusFlags(base) & kUSDHC_CommandInhibitFlag)
  1016. {
  1017. }
  1018. while (data && (USDHC_GetPresentStatusFlags(base) & kUSDHC_DataInhibitFlag))
  1019. {
  1020. }
  1021. /*check re-tuning request*/
  1022. if ((USDHC_GetInterruptStatusFlags(base) & kUSDHC_ReTuningEventFlag) != 0U)
  1023. {
  1024. USDHC_ClearInterruptStatusFlags(base, kUSDHC_ReTuningEventFlag);
  1025. return kStatus_USDHC_ReTuningRequest;
  1026. }
  1027. #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
  1028. if ((data != NULL) && (!(data->executeTuning)))
  1029. {
  1030. if (data->txData != NULL)
  1031. {
  1032. /* clear the DCACHE */
  1033. DCACHE_CleanByRange((uint32_t)data->txData, (data->blockSize) * (data->blockCount));
  1034. }
  1035. else
  1036. {
  1037. /* clear the DCACHE */
  1038. DCACHE_CleanByRange((uint32_t)data->rxData, (data->blockSize) * (data->blockCount));
  1039. }
  1040. }
  1041. #endif
  1042. /* config the transfer parameter */
  1043. if (kStatus_Success != USDHC_SetTransferConfig(base, command, data))
  1044. {
  1045. return kStatus_InvalidArgument;
  1046. }
  1047. /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/
  1048. if ((data != NULL) && (dmaConfig != NULL) && (!data->executeTuning))
  1049. {
  1050. #if 0 //not use adma. there are some error not solved!
  1051. error = USDHC_SetAdmaTableConfig(base, dmaConfig, data, command->flags);
  1052. /* if the target data buffer address is not align , we change the transfer mode
  1053. * to polling automatically, other DMA config error will not cover by driver, user
  1054. * should handle it
  1055. */
  1056. if ((error != kStatus_USDHC_DMADataAddrNotAlign) && (error != kStatus_Success))
  1057. {
  1058. return kStatus_USDHC_PrepareAdmaDescriptorFailed;
  1059. }
  1060. else if (error == kStatus_USDHC_DMADataAddrNotAlign)
  1061. {
  1062. enDMA = false;
  1063. /* disable DMA, using polling mode in this situation */
  1064. base->MIX_CTRL &= ~USDHC_MIX_CTRL_DMAEN_MASK;
  1065. }
  1066. else
  1067. {
  1068. enDMA = true;
  1069. }
  1070. #else
  1071. enDMA = false;
  1072. /* disable DMA, using polling mode in this situation */
  1073. base->MIX_CTRL &= ~USDHC_MIX_CTRL_DMAEN_MASK;
  1074. #endif
  1075. }
  1076. else
  1077. {
  1078. /* disable DMA */
  1079. base->MIX_CTRL &= ~USDHC_MIX_CTRL_DMAEN_MASK;
  1080. }
  1081. /* send command */
  1082. USDHC_SendCommand(base, command);
  1083. /* wait command done */
  1084. error = USDHC_WaitCommandDone(base, command, ((data == NULL) ? false : data->executeTuning));
  1085. /* transfer data */
  1086. if ((data != NULL) && (error == kStatus_Success))
  1087. {
  1088. return USDHC_TransferDataBlocking(base, data, enDMA);
  1089. }
  1090. return error;
  1091. }
  1092. status_t USDHC_TransferNonBlocking(USDHC_Type *base,
  1093. usdhc_handle_t *handle,
  1094. usdhc_adma_config_t *dmaConfig,
  1095. usdhc_transfer_t *transfer)
  1096. {
  1097. assert(handle);
  1098. assert(transfer);
  1099. status_t error = kStatus_Success;
  1100. usdhc_command_t *command = transfer->command;
  1101. usdhc_data_t *data = transfer->data;
  1102. /* Wait until command/data bus out of busy status. */
  1103. if ((USDHC_GetPresentStatusFlags(base) & kUSDHC_CommandInhibitFlag) ||
  1104. (data && (USDHC_GetPresentStatusFlags(base) & kUSDHC_DataInhibitFlag)))
  1105. {
  1106. return kStatus_USDHC_BusyTransferring;
  1107. }
  1108. /*check re-tuning request*/
  1109. if ((USDHC_GetInterruptStatusFlags(base) & (kUSDHC_ReTuningEventFlag)) != 0U)
  1110. {
  1111. USDHC_ClearInterruptStatusFlags(base, kUSDHC_ReTuningEventFlag);
  1112. return kStatus_USDHC_ReTuningRequest;
  1113. }
  1114. #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
  1115. if ((data != NULL) && (!(data->executeTuning)))
  1116. {
  1117. if (data->txData != NULL)
  1118. {
  1119. /* clear the DCACHE */
  1120. DCACHE_CleanByRange((uint32_t)data->txData, (data->blockSize) * (data->blockCount));
  1121. }
  1122. else
  1123. {
  1124. /* clear the DCACHE */
  1125. DCACHE_CleanByRange((uint32_t)data->rxData, (data->blockSize) * (data->blockCount));
  1126. }
  1127. }
  1128. #endif
  1129. /* Save command and data into handle before transferring. */
  1130. handle->command = command;
  1131. handle->data = data;
  1132. handle->interruptFlags = 0U;
  1133. /* transferredWords will only be updated in ISR when transfer way is DATAPORT. */
  1134. handle->transferredWords = 0U;
  1135. if (kStatus_Success != USDHC_SetTransferConfig(base, command, data))
  1136. {
  1137. return kStatus_InvalidArgument;
  1138. }
  1139. /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/
  1140. if ((data != NULL) && (dmaConfig != NULL) && (!data->executeTuning))
  1141. {
  1142. error = USDHC_SetAdmaTableConfig(base, dmaConfig, data, command->flags);
  1143. /* if the target data buffer address is not align , we change the transfer mode
  1144. * to polling automatically, other DMA config error will not cover by driver, user
  1145. * should handle it
  1146. */
  1147. if ((error != kStatus_USDHC_DMADataAddrNotAlign) && (error != kStatus_Success))
  1148. {
  1149. return kStatus_USDHC_PrepareAdmaDescriptorFailed;
  1150. }
  1151. else if (error == kStatus_USDHC_DMADataAddrNotAlign)
  1152. {
  1153. /* disable DMA, using polling mode in this situation */
  1154. base->MIX_CTRL &= ~USDHC_MIX_CTRL_DMAEN_MASK;
  1155. /* enable the interrupt signal for interrupt mode */
  1156. USDHC_EnableInterruptSignal(base, kUSDHC_BufferReadReadyFlag | kUSDHC_BufferWriteReadyFlag);
  1157. }
  1158. else
  1159. {
  1160. }
  1161. }
  1162. else
  1163. {
  1164. /* disable DMA */
  1165. base->MIX_CTRL &= ~USDHC_MIX_CTRL_DMAEN_MASK;
  1166. }
  1167. /* enable the buffer read ready for std tuning */
  1168. if ((data != NULL) && (data->executeTuning))
  1169. {
  1170. USDHC_EnableInterruptSignal(base, kUSDHC_BufferReadReadyFlag);
  1171. }
  1172. /* send command */
  1173. USDHC_SendCommand(base, command);
  1174. return kStatus_Success;
  1175. }
  1176. #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (!FSL_FEATURE_USDHC_HAS_SDR50_MODE)
  1177. #else
  1178. void USDHC_EnableManualTuning(USDHC_Type *base, bool enable)
  1179. {
  1180. if (enable)
  1181. {
  1182. /* make sure std_tun_en bit is clear */
  1183. base->TUNING_CTRL &= ~USDHC_TUNING_CTRL_STD_TUNING_EN_MASK;
  1184. /* disable auto tuning here */
  1185. base->MIX_CTRL &= ~USDHC_MIX_CTRL_AUTO_TUNE_EN_MASK;
  1186. /* execute tuning for SDR104 mode */
  1187. base->MIX_CTRL |=
  1188. USDHC_MIX_CTRL_EXE_TUNE_MASK | USDHC_MIX_CTRL_SMP_CLK_SEL_MASK | USDHC_MIX_CTRL_FBCLK_SEL_MASK;
  1189. }
  1190. else
  1191. { /* abort the tuning */
  1192. base->MIX_CTRL &= ~(USDHC_MIX_CTRL_EXE_TUNE_MASK | USDHC_MIX_CTRL_SMP_CLK_SEL_MASK);
  1193. }
  1194. }
  1195. status_t USDHC_AdjustDelayForManualTuning(USDHC_Type *base, uint32_t delay)
  1196. {
  1197. uint32_t clkTuneCtrl = 0U;
  1198. clkTuneCtrl = base->CLK_TUNE_CTRL_STATUS;
  1199. clkTuneCtrl &= ~USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE_MASK;
  1200. clkTuneCtrl |= USDHC_CLK_TUNE_CTRL_STATUS_DLY_CELL_SET_PRE(delay);
  1201. /* load the delay setting */
  1202. base->CLK_TUNE_CTRL_STATUS = clkTuneCtrl;
  1203. /* check delat setting error */
  1204. if (base->CLK_TUNE_CTRL_STATUS &
  1205. (USDHC_CLK_TUNE_CTRL_STATUS_PRE_ERR_MASK | USDHC_CLK_TUNE_CTRL_STATUS_NXT_ERR_MASK))
  1206. {
  1207. return kStatus_Fail;
  1208. }
  1209. return kStatus_Success;
  1210. }
  1211. void USDHC_EnableStandardTuning(USDHC_Type *base, uint32_t tuningStartTap, uint32_t step, bool enable)
  1212. {
  1213. uint32_t tuningCtrl = 0U;
  1214. if (enable)
  1215. {
  1216. /* feedback clock */
  1217. base->MIX_CTRL |= USDHC_MIX_CTRL_FBCLK_SEL_MASK;
  1218. /* config tuning start and step */
  1219. tuningCtrl = base->TUNING_CTRL;
  1220. tuningCtrl &= ~(USDHC_TUNING_CTRL_TUNING_START_TAP_MASK | USDHC_TUNING_CTRL_TUNING_STEP_MASK);
  1221. tuningCtrl |= (USDHC_TUNING_CTRL_TUNING_START_TAP(tuningStartTap) | USDHC_TUNING_CTRL_TUNING_STEP(step) |
  1222. USDHC_TUNING_CTRL_STD_TUNING_EN_MASK);
  1223. base->TUNING_CTRL = tuningCtrl;
  1224. /* excute tuning */
  1225. base->AUTOCMD12_ERR_STATUS |=
  1226. (USDHC_AUTOCMD12_ERR_STATUS_EXECUTE_TUNING_MASK | USDHC_AUTOCMD12_ERR_STATUS_SMP_CLK_SEL_MASK);
  1227. }
  1228. else
  1229. {
  1230. /* disable the standard tuning */
  1231. base->TUNING_CTRL &= ~USDHC_TUNING_CTRL_STD_TUNING_EN_MASK;
  1232. /* clear excute tuning */
  1233. base->AUTOCMD12_ERR_STATUS &=
  1234. ~(USDHC_AUTOCMD12_ERR_STATUS_EXECUTE_TUNING_MASK | USDHC_AUTOCMD12_ERR_STATUS_SMP_CLK_SEL_MASK);
  1235. }
  1236. }
  1237. void USDHC_EnableAutoTuningForCmdAndData(USDHC_Type *base)
  1238. {
  1239. uint32_t busWidth = 0U;
  1240. base->VEND_SPEC2 |= USDHC_VEND_SPEC2_TUNING_CMD_EN_MASK;
  1241. busWidth = (base->PROT_CTRL & USDHC_PROT_CTRL_DTW_MASK) >> USDHC_PROT_CTRL_DTW_SHIFT;
  1242. if (busWidth == kUSDHC_DataBusWidth1Bit)
  1243. {
  1244. base->VEND_SPEC2 &= ~USDHC_VEND_SPEC2_TUNING_8bit_EN_MASK;
  1245. base->VEND_SPEC2 |= USDHC_VEND_SPEC2_TUNING_1bit_EN_MASK;
  1246. }
  1247. else if (busWidth == kUSDHC_DataBusWidth4Bit)
  1248. {
  1249. base->VEND_SPEC2 &= ~USDHC_VEND_SPEC2_TUNING_8bit_EN_MASK;
  1250. base->VEND_SPEC2 &= ~USDHC_VEND_SPEC2_TUNING_1bit_EN_MASK;
  1251. }
  1252. else if (busWidth == kUSDHC_DataBusWidth8Bit)
  1253. {
  1254. base->VEND_SPEC2 |= USDHC_VEND_SPEC2_TUNING_8bit_EN_MASK;
  1255. base->VEND_SPEC2 &= ~USDHC_VEND_SPEC2_TUNING_1bit_EN_MASK;
  1256. }
  1257. else
  1258. {
  1259. }
  1260. }
  1261. #endif
  1262. static void USDHC_TransferHandleCardDetect(usdhc_handle_t *handle, uint32_t interruptFlags)
  1263. {
  1264. if (interruptFlags & kUSDHC_CardInsertionFlag)
  1265. {
  1266. if (handle->callback.CardInserted)
  1267. {
  1268. handle->callback.CardInserted();
  1269. }
  1270. }
  1271. else
  1272. {
  1273. if (handle->callback.CardRemoved)
  1274. {
  1275. handle->callback.CardRemoved();
  1276. }
  1277. }
  1278. }
  1279. static void USDHC_TransferHandleCommand(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags)
  1280. {
  1281. assert(handle->command);
  1282. if ((interruptFlags & kUSDHC_CommandErrorFlag) && (!(handle->data)) && (handle->callback.TransferComplete))
  1283. {
  1284. handle->callback.TransferComplete(base, handle, kStatus_USDHC_SendCommandFailed, handle->userData);
  1285. }
  1286. else
  1287. {
  1288. /* Receive response */
  1289. if (kStatus_Success != USDHC_ReceiveCommandResponse(base, handle->command))
  1290. {
  1291. handle->callback.TransferComplete(base, handle, kStatus_USDHC_SendCommandFailed, handle->userData);
  1292. }
  1293. else if ((!(handle->data)) && (handle->callback.TransferComplete))
  1294. {
  1295. handle->callback.TransferComplete(base, handle, kStatus_Success, handle->userData);
  1296. }
  1297. else
  1298. {
  1299. }
  1300. }
  1301. }
  1302. static void USDHC_TransferHandleData(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags)
  1303. {
  1304. assert(handle->data);
  1305. if ((!(handle->data->enableIgnoreError) || (interruptFlags & kUSDHC_DataTimeoutFlag)) &&
  1306. (interruptFlags & (kUSDHC_DataErrorFlag | kUSDHC_DmaErrorFlag)) && (handle->callback.TransferComplete))
  1307. {
  1308. handle->callback.TransferComplete(base, handle, kStatus_USDHC_TransferDataFailed, handle->userData);
  1309. }
  1310. else
  1311. {
  1312. if (interruptFlags & kUSDHC_BufferReadReadyFlag)
  1313. {
  1314. /* std tuning process only need to wait BRR */
  1315. if (handle->data->executeTuning)
  1316. {
  1317. handle->callback.TransferComplete(base, handle, kStatus_Success, handle->userData);
  1318. }
  1319. else
  1320. {
  1321. handle->transferredWords = USDHC_ReadDataPort(base, handle->data, handle->transferredWords);
  1322. }
  1323. }
  1324. else if (interruptFlags & kUSDHC_BufferWriteReadyFlag)
  1325. {
  1326. handle->transferredWords = USDHC_WriteDataPort(base, handle->data, handle->transferredWords);
  1327. }
  1328. else if ((interruptFlags & kUSDHC_DataCompleteFlag) && (handle->callback.TransferComplete))
  1329. {
  1330. handle->callback.TransferComplete(base, handle, kStatus_Success, handle->userData);
  1331. }
  1332. else
  1333. {
  1334. /* Do nothing when DMA complete flag is set. Wait until data complete flag is set. */
  1335. }
  1336. #if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
  1337. /* invalidate cache for read */
  1338. if ((handle->data != NULL) && (handle->data->rxData != NULL))
  1339. {
  1340. /* invalidate the DCACHE */
  1341. DCACHE_InvalidateByRange((uint32_t)handle->data->rxData,
  1342. (handle->data->blockSize) * (handle->data->blockCount));
  1343. }
  1344. #endif
  1345. }
  1346. }
  1347. static void USDHC_TransferHandleSdioInterrupt(usdhc_handle_t *handle)
  1348. {
  1349. if (handle->callback.SdioInterrupt)
  1350. {
  1351. handle->callback.SdioInterrupt();
  1352. }
  1353. }
  1354. static void USDHC_TransferHandleReTuning(USDHC_Type *base, usdhc_handle_t *handle, uint32_t interruptFlags)
  1355. {
  1356. assert(handle->callback.ReTuning);
  1357. /* retuning request */
  1358. if ((interruptFlags & kUSDHC_TuningErrorFlag) == kUSDHC_TuningErrorFlag)
  1359. {
  1360. handle->callback.ReTuning(); /* retuning fail */
  1361. }
  1362. }
  1363. static void USDHC_TransferHandleSdioBlockGap(usdhc_handle_t *handle)
  1364. {
  1365. if (handle->callback.SdioBlockGap)
  1366. {
  1367. handle->callback.SdioBlockGap();
  1368. }
  1369. }
  1370. void USDHC_TransferCreateHandle(USDHC_Type *base,
  1371. usdhc_handle_t *handle,
  1372. const usdhc_transfer_callback_t *callback,
  1373. void *userData)
  1374. {
  1375. assert(handle);
  1376. assert(callback);
  1377. /* Zero the handle. */
  1378. memset(handle, 0, sizeof(*handle));
  1379. /* Set the callback. */
  1380. handle->callback.CardInserted = callback->CardInserted;
  1381. handle->callback.CardRemoved = callback->CardRemoved;
  1382. handle->callback.SdioInterrupt = callback->SdioInterrupt;
  1383. handle->callback.SdioBlockGap = callback->SdioBlockGap;
  1384. handle->callback.TransferComplete = callback->TransferComplete;
  1385. handle->callback.ReTuning = callback->ReTuning;
  1386. handle->userData = userData;
  1387. /* Save the handle in global variables to support the double weak mechanism. */
  1388. s_usdhcHandle[USDHC_GetInstance(base)] = handle;
  1389. /* Enable interrupt in NVIC. */
  1390. USDHC_SetTransferInterrupt(base, true);
  1391. /* disable the tuning pass interrupt */
  1392. USDHC_DisableInterruptSignal(base, kUSDHC_TuningPassFlag | kUSDHC_ReTuningEventFlag);
  1393. /* save IRQ handler */
  1394. s_usdhcIsr = USDHC_TransferHandleIRQ;
  1395. EnableIRQ(s_usdhcIRQ[USDHC_GetInstance(base)]);
  1396. }
  1397. void USDHC_TransferHandleIRQ(USDHC_Type *base, usdhc_handle_t *handle)
  1398. {
  1399. assert(handle);
  1400. uint32_t interruptFlags;
  1401. interruptFlags = USDHC_GetInterruptStatusFlags(base);
  1402. handle->interruptFlags = interruptFlags;
  1403. if (interruptFlags & kUSDHC_CardDetectFlag)
  1404. {
  1405. USDHC_TransferHandleCardDetect(handle, (interruptFlags & kUSDHC_CardDetectFlag));
  1406. }
  1407. if (interruptFlags & kUSDHC_CommandFlag)
  1408. {
  1409. USDHC_TransferHandleCommand(base, handle, (interruptFlags & kUSDHC_CommandFlag));
  1410. }
  1411. if (interruptFlags & kUSDHC_DataFlag)
  1412. {
  1413. USDHC_TransferHandleData(base, handle, (interruptFlags & kUSDHC_DataFlag));
  1414. }
  1415. if (interruptFlags & kUSDHC_CardInterruptFlag)
  1416. {
  1417. USDHC_TransferHandleSdioInterrupt(handle);
  1418. }
  1419. if (interruptFlags & kUSDHC_BlockGapEventFlag)
  1420. {
  1421. USDHC_TransferHandleSdioBlockGap(handle);
  1422. }
  1423. if (interruptFlags & kUSDHC_SDR104TuningFlag)
  1424. {
  1425. USDHC_TransferHandleReTuning(base, handle, (interruptFlags & kUSDHC_SDR104TuningFlag));
  1426. }
  1427. USDHC_ClearInterruptStatusFlags(base, interruptFlags);
  1428. }
  1429. #ifdef USDHC0
  1430. void USDHC0_DriverIRQHandler(void)
  1431. {
  1432. s_usdhcIsr(s_usdhcBase[0U], s_usdhcHandle[0U]);
  1433. }
  1434. #endif
  1435. #ifdef USDHC1
  1436. void USDHC1_DriverIRQHandler(void)
  1437. {
  1438. s_usdhcIsr(s_usdhcBase[1U], s_usdhcHandle[1U]);
  1439. }
  1440. #endif
  1441. #ifdef USDHC2
  1442. void USDHC2_DriverIRQHandler(void)
  1443. {
  1444. s_usdhcIsr(s_usdhcBase[2U], s_usdhcHandle[2U]);
  1445. }
  1446. #endif