wm_sdio_host.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. #include "wm_sdio_host.h"
  2. #include "wm_debug.h"
  3. #include "wm_mem.h"
  4. #include "wm_dma.h"
  5. #include "wm_cpu.h"
  6. #define TEST_DEBUG_EN 0
  7. #if TEST_DEBUG_EN
  8. #define TEST_DEBUG(fmt, ...) printf("%s: "fmt, __func__, ##__VA_ARGS__)
  9. #else
  10. #define TEST_DEBUG(fmt, ...)
  11. #endif
  12. SD_CardInfo_t SDCardInfo;
  13. extern void delay_cnt(int count);
  14. static void sh_dumpBuffer(char *name, char* buffer, int len)
  15. {
  16. #if TEST_DEBUG_EN
  17. int i = 0;
  18. printf("%s:\n", name);
  19. for(; i < len; i++)
  20. {
  21. printf("%02X, ", buffer[i]);
  22. if((i + 1) % 16 == 0)
  23. {
  24. printf("\n");
  25. }
  26. }
  27. printf("\n");
  28. #endif
  29. }
  30. void wm_sdh_send_cmd(uint8_t cmdnum, uint32_t cmdarg, uint8_t mmcio)
  31. {
  32. SDIO_HOST->CMD_BUF[4] = cmdnum | 0x40;
  33. SDIO_HOST->CMD_BUF[3] = (cmdarg >> 24) & 0xFF;
  34. SDIO_HOST->CMD_BUF[2] = (cmdarg >> 16) & 0xFF;
  35. SDIO_HOST->CMD_BUF[1] = (cmdarg >> 8) & 0xFF;
  36. SDIO_HOST->CMD_BUF[0] = (cmdarg & 0xFF);
  37. SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly
  38. SDIO_HOST->MMC_IO = mmcio;
  39. }
  40. void wm_sdh_get_response(uint32_t * respbuf, uint32_t buflen)
  41. {
  42. int i = 0;
  43. for(i = 0; i < buflen; i++)
  44. {
  45. respbuf[i] = (SDIO_HOST->CMD_BUF[i*4 + 3] << 24) | (SDIO_HOST->CMD_BUF[i*4 + 2] << 16) | (SDIO_HOST->CMD_BUF[i*4 + 1] << 8) | (SDIO_HOST->CMD_BUF[i*4]);
  46. }
  47. }
  48. static int sm_sdh_wait_interrupt(uint8_t srcbit, int timeout)
  49. {
  50. int ret = 0;
  51. unsigned int tmp = (1 << srcbit);
  52. volatile int vtimeout= timeout;
  53. if(vtimeout == -1) {
  54. vtimeout = 0x7FFFF;
  55. }
  56. while(1)
  57. {
  58. if(SDIO_HOST->MMC_INT_SRC & tmp)
  59. {
  60. SDIO_HOST->MMC_INT_SRC |= tmp;
  61. if(SDIO_HOST->MMC_INT_SRC)
  62. {
  63. TEST_DEBUG("Err Int 0x%x\n", SDIO_HOST->MMC_INT_SRC);
  64. }
  65. break;
  66. }
  67. vtimeout--;
  68. if((vtimeout == 0) || (vtimeout < 0))
  69. {
  70. ret = 1; //timeout, err
  71. break;
  72. }
  73. delay_cnt(1);
  74. }
  75. return ret;
  76. }
  77. int wm_sdh_config(void)
  78. {
  79. tls_sys_clk sysclk;
  80. tls_sys_clk_get(&sysclk);
  81. SDIO_HOST->MMC_CARDSEL = 0xC0 | (sysclk.cpuclk / 2 - 1);//0xd3; //enable module, enable mmcclk
  82. SDIO_HOST->MMC_CTL = 0x13;//0xC3; //4bits, low speed, 1/4 divider, auto transfer, mmc mode.
  83. SDIO_HOST->MMC_INT_MASK = 0x100; //unmask sdio data interrupt.
  84. SDIO_HOST->MMC_CRCCTL = 0xC0; //
  85. SDIO_HOST->MMC_TIMEOUTCNT = 0xff;
  86. SDIO_HOST->MMC_IO_MBCTL |= 0xf0;
  87. return 0;
  88. }
  89. int wm_sd_card_initialize(uint32_t *rca)
  90. {
  91. int ret = -1;
  92. uint32_t respCmd[4];
  93. int recnt = 5;
  94. wm_sdh_config();
  95. //======================================================
  96. // set up
  97. // Test: Init sequence, With response check
  98. // CMD 0 Reset Card
  99. // CMD 8 Get voltage (Only 2.0 Card response to this)
  100. // CMD55 Indicate Next Command are Application specific
  101. // ACMD41 Get Voltage windows
  102. // CMD 2 CID reg
  103. // CMD 3 Get RCA.
  104. //======================================================
  105. begin:
  106. //Send CMD0 + 8 null clock to reset and stablize
  107. for (int i = 0; i < 7 - recnt; i++)
  108. {
  109. wm_sdh_send_cmd(0, 0, 0x84);
  110. sm_sdh_wait_interrupt(0, -1);
  111. }
  112. delay_cnt(1000);
  113. wm_sdh_send_cmd(8, 0x1AA, 0xC4); //Send CMD8
  114. sm_sdh_wait_interrupt(0, -1);
  115. wm_sdh_get_response(respCmd, 2);
  116. sh_dumpBuffer("CMD8 respCmd", (char *)respCmd, 5);
  117. if(respCmd[0] != 0x1AA || (respCmd[1] & 0xFF) != 8)
  118. {
  119. TEST_DEBUG("CMD8 Error\n");
  120. if(recnt--)
  121. goto begin;
  122. goto end;
  123. }
  124. while(1)
  125. {
  126. wm_sdh_send_cmd(55, 0, 0xC4); //Send CMD55
  127. sm_sdh_wait_interrupt(0, -1);
  128. wm_sdh_get_response(respCmd, 2);
  129. sh_dumpBuffer("CMD55 respCmd", (char *)respCmd, 5);
  130. if((respCmd[1] & 0xFF) != 55)
  131. goto end;
  132. wm_sdh_send_cmd(41, 0xC0100000, 0xC4); //Send ACMD41
  133. sm_sdh_wait_interrupt(0, -1);
  134. sm_sdh_wait_interrupt(3, 1000); //由于sd规范中,Acmd41返回的crc永远是11111,也就是应该忽略crc;这里的crc错误应该忽略。
  135. wm_sdh_get_response(respCmd, 2);
  136. sh_dumpBuffer("ACMD41 respCmd", (char *)respCmd, 5);
  137. if((respCmd[1] & 0xFF) != 0x3F) //sd规范定义固定为0x3F,所以导致crc错误
  138. goto end;
  139. if(respCmd[0] >> 31 & 0x1)
  140. {
  141. TEST_DEBUG("card is ready\n");
  142. break;
  143. }
  144. }
  145. wm_sdh_send_cmd(2, 0, 0xD4); //Send CMD2
  146. sm_sdh_wait_interrupt(0, -1);
  147. sm_sdh_wait_interrupt(3, 1000);
  148. wm_sdh_get_response(respCmd, 4);
  149. sh_dumpBuffer("CMD2 respCmd", (char *)respCmd, 16);
  150. if((respCmd[3] >> 24 & 0xFF) != 0x3F) //sd规范定义固定为0x3F,所以导致crc错误
  151. goto end;
  152. wm_sdh_send_cmd(3, 0, 0xC4); //Send CMD3
  153. sm_sdh_wait_interrupt(0, -1);
  154. wm_sdh_get_response(respCmd, 2);
  155. sh_dumpBuffer("CMD3 respCmd", (char *)respCmd, 5);
  156. if((respCmd[1] & 0xFF) != 3)
  157. goto end;
  158. *rca = respCmd[0] >> 16;
  159. TEST_DEBUG("RCA = %x\n", *rca);
  160. ret = 0;
  161. end:
  162. return ret;
  163. }
  164. static uint32_t SD_GetCapacity(uint8_t *csd, SD_CardInfo_t *SDCardInfo)
  165. {
  166. uint32_t Capacity;
  167. uint16_t n;
  168. uint32_t csize;
  169. if((csd[0]&0xC0)==0x40)//判断bit126是否为1
  170. {
  171. SDCardInfo->CSDVer = 2;
  172. csize = csd[9] + ((uint32_t)csd[8] << 8) + ((uint32_t)(csd[7] & 63) << 16) + 1;
  173. Capacity = csize << 9;
  174. SDCardInfo->CardCapacity = (long long)Capacity*1024;
  175. SDCardInfo->CardBlockSize = 512;
  176. }
  177. else
  178. {
  179. SDCardInfo->CSDVer = 1;
  180. n = (csd[5] & 0x0F) + ((csd[10] & 0x80) >> 7) + ((csd[9] & 0x03) << 1) + 2;
  181. csize = (csd[8] >> 6) + ((uint16_t)csd[7] << 2) + ((uint16_t)(csd[6] & 0x03) << 10) + 1;
  182. Capacity = (uint32_t)csize << (n - 10);
  183. SDCardInfo->CardCapacity = (long long)Capacity*1024;
  184. SDCardInfo->CardBlockSize = 1<<(csd[5] & 0x0F);
  185. }
  186. return Capacity;
  187. }
  188. int wm_sd_card_query_csd(uint32_t rca)
  189. {
  190. int ret = -1, i;
  191. uint32_t respCmd[4];
  192. char adjustResp[16];
  193. wm_sdh_send_cmd(9, rca<<16, 0x54); //Send CMD9
  194. sm_sdh_wait_interrupt(0, -1);
  195. sm_sdh_wait_interrupt(3, 1000);
  196. wm_sdh_get_response(respCmd, 4);
  197. for(i=0; i<16; i++) adjustResp[15-i] = SDIO_HOST->CMD_BUF[i];
  198. SD_GetCapacity((uint8_t*)&adjustResp[1], &SDCardInfo);
  199. sh_dumpBuffer("CMD9 respCmd", adjustResp, 16);
  200. if((respCmd[3] >> 24 & 0xFF) != 0x3F) //sd规范定义固定为0x3F,所以导致crc错误
  201. goto end;
  202. ret = 0;
  203. end:
  204. return ret;
  205. }
  206. int wm_sd_card_set_blocklen(uint32_t blocklen)
  207. {
  208. int ret = -1;
  209. uint32_t respCmd[2];
  210. wm_sdh_send_cmd(16, blocklen, 0xC4); //Send CMD16
  211. sm_sdh_wait_interrupt(0, -1);
  212. wm_sdh_get_response(respCmd, 2);
  213. sh_dumpBuffer("CMD16 respCmd", (char *)respCmd, 5);
  214. if((respCmd[1] & 0xFF) != 16)
  215. goto end;
  216. ret = 0;
  217. end:
  218. return ret;
  219. }
  220. int wm_sd_card_select(uint32_t rca)
  221. {
  222. int ret = -1;
  223. uint32_t respCmd[2];
  224. wm_sdh_send_cmd(7, rca<<16, 0xC4); //Send CMD7
  225. sm_sdh_wait_interrupt(0, -1);
  226. wm_sdh_get_response(respCmd, 2);
  227. sh_dumpBuffer("CMD7 respCmd", (char *)respCmd, 5);
  228. if((respCmd[1] & 0xFF) != 7)
  229. goto end;
  230. ret = 0;
  231. end:
  232. return ret;
  233. }
  234. void wm_sd_card_deselect()
  235. {
  236. wm_sdh_send_cmd(7, 0, 0x84); //Send CMD7
  237. sm_sdh_wait_interrupt(0, -1);
  238. }
  239. int wm_sd_card_query_status(uint32_t rca, uint32_t *respCmd0)
  240. {
  241. int ret = -1;
  242. #if TEST_DEBUG_EN
  243. uint8_t current_state = 0;
  244. uint8_t error_state = 0;
  245. #endif
  246. uint32_t respCmd[2];
  247. wm_sdh_send_cmd(13, rca<<16, 0xC4); //Send CMD13
  248. sm_sdh_wait_interrupt(0, -1);
  249. wm_sdh_get_response(respCmd, 2);
  250. sh_dumpBuffer("CMD13 respCmd", (char *)respCmd, 5);
  251. if((respCmd[1] & 0xFF) != 13)
  252. goto end;
  253. if(respCmd0)
  254. {
  255. *respCmd0 = respCmd[0];
  256. }
  257. #if TEST_DEBUG_EN
  258. current_state = respCmd[0] >> 9 & 0xF;
  259. error_state = respCmd[0] >> 19 & 0x1;
  260. TEST_DEBUG("current_state %d, error_state %d\n",current_state,error_state);
  261. #endif
  262. ret = 0;
  263. end:
  264. return ret;
  265. }
  266. /*
  267. * speed_mode: 0: low speed; 1: high speed;
  268. * */
  269. int wm_sd_card_switch_func(uint8_t speed_mode)
  270. {
  271. int ret = -1;
  272. int i;
  273. uint32_t respCmd[2];
  274. wm_sdh_send_cmd(6, 0x00fffff1, 0xC4); //Send CMD6
  275. sm_sdh_wait_interrupt(0, -1);
  276. wm_sdh_get_response(respCmd, 2);
  277. sh_dumpBuffer("CMD6 respCmd", (char *)respCmd, 5);
  278. if((respCmd[1] & 0xFF) != 6)
  279. goto end;
  280. SDIO_HOST->BUF_CTL = 0x4020; //disable dma, read sd card
  281. SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly
  282. SDIO_HOST->MMC_IO = 0x83; //!!!read data, auto transfer
  283. sm_sdh_wait_interrupt(1, -1);
  284. TEST_DEBUG("read complete\n");
  285. for(i = 0; i < 128; i++)
  286. {
  287. respCmd[0] = SDIO_HOST->DATA_BUF[0];
  288. if(i == 4)
  289. {
  290. respCmd[1] = respCmd[0];
  291. }
  292. printf("0x%x, ", respCmd[0]);
  293. if(i % 4 == 3)
  294. {
  295. printf("\n");
  296. }
  297. }
  298. TEST_DEBUG("the value of byte 17~20 is 0x%x\n", respCmd[1]);
  299. if(respCmd[1] & 0xF) //support high speed
  300. {
  301. wm_sdh_send_cmd(6, 0x80fffff0 | speed_mode, 0xC4); //Send CMD6
  302. sm_sdh_wait_interrupt(0, -1);
  303. wm_sdh_get_response(respCmd, 2);
  304. sh_dumpBuffer("CMD6 respCmd", (char *)respCmd, 5);
  305. if((respCmd[1] & 0xFF) != 6)
  306. goto end;
  307. SDIO_HOST->BUF_CTL = 0x4020; //disable dma, read sd card
  308. SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly
  309. SDIO_HOST->MMC_IO = 0x83; //!!!read data, auto transfer
  310. sm_sdh_wait_interrupt(1, -1);
  311. TEST_DEBUG("read complete\n");
  312. for(i = 0; i < 128; i++)
  313. {
  314. respCmd[0] = SDIO_HOST->DATA_BUF[0];
  315. if(i == 4)
  316. {
  317. respCmd[1] = respCmd[0];
  318. }
  319. printf("0x%x, ", respCmd[0]);
  320. if(i % 4 == 3)
  321. {
  322. printf("\n");
  323. }
  324. }
  325. TEST_DEBUG("the value of byte 17~20 is 0x%x\n", respCmd[1]);
  326. if((respCmd[1] & 0xF) == speed_mode)
  327. {
  328. if(speed_mode == 1)
  329. {
  330. SDIO_HOST->MMC_CTL |= (1 << 6);
  331. }
  332. else
  333. {
  334. SDIO_HOST->MMC_CTL &= ~(1 << 6);
  335. }
  336. TEST_DEBUG("switch speed_mode %d success\n", speed_mode);
  337. }
  338. }
  339. ret = 0;
  340. end:
  341. return ret;
  342. }
  343. /*
  344. * bus_width: 0:1bit; 2:4bits
  345. * */
  346. int wm_sd_card_set_bus_width(uint32_t rca, uint8_t bus_width)
  347. {
  348. int ret = -1;
  349. uint32_t respCmd[2];
  350. if(bus_width != 0 && bus_width != 2)
  351. {
  352. TEST_DEBUG("bus width parameter error\n");
  353. goto end;
  354. }
  355. if(bus_width == 2)
  356. {
  357. SDIO_HOST->MMC_CTL |= (1 << 7);
  358. }
  359. else
  360. {
  361. SDIO_HOST->MMC_CTL &= ~(1 << 7);
  362. }
  363. wm_sdh_send_cmd(55, rca<<16, 0xC4); //Send CMD55
  364. sm_sdh_wait_interrupt(0, -1);
  365. wm_sdh_get_response(respCmd, 2);
  366. sh_dumpBuffer("CMD55 respCmd", (char *)respCmd, 5);
  367. if((respCmd[1] & 0xFF) != 55)
  368. goto end;
  369. wm_sdh_send_cmd(6, bus_width, 0xC4); //Send ACMD6
  370. sm_sdh_wait_interrupt(0, -1);
  371. wm_sdh_get_response(respCmd, 2);
  372. sh_dumpBuffer("ACMD6 respCmd", (char *)respCmd, 5);
  373. if((respCmd[1] & 0xFF) != 6)
  374. goto end;
  375. ret = 0;
  376. end:
  377. return ret;
  378. }
  379. int wm_sd_card_stop_trans(void)
  380. {
  381. int ret = -1;
  382. uint32_t respCmd[2];
  383. wm_sdh_send_cmd(12, 0, 0xC4); //Send CMD12
  384. ret = sm_sdh_wait_interrupt(0, -1);
  385. if(ret)
  386. goto end;
  387. wm_sdh_get_response(respCmd, 2);
  388. sh_dumpBuffer("CMD12 respCmd", (char *)respCmd, 5);
  389. if((respCmd[1] & 0xFF) != 12)
  390. goto end;
  391. ret = 0;
  392. end:
  393. return ret;
  394. }
  395. static void sdio_host_reset(void)
  396. {
  397. tls_bitband_write(HR_CLK_RST_CTL, 27, 0);
  398. delay_cnt(1000);
  399. tls_bitband_write(HR_CLK_RST_CTL, 27, 1);
  400. while(tls_bitband_read(HR_CLK_RST_CTL, 27) == 0);
  401. }
  402. int sdh_card_init(uint32_t *rca_ref)
  403. {
  404. int ret = -1;
  405. uint32_t rca = 0;
  406. sdio_host_reset();
  407. ret = wm_sd_card_initialize(&rca);
  408. if(ret)
  409. goto end;
  410. SDCardInfo.RCA = (u16)(rca & 0xFFFF);
  411. ret = wm_sd_card_query_csd(rca);
  412. if(ret)
  413. goto end;
  414. ret = wm_sd_card_query_status(rca, NULL);
  415. if(ret)
  416. goto end;
  417. ret = wm_sd_card_select(rca);
  418. if(ret)
  419. goto end;
  420. ret = wm_sd_card_query_status(rca, NULL);
  421. if(ret)
  422. goto end;
  423. *rca_ref = rca;
  424. SDIO_HOST->MMC_CTL = 0xD3;
  425. ret = 0;
  426. end:
  427. TEST_DEBUG("ret %d\n", ret);
  428. return ret;
  429. }
  430. /*buf's len must >= 512*/
  431. int wm_sd_card_block_read(uint32_t rca, uint32_t sd_addr, char *buf)
  432. {
  433. int ret = -1;
  434. int i;
  435. uint32_t respCmd[2];
  436. wm_sdh_send_cmd(17, sd_addr, 0x44); //Send CMD17
  437. sm_sdh_wait_interrupt(0, -1);
  438. wm_sdh_get_response(respCmd, 2);
  439. sh_dumpBuffer("CMD17 respCmd", (char *)respCmd, 5);
  440. if((respCmd[1] & 0xFF) != 17)
  441. goto end;
  442. SDIO_HOST->BUF_CTL = 0x4020; //disable dma, read sd card
  443. SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly
  444. SDIO_HOST->MMC_IO = 0x3; //!!!read data, auto transfer
  445. sm_sdh_wait_interrupt(1, -1);
  446. TEST_DEBUG("read complete\n");
  447. for(i = 0; i < 128; i++)
  448. {
  449. *((uint32_t*)(buf + 4*i)) = SDIO_HOST->DATA_BUF[0];
  450. }
  451. ret = 0;
  452. end:
  453. return ret;
  454. }
  455. /*buf's len must be 512*/
  456. int wm_sd_card_block_write(uint32_t rca, uint32_t sd_addr, char *buf)
  457. {
  458. int i;
  459. int ret = -1;
  460. uint32_t respCmd[2];
  461. uint8_t current_state = 0;
  462. uint8_t error_state = 0;
  463. wm_sdh_send_cmd(24, sd_addr, 0x44); //Send CMD24
  464. sm_sdh_wait_interrupt(0, -1);
  465. wm_sdh_get_response(respCmd, 2);
  466. sh_dumpBuffer("CMD24 respCmd", (char *)respCmd, 5);
  467. if((respCmd[1] & 0xFF) != 24)
  468. goto end;
  469. SDIO_HOST->BUF_CTL = 0x4820; //disable dma, write sd card
  470. for(i = 0; i < 128; i++)
  471. {
  472. SDIO_HOST->DATA_BUF[i] = *((uint32*)(buf + 4*i));
  473. }
  474. SDIO_HOST->MMC_BYTECNTL = 512;
  475. SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly
  476. SDIO_HOST->MMC_IO = 0x1; //!!!write data, auto transfer
  477. sm_sdh_wait_interrupt(1, -1);
  478. while(true)
  479. {
  480. ret = wm_sd_card_query_status(rca, &respCmd[0]);
  481. if(ret)
  482. goto end;
  483. current_state = respCmd[0] >> 9 & 0xF;
  484. error_state = respCmd[0] >> 19 & 0x1;
  485. if(current_state == 4) //tran
  486. {
  487. break;
  488. }
  489. if(error_state)
  490. {
  491. ret = -1;
  492. goto end;
  493. }
  494. }
  495. ret = 0;
  496. end:
  497. TEST_DEBUG("write complete err %d\n", ret);
  498. return ret;
  499. }
  500. /* dir: 1, write; 0, read*/
  501. int wm_sd_card_dma_config(u32*mbuf,u32 bufsize,u8 dir)
  502. {
  503. int ch;
  504. u32 addr_inc = 0;
  505. ch = tls_dma_request(0, NULL);
  506. DMA_CHNLCTRL_REG(ch) = DMA_CHNL_CTRL_CHNL_OFF;
  507. if(dir)
  508. {
  509. DMA_SRCADDR_REG(ch) = (unsigned int)mbuf;
  510. DMA_DESTADDR_REG(ch) = (unsigned int)SDIO_HOST->DATA_BUF;
  511. addr_inc = (1 << 1);
  512. }
  513. else
  514. {
  515. DMA_SRCADDR_REG(ch) = (unsigned int)SDIO_HOST->DATA_BUF;
  516. DMA_DESTADDR_REG(ch) = (unsigned int)mbuf;
  517. addr_inc = (1 << 3);
  518. }
  519. DMA_CTRL_REG(ch) = addr_inc | (2 << 5) | (bufsize << 8);
  520. DMA_MODE_REG(ch) = DMA_MODE_SEL_SDIOHOST | DMA_MODE_HARD_MODE;
  521. DMA_CHNLCTRL_REG(ch) = DMA_CHNL_CTRL_CHNL_ON;
  522. return ch;
  523. }
  524. static int wm_sdh_wait_blocks_done(void)
  525. {
  526. int ret = 0;
  527. uint32_t timeout = 0x7FFFF * 8;
  528. while(1)
  529. {
  530. if((SDIO_HOST->MMC_IO_MBCTL & 0x01) == 0x00)
  531. {
  532. break;
  533. }
  534. if(timeout == 0)
  535. {
  536. ret = -1;
  537. tls_os_time_delay(HZ);
  538. }
  539. else
  540. {
  541. delay_cnt(1);
  542. timeout--;
  543. }
  544. }
  545. return ret;
  546. }
  547. /*read blocks by dma
  548. * buflen must be integer multiple of 512
  549. * */
  550. int wm_sd_card_blocks_read(uint32_t rca, uint32_t sd_addr, char *buf, uint32_t buflen)
  551. {
  552. int ret = -1, dma_channel = 0xFF, retresp = -100;
  553. uint32_t respCmd[2];
  554. int block_cnt = buflen/512;
  555. uint8_t current_state = 0;
  556. uint8_t error_state = 0;
  557. wm_sdh_send_cmd(18, sd_addr, 0x44); //Send CMD18
  558. sm_sdh_wait_interrupt(0, -1);
  559. wm_sdh_get_response(respCmd, 2);
  560. sh_dumpBuffer("CMD18 respCmd", (char *)respCmd, 5);
  561. if((respCmd[1] & 0xFF) != 18)
  562. goto end;
  563. SDIO_HOST->BUF_CTL = 0x4000; //disable dma,
  564. dma_channel = wm_sd_card_dma_config((u32*)buf, 512*block_cnt, 0);
  565. SDIO_HOST->BUF_CTL = 0x404; //enable dma, read sd card
  566. SDIO_HOST->MMC_BLOCKCNT = block_cnt;
  567. SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly
  568. SDIO_HOST->MMC_IO_MBCTL = 0xa3; //read data, enable multi blocks data transfer
  569. // sm_sdh_wait_interrupt(1, -1);
  570. ret = wm_sdh_wait_blocks_done();
  571. if(ret)
  572. {
  573. TEST_DEBUG("wm_sd_card_blocks_read: timeout error\n");
  574. goto end;
  575. }
  576. TEST_DEBUG("read complete\n");
  577. ret = wm_sd_card_stop_trans();
  578. if(ret)
  579. goto end;
  580. /*waiting for card to trans state*/
  581. do
  582. {
  583. ret = wm_sd_card_query_status(rca, &respCmd[0]);
  584. if(ret)
  585. break;
  586. current_state = respCmd[0] >> 9 & 0xF;
  587. error_state = respCmd[0] >> 19 & 0x1;
  588. if(error_state)
  589. {
  590. ret = -1;
  591. break;
  592. }
  593. }while(current_state != 4);
  594. if (ret)
  595. {
  596. TEST_DEBUG("mr blocks:%x\r\n", error_state);
  597. goto end;
  598. }
  599. ret = 0;
  600. end:
  601. if (ret)
  602. {
  603. wm_sd_card_stop_trans();
  604. do
  605. {
  606. retresp = wm_sd_card_query_status(rca, &respCmd[0]);
  607. if(retresp)
  608. break;
  609. current_state = respCmd[0] >> 9 & 0xF;
  610. error_state = respCmd[0] >> 19 & 0x1;
  611. if(error_state)
  612. {
  613. ret = -1;
  614. break;
  615. }
  616. }while(current_state != 4);
  617. }
  618. tls_dma_free(dma_channel);
  619. return ret;
  620. }
  621. /*write blocks by dma
  622. * buflen must be integer multiple of 512
  623. * */
  624. int wm_sd_card_blocks_write(uint32_t rca, uint32_t sd_addr, char *buf, uint32_t buflen)
  625. {
  626. int dma_channel = 0xFF;
  627. int ret = -1, retresp = -100;
  628. uint32_t respCmd[2];
  629. int block_cnt = buflen/512;
  630. uint8_t current_state = 0;
  631. uint8_t error_state = 0;
  632. wm_sdh_send_cmd(25, sd_addr, 0x44); //Send CMD25
  633. ret = sm_sdh_wait_interrupt(0, -1);
  634. if(ret)
  635. goto end;
  636. wm_sdh_get_response(respCmd, 2);
  637. sh_dumpBuffer("CMD25 respCmd", (char *)respCmd, 5);
  638. if((respCmd[1] & 0xFF) != 25) {
  639. ret = -1;
  640. goto end;
  641. }
  642. SDIO_HOST->BUF_CTL = 0x4000; //disable dma,
  643. dma_channel = wm_sd_card_dma_config((u32*)buf, 512*block_cnt, 1);
  644. SDIO_HOST->BUF_CTL = 0xC20; //enable dma, write sd card
  645. SDIO_HOST->MMC_BLOCKCNT = block_cnt;
  646. SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly
  647. SDIO_HOST->MMC_IO_MBCTL = 0xa1;////write data, enable multi blocks data transfer
  648. #if 0
  649. ret = sm_sdh_wait_interrupt(1, -1);
  650. if(ret)
  651. goto end;
  652. #endif
  653. ret = wm_sdh_wait_blocks_done();
  654. if(ret)
  655. goto end;
  656. ret = wm_sd_card_stop_trans();
  657. if(ret)
  658. goto end;
  659. /*waiting for card to trans state*/
  660. do
  661. {
  662. ret = wm_sd_card_query_status(rca, &respCmd[0]);
  663. if(ret)
  664. break;
  665. current_state = respCmd[0] >> 9 & 0xF;
  666. error_state = respCmd[0] >> 19 & 0x1;
  667. if(error_state)
  668. {
  669. ret = -1;
  670. break;
  671. }
  672. }while(current_state != 4);
  673. if (ret)
  674. {
  675. TEST_DEBUG("mw blocks:%x\r\n", error_state);
  676. goto end;
  677. }
  678. TEST_DEBUG("write complete\n");
  679. ret = 0;
  680. end:
  681. if (ret)
  682. {
  683. wm_sd_card_stop_trans();
  684. do
  685. {
  686. retresp = wm_sd_card_query_status(rca, &respCmd[0]);
  687. if(retresp)
  688. break;
  689. current_state = respCmd[0] >> 9 & 0xF;
  690. error_state = respCmd[0] >> 19 & 0x1;
  691. if(error_state)
  692. {
  693. ret = -1;
  694. break;
  695. }
  696. }while(current_state != 4);
  697. }
  698. tls_dma_free(dma_channel);
  699. return ret;
  700. }