drv_sdio.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Email: opensource_embedded@phytium.com.cn
  7. *
  8. * Change Logs:
  9. * Date Author Notes
  10. * 2023/7/11 liqiaozhong init SD card and mount file system
  11. */
  12. /***************************** Include Files *********************************/
  13. #include <rthw.h>
  14. #include <rtthread.h>
  15. #ifdef BSP_USING_SDIO
  16. #include <rtdevice.h>
  17. #include <rtdbg.h>
  18. #include <drivers/mmcsd_core.h>
  19. #ifdef RT_USING_SMART
  20. #include "ioremap.h"
  21. #endif
  22. #include "mm_aspace.h"
  23. #include "ftypes.h"
  24. #if defined(TARGET_E2000)
  25. #include "fparameters.h"
  26. #endif
  27. #include "fsdio.h"
  28. #include "fsdio_hw.h"
  29. #include "drv_sdio.h"
  30. /************************** Constant Definitions *****************************/
  31. #ifdef USING_SDIO0
  32. #define SDIO_CONTROLLER_ID FSDIO0_ID
  33. #elif defined (USING_SDIO1)
  34. #define SDIO_CONTROLLER_ID FSDIO1_ID
  35. #endif
  36. #define SDIO_TF_CARD_HOST_ID 0x1
  37. #define SDIO_MALLOC_CAP_DESC 256U
  38. #define SDIO_DMA_ALIGN 512U
  39. #define SDIO_DMA_BLK_SZ 512U
  40. #define SDIO_VALID_OCR 0x00FFFF80 /* supported voltage range is 1.65v-3.6v (VDD_165_195-VDD_35_36) */
  41. #define SDIO_MAX_BLK_TRANS 20U
  42. #ifndef CONFIG_SDCARD_OFFSET
  43. #define CONFIG_SDCARD_OFFSET 0x0U
  44. #endif
  45. /**************************** Type Definitions *******************************/
  46. typedef struct
  47. {
  48. FSdio *mmcsd_instance;
  49. FSdioIDmaDesc *rw_desc;
  50. rt_err_t (*transfer)(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req, FSdioCmdData *cmd_data_p);
  51. } mmcsd_info_t;
  52. /************************** Variable Definitions *****************************/
  53. /***************** Macros (Inline Functions) Definitions *********************/
  54. /*******************************Api Functions*********************************/
  55. static void fsdio_host_relax(void)
  56. {
  57. rt_thread_mdelay(1);
  58. }
  59. static rt_err_t fsdio_ctrl_init(struct rt_mmcsd_host *host)
  60. {
  61. mmcsd_info_t *private_data_t = (mmcsd_info_t *)host->private_data;
  62. FSdio *mmcsd_instance = RT_NULL;
  63. const FSdioConfig *default_mmcsd_config = RT_NULL;
  64. FSdioConfig mmcsd_config;
  65. FSdioIDmaDesc *rw_desc = RT_NULL;
  66. mmcsd_instance = rt_malloc(sizeof(FSdio));
  67. if (!mmcsd_instance)
  68. {
  69. LOG_E("Malloc mmcsd_instance failed");
  70. return RT_ERROR;
  71. }
  72. rw_desc = rt_malloc_align(SDIO_MAX_BLK_TRANS * sizeof(FSdioIDmaDesc), SDIO_MALLOC_CAP_DESC);
  73. if (!rw_desc)
  74. {
  75. LOG_E("Malloc rw_desc failed");
  76. return RT_ERROR;
  77. }
  78. rt_memset(mmcsd_instance, 0, sizeof(FSdio));
  79. rt_memset(rw_desc, 0, SDIO_MAX_BLK_TRANS * sizeof(FSdioIDmaDesc));
  80. /* SDIO controller init */
  81. RT_ASSERT((default_mmcsd_config = FSdioLookupConfig(SDIO_CONTROLLER_ID)) != RT_NULL);
  82. mmcsd_config = *default_mmcsd_config; /* load default config */
  83. #ifdef RT_USING_SMART
  84. mmcsd_config.base_addr = (uintptr)rt_ioremap((void *)mmcsd_config.base_addr, 0x1000);
  85. #endif
  86. mmcsd_config.trans_mode = FSDIO_IDMA_TRANS_MODE;
  87. #ifdef USING_EMMC
  88. mmcsd_config.non_removable = TRUE; /* eMMC is unremovable on board */
  89. #else
  90. mmcsd_config.non_removable = FALSE; /* TF card is removable on board */
  91. #endif
  92. if (FSDIO_SUCCESS != FSdioCfgInitialize(mmcsd_instance, &mmcsd_config))
  93. {
  94. LOG_E("SDIO controller init failed.");
  95. return RT_ERROR;
  96. }
  97. if (FSDIO_SUCCESS != FSdioSetIDMAList(mmcsd_instance, rw_desc, SDIO_MAX_BLK_TRANS))
  98. {
  99. LOG_E("SDIO controller setup DMA failed.");
  100. return RT_ERROR;
  101. }
  102. mmcsd_instance->desc_list.first_desc_p = (uintptr)rw_desc + PV_OFFSET;
  103. FSdioRegisterRelaxHandler(mmcsd_instance, fsdio_host_relax); /* SDIO delay for a while */
  104. private_data_t->mmcsd_instance = mmcsd_instance;
  105. private_data_t->rw_desc = rw_desc;
  106. rt_kprintf("SDIO controller init success!\r\n");
  107. return RT_EOK;
  108. }
  109. rt_inline rt_err_t sdio_dma_transfer(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req, FSdioCmdData *req_cmd)
  110. {
  111. FError ret = FT_SUCCESS;
  112. mmcsd_info_t *private_data_t = (mmcsd_info_t *)host->private_data;
  113. FSdio *mmcsd_instance = private_data_t->mmcsd_instance;
  114. ret = FSdioDMATransfer(mmcsd_instance, req_cmd);
  115. if (ret != FT_SUCCESS)
  116. {
  117. LOG_E("FSdioDMATransfer() fail.");
  118. return -RT_ERROR;
  119. }
  120. ret = FSdioPollWaitDMAEnd(mmcsd_instance, req_cmd);
  121. if (ret != FT_SUCCESS)
  122. {
  123. LOG_E("FSdioPollWaitDMAEnd() fail.");
  124. return -RT_ERROR;
  125. }
  126. if (resp_type(req->cmd) & RESP_MASK)
  127. {
  128. if (resp_type(req->cmd) == RESP_R2)
  129. {
  130. req->cmd->resp[3] = req_cmd->response[0];
  131. req->cmd->resp[2] = req_cmd->response[1];
  132. req->cmd->resp[1] = req_cmd->response[2];
  133. req->cmd->resp[0] = req_cmd->response[3];
  134. }
  135. else
  136. {
  137. req->cmd->resp[0] = req_cmd->response[0];
  138. }
  139. }
  140. return RT_EOK;
  141. }
  142. static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
  143. {
  144. /* ignore some SDIO-ONIY cmd */
  145. if ((req->cmd->cmd_code == SD_IO_SEND_OP_COND) || (req->cmd->cmd_code == SD_IO_RW_DIRECT))
  146. {
  147. req->cmd->err = -1;
  148. goto skip_cmd;
  149. }
  150. mmcsd_info_t *private_data_t = (mmcsd_info_t *)host->private_data;
  151. FSdioCmdData req_cmd;
  152. FSdioCmdData req_stop;
  153. FSdioData req_data;
  154. rt_uint32_t *data_buf_aligned = RT_NULL;
  155. rt_uint32_t cmd_flag = resp_type(req->cmd);
  156. rt_memset(&req_cmd, 0, sizeof(FSdioCmdData));
  157. rt_memset(&req_stop, 0, sizeof(FSdioCmdData));
  158. rt_memset(&req_data, 0, sizeof(FSdioData));
  159. /* convert req into ft driver type */
  160. if (req->cmd->cmd_code == GO_IDLE_STATE)
  161. {
  162. req_cmd.flag |= FSDIO_CMD_FLAG_NEED_INIT;
  163. }
  164. if (req->cmd->cmd_code == GO_INACTIVE_STATE)
  165. {
  166. req_cmd.flag |= FSDIO_CMD_FLAG_NEED_AUTO_STOP;
  167. }
  168. if ((cmd_flag != RESP_R3) && (cmd_flag != RESP_R4) && (cmd_flag != RESP_NONE))
  169. {
  170. req_cmd.flag |= FSDIO_CMD_FLAG_NEED_RESP_CRC;
  171. }
  172. if (cmd_flag & RESP_MASK)
  173. {
  174. req_cmd.flag |= FSDIO_CMD_FLAG_EXP_RESP;
  175. if (cmd_flag == RESP_R2)
  176. {
  177. req_cmd.flag |= FSDIO_CMD_FLAG_EXP_LONG_RESP;
  178. }
  179. }
  180. if (req->data) /* transfer command with data */
  181. {
  182. data_buf_aligned = rt_malloc_align(SDIO_DMA_BLK_SZ * req->data->blks, SDIO_DMA_ALIGN);
  183. if (!data_buf_aligned)
  184. {
  185. LOG_E("Malloc data_buf_aligned failed");
  186. return;
  187. }
  188. rt_memset(data_buf_aligned, 0, SDIO_DMA_BLK_SZ * req->data->blks);
  189. req_cmd.flag |= FSDIO_CMD_FLAG_EXP_DATA;
  190. req_data.blksz = req->data->blksize;
  191. req_data.blkcnt = req->data->blks + CONFIG_SDCARD_OFFSET;
  192. req_data.datalen = req->data->blksize * req->data->blks;
  193. if ((uintptr)req->data->buf % SDIO_DMA_ALIGN) /* data buffer should be 512-aligned */
  194. {
  195. if (req->data->flags & DATA_DIR_WRITE)
  196. {
  197. rt_memcpy((void *)data_buf_aligned, (void *)req->data->buf, req_data.datalen);
  198. }
  199. req_data.buf = (rt_uint8_t *)data_buf_aligned;
  200. req_data.buf_p = (uintptr)data_buf_aligned + PV_OFFSET;
  201. }
  202. else
  203. {
  204. req_data.buf = (rt_uint8_t *)req->data->buf;
  205. req_data.buf_p = (uintptr)req->data->buf + PV_OFFSET;
  206. }
  207. req_cmd.data_p = &req_data;
  208. if (req->data->flags & DATA_DIR_READ)
  209. {
  210. req_cmd.flag |= FSDIO_CMD_FLAG_READ_DATA;
  211. }
  212. else if (req->data->flags & DATA_DIR_WRITE)
  213. {
  214. req_cmd.flag |= FSDIO_CMD_FLAG_WRITE_DATA;
  215. }
  216. }
  217. req_cmd.cmdidx = req->cmd->cmd_code;
  218. req_cmd.cmdarg = req->cmd->arg;
  219. /* do cmd and data transfer */
  220. req->cmd->err = (private_data_t->transfer)(host, req, &req_cmd);
  221. if (req->cmd->err != RT_EOK)
  222. {
  223. LOG_E("transfer failed in %s", __func__);
  224. }
  225. if (req->data && (req->data->flags & DATA_DIR_READ))
  226. {
  227. if ((uintptr)req->data->buf % SDIO_DMA_ALIGN) /* data buffer should be 512-aligned */
  228. {
  229. rt_memcpy((void *)req->data->buf, (void *)data_buf_aligned, req_data.datalen);
  230. }
  231. }
  232. /* stop cmd */
  233. if (req->stop)
  234. {
  235. req_stop.cmdidx = req->stop->cmd_code;
  236. req_stop.cmdarg = req->stop->arg;
  237. if (req->stop->flags & RESP_MASK)
  238. {
  239. req_stop.flag |= FSDIO_CMD_FLAG_READ_DATA;
  240. if (resp_type(req->stop) == RESP_R2)
  241. req_stop.flag |= FSDIO_CMD_FLAG_EXP_LONG_RESP;
  242. }
  243. req->stop->err = (private_data_t->transfer)(host, req, &req_stop);
  244. }
  245. if (data_buf_aligned)
  246. rt_free_align(data_buf_aligned);
  247. skip_cmd:
  248. mmcsd_req_complete(host);
  249. }
  250. static void mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
  251. {
  252. FError ret = FT_SUCCESS;
  253. mmcsd_info_t *private_data_t = (mmcsd_info_t *)host->private_data;
  254. FSdio *mmcsd_instance = private_data_t->mmcsd_instance;
  255. uintptr base_addr = mmcsd_instance->config.base_addr;
  256. if (0 != io_cfg->clock)
  257. {
  258. ret = FSdioSetClkFreq(mmcsd_instance, io_cfg->clock);
  259. if (ret != FT_SUCCESS)
  260. {
  261. LOG_E("FSdioSetClkFreq fail.");
  262. }
  263. }
  264. switch (io_cfg->bus_width)
  265. {
  266. case MMCSD_BUS_WIDTH_1:
  267. FSdioSetBusWidth(base_addr, 1U);
  268. break;
  269. case MMCSD_BUS_WIDTH_4:
  270. FSdioSetBusWidth(base_addr, 4U);
  271. break;
  272. case MMCSD_BUS_WIDTH_8:
  273. FSdioSetBusWidth(base_addr, 8U);
  274. break;
  275. default:
  276. LOG_E("Invalid bus width %d", io_cfg->bus_width);
  277. break;
  278. }
  279. }
  280. static const struct rt_mmcsd_host_ops ops =
  281. {
  282. mmc_request_send,
  283. mmc_set_iocfg,
  284. RT_NULL,
  285. RT_NULL,
  286. RT_NULL,
  287. };
  288. int ft_mmcsd_init(void)
  289. {
  290. /* variables init */
  291. struct rt_mmcsd_host *host = RT_NULL;
  292. mmcsd_info_t *private_data = RT_NULL;
  293. host = mmcsd_alloc_host();
  294. if (!host)
  295. {
  296. LOG_E("Alloc host failed");
  297. goto err_free;
  298. }
  299. private_data = rt_malloc(sizeof(mmcsd_info_t));
  300. if (!private_data)
  301. {
  302. LOG_E("Malloc private_data failed");
  303. goto err_free;
  304. }
  305. rt_memset(private_data, 0, sizeof(mmcsd_info_t));
  306. private_data->transfer = sdio_dma_transfer;
  307. /* host data init */
  308. host->ops = &ops;
  309. host->freq_min = 400000;
  310. host->freq_max = 50000000;
  311. host->valid_ocr = SDIO_VALID_OCR; /* the voltage range supported is 1.65v-3.6v */
  312. host->flags = MMCSD_MUTBLKWRITE | MMCSD_BUSWIDTH_4;
  313. host->max_seg_size = SDIO_DMA_BLK_SZ; /* used in block_dev.c */
  314. host->max_dma_segs = SDIO_MAX_BLK_TRANS; /* physical segment number */
  315. host->max_blk_size = SDIO_DMA_BLK_SZ; /* all the 4 para limits size of one blk tran */
  316. host->max_blk_count = SDIO_MAX_BLK_TRANS;
  317. host->private_data = private_data;
  318. if (RT_EOK != fsdio_ctrl_init(host))
  319. {
  320. LOG_E("fsdio_ctrl_init() failed");
  321. goto err_free;
  322. }
  323. mmcsd_change(host);
  324. return RT_EOK;
  325. err_free:
  326. if (host)
  327. rt_free(host);
  328. if (private_data->mmcsd_instance)
  329. rt_free(private_data->mmcsd_instance);
  330. if (private_data->rw_desc)
  331. rt_free_align(private_data->rw_desc);
  332. if (private_data)
  333. rt_free(private_data);
  334. return -RT_EOK;
  335. }
  336. INIT_DEVICE_EXPORT(ft_mmcsd_init);
  337. #endif // #ifdef RT_USING_SDIO