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