drv_sdio.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. /*
  2. * File : drv_sdio.c
  3. * Copyright (c) 2006-2018, 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 <rtthread.h>
  12. #include <rthw.h>
  13. #include <rtdevice.h>
  14. #include <string.h>
  15. #include "drv_sdio.h"
  16. #include "interrupt.h"
  17. #include "drv_gpio.h"
  18. #include "bcm283x.h"
  19. #include <drivers/mmcsd_core.h>
  20. #include "bcm283x.h"
  21. #include <rtdbg.h>
  22. #ifdef RT_USING_SDIO
  23. #define CONFIG_MMC_USE_DMA
  24. #define DMA_ALIGN (32U)
  25. typedef struct EMMCCommand
  26. {
  27. const char* name;
  28. unsigned int code;
  29. unsigned char resp;
  30. unsigned char rca;
  31. int delay;
  32. } EMMCCommand;
  33. static EMMCCommand sdCommandTable[] =
  34. {
  35. {"GO_IDLE_STATE", 0x00000000 | CMD_RSPNS_NO , RESP_NO , RCA_NO ,0},
  36. {"ALL_SEND_CID" , 0x02000000 | CMD_RSPNS_136 , RESP_R2I, RCA_NO ,0},
  37. {"SEND_REL_ADDR", 0x03000000 | CMD_RSPNS_48 , RESP_R6 , RCA_NO ,0},
  38. {"SET_DSR" , 0x04000000 | CMD_RSPNS_NO , RESP_NO , RCA_NO ,0},
  39. {"SWITCH_FUNC" , 0x06000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  40. {"CARD_SELECT" , 0x07000000 | CMD_RSPNS_48B , RESP_R1b, RCA_YES ,0},
  41. {"SEND_IF_COND" , 0x08000000 | CMD_RSPNS_48 , RESP_R7 , RCA_NO ,100},
  42. {"SEND_CSD" , 0x09000000 | CMD_RSPNS_136 , RESP_R2S, RCA_YES ,0},
  43. {"SEND_CID" , 0x0A000000 | CMD_RSPNS_136 , RESP_R2I, RCA_YES ,0},
  44. {"VOLT_SWITCH" , 0x0B000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  45. {"STOP_TRANS" , 0x0C000000 | CMD_RSPNS_48B , RESP_R1b, RCA_NO ,0},
  46. {"SEND_STATUS" , 0x0D000000 | CMD_RSPNS_48 , RESP_R1 , RCA_YES ,0},
  47. {"GO_INACTIVE" , 0x0F000000 | CMD_RSPNS_NO , RESP_NO , RCA_YES ,0},
  48. {"SET_BLOCKLEN" , 0x10000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  49. {"READ_SINGLE" , 0x11000000 | CMD_RSPNS_48 | CMD_IS_DATA | TM_DAT_DIR_CH, RESP_R1 , RCA_NO ,0},
  50. {"READ_MULTI" , 0x12000000 | CMD_RSPNS_48 | TM_MULTI_DATA | TM_DAT_DIR_CH, RESP_R1 , RCA_NO ,0},
  51. {"SEND_TUNING" , 0x13000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  52. {"SPEED_CLASS" , 0x14000000 | CMD_RSPNS_48B , RESP_R1b, RCA_NO ,0},
  53. {"SET_BLOCKCNT" , 0x17000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  54. {"WRITE_SINGLE" , 0x18000000 | CMD_RSPNS_48 | CMD_IS_DATA | TM_DAT_DIR_HC, RESP_R1 , RCA_NO ,0},
  55. {"WRITE_MULTI" , 0x19000000 | CMD_RSPNS_48 | TM_MULTI_DATA | TM_DAT_DIR_HC, RESP_R1 , RCA_NO ,0},
  56. {"PROGRAM_CSD" , 0x1B000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  57. {"SET_WRITE_PR" , 0x1C000000 | CMD_RSPNS_48B , RESP_R1b, RCA_NO ,0},
  58. {"CLR_WRITE_PR" , 0x1D000000 | CMD_RSPNS_48B , RESP_R1b, RCA_NO ,0},
  59. {"SND_WRITE_PR" , 0x1E000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  60. {"ERASE_WR_ST" , 0x20000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  61. {"ERASE_WR_END" , 0x21000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  62. {"ERASE" , 0x26000000 | CMD_RSPNS_48B , RESP_R1b, RCA_NO ,0},
  63. {"LOCK_UNLOCK" , 0x2A000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  64. {"APP_CMD" , 0x37000000 | CMD_RSPNS_NO , RESP_NO , RCA_NO ,100},
  65. {"APP_CMD" , 0x37000000 | CMD_RSPNS_48 , RESP_R1 , RCA_YES ,0},
  66. {"GEN_CMD" , 0x38000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  67. // APP commands must be prefixed by an APP_CMD.
  68. {"SET_BUS_WIDTH", 0x06000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  69. {"SD_STATUS" , 0x0D000000 | CMD_RSPNS_48 , RESP_R1 , RCA_YES ,0}, // RCA???
  70. {"SEND_NUM_WRBL", 0x16000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  71. {"SEND_NUM_ERS" , 0x17000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  72. {"SD_SENDOPCOND", 0x29000000 | CMD_RSPNS_48 , RESP_R3 , RCA_NO ,1000},
  73. {"SET_CLR_DET" , 0x2A000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0},
  74. {"SEND_SCR" , 0x33000000 | CMD_RSPNS_48 | CMD_IS_DATA | TM_DAT_DIR_CH , RESP_R1 , RCA_NO ,0},
  75. };
  76. static rt_err_t sdhci_setwidth(struct sdhci_t * sdhci, rt_uint32_t width);
  77. static rt_err_t sdhci_setclock(struct sdhci_t * sdhci, rt_uint32_t clock);
  78. static rt_err_t sdhci_transfer(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat);
  79. static inline rt_uint32_t read32(rt_uint32_t addr)
  80. {
  81. return( *((volatile rt_uint32_t *)(addr)) );
  82. }
  83. static inline void write32(rt_uint32_t addr, rt_uint32_t value)
  84. {
  85. *((volatile rt_uint32_t *)(addr)) = value;
  86. }
  87. static rt_err_t raspi_transfer_command(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd)
  88. {
  89. rt_uint32_t cmdidx;
  90. rt_uint32_t status;
  91. rt_err_t ret = RT_EOK;
  92. if(read32(pdat->virt + EMMC_STATUS) & SR_CMD_INHIBIT)
  93. write32(pdat->virt + EMMC_CMDTM, 0x0);
  94. EMMCCommand* cmdtab = &sdCommandTable[cmd->cmdidx];
  95. cmdidx = cmdtab->code;
  96. write32(pdat->virt + EMMC_ARG1, cmd->cmdarg);
  97. write32(pdat->virt + EMMC_CMDTM, cmdidx);
  98. do {
  99. status = read32(pdat->virt + EMMC_STATUS);
  100. } while(!(status & SR_CMD_INHIBIT));
  101. if(cmd->resptype & RESP_MASK)
  102. {
  103. cmd->response[0] = read32(pdat->virt + EMMC_RESP0);
  104. if(cmd->resptype & RESP_R2)
  105. {
  106. cmd->response[1] = read32(pdat->virt + EMMC_RESP1);
  107. cmd->response[2] = read32(pdat->virt + EMMC_RESP2);
  108. cmd->response[3] = read32(pdat->virt + EMMC_RESP3);
  109. }
  110. }
  111. return ret;
  112. }
  113. static rt_err_t read_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
  114. {
  115. rt_uint32_t * tmp = buf;
  116. rt_uint32_t count = blkcount * blksize;
  117. rt_uint32_t status, err;
  118. // status = read32(pdat->virt + PL180_STATUS);
  119. // err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_RX_OVERRUN);
  120. // while((!err) && (count >= sizeof(rt_uint32_t)))
  121. // {
  122. // if(status & PL180_STAT_RX_FIFO_AVL)
  123. // {
  124. // *(tmp) = read32(pdat->virt + PL180_FIFO);
  125. // tmp++;
  126. // count -= sizeof(rt_uint32_t);
  127. // }
  128. // status = read32(pdat->virt + PL180_STATUS);
  129. // err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_RX_OVERRUN);
  130. // }
  131. //
  132. // err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_DAT_BLK_END | PL180_STAT_RX_OVERRUN);
  133. // while(!err)
  134. // {
  135. // status = read32(pdat->virt + PL180_STATUS);
  136. // err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_DAT_BLK_END | PL180_STAT_RX_OVERRUN);
  137. // }
  138. //
  139. // if(status & PL180_STAT_DAT_TIME_OUT)
  140. // return -RT_ERROR;
  141. // else if (status & PL180_STAT_DAT_CRC_FAIL)
  142. // return -RT_ERROR;
  143. // else if (status & PL180_STAT_RX_OVERRUN)
  144. // return -RT_ERROR;
  145. // write32(pdat->virt + PL180_CLEAR, 0x1DC007FF);
  146. //
  147. // if(count)
  148. // return -RT_ERROR;
  149. return RT_EOK;
  150. }
  151. static rt_err_t write_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
  152. {
  153. rt_uint32_t * tmp = buf;
  154. rt_uint32_t count = blkcount * blksize;
  155. rt_uint32_t status, err;
  156. int i;
  157. // status = read32(pdat->virt + PL180_STATUS);
  158. // err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT);
  159. // while(!err && count)
  160. // {
  161. // if(status & PL180_STAT_TX_FIFO_HALF)
  162. // {
  163. // if(count >= 8 * sizeof(rt_uint32_t))
  164. // {
  165. // for(i = 0; i < 8; i++)
  166. // write32(pdat->virt + PL180_FIFO, *(tmp + i));
  167. // tmp += 8;
  168. // count -= 8 * sizeof(rt_uint32_t);
  169. // }
  170. // else
  171. // {
  172. // while(count >= sizeof(rt_uint32_t))
  173. // {
  174. // write32(pdat->virt + PL180_FIFO, *tmp);
  175. // tmp++;
  176. // count -= sizeof(rt_uint32_t);
  177. // }
  178. // }
  179. // }
  180. // status = read32(pdat->virt + PL180_STATUS);
  181. // err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT);
  182. // }
  183. //
  184. // err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_DAT_BLK_END);
  185. // while(!err)
  186. // {
  187. // status = read32(pdat->virt + PL180_STATUS);
  188. // err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_DAT_BLK_END);
  189. // }
  190. //
  191. // if(status & PL180_STAT_DAT_TIME_OUT)
  192. // return -RT_ERROR;
  193. // else if (status & PL180_STAT_DAT_CRC_FAIL)
  194. // return -RT_ERROR;
  195. // write32(pdat->virt + PL180_CLEAR, 0x1DC007FF);
  196. //
  197. // if(count)
  198. // return -RT_ERROR;
  199. return RT_EOK;
  200. }
  201. static rt_err_t raspi_transfer_data(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
  202. {
  203. rt_uint32_t dlen = (rt_uint32_t)(dat->blkcnt * dat->blksz);
  204. rt_uint32_t blksz_bits = dat->blksz - 1;
  205. rt_err_t ret = -RT_ERROR;
  206. write32(pdat->virt + EMMC_BLKSIZECNT, dlen);
  207. if(dat->flag & DATA_DIR_READ)
  208. {
  209. write32(pdat->virt + EMMC_STATUS, SR_READ_TRANSFER);
  210. ret = raspi_transfer_command(pdat, cmd);
  211. if (ret < 0) return ret;
  212. ret = read_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
  213. }
  214. else if(dat->flag & DATA_DIR_WRITE)
  215. {
  216. ret = raspi_transfer_command(pdat, cmd);
  217. if (ret < 0) return ret;
  218. write32(pdat->virt + EMMC_STATUS, SR_WRITE_TRANSFER);
  219. ret = write_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
  220. }
  221. return ret;
  222. }
  223. static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
  224. {
  225. struct sdhci_t *sdhci = (struct sdhci_t *)host->private_data;
  226. struct sdhci_cmd_t cmd;
  227. struct sdhci_cmd_t stop;
  228. struct sdhci_data_t dat;
  229. rt_memset(&cmd, 0, sizeof(struct sdhci_cmd_t));
  230. rt_memset(&stop, 0, sizeof(struct sdhci_cmd_t));
  231. rt_memset(&dat, 0, sizeof(struct sdhci_data_t));
  232. cmd.cmdidx = req->cmd->cmd_code;
  233. EMMCCommand* cmdtab = &sdCommandTable[cmd.cmdidx];
  234. cmd.cmdarg = req->cmd->arg;
  235. cmd.resptype = cmdtab->resp;
  236. if(req->data)
  237. {
  238. dat.buf = (rt_uint8_t *)req->data->buf;
  239. dat.flag = req->data->flags;
  240. dat.blksz = req->data->blksize;
  241. dat.blkcnt = req->data->blks;
  242. req->cmd->err = sdhci_transfer(sdhci, &cmd, &dat);
  243. }
  244. else
  245. {
  246. req->cmd->err = sdhci_transfer(sdhci, &cmd, RT_NULL);
  247. }
  248. req->cmd->resp[3] = cmd.response[3];
  249. req->cmd->resp[2] = cmd.response[2];
  250. req->cmd->resp[1] = cmd.response[1];
  251. req->cmd->resp[0] = cmd.response[0];
  252. if (req->stop)
  253. {
  254. stop.cmdidx = req->stop->cmd_code;
  255. cmdtab = &sdCommandTable[cmd.cmdidx];
  256. stop.cmdarg = req->stop->arg;
  257. cmd.resptype = cmdtab->resp;
  258. req->stop->err = sdhci_transfer(sdhci, &stop, RT_NULL);
  259. }
  260. mmcsd_req_complete(host);
  261. }
  262. static rt_err_t sdhci_transfer(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
  263. {
  264. struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
  265. if(!dat)
  266. return raspi_transfer_command(pdat, cmd);
  267. return raspi_transfer_data(pdat, cmd, dat);
  268. }
  269. //#ifdef CONFIG_MMC_USE_DMA
  270. //#ifdef BSP_USING_SDIO0
  271. ////ALIGN(32) static rt_uint8_t dma_buffer[64 * 1024];
  272. //static rt_uint8_t dma_buffer[64 * 1024];
  273. //#endif
  274. //#endif
  275. static void mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
  276. {
  277. struct sdhci_t * sdhci = (struct sdhci_t *)host->private_data;
  278. sdhci_setclock(sdhci, io_cfg->clock);
  279. sdhci_setwidth(sdhci, io_cfg->bus_width);
  280. }
  281. rt_int32_t mmc_card_status(struct rt_mmcsd_host *host)
  282. {
  283. return 0;
  284. }
  285. void mmc_enable_irq(struct rt_mmcsd_host *host, rt_int32_t en)
  286. {
  287. }
  288. static rt_err_t sdhci_detect(struct sdhci_t * sdhci)
  289. {
  290. return RT_EOK;
  291. }
  292. static rt_err_t sdhci_setwidth(struct sdhci_t * sdhci, rt_uint32_t width)
  293. {
  294. rt_uint32_t temp = 0;
  295. struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
  296. temp = read32((pdat->virt + EMMC_CONTROL0));
  297. temp |= C0_HCTL_HS_EN;
  298. temp |= C0_HCTL_DWITDH; // always use 4 data lines:
  299. write32((pdat->virt + EMMC_CONTROL0), temp);
  300. return RT_EOK;
  301. }
  302. static rt_uint32_t sdhci_getdivider( rt_uint32_t sdHostVer, rt_uint32_t freq )
  303. {
  304. rt_uint32_t divisor;
  305. rt_uint32_t closest = 41666666 / freq;
  306. rt_uint32_t shiftcount = __rt_fls(closest - 1);
  307. if (shiftcount > 0) shiftcount--;
  308. if (shiftcount > 7) shiftcount = 7;
  309. if (sdHostVer > HOST_SPEC_V2)
  310. divisor = closest;
  311. else
  312. divisor = (1 << shiftcount);
  313. if (divisor <= 2) {
  314. divisor = 2;
  315. shiftcount = 0;
  316. }
  317. rt_uint32_t hi = 0;
  318. if (sdHostVer > HOST_SPEC_V2)
  319. hi = (divisor & 0x300) >> 2;
  320. rt_uint32_t lo = (divisor & 0x0ff);
  321. rt_uint32_t cdiv = (lo << 8) + hi;
  322. return cdiv;
  323. }
  324. static rt_err_t sdhci_setclock(struct sdhci_t * sdhci, rt_uint32_t clock)
  325. {
  326. rt_uint32_t temp = 0;
  327. rt_uint32_t sdHostVer = 0;
  328. int count = 100000;
  329. struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
  330. temp = read32(pdat->virt + EMMC_STATUS);
  331. while((temp & (SR_CMD_INHIBIT | SR_DAT_INHIBIT))&&(--count))
  332. bcm283x_clo_delayMicros(1);
  333. if( count <= 0 )
  334. {
  335. rt_kprintf("EMMC: Set clock: timeout waiting for inhibit flags. Status %08x.\n", temp);
  336. return RT_ERROR;
  337. }
  338. // Switch clock off.
  339. temp = read32((pdat->virt + EMMC_CONTROL1));
  340. temp |= ~C1_CLK_EN;
  341. write32((pdat->virt + EMMC_CONTROL1),temp);
  342. bcm283x_clo_delayMicros(10);
  343. // Request the new clock setting and enable the clock
  344. temp = read32(pdat->virt + EMMC_SLOTISR_VER);
  345. sdHostVer = (temp & HOST_SPEC_NUM) >> HOST_SPEC_NUM_SHIFT;
  346. int cdiv = sdhci_getdivider(sdHostVer, clock);
  347. temp = read32((pdat->virt + EMMC_CONTROL1));
  348. temp = (temp & 0xffff003f) | cdiv;
  349. write32((pdat->virt + EMMC_CONTROL1),temp);
  350. bcm283x_clo_delayMicros(10);
  351. // Enable the clock.
  352. temp = read32(pdat->virt + EMMC_CONTROL1);
  353. temp |= C1_CLK_EN;
  354. write32((pdat->virt + EMMC_CONTROL1),temp);
  355. bcm283x_clo_delayMicros(10);
  356. // Wait for clock to be stable.
  357. count = 10000;
  358. temp = read32(pdat->virt + EMMC_CONTROL1);
  359. while( !(temp & C1_CLK_STABLE) && count-- )
  360. bcm283x_clo_delayMicros(10);
  361. if( count <= 0 )
  362. {
  363. rt_kprintf("EMMC: ERROR: failed to get stable clock.\n");
  364. return RT_ERROR;
  365. }
  366. return RT_EOK;
  367. }
  368. static const struct rt_mmcsd_host_ops ops =
  369. {
  370. mmc_request_send,
  371. mmc_set_iocfg,
  372. RT_NULL,
  373. RT_NULL,
  374. };
  375. static void sdmmc_gpio_init()
  376. {
  377. int pin;
  378. for (pin = BCM_GPIO_PIN_48; pin <= BCM_GPIO_PIN_53; pin++)
  379. {
  380. bcm283x_gpio_set_pud(pin, BCM283X_GPIO_PUD_UP);
  381. bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_ALT3);
  382. }
  383. bcm283x_gpio_set_pud(pin, BCM283X_GPIO_PUD_UP);
  384. bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_INPT);
  385. }
  386. int raspi_sdmmc_init(void)
  387. {
  388. rt_uint32_t virt;
  389. rt_uint32_t id;
  390. struct rt_mmcsd_host * host = RT_NULL;
  391. struct sdhci_pdata_t * pdat = RT_NULL;
  392. struct sdhci_t * sdhci = RT_NULL;
  393. rt_kprintf("raspi_sdmmc_init start\n");
  394. #ifdef BSP_USING_SDIO0
  395. host = mmcsd_alloc_host();
  396. if (!host)
  397. {
  398. rt_kprintf("alloc host failed");
  399. goto err;
  400. }
  401. sdhci = rt_malloc(sizeof(struct sdhci_t));
  402. if (!sdhci)
  403. {
  404. rt_kprintf("alloc sdhci failed");
  405. goto err;
  406. }
  407. rt_memset(sdhci, 0, sizeof(struct sdhci_t));
  408. rt_kprintf(">> sdmmc_gpio_init\n");
  409. sdmmc_gpio_init();
  410. rt_kprintf("<< sdmmc_gpio_init\n");
  411. virt = MMC0_BASE_ADDR;
  412. pdat = (struct sdhci_pdata_t *)rt_malloc(sizeof(struct sdhci_pdata_t));
  413. RT_ASSERT(pdat != RT_NULL);
  414. pdat->virt = (rt_uint32_t)virt;
  415. sdhci->name = "sd0";
  416. sdhci->voltages = VDD_33_34;
  417. sdhci->width = MMCSD_BUSWIDTH_4;
  418. sdhci->clock = 26 * 1000 * 1000;
  419. sdhci->removeable = RT_TRUE;
  420. sdhci->detect = sdhci_detect;
  421. sdhci->setwidth = sdhci_setwidth;
  422. sdhci->setclock = sdhci_setclock;
  423. sdhci->transfer = sdhci_transfer;
  424. sdhci->priv = pdat;
  425. //write32(pdat->virt + PL180_POWER, 0xbf);
  426. host->ops = &ops;
  427. host->freq_min = 400000;
  428. host->freq_max = 50000000;
  429. host->valid_ocr = VDD_32_33 | VDD_33_34;
  430. host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ | MMCSD_BUSWIDTH_4;
  431. host->max_seg_size = 2048;
  432. host->max_dma_segs = 10;
  433. host->max_blk_size = 512;
  434. host->max_blk_count = 4096;
  435. host->private_data = sdhci;
  436. mmcsd_change(host);
  437. return RT_EOK;
  438. err:
  439. if(host) rt_free(host);
  440. if(sdhci) rt_free(sdhci);
  441. return -RT_EIO;
  442. #endif
  443. }
  444. INIT_APP_EXPORT(raspi_sdmmc_init);
  445. #endif