drv_mmc.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. /*
  2. * File : drv_mmc.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2013 - 2015, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2013-03-09 aozima the first version
  13. * 2013-03-29 aozima support Jz4770.
  14. * 2013-04-01 aozima add interrupt support for Jz4770.
  15. */
  16. #include <rthw.h>
  17. #include <rtthread.h>
  18. #include <rtdevice.h>
  19. #include <drivers/mmcsd_core.h>
  20. #include <drivers/sdio.h>
  21. #include "board.h"
  22. #include "drv_gpio.h"
  23. #include "drv_clock.h"
  24. #include "drv_mmc.h"
  25. #define RT_USING_MSC0
  26. #define RT_USING_MSC1
  27. // #define JZ47XX_SDIO_DBG
  28. #ifdef JZ47XX_SDIO_DBG
  29. #define sdio_dbg(fmt, ...) rt_kprintf("[SDIO]");rt_kprintf(fmt, ##__VA_ARGS__)
  30. #else
  31. #define sdio_dbg(fmt, ...)
  32. #endif
  33. static void msc_handler(int irqno, void* param)
  34. {
  35. struct jz47xx_sdio * jz_sdio = (struct jz47xx_sdio *)param;
  36. /* disable interrupt */
  37. rt_hw_interrupt_mask(jz_sdio->irqno);
  38. rt_completion_done(&jz_sdio->completion);
  39. }
  40. rt_inline void jz_mmc_clk_autoctrl(struct jz47xx_sdio *host, unsigned int on)
  41. {
  42. if(on)
  43. {
  44. if(!clk_is_enabled(host->clock))
  45. clk_enable(host->clock);
  46. if(!clk_is_enabled(host->clock_gate))
  47. clk_enable(host->clock_gate);
  48. }
  49. else
  50. {
  51. if(clk_is_enabled(host->clock_gate))
  52. clk_disable(host->clock_gate);
  53. if(clk_is_enabled(host->clock))
  54. clk_disable(host->clock);
  55. }
  56. }
  57. /* Stop the MMC clock and wait while it happens */
  58. rt_inline rt_err_t jz_mmc_stop_clock(uint32_t hw_base)
  59. {
  60. uint16_t value;
  61. int timeout = 10000;
  62. value = readw(hw_base + MSC_CTRL_OFFSET);
  63. value |= MSC_CTRL_CLOCK_STOP;
  64. writew(value, hw_base + MSC_CTRL_OFFSET);
  65. while (timeout && (readl(hw_base + MSC_STAT_OFFSET) & MSC_STAT_CLK_EN))
  66. {
  67. timeout--;
  68. if (timeout == 0)
  69. {
  70. return -RT_ETIMEOUT;
  71. }
  72. rt_thread_delay(1);
  73. }
  74. return RT_EOK;
  75. }
  76. /* Start the MMC clock and operation */
  77. rt_inline void jz_mmc_start_clock(uint32_t hw_base)
  78. {
  79. uint16_t value;
  80. value = readw(hw_base + MSC_CTRL_OFFSET);
  81. value |= (MSC_CTRL_CLOCK_START | MSC_CTRL_START_OP);
  82. writew(value, hw_base + MSC_CTRL_OFFSET);
  83. }
  84. static int jz_mmc_hardware_init(struct jz47xx_sdio * jz_sdio)
  85. {
  86. uint32_t hw_base = jz_sdio->hw_base;
  87. uint32_t value;
  88. /* reset mmc/sd controller */
  89. value = readl(hw_base + MSC_CTRL_OFFSET);
  90. value |= MSC_CTRL_RESET;
  91. writel(value, hw_base + MSC_CTRL_OFFSET);
  92. rt_thread_delay(1);
  93. value &= ~MSC_CTRL_RESET;
  94. writel(value, hw_base + MSC_CTRL_OFFSET);
  95. while(readl(hw_base + MSC_STAT_OFFSET) & MSC_STAT_IS_RESETTING);
  96. /* mask all IRQs */
  97. writel(0xffffffff, hw_base + MSC_IMASK_OFFSET);
  98. writel(0xffffffff, hw_base + MSC_IREG_OFFSET);
  99. /* set timeout */
  100. writel(0x100, hw_base + MSC_RESTO_OFFSET);
  101. writel(0x1ffffff, hw_base + MSC_RDTO_OFFSET);
  102. /* stop MMC/SD clock */
  103. jz_mmc_stop_clock(hw_base);
  104. }
  105. /* Set the MMC clock frequency */
  106. void jz_mmc_set_clock(struct jz47xx_sdio * jz_sdio, unsigned int clock)
  107. {
  108. unsigned int msc_clock = jz_sdio->msc_clock;
  109. /* calc and set MSC_CLKRT. */
  110. {
  111. unsigned int div = 0;
  112. while (clock < msc_clock)
  113. {
  114. div++;
  115. msc_clock >>= 1;
  116. }
  117. if(div > 7) div = 7;
  118. sdio_dbg("msc_clock: %u, SDIO_CLK: %u, MSC_CLKRT: %u\r\n", jz_sdio->msc_clock, clock, div);
  119. writew(div, jz_sdio->hw_base + MSC_CLKRT_OFFSET);
  120. }
  121. }
  122. /* RT-Thread SDIO interface */
  123. static void jz47xx_sdio_request(struct rt_mmcsd_host *host,
  124. struct rt_mmcsd_req *req)
  125. {
  126. struct jz47xx_sdio *sdio = host->private_data;
  127. unsigned int cmdat = 0;
  128. unsigned int stat;
  129. uint32_t hw_base, value;
  130. hw_base = sdio->hw_base;
  131. jz_mmc_stop_clock(hw_base);
  132. sdio_dbg("CMD: %d ARG: %08X\n", req->cmd->cmd_code, req->cmd->arg);
  133. if(sdio->flag & MSC_CMDAT_BUS_WIDTH_4BIT)
  134. {
  135. cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT;
  136. }
  137. /* auto send stop */
  138. if (req->stop)
  139. {
  140. sdio_dbg("CMD STOP: %d ARG: %08X\n", req->stop->cmd_code,
  141. req->stop->arg);
  142. cmdat |= MSC_CMDAT_SEND_AS_STOP;
  143. }
  144. if(req->cmd->cmd_code == GO_IDLE_STATE)
  145. {
  146. cmdat |= MSC_CMDAT_INIT;
  147. }
  148. /* clear status */
  149. writew(0xFFFF, hw_base + MSC_IREG_OFFSET);
  150. /* open interrupt */
  151. value = readl(hw_base + MSC_IMASK_OFFSET);
  152. value &= ~(MSC_DATA_TRAN_DONE | MSC_PRG_DONE | MSC_END_CMD_RES);
  153. writel(value, hw_base + MSC_IMASK_OFFSET);
  154. if(req->data)
  155. {
  156. writew(req->data->blksize, hw_base + MSC_BLKLEN_OFFSET);
  157. writew(req->data->blks, hw_base + MSC_NOB_OFFSET);
  158. cmdat |= MSC_CMDAT_DATA_EN;
  159. if (req->data->flags & DATA_DIR_WRITE)
  160. {
  161. cmdat |= MSC_CMDAT_WRITE;
  162. }
  163. else if (req->data->flags & DATA_DIR_READ)
  164. {
  165. cmdat |= MSC_CMDAT_READ;
  166. }
  167. }
  168. else
  169. {
  170. writew(0, hw_base + MSC_BLKLEN_OFFSET);
  171. writew(0, hw_base + MSC_NOB_OFFSET);
  172. }
  173. /* set command */
  174. writeb(req->cmd->cmd_code, hw_base + MSC_CMD_OFFSET);
  175. /* set argument */
  176. writel(req->cmd->arg, hw_base + MSC_ARG_OFFSET);
  177. /* Set response type */
  178. #ifdef JZ47XX_SDIO_DBG
  179. {
  180. int res_type = req->cmd->flags & RESP_MASK;
  181. sdio_dbg("resp type:%u\r\n", res_type);
  182. }
  183. #endif
  184. cmdat &= ~(MSC_CMDAT_RESP_FORMAT_MASK);
  185. switch (req->cmd->flags & RESP_MASK)
  186. {
  187. case RESP_NONE:
  188. break;
  189. case RESP_R1B:
  190. cmdat |= MSC_CMDAT_BUSY;
  191. /*FALLTHRU*/
  192. case RESP_R1:
  193. cmdat |= MSC_CMDAT_RESPONSE_R1;
  194. break;
  195. case RESP_R2:
  196. cmdat |= MSC_CMDAT_RESPONSE_R2;
  197. break;
  198. case RESP_R3:
  199. cmdat |= MSC_CMDAT_RESPONSE_R3;
  200. break;
  201. case RESP_R4:
  202. cmdat |= MSC_CMDAT_RESPONSE_R4;
  203. break;
  204. case RESP_R5:
  205. cmdat |= MSC_CMDAT_RESPONSE_R5;
  206. break;
  207. case RESP_R6:
  208. cmdat |= MSC_CMDAT_RESPONSE_R6;
  209. case RESP_R7:
  210. cmdat |= MSC_CMDAT_RESPONSE_R7;
  211. break;
  212. default:
  213. break;
  214. }
  215. /* Set command */
  216. sdio_dbg("cmdat: %08X\r\n", cmdat);
  217. writel(cmdat, sdio->hw_base + MSC_CMDAT_OFFSET);
  218. writel(MSC_CTRL_START_OP, sdio->hw_base + MSC_CTRL_OFFSET);
  219. writel(0xFF, sdio->hw_base + MSC_RESTO_OFFSET);
  220. writel(0xFFFFFFFF, sdio->hw_base + MSC_RDTO_OFFSET);
  221. jz_mmc_start_clock(sdio->hw_base);
  222. req->cmd->err = RT_EOK;
  223. if(!(readl(sdio->hw_base + MSC_IREG_OFFSET) & MSC_END_CMD_RES))
  224. {
  225. rt_err_t ret;
  226. rt_completion_init(&sdio->completion);
  227. rt_hw_interrupt_umask(sdio->irqno);
  228. ret = rt_completion_wait(&sdio->completion, RT_TICK_PER_SECOND);
  229. if(ret == RT_EOK)
  230. {
  231. sdio_dbg("wait END_CMD_RES OK!\r\n");
  232. }
  233. else
  234. {
  235. uint32_t value;
  236. value = readl(hw_base + MSC_STAT_OFFSET);
  237. sdio_dbg("stat=0x%08x\n", value);
  238. value = readl(hw_base + MSC_IREG_OFFSET);
  239. sdio_dbg("iflag=0x%08x\n", value);
  240. req->cmd->err = ret;
  241. sdio_dbg("wait END_CMD_RES timeout[uncompletion]\r\n");
  242. }
  243. }
  244. else
  245. {
  246. sdio_dbg("no need wait MSC_END_CMD_RES!\r\n");
  247. }
  248. stat = readl(hw_base + MSC_STAT_OFFSET);
  249. writew(MSC_END_CMD_RES, hw_base + MSC_IREG_OFFSET);
  250. /* get response. */
  251. {
  252. uint8_t buf[16];
  253. uint32_t data;
  254. if(req->cmd->err == RT_EOK)
  255. {
  256. if(stat & MSC_STAT_TIME_OUT_RES)
  257. {
  258. sdio_dbg("ERR: MSC_STAT_TIME_OUT_RES\r\n");
  259. req->cmd->err = -RT_ETIMEOUT;
  260. }
  261. else if(stat & MSC_STAT_CRC_READ_ERR)
  262. {
  263. sdio_dbg("ERR: MSC_STAT_CRC_READ_ERR\r\n");
  264. req->cmd->err = -1;
  265. }
  266. }
  267. switch (req->cmd->flags & RESP_MASK)
  268. {
  269. case RESP_R1:
  270. case RESP_R1B:
  271. case RESP_R6:
  272. case RESP_R3:
  273. case RESP_R4:
  274. case RESP_R5:
  275. case RESP_R7:
  276. data = readw(sdio->hw_base + MSC_RES_OFFSET);
  277. buf[1] = data & 0xFF;
  278. data = readw(sdio->hw_base + MSC_RES_OFFSET);
  279. buf[2] = (data >> 8) & 0xFF;
  280. buf[3] = data & 0xFF;
  281. data = readw(sdio->hw_base + MSC_RES_OFFSET);
  282. buf[4] = data & 0xFF;
  283. req->cmd->resp[0] = buf[1] << 24 | buf[2] << 16
  284. | buf[3] << 8 | buf[4];
  285. break;
  286. case RESP_R2:
  287. {
  288. uint32_t i, v, w1, w2;
  289. data = readw(sdio->hw_base + MSC_RES_OFFSET);
  290. v = data & 0xFFFF;
  291. for(i=0; i<4; i++)
  292. {
  293. data = readw(sdio->hw_base + MSC_RES_OFFSET);
  294. w1 = data & 0xFFFF;
  295. data = readw(sdio->hw_base + MSC_RES_OFFSET);
  296. w2 = data & 0xFFFF;
  297. req->cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8;
  298. v = w2;
  299. }
  300. }
  301. break;
  302. default:
  303. break;
  304. }
  305. sdio_dbg("error:%d cmd->resp [%08X, %08X, %08X, %08X]\r\n\r\n",
  306. req->cmd->err,
  307. req->cmd->resp[0],
  308. req->cmd->resp[1],
  309. req->cmd->resp[2],
  310. req->cmd->resp[3]
  311. );
  312. }
  313. if(req->data)
  314. {
  315. unsigned int waligned;
  316. uint32_t len = req->data->blksize * req->data->blks;
  317. /* word aligned ? */
  318. waligned = (((unsigned int)req->data->buf & 0x3) == 0);
  319. if (req->data->flags & DATA_DIR_WRITE)
  320. {
  321. if(waligned)
  322. {
  323. uint32_t i;
  324. uint32_t *src = (uint32_t *)req->data->buf;
  325. for(i=0; i<len; i+=4)
  326. {
  327. while (readl(sdio->hw_base + MSC_STAT_OFFSET) & MSC_STAT_DATA_FIFO_FULL);
  328. writel(*src++, hw_base + MSC_TXFIFO_OFFSET);
  329. }
  330. }
  331. else
  332. {
  333. uint32_t i, data;
  334. uint8_t * src = (uint8_t *)req->data->buf;
  335. for(i=0; i<len; i+=4)
  336. {
  337. while (readl(sdio->hw_base + MSC_STAT_OFFSET) & MSC_STAT_DATA_FIFO_FULL);
  338. data = (*src++ << 0);
  339. data |= (*src++ << 8);
  340. data |= (*src++ << 16);
  341. data |= (*src++ << 24);
  342. writel(data, hw_base + MSC_TXFIFO_OFFSET);
  343. }
  344. }
  345. writel(IFLG_PRG_DONE, hw_base + MSC_IREG_OFFSET);
  346. }
  347. else if (req->data->flags & DATA_DIR_READ)
  348. {
  349. if(waligned)
  350. {
  351. uint32_t i;
  352. uint32_t * dst = (uint32_t *)req->data->buf;
  353. for(i=0; i<len; i+=4)
  354. {
  355. while (readl(sdio->hw_base + MSC_STAT_OFFSET) & MSC_STAT_DATA_FIFO_EMPTY);
  356. *dst ++ = readl(sdio->hw_base + MSC_RXFIFO_OFFSET);
  357. }
  358. }
  359. else
  360. {
  361. uint32_t data, i;
  362. uint8_t * dst = (uint8_t *)req->data->buf;
  363. for(i=0; i<len; i+=4)
  364. {
  365. while (readl(sdio->hw_base + MSC_STAT_OFFSET) & MSC_STAT_DATA_FIFO_EMPTY);
  366. data = readl(sdio->hw_base + MSC_RXFIFO_OFFSET);
  367. *dst++ = (uint8_t)(data >> 0);
  368. *dst++ = (uint8_t)(data >> 8);
  369. *dst++ = (uint8_t)(data >> 16);
  370. *dst++ = (uint8_t)(data >> 24);
  371. }
  372. }
  373. writel(IFLG_DATA_TRAN_DONE, hw_base + MSC_IREG_OFFSET);
  374. }
  375. #if 0
  376. value = readl(hw_base + MSC_IMASK_OFFSET);
  377. value &= ~MSC_DATA_TRAN_DONE;
  378. writel(value, hw_base + MSC_IMASK_OFFSET);
  379. if(!(readl(sdio->hw_base + MSC_IREG_OFFSET) & MSC_DATA_TRAN_DONE))
  380. {
  381. rt_err_t ret;
  382. rt_completion_init(&sdio->completion);
  383. sdio_dbg("TRAN_DONE umask\r\n");
  384. rt_hw_interrupt_umask(sdio->irqno);
  385. ret = rt_completion_wait(&sdio->completion, RT_TICK_PER_SECOND);
  386. if(ret == RT_EOK)
  387. {
  388. sdio_dbg("wait END_CMD_RES OK!\r\n");
  389. }
  390. else
  391. {
  392. rt_kprintf("SD DATA: int status 0x%08x\n", readl(sdio->hw_base + MSC_IREG_OFFSET));
  393. sdio_dbg("wait END_CMD_RES timeout!\r\n");
  394. }
  395. }
  396. else
  397. {
  398. sdio_dbg("no need wait MSC_DATA_TRAN_DONE!\r\n");
  399. }
  400. #endif
  401. /* clear status */
  402. writew(MSC_DATA_TRAN_DONE, hw_base + MSC_IREG_OFFSET);
  403. } /* if req->data */
  404. mmcsd_req_complete(host);
  405. }
  406. static void jz47xx_sdio_set_iocfg(struct rt_mmcsd_host *host,
  407. struct rt_mmcsd_io_cfg *io_cfg)
  408. {
  409. struct jz47xx_sdio * jz_sdio = host->private_data;
  410. rt_uint32_t clkdiv;
  411. sdio_dbg("set_iocfg clock: %d\n", io_cfg->clock);
  412. if (io_cfg->bus_width == MMCSD_BUS_WIDTH_4)
  413. {
  414. sdio_dbg("MMC: Setting controller bus width to 4\n");
  415. jz_sdio->flag |= MSC_CMDAT_BUS_WIDTH_4BIT;
  416. }
  417. else
  418. {
  419. jz_sdio->flag &= ~(MSC_CMDAT_BUS_WIDTH_4BIT);
  420. sdio_dbg("MMC: Setting controller bus width to 1\n");
  421. }
  422. if (io_cfg->clock)
  423. {
  424. unsigned int clk_set = 0, clkrt = 0;
  425. unsigned int clk_want = io_cfg->clock;
  426. unsigned int lpm = 0;
  427. if (io_cfg->clock > 1 * 1000 * 1000)
  428. {
  429. io_cfg->clock = 1000 * 1000;
  430. }
  431. jz_mmc_clk_autoctrl(jz_sdio, 1);
  432. if (clk_want > 3000000)
  433. {
  434. clk_set_rate(jz_sdio->clock, io_cfg->clock);
  435. }
  436. else
  437. {
  438. clk_set_rate(jz_sdio->clock, 24000000);
  439. }
  440. clk_set = clk_get_rate(jz_sdio->clock);
  441. while (clk_want < clk_set)
  442. {
  443. clkrt++;
  444. clk_set >>= 1;
  445. }
  446. if (clkrt > 7)
  447. {
  448. sdio_dbg("invalid value of CLKRT: "
  449. "ios->clock=%d clk_want=%d "
  450. "clk_set=%d clkrt=%X,\n",
  451. io_cfg->clock, clk_want, clk_set, clkrt);
  452. return;
  453. }
  454. if (!clkrt)
  455. {
  456. sdio_dbg("clk_want: %u, clk_set: %luHz\n", io_cfg->clock, clk_get_rate(jz_sdio->clock));
  457. }
  458. writel(clkrt, jz_sdio->hw_base + MSC_CLKRT_OFFSET);
  459. if (clk_set > 25000000)
  460. {
  461. lpm = (0x2 << LPM_DRV_SEL_SHF) | LPM_SMP_SEL;
  462. }
  463. if(jz_sdio->sdio_clk)
  464. {
  465. writel(lpm, jz_sdio->hw_base + MSC_LPM_OFFSET);
  466. writel(MSC_CTRL_CLOCK_START, jz_sdio->hw_base + MSC_CTRL_OFFSET);
  467. }
  468. else
  469. {
  470. lpm |= LPM_LPM;
  471. writel(lpm, jz_sdio->hw_base + MSC_LPM_OFFSET);
  472. }
  473. }
  474. else
  475. {
  476. jz_mmc_clk_autoctrl(jz_sdio, 0);
  477. }
  478. /* maybe switch power to the card */
  479. switch (io_cfg->power_mode)
  480. {
  481. case MMCSD_POWER_OFF:
  482. sdio_dbg("MMCSD_POWER_OFF\r\n");
  483. break;
  484. case MMCSD_POWER_UP:
  485. sdio_dbg("MMCSD_POWER_UP\r\n");
  486. break;
  487. case MMCSD_POWER_ON:
  488. sdio_dbg("MMCSD_POWER_ON\r\n");
  489. jz_mmc_hardware_init(jz_sdio);
  490. // jz_mmc_set_clock(jz_sdio, io_cfg->clock);
  491. break;
  492. default:
  493. sdio_dbg("unknown power_mode %d\n", io_cfg->power_mode);
  494. break;
  495. }
  496. }
  497. static rt_int32_t jz47xx_SD_Detect(struct rt_mmcsd_host *host)
  498. {
  499. sdio_dbg("jz47xx_SD_Detect\n");
  500. }
  501. static void jz47xx_sdio_enable_sdio_irq(struct rt_mmcsd_host *host,
  502. rt_int32_t enable)
  503. {
  504. sdio_dbg("jz47xx_sdio_enable_sdio_irq, enable:%d\n", enable);
  505. }
  506. static const struct rt_mmcsd_host_ops ops =
  507. {
  508. jz47xx_sdio_request,
  509. jz47xx_sdio_set_iocfg,
  510. jz47xx_SD_Detect,
  511. jz47xx_sdio_enable_sdio_irq,
  512. };
  513. int jz47xx_sdio_init(void)
  514. {
  515. struct rt_mmcsd_host *host = RT_NULL;
  516. struct jz47xx_sdio * jz_sdio = RT_NULL;
  517. #ifdef RT_USING_MSC0
  518. host = mmcsd_alloc_host();
  519. jz_sdio = rt_malloc(sizeof(struct jz47xx_sdio));
  520. if(!(host && jz_sdio))
  521. {
  522. goto err;
  523. }
  524. rt_memset(jz_sdio, 0, sizeof(struct jz47xx_sdio));
  525. /* set hardware base firstly */
  526. jz_sdio->hw_base = MSC0_BASE;
  527. jz_sdio->clock = clk_get("cgu_msc0");
  528. jz_sdio->clock_gate = clk_get("msc0");
  529. /* init GPIO (msc0 boot)
  530. * name pin fun
  531. * X1000 MSC0_D0: PA23 1
  532. * X1000 MSC0_D1: PA22 1
  533. * X1000 MSC0_D2: PA21 1
  534. * X1000 MSC0_D3: PA20 1
  535. * X1000 MSC0_CMD: PA25 1
  536. * X1000 MSC0_CLK: PA24 1
  537. */
  538. {
  539. gpio_set_func(GPIO_PORT_A, GPIO_Pin_20, GPIO_FUNC_1);
  540. gpio_set_func(GPIO_PORT_A, GPIO_Pin_21, GPIO_FUNC_1);
  541. gpio_set_func(GPIO_PORT_A, GPIO_Pin_22, GPIO_FUNC_1);
  542. gpio_set_func(GPIO_PORT_A, GPIO_Pin_23, GPIO_FUNC_1);
  543. gpio_set_func(GPIO_PORT_A, GPIO_Pin_24, GPIO_FUNC_1);
  544. gpio_set_func(GPIO_PORT_A, GPIO_Pin_25, GPIO_FUNC_1);
  545. }
  546. /* enable MSC0 clock gate. */
  547. clk_enable(jz_sdio->clock_gate);
  548. jz_sdio->msc_clock = 24UL * 1000 * 1000; /* 50Mhz */
  549. host->freq_min = 400 * 1000; /* min 400Khz. */
  550. host->freq_max = 24 * 1000 * 1000; /* max 50Mhz. */
  551. /* set clock */
  552. clk_set_rate(jz_sdio->clock, BOARD_EXTAL_CLK);
  553. host->ops = &ops;
  554. host->valid_ocr = VDD_27_28 | VDD_28_29 | VDD_29_30 | VDD_30_31 | VDD_31_32 |
  555. VDD_32_33 | VDD_33_34 | VDD_34_35 | VDD_35_36;
  556. host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED;
  557. host->max_seg_size = 65535;
  558. host->max_dma_segs = 2;
  559. host->max_blk_size = 512;
  560. host->max_blk_count = 4096;
  561. host->private_data = jz_sdio;
  562. jz_sdio->host = host;
  563. jz_sdio->irqno = IRQ_MSC0;
  564. rt_hw_interrupt_install(jz_sdio->irqno, msc_handler, jz_sdio, "msc0");
  565. rt_hw_interrupt_mask(jz_sdio->irqno);
  566. mmcsd_change(host);
  567. #endif // RT_USING_MSC0
  568. #ifdef RT_USING_MSC1
  569. host = mmcsd_alloc_host();
  570. jz_sdio = rt_malloc(sizeof(struct jz47xx_sdio));
  571. if(!(host && jz_sdio))
  572. {
  573. goto err;
  574. }
  575. rt_memset(jz_sdio, 0, sizeof(struct jz47xx_sdio));
  576. jz_sdio->hw_base = MSC1_BASE;
  577. jz_sdio->clock = clk_get("cgu_msc1");
  578. jz_sdio->clock_gate = clk_get("msc1");
  579. /* init GPIO (paladin msc1 SDIO wifi)
  580. * name pin fun
  581. * X1000 MSC1_D0: PC02 0
  582. * X1000 MSC1_D1: PC03 0
  583. * X1000 MSC1_D2: PC04 0
  584. * X1000 MSC1_D3: PC05 0
  585. * X1000 MSC1_CMD: PC01 0
  586. * X1000 MSC1_CLK: PC00 0
  587. *
  588. */
  589. {
  590. gpio_set_func(GPIO_PORT_C, GPIO_Pin_0, GPIO_FUNC_0);
  591. gpio_set_func(GPIO_PORT_C, GPIO_Pin_1, GPIO_FUNC_0);
  592. gpio_set_func(GPIO_PORT_C, GPIO_Pin_2, GPIO_FUNC_0);
  593. gpio_set_func(GPIO_PORT_C, GPIO_Pin_3, GPIO_FUNC_0);
  594. gpio_set_func(GPIO_PORT_C, GPIO_Pin_4, GPIO_FUNC_0);
  595. gpio_set_func(GPIO_PORT_C, GPIO_Pin_5, GPIO_FUNC_0);
  596. }
  597. /* enable MSC1 clock gate. */
  598. clk_enable(jz_sdio->clock_gate);
  599. jz_sdio->msc_clock = 50UL * 1000 * 1000; /* 50Mhz */
  600. host->freq_min = 400 * 1000; /* min 400Khz. */
  601. host->freq_max = 50 * 1000 * 1000; /* max 50Mhz. */
  602. /* set clock */
  603. clk_set_rate(jz_sdio->clock, BOARD_EXTAL_CLK);
  604. host->ops = &ops;
  605. host->valid_ocr = VDD_27_28 | VDD_28_29 | VDD_29_30 | VDD_30_31 | VDD_31_32 |
  606. VDD_32_33 | VDD_33_34 | VDD_34_35 | VDD_35_36;
  607. host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE;
  608. host->max_seg_size = 65535;
  609. host->max_dma_segs = 2;
  610. host->max_blk_size = 512;
  611. host->max_blk_count = 4096;
  612. host->private_data = jz_sdio;
  613. jz_sdio->host = host;
  614. jz_sdio->irqno = IRQ_MSC1;
  615. rt_hw_interrupt_install(jz_sdio->irqno, msc_handler, jz_sdio, "msc1");
  616. rt_hw_interrupt_mask(jz_sdio->irqno);
  617. mmcsd_change(host);
  618. #endif // RT_USING_MSC1
  619. return RT_EOK;
  620. err:
  621. if(host)
  622. {
  623. mmcsd_free_host(host);
  624. }
  625. if(jz_sdio)
  626. {
  627. rt_free(host);
  628. }
  629. return -RT_ENOMEM;
  630. }