fsl_sdhc.c 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416
  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_sdhc.h"
  31. /*******************************************************************************
  32. * Definitions
  33. ******************************************************************************/
  34. /*! @brief Clock setting */
  35. /* Max SD clock divisor from base clock */
  36. #define SDHC_MAX_DVS ((SDHC_SYSCTL_DVS_MASK >> SDHC_SYSCTL_DVS_SHIFT) + 1U)
  37. #define SDHC_PREV_DVS(x) ((x) -= 1U)
  38. #define SDHC_MAX_CLKFS ((SDHC_SYSCTL_SDCLKFS_MASK >> SDHC_SYSCTL_SDCLKFS_SHIFT) + 1U)
  39. #define SDHC_PREV_CLKFS(x) ((x) >>= 1U)
  40. /* Typedef for interrupt handler. */
  41. typedef void (*sdhc_isr_t)(SDHC_Type *base, sdhc_handle_t *handle);
  42. /*! @brief ADMA table configuration */
  43. typedef struct _sdhc_adma_table_config
  44. {
  45. uint32_t *admaTable; /*!< ADMA table address, can't be null if transfer way is ADMA1/ADMA2 */
  46. uint32_t admaTableWords; /*!< ADMA table length united as words, can't be 0 if transfer way is ADMA1/ADMA2 */
  47. } sdhc_adma_table_config_t;
  48. /*******************************************************************************
  49. * Prototypes
  50. ******************************************************************************/
  51. /*!
  52. * @brief Get the instance.
  53. *
  54. * @param base SDHC peripheral base address.
  55. * @return Instance number.
  56. */
  57. static uint32_t SDHC_GetInstance(SDHC_Type *base);
  58. /*!
  59. * @brief Set transfer interrupt.
  60. *
  61. * @param base SDHC peripheral base address.
  62. * @param usingInterruptSignal True to use IRQ signal.
  63. */
  64. static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal);
  65. /*!
  66. * @brief Start transfer according to current transfer state
  67. *
  68. * @param base SDHC peripheral base address.
  69. * @param command Command to be sent.
  70. * @param data Data to be transferred.
  71. * @param DMA mode selection
  72. */
  73. static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data, sdhc_dma_mode_t dmaMode);
  74. /*!
  75. * @brief Receive command response
  76. *
  77. * @param base SDHC peripheral base address.
  78. * @param command Command to be sent.
  79. */
  80. static status_t SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command);
  81. /*!
  82. * @brief Read DATAPORT when buffer enable bit is set.
  83. *
  84. * @param base SDHC peripheral base address.
  85. * @param data Data to be read.
  86. * @param transferredWords The number of data words have been transferred last time transaction.
  87. * @return The number of total data words have been transferred after this time transaction.
  88. */
  89. static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords);
  90. /*!
  91. * @brief Read data by using DATAPORT polling way.
  92. *
  93. * @param base SDHC peripheral base address.
  94. * @param data Data to be read.
  95. * @retval kStatus_Fail Read DATAPORT failed.
  96. * @retval kStatus_Success Operate successfully.
  97. */
  98. static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data);
  99. /*!
  100. * @brief Write DATAPORT when buffer enable bit is set.
  101. *
  102. * @param base SDHC peripheral base address.
  103. * @param data Data to be read.
  104. * @param transferredWords The number of data words have been transferred last time.
  105. * @return The number of total data words have been transferred after this time transaction.
  106. */
  107. static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords);
  108. /*!
  109. * @brief Write data by using DATAPORT polling way.
  110. *
  111. * @param base SDHC peripheral base address.
  112. * @param data Data to be transferred.
  113. * @retval kStatus_Fail Write DATAPORT failed.
  114. * @retval kStatus_Success Operate successfully.
  115. */
  116. static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data);
  117. /*!
  118. * @brief Send command by using polling way.
  119. *
  120. * @param base SDHC peripheral base address.
  121. * @param command Command to be sent.
  122. * @retval kStatus_Fail Send command failed.
  123. * @retval kStatus_Success Operate successfully.
  124. */
  125. static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *command);
  126. /*!
  127. * @brief Transfer data by DATAPORT and polling way.
  128. *
  129. * @param base SDHC peripheral base address.
  130. * @param data Data to be transferred.
  131. * @retval kStatus_Fail Transfer data failed.
  132. * @retval kStatus_Success Operate successfully.
  133. */
  134. static status_t SDHC_TransferByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data);
  135. /*!
  136. * @brief Transfer data by ADMA2 and polling way.
  137. *
  138. * @param base SDHC peripheral base address.
  139. * @param data Data to be transferred.
  140. * @retval kStatus_Fail Transfer data failed.
  141. * @retval kStatus_Success Operate successfully.
  142. */
  143. static status_t SDHC_TransferByAdma2Blocking(SDHC_Type *base, sdhc_data_t *data);
  144. /*!
  145. * @brief Transfer data by polling way.
  146. *
  147. * @param dmaMode DMA mode.
  148. * @param base SDHC peripheral base address.
  149. * @param data Data to be transferred.
  150. * @retval kStatus_Fail Transfer data failed.
  151. * @retval kStatus_InvalidArgument Argument is invalid.
  152. * @retval kStatus_Success Operate successfully.
  153. */
  154. static status_t SDHC_TransferDataBlocking(sdhc_dma_mode_t dmaMode, SDHC_Type *base, sdhc_data_t *data);
  155. /*!
  156. * @brief Handle card detect interrupt.
  157. *
  158. * @param handle SDHC handle.
  159. * @param interruptFlags Card detect related interrupt flags.
  160. */
  161. static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interruptFlags);
  162. /*!
  163. * @brief Handle command interrupt.
  164. *
  165. * @param base SDHC peripheral base address.
  166. * @param handle SDHC handle.
  167. * @param interruptFlags Command related interrupt flags.
  168. */
  169. static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags);
  170. /*!
  171. * @brief Handle data interrupt.
  172. *
  173. * @param base SDHC peripheral base address.
  174. * @param handle SDHC handle.
  175. * @param interruptFlags Data related interrupt flags.
  176. */
  177. static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags);
  178. /*!
  179. * @brief Handle SDIO card interrupt signal.
  180. *
  181. * @param handle SDHC handle.
  182. */
  183. static void SDHC_TransferHandleSdioInterrupt(sdhc_handle_t *handle);
  184. /*!
  185. * @brief Handle SDIO block gap event.
  186. *
  187. * @param handle SDHC handle.
  188. */
  189. static void SDHC_TransferHandleSdioBlockGap(sdhc_handle_t *handle);
  190. /*******************************************************************************
  191. * Variables
  192. ******************************************************************************/
  193. /*! @brief SDHC internal handle pointer array */
  194. static sdhc_handle_t *s_sdhcHandle[FSL_FEATURE_SOC_SDHC_COUNT];
  195. /*! @brief SDHC base pointer array */
  196. static SDHC_Type *const s_sdhcBase[] = SDHC_BASE_PTRS;
  197. /*! @brief SDHC IRQ name array */
  198. static const IRQn_Type s_sdhcIRQ[] = SDHC_IRQS;
  199. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  200. /*! @brief SDHC clock array name */
  201. static const clock_ip_name_t s_sdhcClock[] = SDHC_CLOCKS;
  202. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  203. /* SDHC ISR for transactional APIs. */
  204. static sdhc_isr_t s_sdhcIsr;
  205. /*******************************************************************************
  206. * Code
  207. ******************************************************************************/
  208. static uint32_t SDHC_GetInstance(SDHC_Type *base)
  209. {
  210. uint8_t instance = 0;
  211. while ((instance < ARRAY_SIZE(s_sdhcBase)) && (s_sdhcBase[instance] != base))
  212. {
  213. instance++;
  214. }
  215. assert(instance < ARRAY_SIZE(s_sdhcBase));
  216. return instance;
  217. }
  218. static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal)
  219. {
  220. uint32_t interruptEnabled; /* The Interrupt status flags to be enabled */
  221. bool cardDetectDat3 = (bool)(base->PROCTL & SDHC_PROCTL_D3CD_MASK);
  222. /* Disable all interrupts */
  223. SDHC_DisableInterruptStatus(base, (uint32_t)kSDHC_AllInterruptFlags);
  224. SDHC_DisableInterruptSignal(base, (uint32_t)kSDHC_AllInterruptFlags);
  225. DisableIRQ(s_sdhcIRQ[SDHC_GetInstance(base)]);
  226. interruptEnabled =
  227. (kSDHC_CommandIndexErrorFlag | kSDHC_CommandCrcErrorFlag | kSDHC_CommandEndBitErrorFlag |
  228. kSDHC_CommandTimeoutFlag | kSDHC_CommandCompleteFlag | kSDHC_DataTimeoutFlag | kSDHC_DataCrcErrorFlag |
  229. kSDHC_DataEndBitErrorFlag | kSDHC_DataCompleteFlag | kSDHC_AutoCommand12ErrorFlag | kSDHC_BufferReadReadyFlag |
  230. kSDHC_BufferWriteReadyFlag | kSDHC_DmaErrorFlag | kSDHC_DmaCompleteFlag);
  231. if (cardDetectDat3)
  232. {
  233. interruptEnabled |= (kSDHC_CardInsertionFlag | kSDHC_CardRemovalFlag);
  234. }
  235. SDHC_EnableInterruptStatus(base, interruptEnabled);
  236. if (usingInterruptSignal)
  237. {
  238. SDHC_EnableInterruptSignal(base, interruptEnabled);
  239. }
  240. }
  241. static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data, sdhc_dma_mode_t dmaMode)
  242. {
  243. uint32_t flags = 0U;
  244. sdhc_transfer_config_t sdhcTransferConfig = {0};
  245. /* Define the flag corresponding to each response type. */
  246. switch (command->responseType)
  247. {
  248. case kCARD_ResponseTypeNone:
  249. break;
  250. case kCARD_ResponseTypeR1: /* Response 1 */
  251. flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
  252. break;
  253. case kCARD_ResponseTypeR1b: /* Response 1 with busy */
  254. flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
  255. break;
  256. case kCARD_ResponseTypeR2: /* Response 2 */
  257. flags |= (kSDHC_ResponseLength136Flag | kSDHC_EnableCrcCheckFlag);
  258. break;
  259. case kCARD_ResponseTypeR3: /* Response 3 */
  260. flags |= (kSDHC_ResponseLength48Flag);
  261. break;
  262. case kCARD_ResponseTypeR4: /* Response 4 */
  263. flags |= (kSDHC_ResponseLength48Flag);
  264. break;
  265. case kCARD_ResponseTypeR5: /* Response 5 */
  266. flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
  267. break;
  268. case kCARD_ResponseTypeR5b: /* Response 5 with busy */
  269. flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
  270. break;
  271. case kCARD_ResponseTypeR6: /* Response 6 */
  272. flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
  273. break;
  274. case kCARD_ResponseTypeR7: /* Response 7 */
  275. flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
  276. break;
  277. default:
  278. break;
  279. }
  280. if (command->type == kCARD_CommandTypeAbort)
  281. {
  282. flags |= kSDHC_CommandTypeAbortFlag;
  283. }
  284. if (data)
  285. {
  286. flags |= kSDHC_DataPresentFlag;
  287. if (dmaMode != kSDHC_DmaModeNo)
  288. {
  289. flags |= kSDHC_EnableDmaFlag;
  290. }
  291. if (data->rxData)
  292. {
  293. flags |= kSDHC_DataReadFlag;
  294. }
  295. if (data->blockCount > 1U)
  296. {
  297. flags |= (kSDHC_MultipleBlockFlag | kSDHC_EnableBlockCountFlag);
  298. if (data->enableAutoCommand12)
  299. {
  300. /* Enable Auto command 12. */
  301. flags |= kSDHC_EnableAutoCommand12Flag;
  302. }
  303. }
  304. sdhcTransferConfig.dataBlockSize = data->blockSize;
  305. sdhcTransferConfig.dataBlockCount = data->blockCount;
  306. }
  307. else
  308. {
  309. sdhcTransferConfig.dataBlockSize = 0U;
  310. sdhcTransferConfig.dataBlockCount = 0U;
  311. }
  312. sdhcTransferConfig.commandArgument = command->argument;
  313. sdhcTransferConfig.commandIndex = command->index;
  314. sdhcTransferConfig.flags = flags;
  315. SDHC_SetTransferConfig(base, &sdhcTransferConfig);
  316. }
  317. static status_t SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command)
  318. {
  319. uint32_t i;
  320. if (command->responseType != kCARD_ResponseTypeNone)
  321. {
  322. command->response[0U] = SDHC_GetCommandResponse(base, 0U);
  323. if (command->responseType == kCARD_ResponseTypeR2)
  324. {
  325. command->response[1U] = SDHC_GetCommandResponse(base, 1U);
  326. command->response[2U] = SDHC_GetCommandResponse(base, 2U);
  327. command->response[3U] = SDHC_GetCommandResponse(base, 3U);
  328. i = 4U;
  329. /* R3-R2-R1-R0(lowest 8 bit is invalid bit) has the same format as R2 format in SD specification document
  330. after removed internal CRC7 and end bit. */
  331. do
  332. {
  333. command->response[i - 1U] <<= 8U;
  334. if (i > 1U)
  335. {
  336. command->response[i - 1U] |= ((command->response[i - 2U] & 0xFF000000U) >> 24U);
  337. }
  338. } while (i--);
  339. }
  340. }
  341. /* check response error flag */
  342. if ((command->responseErrorFlags != 0U) &&
  343. ((command->responseType == kCARD_ResponseTypeR1) || (command->responseType == kCARD_ResponseTypeR1b) ||
  344. (command->responseType == kCARD_ResponseTypeR6) || (command->responseType == kCARD_ResponseTypeR5)))
  345. {
  346. if (((command->responseErrorFlags) & (command->response[0U])) != 0U)
  347. {
  348. return kStatus_SDHC_SendCommandFailed;
  349. }
  350. }
  351. return kStatus_Success;
  352. }
  353. static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords)
  354. {
  355. uint32_t i;
  356. uint32_t totalWords;
  357. uint32_t wordsCanBeRead; /* The words can be read at this time. */
  358. uint32_t readWatermark = ((base->WML & SDHC_WML_RDWML_MASK) >> SDHC_WML_RDWML_SHIFT);
  359. /*
  360. * Add non aligned access support ,user need make sure your buffer size is big
  361. * enough to hold the data,in other words,user need make sure the buffer size
  362. * is 4 byte aligned
  363. */
  364. if (data->blockSize % sizeof(uint32_t) != 0U)
  365. {
  366. data->blockSize +=
  367. sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
  368. }
  369. totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
  370. /* If watermark level is equal or bigger than totalWords, transfers totalWords data. */
  371. if (readWatermark >= totalWords)
  372. {
  373. wordsCanBeRead = totalWords;
  374. }
  375. /* If watermark level is less than totalWords and left words to be sent is equal or bigger than readWatermark,
  376. transfers watermark level words. */
  377. else if ((readWatermark < totalWords) && ((totalWords - transferredWords) >= readWatermark))
  378. {
  379. wordsCanBeRead = readWatermark;
  380. }
  381. /* If watermark level is less than totalWords and left words to be sent is less than readWatermark, transfers left
  382. words. */
  383. else
  384. {
  385. wordsCanBeRead = (totalWords - transferredWords);
  386. }
  387. i = 0U;
  388. while (i < wordsCanBeRead)
  389. {
  390. data->rxData[transferredWords++] = SDHC_ReadData(base);
  391. i++;
  392. }
  393. return transferredWords;
  394. }
  395. static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
  396. {
  397. uint32_t totalWords;
  398. uint32_t transferredWords = 0U;
  399. status_t error = kStatus_Success;
  400. /*
  401. * Add non aligned access support ,user need make sure your buffer size is big
  402. * enough to hold the data,in other words,user need make sure the buffer size
  403. * is 4 byte aligned
  404. */
  405. if (data->blockSize % sizeof(uint32_t) != 0U)
  406. {
  407. data->blockSize +=
  408. sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
  409. }
  410. totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
  411. while ((error == kStatus_Success) && (transferredWords < totalWords))
  412. {
  413. while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_BufferReadReadyFlag | kSDHC_DataErrorFlag)))
  414. {
  415. }
  416. if (SDHC_GetInterruptStatusFlags(base) & kSDHC_DataErrorFlag)
  417. {
  418. if (!(data->enableIgnoreError))
  419. {
  420. error = kStatus_Fail;
  421. }
  422. }
  423. if (error == kStatus_Success)
  424. {
  425. transferredWords = SDHC_ReadDataPort(base, data, transferredWords);
  426. }
  427. /* clear buffer ready and error */
  428. SDHC_ClearInterruptStatusFlags(base, kSDHC_BufferReadReadyFlag | kSDHC_DataErrorFlag);
  429. }
  430. /* Clear data complete flag after the last read operation. */
  431. SDHC_ClearInterruptStatusFlags(base, kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag);
  432. return error;
  433. }
  434. static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords)
  435. {
  436. uint32_t i;
  437. uint32_t totalWords;
  438. uint32_t wordsCanBeWrote; /* Words can be wrote at this time. */
  439. uint32_t writeWatermark = ((base->WML & SDHC_WML_WRWML_MASK) >> SDHC_WML_WRWML_SHIFT);
  440. /*
  441. * Add non aligned access support ,user need make sure your buffer size is big
  442. * enough to hold the data,in other words,user need make sure the buffer size
  443. * is 4 byte aligned
  444. */
  445. if (data->blockSize % sizeof(uint32_t) != 0U)
  446. {
  447. data->blockSize +=
  448. sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
  449. }
  450. totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
  451. /* If watermark level is equal or bigger than totalWords, transfers totalWords data.*/
  452. if (writeWatermark >= totalWords)
  453. {
  454. wordsCanBeWrote = totalWords;
  455. }
  456. /* If watermark level is less than totalWords and left words to be sent is equal or bigger than watermark,
  457. transfers watermark level words. */
  458. else if ((writeWatermark < totalWords) && ((totalWords - transferredWords) >= writeWatermark))
  459. {
  460. wordsCanBeWrote = writeWatermark;
  461. }
  462. /* If watermark level is less than totalWords and left words to be sent is less than watermark, transfers left
  463. words. */
  464. else
  465. {
  466. wordsCanBeWrote = (totalWords - transferredWords);
  467. }
  468. i = 0U;
  469. while (i < wordsCanBeWrote)
  470. {
  471. SDHC_WriteData(base, data->txData[transferredWords++]);
  472. i++;
  473. }
  474. return transferredWords;
  475. }
  476. static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
  477. {
  478. uint32_t totalWords;
  479. uint32_t transferredWords = 0U;
  480. status_t error = kStatus_Success;
  481. /*
  482. * Add non aligned access support ,user need make sure your buffer size is big
  483. * enough to hold the data,in other words,user need make sure the buffer size
  484. * is 4 byte aligned
  485. */
  486. if (data->blockSize % sizeof(uint32_t) != 0U)
  487. {
  488. data->blockSize +=
  489. sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
  490. }
  491. totalWords = (data->blockCount * data->blockSize) / sizeof(uint32_t);
  492. while ((error == kStatus_Success) && (transferredWords < totalWords))
  493. {
  494. while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_BufferWriteReadyFlag | kSDHC_DataErrorFlag)))
  495. {
  496. }
  497. if (SDHC_GetInterruptStatusFlags(base) & kSDHC_DataErrorFlag)
  498. {
  499. if (!(data->enableIgnoreError))
  500. {
  501. error = kStatus_Fail;
  502. }
  503. }
  504. if (error == kStatus_Success)
  505. {
  506. transferredWords = SDHC_WriteDataPort(base, data, transferredWords);
  507. }
  508. /* Clear buffer enable flag to trigger transfer. Clear error flag when SDHC encounter error. */
  509. SDHC_ClearInterruptStatusFlags(base, (kSDHC_BufferWriteReadyFlag | kSDHC_DataErrorFlag));
  510. }
  511. /* Wait write data complete or data transfer error after the last writing operation. */
  512. while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag)))
  513. {
  514. }
  515. if (SDHC_GetInterruptStatusFlags(base) & kSDHC_DataErrorFlag)
  516. {
  517. if (!(data->enableIgnoreError))
  518. {
  519. error = kStatus_Fail;
  520. }
  521. }
  522. SDHC_ClearInterruptStatusFlags(base, (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag));
  523. return error;
  524. }
  525. static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *command)
  526. {
  527. status_t error = kStatus_Success;
  528. /* Wait command complete or SDHC encounters error. */
  529. while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_CommandCompleteFlag | kSDHC_CommandErrorFlag)))
  530. {
  531. }
  532. if (SDHC_GetInterruptStatusFlags(base) & kSDHC_CommandErrorFlag)
  533. {
  534. error = kStatus_Fail;
  535. }
  536. /* Receive response when command completes successfully. */
  537. if (error == kStatus_Success)
  538. {
  539. error = SDHC_ReceiveCommandResponse(base, command);
  540. }
  541. SDHC_ClearInterruptStatusFlags(base, (kSDHC_CommandCompleteFlag | kSDHC_CommandErrorFlag));
  542. return error;
  543. }
  544. static status_t SDHC_TransferByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
  545. {
  546. status_t error = kStatus_Success;
  547. if (data->rxData)
  548. {
  549. error = SDHC_ReadByDataPortBlocking(base, data);
  550. }
  551. else
  552. {
  553. error = SDHC_WriteByDataPortBlocking(base, data);
  554. }
  555. return error;
  556. }
  557. static status_t SDHC_TransferByAdma2Blocking(SDHC_Type *base, sdhc_data_t *data)
  558. {
  559. status_t error = kStatus_Success;
  560. /* Wait data complete or SDHC encounters error. */
  561. while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag)))
  562. {
  563. }
  564. if (SDHC_GetInterruptStatusFlags(base) & (kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag))
  565. {
  566. if (!(data->enableIgnoreError))
  567. {
  568. error = kStatus_Fail;
  569. }
  570. }
  571. SDHC_ClearInterruptStatusFlags(
  572. base, (kSDHC_DataCompleteFlag | kSDHC_DmaCompleteFlag | kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag));
  573. return error;
  574. }
  575. #if defined FSL_SDHC_ENABLE_ADMA1
  576. #define SDHC_TransferByAdma1Blocking(base, data) SDHC_TransferByAdma2Blocking(base, data)
  577. #endif /* FSL_SDHC_ENABLE_ADMA1 */
  578. static status_t SDHC_TransferDataBlocking(sdhc_dma_mode_t dmaMode, SDHC_Type *base, sdhc_data_t *data)
  579. {
  580. status_t error = kStatus_Success;
  581. switch (dmaMode)
  582. {
  583. case kSDHC_DmaModeNo:
  584. error = SDHC_TransferByDataPortBlocking(base, data);
  585. break;
  586. #if defined FSL_SDHC_ENABLE_ADMA1
  587. case kSDHC_DmaModeAdma1:
  588. error = SDHC_TransferByAdma1Blocking(base, data);
  589. break;
  590. #endif /* FSL_SDHC_ENABLE_ADMA1 */
  591. case kSDHC_DmaModeAdma2:
  592. error = SDHC_TransferByAdma2Blocking(base, data);
  593. break;
  594. default:
  595. error = kStatus_InvalidArgument;
  596. break;
  597. }
  598. return error;
  599. }
  600. static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interruptFlags)
  601. {
  602. if (interruptFlags & kSDHC_CardInsertionFlag)
  603. {
  604. if (handle->callback.CardInserted)
  605. {
  606. handle->callback.CardInserted();
  607. }
  608. }
  609. else
  610. {
  611. if (handle->callback.CardRemoved)
  612. {
  613. handle->callback.CardRemoved();
  614. }
  615. }
  616. }
  617. static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags)
  618. {
  619. assert(handle->command);
  620. if ((interruptFlags & kSDHC_CommandErrorFlag) && (!(handle->data)) && (handle->callback.TransferComplete))
  621. {
  622. handle->callback.TransferComplete(base, handle, kStatus_SDHC_SendCommandFailed, handle->userData);
  623. }
  624. else
  625. {
  626. /* Receive response */
  627. SDHC_ReceiveCommandResponse(base, handle->command);
  628. if ((!(handle->data)) && (handle->callback.TransferComplete))
  629. {
  630. handle->callback.TransferComplete(base, handle, kStatus_Success, handle->userData);
  631. }
  632. }
  633. }
  634. static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags)
  635. {
  636. assert(handle->data);
  637. if ((!(handle->data->enableIgnoreError)) && (interruptFlags & (kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag)) &&
  638. (handle->callback.TransferComplete))
  639. {
  640. handle->callback.TransferComplete(base, handle, kStatus_SDHC_TransferDataFailed, handle->userData);
  641. }
  642. else
  643. {
  644. if (interruptFlags & kSDHC_BufferReadReadyFlag)
  645. {
  646. handle->transferredWords = SDHC_ReadDataPort(base, handle->data, handle->transferredWords);
  647. }
  648. else if (interruptFlags & kSDHC_BufferWriteReadyFlag)
  649. {
  650. handle->transferredWords = SDHC_WriteDataPort(base, handle->data, handle->transferredWords);
  651. }
  652. else
  653. {
  654. }
  655. if ((interruptFlags & kSDHC_DataCompleteFlag) && (handle->callback.TransferComplete))
  656. {
  657. handle->callback.TransferComplete(base, handle, kStatus_Success, handle->userData);
  658. }
  659. else
  660. {
  661. /* Do nothing when DMA complete flag is set. Wait until data complete flag is set. */
  662. }
  663. }
  664. }
  665. static void SDHC_TransferHandleSdioInterrupt(sdhc_handle_t *handle)
  666. {
  667. if (handle->callback.SdioInterrupt)
  668. {
  669. handle->callback.SdioInterrupt();
  670. }
  671. }
  672. static void SDHC_TransferHandleSdioBlockGap(sdhc_handle_t *handle)
  673. {
  674. if (handle->callback.SdioBlockGap)
  675. {
  676. handle->callback.SdioBlockGap();
  677. }
  678. }
  679. void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config)
  680. {
  681. assert(config);
  682. #if !defined FSL_SDHC_ENABLE_ADMA1
  683. assert(config->dmaMode != kSDHC_DmaModeAdma1);
  684. #endif /* FSL_SDHC_ENABLE_ADMA1 */
  685. assert((config->writeWatermarkLevel >= 1U) && (config->writeWatermarkLevel <= 128U));
  686. assert((config->readWatermarkLevel >= 1U) && (config->readWatermarkLevel <= 128U));
  687. uint32_t proctl;
  688. uint32_t wml;
  689. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  690. /* Enable SDHC clock. */
  691. CLOCK_EnableClock(s_sdhcClock[SDHC_GetInstance(base)]);
  692. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  693. /* Reset SDHC. */
  694. SDHC_Reset(base, kSDHC_ResetAll, 100);
  695. proctl = base->PROCTL;
  696. wml = base->WML;
  697. proctl &= ~(SDHC_PROCTL_D3CD_MASK | SDHC_PROCTL_EMODE_MASK | SDHC_PROCTL_DMAS_MASK);
  698. /* Set DAT3 as card detection pin */
  699. if (config->cardDetectDat3)
  700. {
  701. proctl |= SDHC_PROCTL_D3CD_MASK;
  702. }
  703. /* Endian mode and DMA mode */
  704. proctl |= (SDHC_PROCTL_EMODE(config->endianMode) | SDHC_PROCTL_DMAS(config->dmaMode));
  705. /* Watermark level */
  706. wml &= ~(SDHC_WML_RDWML_MASK | SDHC_WML_WRWML_MASK);
  707. wml |= (SDHC_WML_RDWML(config->readWatermarkLevel) | SDHC_WML_WRWML(config->writeWatermarkLevel));
  708. base->WML = wml;
  709. base->PROCTL = proctl;
  710. /* Disable all clock auto gated off feature because of DAT0 line logic(card buffer full status) can't be updated
  711. correctly when clock auto gated off is enabled. */
  712. base->SYSCTL |= (SDHC_SYSCTL_PEREN_MASK | SDHC_SYSCTL_HCKEN_MASK | SDHC_SYSCTL_IPGEN_MASK);
  713. /* Enable interrupt status but doesn't enable interrupt signal. */
  714. SDHC_SetTransferInterrupt(base, false);
  715. }
  716. void SDHC_Deinit(SDHC_Type *base)
  717. {
  718. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  719. /* Disable clock. */
  720. CLOCK_DisableClock(s_sdhcClock[SDHC_GetInstance(base)]);
  721. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  722. }
  723. bool SDHC_Reset(SDHC_Type *base, uint32_t mask, uint32_t timeout)
  724. {
  725. base->SYSCTL |= (mask & (SDHC_SYSCTL_RSTA_MASK | SDHC_SYSCTL_RSTC_MASK | SDHC_SYSCTL_RSTD_MASK));
  726. /* Delay some time to wait reset success. */
  727. while ((base->SYSCTL & mask))
  728. {
  729. if (!timeout)
  730. {
  731. break;
  732. }
  733. timeout--;
  734. }
  735. return ((!timeout) ? false : true);
  736. }
  737. void SDHC_GetCapability(SDHC_Type *base, sdhc_capability_t *capability)
  738. {
  739. assert(capability);
  740. uint32_t htCapability;
  741. uint32_t hostVer;
  742. uint32_t maxBlockLength;
  743. hostVer = base->HOSTVER;
  744. htCapability = base->HTCAPBLT;
  745. /* Get the capability of SDHC. */
  746. capability->specVersion = ((hostVer & SDHC_HOSTVER_SVN_MASK) >> SDHC_HOSTVER_SVN_SHIFT);
  747. capability->vendorVersion = ((hostVer & SDHC_HOSTVER_VVN_MASK) >> SDHC_HOSTVER_VVN_SHIFT);
  748. maxBlockLength = ((htCapability & SDHC_HTCAPBLT_MBL_MASK) >> SDHC_HTCAPBLT_MBL_SHIFT);
  749. capability->maxBlockLength = (512U << maxBlockLength);
  750. /* Other attributes not in HTCAPBLT register. */
  751. capability->maxBlockCount = SDHC_MAX_BLOCK_COUNT;
  752. capability->flags = (htCapability & (kSDHC_SupportAdmaFlag | kSDHC_SupportHighSpeedFlag | kSDHC_SupportDmaFlag |
  753. kSDHC_SupportSuspendResumeFlag | kSDHC_SupportV330Flag));
  754. #if defined FSL_FEATURE_SDHC_HAS_V300_SUPPORT && FSL_FEATURE_SDHC_HAS_V300_SUPPORT
  755. capability->flags |= (htCapability & kSDHC_SupportV300Flag);
  756. #endif
  757. #if defined FSL_FEATURE_SDHC_HAS_V180_SUPPORT && FSL_FEATURE_SDHC_HAS_V180_SUPPORT
  758. capability->flags |= (htCapability & kSDHC_SupportV180Flag);
  759. #endif
  760. /* eSDHC on all kinetis boards will support 4/8 bit data bus width. */
  761. capability->flags |= (kSDHC_Support4BitFlag | kSDHC_Support8BitFlag);
  762. }
  763. uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz)
  764. {
  765. assert(srcClock_Hz != 0U);
  766. assert((busClock_Hz != 0U) && (busClock_Hz <= srcClock_Hz));
  767. uint32_t totalDiv = 0U;
  768. uint32_t divisor = 0U;
  769. uint32_t prescaler = 0U;
  770. uint32_t sysctl = 0U;
  771. uint32_t nearestFrequency = 0U;
  772. /* calucate total divisor first */
  773. totalDiv = srcClock_Hz / busClock_Hz;
  774. if (totalDiv != 0U)
  775. {
  776. /* calucate the divisor (srcClock_Hz / divisor) <= busClock_Hz */
  777. if ((srcClock_Hz / totalDiv) > busClock_Hz)
  778. {
  779. totalDiv++;
  780. }
  781. /* divide the total divisor to div and prescaler */
  782. if (totalDiv > SDHC_MAX_DVS)
  783. {
  784. prescaler = totalDiv / SDHC_MAX_DVS;
  785. /* prescaler must be a value which equal 2^n and smaller than SDHC_MAX_CLKFS */
  786. while (((SDHC_MAX_CLKFS % prescaler) != 0U) || (prescaler == 1U))
  787. {
  788. prescaler++;
  789. }
  790. /* calucate the divisor */
  791. divisor = totalDiv / prescaler;
  792. /* fine tuning the divisor until divisor * prescaler >= totalDiv */
  793. while ((divisor * prescaler) < totalDiv)
  794. {
  795. divisor++;
  796. }
  797. nearestFrequency = srcClock_Hz / divisor / prescaler;
  798. }
  799. else
  800. {
  801. divisor = totalDiv;
  802. prescaler = 0U;
  803. nearestFrequency = srcClock_Hz / divisor;
  804. }
  805. }
  806. /* in this condition , srcClock_Hz = busClock_Hz, */
  807. else
  808. {
  809. /* total divider = 1U */
  810. divisor = 0U;
  811. prescaler = 0U;
  812. nearestFrequency = srcClock_Hz;
  813. }
  814. /* calucate the value write to register */
  815. if (divisor != 0U)
  816. {
  817. SDHC_PREV_DVS(divisor);
  818. }
  819. /* calucate the value write to register */
  820. if (prescaler != 0U)
  821. {
  822. SDHC_PREV_CLKFS(prescaler);
  823. }
  824. /* Disable SD clock. It should be disabled before changing the SD clock frequency.*/
  825. base->SYSCTL &= ~SDHC_SYSCTL_SDCLKEN_MASK;
  826. /* Set the SD clock frequency divisor, SD clock frequency select, data timeout counter value. */
  827. sysctl = base->SYSCTL;
  828. sysctl &= ~(SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK | SDHC_SYSCTL_DTOCV_MASK);
  829. sysctl |= (SDHC_SYSCTL_DVS(divisor) | SDHC_SYSCTL_SDCLKFS(prescaler) | SDHC_SYSCTL_DTOCV(0xEU));
  830. base->SYSCTL = sysctl;
  831. /* Wait until the SD clock is stable. */
  832. while (!(base->PRSSTAT & SDHC_PRSSTAT_SDSTB_MASK))
  833. {
  834. }
  835. /* Enable the SD clock. */
  836. base->SYSCTL |= SDHC_SYSCTL_SDCLKEN_MASK;
  837. return nearestFrequency;
  838. }
  839. bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout)
  840. {
  841. base->SYSCTL |= SDHC_SYSCTL_INITA_MASK;
  842. /* Delay some time to wait card become active state. */
  843. while (base->SYSCTL & SDHC_SYSCTL_INITA_MASK)
  844. {
  845. if (!timeout)
  846. {
  847. break;
  848. }
  849. timeout--;
  850. }
  851. return ((!timeout) ? false : true);
  852. }
  853. void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config)
  854. {
  855. assert(config);
  856. assert(config->dataBlockSize <= (SDHC_BLKATTR_BLKSIZE_MASK >> SDHC_BLKATTR_BLKSIZE_SHIFT));
  857. assert(config->dataBlockCount <= (SDHC_BLKATTR_BLKCNT_MASK >> SDHC_BLKATTR_BLKCNT_SHIFT));
  858. base->BLKATTR = ((base->BLKATTR & ~(SDHC_BLKATTR_BLKSIZE_MASK | SDHC_BLKATTR_BLKCNT_MASK)) |
  859. (SDHC_BLKATTR_BLKSIZE(config->dataBlockSize) | SDHC_BLKATTR_BLKCNT(config->dataBlockCount)));
  860. base->CMDARG = config->commandArgument;
  861. base->XFERTYP = (((config->commandIndex << SDHC_XFERTYP_CMDINX_SHIFT) & SDHC_XFERTYP_CMDINX_MASK) |
  862. (config->flags & (SDHC_XFERTYP_DMAEN_MASK | SDHC_XFERTYP_MSBSEL_MASK | SDHC_XFERTYP_DPSEL_MASK |
  863. SDHC_XFERTYP_CMDTYP_MASK | SDHC_XFERTYP_BCEN_MASK | SDHC_XFERTYP_CICEN_MASK |
  864. SDHC_XFERTYP_CCCEN_MASK | SDHC_XFERTYP_RSPTYP_MASK | SDHC_XFERTYP_DTDSEL_MASK |
  865. SDHC_XFERTYP_AC12EN_MASK)));
  866. }
  867. void SDHC_EnableSdioControl(SDHC_Type *base, uint32_t mask, bool enable)
  868. {
  869. uint32_t proctl = base->PROCTL;
  870. uint32_t vendor = base->VENDOR;
  871. if (enable)
  872. {
  873. if (mask & kSDHC_StopAtBlockGapFlag)
  874. {
  875. proctl |= SDHC_PROCTL_SABGREQ_MASK;
  876. }
  877. if (mask & kSDHC_ReadWaitControlFlag)
  878. {
  879. proctl |= SDHC_PROCTL_RWCTL_MASK;
  880. }
  881. if (mask & kSDHC_InterruptAtBlockGapFlag)
  882. {
  883. proctl |= SDHC_PROCTL_IABG_MASK;
  884. }
  885. if (mask & kSDHC_ExactBlockNumberReadFlag)
  886. {
  887. vendor |= SDHC_VENDOR_EXBLKNU_MASK;
  888. }
  889. }
  890. else
  891. {
  892. if (mask & kSDHC_StopAtBlockGapFlag)
  893. {
  894. proctl &= ~SDHC_PROCTL_SABGREQ_MASK;
  895. }
  896. if (mask & kSDHC_ReadWaitControlFlag)
  897. {
  898. proctl &= ~SDHC_PROCTL_RWCTL_MASK;
  899. }
  900. if (mask & kSDHC_InterruptAtBlockGapFlag)
  901. {
  902. proctl &= ~SDHC_PROCTL_IABG_MASK;
  903. }
  904. if (mask & kSDHC_ExactBlockNumberReadFlag)
  905. {
  906. vendor &= ~SDHC_VENDOR_EXBLKNU_MASK;
  907. }
  908. }
  909. base->PROCTL = proctl;
  910. base->VENDOR = vendor;
  911. }
  912. void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config)
  913. {
  914. assert(config);
  915. assert(config->ackTimeoutCount <= (SDHC_MMCBOOT_DTOCVACK_MASK >> SDHC_MMCBOOT_DTOCVACK_SHIFT));
  916. assert(config->blockCount <= (SDHC_MMCBOOT_BOOTBLKCNT_MASK >> SDHC_MMCBOOT_BOOTBLKCNT_SHIFT));
  917. uint32_t mmcboot = 0U;
  918. mmcboot = (SDHC_MMCBOOT_DTOCVACK(config->ackTimeoutCount) | SDHC_MMCBOOT_BOOTMODE(config->bootMode) |
  919. SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount));
  920. if (config->enableBootAck)
  921. {
  922. mmcboot |= SDHC_MMCBOOT_BOOTACK_MASK;
  923. }
  924. if (config->enableBoot)
  925. {
  926. mmcboot |= SDHC_MMCBOOT_BOOTEN_MASK;
  927. }
  928. if (config->enableAutoStopAtBlockGap)
  929. {
  930. mmcboot |= SDHC_MMCBOOT_AUTOSABGEN_MASK;
  931. }
  932. base->MMCBOOT = mmcboot;
  933. }
  934. status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
  935. sdhc_dma_mode_t dmaMode,
  936. uint32_t *table,
  937. uint32_t tableWords,
  938. const uint32_t *data,
  939. uint32_t dataBytes)
  940. {
  941. status_t error = kStatus_Success;
  942. const uint32_t *startAddress = data;
  943. uint32_t entries;
  944. uint32_t i;
  945. #if defined FSL_SDHC_ENABLE_ADMA1
  946. sdhc_adma1_descriptor_t *adma1EntryAddress;
  947. #endif
  948. sdhc_adma2_descriptor_t *adma2EntryAddress;
  949. if ((((!table) || (!tableWords)) && ((dmaMode == kSDHC_DmaModeAdma1) || (dmaMode == kSDHC_DmaModeAdma2))) ||
  950. (!data) || (!dataBytes)
  951. #if !defined FSL_SDHC_ENABLE_ADMA1
  952. || (dmaMode == kSDHC_DmaModeAdma1)
  953. #endif
  954. )
  955. {
  956. error = kStatus_InvalidArgument;
  957. }
  958. else if (((dmaMode == kSDHC_DmaModeAdma2) && (((uint32_t)startAddress % SDHC_ADMA2_LENGTH_ALIGN) != 0U))
  959. #if defined FSL_SDHC_ENABLE_ADMA1
  960. || ((dmaMode == kSDHC_DmaModeAdma1) && (((uint32_t)startAddress % SDHC_ADMA1_LENGTH_ALIGN) != 0U))
  961. #endif
  962. )
  963. {
  964. error = kStatus_SDHC_DMADataBufferAddrNotAlign;
  965. }
  966. else
  967. {
  968. switch (dmaMode)
  969. {
  970. case kSDHC_DmaModeNo:
  971. break;
  972. #if defined FSL_SDHC_ENABLE_ADMA1
  973. case kSDHC_DmaModeAdma1:
  974. /*
  975. * Add non aligned access support ,user need make sure your buffer size is big
  976. * enough to hold the data,in other words,user need make sure the buffer size
  977. * is 4 byte aligned
  978. */
  979. if (dataBytes % sizeof(uint32_t) != 0U)
  980. {
  981. dataBytes +=
  982. sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */
  983. }
  984. /* Check if ADMA descriptor's number is enough. */
  985. entries = ((dataBytes / SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U);
  986. /* ADMA1 needs two descriptors to finish a transfer */
  987. entries <<= 1U;
  988. if (entries > ((tableWords * sizeof(uint32_t)) / sizeof(sdhc_adma1_descriptor_t)))
  989. {
  990. error = kStatus_OutOfRange;
  991. }
  992. else
  993. {
  994. adma1EntryAddress = (sdhc_adma1_descriptor_t *)(table);
  995. for (i = 0U; i < entries; i += 2U)
  996. {
  997. /* Each descriptor for ADMA1 is 32-bit in length */
  998. if ((dataBytes - sizeof(uint32_t) * (startAddress - data)) <=
  999. SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY)
  1000. {
  1001. /* The last piece of data, setting end flag in descriptor */
  1002. adma1EntryAddress[i] = ((uint32_t)(dataBytes - sizeof(uint32_t) * (startAddress - data))
  1003. << SDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT);
  1004. adma1EntryAddress[i] |= kSDHC_Adma1DescriptorTypeSetLength;
  1005. adma1EntryAddress[i + 1U] =
  1006. ((uint32_t)(startAddress) << SDHC_ADMA1_DESCRIPTOR_ADDRESS_SHIFT);
  1007. adma1EntryAddress[i + 1U] |=
  1008. (kSDHC_Adma1DescriptorTypeTransfer | kSDHC_Adma1DescriptorEndFlag);
  1009. }
  1010. else
  1011. {
  1012. adma1EntryAddress[i] = ((uint32_t)SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY
  1013. << SDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT);
  1014. adma1EntryAddress[i] |= kSDHC_Adma1DescriptorTypeSetLength;
  1015. adma1EntryAddress[i + 1U] =
  1016. ((uint32_t)(startAddress) << SDHC_ADMA1_DESCRIPTOR_ADDRESS_SHIFT);
  1017. adma1EntryAddress[i + 1U] |= kSDHC_Adma1DescriptorTypeTransfer;
  1018. startAddress += SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY / sizeof(uint32_t);
  1019. }
  1020. }
  1021. /* When use ADMA, disable simple DMA */
  1022. base->DSADDR = 0U;
  1023. base->ADSADDR = (uint32_t)table;
  1024. /* disable the buffer ready flag in DMA mode */
  1025. SDHC_DisableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
  1026. SDHC_DisableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
  1027. }
  1028. break;
  1029. #endif /* FSL_SDHC_ENABLE_ADMA1 */
  1030. case kSDHC_DmaModeAdma2:
  1031. /*
  1032. * Add non aligned access support ,user need make sure your buffer size is big
  1033. * enough to hold the data,in other words,user need make sure the buffer size
  1034. * is 4 byte aligned
  1035. */
  1036. if (dataBytes % sizeof(uint32_t) != 0U)
  1037. {
  1038. dataBytes +=
  1039. sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */
  1040. }
  1041. /* Check if ADMA descriptor's number is enough. */
  1042. entries = ((dataBytes / SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U);
  1043. if (entries > ((tableWords * sizeof(uint32_t)) / sizeof(sdhc_adma2_descriptor_t)))
  1044. {
  1045. error = kStatus_OutOfRange;
  1046. }
  1047. else
  1048. {
  1049. adma2EntryAddress = (sdhc_adma2_descriptor_t *)(table);
  1050. for (i = 0U; i < entries; i++)
  1051. {
  1052. /* Each descriptor for ADMA2 is 64-bit in length */
  1053. if ((dataBytes - sizeof(uint32_t) * (startAddress - data)) <=
  1054. SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY)
  1055. {
  1056. /* The last piece of data, setting end flag in descriptor */
  1057. adma2EntryAddress[i].address = startAddress;
  1058. adma2EntryAddress[i].attribute = ((dataBytes - sizeof(uint32_t) * (startAddress - data))
  1059. << SDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT);
  1060. adma2EntryAddress[i].attribute |=
  1061. (kSDHC_Adma2DescriptorTypeTransfer | kSDHC_Adma2DescriptorEndFlag);
  1062. }
  1063. else
  1064. {
  1065. adma2EntryAddress[i].address = startAddress;
  1066. adma2EntryAddress[i].attribute =
  1067. (((SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY / sizeof(uint32_t)) * sizeof(uint32_t))
  1068. << SDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT);
  1069. adma2EntryAddress[i].attribute |= kSDHC_Adma2DescriptorTypeTransfer;
  1070. startAddress += (SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY / sizeof(uint32_t));
  1071. }
  1072. }
  1073. /* When use ADMA, disable simple DMA */
  1074. base->DSADDR = 0U;
  1075. base->ADSADDR = (uint32_t)table;
  1076. /* disable the buffer read flag in DMA mode */
  1077. SDHC_DisableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
  1078. SDHC_DisableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
  1079. }
  1080. break;
  1081. default:
  1082. break;
  1083. }
  1084. }
  1085. return error;
  1086. }
  1087. status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer)
  1088. {
  1089. assert(transfer);
  1090. status_t error = kStatus_Success;
  1091. sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT);
  1092. sdhc_command_t *command = transfer->command;
  1093. sdhc_data_t *data = transfer->data;
  1094. /* make sure the cmd/block count is valid */
  1095. if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT)))
  1096. {
  1097. return kStatus_InvalidArgument;
  1098. }
  1099. /* Wait until command/data bus out of busy status. */
  1100. while (SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag)
  1101. {
  1102. }
  1103. while (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag))
  1104. {
  1105. }
  1106. /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/
  1107. if (data && (NULL != admaTable))
  1108. {
  1109. error =
  1110. SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords,
  1111. (data->rxData ? data->rxData : data->txData), (data->blockCount * data->blockSize));
  1112. /* in this situation , we disable the DMA instead of polling transfer mode */
  1113. if (error == kStatus_SDHC_DMADataBufferAddrNotAlign)
  1114. {
  1115. dmaMode = kSDHC_DmaModeNo;
  1116. SDHC_EnableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
  1117. }
  1118. else if (error != kStatus_Success)
  1119. {
  1120. return error;
  1121. }
  1122. else
  1123. {
  1124. }
  1125. }
  1126. /* Send command and receive data. */
  1127. SDHC_StartTransfer(base, command, data, dmaMode);
  1128. if (kStatus_Success != SDHC_SendCommandBlocking(base, command))
  1129. {
  1130. return kStatus_SDHC_SendCommandFailed;
  1131. }
  1132. else if (data && (kStatus_Success != SDHC_TransferDataBlocking(dmaMode, base, data)))
  1133. {
  1134. return kStatus_SDHC_TransferDataFailed;
  1135. }
  1136. else
  1137. {
  1138. }
  1139. return kStatus_Success;
  1140. }
  1141. void SDHC_TransferCreateHandle(SDHC_Type *base,
  1142. sdhc_handle_t *handle,
  1143. const sdhc_transfer_callback_t *callback,
  1144. void *userData)
  1145. {
  1146. assert(handle);
  1147. assert(callback);
  1148. /* Zero the handle. */
  1149. memset(handle, 0, sizeof(*handle));
  1150. /* Set the callback. */
  1151. handle->callback.CardInserted = callback->CardInserted;
  1152. handle->callback.CardRemoved = callback->CardRemoved;
  1153. handle->callback.SdioInterrupt = callback->SdioInterrupt;
  1154. handle->callback.SdioBlockGap = callback->SdioBlockGap;
  1155. handle->callback.TransferComplete = callback->TransferComplete;
  1156. handle->userData = userData;
  1157. /* Save the handle in global variables to support the double weak mechanism. */
  1158. s_sdhcHandle[SDHC_GetInstance(base)] = handle;
  1159. /* Enable interrupt in NVIC. */
  1160. SDHC_SetTransferInterrupt(base, true);
  1161. /* save IRQ handler */
  1162. s_sdhcIsr = SDHC_TransferHandleIRQ;
  1163. EnableIRQ(s_sdhcIRQ[SDHC_GetInstance(base)]);
  1164. }
  1165. status_t SDHC_TransferNonBlocking(
  1166. SDHC_Type *base, sdhc_handle_t *handle, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer)
  1167. {
  1168. assert(transfer);
  1169. sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT);
  1170. status_t error = kStatus_Success;
  1171. sdhc_command_t *command = transfer->command;
  1172. sdhc_data_t *data = transfer->data;
  1173. /* make sure cmd/block count is valid */
  1174. if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT)))
  1175. {
  1176. return kStatus_InvalidArgument;
  1177. }
  1178. /* Wait until command/data bus out of busy status. */
  1179. if ((SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) ||
  1180. (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag)))
  1181. {
  1182. return kStatus_SDHC_BusyTransferring;
  1183. }
  1184. /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/
  1185. if (data && (NULL != admaTable))
  1186. {
  1187. error =
  1188. SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords,
  1189. (data->rxData ? data->rxData : data->txData), (data->blockCount * data->blockSize));
  1190. /* in this situation , we disable the DMA instead of polling transfer mode */
  1191. if (error == kStatus_SDHC_DMADataBufferAddrNotAlign)
  1192. {
  1193. /* change to polling mode */
  1194. dmaMode = kSDHC_DmaModeNo;
  1195. SDHC_EnableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
  1196. SDHC_EnableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
  1197. }
  1198. else if (error != kStatus_Success)
  1199. {
  1200. return error;
  1201. }
  1202. else
  1203. {
  1204. }
  1205. }
  1206. /* Save command and data into handle before transferring. */
  1207. handle->command = command;
  1208. handle->data = data;
  1209. handle->interruptFlags = 0U;
  1210. /* transferredWords will only be updated in ISR when transfer way is DATAPORT. */
  1211. handle->transferredWords = 0U;
  1212. SDHC_StartTransfer(base, command, data, dmaMode);
  1213. return kStatus_Success;
  1214. }
  1215. void SDHC_TransferHandleIRQ(SDHC_Type *base, sdhc_handle_t *handle)
  1216. {
  1217. assert(handle);
  1218. uint32_t interruptFlags;
  1219. interruptFlags = SDHC_GetInterruptStatusFlags(base);
  1220. handle->interruptFlags = interruptFlags;
  1221. if (interruptFlags & kSDHC_CardDetectFlag)
  1222. {
  1223. SDHC_TransferHandleCardDetect(handle, (interruptFlags & kSDHC_CardDetectFlag));
  1224. }
  1225. if (interruptFlags & kSDHC_CommandFlag)
  1226. {
  1227. SDHC_TransferHandleCommand(base, handle, (interruptFlags & kSDHC_CommandFlag));
  1228. }
  1229. if (interruptFlags & kSDHC_DataFlag)
  1230. {
  1231. SDHC_TransferHandleData(base, handle, (interruptFlags & kSDHC_DataFlag));
  1232. }
  1233. if (interruptFlags & kSDHC_CardInterruptFlag)
  1234. {
  1235. SDHC_TransferHandleSdioInterrupt(handle);
  1236. }
  1237. if (interruptFlags & kSDHC_BlockGapEventFlag)
  1238. {
  1239. SDHC_TransferHandleSdioBlockGap(handle);
  1240. }
  1241. SDHC_ClearInterruptStatusFlags(base, interruptFlags);
  1242. }
  1243. #if defined(SDHC)
  1244. void SDHC_DriverIRQHandler(void)
  1245. {
  1246. assert(s_sdhcHandle[0]);
  1247. s_sdhcIsr(SDHC, s_sdhcHandle[0]);
  1248. }
  1249. #endif