fsl_sdhc.c 50 KB

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