drv_sdio.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2017-10-10 Tanek first version
  9. * 2021-07-07 linzhenxing add sd card drivers in mmu
  10. * 2021-07-14 linzhenxing add emmc
  11. */
  12. #include <rtthread.h>
  13. #include <rthw.h>
  14. #include <drivers/mmcsd_core.h>
  15. #include <ioremap.h>
  16. #include <board.h>
  17. #include <fsl_usdhc.h>
  18. #include <fsl_gpio.h>
  19. #include <fsl_iomuxc.h>
  20. #include <ioremap.h>
  21. #include <string.h>
  22. #define DBG_TAG "drv_sdio"
  23. #ifdef RT_SDIO_DEBUG
  24. #define DBG_LVL DBG_LOG
  25. #else
  26. #define DBG_LVL DBG_INFO
  27. #endif /* RT_SDIO_DEBUG */
  28. #include <rtdbg.h>
  29. #define CACHE_LINESIZE (32)
  30. #define USDHC_ADMA_TABLE_WORDS (8U) /* define the ADMA descriptor table length */
  31. #define USDHC_ADMA2_ADDR_ALIGN (4U) /* define the ADMA2 descriptor table addr align size */
  32. #define IMXRT_MAX_FREQ (52UL * 1000UL * 1000UL)
  33. #define USDHC_ADMA_TABLE_WORDS (8U) /* define the ADMA descriptor table length */
  34. #define USDHC_ADMA2_ADDR_ALIGN (4U) /* define the ADMA2 descriptor table addr align size */
  35. #define USDHC_READ_BURST_LEN (8U) /*!< number of words USDHC read in a single burst */
  36. #define USDHC_WRITE_BURST_LEN (8U) /*!< number of words USDHC write in a single burst */
  37. #define USDHC_DATA_TIMEOUT (0xFU) /*!< data timeout counter value */
  38. /* Read/write watermark level. The bigger value indicates DMA has higher read/write performance. */
  39. #define USDHC_READ_WATERMARK_LEVEL (0x80U)
  40. #define USDHC_WRITE_WATERMARK_LEVEL (0x80U)
  41. /* DMA mode */
  42. #define USDHC_DMA_MODE kUSDHC_DmaModeAdma2
  43. /* Endian mode. */
  44. #define USDHC_ENDIAN_MODE kUSDHC_EndianModeLittle
  45. static uint32_t g_usdhcAdma2Table[USDHC_ADMA_TABLE_WORDS];
  46. struct rt_mmcsd_host *host1;
  47. struct rt_mmcsd_host *host2;
  48. static rt_mutex_t mmcsd_mutex = RT_NULL;
  49. void host_change(void);
  50. struct imxrt_mmcsd
  51. {
  52. struct rt_mmcsd_host *host;
  53. struct rt_mmcsd_req *req;
  54. struct rt_mmcsd_cmd *cmd;
  55. struct rt_timer timer;
  56. rt_uint32_t *buf;
  57. usdhc_host_t usdhc_host;
  58. clock_div_t usdhc_div;
  59. clock_ip_name_t ip_clock;
  60. uint32_t *usdhc_adma2_table;
  61. };
  62. /*! @name Configuration */
  63. /*@{*/
  64. /*!
  65. * @brief Sets the IOMUXC pin mux mode.
  66. * @note The first five parameters can be filled with the pin function ID macros.
  67. *
  68. * This is an example to set the ENET1_RX_DATA0 Pad as FLEXCAN1_TX:
  69. * @code
  70. * IOMUXC_SetPinMux(IOMUXC_ENET1_RX_DATA0_FLEXCAN1_TX, 0);
  71. * @endcode
  72. *
  73. * This is an example to set the GPIO1_IO02 Pad as I2C1_SCL:
  74. * @code
  75. * IOMUXC_SetPinMux(IOMUXC_GPIO1_IO02_I2C1_SCL, 0);
  76. * @endcode
  77. *
  78. * @param muxRegister The pin mux register.
  79. * @param muxMode The pin mux mode.
  80. * @param inputRegister The select input register.
  81. * @param inputDaisy The input daisy.
  82. * @param configRegister The config register.
  83. * @param inputOnfield Software input on field.
  84. */
  85. static inline void _IOMUXC_SetPinMux(uint32_t muxRegister,
  86. uint32_t muxMode,
  87. uint32_t inputRegister,
  88. uint32_t inputDaisy,
  89. uint32_t configRegister,
  90. uint32_t inputOnfield)
  91. {
  92. *((volatile uint32_t *)rt_ioremap((void*)muxRegister, 0x4)) =
  93. IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) | IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield);
  94. if (inputRegister)
  95. {
  96. *((volatile uint32_t *)rt_ioremap((void*)inputRegister, 0x4)) = IOMUXC_SELECT_INPUT_DAISY(inputDaisy);
  97. }
  98. }
  99. /*!
  100. * @brief Sets the IOMUXC pin configuration.
  101. * @note The previous five parameters can be filled with the pin function ID macros.
  102. *
  103. * This is an example to set pin configuration for IOMUXC_GPIO1_IO02_I2C1_SCL:
  104. * @code
  105. * IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO02_I2C1_SCL, IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(2U));
  106. * @endcode
  107. *
  108. * @param muxRegister The pin mux register.
  109. * @param muxMode The pin mux mode.
  110. * @param inputRegister The select input register.
  111. * @param inputDaisy The input daisy.
  112. * @param configRegister The config register.
  113. * @param configValue The pin config value.
  114. */
  115. static inline void _IOMUXC_SetPinConfig(uint32_t muxRegister,
  116. uint32_t muxMode,
  117. uint32_t inputRegister,
  118. uint32_t inputDaisy,
  119. uint32_t configRegister,
  120. uint32_t configValue)
  121. {
  122. if (configRegister)
  123. {
  124. *((volatile uint32_t *)rt_ioremap((void*)configRegister, 0x4)) = configValue;
  125. }
  126. }
  127. static void _mmcsd_gpio_init(struct imxrt_mmcsd *mmcsd)
  128. {
  129. CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */
  130. #ifdef RT_USING_SDIO1
  131. /* uSDHC1 pins start*/
  132. _IOMUXC_SetPinMux(IOMUXC_UART1_RTS_B_USDHC1_CD_B, 0U);
  133. _IOMUXC_SetPinConfig(IOMUXC_UART1_RTS_B_USDHC1_CD_B,
  134. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  135. IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
  136. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  137. _IOMUXC_SetPinMux(IOMUXC_SD1_CLK_USDHC1_CLK, 0U);
  138. _IOMUXC_SetPinConfig(IOMUXC_SD1_CLK_USDHC1_CLK,
  139. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  140. IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
  141. IOMUXC_SW_PAD_CTL_PAD_SPEED(1U) |
  142. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  143. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  144. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  145. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  146. _IOMUXC_SetPinMux(IOMUXC_SD1_CMD_USDHC1_CMD, 0U);
  147. _IOMUXC_SetPinConfig(IOMUXC_SD1_CMD_USDHC1_CMD,
  148. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  149. IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
  150. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  151. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  152. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  153. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  154. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  155. _IOMUXC_SetPinMux(IOMUXC_SD1_DATA0_USDHC1_DATA0, 0U);
  156. _IOMUXC_SetPinConfig(IOMUXC_SD1_DATA0_USDHC1_DATA0,
  157. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  158. IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
  159. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  160. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  161. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  162. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  163. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  164. _IOMUXC_SetPinMux(IOMUXC_SD1_DATA1_USDHC1_DATA1, 0U);
  165. _IOMUXC_SetPinConfig(IOMUXC_SD1_DATA1_USDHC1_DATA1,
  166. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  167. IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
  168. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  169. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  170. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  171. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  172. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  173. _IOMUXC_SetPinMux(IOMUXC_SD1_DATA2_USDHC1_DATA2, 0U);
  174. _IOMUXC_SetPinConfig(IOMUXC_SD1_DATA2_USDHC1_DATA2,
  175. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  176. IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
  177. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  178. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  179. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  180. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  181. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  182. _IOMUXC_SetPinMux(IOMUXC_SD1_DATA3_USDHC1_DATA3, 0U);
  183. _IOMUXC_SetPinConfig(IOMUXC_SD1_DATA3_USDHC1_DATA3,
  184. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  185. IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
  186. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  187. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  188. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  189. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  190. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  191. /* uSDHC1 pins end*/
  192. #endif
  193. #ifdef RT_USING_SDIO2
  194. /* uSDHC2 pins start*/
  195. _IOMUXC_SetPinMux(IOMUXC_NAND_WE_B_USDHC2_CMD, 0U);
  196. _IOMUXC_SetPinConfig(IOMUXC_NAND_WE_B_USDHC2_CMD,
  197. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  198. IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
  199. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  200. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  201. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  202. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  203. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  204. _IOMUXC_SetPinMux(IOMUXC_NAND_RE_B_USDHC2_CLK, 0U);
  205. _IOMUXC_SetPinConfig(IOMUXC_NAND_RE_B_USDHC2_CLK,
  206. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  207. IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
  208. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  209. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  210. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  211. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  212. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  213. _IOMUXC_SetPinMux(IOMUXC_NAND_ALE_USDHC2_RESET_B, 0U);
  214. _IOMUXC_SetPinConfig(IOMUXC_NAND_ALE_USDHC2_RESET_B,
  215. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  216. IOMUXC_SW_PAD_CTL_PAD_DSE(1U) |
  217. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  218. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  219. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  220. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  221. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  222. _IOMUXC_SetPinMux(IOMUXC_NAND_DATA00_USDHC2_DATA0, 0U);
  223. _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA00_USDHC2_DATA0,
  224. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  225. IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
  226. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  227. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  228. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  229. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  230. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  231. _IOMUXC_SetPinMux(IOMUXC_NAND_DATA01_USDHC2_DATA1, 0U);
  232. _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA01_USDHC2_DATA1,
  233. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  234. IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
  235. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  236. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  237. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  238. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  239. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  240. _IOMUXC_SetPinMux(IOMUXC_NAND_DATA02_USDHC2_DATA2, 0U);
  241. _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA02_USDHC2_DATA2,
  242. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  243. IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
  244. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  245. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  246. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  247. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  248. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  249. _IOMUXC_SetPinMux(IOMUXC_NAND_DATA03_USDHC2_DATA3, 0U);
  250. _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA03_USDHC2_DATA3,
  251. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  252. IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
  253. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  254. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  255. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  256. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  257. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  258. _IOMUXC_SetPinMux(IOMUXC_NAND_DATA04_USDHC2_DATA4, 0U);
  259. _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA04_USDHC2_DATA4,
  260. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  261. IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
  262. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  263. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  264. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  265. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  266. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  267. _IOMUXC_SetPinMux(IOMUXC_NAND_DATA05_USDHC2_DATA5, 0U);
  268. _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA05_USDHC2_DATA5,
  269. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  270. IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
  271. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  272. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  273. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  274. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  275. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  276. _IOMUXC_SetPinMux(IOMUXC_NAND_DATA06_USDHC2_DATA6, 0U);
  277. _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA06_USDHC2_DATA6,
  278. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  279. IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
  280. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  281. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  282. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  283. IOMUXC_SW_PAD_CTL_PAD_PUS(7U) |
  284. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  285. _IOMUXC_SetPinMux(IOMUXC_NAND_DATA07_USDHC2_DATA7, 0U);
  286. _IOMUXC_SetPinConfig(IOMUXC_NAND_DATA07_USDHC2_DATA7,
  287. IOMUXC_SW_PAD_CTL_PAD_SRE_MASK |
  288. IOMUXC_SW_PAD_CTL_PAD_DSE(7U) |
  289. IOMUXC_SW_PAD_CTL_PAD_SPEED(2U) |
  290. IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
  291. IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
  292. IOMUXC_SW_PAD_CTL_PAD_PUS(1U) |
  293. IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
  294. /* uSDHC2 pins end*/
  295. #endif
  296. }
  297. static void SDMMCHOST_ErrorRecovery(USDHC_Type *base)
  298. {
  299. uint32_t status = 0U;
  300. /* get host present status */
  301. status = USDHC_GetPresentStatusFlags(base);
  302. /* check command inhibit status flag */
  303. if ((status & kUSDHC_CommandInhibitFlag) != 0U)
  304. {
  305. /* reset command line */
  306. USDHC_Reset(base, kUSDHC_ResetCommand, 1000U);
  307. }
  308. /* check data inhibit status flag */
  309. if ((status & kUSDHC_DataInhibitFlag) != 0U)
  310. {
  311. /* reset data line */
  312. USDHC_Reset(base, kUSDHC_ResetData, 1000U);
  313. }
  314. }
  315. static void _mmcsd_host_init(struct imxrt_mmcsd *mmcsd)
  316. {
  317. usdhc_host_t *usdhc_host = &mmcsd->usdhc_host;
  318. /* Initializes SDHC. */
  319. usdhc_host->config.dataTimeout = USDHC_DATA_TIMEOUT;
  320. usdhc_host->config.endianMode = USDHC_ENDIAN_MODE;
  321. usdhc_host->config.readWatermarkLevel = USDHC_READ_WATERMARK_LEVEL;
  322. usdhc_host->config.writeWatermarkLevel = USDHC_WRITE_WATERMARK_LEVEL;
  323. usdhc_host->config.readBurstLen = USDHC_READ_BURST_LEN;
  324. usdhc_host->config.writeBurstLen = USDHC_WRITE_BURST_LEN;
  325. USDHC_Init(usdhc_host->base, &(usdhc_host->config));
  326. }
  327. static void _mmcsd_clk_init(struct imxrt_mmcsd *mmcsd)
  328. {
  329. CLOCK_EnableClock(mmcsd->ip_clock);
  330. CLOCK_SetDiv(mmcsd->usdhc_div, 5U);
  331. }
  332. static void _mmc_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
  333. {
  334. struct imxrt_mmcsd *mmcsd;
  335. struct rt_mmcsd_cmd *cmd;
  336. struct rt_mmcsd_data *data;
  337. status_t error;
  338. usdhc_adma_config_t dmaConfig;
  339. usdhc_transfer_t fsl_content = {0};
  340. usdhc_command_t fsl_command = {0};
  341. usdhc_data_t fsl_data = {0};
  342. rt_uint32_t *buf = NULL;
  343. rt_mutex_take(mmcsd_mutex, RT_WAITING_FOREVER);
  344. RT_ASSERT(host != RT_NULL);
  345. RT_ASSERT(req != RT_NULL);
  346. mmcsd = (struct imxrt_mmcsd *)host->private_data;
  347. RT_ASSERT(mmcsd != RT_NULL);
  348. cmd = req->cmd;
  349. RT_ASSERT(cmd != RT_NULL);
  350. LOG_D("\tcmd->cmd_code: %02d, cmd->arg: %08x, cmd->flags: %08x --> ", cmd->cmd_code, cmd->arg, cmd->flags);
  351. data = cmd->data;
  352. memset(&dmaConfig, 0, sizeof(usdhc_adma_config_t));
  353. /* config adma */
  354. dmaConfig.dmaMode = USDHC_DMA_MODE;
  355. dmaConfig.burstLen = kUSDHC_EnBurstLenForINCR;
  356. dmaConfig.admaTable = mmcsd->usdhc_adma2_table;
  357. dmaConfig.admaTableWords = USDHC_ADMA_TABLE_WORDS;
  358. fsl_command.index = cmd->cmd_code;
  359. fsl_command.argument = cmd->arg;
  360. if (cmd->cmd_code == STOP_TRANSMISSION)
  361. fsl_command.type = kCARD_CommandTypeAbort;
  362. else
  363. fsl_command.type = kCARD_CommandTypeNormal;
  364. switch (cmd->flags & RESP_MASK)
  365. {
  366. case RESP_NONE:
  367. fsl_command.responseType = kCARD_ResponseTypeNone;
  368. break;
  369. case RESP_R1:
  370. fsl_command.responseType = kCARD_ResponseTypeR1;
  371. break;
  372. case RESP_R1B:
  373. fsl_command.responseType = kCARD_ResponseTypeR1b;
  374. break;
  375. case RESP_R2:
  376. fsl_command.responseType = kCARD_ResponseTypeR2;
  377. break;
  378. case RESP_R3:
  379. fsl_command.responseType = kCARD_ResponseTypeR3;
  380. break;
  381. case RESP_R4:
  382. fsl_command.responseType = kCARD_ResponseTypeR4;
  383. break;
  384. case RESP_R6:
  385. fsl_command.responseType = kCARD_ResponseTypeR6;
  386. break;
  387. case RESP_R7:
  388. fsl_command.responseType = kCARD_ResponseTypeR7;
  389. break;
  390. case RESP_R5:
  391. fsl_command.responseType = kCARD_ResponseTypeR5;
  392. break;
  393. default:
  394. RT_ASSERT(NULL);
  395. }
  396. fsl_command.flags = 0;
  397. fsl_content.command = &fsl_command;
  398. if (data)
  399. {
  400. if (req->stop != NULL)
  401. fsl_data.enableAutoCommand12 = true;
  402. else
  403. fsl_data.enableAutoCommand12 = false;
  404. fsl_data.enableAutoCommand23 = false;
  405. fsl_data.enableIgnoreError = false;
  406. fsl_data.blockSize = data->blksize;
  407. fsl_data.blockCount = data->blks;
  408. LOG_D(" blksize:%d, blks:%d ", fsl_data.blockSize, fsl_data.blockCount);
  409. if (((rt_uint32_t)data->buf & (CACHE_LINESIZE - 1)) || // align cache(32byte)
  410. ((rt_uint32_t)data->buf > 0x00000000 && (rt_uint32_t)data->buf < 0x00080000) /*|| // ITCM
  411. ((rt_uint32_t)data->buf >= 0x20000000 && (rt_uint32_t)data->buf < 0x20080000)*/) // DTCM
  412. {
  413. buf = rt_malloc_align(fsl_data.blockSize * fsl_data.blockCount, CACHE_LINESIZE);
  414. RT_ASSERT(buf != RT_NULL);
  415. LOG_D(" malloc buf: %p, data->buf:%p, %d ", buf, data->buf, fsl_data.blockSize * fsl_data.blockCount);
  416. }
  417. if ((cmd->cmd_code == WRITE_BLOCK) || (cmd->cmd_code == WRITE_MULTIPLE_BLOCK))
  418. {
  419. if (buf)
  420. {
  421. LOG_D(" write(data->buf to buf) ");
  422. rt_memcpy(buf, data->buf, fsl_data.blockSize * fsl_data.blockCount);
  423. fsl_data.txData = (uint32_t const *)buf;
  424. }
  425. else
  426. {
  427. fsl_data.txData = (uint32_t const *)data->buf;
  428. }
  429. fsl_data.rxData = NULL;
  430. }
  431. else
  432. {
  433. if (buf)
  434. {
  435. fsl_data.rxData = (uint32_t *)buf;
  436. }
  437. else
  438. {
  439. fsl_data.rxData = (uint32_t *)data->buf;
  440. }
  441. fsl_data.txData = NULL;
  442. }
  443. fsl_content.data = &fsl_data;
  444. }
  445. else
  446. {
  447. fsl_content.data = NULL;
  448. }
  449. error = USDHC_TransferBlocking(mmcsd->usdhc_host.base, &dmaConfig, &fsl_content);
  450. if (error == kStatus_Fail)
  451. {
  452. SDMMCHOST_ErrorRecovery(mmcsd->usdhc_host.base);
  453. LOG_D(" ***USDHC_TransferBlocking error: %d*** --> \n", error);
  454. cmd->err = -RT_ERROR;
  455. }
  456. if (buf)
  457. {
  458. if (fsl_data.rxData)
  459. {
  460. LOG_D("read copy buf to data->buf ");
  461. rt_memcpy(data->buf, buf, fsl_data.blockSize * fsl_data.blockCount);
  462. }
  463. rt_free_align(buf);
  464. }
  465. if ((cmd->flags & RESP_MASK) == RESP_R2)
  466. {
  467. cmd->resp[3] = fsl_command.response[0];
  468. cmd->resp[2] = fsl_command.response[1];
  469. cmd->resp[1] = fsl_command.response[2];
  470. cmd->resp[0] = fsl_command.response[3];
  471. LOG_D(" resp 0x%08X 0x%08X 0x%08X 0x%08X\n",
  472. cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
  473. }
  474. else
  475. {
  476. cmd->resp[0] = fsl_command.response[0];
  477. LOG_D(" resp 0x%08X\n", cmd->resp[0]);
  478. }
  479. mmcsd_req_complete(host);
  480. rt_mutex_release(mmcsd_mutex);
  481. return;
  482. }
  483. static void _mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
  484. {
  485. struct imxrt_mmcsd *mmcsd;
  486. unsigned int usdhc_clk;
  487. unsigned int bus_width;
  488. uint32_t src_clk;
  489. RT_ASSERT(host != RT_NULL);
  490. RT_ASSERT(host->private_data != RT_NULL);
  491. RT_ASSERT(io_cfg != RT_NULL);
  492. mmcsd = (struct imxrt_mmcsd *)host->private_data;
  493. usdhc_clk = io_cfg->clock;
  494. bus_width = io_cfg->bus_width;
  495. if (usdhc_clk > IMXRT_MAX_FREQ)
  496. usdhc_clk = IMXRT_MAX_FREQ;
  497. src_clk = (CLOCK_GetSysPfdFreq(kCLOCK_Pfd2) / (CLOCK_GetDiv(mmcsd->usdhc_div) + 1U));
  498. LOG_D("\tsrc_clk: %d, usdhc_clk: %d, bus_width: %d\n", src_clk, usdhc_clk, bus_width);
  499. if (usdhc_clk)
  500. {
  501. USDHC_SetSdClock(mmcsd->usdhc_host.base, src_clk, usdhc_clk);
  502. /* Change bus width */
  503. if (bus_width == MMCSD_BUS_WIDTH_8)
  504. USDHC_SetDataBusWidth(mmcsd->usdhc_host.base, kUSDHC_DataBusWidth8Bit);
  505. else if (bus_width == MMCSD_BUS_WIDTH_4)
  506. USDHC_SetDataBusWidth(mmcsd->usdhc_host.base, kUSDHC_DataBusWidth4Bit);
  507. else if (bus_width == MMCSD_BUS_WIDTH_1)
  508. USDHC_SetDataBusWidth(mmcsd->usdhc_host.base, kUSDHC_DataBusWidth1Bit);
  509. else
  510. RT_ASSERT(RT_NULL);
  511. }
  512. }
  513. static const struct rt_mmcsd_host_ops ops =
  514. {
  515. _mmc_request,
  516. _mmc_set_iocfg,
  517. RT_NULL,//_mmc_get_card_status,
  518. RT_NULL,//_mmc_enable_sdio_irq,
  519. };
  520. rt_int32_t imxrt_mci_init(void)
  521. {
  522. #ifdef RT_USING_SDIO1
  523. struct imxrt_mmcsd *mmcsd1;
  524. host1 = mmcsd_alloc_host();
  525. if (!host1)
  526. {
  527. return -RT_ERROR;
  528. }
  529. mmcsd1 = rt_malloc(sizeof(struct imxrt_mmcsd));
  530. if (!mmcsd1)
  531. {
  532. LOG_E("alloc mci failed\n");
  533. goto err;
  534. }
  535. rt_memset(mmcsd1, 0, sizeof(struct imxrt_mmcsd));
  536. mmcsd1->usdhc_host.base = (USDHC_Type *)rt_ioremap((void*)USDHC1_BASE, 0x1000);
  537. mmcsd1->usdhc_div = kCLOCK_Usdhc1Div;
  538. mmcsd1->usdhc_adma2_table = g_usdhcAdma2Table;
  539. strncpy(host1->name, "sd", sizeof(host1->name)-1);
  540. host1->ops = &ops;
  541. host1->freq_min = 375000;
  542. host1->freq_max = 25000000;
  543. host1->valid_ocr = VDD_32_33 | VDD_33_34;
  544. host1->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | \
  545. MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ;
  546. host1->max_seg_size = 65535;
  547. host1->max_dma_segs = 2;
  548. host1->max_blk_size = 512;
  549. host1->max_blk_count = 4096;
  550. mmcsd1->host = host1;
  551. _mmcsd_clk_init(mmcsd1);
  552. _mmcsd_gpio_init(mmcsd1);
  553. _mmcsd_host_init(mmcsd1);
  554. host1->private_data = mmcsd1;
  555. mmcsd_change(host1);
  556. #endif
  557. #ifdef RT_USING_SDIO2
  558. struct imxrt_mmcsd *mmcsd2;
  559. host2 = mmcsd_alloc_host();
  560. if (!host2)
  561. {
  562. return -RT_ERROR;
  563. }
  564. mmcsd2 = rt_malloc(sizeof(struct imxrt_mmcsd));
  565. if (!mmcsd2)
  566. {
  567. LOG_E("alloc mci failed\n");
  568. goto err;
  569. }
  570. rt_memset(mmcsd2, 0, sizeof(struct imxrt_mmcsd));
  571. mmcsd2->usdhc_host.base = (USDHC_Type *)rt_ioremap((void*)USDHC2_BASE, 0x1000);
  572. mmcsd2->usdhc_div = kCLOCK_Usdhc1Div;
  573. mmcsd2->usdhc_adma2_table = g_usdhcAdma2Table;
  574. strncpy(host2->name, "emmc", sizeof(host2->name)-1);
  575. host2->ops = &ops;
  576. host2->freq_min = 375000;
  577. host2->freq_max = 52000000;
  578. host2->valid_ocr = VDD_35_36;
  579. host2->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | \
  580. MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ;
  581. host2->max_seg_size = 65535;
  582. host2->max_dma_segs = 2;
  583. host2->max_blk_size = 512;
  584. host2->max_blk_count = 4096;
  585. mmcsd2->host = host2;
  586. _mmcsd_clk_init(mmcsd2);
  587. _mmcsd_gpio_init(mmcsd2);
  588. _mmcsd_host_init(mmcsd2);
  589. host2->private_data = mmcsd2;
  590. mmcsd_change(host2);
  591. #endif
  592. mmcsd_mutex = rt_mutex_create("mmutex", RT_IPC_FLAG_FIFO);
  593. if (mmcsd_mutex == RT_NULL)
  594. {
  595. LOG_E("create mmcsd mutex failed.\n");
  596. return -1;
  597. }
  598. return 0;
  599. err:
  600. #ifdef RT_USING_SDIO1
  601. mmcsd_free_host(host1);
  602. #endif
  603. #ifdef RT_USING_SDIO2
  604. mmcsd_free_host(host2);
  605. #endif
  606. return -RT_ENOMEM;
  607. }
  608. INIT_DEVICE_EXPORT(imxrt_mci_init);
  609. void host_change(void)
  610. {
  611. mmcsd_change(host1);
  612. }