drv_sdhi.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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. * 2021-11-03 mazhiyuan first version
  9. */
  10. #include <drv_sdhi.h>
  11. struct ra_sdhi sdhi;
  12. #define RTHW_SDIO_LOCK(_sdio) rt_mutex_take(&_sdio->mutex, RT_WAITING_FOREVER)
  13. #define RTHW_SDIO_UNLOCK(_sdio) rt_mutex_release(&_sdio->mutex);
  14. struct rthw_sdio
  15. {
  16. struct rt_mmcsd_host *host;
  17. struct ra_sdhi sdhi_des;
  18. struct rt_event event;
  19. struct rt_mutex mutex;
  20. };
  21. static struct rt_mmcsd_host *host;
  22. ALIGN(SDIO_ALIGN_LEN)
  23. static rt_uint8_t cache_buf[SDIO_BUFF_SIZE];
  24. rt_err_t command_send(sdhi_instance_ctrl_t *p_ctrl, struct rt_mmcsd_cmd *cmd)
  25. {
  26. uint32_t wait_bit;
  27. uint32_t timeout = BUSY_TIMEOUT_US;
  28. volatile sdhi_event_t event;
  29. struct rt_mmcsd_data *data = cmd->data;
  30. while (SD_INFO2_CBSY_SDD0MON_IDLE_VAL !=
  31. (p_ctrl->p_reg->SD_INFO2 & SD_INFO2_CBSY_SDD0MON_IDLE_MASK))
  32. {
  33. if (timeout == 0)
  34. {
  35. return RT_ETIMEOUT;
  36. }
  37. R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
  38. timeout--;
  39. }
  40. p_ctrl->p_reg->SD_INFO1 = 0U;
  41. p_ctrl->p_reg->SD_INFO2 = 0U;
  42. p_ctrl->sdhi_event.word = 0U;
  43. /* Enable response end interrupt. */
  44. /* Disable access end interrupt and enable response end interrupt. */
  45. uint32_t mask = p_ctrl->p_reg->SD_INFO1_MASK;
  46. mask &= (~SDHI_INFO1_RESPONSE_END);
  47. mask |= SDHI_INFO1_ACCESS_END;
  48. p_ctrl->p_reg->SD_INFO1_MASK = mask;
  49. p_ctrl->p_reg->SD_INFO2_MASK = SDHI_INFO2_MASK_CMD_SEND;
  50. /* Write argument, then command to the SDHI peripheral. */
  51. p_ctrl->p_reg->SD_ARG = cmd->arg & UINT16_MAX;
  52. p_ctrl->p_reg->SD_ARG1 = cmd->arg >> 16;
  53. if ((cmd->flags & CMD_MASK) == CMD_ADTC)
  54. {
  55. cmd->cmd_code |= SDHI_CMD_ADTC_EN;
  56. switch (cmd->flags & RESP_MASK)
  57. {
  58. case RESP_R1:
  59. case RESP_R5:
  60. case RESP_R6:
  61. case RESP_R7:
  62. cmd->cmd_code |= SDHI_CMD_RESP_TYPE_EXT_R1_R5_R6_R7;
  63. break;
  64. case RESP_R1B:
  65. cmd->cmd_code |= SDHI_CMD_RESP_TYPE_EXT_R1B;
  66. break;
  67. case RESP_R2:
  68. cmd->cmd_code |= SDHI_CMD_RESP_TYPE_EXT_R2;
  69. break;
  70. case RESP_R3:
  71. case RESP_R4:
  72. cmd->cmd_code |= SDHI_CMD_RESP_TYPE_EXT_R3_R4;
  73. break;
  74. case RESP_NONE:
  75. cmd->cmd_code |= SDHI_CMD_RESP_TYPE_EXT_NONE;
  76. break;
  77. }
  78. if (data != RT_NULL)
  79. {
  80. if ((data->flags & 7) == DATA_DIR_WRITE)
  81. {
  82. cmd->cmd_code &= ~SDHI_CMD_DATA_DIR_READ;
  83. }
  84. else if ((data->flags & 7) == DATA_DIR_READ)
  85. {
  86. cmd->cmd_code |= SDHI_CMD_DATA_DIR_READ;
  87. }
  88. }
  89. }
  90. p_ctrl->p_reg->SD_CMD = cmd->cmd_code;
  91. timeout = 100000;
  92. while (true)
  93. {
  94. /* Check for updates to the event status. */
  95. event.word = p_ctrl->sdhi_event.word;
  96. /* Return an error if a hardware error occurred. */
  97. if (event.bit.event_error)
  98. {
  99. cmd->err = -RT_ERROR;
  100. if ((event.word & HW_SDHI_ERR_CRCE) && (resp_type(cmd) & (RESP_R3 | RESP_R4)))
  101. {
  102. if ((cmd->flags & RESP_MASK) == RESP_R2)
  103. {
  104. cmd->resp[0] = (p_ctrl->p_reg->SD_RSP76 << 8) | (p_ctrl->p_reg->SD_RSP54 >> 24);
  105. cmd->resp[1] = (p_ctrl->p_reg->SD_RSP54 << 8) | (p_ctrl->p_reg->SD_RSP32 >> 24);
  106. cmd->resp[2] = (p_ctrl->p_reg->SD_RSP32 << 8) | (p_ctrl->p_reg->SD_RSP10 >> 24);
  107. cmd->resp[3] = (p_ctrl->p_reg->SD_RSP10 << 8);
  108. }
  109. else
  110. {
  111. cmd->resp[0] = p_ctrl->p_reg->SD_RSP10;
  112. }
  113. cmd->err = RT_EOK;
  114. }
  115. if (event.word & HW_SDHI_ERR_RTIMEOUT)
  116. {
  117. cmd->err = -RT_ETIMEOUT;
  118. }
  119. if (event.word & HW_SDHI_ERR_DTIMEOUT)
  120. {
  121. data->err = -RT_ETIMEOUT;
  122. }
  123. return -RT_ERROR;
  124. }
  125. if (data != RT_NULL)
  126. {
  127. wait_bit = SDHI_WAIT_ACCESS_BIT;
  128. }
  129. else
  130. {
  131. wait_bit = SDHI_WAIT_RESPONSE_BIT;
  132. }
  133. /* If the requested bit is set, return success. */
  134. if (event.word & (1U << wait_bit))
  135. {
  136. cmd->err = RT_EOK;
  137. if ((cmd->flags & RESP_MASK) == RESP_R2)
  138. {
  139. cmd->resp[0] = (p_ctrl->p_reg->SD_RSP76 << 8) | (p_ctrl->p_reg->SD_RSP54 >> 24);
  140. cmd->resp[1] = (p_ctrl->p_reg->SD_RSP54 << 8) | (p_ctrl->p_reg->SD_RSP32 >> 24);
  141. cmd->resp[2] = (p_ctrl->p_reg->SD_RSP32 << 8) | (p_ctrl->p_reg->SD_RSP10 >> 24);
  142. cmd->resp[3] = (p_ctrl->p_reg->SD_RSP10 << 8);
  143. }
  144. else
  145. {
  146. cmd->resp[0] = p_ctrl->p_reg->SD_RSP10;
  147. }
  148. return RT_EOK;
  149. }
  150. /* Check for timeout. */
  151. timeout--;
  152. if (0U == timeout)
  153. {
  154. cmd->err = -RT_ETIMEOUT;
  155. return RT_ERROR;
  156. }
  157. /* Wait 1 us for consistent loop timing. */
  158. R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
  159. }
  160. }
  161. rt_err_t transfer_write(sdhi_instance_ctrl_t *const p_ctrl,
  162. uint32_t block_count,
  163. uint32_t bytes,
  164. const uint8_t *p_data)
  165. {
  166. transfer_info_t *p_info = p_ctrl->p_cfg->p_lower_lvl_transfer->p_cfg->p_info;
  167. /* When the SD_DMAEN.DMAEN bit is 1, set the SD_INFO2_MASK.BWEM bit to 1 and the SD_INFO2_MASK.BREM bit to 1. */
  168. p_ctrl->p_reg->SD_INFO2_MASK |= 0x300U;
  169. p_ctrl->p_reg->SD_DMAEN = 0x2U;
  170. uint32_t transfer_settings = (uint32_t)TRANSFER_MODE_BLOCK << TRANSFER_SETTINGS_MODE_BITS;
  171. transfer_settings |= TRANSFER_ADDR_MODE_INCREMENTED << TRANSFER_SETTINGS_SRC_ADDR_BITS;
  172. transfer_settings |= TRANSFER_SIZE_4_BYTE << TRANSFER_SETTINGS_SIZE_BITS;
  173. #if SDMMC_CFG_UNALIGNED_ACCESS_ENABLE
  174. if ((0U != ((uint32_t)p_data & 0x3U)) || (0U != (bytes & 3U)))
  175. {
  176. transfer_settings |= TRANSFER_IRQ_EACH << TRANSFER_SETTINGS_IRQ_BITS;
  177. transfer_settings |= TRANSFER_REPEAT_AREA_SOURCE << TRANSFER_SETTINGS_REPEAT_AREA_BITS;
  178. /* If the pointer is not 4-byte aligned or the number of bytes is not a multiple of 4, use a temporary buffer.
  179. * Transfer the first block to the temporary buffer before enabling the transfer. Subsequent blocks will be
  180. * transferred from the user buffer to the temporary buffer in an interrupt after each block transfer. */
  181. rt_memcpy((void *)&p_ctrl->aligned_buff[0], p_data, bytes);
  182. p_info->p_src = &p_ctrl->aligned_buff[0];
  183. p_ctrl->transfer_block_current = 1U;
  184. p_ctrl->transfer_blocks_total = block_count;
  185. p_ctrl->p_transfer_data = (uint8_t *)&p_data[bytes];
  186. p_ctrl->transfer_dir = SDHI_TRANSFER_DIR_WRITE;
  187. p_ctrl->transfer_block_size = bytes;
  188. }
  189. else
  190. #endif
  191. {
  192. p_info->p_src = p_data;
  193. }
  194. p_info->transfer_settings_word = transfer_settings;
  195. p_info->p_dest = (uint32_t *)(&p_ctrl->p_reg->SD_BUF0);
  196. p_info->num_blocks = (uint16_t)block_count;
  197. /* Round up to the nearest multiple of 4 bytes for the transfer. */
  198. uint32_t words = (bytes + (sizeof(uint32_t) - 1U)) / sizeof(uint32_t);
  199. p_info->length = (uint16_t)words;
  200. /* Configure the transfer driver to write to the SD buffer. */
  201. fsp_err_t err = p_ctrl->p_cfg->p_lower_lvl_transfer->p_api->reconfigure(p_ctrl->p_cfg->p_lower_lvl_transfer->p_ctrl,
  202. p_ctrl->p_cfg->p_lower_lvl_transfer->p_cfg->p_info);
  203. if (FSP_SUCCESS != err)
  204. return RT_ERROR;
  205. return RT_EOK;
  206. }
  207. rt_err_t transfer_read(sdhi_instance_ctrl_t *const p_ctrl,
  208. uint32_t block_count,
  209. uint32_t bytes,
  210. void *p_data)
  211. {
  212. transfer_info_t *p_info = p_ctrl->p_cfg->p_lower_lvl_transfer->p_cfg->p_info;
  213. /* When the SD_DMAEN.DMAEN bit is 1, set the SD_INFO2_MASK.BWEM bit to 1 and the SD_INFO2_MASK.BREM bit to 1. */
  214. p_ctrl->p_reg->SD_INFO2_MASK |= 0X300U;
  215. p_ctrl->p_reg->SD_DMAEN = 0x2U;
  216. uint32_t transfer_settings = (uint32_t)TRANSFER_MODE_BLOCK << TRANSFER_SETTINGS_MODE_BITS;
  217. transfer_settings |= TRANSFER_ADDR_MODE_INCREMENTED << TRANSFER_SETTINGS_DEST_ADDR_BITS;
  218. transfer_settings |= TRANSFER_SIZE_4_BYTE << TRANSFER_SETTINGS_SIZE_BITS;
  219. #if SDMMC_CFG_UNALIGNED_ACCESS_ENABLE
  220. /* If the pointer is not 4-byte aligned or the number of bytes is not a multiple of 4, use a temporary buffer.
  221. * Data will be transferred from the temporary buffer into the user buffer in an interrupt after each block transfer. */
  222. if ((0U != ((uint32_t)p_data & 0x3U)) || (0U != (bytes & 3U)))
  223. {
  224. transfer_settings |= TRANSFER_IRQ_EACH << TRANSFER_SETTINGS_IRQ_BITS;
  225. p_info->p_dest = &p_ctrl->aligned_buff[0];
  226. p_ctrl->transfer_block_current = 0U;
  227. p_ctrl->transfer_blocks_total = block_count;
  228. p_ctrl->p_transfer_data = (uint8_t *)p_data;
  229. p_ctrl->transfer_dir = SDHI_TRANSFER_DIR_READ;
  230. p_ctrl->transfer_block_size = bytes;
  231. }
  232. else
  233. #endif
  234. {
  235. transfer_settings |= TRANSFER_REPEAT_AREA_SOURCE << TRANSFER_SETTINGS_REPEAT_AREA_BITS;
  236. p_info->p_dest = p_data;
  237. }
  238. p_info->transfer_settings_word = transfer_settings;
  239. p_info->p_src = (uint32_t *)(&p_ctrl->p_reg->SD_BUF0);
  240. p_info->num_blocks = (uint16_t)block_count;
  241. /* Round up to the nearest multiple of 4 bytes for the transfer. */
  242. uint32_t words = (bytes + (sizeof(uint32_t) - 1U)) / sizeof(uint32_t);
  243. p_info->length = (uint16_t)words;
  244. /* Configure the transfer driver to read from the SD buffer. */
  245. fsp_err_t err = p_ctrl->p_cfg->p_lower_lvl_transfer->p_api->reconfigure(p_ctrl->p_cfg->p_lower_lvl_transfer->p_ctrl,
  246. p_ctrl->p_cfg->p_lower_lvl_transfer->p_cfg->p_info);
  247. if (err != FSP_SUCCESS)
  248. return RT_ERROR;
  249. return RT_EOK;
  250. }
  251. void ra_sdhi_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
  252. {
  253. struct rthw_sdio *sdio = host->private_data;
  254. struct rt_mmcsd_data *data;
  255. static rt_uint8_t *buffer;
  256. RTHW_SDIO_LOCK(sdio);
  257. if (req->cmd != RT_NULL)
  258. {
  259. data = req->cmd->data;
  260. if (data != RT_NULL)
  261. {
  262. rt_uint32_t size = data->blks * data->blksize;
  263. RT_ASSERT(size <= SDIO_BUFF_SIZE);
  264. buffer = (rt_uint8_t *)data->buf;
  265. if ((rt_uint32_t)data->buf & (SDIO_ALIGN_LEN - 1))
  266. {
  267. buffer = cache_buf;
  268. if (data->flags & DATA_DIR_WRITE)
  269. {
  270. rt_memcpy(cache_buf, data->buf, size);
  271. }
  272. }
  273. if (data->flags & DATA_DIR_WRITE)
  274. {
  275. transfer_write(sdio->sdhi_des.instance->p_ctrl, data->blks, data->blksize, buffer);
  276. }
  277. else if (data->flags & DATA_DIR_READ)
  278. {
  279. transfer_read(sdio->sdhi_des.instance->p_ctrl, data->blks, data->blksize, buffer);
  280. }
  281. /* Set the sector count. */
  282. if (data->blks > 1U)
  283. {
  284. ((sdhi_instance_ctrl_t *)sdio->sdhi_des.instance->p_ctrl)->p_reg->SD_STOP = 0x100U;
  285. ((sdhi_instance_ctrl_t *)sdio->sdhi_des.instance->p_ctrl)->p_reg->SD_SECCNT = data->blks;
  286. }
  287. else
  288. {
  289. ((sdhi_instance_ctrl_t *)sdio->sdhi_des.instance->p_ctrl)->p_reg->SD_STOP = 0U;
  290. }
  291. ((sdhi_instance_ctrl_t *)sdio->sdhi_des.instance->p_ctrl)->p_reg->SD_SIZE = data->blksize;
  292. }
  293. rt_enter_critical();
  294. command_send(sdio->sdhi_des.instance->p_ctrl, req->cmd);
  295. rt_exit_critical();
  296. if ((data != RT_NULL) && (data->flags & DATA_DIR_READ) && ((rt_uint32_t)data->buf & (SDIO_ALIGN_LEN - 1)))
  297. {
  298. rt_memcpy(data->buf, cache_buf, data->blksize * data->blks);
  299. }
  300. }
  301. if (req->stop != RT_NULL)
  302. {
  303. rt_enter_critical();
  304. command_send(sdio->sdhi_des.instance->p_ctrl, req->stop);
  305. rt_exit_critical();
  306. }
  307. RTHW_SDIO_UNLOCK(sdio);
  308. mmcsd_req_complete(sdio->host);
  309. }
  310. static rt_err_t clock_rate_set(sdhi_instance_ctrl_t *p_ctrl, uint32_t max_rate)
  311. {
  312. uint32_t setting = 0xFFU;
  313. /* Get the runtime frequency of the source of the SD clock */
  314. uint32_t frequency = R_FSP_SystemClockHzGet(BSP_FEATURE_SDHI_CLOCK);
  315. /* Iterate over all possible divisors, starting with the smallest, until the resulting clock rate is less than
  316. * or equal to the requested maximum rate. */
  317. for (uint32_t divisor_shift = BSP_FEATURE_SDHI_MIN_CLOCK_DIVISION_SHIFT;
  318. divisor_shift <= 9U;
  319. divisor_shift++)
  320. {
  321. if ((frequency >> divisor_shift) <= max_rate)
  322. {
  323. /* If the calculated frequency is less than or equal to the maximum supported by the device,
  324. * select this frequency. The register setting is the divisor value divided by 4, or 0xFF for no divider. */
  325. setting = divisor_shift ? ((1U << divisor_shift) >> 2U) : UINT8_MAX;
  326. /* Set the clock setting. */
  327. /* The clock register is accessible 8 SD clock counts after the last command completes. Each register access
  328. * requires at least one PCLK count, so check the register up to 8 times the maximum PCLK divisor value (512). */
  329. uint32_t timeout = 8U * 512U;
  330. while (timeout > 0U)
  331. {
  332. /* Do not write to clock control register until this bit is set. */
  333. if (p_ctrl->p_reg->SD_INFO2_b.SD_CLK_CTRLEN)
  334. {
  335. /* Set the calculated divider and enable clock output to start the 74 clocks required before
  336. * initialization. Do not change the automatic clock control setting. */
  337. uint32_t clkctrlen = p_ctrl->p_reg->SD_CLK_CTRL & (1U << 9);
  338. p_ctrl->p_reg->SD_CLK_CTRL = setting | clkctrlen | (1U << 8);
  339. p_ctrl->device.clock_rate = frequency >> divisor_shift;
  340. return RT_EOK;
  341. }
  342. timeout--;
  343. }
  344. /* Valid setting already found, stop looking. */
  345. break;
  346. }
  347. }
  348. return RT_ERROR;
  349. }
  350. void ra_sdhi_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
  351. {
  352. struct rthw_sdio *sdio = host->private_data;
  353. RTHW_SDIO_LOCK(sdio);
  354. if (io_cfg->bus_width == MMCSD_BUS_WIDTH_1)
  355. {
  356. ((sdhi_instance_ctrl_t *)sdio->sdhi_des.instance->p_ctrl)->p_reg->SD_OPTION_b.WIDTH = 1;
  357. }
  358. else if (io_cfg->bus_width == MMCSD_BUS_WIDTH_4)
  359. {
  360. ((sdhi_instance_ctrl_t *)sdio->sdhi_des.instance->p_ctrl)->p_reg->SD_OPTION_b.WIDTH = 0;
  361. ((sdhi_instance_ctrl_t *)sdio->sdhi_des.instance->p_ctrl)->p_reg->SD_OPTION_b.WIDTH8 = 0;
  362. }
  363. else if (io_cfg->bus_width == MMCSD_BUS_WIDTH_8)
  364. {
  365. ((sdhi_instance_ctrl_t *)sdio->sdhi_des.instance->p_ctrl)->p_reg->SD_OPTION_b.WIDTH = 0;
  366. ((sdhi_instance_ctrl_t *)sdio->sdhi_des.instance->p_ctrl)->p_reg->SD_OPTION_b.WIDTH8 = 1;
  367. }
  368. clock_rate_set(sdio->sdhi_des.instance->p_ctrl, io_cfg->clock);
  369. RTHW_SDIO_UNLOCK(sdio);
  370. }
  371. rt_int32_t ra_sdhi_get_card_status(struct rt_mmcsd_host *host)
  372. {
  373. sdmmc_status_t status;
  374. struct rthw_sdio *sdio = host->private_data;
  375. sdio->sdhi_des.instance->p_api->statusGet(sdio->sdhi_des.instance->p_ctrl, &status);
  376. return status.card_inserted;
  377. }
  378. void ra_sdhi_enable_sdio_irq(struct rt_mmcsd_host *host, rt_int32_t en)
  379. {
  380. struct rthw_sdio *sdio = host->private_data;
  381. sdio->sdhi_des.instance->p_api->ioIntEnable(sdio->sdhi_des.instance->p_ctrl, en);
  382. }
  383. struct rt_mmcsd_host_ops ra_sdhi_ops =
  384. {
  385. .request = ra_sdhi_request,
  386. .set_iocfg = ra_sdhi_set_iocfg,
  387. .get_card_status = ra_sdhi_get_card_status,
  388. .enable_sdio_irq = ra_sdhi_enable_sdio_irq
  389. };
  390. void sdhi_callback(sdmmc_callback_args_t *p_args)
  391. {
  392. }
  393. struct rt_mmcsd_host *sdio_host_create(struct ra_sdhi *sdhi_des)
  394. {
  395. struct rt_mmcsd_host *host;
  396. struct rthw_sdio *sdio = RT_NULL;
  397. if (sdhi_des == RT_NULL)
  398. return RT_NULL;
  399. sdio = rt_malloc(sizeof(struct rthw_sdio));
  400. if (sdio == RT_NULL)
  401. return RT_NULL;
  402. rt_memset(sdio, 0, sizeof(struct rthw_sdio));
  403. host = mmcsd_alloc_host();
  404. if (host == RT_NULL)
  405. {
  406. rt_free(sdio);
  407. return RT_NULL;
  408. }
  409. rt_memcpy(&sdio->sdhi_des, sdhi_des, sizeof(struct ra_sdhi));
  410. rt_event_init(&sdio->event, "sdio", RT_IPC_FLAG_FIFO);
  411. rt_mutex_init(&sdio->mutex, "sdio", RT_IPC_FLAG_FIFO);
  412. /* set host defautl attributes */
  413. host->ops = &ra_sdhi_ops;
  414. host->freq_min = 400 * 1000;
  415. host->freq_max = SDIO_MAX_FREQ;
  416. host->valid_ocr = 0X00FFFF80; /* The voltage range supported is 1.65v-3.6v */
  417. #ifndef SDHI_USING_1_BIT
  418. host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_SDIO_IRQ;
  419. #else
  420. host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_SDIO_IRQ;
  421. #endif
  422. host->max_seg_size = SDIO_BUFF_SIZE;
  423. host->max_dma_segs = 1;
  424. host->max_blk_size = 512;
  425. host->max_blk_count = 512;
  426. /* link up host and sdio */
  427. sdio->host = host;
  428. host->private_data = sdio;
  429. ra_sdhi_enable_sdio_irq(host, 1);
  430. /* ready to change */
  431. mmcsd_change(host);
  432. return host;
  433. }
  434. int rt_hw_sdhi_init(void)
  435. {
  436. sdhi.instance = &g_sdmmc0;
  437. sdhi.instance->p_api->open(sdhi.instance->p_ctrl, sdhi.instance->p_cfg);
  438. host = sdio_host_create(&sdhi);
  439. if (host == RT_NULL)
  440. {
  441. return -1;
  442. }
  443. return 0;
  444. }
  445. INIT_DEVICE_EXPORT(rt_hw_sdhi_init);