wm_sdio_host.c 21 KB

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