drv_sdio.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. /*
  2. * Copyright (c) 2006-2022, Synwit Technology Co.,Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-07-01 lik first version
  9. */
  10. #include "drv_sdio.h"
  11. #ifdef RT_USING_SDIO
  12. #ifdef BSP_USING_SDIO
  13. //#define DRV_DEBUG
  14. #define LOG_TAG "drv.sdio"
  15. #include <drv_log.h>
  16. #define SDIO_BUFF_SIZE 4096
  17. #define SDIO_ALIGN_LEN 4
  18. #ifndef SDIO_MAX_FREQ
  19. #define SDIO_MAX_FREQ (30000000)
  20. #endif
  21. struct swm_sdio_pkg
  22. {
  23. struct rt_mmcsd_cmd *cmd;
  24. void *buff;
  25. rt_uint32_t flag;
  26. };
  27. typedef rt_err_t (*sdio_txconfig)(struct swm_sdio_pkg *pkg, rt_uint32_t *buff, int size);
  28. typedef rt_err_t (*sdio_rxconfig)(struct swm_sdio_pkg *pkg, rt_uint32_t *buff, int size);
  29. typedef rt_uint32_t (*sdio_clk_get)(SDIO_TypeDef *swm_sdio);
  30. struct swm_sdio_des
  31. {
  32. SDIO_TypeDef *swm_sdio;
  33. sdio_txconfig txconfig;
  34. sdio_rxconfig rxconfig;
  35. sdio_clk_get clk_get;
  36. };
  37. static struct rt_mmcsd_host *host;
  38. #define RTHW_SDIO_LOCK(_sdio) rt_mutex_take(&_sdio->mutex, RT_WAITING_FOREVER)
  39. #define RTHW_SDIO_UNLOCK(_sdio) rt_mutex_release(&_sdio->mutex);
  40. struct swm_sdio_device
  41. {
  42. struct rt_mmcsd_host *host;
  43. struct swm_sdio_des sdio_des;
  44. struct rt_event event;
  45. struct rt_mutex mutex;
  46. struct swm_sdio_pkg *pkg;
  47. };
  48. rt_align(SDIO_ALIGN_LEN)
  49. static rt_uint8_t cache_buf[SDIO_BUFF_SIZE];
  50. /**
  51. * @brief This function wait sdio completed.
  52. * @param sdio swm_sdio_device
  53. * @retval None
  54. */
  55. static void swm_sdio_wait_completed(struct swm_sdio_device *sdio)
  56. {
  57. rt_uint32_t status;
  58. struct rt_mmcsd_cmd *cmd = sdio->pkg->cmd;
  59. struct rt_mmcsd_data *data = cmd->data;
  60. SDIO_TypeDef *swm_sdio = sdio->sdio_des.swm_sdio;
  61. if (rt_event_recv(&sdio->event, 0xffffffff, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
  62. rt_tick_from_millisecond(2000), &status) != RT_EOK)
  63. {
  64. LOG_E("wait completed timeout");
  65. cmd->err = -RT_ETIMEOUT;
  66. return;
  67. }
  68. if (sdio->pkg == RT_NULL)
  69. {
  70. return;
  71. }
  72. if (resp_type(cmd) == RESP_NONE)
  73. {
  74. ;
  75. }
  76. else if (resp_type(cmd) == RESP_R2)
  77. {
  78. LOG_D("R2");
  79. cmd->resp[0] = (swm_sdio->RESP[3] << 8) + ((swm_sdio->RESP[2] >> 24) & 0xFF);
  80. cmd->resp[1] = (swm_sdio->RESP[2] << 8) + ((swm_sdio->RESP[1] >> 24) & 0xFF);
  81. cmd->resp[2] = (swm_sdio->RESP[1] << 8) + ((swm_sdio->RESP[0] >> 24) & 0xFF);
  82. cmd->resp[3] = (swm_sdio->RESP[0] << 8) + 0x00;
  83. }
  84. else
  85. {
  86. cmd->resp[0] = swm_sdio->RESP[0];
  87. }
  88. if (status & SDIO_IF_ERROR_Msk)
  89. {
  90. if ((status & SDIO_IF_CMDCRCERR_Msk) && (resp_type(cmd) & (RESP_R3 | RESP_R4)))
  91. {
  92. cmd->err = RT_EOK;
  93. }
  94. else
  95. {
  96. cmd->err = -RT_ERROR;
  97. }
  98. if (status & SDIO_IF_CMDCRCERR_Msk)
  99. {
  100. SDIO->CR2 |= (1 << SDIO_CR2_RSTCMD_Pos);
  101. data->err = -RT_ERROR;
  102. }
  103. if (status & SDIO_IF_CMDTIMEOUT_Msk)
  104. {
  105. SDIO->CR2 |= (1 << SDIO_CR2_RSTCMD_Pos);
  106. cmd->err = -RT_ETIMEOUT;
  107. }
  108. if (status & SDIO_IF_DATCRCERR_Msk)
  109. {
  110. SDIO->CR2 |= (1 << SDIO_CR2_RSTDAT_Pos);
  111. data->err = -RT_ERROR;
  112. }
  113. if (status & SDIO_IF_DATTIMEOUT_Msk)
  114. {
  115. SDIO->CR2 |= (1 << SDIO_CR2_RSTDAT_Pos);
  116. data->err = -RT_ETIMEOUT;
  117. }
  118. if (cmd->err == RT_EOK)
  119. {
  120. LOG_D("sta:0x%08X [%08X %08X %08X %08X]", status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
  121. }
  122. else
  123. {
  124. LOG_D("err:0x%08x, %s%s%s%s%s cmd:%d arg:0x%08x rw:%c len:%d blksize:%d",
  125. status,
  126. status & SDIO_IF_CMDCRCERR_Msk ? "CCRCFAIL " : "",
  127. status & SDIO_IF_DATCRCERR_Msk ? "DCRCFAIL " : "",
  128. status & SDIO_IF_CMDTIMEOUT_Msk ? "CTIMEOUT " : "",
  129. status & SDIO_IF_DATTIMEOUT_Msk ? "DTIMEOUT " : "",
  130. status == 0 ? "NULL" : "",
  131. cmd->cmd_code,
  132. cmd->arg,
  133. data ? (data->flags & DATA_DIR_WRITE ? 'w' : 'r') : '-',
  134. data ? data->blks * data->blksize : 0,
  135. data ? data->blksize : 0);
  136. }
  137. }
  138. else
  139. {
  140. cmd->err = RT_EOK;
  141. LOG_D("sta:0x%08X [%08X %08X %08X %08X]", status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
  142. }
  143. }
  144. /**
  145. * @brief This function transfer data by dma.
  146. * @param sdio swm_sdio_device
  147. * @param pkg sdio package
  148. * @retval None
  149. */
  150. static void swm_sdio_transfer(struct swm_sdio_device *sdio, struct swm_sdio_pkg *pkg)
  151. {
  152. struct rt_mmcsd_data *data;
  153. int size;
  154. void *buff;
  155. if ((RT_NULL == pkg) || (RT_NULL == sdio))
  156. {
  157. LOG_E("swm_sdio_transfer invalid args");
  158. return;
  159. }
  160. data = pkg->cmd->data;
  161. if (RT_NULL == data)
  162. {
  163. LOG_E("swm_sdio_transfer invalid args");
  164. return;
  165. }
  166. buff = pkg->buff;
  167. if (RT_NULL == buff)
  168. {
  169. LOG_E("swm_sdio_transfer invalid args");
  170. return;
  171. }
  172. size = data->blks * data->blksize;
  173. if (data->flags & DATA_DIR_WRITE)
  174. {
  175. sdio->sdio_des.txconfig(pkg, (rt_uint32_t *)buff, size);
  176. }
  177. else if (data->flags & DATA_DIR_READ)
  178. {
  179. sdio->sdio_des.rxconfig(pkg, (rt_uint32_t *)buff, size);
  180. }
  181. }
  182. /**
  183. * @brief This function send command.
  184. * @param sdio swm_sdio_device
  185. * @param pkg sdio package
  186. * @retval None
  187. */
  188. static void swm_sdio_send_command(struct swm_sdio_device *sdio, struct swm_sdio_pkg *pkg)
  189. {
  190. struct rt_mmcsd_cmd *cmd = pkg->cmd;
  191. struct rt_mmcsd_data *data = cmd->data;
  192. SDIO_TypeDef *swm_sdio = sdio->sdio_des.swm_sdio;
  193. rt_uint32_t reg_cmd;
  194. /* save pkg */
  195. sdio->pkg = pkg;
  196. LOG_D("CMD:%d ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c len:%d blksize:%d",
  197. cmd->cmd_code,
  198. cmd->arg,
  199. resp_type(cmd) == RESP_NONE ? "NONE" : "",
  200. resp_type(cmd) == RESP_R1 ? "R1" : "",
  201. resp_type(cmd) == RESP_R1B ? "R1B" : "",
  202. resp_type(cmd) == RESP_R2 ? "R2" : "",
  203. resp_type(cmd) == RESP_R3 ? "R3" : "",
  204. resp_type(cmd) == RESP_R4 ? "R4" : "",
  205. resp_type(cmd) == RESP_R5 ? "R5" : "",
  206. resp_type(cmd) == RESP_R6 ? "R6" : "",
  207. resp_type(cmd) == RESP_R7 ? "R7" : "",
  208. data ? (data->flags & DATA_DIR_WRITE ? 'w' : 'r') : '-',
  209. data ? data->blks * data->blksize : 0,
  210. data ? data->blksize : 0);
  211. /* config cmd reg */
  212. reg_cmd = (cmd->cmd_code << SDIO_CMD_CMDINDX_Pos) |
  213. (0 << SDIO_CMD_CMDTYPE_Pos) |
  214. (0 << SDIO_CMD_IDXCHECK_Pos) |
  215. (0 << SDIO_CMD_CRCCHECK_Pos) |
  216. (0 << SDIO_CMD_DMAEN_Pos);
  217. if (resp_type(cmd) == RESP_NONE)
  218. reg_cmd |= SD_RESP_NO << SDIO_CMD_RESPTYPE_Pos;
  219. else if (resp_type(cmd) == RESP_R2)
  220. reg_cmd |= SD_RESP_128b << SDIO_CMD_RESPTYPE_Pos;
  221. else
  222. reg_cmd |= SD_RESP_32b << SDIO_CMD_RESPTYPE_Pos;
  223. /* config data reg */
  224. if (data != RT_NULL)
  225. {
  226. rt_uint32_t dir = 0;
  227. dir = (data->flags & DATA_DIR_READ) ? 1 : 0;
  228. swm_sdio->BLK = (data->blks << SDIO_BLK_COUNT_Pos) | (data->blksize << SDIO_BLK_SIZE_Pos);
  229. reg_cmd |= (1 << SDIO_CMD_HAVEDATA_Pos) |
  230. (dir << SDIO_CMD_DIRREAD_Pos) |
  231. ((data->blks > 1) << SDIO_CMD_MULTBLK_Pos) |
  232. ((data->blks > 1) << SDIO_CMD_BLKCNTEN_Pos) |
  233. (0 << SDIO_CMD_AUTOCMD12_Pos);
  234. }
  235. else
  236. {
  237. reg_cmd |= (0 << SDIO_CMD_HAVEDATA_Pos);
  238. }
  239. /* send cmd */
  240. swm_sdio->ARG = cmd->arg;
  241. swm_sdio->CMD = reg_cmd;
  242. /* transfer config */
  243. if (data != RT_NULL)
  244. {
  245. swm_sdio_transfer(sdio, pkg);
  246. }
  247. /* wait completed */
  248. swm_sdio_wait_completed(sdio);
  249. /* clear pkg */
  250. sdio->pkg = RT_NULL;
  251. }
  252. /**
  253. * @brief This function send sdio request.
  254. * @param sdio swm_sdio_device
  255. * @param req request
  256. * @retval None
  257. */
  258. static void swm_sdio_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
  259. {
  260. struct swm_sdio_pkg pkg;
  261. struct swm_sdio_device *sdio = host->private_data;
  262. struct rt_mmcsd_data *data;
  263. RTHW_SDIO_LOCK(sdio);
  264. if (req->cmd != RT_NULL)
  265. {
  266. rt_memset(&pkg, 0, sizeof(pkg));
  267. data = req->cmd->data;
  268. pkg.cmd = req->cmd;
  269. if (data != RT_NULL)
  270. {
  271. rt_uint32_t size = data->blks * data->blksize;
  272. RT_ASSERT(size <= SDIO_BUFF_SIZE);
  273. pkg.buff = data->buf;
  274. if ((rt_uint32_t)data->buf & (SDIO_ALIGN_LEN - 1))
  275. {
  276. pkg.buff = cache_buf;
  277. if (data->flags & DATA_DIR_WRITE)
  278. {
  279. rt_memcpy(cache_buf, data->buf, size);
  280. }
  281. }
  282. }
  283. swm_sdio_send_command(sdio, &pkg);
  284. if ((data != RT_NULL) && (data->flags & DATA_DIR_READ) && ((rt_uint32_t)data->buf & (SDIO_ALIGN_LEN - 1)))
  285. {
  286. rt_memcpy(data->buf, cache_buf, data->blksize * data->blks);
  287. }
  288. }
  289. if (req->stop != RT_NULL)
  290. {
  291. rt_memset(&pkg, 0, sizeof(pkg));
  292. pkg.cmd = req->stop;
  293. swm_sdio_send_command(sdio, &pkg);
  294. }
  295. RTHW_SDIO_UNLOCK(sdio);
  296. mmcsd_req_complete(sdio->host);
  297. }
  298. /**
  299. * @brief This function config sdio.
  300. * @param host rt_mmcsd_host
  301. * @param io_cfg rt_mmcsd_io_cfg
  302. * @retval None
  303. */
  304. static void swm_sdio_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
  305. {
  306. rt_uint32_t clkcr, div, clk_src;
  307. rt_uint32_t clk = io_cfg->clock;
  308. struct swm_sdio_device *sdio = host->private_data;
  309. SDIO_TypeDef *swm_sdio = sdio->sdio_des.swm_sdio;
  310. clk_src = sdio->sdio_des.clk_get(sdio->sdio_des.swm_sdio);
  311. if (clk_src < 400 * 1000)
  312. {
  313. LOG_E("The clock rate is too low! rata:%d", clk_src);
  314. return;
  315. }
  316. if (clk > host->freq_max)
  317. clk = host->freq_max;
  318. if (clk > clk_src)
  319. {
  320. LOG_W("Setting rate is greater than clock source rate.");
  321. clk = clk_src;
  322. }
  323. LOG_D("clk:%d width:%s%s%s power:%s%s%s",
  324. clk,
  325. io_cfg->bus_width == MMCSD_BUS_WIDTH_8 ? "8" : "",
  326. io_cfg->bus_width == MMCSD_BUS_WIDTH_4 ? "4" : "",
  327. io_cfg->bus_width == MMCSD_BUS_WIDTH_1 ? "1" : "",
  328. io_cfg->power_mode == MMCSD_POWER_OFF ? "OFF" : "",
  329. io_cfg->power_mode == MMCSD_POWER_UP ? "UP" : "",
  330. io_cfg->power_mode == MMCSD_POWER_ON ? "ON" : "");
  331. RTHW_SDIO_LOCK(sdio);
  332. swm_sdio->CR1 = (1 << SDIO_CR1_CDSRC_Pos) | (7 << SDIO_CR1_VOLT_Pos);
  333. if (io_cfg->bus_width == MMCSD_BUS_WIDTH_8)
  334. {
  335. swm_sdio->CR1 |= (1 << SDIO_CR1_8BIT_Pos);
  336. }
  337. else
  338. {
  339. swm_sdio->CR1 &= ~SDIO_CR1_8BIT_Msk;
  340. if (io_cfg->bus_width == MMCSD_BUS_WIDTH_4)
  341. {
  342. swm_sdio->CR1 |= (1 << SDIO_CR1_4BIT_Pos);
  343. }
  344. else
  345. {
  346. swm_sdio->CR1 &= ~SDIO_CR1_4BIT_Msk;
  347. }
  348. }
  349. switch (io_cfg->power_mode)
  350. {
  351. case MMCSD_POWER_OFF:
  352. swm_sdio->CR1 &= ~SDIO_CR1_PWRON_Msk;
  353. break;
  354. case MMCSD_POWER_UP:
  355. case MMCSD_POWER_ON:
  356. swm_sdio->CR1 |= (1 << SDIO_CR1_PWRON_Pos);
  357. break;
  358. default:
  359. LOG_W("unknown power_mode %d", io_cfg->power_mode);
  360. break;
  361. }
  362. div = clk_src / clk;
  363. if ((clk == 0) || (div == 0))
  364. {
  365. clkcr = 0;
  366. }
  367. else
  368. {
  369. if (div > 128)
  370. clkcr = 0x80;
  371. else if (div > 64)
  372. clkcr = 0x40;
  373. else if (div > 32)
  374. clkcr = 0x20;
  375. else if (div > 16)
  376. clkcr = 0x10;
  377. else if (div > 8)
  378. clkcr = 0x08;
  379. else if (div > 4)
  380. clkcr = 0x04;
  381. else if (div > 2)
  382. clkcr = 0x02;
  383. else if (div > 1)
  384. clkcr = 0x01;
  385. else
  386. clkcr = 0x00;
  387. }
  388. SDIO->CR2 = (1 << SDIO_CR2_CLKEN_Pos) |
  389. (1 << SDIO_CR2_SDCLKEN_Pos) |
  390. (clkcr << SDIO_CR2_SDCLKDIV_Pos) |
  391. (0xC << SDIO_CR2_TIMEOUT_Pos); // 2**25 SDIO_CLK
  392. while ((SDIO->CR2 & SDIO_CR2_CLKRDY_Msk) == 0)
  393. ;
  394. RTHW_SDIO_UNLOCK(sdio);
  395. }
  396. /**
  397. * @brief This function delect sdcard.
  398. * @param host rt_mmcsd_host
  399. * @retval 0x01
  400. */
  401. static rt_int32_t swm_sdio_get_card_status(struct rt_mmcsd_host *host)
  402. {
  403. LOG_D("try to detect device");
  404. return 0x01;
  405. }
  406. /**
  407. * @brief This function update sdio interrupt.
  408. * @param host rt_mmcsd_host
  409. * @param enable
  410. * @retval None
  411. */
  412. void swm_sdio_enable_irq(struct rt_mmcsd_host *host, rt_int32_t enable)
  413. {
  414. struct swm_sdio_device *sdio = host->private_data;
  415. SDIO_TypeDef *swm_sdio = sdio->sdio_des.swm_sdio;
  416. if (enable)
  417. {
  418. LOG_D("enable sdio irq");
  419. swm_sdio->IM = 0xFFFFFFFF;
  420. swm_sdio->IE = 0xFFFF000F;
  421. }
  422. else
  423. {
  424. LOG_D("disable sdio irq");
  425. swm_sdio->IM &= ~0xFFFFFFFF;
  426. swm_sdio->IE &= ~0xFFFFFFFF;
  427. }
  428. }
  429. static const struct rt_mmcsd_host_ops swm_sdio_ops =
  430. {
  431. .request = swm_sdio_request,
  432. .set_iocfg = swm_sdio_set_iocfg,
  433. .get_card_status = swm_sdio_get_card_status,
  434. .enable_sdio_irq = swm_sdio_enable_irq,
  435. };
  436. struct rt_mmcsd_host *swm_sdio_host_create(struct swm_sdio_des *sdio_des)
  437. {
  438. struct rt_mmcsd_host *host;
  439. struct swm_sdio_device *sdio = RT_NULL;
  440. if ((sdio_des == RT_NULL) || (sdio_des->txconfig == RT_NULL) || (sdio_des->rxconfig == RT_NULL))
  441. {
  442. LOG_E("L:%d F:%s %s %s %s",
  443. (sdio_des == RT_NULL ? "sdio_des is NULL" : ""),
  444. (sdio_des ? (sdio_des->txconfig ? "txconfig is NULL" : "") : ""),
  445. (sdio_des ? (sdio_des->rxconfig ? "rxconfig is NULL" : "") : ""));
  446. return RT_NULL;
  447. }
  448. sdio = rt_malloc(sizeof(struct swm_sdio_device));
  449. if (sdio == RT_NULL)
  450. {
  451. LOG_E("L:%d F:%s malloc swm_sdio_device fail");
  452. return RT_NULL;
  453. }
  454. rt_memset(sdio, 0, sizeof(struct swm_sdio_device));
  455. host = mmcsd_alloc_host();
  456. if (host == RT_NULL)
  457. {
  458. LOG_E("L:%d F:%s mmcsd alloc host fail");
  459. rt_free(sdio);
  460. return RT_NULL;
  461. }
  462. rt_memcpy(&sdio->sdio_des, sdio_des, sizeof(struct swm_sdio_des));
  463. rt_event_init(&sdio->event, "sdio", RT_IPC_FLAG_FIFO);
  464. rt_mutex_init(&sdio->mutex, "sdio", RT_IPC_FLAG_FIFO);
  465. /* set host defautl attributes */
  466. host->ops = &swm_sdio_ops;
  467. host->freq_min = 400 * 1000;
  468. host->freq_max = SDIO_MAX_FREQ;
  469. host->valid_ocr = 0X00FFFF80; /* The voltage range supported is 1.65v-3.6v */
  470. #ifndef SDIO_USING_1_BIT
  471. host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_SDIO_IRQ;
  472. #else
  473. host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_SDIO_IRQ;
  474. #endif
  475. host->max_seg_size = SDIO_BUFF_SIZE;
  476. host->max_dma_segs = 1;
  477. host->max_blk_size = 512;
  478. host->max_blk_count = 512;
  479. /* link up host and sdio */
  480. sdio->host = host;
  481. host->private_data = sdio;
  482. swm_sdio_enable_irq(host, 1);
  483. /* ready to change */
  484. mmcsd_change(host);
  485. return host;
  486. }
  487. static rt_uint32_t swm_sdio_clock_get(SDIO_TypeDef *swm_sdio)
  488. {
  489. uint32_t prediv = ((SYS->CLKDIV & SYS_CLKDIV_SDIO_Msk) >> SYS_CLKDIV_SDIO_Pos);
  490. return (SystemCoreClock / (1 << prediv));
  491. }
  492. static rt_err_t swm_sdio_rxconfig(struct swm_sdio_pkg *pkg, rt_uint32_t *buff, int size)
  493. {
  494. struct rt_mmcsd_cmd *cmd = pkg->cmd;
  495. struct rt_mmcsd_data *data = cmd->data;
  496. int offset = 0;
  497. for (uint32_t i = 0; i < data->blks; i++)
  498. {
  499. offset = i* data->blksize / 4;
  500. while ((SDIO->IF & SDIO_IF_BUFRDRDY_Msk) == 0)
  501. __NOP();
  502. SDIO->IF = SDIO_IF_BUFRDRDY_Msk;
  503. for (uint32_t j = 0; j < data->blksize / 4; j++)
  504. {
  505. buff[offset + j] = SDIO->DATA;
  506. }
  507. }
  508. return RT_EOK;
  509. }
  510. static rt_err_t swm_sdio_txconfig(struct swm_sdio_pkg *pkg, rt_uint32_t *buff, int size)
  511. {
  512. struct rt_mmcsd_cmd *cmd = pkg->cmd;
  513. struct rt_mmcsd_data *data = cmd->data;
  514. int offset = 0;
  515. for (uint32_t i = 0; i < data->blks; i++)
  516. {
  517. offset = i* data->blksize / 4;
  518. while ((SDIO->IF & SDIO_IF_BUFWRRDY_Msk) == 0)
  519. __NOP();
  520. SDIO->IF = SDIO_IF_BUFWRRDY_Msk;
  521. for (uint32_t j = 0; j < data->blksize / 4; j++)
  522. {
  523. SDIO->DATA = buff[offset + j];
  524. }
  525. }
  526. return RT_EOK;
  527. }
  528. /**
  529. * @brief This function interrupt process function.
  530. * @param host rt_mmcsd_host
  531. * @retval None
  532. */
  533. static void swm_sdio_irq_process(struct rt_mmcsd_host *host)
  534. {
  535. int complete = 0;
  536. struct swm_sdio_device *sdio = host->private_data;
  537. SDIO_TypeDef *swm_sdio = sdio->sdio_des.swm_sdio;
  538. rt_uint32_t intstatus = swm_sdio->IF;
  539. if (intstatus & SDIO_IF_ERROR_Msk)
  540. {
  541. swm_sdio->IF = 0xFFFFFFFF;
  542. complete = 1;
  543. }
  544. else
  545. {
  546. if (intstatus & SDIO_IF_CMDDONE_Msk)
  547. {
  548. swm_sdio->IF = SDIO_IF_CMDDONE_Msk;
  549. if (sdio->pkg != RT_NULL)
  550. {
  551. if (!sdio->pkg->cmd->data)
  552. {
  553. complete = 1;
  554. }
  555. }
  556. }
  557. if (intstatus & SDIO_IF_TRXDONE_Msk)
  558. {
  559. swm_sdio->IF = SDIO_IF_TRXDONE_Msk;
  560. complete = 1;
  561. }
  562. }
  563. if (complete)
  564. {
  565. rt_event_send(&sdio->event, intstatus);
  566. }
  567. }
  568. void SDIO_Handler(void)
  569. {
  570. /* enter interrupt */
  571. rt_interrupt_enter();
  572. /* Process All SDIO Interrupt Sources */
  573. swm_sdio_irq_process(host);
  574. /* leave interrupt */
  575. rt_interrupt_leave();
  576. }
  577. int swm_sdio_init(void)
  578. {
  579. int result = RT_EOK;
  580. struct swm_sdio_des sdio_des;
  581. #if 1
  582. PORT_Init(PORTB, PIN1, PORTB_PIN1_SD_CLK, 0);
  583. PORT_Init(PORTB, PIN2, PORTB_PIN2_SD_CMD, 1);
  584. PORT_Init(PORTB, PIN3, PORTB_PIN3_SD_D0, 1);
  585. PORT_Init(PORTB, PIN4, PORTB_PIN4_SD_D1, 1);
  586. PORT_Init(PORTB, PIN5, PORTB_PIN5_SD_D2, 1);
  587. PORT_Init(PORTB, PIN6, PORTB_PIN6_SD_D3, 1);
  588. #else
  589. PORT_Init(PORTP, PIN11, PORTP_PIN11_SD_CLK, 0);
  590. PORT_Init(PORTP, PIN10, PORTP_PIN10_SD_CMD, 1);
  591. PORT_Init(PORTP, PIN9, PORTP_PIN9_SD_D0, 1);
  592. PORT_Init(PORTP, PIN8, PORTP_PIN8_SD_D1, 1);
  593. PORT_Init(PORTP, PIN7, PORTP_PIN7_SD_D2, 1);
  594. PORT_Init(PORTP, PIN6, PORTP_PIN6_SD_D3, 1);
  595. #endif
  596. NVIC_EnableIRQ(SDIO_IRQn);
  597. SYS->CLKDIV &= ~SYS_CLKDIV_SDIO_Msk;
  598. if (SystemCoreClock > 80000000) //SDIO时钟需要小于52MHz
  599. SYS->CLKDIV |= (2 << SYS_CLKDIV_SDIO_Pos); //SDCLK = SYSCLK / 4
  600. else
  601. SYS->CLKDIV |= (1 << SYS_CLKDIV_SDIO_Pos); //SDCLK = SYSCLK / 2
  602. SYS->CLKEN |= (0x01 << SYS_CLKEN_SDIO_Pos);
  603. SDIO->CR2 = (1 << SDIO_CR2_RSTALL_Pos);
  604. NVIC_EnableIRQ(SDIO_IRQn);
  605. sdio_des.clk_get = swm_sdio_clock_get;
  606. sdio_des.swm_sdio = SDIO;
  607. sdio_des.rxconfig = swm_sdio_rxconfig;
  608. sdio_des.txconfig = swm_sdio_txconfig;
  609. host = swm_sdio_host_create(&sdio_des);
  610. if (host == RT_NULL)
  611. {
  612. LOG_E("host create fail.");
  613. result = -1;
  614. }
  615. else
  616. {
  617. LOG_D("host create success.");
  618. result = 0;
  619. }
  620. return result;
  621. }
  622. INIT_DEVICE_EXPORT(swm_sdio_init);
  623. #endif /* BSP_USING_SDIO */
  624. #endif /* RT_USING_SDIO */