drv_sdio.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020/12/31 Bernard Add license info
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #include <drivers/mmcsd_core.h>
  14. #include <stdint.h>
  15. #include <stdio.h>
  16. #include "board.h"
  17. #include "drv_sdio.h"
  18. #ifdef RT_USING_SDIO
  19. #define MMC_BASE_ADDR (0x10005000)
  20. #define PL180_POWER (0x00)
  21. #define PL180_CLOCK (0x04)
  22. #define PL180_ARGUMENT (0x08)
  23. #define PL180_COMMAND (0x0c)
  24. #define PL180_RESPCMD (0x10)
  25. #define PL180_RESP0 (0x14)
  26. #define PL180_RESP1 (0x18)
  27. #define PL180_RESP2 (0x1c)
  28. #define PL180_RESP3 (0x20)
  29. #define PL180_DATA_TIMER (0x24)
  30. #define PL180_DATA_LENGTH (0x28)
  31. #define PL180_DATA_CTRL (0x2c)
  32. #define PL180_DATA_CNT (0x30)
  33. #define PL180_STATUS (0x34)
  34. #define PL180_CLEAR (0x38)
  35. #define PL180_MASK0 (0x3c)
  36. #define PL180_MASK1 (0x40)
  37. #define PL180_SELECT (0x44)
  38. #define PL180_FIFO_CNT (0x48)
  39. #define PL180_FIFO (0x80)
  40. #define PL180_RSP_NONE (0 << 0)
  41. #define PL180_RSP_PRESENT (1 << 0)
  42. #define PL180_RSP_136BIT (1 << 1)
  43. #define PL180_RSP_CRC (1 << 2)
  44. #define PL180_CMD_WAITRESP (1 << 6)
  45. #define PL180_CMD_LONGRSP (1 << 7)
  46. #define PL180_CMD_WAITINT (1 << 8)
  47. #define PL180_CMD_WAITPEND (1 << 9)
  48. #define PL180_CMD_ENABLE (1 << 10)
  49. #define PL180_STAT_CMD_CRC_FAIL (1 << 0)
  50. #define PL180_STAT_DAT_CRC_FAIL (1 << 1)
  51. #define PL180_STAT_CMD_TIME_OUT (1 << 2)
  52. #define PL180_STAT_DAT_TIME_OUT (1 << 3)
  53. #define PL180_STAT_TX_UNDERRUN (1 << 4)
  54. #define PL180_STAT_RX_OVERRUN (1 << 5)
  55. #define PL180_STAT_CMD_RESP_END (1 << 6)
  56. #define PL180_STAT_CMD_SENT (1 << 7)
  57. #define PL180_STAT_DAT_END (1 << 8)
  58. #define PL180_STAT_DAT_BLK_END (1 << 10)
  59. #define PL180_STAT_CMD_ACT (1 << 11)
  60. #define PL180_STAT_TX_ACT (1 << 12)
  61. #define PL180_STAT_RX_ACT (1 << 13)
  62. #define PL180_STAT_TX_FIFO_HALF (1 << 14)
  63. #define PL180_STAT_RX_FIFO_HALF (1 << 15)
  64. #define PL180_STAT_TX_FIFO_FULL (1 << 16)
  65. #define PL180_STAT_RX_FIFO_FULL (1 << 17)
  66. #define PL180_STAT_TX_FIFO_ZERO (1 << 18)
  67. #define PL180_STAT_RX_DAT_ZERO (1 << 19)
  68. #define PL180_STAT_TX_DAT_AVL (1 << 20)
  69. #define PL180_STAT_RX_FIFO_AVL (1 << 21)
  70. #define PL180_CLR_CMD_CRC_FAIL (1 << 0)
  71. #define PL180_CLR_DAT_CRC_FAIL (1 << 1)
  72. #define PL180_CLR_CMD_TIMEOUT (1 << 2)
  73. #define PL180_CLR_DAT_TIMEOUT (1 << 3)
  74. #define PL180_CLR_TX_UNDERRUN (1 << 4)
  75. #define PL180_CLR_RX_OVERRUN (1 << 5)
  76. #define PL180_CLR_CMD_RESP_END (1 << 6)
  77. #define PL180_CLR_CMD_SENT (1 << 7)
  78. #define PL180_CLR_DAT_END (1 << 8)
  79. #define PL180_CLR_DAT_BLK_END (1 << 10)
  80. #define DBG_TAG "drv.sdio"
  81. #define DBG_LVL DBG_INFO
  82. #include "rtdbg.h"
  83. struct sdhci_pl180_pdata_t
  84. {
  85. rt_uint32_t virt;
  86. };
  87. static inline rt_uint32_t read32(uint32_t addr)
  88. {
  89. return( *((volatile rt_uint32_t *)(addr)) );
  90. }
  91. static inline void write32(uint32_t addr, rt_uint32_t value)
  92. {
  93. *((volatile rt_uint32_t *)(addr)) = value;
  94. }
  95. static rt_err_t pl180_transfer_command(struct sdhci_pl180_pdata_t * pdat, struct sdhci_cmd_t * cmd)
  96. {
  97. rt_uint32_t cmdidx;
  98. rt_uint32_t status;
  99. rt_err_t ret = RT_EOK;
  100. if(read32(pdat->virt + PL180_COMMAND) & PL180_CMD_ENABLE)
  101. write32(pdat->virt + PL180_COMMAND, 0x0);
  102. cmdidx = (cmd->cmdidx & 0xff) | PL180_CMD_ENABLE;
  103. if(cmd->resptype)
  104. {
  105. cmdidx |= PL180_CMD_WAITRESP;
  106. if(cmd->resptype & PL180_RSP_136BIT)
  107. cmdidx |= PL180_CMD_LONGRSP;
  108. }
  109. write32(pdat->virt + PL180_ARGUMENT, cmd->cmdarg);
  110. write32(pdat->virt + PL180_COMMAND, cmdidx);
  111. do {
  112. status = read32(pdat->virt + PL180_STATUS);
  113. } while(!(status & (PL180_STAT_CMD_SENT | PL180_STAT_CMD_RESP_END | PL180_STAT_CMD_TIME_OUT | PL180_STAT_CMD_CRC_FAIL)));
  114. LOG_D("mmc status done!");
  115. if(cmd->resptype & PL180_RSP_PRESENT)
  116. {
  117. cmd->response[0] = read32(pdat->virt + PL180_RESP0);
  118. if(cmd->resptype & PL180_RSP_136BIT)
  119. {
  120. LOG_D("136bit response");
  121. cmd->response[1] = read32(pdat->virt + PL180_RESP1);
  122. cmd->response[2] = read32(pdat->virt + PL180_RESP2);
  123. cmd->response[3] = read32(pdat->virt + PL180_RESP3);
  124. }
  125. }
  126. if(status & PL180_STAT_CMD_TIME_OUT)
  127. {
  128. ret = -RT_ETIMEOUT;
  129. }
  130. else if ((status & PL180_STAT_CMD_CRC_FAIL) && (cmd->resptype & PL180_RSP_CRC))
  131. {
  132. ret = -RT_ERROR;
  133. }
  134. write32(pdat->virt + PL180_CLEAR, (PL180_CLR_CMD_SENT | PL180_CLR_CMD_RESP_END | PL180_CLR_CMD_TIMEOUT | PL180_CLR_CMD_CRC_FAIL));
  135. return ret;
  136. }
  137. static rt_err_t read_bytes(struct sdhci_pl180_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
  138. {
  139. rt_uint32_t * tmp = buf;
  140. rt_uint32_t count = blkcount * blksize;
  141. rt_uint32_t status, err;
  142. status = read32(pdat->virt + PL180_STATUS);
  143. err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_RX_OVERRUN);
  144. while((!err) && (count >= sizeof(rt_uint32_t)))
  145. {
  146. if(status & PL180_STAT_RX_FIFO_AVL)
  147. {
  148. *(tmp) = read32(pdat->virt + PL180_FIFO);
  149. tmp++;
  150. count -= sizeof(rt_uint32_t);
  151. }
  152. status = read32(pdat->virt + PL180_STATUS);
  153. err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_RX_OVERRUN);
  154. }
  155. err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_DAT_BLK_END | PL180_STAT_RX_OVERRUN);
  156. while(!err)
  157. {
  158. status = read32(pdat->virt + PL180_STATUS);
  159. err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_DAT_BLK_END | PL180_STAT_RX_OVERRUN);
  160. }
  161. if(status & PL180_STAT_DAT_TIME_OUT)
  162. return -RT_ERROR;
  163. else if (status & PL180_STAT_DAT_CRC_FAIL)
  164. return -RT_ERROR;
  165. else if (status & PL180_STAT_RX_OVERRUN)
  166. return -RT_ERROR;
  167. write32(pdat->virt + PL180_CLEAR, 0x1DC007FF);
  168. if(count)
  169. return -RT_ERROR;
  170. return RT_EOK;
  171. }
  172. static rt_err_t write_bytes(struct sdhci_pl180_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
  173. {
  174. rt_uint32_t * tmp = buf;
  175. rt_uint32_t count = blkcount * blksize;
  176. rt_uint32_t status, err;
  177. int i;
  178. status = read32(pdat->virt + PL180_STATUS);
  179. err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT);
  180. while(!err && count)
  181. {
  182. if(status & PL180_STAT_TX_FIFO_HALF)
  183. {
  184. if(count >= 8 * sizeof(rt_uint32_t))
  185. {
  186. for(i = 0; i < 8; i++)
  187. write32(pdat->virt + PL180_FIFO, *(tmp + i));
  188. tmp += 8;
  189. count -= 8 * sizeof(rt_uint32_t);
  190. }
  191. else
  192. {
  193. while(count >= sizeof(rt_uint32_t))
  194. {
  195. write32(pdat->virt + PL180_FIFO, *tmp);
  196. tmp++;
  197. count -= sizeof(rt_uint32_t);
  198. }
  199. }
  200. }
  201. status = read32(pdat->virt + PL180_STATUS);
  202. err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT);
  203. }
  204. err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_DAT_BLK_END);
  205. while(!err)
  206. {
  207. status = read32(pdat->virt + PL180_STATUS);
  208. err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_DAT_BLK_END);
  209. }
  210. if(status & PL180_STAT_DAT_TIME_OUT)
  211. return -RT_ERROR;
  212. else if (status & PL180_STAT_DAT_CRC_FAIL)
  213. return -RT_ERROR;
  214. write32(pdat->virt + PL180_CLEAR, 0x1DC007FF);
  215. if(count)
  216. return -RT_ERROR;
  217. return RT_EOK;
  218. }
  219. static rt_err_t pl180_transfer_data(struct sdhci_pl180_pdata_t * pdat, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
  220. {
  221. rt_uint32_t dlen = (rt_uint32_t)(dat->blkcnt * dat->blksz);
  222. rt_uint32_t blksz_bits = dat->blksz - 1;
  223. rt_uint32_t dctrl = (blksz_bits << 4) | (0x1 << 0) | (0x1 << 14);
  224. rt_err_t ret = -RT_ERROR;
  225. write32(pdat->virt + PL180_DATA_TIMER, 0xffff);
  226. write32(pdat->virt + PL180_DATA_LENGTH, dlen);
  227. if(dat->flag & DATA_DIR_READ)
  228. {
  229. dctrl |= (0x1 << 1);
  230. write32(pdat->virt + PL180_DATA_CTRL, dctrl);
  231. ret = pl180_transfer_command(pdat, cmd);
  232. if (ret < 0) return ret;
  233. ret = read_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
  234. }
  235. else if(dat->flag & DATA_DIR_WRITE)
  236. {
  237. ret = pl180_transfer_command(pdat, cmd);
  238. if (ret < 0) return ret;
  239. write32(pdat->virt + PL180_DATA_CTRL, dctrl);
  240. ret = write_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
  241. }
  242. return ret;
  243. }
  244. static rt_err_t sdhci_pl180_detect(struct sdhci_t * sdhci)
  245. {
  246. return RT_EOK;
  247. }
  248. static rt_err_t sdhci_pl180_setwidth(struct sdhci_t * sdhci, rt_uint32_t width)
  249. {
  250. return RT_EOK;
  251. }
  252. static rt_err_t sdhci_pl180_setclock(struct sdhci_t * sdhci, rt_uint32_t clock)
  253. {
  254. rt_uint32_t temp = 0;
  255. struct sdhci_pl180_pdata_t * pdat = (struct sdhci_pl180_pdata_t *)sdhci->priv;
  256. if(clock)
  257. {
  258. temp = read32(pdat->virt + PL180_CLOCK) | (0x1 << 8);
  259. (void)temp; // skip warning
  260. write32(pdat->virt + PL180_CLOCK, 0x100);
  261. }
  262. else
  263. {
  264. //write32(pdat->virt + PL180_CLOCK, read32(pdat->virt + PL180_CLOCK) & (~(0x1<<8)));
  265. }
  266. return RT_EOK;
  267. }
  268. static rt_err_t sdhci_pl180_transfer(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
  269. {
  270. struct sdhci_pl180_pdata_t * pdat = (struct sdhci_pl180_pdata_t *)sdhci->priv;
  271. if(!dat)
  272. return pl180_transfer_command(pdat, cmd);
  273. return pl180_transfer_data(pdat, cmd, dat);
  274. }
  275. static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
  276. {
  277. struct sdhci_t *sdhci = (struct sdhci_t *)host->private_data;
  278. struct sdhci_cmd_t cmd;
  279. struct sdhci_cmd_t stop;
  280. struct sdhci_data_t dat;
  281. rt_memset(&cmd, 0, sizeof(struct sdhci_cmd_t));
  282. rt_memset(&stop, 0, sizeof(struct sdhci_cmd_t));
  283. rt_memset(&dat, 0, sizeof(struct sdhci_data_t));
  284. cmd.cmdidx = req->cmd->cmd_code;
  285. cmd.cmdarg = req->cmd->arg;
  286. if (req->cmd->flags & RESP_MASK)
  287. {
  288. cmd.resptype = PL180_RSP_PRESENT;
  289. if (resp_type(req->cmd) == RESP_R2)
  290. cmd.resptype |= PL180_RSP_136BIT;
  291. }
  292. else
  293. cmd.resptype = 0;
  294. if(req->data)
  295. {
  296. dat.buf = (rt_uint8_t *)req->data->buf;
  297. dat.flag = req->data->flags;
  298. dat.blksz = req->data->blksize;
  299. dat.blkcnt = req->data->blks;
  300. req->cmd->err = sdhci_pl180_transfer(sdhci, &cmd, &dat);
  301. }
  302. else
  303. {
  304. req->cmd->err = sdhci_pl180_transfer(sdhci, &cmd, RT_NULL);
  305. }
  306. LOG_D("cmdarg:%d", cmd.cmdarg);
  307. LOG_D("cmdidx:%d", cmd.cmdidx);
  308. LOG_D("[0]:0x%08x [1]:0x%08x [2]:0x%08x [3]:0x%08x", cmd.response[0], cmd.response[1], cmd.response[2], cmd.response[3]);
  309. req->cmd->resp[3] = cmd.response[3];
  310. req->cmd->resp[2] = cmd.response[2];
  311. req->cmd->resp[1] = cmd.response[1];
  312. req->cmd->resp[0] = cmd.response[0];
  313. if (req->stop)
  314. {
  315. stop.cmdidx = req->stop->cmd_code;
  316. stop.cmdarg = req->stop->arg;
  317. if (req->stop->flags & RESP_MASK)
  318. {
  319. stop.resptype = PL180_RSP_PRESENT;
  320. if (resp_type(req->stop) == RESP_R2)
  321. stop.resptype |= PL180_RSP_136BIT;
  322. }
  323. else
  324. stop.resptype = 0;
  325. req->stop->err = sdhci_pl180_transfer(sdhci, &stop, RT_NULL);
  326. }
  327. mmcsd_req_complete(host);
  328. }
  329. static void mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
  330. {
  331. struct sdhci_t * sdhci = (struct sdhci_t *)host->private_data;
  332. sdhci_pl180_setclock(sdhci, io_cfg->clock);
  333. sdhci_pl180_setwidth(sdhci, io_cfg->bus_width);
  334. LOG_D("clock:%d bus_width:%d", io_cfg->clock, io_cfg->bus_width);
  335. }
  336. static const struct rt_mmcsd_host_ops ops =
  337. {
  338. mmc_request_send,
  339. mmc_set_iocfg,
  340. RT_NULL,
  341. RT_NULL,
  342. };
  343. int pl180_init(void)
  344. {
  345. rt_uint32_t virt;
  346. rt_uint32_t id;
  347. struct rt_mmcsd_host * host = RT_NULL;
  348. struct sdhci_pl180_pdata_t * pdat = RT_NULL;
  349. struct sdhci_t * sdhci = RT_NULL;
  350. host = mmcsd_alloc_host();
  351. if (!host)
  352. {
  353. LOG_E("alloc host failed");
  354. goto err;
  355. }
  356. sdhci = rt_malloc(sizeof(struct sdhci_t));
  357. if (!sdhci)
  358. {
  359. LOG_E("alloc sdhci failed");
  360. goto err;
  361. }
  362. rt_memset(sdhci, 0, sizeof(struct sdhci_t));
  363. #ifdef RT_USING_SMART
  364. virt = (rt_uint32_t)rt_ioremap((void*)MMC_BASE_ADDR, 0x1000);
  365. #else
  366. virt = MMC_BASE_ADDR;
  367. #endif
  368. id = (((read32((virt + 0xfec)) & 0xff) << 24) |
  369. ((read32((virt + 0xfe8)) & 0xff) << 16) |
  370. ((read32((virt + 0xfe4)) & 0xff) << 8) |
  371. ((read32((virt + 0xfe0)) & 0xff) << 0));
  372. LOG_D("id=0x%08x", id);
  373. if(((id >> 12) & 0xff) != 0x41 || (id & 0xfff) != 0x181)
  374. {
  375. LOG_E("check id failed");
  376. goto err;
  377. }
  378. pdat = (struct sdhci_pl180_pdata_t *)rt_malloc(sizeof(struct sdhci_pl180_pdata_t));
  379. RT_ASSERT(pdat != RT_NULL);
  380. pdat->virt = (uint32_t)virt;
  381. sdhci->name = "sd0";
  382. sdhci->voltages = VDD_33_34;
  383. sdhci->width = MMCSD_BUSWIDTH_4;
  384. sdhci->clock = 26 * 1000 * 1000;
  385. sdhci->removeable = RT_TRUE;
  386. sdhci->detect = sdhci_pl180_detect;
  387. sdhci->setwidth = sdhci_pl180_setwidth;
  388. sdhci->setclock = sdhci_pl180_setclock;
  389. sdhci->transfer = sdhci_pl180_transfer;
  390. sdhci->priv = pdat;
  391. write32(pdat->virt + PL180_POWER, 0xbf);
  392. host->ops = &ops;
  393. host->freq_min = 400000;
  394. host->freq_max = 50000000;
  395. host->valid_ocr = VDD_32_33 | VDD_33_34;
  396. host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ | MMCSD_BUSWIDTH_4;
  397. host->max_seg_size = 2048;
  398. host->max_dma_segs = 10;
  399. host->max_blk_size = 512;
  400. host->max_blk_count = 4096;
  401. host->private_data = sdhci;
  402. mmcsd_change(host);
  403. return RT_EOK;
  404. err:
  405. if(host) rt_free(host);
  406. if(sdhci) rt_free(sdhci);
  407. return -RT_EIO;
  408. }
  409. INIT_DEVICE_EXPORT(pl180_init);
  410. #endif