fsl_usdhc.c 61 KB

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