drv_sdhi.c 18 KB

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