drv_sdctrl.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  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. * 2021-03-18 Carl the first version
  9. */
  10. #include "drv_sdctrl.h"
  11. #include "ft_sdctrl_hw.h"
  12. #include "ft_sdctrl.h"
  13. #include "ft_debug.h"
  14. #include "ft_types.h"
  15. #include "ft_generic_timer.h"
  16. #include <drivers/mmcsd_core.h>
  17. #include "interrupt.h"
  18. #include "rtconfig.h"
  19. #include "ft_cache.h"
  20. #ifdef BSP_USING_SDC
  21. #define LOG_TAG "drv.sdmmc"
  22. #include <drv_log.h>
  23. #define RTHW_SDCTRL_LOCK(_sdctrl) rt_mutex_take(&_sdctrl->mutex, RT_WAITING_FOREVER)
  24. #define RTHW_SDCTRL_UNLOCK(_sdctrl) rt_mutex_release(&_sdctrl->mutex);
  25. struct mmcsd_pkg
  26. {
  27. struct rt_mmcsd_cmd *cmd;
  28. void *buff;
  29. rt_uint32_t flag;
  30. };
  31. typedef struct
  32. {
  33. FtsdCtrl_t ft_sdctrl;
  34. struct rt_mmcsd_host *host;
  35. struct rt_event event;
  36. struct rt_mutex mutex;
  37. struct mmcsd_pkg *pkg;
  38. } ft_sdctrl_class_t;
  39. ft_sdctrl_class_t sdctrl_class;
  40. rt_align(SDCTR_ALIGN_LEN)
  41. static rt_uint8_t cache_buf[SDCTR_BUFF_SIZE];
  42. static void rthw_sdctrl_send_command(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg);
  43. static void demo_dump_sdc(void)
  44. {
  45. Ft_DumpHexWord((const rt_uint32_t *)(0x28207C00), 256);
  46. }
  47. MSH_CMD_EXPORT_ALIAS(demo_dump_sdc, dump_sdc, output all dump_sdc);
  48. static void rthw_sdctrl_delay(u32 delayCnt)
  49. {
  50. Ft_GenericTimer_UsDelay(delayCnt);
  51. }
  52. static u32 rthw_sdctrl_rasp2type(u32 rasp)
  53. {
  54. switch (rasp)
  55. {
  56. case RESP_NONE:
  57. return FTSDCTRL_CMD_RES_NONE;
  58. case RESP_R2:
  59. return FTSDCTRL_CMD_RES_LONG;
  60. default:
  61. return FTSDCTRL_CMD_RES_SHORT;
  62. }
  63. return FTSDCTRL_CMD_RES_SHORT;
  64. }
  65. static void rthw_sdctrl_transfer_by_dma(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg)
  66. {
  67. struct rt_mmcsd_data *data;
  68. struct rt_mmcsd_cmd *cmd;
  69. u32 rasp;
  70. u32 *buff;
  71. FtsdCtrl_t *ft_sdctrl_p;
  72. if ((RT_NULL == class_p))
  73. {
  74. LOG_E("rthw_sdctrl_transfer_by_dma invalid class_p");
  75. return;
  76. }
  77. ft_sdctrl_p = &class_p->ft_sdctrl;
  78. if ((RT_NULL == pkg))
  79. {
  80. LOG_E("rthw_sdctrl_transfer_by_dma invalid args");
  81. return;
  82. }
  83. data = pkg->cmd->data;
  84. if (RT_NULL == data)
  85. {
  86. LOG_E("rthw_sdctrl_transfer_by_dma invalid args");
  87. return;
  88. }
  89. buff = pkg->buff;
  90. if (RT_NULL == buff)
  91. {
  92. LOG_E("rthw_sdctrl_transfer_by_dma invalid args");
  93. return;
  94. }
  95. cmd = pkg->cmd;
  96. rasp = resp_type(pkg->cmd);
  97. rasp = rthw_sdctrl_rasp2type(rasp);
  98. if (data->flags & DATA_DIR_WRITE)
  99. {
  100. #ifdef BSP_SDC_DEBUG_PRINT
  101. rt_kprintf("DATA_DIR_WRITE %x \r\n", cmd->arg);
  102. #endif
  103. FCache_cpuDcacheClean(buff, data->blks * data->blksize);
  104. /* data, card, blk: card : data + blk */
  105. FSdCtrl_WriteData(ft_sdctrl_p, (UINTPTR)buff, cmd->arg, data->blks);
  106. cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp);
  107. #ifdef BSP_SDC_DEBUG_PRINT
  108. for (int i = 0; i < 4; i++)
  109. {
  110. rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]);
  111. }
  112. Ft_DumpHexWord(buff, 256);
  113. #endif
  114. FSdCtrl_WaitWriteDataEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, data->blks);
  115. FCache_cpuDcacheInvalidate(buff, data->blks * data->blksize);
  116. }
  117. else if (data->flags & DATA_DIR_READ)
  118. {
  119. #ifdef BSP_SDC_DEBUG_PRINT
  120. rt_kprintf("DATA_DIR_READ %x \r\n", cmd->arg);
  121. #endif
  122. if ((cmd->flags & CMD_ADTC) && (data->blksize < 512))
  123. {
  124. #ifdef BSP_SDC_DEBUG_PRINT
  125. LOG_E("CMD_ADTC \r\n");
  126. #endif
  127. FSdCtrl_DoACmd(ft_sdctrl_p, cmd->cmd_code, rasp, cmd->arg);
  128. rt_thread_mdelay(10);
  129. }
  130. FCache_cpuDcacheInvalidate(buff, data->blks * data->blksize);
  131. FSdCtrl_ReadData(ft_sdctrl_p, (UINTPTR)buff, cmd->arg, data->blks);
  132. cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp);
  133. #ifdef BSP_SDC_DEBUG_PRINT
  134. for (int i = 0; i < 4; i++)
  135. {
  136. rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]);
  137. }
  138. #endif
  139. FSdCtrl_WaitReadDataEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, data->blks);
  140. FCache_cpuDcacheClean(buff, data->blks * data->blksize);
  141. #ifdef BSP_SDC_DEBUG_PRINT
  142. Ft_DumpHexWord(buff, data->blks * data->blksize);
  143. #endif
  144. }
  145. }
  146. static void rthw_sdctrl_docmd(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg)
  147. {
  148. struct rt_mmcsd_cmd *cmd;
  149. u32 rasp;
  150. FtsdCtrl_t *ft_sdctrl_p;
  151. if ((RT_NULL == class_p))
  152. {
  153. LOG_E("rthw_sdctrl_docmd invalid class_p");
  154. return;
  155. }
  156. ft_sdctrl_p = &class_p->ft_sdctrl;
  157. if ((RT_NULL == pkg))
  158. {
  159. LOG_E("rthw_sdctrl_docmd invalid args");
  160. return;
  161. }
  162. cmd = pkg->cmd;
  163. rasp = resp_type(pkg->cmd);
  164. rasp = rthw_sdctrl_rasp2type(rasp);
  165. FSdCtrl_DoCmd(ft_sdctrl_p, pkg->cmd->cmd_code, rasp, cmd->arg);
  166. cmd->err = FSdCtrl_WaitCmdEnd(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay, rasp, cmd->resp);
  167. #ifdef BSP_SDC_DEBUG_PRINT
  168. for (int i = 0; i < 4; i++)
  169. {
  170. rt_kprintf("cmdRsp[%d] %x \r\n", i, cmd->resp[i]);
  171. }
  172. #endif
  173. }
  174. static void rthw_sdctrl_send_command(ft_sdctrl_class_t *class_p, struct mmcsd_pkg *pkg)
  175. {
  176. struct rt_mmcsd_cmd *cmd = pkg->cmd;
  177. struct rt_mmcsd_data *data = cmd->data;
  178. /* save pkg */
  179. class_p->pkg = pkg;
  180. /* config data reg */
  181. if (data != RT_NULL && data->blks)
  182. {
  183. /* transfer config */
  184. rthw_sdctrl_transfer_by_dma(class_p, pkg);
  185. }
  186. else
  187. {
  188. rthw_sdctrl_docmd(class_p, pkg);
  189. }
  190. }
  191. /**
  192. * @brief This function send sdio request.
  193. * @param host rt_mmcsd_host
  194. * @param req request
  195. * @retval None
  196. */
  197. static void rthw_sdctrl_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
  198. {
  199. struct mmcsd_pkg pkg;
  200. ft_sdctrl_class_t *class_p = host->private_data;
  201. struct rt_mmcsd_data *data;
  202. RTHW_SDCTRL_LOCK(class_p);
  203. if (req->cmd != RT_NULL)
  204. {
  205. rt_memset(&pkg, 0, sizeof(pkg));
  206. data = req->cmd->data;
  207. pkg.cmd = req->cmd;
  208. if (pkg.cmd->cmd_code == 5 || pkg.cmd->cmd_code == 1)
  209. {
  210. rt_kprintf("cmd_code is not vaild %x \r\n", pkg.cmd->cmd_code);
  211. pkg.cmd->err = RT_EINVAL;
  212. goto _exit;
  213. }
  214. #ifdef BSP_SDC_DEBUG_PRINT
  215. struct rt_mmcsd_cmd *cmd;
  216. cmd = req->cmd;
  217. LOG_E("CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c len:%d blksize:%d",
  218. cmd->cmd_code,
  219. cmd->arg,
  220. resp_type(cmd) == RESP_NONE ? "NONE" : "",
  221. resp_type(cmd) == RESP_R1 ? "R1" : "",
  222. resp_type(cmd) == RESP_R1B ? "R1B" : "",
  223. resp_type(cmd) == RESP_R2 ? "R2" : "",
  224. resp_type(cmd) == RESP_R3 ? "R3" : "",
  225. resp_type(cmd) == RESP_R4 ? "R4" : "",
  226. resp_type(cmd) == RESP_R5 ? "R5" : "",
  227. resp_type(cmd) == RESP_R6 ? "R6" : "",
  228. resp_type(cmd) == RESP_R7 ? "R7" : "",
  229. data ? (data->flags & DATA_DIR_WRITE ? 'w' : 'r') : '-',
  230. data ? data->blks * data->blksize : 0,
  231. data ? data->blksize : 0);
  232. #endif
  233. if (data != RT_NULL)
  234. {
  235. rt_uint32_t size = data->blks * data->blksize;
  236. RT_ASSERT(size <= SDCTR_BUFF_SIZE);
  237. pkg.buff = data->buf;
  238. if ((rt_uint32_t)data->buf & (SDCTR_ALIGN_LEN - 1))
  239. {
  240. pkg.buff = cache_buf;
  241. if (data->flags & DATA_DIR_WRITE)
  242. {
  243. rt_memcpy(cache_buf, data->buf, size);
  244. }
  245. }
  246. }
  247. rthw_sdctrl_send_command(class_p, &pkg);
  248. if ((data != RT_NULL) && (data->flags & DATA_DIR_READ) && ((rt_uint32_t)data->buf & (SDCTR_ALIGN_LEN - 1)))
  249. {
  250. rt_memcpy(data->buf, cache_buf, data->blksize * data->blks);
  251. }
  252. }
  253. if (req->stop != RT_NULL)
  254. {
  255. rt_memset(&pkg, 0, sizeof(pkg));
  256. pkg.cmd = req->stop;
  257. rthw_sdctrl_send_command(class_p, &pkg);
  258. }
  259. _exit:
  260. RTHW_SDCTRL_UNLOCK(class_p);
  261. mmcsd_req_complete(class_p->host);
  262. }
  263. static void rthw_sdctrl_clk_divider(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
  264. {
  265. ft_sdctrl_class_t *class_p = host->private_data;
  266. FtsdCtrl_t *sd_ctrl = &(class_p->ft_sdctrl);
  267. /* bus mode is pull push */
  268. FSdCtrl_ClkFreqSetup(sd_ctrl, io_cfg->clock);
  269. return;
  270. }
  271. static void rthw_sdctrl_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
  272. {
  273. ft_sdctrl_class_t *class_p = host->private_data;
  274. RTHW_SDCTRL_LOCK(class_p);
  275. /* calculate and set clk divider */
  276. rthw_sdctrl_clk_divider(host, io_cfg);
  277. RTHW_SDCTRL_UNLOCK(class_p);
  278. }
  279. rt_int32_t rthw_sdctrl_detect(struct rt_mmcsd_host *host)
  280. {
  281. ft_sdctrl_class_t *class_p = host->private_data;
  282. return FSdCtrl_CardDetect(&class_p->ft_sdctrl);
  283. }
  284. static const struct rt_mmcsd_host_ops ops =
  285. {
  286. rthw_sdctrl_request,
  287. rthw_sdctrl_iocfg,
  288. rthw_sdctrl_detect,
  289. RT_NULL,
  290. };
  291. void rthw_sdctrl_nomarl_callback(void *args)
  292. {
  293. FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args;
  294. rt_uint32_t status;
  295. ft_sdctrl_class_t *class_p;
  296. if (RT_NULL == pFtsdCtrl)
  297. {
  298. return;
  299. }
  300. class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
  301. status = FSdCtrl_GetNormalIrqStatus(pFtsdCtrl);
  302. if (status & NORMAL_INT_STATUS_CR)
  303. {
  304. rt_event_send(&class_p->event, SDCTR_CARD_REMOVE_FLG);
  305. }
  306. else if (status & NORMAL_INT_STATUS_CC)
  307. {
  308. rt_event_send(&class_p->event, SDCTR_CMD_IS_COMPLETE_FLG);
  309. }
  310. else if (status & NORMAL_INT_STATUS_EI)
  311. {
  312. rt_event_send(&class_p->event, SDCTR_CMD_IS_ERROR_FLG);
  313. }
  314. return;
  315. }
  316. void rthw_sdctrl_dma_callback(void *args)
  317. {
  318. FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args;
  319. rt_uint32_t status;
  320. ft_sdctrl_class_t *class_p;
  321. if (RT_NULL == pFtsdCtrl)
  322. {
  323. return;
  324. }
  325. class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
  326. status = FSdCtrl_GetDataIrqStatus(pFtsdCtrl);
  327. if (status & BD_ISR_REG_TRS)
  328. {
  329. /* send write complete event */
  330. rt_event_send(&class_p->event, SDCTR_WRITE_IS_COMPLETE_FLG);
  331. }
  332. if (status & BD_ISR_REG_RESPE)
  333. {
  334. /* send read complete event */
  335. rt_event_send(&class_p->event, SDCTR_READ_IS_COMPLETE_FLG);
  336. }
  337. if (status & BD_ISR_REG_DAIS)
  338. {
  339. /* send dma errror event */
  340. rt_event_send(&class_p->event, SDCTR_DMA_IS_ERROR_FLG);
  341. }
  342. }
  343. void rthw_sdctrl_error_callback(void *args)
  344. {
  345. FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)args;
  346. rt_uint32_t status;
  347. ft_sdctrl_class_t *class_p;
  348. if (RT_NULL == pFtsdCtrl)
  349. {
  350. return;
  351. }
  352. class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
  353. status = FSdCtrl_GetErrorIrqStatus(pFtsdCtrl);
  354. if (status & SDCTR_CMD_TIMEOUT_FLG)
  355. {
  356. rt_event_send(&class_p->event, SDCTR_CMD_TIMEOUT_FLG);
  357. }
  358. if (status & ERROR_INT_EN_CNR)
  359. {
  360. rt_event_send(&class_p->event, SDCTR_CMD_RECEIVE_IS_ERROR_FLG);
  361. }
  362. if (status & ERROR_INT_EN_CCRCE)
  363. {
  364. rt_event_send(&class_p->event, SDCTR_CMD_CRC_IS_ERROR_FLG);
  365. }
  366. }
  367. void rthw_sdctrl_normal_irq(int vector, void *param)
  368. {
  369. FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param;
  370. FSdCtrl_NormalIrq(pFtsdCtrl);
  371. }
  372. void rthw_sdctrl_dma_irq(int vector, void *param)
  373. {
  374. FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param;
  375. FSdCtrl_DmaIrq(pFtsdCtrl);
  376. }
  377. void rthw_sdctrl_err_irq(int vector, void *param)
  378. {
  379. FtsdCtrl_t *pFtsdCtrl = (FtsdCtrl_t *)param;
  380. FSdCtrl_ErrIrq(pFtsdCtrl);
  381. }
  382. ft_error_t rthw_sdctrl_cmd_wait(FtsdCtrl_t *pFtsdCtrl)
  383. {
  384. rt_uint32_t status;
  385. ft_sdctrl_class_t *class_p;
  386. if (RT_NULL == pFtsdCtrl)
  387. {
  388. return FTSDC_INVALID_PARAM;
  389. }
  390. class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
  391. if (rt_event_recv(&class_p->event, SDCTR_CMD_IS_COMPLETE_FLG | SDCTR_CMD_IS_ERROR_FLG | SDCTR_CMD_CRC_IS_ERROR_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
  392. rt_tick_from_millisecond(50000), &status) != RT_EOK)
  393. {
  394. /* wait cmd completed timeout */
  395. LOG_E("wait cmd completed timeout");
  396. return FTSDC_TIMEOUT;
  397. }
  398. if (SDCTR_CMD_IS_COMPLETE_FLG == (status & SDCTR_CMD_IS_COMPLETE_FLG))
  399. {
  400. return FTSDC_SUCCESS;
  401. }
  402. else
  403. {
  404. LOG_E("wait cmd is error %x ", status);
  405. return FTSDC_FAILURE;
  406. }
  407. }
  408. ft_error_t rthw_sdctrl_read_wait(FtsdCtrl_t *pFtsdCtrl)
  409. {
  410. rt_uint32_t status;
  411. ft_sdctrl_class_t *class_p;
  412. if (RT_NULL == pFtsdCtrl)
  413. {
  414. return FTSDC_INVALID_PARAM;
  415. }
  416. class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
  417. if (rt_event_recv(&class_p->event, SDCTR_READ_IS_COMPLETE_FLG | SDCTR_CMD_RECEIVE_IS_ERROR_FLG,
  418. RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
  419. rt_tick_from_millisecond(50000), &status) != RT_EOK)
  420. {
  421. /* wait read completed timeout */
  422. LOG_E("wait read completed timeout");
  423. return FTSDC_TIMEOUT;
  424. }
  425. if (SDCTR_READ_IS_COMPLETE_FLG == (status & SDCTR_READ_IS_COMPLETE_FLG))
  426. {
  427. return FTSDC_SUCCESS;
  428. }
  429. else
  430. {
  431. LOG_E("wait read is error %x ", status);
  432. return FTSDC_FAILURE;
  433. }
  434. }
  435. ft_error_t rthw_sdctrl_write_wait(FtsdCtrl_t *pFtsdCtrl)
  436. {
  437. rt_uint32_t status;
  438. ft_sdctrl_class_t *class_p;
  439. if (RT_NULL == pFtsdCtrl)
  440. {
  441. return FTSDC_INVALID_PARAM;
  442. }
  443. class_p = rt_container_of(pFtsdCtrl, ft_sdctrl_class_t, ft_sdctrl);
  444. if (rt_event_recv(&class_p->event, SDCTR_WRITE_IS_COMPLETE_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
  445. rt_tick_from_millisecond(50000), &status) != RT_EOK)
  446. {
  447. /* wait write completed timeout */
  448. LOG_E("wait write completed timeout");
  449. return FTSDC_TIMEOUT;
  450. }
  451. if (SDCTR_WRITE_IS_COMPLETE_FLG == (status & SDCTR_WRITE_IS_COMPLETE_FLG))
  452. {
  453. return FTSDC_SUCCESS;
  454. }
  455. else
  456. {
  457. LOG_E("wait write is error %x ", status);
  458. return FTSDC_FAILURE;
  459. }
  460. }
  461. static rt_err_t rthw_sdctrl_create(ft_sdctrl_class_t *class_p)
  462. {
  463. struct rt_mmcsd_host *host;
  464. host = mmcsd_alloc_host();
  465. if (host == RT_NULL)
  466. {
  467. LOG_E("L:%d F:%s mmcsd alloc host fail");
  468. return RT_ENOMEM;
  469. }
  470. class_p->ft_sdctrl.config = *(FSdCtrl_Config_t *)FSdCtrl_LookupConfig(0);
  471. rt_event_init(&class_p->event, "sdctrl", RT_IPC_FLAG_FIFO);
  472. rt_mutex_init(&class_p->mutex, "sdctrl", RT_IPC_FLAG_PRIO);
  473. class_p->host = host;
  474. host->ops = &ops;
  475. /* range of sd work speed */
  476. host->freq_min = 400 * 1000;
  477. host->freq_max = 48 * 1000000;
  478. host->valid_ocr = 0X00FFFF80; /* The voltage range supported is 1.65v-3.6v */
  479. host->flags = MMCSD_BUSWIDTH_4;
  480. host->private_data = class_p;
  481. /* ready to change */
  482. return RT_EOK;
  483. }
  484. int rthw_sdctrl_init(void)
  485. {
  486. FtsdCtrl_t *ft_sdctrl_p;
  487. #ifdef BSP_SDC_USE_IRQ
  488. FSdCtrl_Config_t *config_p;
  489. FSdCtrl_NormalIrqSelect_t normalIrqFlgs = 0;
  490. #endif
  491. rt_kprintf("rthw_sdctrl_init \r\n");
  492. RT_ASSERT(rthw_sdctrl_create(&sdctrl_class) == RT_EOK);
  493. ft_sdctrl_p = &sdctrl_class.ft_sdctrl;
  494. FSdCtrl_Reset(ft_sdctrl_p, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay);
  495. FsdCtrl_Init(ft_sdctrl_p);
  496. #ifdef BSP_SDC_USE_IRQ
  497. config_p = &ft_sdctrl_p->config;
  498. #ifdef BSP_SDC_IRQ_CARD_REMOVE
  499. normalIrqFlgs |= NORMAL_IRQ_CR;
  500. #endif
  501. normalIrqFlgs |= NORMAL_IRQ_CC;
  502. /* register handler、irq enable bit and wait callback */
  503. FSdCtrl_SetHandler(ft_sdctrl_p, FTSDCTRL_CMDIRQID, rthw_sdctrl_nomarl_callback, ft_sdctrl_p);
  504. FSdCtrl_NormalIrqSet(ft_sdctrl_p, normalIrqFlgs);
  505. FSdCtrl_CmdWaitRegister(ft_sdctrl_p, rthw_sdctrl_cmd_wait);
  506. FSdCtrl_SetHandler(ft_sdctrl_p, FTSDCTRL_DMADATAIRQID, rthw_sdctrl_dma_callback, ft_sdctrl_p);
  507. FSdCtrl_BdIrqSet(ft_sdctrl_p, BD_IRQ_TRS | BD_IRQ_RESPE);
  508. FSdCtrl_WriteWaitRegister(ft_sdctrl_p, rthw_sdctrl_write_wait);
  509. FSdCtrl_ReadWaitRegister(ft_sdctrl_p, rthw_sdctrl_read_wait);
  510. config_p->workMode = FTSDCTRL_CMD_IRQ_MASK | FTSDCTRL_DATA_WRITE_IRQ_MASK | FTSDCTRL_DATA_READ_IRQ_MASK;
  511. #else
  512. #endif
  513. /* install normal irq */
  514. rt_hw_interrupt_install(ft_sdctrl_p->config.normalIrqNum, rthw_sdctrl_normal_irq,
  515. &sdctrl_class.ft_sdctrl, "normalIrq");
  516. rt_hw_interrupt_umask(ft_sdctrl_p->config.normalIrqNum);
  517. rt_hw_interrupt_install(ft_sdctrl_p->config.dmaIrqNum, rthw_sdctrl_dma_irq,
  518. &sdctrl_class.ft_sdctrl, "dmaIrq");
  519. rt_hw_interrupt_umask(ft_sdctrl_p->config.dmaIrqNum);
  520. return 0;
  521. }
  522. INIT_DEVICE_EXPORT(rthw_sdctrl_init);
  523. void ft2004_mmcsd_change(void)
  524. {
  525. mmcsd_change(sdctrl_class.host);
  526. }
  527. rt_bool_t ft2004_card_status(void)
  528. {
  529. return FSdCtrl_CardDetect(&sdctrl_class.ft_sdctrl);
  530. }
  531. rt_err_t ft2004_card_remove_check(rt_int32_t timeout, rt_uint32_t *status)
  532. {
  533. return rt_event_recv(&sdctrl_class.event, SDCTR_CARD_REMOVE_FLG, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
  534. timeout, status);
  535. }
  536. void ft2004_sdctrl_reset(void)
  537. {
  538. FSdCtrl_Reset(&sdctrl_class.ft_sdctrl, (pFtsdCtrl_delayTimer_t)rthw_sdctrl_delay);
  539. FsdCtrl_Init(&sdctrl_class.ft_sdctrl);
  540. #ifdef BSP_SDC_USE_IRQ
  541. FSdCtrl_NormalIrqSet(&sdctrl_class.ft_sdctrl, NORMAL_IRQ_CC | NORMAL_IRQ_CR | NORMAL_IRQ_EI);
  542. FSdCtrl_BdIrqSet(&sdctrl_class.ft_sdctrl, BD_IRQ_TRS | BD_IRQ_RESPE);
  543. #endif
  544. }
  545. #endif