mmc.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. /*
  2. * This file is part of FH8620 BSP for RT-Thread distribution.
  3. *
  4. * Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
  5. * All rights reserved
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, write to the Free Software Foundation, Inc.,
  19. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. * Visit http://www.fullhan.com to get contact with Fullhan.
  22. *
  23. * Change Logs:
  24. * Date Author Notes
  25. */
  26. #include "board_info.h"
  27. #include <rtdef.h>
  28. #include <rtdevice.h>
  29. #include <drivers/mmcsd_core.h>
  30. #include "mmc.h"
  31. //#define FH_MMC_DEBUG
  32. #define MMC_USE_INTERNAL_BUF
  33. #ifdef FH_MMC_DEBUG
  34. #define PRINT_MMC_DBG(fmt, args...) \
  35. do \
  36. { \
  37. rt_kprintf("FH_MMC_DEBUG: tick-%d, ", rt_tick_get()); \
  38. rt_kprintf(fmt, ## args); \
  39. } \
  40. while(0)
  41. #else
  42. #define PRINT_MMC_DBG(fmt, args...) do { } while (0)
  43. #endif
  44. #define PRINT_MMC_REGS(base) \
  45. do \
  46. { \
  47. int i_for_marco; \
  48. rt_uint32_t addr; \
  49. for(i_for_marco=0; i_for_marco<20; i_for_marco++) \
  50. { \
  51. addr = base + i_for_marco*4*4; \
  52. rt_kprintf("0x%x: 0x%x, 0x%x, 0x%x, 0x%x\n", addr, \
  53. GET_REG(addr+0x0), \
  54. GET_REG(addr+0x4), \
  55. GET_REG(addr+0x8), \
  56. GET_REG(addr+0xc)); \
  57. } \
  58. } \
  59. while(0)
  60. #define MMC_INTERNAL_DMA_BUF_SIZE (32*1024)
  61. static rt_uint32_t *g_mmc_dma_buf;
  62. static int fh_mmc_write_pio(struct mmc_driver *mmc_drv)
  63. {
  64. struct fh_mmc_obj *mmc_obj = (struct fh_mmc_obj *)mmc_drv->priv;
  65. struct rt_mmcsd_cmd *cmd = mmc_drv->cmd;
  66. struct rt_mmcsd_data *data = RT_NULL;
  67. rt_uint32_t size;
  68. if(cmd)
  69. data = cmd->data;
  70. if(!data)
  71. {
  72. rt_kprintf("ERROR: %s, data is NULL\n", __func__);
  73. return -RT_EIO;
  74. }
  75. size = data->blks * data->blksize;
  76. PRINT_MMC_DBG("%s, Send %d bytes\n", __func__, size);
  77. MMC_WriteData(mmc_obj, data->buf, size);
  78. MMC_ResetFifo(mmc_obj);
  79. return 0;
  80. }
  81. static int fh_mmc_read_pio(struct mmc_driver *mmc_drv)
  82. {
  83. struct fh_mmc_obj *mmc_obj = (struct fh_mmc_obj *)mmc_drv->priv;
  84. struct rt_mmcsd_cmd *cmd = mmc_drv->cmd;
  85. struct rt_mmcsd_data *data = RT_NULL;
  86. rt_uint32_t size;
  87. int ret;
  88. if(cmd)
  89. data = cmd->data;
  90. if(!data)
  91. {
  92. rt_kprintf("ERROR: %s, data is NULL\n", __func__);
  93. return -RT_EIO;
  94. }
  95. size = data->blks * data->blksize;
  96. PRINT_MMC_DBG("%s, read %d bytes\n", __func__, size);
  97. ret = MMC_ReadData(mmc_obj, data->buf, size);
  98. if(ret)
  99. {
  100. rt_kprintf("ERROR: %s, fifo IO error, ret: %d\n", __func__, ret);
  101. return -RT_EIO;
  102. }
  103. MMC_ResetFifo(mmc_obj);
  104. return 0;
  105. }
  106. static void fh_mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
  107. {
  108. rt_uint32_t clkdiv;
  109. struct mmc_driver *mmc_drv = host->private_data;
  110. struct fh_mmc_obj *mmc_obj = (struct fh_mmc_obj *)mmc_drv->priv;
  111. PRINT_MMC_DBG("%s start\n", __func__);
  112. //fixme: read from PMU
  113. //why io_cfg->clock == 0 ?
  114. if(io_cfg->clock)
  115. {
  116. clkdiv = MMC_CLOCK_IN / io_cfg->clock / 2;
  117. MMC_UpdateClockRegister(mmc_obj, clkdiv);
  118. PRINT_MMC_DBG("io_cfg->clock: %lu, clock in: %lu, clkdiv: %d\n", io_cfg->clock, MMC_CLOCK_IN, clkdiv);
  119. }
  120. if (io_cfg->bus_width == MMCSD_BUS_WIDTH_4)
  121. {
  122. MMC_SetCardWidth(mmc_obj, MMC_CARD_WIDTH_4BIT);
  123. PRINT_MMC_DBG("set to 4-bit mode\n", MMC_CLOCK_IN, clkdiv);
  124. }
  125. else
  126. {
  127. MMC_SetCardWidth(mmc_obj, MMC_CARD_WIDTH_1BIT);
  128. PRINT_MMC_DBG("set to 1-bit mode\n", MMC_CLOCK_IN, clkdiv);
  129. }
  130. /* maybe switch power to the card */
  131. switch (io_cfg->power_mode)
  132. {
  133. case MMCSD_POWER_OFF:
  134. break;
  135. case MMCSD_POWER_UP:
  136. break;
  137. case MMCSD_POWER_ON:
  138. break;
  139. default:
  140. rt_kprintf("ERROR: %s, unknown power_mode %d\n", __func__, io_cfg->power_mode);
  141. break;
  142. }
  143. PRINT_MMC_DBG("%s end\n", __func__);
  144. }
  145. static void fh_mmc_enable_sdio_irq(struct rt_mmcsd_host *host, rt_int32_t enable)
  146. {
  147. struct mmc_driver *mmc_drv = host->private_data;
  148. struct fh_mmc_obj *mmc_obj = (struct fh_mmc_obj *)mmc_drv->priv;
  149. rt_uint32_t reg;
  150. PRINT_MMC_DBG("%s start\n", __func__);
  151. if (enable)
  152. {
  153. MMC_ClearRawInterrupt(mmc_obj, MMC_INT_STATUS_SDIO);
  154. reg = MMC_GetInterruptMask(mmc_obj);
  155. reg |= MMC_INT_STATUS_SDIO;
  156. MMC_SetInterruptMask(mmc_obj, reg);
  157. }
  158. else
  159. {
  160. reg = MMC_GetInterruptMask(mmc_obj);
  161. reg &= ~MMC_INT_STATUS_SDIO;
  162. MMC_SetInterruptMask(mmc_obj, reg);
  163. }
  164. }
  165. static rt_int32_t fh_mmc_get_card_status(struct rt_mmcsd_host *host)
  166. {
  167. PRINT_MMC_DBG("%s, start\n", __func__);
  168. PRINT_MMC_DBG("%s, end\n", __func__);
  169. return 0;
  170. }
  171. static void fh_mmc_send_command(struct mmc_driver *mmc_drv, struct rt_mmcsd_cmd *cmd)
  172. {
  173. struct fh_mmc_obj *mmc_obj = (struct fh_mmc_obj *)mmc_drv->priv;
  174. struct rt_mmcsd_host *host = mmc_drv->host;
  175. struct rt_mmcsd_req *req = mmc_drv->req;
  176. //fixme: cmd->data or req->data
  177. struct rt_mmcsd_data *data = cmd->data;
  178. int ret;
  179. rt_uint32_t retries = 0;
  180. rt_uint32_t cmd_flags = 0;
  181. PRINT_MMC_DBG("%s, start\n", __func__);
  182. if (!cmd)
  183. {
  184. //fixme: stop dma
  185. rt_kprintf("ERROR: %s, cmd is NULL\n", __func__);
  186. return;
  187. }
  188. if (data)
  189. {
  190. cmd_flags |= MMC_CMD_FLAG_DATA_EXPECTED;
  191. /* always set data start - also set direction flag for read */
  192. if (data->flags & DATA_DIR_WRITE)
  193. cmd_flags |= MMC_CMD_FLAG_WRITE_TO_CARD;
  194. if (data->flags & DATA_STREAM)
  195. cmd_flags |= MMC_CMD_FLAG_DATA_STREAM;
  196. }
  197. if (cmd == req->stop)
  198. cmd_flags |= MMC_CMD_FLAG_STOP_TRANSFER;
  199. else
  200. cmd_flags |= MMC_CMD_FLAG_WAIT_PREV_DATA;
  201. switch (resp_type(cmd))
  202. {
  203. case RESP_NONE:
  204. break;
  205. case RESP_R1:
  206. case RESP_R5:
  207. case RESP_R6:
  208. case RESP_R7:
  209. case RESP_R1B:
  210. cmd_flags |= MMC_CMD_FLAG_RESPONSE_EXPECTED;
  211. cmd_flags |= MMC_CMD_FLAG_CHECK_RESP_CRC;
  212. break;
  213. case RESP_R2:
  214. cmd_flags |= MMC_CMD_FLAG_RESPONSE_EXPECTED;
  215. cmd_flags |= MMC_CMD_FLAG_CHECK_RESP_CRC;
  216. cmd_flags |= MMC_CMD_FLAG_LONG_RESPONSE;
  217. break;
  218. case RESP_R3:
  219. case RESP_R4:
  220. cmd_flags |= MMC_CMD_FLAG_RESPONSE_EXPECTED;
  221. break;
  222. default:
  223. rt_kprintf("ERROR: %s, unknown cmd type %x\n", __func__, resp_type(cmd));
  224. return;
  225. }
  226. if (cmd->cmd_code == GO_IDLE_STATE)
  227. cmd_flags |= MMC_CMD_FLAG_SEND_INIT;
  228. /* CMD 11 check switch voltage */
  229. if (cmd->cmd_code == READ_DAT_UNTIL_STOP)
  230. cmd_flags |= MMC_CMD_FLAG_SWITCH_VOLTAGE;
  231. PRINT_MMC_DBG("cmd code: %d, args: 0x%x, resp type: 0x%x, flag: 0x%x\n", cmd->cmd_code, cmd->arg, resp_type(cmd), cmd_flags);
  232. ret = MMC_SendCommand(mmc_obj, cmd->cmd_code, cmd->arg, cmd_flags);
  233. if(ret)
  234. {
  235. rt_kprintf("ERROR: %s, Send command timeout, cmd: %d, status: 0x%x\n", __func__, cmd->cmd_code, MMC_GetStatus(mmc_obj));
  236. }
  237. }
  238. static void fh_mmc_perpare_data(struct mmc_driver *mmc_drv)
  239. {
  240. struct rt_mmcsd_cmd *cmd = mmc_drv->cmd;
  241. struct rt_mmcsd_data *data = cmd->data;
  242. struct fh_mmc_obj *mmc_obj = (struct fh_mmc_obj *)mmc_drv->priv;
  243. rt_uint32_t data_size;
  244. int i;
  245. if(!data)
  246. {
  247. MMC_SetBlockSize(mmc_obj, 0);
  248. MMC_SetByteCount(mmc_obj, 0);
  249. return;
  250. }
  251. PRINT_MMC_DBG("%s, start\n", __func__);
  252. if(MMC_ResetFifo(mmc_obj))
  253. {
  254. return;
  255. }
  256. data_size = data->blks * data->blksize;
  257. MMC_SetBlockSize(mmc_obj, data->blksize);
  258. if(data_size % 4)
  259. {
  260. rt_kprintf("ERROR: data_size should be a multiple of 4, but now is %d\n", data_size);
  261. }
  262. MMC_SetByteCount(mmc_obj, data_size);
  263. PRINT_MMC_DBG("%s, set blk size: 0x%x, byte count: 0x%x\n", __func__, data->blksize, data_size);
  264. if(data_size > MMC_DMA_DESC_BUFF_SIZE * mmc_drv->max_desc)
  265. {
  266. rt_kprintf("ERROR: %s, given buffer is too big, size: 0x%x, max: 0x%x\n", __func__, data_size, MMC_DMA_DESC_BUFF_SIZE * mmc_drv->max_desc);
  267. return;
  268. }
  269. if (data_size > MMC_INTERNAL_DMA_BUF_SIZE)
  270. {
  271. rt_kprintf("ERROR: please increase MMC_INTERNAL_DMA_BUF_SIZE.\n");
  272. return;
  273. }
  274. #ifdef MMC_USE_DMA
  275. #ifdef MMC_USE_INTERNAL_BUF
  276. if (data->flags & DATA_DIR_WRITE)
  277. {
  278. rt_memcpy(g_mmc_dma_buf, data->buf, data_size);
  279. mmu_clean_invalidated_dcache(g_mmc_dma_buf, data_size);
  280. }
  281. else
  282. {
  283. mmu_invalidate_dcache(g_mmc_dma_buf, data_size);
  284. }
  285. MMC_InitDescriptors(mmc_obj, (rt_uint32_t*)g_mmc_dma_buf, data_size);
  286. mmu_clean_invalidated_dcache(mmc_obj->descriptors, sizeof(MMC_DMA_Descriptors) * mmc_drv->max_desc);
  287. MMC_StartDma(mmc_obj);
  288. #else
  289. MMC_InitDescriptors(mmc_obj, data->buf, data_size);
  290. mmu_clean_invalidated_dcache(mmc_obj->descriptors, sizeof(MMC_DMA_Descriptors) * mmc_drv->max_desc);
  291. mmu_clean_invalidated_dcache(data->buf, data_size);
  292. MMC_StartDma(mmc_obj);
  293. #endif
  294. #endif
  295. PRINT_MMC_DBG("%s, end\n", __func__);
  296. }
  297. int fh_mmc_wait_card_idle(struct fh_mmc_obj *mmc_obj)
  298. {
  299. rt_uint32_t tick, timeout;
  300. tick = rt_tick_get();
  301. timeout = tick + RT_TICK_PER_SECOND / 2; //500ms
  302. while(MMC_GetStatus(mmc_obj) & MMC_STATUS_DATA_BUSY)
  303. {
  304. tick = rt_tick_get();
  305. if(tick > timeout)
  306. {
  307. return -RT_ETIMEOUT;
  308. }
  309. }
  310. return 0;
  311. }
  312. static int fh_mmc_get_response(struct mmc_driver *mmc_drv, struct rt_mmcsd_cmd *cmd)
  313. {
  314. int i;
  315. rt_uint32_t tick, timeout, status;
  316. struct fh_mmc_obj *mmc_obj = (struct fh_mmc_obj *)mmc_drv->priv;
  317. cmd->resp[0] = 0;
  318. cmd->resp[1] = 0;
  319. cmd->resp[2] = 0;
  320. cmd->resp[3] = 0;
  321. tick = rt_tick_get();
  322. timeout = tick + RT_TICK_PER_SECOND / 2; //500ms
  323. //fixme: spin_lock_irqsave?
  324. do
  325. {
  326. status = MMC_GetRawInterrupt(mmc_obj);
  327. tick = rt_tick_get();
  328. if(tick > timeout)
  329. {
  330. PRINT_MMC_DBG("ERROR: %s, get response timeout(cmd is not received by card), RINTSTS: 0x%x, cmd: %d\n", __func__, status, cmd->cmd_code);
  331. return -RT_ETIMEOUT;
  332. }
  333. }
  334. while(!(status & MMC_INT_STATUS_CMD_DONE));
  335. MMC_ClearRawInterrupt(mmc_obj, MMC_INT_STATUS_CMD_DONE);
  336. for (i = 0; i < 4; i++)
  337. {
  338. if (resp_type(cmd) == RESP_R2)
  339. {
  340. cmd->resp[i] = MMC_GetResponse(mmc_obj, 3 - i);
  341. //fixme : R2 must delay some time here ,when use UHI card, need check why
  342. //1ms
  343. //rt_thread_sleep(RT_TICK_PER_SECOND / 100);
  344. }
  345. else
  346. {
  347. cmd->resp[i] = MMC_GetResponse(mmc_obj, i);
  348. }
  349. }
  350. PRINT_MMC_DBG("resp: 0x%x, 0x%x, 0x%x, 0x%x\n", cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
  351. if (status & MMC_INT_STATUS_RESPONSE_TIMEOUT)
  352. {
  353. MMC_ClearRawInterrupt(mmc_obj, MMC_INT_STATUS_RESPONSE_TIMEOUT);
  354. PRINT_MMC_DBG("ERROR: %s, get response timeout, RINTSTS: 0x%x\n", __func__, status);
  355. return -RT_ETIMEOUT;
  356. }
  357. else if (status & (MMC_INT_STATUS_RESP_CRC_ERROR | MMC_INT_STATUS_RESPONSE_ERROR))
  358. {
  359. MMC_ClearRawInterrupt(mmc_obj, MMC_INT_STATUS_RESP_CRC_ERROR | MMC_INT_STATUS_RESPONSE_ERROR);
  360. rt_kprintf("ERROR: %s, response error or response crc error, RINTSTS: 0x%x\n", __func__, status);
  361. //return -RT_ERROR;
  362. }
  363. return 0;
  364. }
  365. static int fh_mmc_start_transfer(struct mmc_driver *mmc_drv)
  366. {
  367. struct fh_mmc_obj *mmc_obj = (struct fh_mmc_obj *)mmc_drv->priv;
  368. struct rt_mmcsd_host *host = mmc_drv->host;
  369. struct rt_mmcsd_req *req = mmc_drv->req;
  370. struct rt_mmcsd_cmd *cmd = mmc_drv->cmd;
  371. struct rt_mmcsd_data *data = RT_NULL;
  372. int ret;
  373. rt_uint32_t interrupt, status, reg;
  374. if(cmd)
  375. data = cmd->data;
  376. if(!data)
  377. {
  378. return 0;
  379. }
  380. PRINT_MMC_DBG("%s, start\n", __func__);
  381. //fixme: spin_lock_irqsave(&host->lock, flags);
  382. //open data interrupts
  383. reg = MMC_GetInterruptMask(mmc_obj);
  384. reg |= MMC_INT_STATUS_DATA;
  385. MMC_SetInterruptMask(mmc_obj, reg);
  386. //fixme: spin_unlock_irqrestore(&host->lock, flags);
  387. ret = rt_completion_wait(&mmc_drv->transfer_completion, RT_TICK_PER_SECOND * 5);
  388. reg = MMC_GetInterruptMask(mmc_obj);
  389. reg &= ~MMC_INT_STATUS_DATA;
  390. MMC_SetInterruptMask(mmc_obj, reg);
  391. if(ret)
  392. {
  393. //fixme: error handle
  394. cmd->err = ret;
  395. interrupt = MMC_GetRawInterrupt(mmc_obj);
  396. status = MMC_GetStatus(mmc_obj);
  397. rt_kprintf("ERROR: %s, transfer timeout, ret: %d, RINTSTS: 0x%x, STATUS: 0x%x\n", __func__, ret, interrupt, status);
  398. //PRINT_MMC_REGS(mmc_obj->base);
  399. return -RT_ETIMEOUT;
  400. }
  401. data->bytes_xfered = data->blks * data->blksize;
  402. #ifdef MMC_USE_INTERNAL_BUF
  403. if (!(data->flags & DATA_DIR_WRITE))
  404. {
  405. rt_memcpy(data->buf, g_mmc_dma_buf, data->bytes_xfered);
  406. mmu_invalidate_dcache(g_mmc_dma_buf, data->bytes_xfered);
  407. }
  408. #endif
  409. return 0;
  410. }
  411. static void fh_mmc_complete_request(struct mmc_driver *mmc_drv)
  412. {
  413. struct fh_mmc_obj *mmc_obj = (struct fh_mmc_obj *)mmc_drv->priv;
  414. #ifdef MMC_USE_DMA
  415. MMC_StopDma(mmc_obj);
  416. #endif
  417. mmc_drv->cmd = RT_NULL;
  418. mmc_drv->req = RT_NULL;
  419. mmc_drv->data = RT_NULL;
  420. rt_memset(mmc_obj->descriptors, 0, 4096);
  421. MMC_SetBlockSize(mmc_obj, 0);
  422. MMC_SetByteCount(mmc_obj, 0);
  423. mmcsd_req_complete(mmc_drv->host);
  424. }
  425. static void fh_mmc_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
  426. {
  427. int ret;
  428. struct mmc_driver *mmc_drv = host->private_data;
  429. struct rt_mmcsd_cmd *cmd = req->cmd;
  430. struct fh_mmc_obj *mmc_obj = (struct fh_mmc_obj *)mmc_drv->priv;
  431. PRINT_MMC_DBG("%s start\n", __func__);
  432. mmc_drv->req = req;
  433. mmc_drv->cmd = cmd;
  434. rt_completion_init(&mmc_drv->transfer_completion);
  435. ret = fh_mmc_wait_card_idle(mmc_obj);
  436. if (ret)
  437. {
  438. rt_kprintf("ERROR: %s, data transfer timeout, status: 0x%x\n", __func__, MMC_GetStatus(mmc_obj));
  439. return;
  440. }
  441. fh_mmc_perpare_data(mmc_drv);
  442. fh_mmc_send_command(mmc_drv, cmd);
  443. ret = fh_mmc_get_response(mmc_drv, cmd);
  444. if(ret)
  445. {
  446. cmd->err = ret;
  447. rt_kprintf("%s,get response returns %d, cmd: %d\n", __func__, ret, cmd->cmd_code);
  448. goto out;
  449. }
  450. fh_mmc_start_transfer(mmc_drv);
  451. if(req->stop)
  452. {
  453. /* send stop command */
  454. PRINT_MMC_DBG("%s send stop\n", __func__);
  455. fh_mmc_send_command(mmc_drv, req->stop);
  456. }
  457. out:
  458. fh_mmc_complete_request(mmc_drv);
  459. PRINT_MMC_DBG("%s end\n", __func__);
  460. }
  461. static const struct rt_mmcsd_host_ops fh_mmc_ops =
  462. {
  463. .request = fh_mmc_request,
  464. .set_iocfg = fh_mmc_set_iocfg,
  465. .enable_sdio_irq = fh_mmc_enable_sdio_irq,
  466. .get_card_status = fh_mmc_get_card_status,
  467. };
  468. static void fh_mmc_interrupt(int irq, void *param)
  469. {
  470. struct mmc_driver *mmc_drv = (struct mmc_driver *)param;
  471. struct fh_mmc_obj *mmc_obj = (struct fh_mmc_obj *)mmc_drv->priv;
  472. struct rt_mmcsd_req *req = mmc_drv->req;
  473. struct rt_mmcsd_cmd *cmd = mmc_drv->cmd;
  474. struct rt_mmcsd_data *data;
  475. rt_uint32_t status;
  476. if (cmd && cmd->data)
  477. {
  478. data = cmd->data;
  479. }
  480. status = MMC_GetUnmaskedInterrupt(mmc_obj);
  481. PRINT_MMC_DBG("unmasked interrupts: 0x%x\n", status);
  482. if(status & MMC_INT_STATUS_CARD_DETECT)
  483. {
  484. rt_uint32_t card_status = MMC_GetCardStatus(mmc_obj);
  485. if (card_status == CARD_UNPLUGED)
  486. {
  487. rt_kprintf("card disconnected\n");
  488. }
  489. else
  490. {
  491. rt_kprintf("card connected\n");
  492. }
  493. mmcsd_change(mmc_drv->host);
  494. }
  495. if (status & MMC_INT_STATUS_SDIO)
  496. {
  497. //fixme: handle sdio
  498. //mmc_signal_sdio_irq ?
  499. }
  500. if(status & MMC_INIT_STATUS_DATA_ERROR)
  501. {
  502. rt_kprintf("ERROR: %s, data error, status: 0x%x\n", __func__, status);
  503. }
  504. if (status & MMC_INT_STATUS_TRANSFER_OVER)
  505. {
  506. //MMC_ResetFifo(mmc_obj);
  507. //rt_completion_done(&mmc_drv->transfer_completion);
  508. }
  509. if (status & MMC_INT_STATUS_TX_REQUEST)
  510. {
  511. fh_mmc_write_pio(mmc_drv);
  512. }
  513. if (status & MMC_INT_STATUS_RX_REQUEST)
  514. {
  515. fh_mmc_read_pio(mmc_drv);
  516. }
  517. MMC_ClearRawInterrupt(mmc_obj, MMC_INT_STATUS_ALL);
  518. rt_completion_done(&mmc_drv->transfer_completion);
  519. }
  520. int fh_mmc_probe(void *priv_data)
  521. {
  522. struct mmc_driver *mmc_drv;
  523. struct rt_mmcsd_host *host;
  524. struct fh_mmc_obj *mmc_obj = (struct fh_mmc_obj *)priv_data;
  525. PRINT_MMC_DBG("%s start\n", __func__);
  526. mmc_drv = (struct mmc_driver*)rt_malloc(sizeof(struct mmc_driver));
  527. rt_memset(mmc_drv, 0, sizeof(struct mmc_driver));
  528. mmc_drv->priv = mmc_obj;
  529. host = mmcsd_alloc_host();
  530. if (!host)
  531. {
  532. rt_kprintf("ERROR: %s, failed to malloc host\n", __func__);
  533. return -RT_ENOMEM;
  534. }
  535. mmc_obj->descriptors = (MMC_DMA_Descriptors*)rt_malloc(4096+64);
  536. mmc_obj->descriptors = (MMC_DMA_Descriptors*)(((UINT32)(mmc_obj->descriptors)+31)&(~31)); //cache-line aligned...
  537. g_mmc_dma_buf = rt_malloc(MMC_INTERNAL_DMA_BUF_SIZE+64);
  538. g_mmc_dma_buf = (rt_uint32_t*)(((rt_uint32_t)g_mmc_dma_buf+31) & (~31));
  539. if(!mmc_obj->descriptors)
  540. {
  541. rt_kprintf("ERROR: %s, failed to malloc dma descriptors\n", __func__);
  542. return -RT_ENOMEM;
  543. }
  544. rt_memset(mmc_obj->descriptors, 0, 4096);
  545. mmc_drv->max_desc = 4096 / (sizeof(MMC_DMA_Descriptors));
  546. host->ops = &fh_mmc_ops;
  547. host->freq_min = MMC_FEQ_MIN;
  548. host->freq_max = MMC_FEQ_MAX;
  549. host->valid_ocr = VDD_32_33 | VDD_33_34;
  550. host->flags = MMCSD_MUTBLKWRITE | \
  551. MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ;
  552. host->max_seg_size = MMC_DMA_DESC_BUFF_SIZE;
  553. host->max_dma_segs = mmc_drv->max_desc;
  554. host->max_blk_size = 512;
  555. //fixme: max_blk_count?
  556. host->max_blk_count = 2048;
  557. host->private_data = mmc_drv;
  558. mmc_drv->host = host;
  559. gpio_request(mmc_obj->power_pin_gpio);
  560. gpio_direction_output(mmc_obj->power_pin_gpio, 0);
  561. MMC_Init(mmc_obj);
  562. if(mmc_obj->id == 0){
  563. rt_hw_interrupt_install(mmc_obj->irq, fh_mmc_interrupt, (void *)mmc_drv, "mmc_isr_0");
  564. }
  565. else if(mmc_obj->id == 1){
  566. rt_hw_interrupt_install(mmc_obj->irq, fh_mmc_interrupt, (void *)mmc_drv, "mmc_isr_1");
  567. }
  568. rt_hw_interrupt_umask(mmc_obj->irq);
  569. mmcsd_change(host);
  570. MMC_SetInterruptMask(mmc_obj, MMC_INT_STATUS_CARD_DETECT);
  571. PRINT_MMC_DBG("%s end\n", __func__);
  572. return 0;
  573. }
  574. int fh_mmc_exit(void *priv_data)
  575. {
  576. return 0;
  577. }
  578. struct fh_board_ops mmc_driver_ops =
  579. {
  580. .probe = fh_mmc_probe,
  581. .exit = fh_mmc_exit,
  582. };
  583. void rt_hw_mmc_init(void)
  584. {
  585. PRINT_MMC_DBG("%s start\n", __func__);
  586. fh_board_driver_register("mmc", &mmc_driver_ops);
  587. PRINT_MMC_DBG("%s end\n", __func__);
  588. }