drv_sdio.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. /*
  2. * File : drv_sdio.c
  3. * Copyright (c) 2006-2021, RT-Thread Development Team
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2019-07-29 zdzn first version
  10. */
  11. #include "drv_sdio.h"
  12. #include "raspi.h"
  13. static rt_uint32_t sdCommandTable[] = {
  14. SD_CMD_INDEX(0),
  15. SD_CMD_RESERVED(1),
  16. SD_CMD_INDEX(2) | SD_RESP_R2,
  17. SD_CMD_INDEX(3) | SD_RESP_R1,
  18. SD_CMD_INDEX(4),
  19. SD_CMD_RESERVED(5), //SD_CMD_INDEX(5) | SD_RESP_R4,
  20. SD_CMD_INDEX(6) | SD_RESP_R1,
  21. SD_CMD_INDEX(7) | SD_RESP_R1b,
  22. SD_CMD_INDEX(8) | SD_RESP_R1,
  23. SD_CMD_INDEX(9) | SD_RESP_R2,
  24. SD_CMD_INDEX(10) | SD_RESP_R2,
  25. SD_CMD_INDEX(11) | SD_RESP_R1,
  26. SD_CMD_INDEX(12) | SD_RESP_R1b | SD_CMD_TYPE_ABORT,
  27. SD_CMD_INDEX(13) | SD_RESP_R1,
  28. SD_CMD_RESERVED(14),
  29. SD_CMD_INDEX(15),
  30. SD_CMD_INDEX(16) | SD_RESP_R1,
  31. SD_CMD_INDEX(17) | SD_RESP_R1 | SD_DATA_READ,
  32. SD_CMD_INDEX(18) | SD_RESP_R1 | SD_DATA_READ | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
  33. SD_CMD_INDEX(19) | SD_RESP_R1 | SD_DATA_READ,
  34. SD_CMD_INDEX(20) | SD_RESP_R1b,
  35. SD_CMD_RESERVED(21),
  36. SD_CMD_RESERVED(22),
  37. SD_CMD_INDEX(23) | SD_RESP_R1,
  38. SD_CMD_INDEX(24) | SD_RESP_R1 | SD_DATA_WRITE,
  39. SD_CMD_INDEX(25) | SD_RESP_R1 | SD_DATA_WRITE | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
  40. SD_CMD_INDEX(26) | SD_RESP_R1 | SD_DATA_WRITE, //add
  41. SD_CMD_INDEX(27) | SD_RESP_R1 | SD_DATA_WRITE,
  42. SD_CMD_INDEX(28) | SD_RESP_R1b,
  43. SD_CMD_INDEX(29) | SD_RESP_R1b,
  44. SD_CMD_INDEX(30) | SD_RESP_R1 | SD_DATA_READ,
  45. SD_CMD_RESERVED(31),
  46. SD_CMD_INDEX(32) | SD_RESP_R1,
  47. SD_CMD_INDEX(33) | SD_RESP_R1,
  48. SD_CMD_RESERVED(34),
  49. SD_CMD_INDEX(35) | SD_RESP_R1, //add
  50. SD_CMD_INDEX(36) | SD_RESP_R1, //add
  51. SD_CMD_RESERVED(37),
  52. SD_CMD_INDEX(38) | SD_RESP_R1b,
  53. SD_CMD_INDEX(39) | SD_RESP_R4, //add
  54. SD_CMD_INDEX(40) | SD_RESP_R5, //add
  55. SD_CMD_INDEX(41) | SD_RESP_R3, //add, mov from harbote
  56. SD_CMD_RESERVED(42) | SD_RESP_R1,
  57. SD_CMD_RESERVED(43),
  58. SD_CMD_RESERVED(44),
  59. SD_CMD_RESERVED(45),
  60. SD_CMD_RESERVED(46),
  61. SD_CMD_RESERVED(47),
  62. SD_CMD_RESERVED(48),
  63. SD_CMD_RESERVED(49),
  64. SD_CMD_RESERVED(50),
  65. SD_CMD_INDEX(51) | SD_RESP_R1 | SD_DATA_READ,
  66. SD_CMD_RESERVED(52),
  67. SD_CMD_RESERVED(53),
  68. SD_CMD_RESERVED(54),
  69. SD_CMD_INDEX(55) | SD_RESP_R3,
  70. SD_CMD_INDEX(56) | SD_RESP_R1 | SD_CMD_ISDATA,
  71. SD_CMD_RESERVED(57),
  72. SD_CMD_RESERVED(58),
  73. SD_CMD_RESERVED(59),
  74. SD_CMD_RESERVED(60),
  75. SD_CMD_RESERVED(61),
  76. SD_CMD_RESERVED(62),
  77. SD_CMD_RESERVED(63)
  78. };
  79. static inline rt_uint32_t read32(rt_uint32_t addr)
  80. {
  81. return (*((volatile unsigned int*)((rt_uint64_t)addr)));
  82. //return (*((volatile rt_uint64_t *)(((long))addr)));
  83. }
  84. static inline void write32(rt_uint32_t addr, rt_uint32_t value)
  85. {
  86. (*((volatile unsigned int*)((rt_uint64_t)addr))) = value;
  87. //*((volatile rt_uint64_t *)(((long))addr)) = value;
  88. }
  89. rt_err_t sd_int(struct sdhci_pdata_t * pdat, unsigned int mask)
  90. {
  91. unsigned int r;
  92. unsigned int m = mask | INT_ERROR_MASK;
  93. int cnt = 1000000;
  94. while (!(read32(pdat->virt + EMMC_INTERRUPT) & (m | INT_ERROR_MASK)) && cnt--)
  95. DELAY_MICROS(1);
  96. r = read32(pdat->virt + EMMC_INTERRUPT);
  97. if (cnt <= 0 || (r & INT_CMD_TIMEOUT) || (r & INT_DATA_TIMEOUT))
  98. {
  99. write32(pdat->virt + EMMC_INTERRUPT, r);
  100. //qemu maybe can not use sdcard
  101. //rt_kprintf("send cmd/data timeout wait for %x int: %x, status: %x\n",mask, r, read32(pdat->virt + EMMC_STATUS));
  102. //return -RT_ETIMEOUT;
  103. }
  104. else if (r & INT_ERROR_MASK)
  105. {
  106. write32(pdat->virt + EMMC_INTERRUPT, r);
  107. rt_kprintf("send cmd/data error %x -> %x\n",r, read32(pdat->virt + EMMC_INTERRUPT));
  108. return -RT_ERROR;
  109. }
  110. write32(pdat->virt + EMMC_INTERRUPT, mask);
  111. return RT_EOK;
  112. }
  113. rt_err_t sd_status(struct sdhci_pdata_t * pdat, unsigned int mask)
  114. {
  115. int cnt = 500000;
  116. while ((read32(pdat->virt + EMMC_STATUS) & mask) && !(read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK) && cnt--)
  117. DELAY_MICROS(1);
  118. if (cnt <= 0)
  119. {
  120. return -RT_ETIMEOUT;
  121. }
  122. else if (read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK)
  123. {
  124. return -RT_ERROR;
  125. }
  126. return RT_EOK;
  127. }
  128. static rt_err_t raspi_transfer_command(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd)
  129. {
  130. rt_uint32_t cmdidx;
  131. rt_err_t ret = RT_EOK;
  132. ret = sd_status(pdat, SR_CMD_INHIBIT);
  133. if (ret)
  134. {
  135. rt_kprintf("ERROR: EMMC busy %d\n", ret);
  136. return ret;
  137. }
  138. cmdidx = sdCommandTable[cmd->cmdidx];
  139. if (cmdidx == 0xFFFFFFFF)
  140. return -RT_EINVAL;
  141. if (cmd->datarw == DATA_READ)
  142. cmdidx |= SD_DATA_READ;
  143. if (cmd->datarw == DATA_WRITE)
  144. cmdidx |= SD_DATA_WRITE;
  145. mmcsd_dbg("transfer cmd %x(%d) %x %x\n", cmdidx, cmd->cmdidx, cmd->cmdarg, read32(pdat->virt + EMMC_INTERRUPT));
  146. write32(pdat->virt + EMMC_INTERRUPT,read32(pdat->virt + EMMC_INTERRUPT));
  147. write32(pdat->virt + EMMC_ARG1, cmd->cmdarg);
  148. write32(pdat->virt + EMMC_CMDTM, cmdidx);
  149. if (cmd->cmdidx == SD_APP_OP_COND)
  150. DELAY_MICROS(1000);
  151. else if ((cmd->cmdidx == SD_SEND_IF_COND) || (cmd->cmdidx == APP_CMD))
  152. DELAY_MICROS(100);
  153. ret = sd_int(pdat, INT_CMD_DONE);
  154. if (ret)
  155. {
  156. return ret;
  157. }
  158. if (cmd->resptype & RESP_MASK)
  159. {
  160. if (cmd->resptype & RESP_R2)
  161. {
  162. rt_uint32_t resp[4];
  163. resp[0] = read32(pdat->virt + EMMC_RESP0);
  164. resp[1] = read32(pdat->virt + EMMC_RESP1);
  165. resp[2] = read32(pdat->virt + EMMC_RESP2);
  166. resp[3] = read32(pdat->virt + EMMC_RESP3);
  167. if (cmd->resptype == RESP_R2)
  168. {
  169. cmd->response[0] = resp[3]<<8 |((resp[2]>>24)&0xff);
  170. cmd->response[1] = resp[2]<<8 |((resp[1]>>24)&0xff);
  171. cmd->response[2] = resp[1]<<8 |((resp[0]>>24)&0xff);
  172. cmd->response[3] = resp[0]<<8 ;
  173. }
  174. else
  175. {
  176. cmd->response[0] = resp[0];
  177. cmd->response[1] = resp[1];
  178. cmd->response[2] = resp[2];
  179. cmd->response[3] = resp[3];
  180. }
  181. }
  182. else
  183. cmd->response[0] = read32(pdat->virt + EMMC_RESP0);
  184. }
  185. mmcsd_dbg("response: %x: %x %x %x %x (%x, %x)\n", cmd->resptype, cmd->response[0], cmd->response[1], cmd->response[2], cmd->response[3], read32(pdat->virt + EMMC_STATUS),read32(pdat->virt + EMMC_INTERRUPT));
  186. return ret;
  187. }
  188. static rt_err_t read_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
  189. {
  190. int c = 0;
  191. rt_err_t ret;
  192. int d;
  193. while (c < blkcount)
  194. {
  195. if ((ret = sd_int(pdat, INT_READ_RDY)))
  196. {
  197. rt_kprintf("timeout happens when reading block %d\n",c);
  198. return ret;
  199. }
  200. for (d=0; d < blksize / 4; d++)
  201. if (read32(pdat->virt + EMMC_STATUS) & SR_READ_AVAILABLE)
  202. buf[d] = read32(pdat->virt + EMMC_DATA);
  203. c++;
  204. buf += blksize / 4;
  205. }
  206. return RT_EOK;
  207. }
  208. static rt_err_t write_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
  209. {
  210. int c = 0;
  211. rt_err_t ret;
  212. int d;
  213. while (c < blkcount)
  214. {
  215. if ((ret = sd_int(pdat, INT_WRITE_RDY)))
  216. {
  217. return ret;
  218. }
  219. for (d=0; d < blksize / 4; d++)
  220. write32(pdat->virt + EMMC_DATA, buf[d]);
  221. c++;
  222. buf += blksize / 4;
  223. }
  224. if ((ret = sd_int(pdat, INT_DATA_DONE)))
  225. {
  226. return ret;
  227. }
  228. return RT_EOK;
  229. }
  230. static rt_err_t raspi_transfer_data(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
  231. {
  232. rt_uint32_t dlen = (rt_uint32_t)(dat->blkcnt * dat->blksz);
  233. rt_err_t ret = sd_status(pdat, SR_DAT_INHIBIT);
  234. if (ret)
  235. {
  236. rt_kprintf("ERROR: EMMC busy\n");
  237. return ret;
  238. }
  239. if (dat->blkcnt > 1)
  240. {
  241. struct sdhci_cmd_t newcmd;
  242. newcmd.cmdidx = SET_BLOCK_COUNT;
  243. newcmd.cmdarg = dat->blkcnt;
  244. newcmd.resptype = RESP_R1;
  245. ret = raspi_transfer_command(pdat, &newcmd);
  246. if (ret) return ret;
  247. }
  248. if(dlen < 512)
  249. {
  250. write32(pdat->virt + EMMC_BLKSIZECNT, dlen | 1 << 16);
  251. }
  252. else
  253. {
  254. write32(pdat->virt + EMMC_BLKSIZECNT, 512 | (dat->blkcnt) << 16);
  255. }
  256. if (dat->flag & DATA_DIR_READ)
  257. {
  258. cmd->datarw = DATA_READ;
  259. ret = raspi_transfer_command(pdat, cmd);
  260. if (ret) return ret;
  261. mmcsd_dbg("read_block %d, %d\n", dat->blkcnt, dat->blksz );
  262. ret = read_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
  263. }
  264. else if (dat->flag & DATA_DIR_WRITE)
  265. {
  266. cmd->datarw = DATA_WRITE;
  267. ret = raspi_transfer_command(pdat, cmd);
  268. if (ret) return ret;
  269. mmcsd_dbg("write_block %d, %d", dat->blkcnt, dat->blksz );
  270. ret = write_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
  271. }
  272. return ret;
  273. }
  274. static rt_err_t sdhci_transfer(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
  275. {
  276. struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
  277. if (!dat)
  278. return raspi_transfer_command(pdat, cmd);
  279. return raspi_transfer_data(pdat, cmd, dat);
  280. }
  281. static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
  282. {
  283. struct sdhci_t *sdhci = (struct sdhci_t *)host->private_data;
  284. struct sdhci_cmd_t cmd;
  285. struct sdhci_cmd_t stop;
  286. struct sdhci_data_t dat;
  287. rt_memset(&cmd, 0, sizeof(struct sdhci_cmd_t));
  288. rt_memset(&stop, 0, sizeof(struct sdhci_cmd_t));
  289. rt_memset(&dat, 0, sizeof(struct sdhci_data_t));
  290. cmd.cmdidx = req->cmd->cmd_code;
  291. cmd.cmdarg = req->cmd->arg;
  292. cmd.resptype =resp_type(req->cmd);
  293. if (req->data)
  294. {
  295. dat.buf = (rt_uint8_t *)req->data->buf;
  296. dat.flag = req->data->flags;
  297. dat.blksz = req->data->blksize;
  298. dat.blkcnt = req->data->blks;
  299. req->cmd->err = sdhci_transfer(sdhci, &cmd, &dat);
  300. }
  301. else
  302. {
  303. req->cmd->err = sdhci_transfer(sdhci, &cmd, RT_NULL);
  304. }
  305. req->cmd->resp[3] = cmd.response[3];
  306. req->cmd->resp[2] = cmd.response[2];
  307. req->cmd->resp[1] = cmd.response[1];
  308. req->cmd->resp[0] = cmd.response[0];
  309. if (req->stop)
  310. {
  311. stop.cmdidx = req->stop->cmd_code;
  312. stop.cmdarg = req->stop->arg;
  313. cmd.resptype =resp_type(req->stop);
  314. req->stop->err = sdhci_transfer(sdhci, &stop, RT_NULL);
  315. }
  316. mmcsd_req_complete(host);
  317. }
  318. rt_int32_t mmc_card_status(struct rt_mmcsd_host *host)
  319. {
  320. return 0;
  321. }
  322. void mmc_enable_irq(struct rt_mmcsd_host *host, rt_int32_t en)
  323. {
  324. }
  325. static rt_err_t sdhci_detect(struct sdhci_t * sdhci)
  326. {
  327. return RT_EOK;
  328. }
  329. static rt_err_t sdhci_setwidth(struct sdhci_t * sdhci, rt_uint32_t width)
  330. {
  331. rt_uint32_t temp = 0;
  332. struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
  333. if (width == MMCSD_BUS_WIDTH_4)
  334. {
  335. temp = read32((pdat->virt + EMMC_CONTROL0));
  336. temp |= C0_HCTL_HS_EN;
  337. temp |= C0_HCTL_DWITDH; // always use 4 data lines:
  338. write32((pdat->virt + EMMC_CONTROL0), temp);
  339. }
  340. return RT_EOK;
  341. }
  342. static rt_uint32_t sdhci_getdivider(rt_uint32_t sdHostVer, rt_uint32_t freq)
  343. {
  344. rt_uint32_t divisor;
  345. rt_uint32_t closest = 41666666 / freq;
  346. rt_uint32_t shiftcount = __rt_fls(closest - 1);
  347. if (shiftcount > 0) shiftcount--;
  348. if (shiftcount > 7) shiftcount = 7;
  349. if (sdHostVer > HOST_SPEC_V2)
  350. divisor = closest;
  351. else
  352. divisor = (1 << shiftcount);
  353. if (divisor <= 2)
  354. {
  355. divisor = 2;
  356. shiftcount = 0;
  357. }
  358. rt_uint32_t hi = 0;
  359. if (sdHostVer > HOST_SPEC_V2)
  360. hi = (divisor & 0x300) >> 2;
  361. rt_uint32_t lo = (divisor & 0x0ff);
  362. rt_uint32_t cdiv = (lo << 8) + hi;
  363. return cdiv;
  364. }
  365. static rt_err_t sdhci_setclock(struct sdhci_t * sdhci, rt_uint32_t clock)
  366. {
  367. rt_uint32_t temp = 0;
  368. rt_uint32_t sdHostVer = 0;
  369. int count = 100000;
  370. struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)(sdhci->priv);
  371. while ((read32(pdat->virt + EMMC_STATUS) & (SR_CMD_INHIBIT | SR_DAT_INHIBIT)) && (--count))
  372. DELAY_MICROS(1);
  373. if (count <= 0)
  374. {
  375. rt_kprintf("EMMC: Set clock: timeout waiting for inhibit flags. Status %08x.\n",read32(pdat->virt + EMMC_STATUS));
  376. return -RT_ERROR;
  377. }
  378. // Switch clock off.
  379. temp = read32((pdat->virt + EMMC_CONTROL1));
  380. temp &= ~C1_CLK_EN;
  381. write32((pdat->virt + EMMC_CONTROL1),temp);
  382. DELAY_MICROS(10);
  383. // Request the new clock setting and enable the clock
  384. temp = read32(pdat->virt + EMMC_SLOTISR_VER);
  385. sdHostVer = (temp & HOST_SPEC_NUM) >> HOST_SPEC_NUM_SHIFT;
  386. int cdiv = sdhci_getdivider(sdHostVer, clock);
  387. temp = read32((pdat->virt + EMMC_CONTROL1));
  388. temp = (temp & 0xffff003f) | cdiv;
  389. write32((pdat->virt + EMMC_CONTROL1),temp);
  390. DELAY_MICROS(10);
  391. // Enable the clock.
  392. temp = read32(pdat->virt + EMMC_CONTROL1);
  393. temp |= C1_CLK_EN;
  394. write32((pdat->virt + EMMC_CONTROL1),temp);
  395. DELAY_MICROS(10);
  396. // Wait for clock to be stable.
  397. count = 10000;
  398. while (!(read32(pdat->virt + EMMC_CONTROL1) & C1_CLK_STABLE) && count--)
  399. DELAY_MICROS(10);
  400. if (count <= 0)
  401. {
  402. rt_kprintf("EMMC: ERROR: failed to get stable clock %d.\n", clock);
  403. return -RT_ERROR;
  404. }
  405. mmcsd_dbg("set stable clock %d.\n", clock);
  406. return RT_EOK;
  407. }
  408. static void mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
  409. {
  410. struct sdhci_t * sdhci = (struct sdhci_t *)host->private_data;
  411. sdhci_setclock(sdhci, io_cfg->clock);
  412. sdhci_setwidth(sdhci, io_cfg->bus_width);
  413. }
  414. static const struct rt_mmcsd_host_ops ops =
  415. {
  416. mmc_request_send,
  417. mmc_set_iocfg,
  418. RT_NULL,
  419. RT_NULL,
  420. };
  421. static void sdmmc_gpio_init()
  422. {
  423. // int pin;
  424. // bcm283x_gpio_fsel(47,BCM283X_GPIO_FSEL_INPT);
  425. // bcm283x_gpio_set_pud(47, BCM283X_GPIO_PUD_UP);
  426. // bcm283x_peri_set_bits(BCM283X_GPIO_BASE + BCM283X_GPIO_GPHEN1, 1<<15, 1<<15);
  427. // for (pin = 53; pin >= 48; pin--)
  428. // {
  429. // bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_ALT3);
  430. // bcm283x_gpio_set_pud(pin, BCM283X_GPIO_PUD_UP);
  431. // }
  432. }
  433. static rt_err_t reset_emmc(struct sdhci_pdata_t * pdat){
  434. rt_uint32_t temp;
  435. int cnt;
  436. write32((pdat->virt + EMMC_CONTROL0),0);
  437. temp = read32((pdat->virt + EMMC_CONTROL1));
  438. temp |= C1_SRST_HC;
  439. write32((pdat->virt + EMMC_CONTROL1),temp);
  440. cnt = 10000;
  441. do
  442. {
  443. DELAY_MICROS(10);
  444. }
  445. while ((read32((pdat->virt + EMMC_CONTROL1)) & C1_SRST_HC) && cnt--);
  446. if (cnt <= 0)
  447. {
  448. rt_kprintf("ERROR: failed to reset EMMC\n");
  449. return -RT_ERROR;
  450. }
  451. temp = read32((pdat->virt + EMMC_CONTROL1));
  452. temp |= C1_CLK_INTLEN | C1_TOUNIT_MAX;
  453. write32((pdat->virt + EMMC_CONTROL1),temp);
  454. DELAY_MICROS(10);
  455. return RT_EOK;
  456. }
  457. #ifdef RT_MMCSD_DBG
  458. void dump_registers(struct sdhci_pdata_t * pdat){
  459. rt_kprintf("EMMC registers:");
  460. int i = EMMC_ARG2;
  461. for (; i <= EMMC_CONTROL2; i += 4)
  462. rt_kprintf("\t%x:%x\n", i, read32(pdat->virt + i));
  463. rt_kprintf("\t%x:%x\n", 0x50, read32(pdat->virt + 0x50));
  464. rt_kprintf("\t%x:%x\n", 0x70, read32(pdat->virt + 0x70));
  465. rt_kprintf("\t%x:%x\n", 0x74, read32(pdat->virt + 0x74));
  466. rt_kprintf("\t%x:%x\n", 0x80, read32(pdat->virt + 0x80));
  467. rt_kprintf("\t%x:%x\n", 0x84, read32(pdat->virt + 0x84));
  468. rt_kprintf("\t%x:%x\n", 0x88, read32(pdat->virt + 0x88));
  469. rt_kprintf("\t%x:%x\n", 0x8c, read32(pdat->virt + 0x8c));
  470. rt_kprintf("\t%x:%x\n", 0x90, read32(pdat->virt + 0x90));
  471. rt_kprintf("\t%x:%x\n", 0xf0, read32(pdat->virt + 0xf0));
  472. rt_kprintf("\t%x:%x\n", 0xfc, read32(pdat->virt + 0xfc));
  473. }
  474. #endif
  475. int raspi_sdmmc_init(void)
  476. {
  477. rt_uint32_t virt;
  478. struct rt_mmcsd_host * host = RT_NULL;
  479. struct sdhci_pdata_t * pdat = RT_NULL;
  480. struct sdhci_t * sdhci = RT_NULL;
  481. #ifdef BSP_USING_SDIO0
  482. host = mmcsd_alloc_host();
  483. if (!host)
  484. {
  485. rt_kprintf("alloc host failed");
  486. goto err;
  487. }
  488. sdhci = rt_malloc(sizeof(struct sdhci_t));
  489. if (!sdhci)
  490. {
  491. rt_kprintf("alloc sdhci failed");
  492. goto err;
  493. }
  494. rt_memset(sdhci, 0, sizeof(struct sdhci_t));
  495. sdmmc_gpio_init();
  496. virt = MMC0_BASE_ADDR;
  497. pdat = (struct sdhci_pdata_t *)rt_malloc(sizeof(struct sdhci_pdata_t));
  498. RT_ASSERT(pdat != RT_NULL);
  499. pdat->virt = (rt_uint32_t)virt;
  500. reset_emmc(pdat);
  501. sdhci->name = "sd0";
  502. sdhci->voltages = VDD_33_34;
  503. sdhci->width = MMCSD_BUSWIDTH_4;
  504. sdhci->clock = 200 * 1000 * 1000;
  505. sdhci->removeable = RT_TRUE;
  506. sdhci->detect = sdhci_detect;
  507. sdhci->setwidth = sdhci_setwidth;
  508. sdhci->setclock = sdhci_setclock;
  509. sdhci->transfer = sdhci_transfer;
  510. sdhci->priv = pdat;
  511. host->ops = &ops;
  512. host->freq_min = 400000;
  513. host->freq_max = 50000000;
  514. host->valid_ocr = VDD_32_33 | VDD_33_34;
  515. host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ | MMCSD_BUSWIDTH_4;
  516. host->max_seg_size = 2048;
  517. host->max_dma_segs = 10;
  518. host->max_blk_size = 512;
  519. host->max_blk_count = 4096;
  520. host->private_data = sdhci;
  521. write32((pdat->virt + EMMC_IRPT_EN),0xffffffff);
  522. write32((pdat->virt + EMMC_IRPT_MASK),0xffffffff);
  523. #ifdef RT_MMCSD_DBG
  524. dump_registers(pdat);
  525. #endif
  526. mmcsd_change(host);
  527. #endif
  528. return RT_EOK;
  529. err:
  530. if (host) rt_free(host);
  531. if (sdhci) rt_free(sdhci);
  532. return -RT_EIO;
  533. }
  534. INIT_DEVICE_EXPORT(raspi_sdmmc_init);