hpm_sdmmc_host.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. /*
  2. * Copyright (c) 2021-2024 HPMicro
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. */
  7. #include "hpm_sdmmc_common.h"
  8. #include "hpm_sdmmc_host.h"
  9. #include "board.h"
  10. #define HPM_SDMMC_HOST_TIMEOUT_DEFAULT (1000UL)
  11. static void sdmmchost_power_control(const sdmmc_host_t *host, hpm_sdmmc_power_option_t option);
  12. static void sdmmchost_switch_to_3v3_as_needed(const sdmmc_host_t *host);
  13. static hpm_stat_t sdmmchost_check_host_availability(sdmmc_host_t *host);
  14. static hpm_stat_t sdmmchost_check_host_availability(sdmmc_host_t *host)
  15. {
  16. hpm_stat_t status = status_success;
  17. if (!sdmmchost_is_card_detected(host)) {
  18. status = status_sdmmc_no_sd_card_inserted;
  19. host->card_inserted = false;
  20. host->card_init_done = false;
  21. }
  22. return status;
  23. }
  24. void sdmmchost_delay_ms(const sdmmc_host_t *host, uint32_t ms)
  25. {
  26. hpm_sdmmc_osal_delay((void *)host, ms);
  27. }
  28. static void sdmmchost_switch_to_3v3_as_needed(const sdmmc_host_t *host)
  29. {
  30. if (IS_HPM_BITMASK_SET(host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_3V3)) {
  31. sdmmchost_vsel_pin_control(host, hpm_sdmmc_io_voltage_3v3);
  32. }
  33. }
  34. hpm_stat_t sdmmchost_init(sdmmc_host_t *host)
  35. {
  36. hpm_stat_t status = status_invalid_argument;
  37. do {
  38. HPM_BREAK_IF(host == NULL);
  39. /* Initialize clock for the identification stage */
  40. host->clock_freq = host->host_param.clock_init_func(host->host_param.base, SDMMC_CLOCK_400KHZ, true);
  41. host->operation_mode = hpm_sdmmc_operation_mode_inactive;
  42. sdmmchost_init_io(host, host->operation_mode);
  43. sdmmchost_power_control(host, hpm_sdmmc_power_off);
  44. sdmmchost_delay_ms(host, 36);
  45. sdmmchost_switch_to_3v3_as_needed(host);
  46. sdmmchost_delay_ms(host, 36);
  47. sdmmchost_power_control(host, hpm_sdmmc_power_on);
  48. sdxc_config_t sdxc_config;
  49. sdxc_config.data_timeout = 1000; /* Data timeout interval, configure to 1000 milliseconds by default */
  50. SDXC_Type *base = host->host_param.base;
  51. sdxc_init(base, &sdxc_config);
  52. sdmmchost_wait_card_active(host);
  53. sdmmchost_delay_ms(host, 10);
  54. #if defined(HPM_SDMMC_HOST_ENABLE_IRQ) && (HPM_SDMMC_HOST_ENABLE_IRQ == 1)
  55. host->xfer_done_or_error_event = hpm_sdmmc_osal_event_create(host);
  56. if (host->xfer_done_or_error_event == NULL) {
  57. break;
  58. }
  59. const uint32_t irq_mask =
  60. SDXC_INT_STAT_CMD_COMPLETE_MASK | SDXC_INT_STAT_XFER_COMPLETE_MASK | SDXC_INT_STAT_ERR_INTERRUPT_MASK;
  61. sdxc_enable_interrupt_signal(base, irq_mask, true);
  62. #endif
  63. status = status_success;
  64. } while (false);
  65. return status;
  66. }
  67. void sdmmchost_vsel_pin_control(const sdmmc_host_t *host, hpm_sdmmc_io_volt_t io_volt)
  68. {
  69. if (sdmmchost_is_voltage_switch_supported(host)) {
  70. const hpm_sdmmc_pin_info_t *pin_info = &host->host_param.io_data.vsel_pin;
  71. if (pin_info->use_gpio) {
  72. bool polarity = pin_info->polarity;
  73. uint32_t gpio_index = pin_info->gpio_pin / 32;
  74. uint32_t pin_index = pin_info->gpio_pin % 32;
  75. volatile uint32_t *gpio_on = (polarity == false)
  76. ? &HPM_GPIO0->DO[gpio_index].SET
  77. : &HPM_GPIO0->DO[gpio_index].CLEAR;
  78. volatile uint32_t *gpio_off = (polarity == false)
  79. ? &HPM_GPIO0->DO[gpio_index].CLEAR
  80. : &HPM_GPIO0->DO[gpio_index].SET;
  81. HPM_GPIO0->OE[gpio_index].SET = (1UL << pin_index);
  82. if (io_volt == hpm_sdmmc_io_voltage_3v3) {
  83. *gpio_off = (1UL << pin_index);
  84. } else {
  85. *gpio_on = (1UL << pin_index);
  86. }
  87. }
  88. }
  89. }
  90. hpm_stat_t sdmmchost_switch_to_1v8(sdmmc_host_t *host)
  91. {
  92. if (host == NULL) {
  93. return status_invalid_argument;
  94. }
  95. /* 1. Stop providing clock to the card */
  96. sdxc_enable_inverse_clock(host->host_param.base, false);
  97. sdxc_enable_sd_clock(host->host_param.base, false);
  98. /* 2. Wait until DAT[3:0] are 4'b0000 */
  99. uint32_t data3_0_level;
  100. uint32_t delay_cnt = 1000000UL;
  101. do {
  102. data3_0_level = sdxc_get_data3_0_level(host->host_param.base);
  103. --delay_cnt;
  104. } while ((data3_0_level != 0U) && (delay_cnt > 0U));
  105. if (delay_cnt < 1) {
  106. return status_timeout;
  107. }
  108. /* 3. Switch signaling to 1.8v */
  109. sdmmchost_vsel_pin_control(host, hpm_sdmmc_io_voltage_1v8);
  110. sdmmchost_select_voltage(host, hpm_sdmmc_io_voltage_1v8);
  111. /* 4. delay 5ms */
  112. sdmmchost_delay_ms(host, 50);
  113. /* 5. Provide SD clock the card again */
  114. sdxc_enable_inverse_clock(host->host_param.base, true);
  115. sdxc_enable_sd_clock(host->host_param.base, true);
  116. /* 6. wait 1ms */
  117. sdmmchost_delay_ms(host, 1);
  118. /* 7. Check DAT[3:0], make sure the value is 4'b0000 */
  119. delay_cnt = 1000000UL;
  120. do {
  121. data3_0_level = sdxc_get_data3_0_level(host->host_param.base);
  122. --delay_cnt;
  123. } while ((data3_0_level == 0U) && (delay_cnt > 0U));
  124. if (delay_cnt < 1) {
  125. return status_timeout;
  126. }
  127. return status_success;
  128. }
  129. void sdmmchost_deinit(sdmmc_host_t *host)
  130. {
  131. if (host != NULL) {
  132. sdxc_reset(host->host_param.base, sdxc_reset_cmd_line, 0xffffu);
  133. sdxc_reset(host->host_param.base, sdxc_reset_data_line, 0xffffu);
  134. #if defined(HPM_SDMMC_HOST_ENABLE_IRQ) && (HPM_SDMMC_HOST_ENABLE_IRQ == 1)
  135. if (host->xfer_done_or_error_event != NULL) {
  136. hpm_sdmmc_osal_event_delete(host, host->xfer_done_or_error_event);
  137. host->xfer_done_or_error_event = NULL;
  138. }
  139. #endif
  140. }
  141. }
  142. void sdmmchost_reset(const sdmmc_host_t *host)
  143. {
  144. sdxc_reset(host->host_param.base, sdxc_reset_cmd_line, 0xffffu);
  145. sdxc_reset(host->host_param.base, sdxc_reset_data_line, 0xffffu);
  146. }
  147. void sdmmchost_enable_emmc_support(const sdmmc_host_t *host, bool enable)
  148. {
  149. sdxc_enable_emmc_support(host->host_param.base, enable);
  150. }
  151. bool sdmmchost_is_card_detected(const sdmmc_host_t *host)
  152. {
  153. bool result = true;
  154. if (IS_HPM_BITMASK_SET(host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_CARD_DETECTION)) {
  155. const hpm_sdmmc_pin_info_t *pin_info = &host->host_param.io_data.cd_pin;
  156. if (!pin_info->use_gpio) {
  157. result = sdxc_is_card_inserted(host->host_param.base);
  158. } else {
  159. uint32_t gpio_index = pin_info->gpio_pin / 32;
  160. uint32_t pin_index = pin_info->gpio_pin % 32;
  161. uint32_t pin_val = HPM_GPIO0->DI[gpio_index].VALUE & (1UL << pin_index);
  162. result = (pin_info->polarity == 0) ? (pin_val != 0) : (pin_val == 0);
  163. }
  164. }
  165. return result;
  166. }
  167. void sdmmchost_set_card_bus_width(sdmmc_host_t *host, sdmmc_buswidth_t bus_width)
  168. {
  169. host->bus_width = bus_width;
  170. sdmmchost_init_io(host, hpm_sdmmc_operation_mode_transfer);
  171. sdxc_set_data_bus_width(host->host_param.base, (sdxc_bus_width_t) bus_width);
  172. }
  173. uint32_t sdmmchost_set_card_clock(sdmmc_host_t *host, uint32_t freq, bool clock_inverse)
  174. {
  175. uint32_t clk_freq = host->host_param.clock_init_func(host->host_param.base, freq, clock_inverse);
  176. host->clock_freq = clk_freq;
  177. return clk_freq;
  178. }
  179. void sdmmchost_wait_card_active(const sdmmc_host_t *host)
  180. {
  181. sdxc_wait_card_active(host->host_param.base);
  182. sdmmchost_delay_ms(host, 10);
  183. }
  184. static hpm_stat_t sdmmchost_wait_command_done(const sdmmc_host_t *host, uint32_t timeout_ms)
  185. {
  186. hpm_stat_t status = status_success;
  187. SDMMCHOST_Type *base = host->host_param.base;
  188. const uint32_t event_to_wait = SDXC_INT_STAT_CMD_COMPLETE_MASK | SDXC_INT_STAT_ERR_INTERRUPT_MASK;
  189. do {
  190. #if defined(HPM_SDMMC_HOST_ENABLE_IRQ) && (HPM_SDMMC_HOST_ENABLE_IRQ == 1)
  191. status = hpm_sdmmc_osal_event_wait((void *) host, host->xfer_done_or_error_event, event_to_wait, timeout_ms);
  192. if (status != status_success) {
  193. break;
  194. }
  195. #else
  196. bool has_done_or_error;
  197. bool timeout_occurred;
  198. uint64_t start_ticks = hpm_csr_get_core_mcycle();
  199. uint32_t ticks_per_ms = clock_get_core_clock_ticks_per_ms();
  200. uint64_t timeout_ticks = start_ticks + (timeout_ms * ticks_per_ms);
  201. do {
  202. uint32_t int_stat = sdxc_get_interrupt_status(base);
  203. has_done_or_error = IS_HPM_BITMASK_SET(int_stat, event_to_wait);
  204. timeout_occurred = (hpm_csr_get_core_mcycle() > timeout_ticks);
  205. } while ((!has_done_or_error) && (!timeout_occurred));
  206. if (timeout_occurred) {
  207. break;
  208. }
  209. #endif
  210. } while (false);
  211. status = sdxc_parse_interrupt_status(base);
  212. sdxc_clear_interrupt_status(base, event_to_wait);
  213. return status;
  214. }
  215. static hpm_stat_t sdmmchost_wait_xfer_done(sdmmc_host_t *host, uint32_t timeout_ms)
  216. {
  217. hpm_stat_t status = status_success;
  218. SDMMCHOST_Type *base = host->host_param.base;
  219. const uint32_t event_to_wait = SDXC_INT_STAT_XFER_COMPLETE_MASK | SDXC_INT_STAT_ERR_INTERRUPT_MASK;
  220. do {
  221. #if defined(HPM_SDMMC_HOST_ENABLE_IRQ) && (HPM_SDMMC_HOST_ENABLE_IRQ == 1)
  222. status = hpm_sdmmc_osal_event_wait(host, host->xfer_done_or_error_event, event_to_wait, timeout_ms);
  223. if (status != status_success) {
  224. break;
  225. }
  226. #else
  227. bool has_done_or_error;
  228. bool timeout_occurred;
  229. uint64_t start_ticks = hpm_csr_get_core_mcycle();
  230. uint32_t ticks_per_ms = clock_get_core_clock_ticks_per_ms();
  231. uint64_t timeout_ticks = start_ticks + (timeout_ms * ticks_per_ms);
  232. do {
  233. uint32_t int_stat = sdxc_get_interrupt_status(base);
  234. has_done_or_error = IS_HPM_BITMASK_SET(int_stat, event_to_wait);
  235. timeout_occurred = (hpm_csr_get_core_mcycle() > timeout_ticks);
  236. } while ((!has_done_or_error) && (!timeout_occurred));
  237. if (timeout_occurred) {
  238. break;
  239. }
  240. #endif
  241. } while (false);
  242. status = sdxc_parse_interrupt_status(base);
  243. sdxc_clear_interrupt_status(base, event_to_wait);
  244. return status;
  245. }
  246. static hpm_stat_t sdmmchost_wait_idle(const sdmmc_host_t *host)
  247. {
  248. /* Wait a while until the BUS is idle after the previous command */
  249. uint32_t wait_cnt = 1000L;
  250. while (!sdxc_is_bus_idle(host->host_param.base) && (wait_cnt > 0U)) {
  251. wait_cnt--;
  252. sdmmchost_delay_ms(host, 1);
  253. }
  254. if (wait_cnt == 0) {
  255. return status_timeout;
  256. }
  257. return status_success;
  258. }
  259. hpm_stat_t sdmmchost_send_command(sdmmc_host_t *host, const sdmmchost_cmd_t *cmd)
  260. {
  261. hpm_stat_t status;
  262. SDXC_Type *base = NULL;
  263. do {
  264. status = sdmmchost_check_host_availability(host);
  265. if (status != status_success) {
  266. break;
  267. }
  268. status = sdmmchost_wait_idle(host);
  269. if (status != status_success) {
  270. break;
  271. }
  272. base = host->host_param.base;
  273. status = sdxc_send_command(base, cmd);
  274. if (status != status_success) {
  275. break;
  276. }
  277. uint32_t timeout_ms = (cmd->cmd_timeout_ms == 0) ? HPM_SDMMC_HOST_TIMEOUT_DEFAULT : cmd->cmd_timeout_ms;
  278. status = sdmmchost_wait_command_done(host, timeout_ms);
  279. if (status != status_success) {
  280. break;
  281. }
  282. if (cmd->resp_type == (sdxc_dev_resp_type_t) sdmmc_resp_r1b) {
  283. status = sdmmchost_wait_xfer_done(host, timeout_ms);
  284. if ((status != status_success) && (status != status_timeout)) {
  285. break;
  286. }
  287. }
  288. status = sdxc_receive_cmd_response(host->host_param.base, &host->cmd);
  289. } while (false);
  290. if (status != status_success) {
  291. sdmmchost_error_recovery(host, NULL);
  292. }
  293. return status;
  294. }
  295. hpm_stat_t sdmmchost_transfer(sdmmc_host_t *host, const sdmmchost_xfer_t *content)
  296. {
  297. hpm_stat_t status;
  298. do {
  299. status = sdmmchost_check_host_availability(host);
  300. if (status != status_success) {
  301. break;
  302. }
  303. status = sdmmchost_wait_idle(host);
  304. if (status != status_success) {
  305. break;
  306. }
  307. SDXC_Type *base = host->host_param.base;
  308. sdxc_adma_config_t dma_config = { 0 };
  309. uint32_t timeout_ms = HPM_SDMMC_HOST_TIMEOUT_DEFAULT;
  310. if (content->data != NULL) {
  311. #if defined(HPM_SDMMC_USE_ADMA2) && (HPM_SDMMC_USE_ADMA2 == 1)
  312. dma_config.dma_type = sdxc_dmasel_adma2;
  313. #else
  314. dma_config.dma_type = sdxc_dmasel_adma3;
  315. #endif
  316. /* Ensure the ADMA descriptor starts at 8-byte aligned address */
  317. dma_config.adma_table = (uint32_t *)HPM_ALIGN_UP(&host->adma_table, HPM_SDMMC_HOST_ADMA3_ALIGN_SIZE);
  318. dma_config.adma_table_words = HPM_SDMMC_HOST_ADMA_TBL_SIZE;
  319. /***************************************************************************************************************
  320. * Calculate the data timeout interval in millisecond =
  321. * (block_count * block_size) / tx_rx_bytes_per_sec * 1000 + margin time
  322. * Here set the margin time to 500 milliseconds
  323. **************************************************************************************************************/
  324. uint32_t bus_width = sdxc_get_data_bus_width(host->host_param.base);
  325. uint32_t tx_rx_bytes_per_sec = host->clock_freq * bus_width / 8;
  326. uint32_t block_cnt = content->data->block_cnt;
  327. uint32_t block_size = content->data->block_size;
  328. uint32_t read_write_size = block_cnt * block_size;
  329. timeout_ms = (uint32_t) (1.0f * read_write_size / tx_rx_bytes_per_sec) * 1000 + 500;
  330. sdxc_set_data_timeout(base, timeout_ms, NULL);
  331. }
  332. if (dma_config.dma_type == sdxc_dmasel_adma3) {
  333. sdxc_clear_interrupt_status(base, ~0U);
  334. }
  335. status = sdxc_transfer_nonblocking(base, &dma_config, content);
  336. if (status != status_success) {
  337. break;
  338. }
  339. if (dma_config.dma_type != sdxc_dmasel_adma3) {
  340. status = sdmmchost_wait_command_done(host, HPM_SDMMC_HOST_TIMEOUT_DEFAULT);
  341. if (status != status_success) {
  342. break;
  343. }
  344. }
  345. status = sdxc_parse_interrupt_status(base);
  346. if (status != status_success) {
  347. break;
  348. }
  349. if (content->data != NULL) {
  350. status = sdmmchost_wait_xfer_done(host, timeout_ms);
  351. if (status != status_success) {
  352. break;
  353. }
  354. }
  355. status = sdxc_receive_cmd_response(host->host_param.base, &host->cmd);
  356. } while (false);
  357. return status;
  358. }
  359. hpm_stat_t sdmmchost_set_speed_mode(const sdmmc_host_t *host, sdmmc_speed_mode_t speed_mode)
  360. {
  361. if ((host == NULL) || (host->host_param.base == NULL)) {
  362. return status_invalid_argument;
  363. }
  364. sdxc_set_speed_mode(host->host_param.base, (sdxc_speed_mode_t) speed_mode);
  365. return status_success;
  366. }
  367. hpm_stat_t sdmmchost_error_recovery(sdmmc_host_t *host, sdmmchost_cmd_t *cmd)
  368. {
  369. return sdxc_error_recovery(host->host_param.base, cmd);
  370. }
  371. void sdmmchost_set_cardclk_delay_chain(const sdmmc_host_t *host)
  372. {
  373. SDXC_Type *base = host->host_param.base;
  374. bool need_inverse = sdxc_is_inverse_clock_enabled(base);
  375. sdxc_enable_inverse_clock(base, false);
  376. sdxc_enable_sd_clock(base, false);
  377. uint32_t num_delaycells = sdxc_get_default_cardclk_delay_chain(base, host->clock_freq);
  378. sdxc_set_cardclk_delay_chain(host->host_param.base, num_delaycells);
  379. sdxc_enable_inverse_clock(base, need_inverse);
  380. sdxc_enable_sd_clock(base, true);
  381. }
  382. bool sdmmchost_is_8bit_supported(const sdmmc_host_t *host)
  383. {
  384. return IS_HPM_BITMASK_SET(host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_8BIT);
  385. }
  386. bool sdmmchost_is_voltage_switch_supported(const sdmmc_host_t *host)
  387. {
  388. return IS_HPM_BITMASK_SET(host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_VOLTAGE_SWITCH);
  389. }
  390. void sdmmchost_power_control(const sdmmc_host_t *host, hpm_sdmmc_power_option_t option)
  391. {
  392. if (IS_HPM_BITMASK_SET(host->host_param.host_flags, HPM_SDMMC_HOST_SUPPORT_POWER_SWITCH)) {
  393. const hpm_sdmmc_pin_info_t *pin_info = &host->host_param.io_data.pwr_pin;
  394. const sdmmc_io_init_apis_t *init_apis = &host->host_param.io_init_apis;
  395. bool use_gpio = pin_info->use_gpio;
  396. SDMMCHOST_Type *base = host->host_param.base;
  397. init_apis->pwr_io_init(base, use_gpio);
  398. if (pin_info->use_gpio) {
  399. uint32_t gpio_index = pin_info->gpio_pin / 32;
  400. uint32_t pin_index = pin_info->gpio_pin % 32;
  401. volatile uint32_t *gpio_reg_off = (pin_info->polarity == 0)
  402. ? &HPM_GPIO0->DO[gpio_index].CLEAR
  403. : &HPM_GPIO0->DO[gpio_index].SET;
  404. volatile uint32_t *gpio_reg_on = (pin_info->polarity == 0)
  405. ? &HPM_GPIO0->DO[gpio_index].SET
  406. : &HPM_GPIO0->DO[gpio_index].CLEAR;
  407. HPM_GPIO0->OE[gpio_index].SET = (1UL << pin_index);
  408. if (option == hpm_sdmmc_power_off) {
  409. *gpio_reg_off = (1UL << pin_index);
  410. } else if (option == hpm_sdmmc_power_on) {
  411. *gpio_reg_on = (1UL << pin_index);
  412. } else {
  413. *gpio_reg_off = (1UL << pin_index);
  414. host->host_param.delay_ms(1);
  415. *gpio_reg_on = (1UL << pin_index);
  416. }
  417. } else {
  418. if (option == hpm_sdmmc_power_off) {
  419. sdxc_enable_power(host->host_param.base, false);
  420. } else if (option == hpm_sdmmc_power_on) {
  421. sdxc_enable_power(host->host_param.base, true);
  422. } else {
  423. sdxc_enable_power(host->host_param.base, false);
  424. host->host_param.delay_ms(1);
  425. sdxc_enable_power(host->host_param.base, true);
  426. }
  427. }
  428. host->host_param.delay_ms(1);
  429. }
  430. }
  431. void sdmmchost_init_io(sdmmc_host_t *host, hpm_sdmmc_operation_mode_t operation_mode)
  432. {
  433. bool as_gpio;
  434. const sdmmc_io_init_apis_t *init_apis = &host->host_param.io_init_apis;
  435. SDMMCHOST_Type *base = host->host_param.base;
  436. uint32_t host_flags = host->host_param.host_flags;
  437. if (operation_mode == hpm_sdmmc_operation_mode_inactive) {
  438. uint32_t bus_width = host->bus_width;
  439. const hpm_sdmmc_pin_info_t *pin_info;
  440. bool support_3v3 = IS_HPM_BITMASK_SET(host_flags, HPM_SDMMC_HOST_SUPPORT_3V3);
  441. host->io_voltage = support_3v3 ? hpm_sdmmc_io_voltage_3v3 : hpm_sdmmc_io_voltage_1v8;
  442. /* Initialize IO */
  443. bool support_pwr = IS_HPM_BITMASK_SET(host_flags, HPM_SDMMC_HOST_SUPPORT_POWER_SWITCH);
  444. if (support_pwr) {
  445. pin_info = &host->host_param.io_data.pwr_pin;
  446. as_gpio = pin_info->use_gpio;
  447. if (init_apis->pwr_io_init != NULL) {
  448. init_apis->pwr_io_init(base, as_gpio);
  449. }
  450. }
  451. bool is_1v8 = host->io_voltage == hpm_sdmmc_io_voltage_3v3 ? false : true;
  452. init_apis->cmd_io_init(base, true, is_1v8); /* Configure CMD pin to open-drain mode */
  453. init_apis->clk_data_io_init(base, bus_width, is_1v8);
  454. bool support_cd = IS_HPM_BITMASK_SET(host_flags, HPM_SDMMC_HOST_SUPPORT_CARD_DETECTION);
  455. if (support_cd) {
  456. pin_info = &host->host_param.io_data.cd_pin;
  457. as_gpio = pin_info->use_gpio;
  458. if (init_apis->cd_io_init != NULL) {
  459. init_apis->cd_io_init(base, as_gpio);
  460. }
  461. }
  462. bool support_vsel = sdmmchost_is_voltage_switch_supported(host);
  463. if (support_vsel) {
  464. pin_info = &host->host_param.io_data.vsel_pin;
  465. as_gpio = pin_info->use_gpio;
  466. if (init_apis->vsel_io_init != NULL) {
  467. init_apis->vsel_io_init(base, as_gpio);
  468. }
  469. /* Since eMMC device doesn't support dynamic voltage switch, so set the voltage at initialization phase */
  470. if (!support_3v3) {
  471. sdmmchost_vsel_pin_control(host, hpm_sdmmc_io_voltage_1v8);
  472. sdmmchost_select_voltage(host, hpm_sdmmc_io_voltage_1v8);
  473. }
  474. }
  475. } else if (operation_mode == hpm_sdmmc_operation_mode_identification) {
  476. bool is_1v8 = host->io_voltage == hpm_sdmmc_io_voltage_3v3 ? false : true;
  477. bool is_opendrain = true;
  478. init_apis->cmd_io_init(base, is_opendrain, is_1v8);
  479. uint32_t bus_width = 1;
  480. switch (host->bus_width) {
  481. case sdmmc_bus_width_4bit:
  482. bus_width = 4;
  483. break;
  484. case sdmmc_bus_width_8bit:
  485. bus_width = 8;
  486. break;
  487. default:
  488. bus_width = 1;
  489. break;
  490. }
  491. init_apis->clk_data_io_init(base, bus_width, is_1v8);
  492. bool support_ds = IS_HPM_BITMASK_SET(host_flags, HPM_SDMMC_HOST_SUPPORT_HS400);
  493. if (support_ds) {
  494. init_apis->ds_io_init(base);
  495. }
  496. } else if (operation_mode == hpm_sdmmc_operation_mode_transfer) {
  497. bool is_1v8 = host->io_voltage == hpm_sdmmc_io_voltage_3v3 ? false : true;
  498. bool is_opendrain = false;
  499. init_apis->cmd_io_init(base, is_opendrain, is_1v8);
  500. uint32_t bus_width = 1;
  501. switch (host->bus_width) {
  502. case sdmmc_bus_width_4bit:
  503. bus_width = 4;
  504. break;
  505. case sdmmc_bus_width_8bit:
  506. bus_width = 8;
  507. break;
  508. default:
  509. bus_width = 1;
  510. break;
  511. }
  512. init_apis->clk_data_io_init(base, bus_width, is_1v8);
  513. bool support_ds = IS_HPM_BITMASK_SET(host_flags, HPM_SDMMC_HOST_SUPPORT_HS400);
  514. if (support_ds) {
  515. init_apis->ds_io_init(base);
  516. }
  517. } else if (operation_mode == hpm_sdmmc_operation_mode_interrupt) {
  518. bool is_1v8 = host->io_voltage == hpm_sdmmc_io_voltage_3v3 ? false : true;
  519. bool is_opendrain = true;
  520. init_apis->cmd_io_init(base, is_opendrain, is_1v8);
  521. } else {
  522. /* DO nothing */
  523. }
  524. /* Wait a while in case the IO initialization requires small delays to get effective */
  525. for (volatile uint32_t delay_cnt = 100; delay_cnt > 0; delay_cnt--) {
  526. NOP();
  527. }
  528. }
  529. void sdmmchost_enable_enhanced_data_strobe(const sdmmc_host_t *host, bool enable)
  530. {
  531. sdxc_enable_enhanced_strobe(host->host_param.base, enable);
  532. }
  533. void sdmmchost_set_data_strobe_delay(const sdmmc_host_t *host)
  534. {
  535. uint32_t num_delaycells = sdxc_get_default_strobe_delay(host->host_param.base);
  536. sdxc_set_data_strobe_delay(host->host_param.base, num_delaycells);
  537. }
  538. void sdmmchost_select_voltage(sdmmc_host_t *host, hpm_sdmmc_io_volt_t io_volt)
  539. {
  540. sdxc_bus_voltage_option_t vsel = sdxc_bus_voltage_sd_3v3;
  541. if (io_volt == hpm_sdmmc_io_voltage_1v8) {
  542. vsel = sdxc_bus_voltage_sd_1v8;
  543. host->io_voltage = hpm_sdmmc_io_voltage_1v8;
  544. } else {
  545. host->io_voltage = hpm_sdmmc_io_voltage_3v3;
  546. }
  547. sdxc_select_voltage(host->host_param.base, vsel);
  548. }
  549. ATTR_RAMFUNC void sdmmchost_irq_handler(sdmmc_host_t *host)
  550. {
  551. SDXC_Type *base = host->host_param.base;
  552. uint32_t int_stat = sdxc_get_interrupt_status(base);
  553. uint32_t int_signal_en = sdxc_get_interrupt_signal(base);
  554. if (((int_stat & SDXC_INT_STAT_CARD_INTERRUPT_MASK) != 0) &&
  555. ((int_signal_en & SDXC_INT_STAT_CARD_INTERRUPT_MASK) != 0)) {
  556. if (host->sdio_irq_handler != NULL) {
  557. host->sdio_irq_handler(host->sdio_irq_param);
  558. }
  559. sdmmchost_enable_sdio_interrupt(host, false);
  560. }
  561. #if defined(HPM_SDMMC_HOST_ENABLE_IRQ) && (HPM_SDMMC_HOST_ENABLE_IRQ == 1)
  562. const uint32_t xfer_done_or_err_int_mask = SDXC_INT_STAT_CMD_COMPLETE_MASK | SDXC_INT_STAT_XFER_COMPLETE_MASK | SDXC_INT_STAT_ERR_INTERRUPT_MASK;
  563. hpm_sdmmc_osal_event_clear(host, host->xfer_done_or_error_event, xfer_done_or_err_int_mask);
  564. if ((int_signal_en & xfer_done_or_err_int_mask) && (int_stat & xfer_done_or_err_int_mask)) {
  565. uint32_t event_flags = int_stat & xfer_done_or_err_int_mask;
  566. hpm_sdmmc_osal_event_set(host, host->xfer_done_or_error_event, event_flags);
  567. sdxc_clear_interrupt_status(base, event_flags);
  568. }
  569. #endif
  570. }
  571. void sdmmchost_enable_sdio_interrupt(sdmmc_host_t *host, bool enable)
  572. {
  573. if (host != NULL) {
  574. if (enable) {
  575. sdxc_enable_interrupt_signal(host->host_param.base, SDXC_INT_STAT_CARD_INTERRUPT_MASK, true);
  576. sdxc_enable_interrupt_status(host->host_param.base, SDXC_INT_STAT_CARD_INTERRUPT_MASK, true);
  577. } else {
  578. sdxc_enable_interrupt_status(host->host_param.base, SDXC_INT_STAT_CARD_INTERRUPT_MASK, false);
  579. }
  580. }
  581. }
  582. void sdmmchost_register_sdio_callback(sdmmc_host_t *host, void (*sdio_irq_callback)(void *param), void *param)
  583. {
  584. if (host != NULL) {
  585. host->sdio_irq_handler = sdio_irq_callback;
  586. host->sdio_irq_param = param;
  587. }
  588. }
  589. uint32_t sdmmchost_get_data_pin_level(sdmmc_host_t *host)
  590. {
  591. uint32_t data_pin_level = 0;
  592. if ((host != NULL) && (host->host_param.base != NULL)) {
  593. SDXC_Type *base = host->host_param.base;
  594. data_pin_level = sdxc_get_data3_0_level(base);
  595. if (sdmmchost_is_8bit_supported(host)) {
  596. data_pin_level |= (sdxc_get_data7_4_level(base) << 4);
  597. }
  598. }
  599. return data_pin_level;
  600. }