|  | /* | 
|  | * Copyright 2022 NXP | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <zephyr/kernel.h> | 
|  | #include <zephyr/drivers/sdhc.h> | 
|  | #include <zephyr/sd/sd.h> | 
|  | #include <zephyr/sd/sdmmc.h> | 
|  | #include <zephyr/sd/sd_spec.h> | 
|  | #include <zephyr/logging/log.h> | 
|  | #include <zephyr/sys/byteorder.h> | 
|  | #include <zephyr/drivers/disk.h> | 
|  |  | 
|  | #include "sd_utils.h" | 
|  | #include "sd_ops.h" | 
|  |  | 
|  | LOG_MODULE_DECLARE(sd, CONFIG_SD_LOG_LEVEL); | 
|  |  | 
|  | static inline void sdmmc_decode_scr(struct sd_scr *scr, uint32_t *raw_scr, uint8_t *version) | 
|  | { | 
|  | uint32_t tmp_version = 0; | 
|  |  | 
|  | scr->flags = 0U; | 
|  | scr->scr_structure = (uint8_t)((raw_scr[0U] & 0xF0000000U) >> 28U); | 
|  | scr->sd_spec = (uint8_t)((raw_scr[0U] & 0xF000000U) >> 24U); | 
|  | if ((uint8_t)((raw_scr[0U] & 0x800000U) >> 23U)) { | 
|  | scr->flags |= SD_SCR_DATA_STATUS_AFTER_ERASE; | 
|  | } | 
|  | scr->sd_sec = (uint8_t)((raw_scr[0U] & 0x700000U) >> 20U); | 
|  | scr->sd_width = (uint8_t)((raw_scr[0U] & 0xF0000U) >> 16U); | 
|  | if ((uint8_t)((raw_scr[0U] & 0x8000U) >> 15U)) { | 
|  | scr->flags |= SD_SCR_SPEC3; | 
|  | } | 
|  | scr->sd_ext_sec = (uint8_t)((raw_scr[0U] & 0x7800U) >> 10U); | 
|  | scr->cmd_support = (uint8_t)(raw_scr[0U] & 0x3U); | 
|  | scr->rsvd = raw_scr[1U]; | 
|  | /* Get specification version. */ | 
|  | switch (scr->sd_spec) { | 
|  | case 0U: | 
|  | tmp_version = SD_SPEC_VER1_0; | 
|  | break; | 
|  | case 1U: | 
|  | tmp_version = SD_SPEC_VER1_1; | 
|  | break; | 
|  | case 2U: | 
|  | tmp_version = SD_SPEC_VER2_0; | 
|  | if (scr->flags & SD_SCR_SPEC3) { | 
|  | tmp_version = SD_SPEC_VER3_0; | 
|  | } | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  |  | 
|  | if (version && tmp_version) { | 
|  | *version = tmp_version; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Helper to send SD app command */ | 
|  | static int sdmmc_app_command(struct sd_card *card, int relative_card_address) | 
|  | { | 
|  | return card_app_command(card, relative_card_address); | 
|  | } | 
|  |  | 
|  | /* Reads OCR from SPI mode card using CMD58 */ | 
|  | static int sdmmc_spi_send_ocr(struct sd_card *card, uint32_t arg) | 
|  | { | 
|  | struct sdhc_command cmd; | 
|  | int ret; | 
|  |  | 
|  | cmd.opcode = SD_SPI_READ_OCR; | 
|  | cmd.arg = arg; | 
|  | cmd.response_type = SD_SPI_RSP_TYPE_R3; | 
|  | cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT; | 
|  | cmd.retries = CONFIG_SD_CMD_RETRIES; | 
|  |  | 
|  | ret = sdhc_request(card->sdhc, &cmd, NULL); | 
|  |  | 
|  | if (ret) { | 
|  | LOG_DBG("CMD58 failed: %d", ret); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | card->ocr = cmd.response[1]; | 
|  | if (card->ocr == 0) { | 
|  | LOG_DBG("No OCR detected"); | 
|  | return -ENOTSUP; | 
|  | } | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* Sends OCR to card using ACMD41 */ | 
|  | static int sdmmc_send_ocr(struct sd_card *card, int ocr) | 
|  | { | 
|  | struct sdhc_command cmd; | 
|  | int ret; | 
|  | int retries; | 
|  |  | 
|  | cmd.opcode = SD_APP_SEND_OP_COND; | 
|  | cmd.arg = ocr; | 
|  | cmd.response_type = (SD_RSP_TYPE_R3 | SD_SPI_RSP_TYPE_R1); | 
|  | cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT; | 
|  | cmd.retries = CONFIG_SD_CMD_RETRIES; | 
|  |  | 
|  | /* Send initialization ACMD41 */ | 
|  | for (retries = 0; retries < CONFIG_SD_OCR_RETRY_COUNT; retries++) { | 
|  | ret = sdmmc_app_command(card, 0U); | 
|  | if (ret == SD_RETRY) { | 
|  | /* Retry */ | 
|  | continue; | 
|  | } else if (ret) { | 
|  | return ret; | 
|  | } | 
|  | ret = sdhc_request(card->sdhc, &cmd, NULL); | 
|  | if (ret) { | 
|  | /* OCR failed */ | 
|  | return ret; | 
|  | } | 
|  | if (ocr == 0) { | 
|  | /* Just probing, don't wait for card to exit busy state */ | 
|  | return 0; | 
|  | } | 
|  | /* | 
|  | * Check to see if card is busy with power up. PWR_BUSY | 
|  | * flag will be cleared when card finishes power up sequence | 
|  | */ | 
|  | if (card->host_props.is_spi) { | 
|  | if (!(cmd.response[0] & SD_SPI_R1IDLE_STATE)) { | 
|  | break; | 
|  | } | 
|  | } else { | 
|  | if ((cmd.response[0U] & SD_OCR_PWR_BUSY_FLAG)) { | 
|  | break; | 
|  | } | 
|  | } | 
|  | sd_delay(10); | 
|  | } | 
|  | if (retries >= CONFIG_SD_OCR_RETRY_COUNT) { | 
|  | /* OCR timed out */ | 
|  | LOG_ERR("Card never left busy state"); | 
|  | return -ETIMEDOUT; | 
|  | } | 
|  | LOG_DBG("SDMMC responded to ACMD41 after %d attempts", retries); | 
|  | if (!card->host_props.is_spi) { | 
|  | /* Save OCR */ | 
|  | card->ocr = cmd.response[0U]; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Reads SD configuration register */ | 
|  | static int sdmmc_read_scr(struct sd_card *card) | 
|  | { | 
|  | struct sdhc_command cmd = {0}; | 
|  | struct sdhc_data data = {0}; | 
|  | /* Place SCR struct on stack to reduce flash usage */ | 
|  | struct sd_scr card_scr; | 
|  | int ret; | 
|  | /* DMA onto stack is unsafe, so we use an internal card buffer */ | 
|  | uint32_t *scr = (uint32_t *)card->card_buffer; | 
|  | uint32_t raw_scr[2]; | 
|  |  | 
|  | ret = sdmmc_app_command(card, card->relative_addr); | 
|  | if (ret) { | 
|  | LOG_DBG("SD app command failed for SD SCR"); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | cmd.opcode = SD_APP_SEND_SCR; | 
|  | cmd.arg = 0; | 
|  | cmd.response_type = (SD_RSP_TYPE_R1 | SD_SPI_RSP_TYPE_R1); | 
|  | cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT; | 
|  | cmd.retries = CONFIG_SD_CMD_RETRIES; | 
|  |  | 
|  | data.block_size = 8U; | 
|  | data.blocks = 1U; | 
|  | data.data = scr; | 
|  | data.timeout_ms = CONFIG_SD_DATA_TIMEOUT; | 
|  |  | 
|  | ret = sdhc_request(card->sdhc, &cmd, &data); | 
|  | if (ret) { | 
|  | LOG_DBG("ACMD51 failed: %d", ret); | 
|  | return ret; | 
|  | } | 
|  | /* Decode SCR */ | 
|  | raw_scr[0] = sys_be32_to_cpu(scr[0]); | 
|  | raw_scr[1] = sys_be32_to_cpu(scr[1]); | 
|  | sdmmc_decode_scr(&card_scr, raw_scr, &card->sd_version); | 
|  | LOG_DBG("SD reports specification version %d", card->sd_version); | 
|  | /* Check card supported bus width */ | 
|  | if (card_scr.sd_width & 0x4U) { | 
|  | card->flags |= SD_4BITS_WIDTH; | 
|  | } | 
|  | /* Check if card supports speed class command (CMD20) */ | 
|  | if (card_scr.cmd_support & 0x1U) { | 
|  | card->flags |= SD_SPEED_CLASS_CONTROL_FLAG; | 
|  | } | 
|  | /* Check for set block count (CMD 23) support */ | 
|  | if (card_scr.cmd_support & 0x2U) { | 
|  | card->flags |= SD_CMD23_FLAG; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Sets block length of SD card */ | 
|  | static int sdmmc_set_blocklen(struct sd_card *card, uint32_t block_len) | 
|  | { | 
|  | struct sdhc_command cmd = {0}; | 
|  |  | 
|  | cmd.opcode = SD_SET_BLOCK_SIZE; | 
|  | cmd.arg = block_len; | 
|  | cmd.response_type = (SD_RSP_TYPE_R1 | SD_SPI_RSP_TYPE_R1); | 
|  | cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT; | 
|  | cmd.retries = CONFIG_SD_CMD_RETRIES; | 
|  |  | 
|  | return sdhc_request(card->sdhc, &cmd, NULL); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Sets bus width of host and card, following section 3.4 of | 
|  | * SD host controller specification | 
|  | */ | 
|  | static int sdmmc_set_bus_width(struct sd_card *card, enum sdhc_bus_width width) | 
|  | { | 
|  | struct sdhc_command cmd = {0}; | 
|  | int ret; | 
|  |  | 
|  | /* | 
|  | * The specification strictly requires card interrupts to be masked, but | 
|  | * Linux does not do so, so we won't either. | 
|  | */ | 
|  | /* Send ACMD6 to change bus width */ | 
|  | ret = sdmmc_app_command(card, card->relative_addr); | 
|  | if (ret) { | 
|  | LOG_DBG("SD app command failed for ACMD6"); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | cmd.opcode = SD_APP_SET_BUS_WIDTH; | 
|  | cmd.response_type = SD_RSP_TYPE_R1; | 
|  | cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT; | 
|  | cmd.retries = CONFIG_SD_CMD_RETRIES; | 
|  |  | 
|  | switch (width) { | 
|  | case SDHC_BUS_WIDTH1BIT: | 
|  | cmd.arg = 0U; | 
|  | break; | 
|  | case SDHC_BUS_WIDTH4BIT: | 
|  | cmd.arg = 2U; | 
|  | break; | 
|  | default: | 
|  | return -ENOTSUP; | 
|  | } | 
|  | /* Send app command */ | 
|  | ret = sdhc_request(card->sdhc, &cmd, NULL); | 
|  | if (ret) { | 
|  | LOG_DBG("Error on ACMD6: %d", ret); | 
|  | return ret; | 
|  | } | 
|  | ret = sd_check_response(&cmd); | 
|  | if (ret) { | 
|  | LOG_DBG("ACMD6 reports error, response 0x%x", cmd.response[0U]); | 
|  | return ret; | 
|  | } | 
|  | /* Card now has changed bus width. Change host bus width */ | 
|  | card->bus_io.bus_width = width; | 
|  | ret = sdhc_set_io(card->sdhc, &card->bus_io); | 
|  | if (ret) { | 
|  | LOG_DBG("Could not change host bus width"); | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Sends SD switch function CMD6. | 
|  | * See table 4-32 in SD physical specification for argument details. | 
|  | * When setting a function, we should set the 4 bit block of the command | 
|  | * argument corresponding to that function to "value", and all other 4 bit | 
|  | * blocks should be left as 0xF (no effect on current function) | 
|  | */ | 
|  | static int sdmmc_switch(struct sd_card *card, enum sd_switch_arg mode, enum sd_group_num group, | 
|  | uint8_t value, uint8_t *response) | 
|  | { | 
|  | struct sdhc_command cmd = {0}; | 
|  | struct sdhc_data data = {0}; | 
|  |  | 
|  | cmd.opcode = SD_SWITCH; | 
|  | cmd.arg = ((mode & 0x1) << 31) | 0x00FFFFFF; | 
|  | cmd.arg &= ~(0xFU << (group * 4)); | 
|  | cmd.arg |= (value & 0xF) << (group * 4); | 
|  | cmd.response_type = (SD_RSP_TYPE_R1 | SD_SPI_RSP_TYPE_R1); | 
|  | cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT; | 
|  | cmd.retries = CONFIG_SD_CMD_RETRIES; | 
|  |  | 
|  | data.block_size = 64U; | 
|  | data.blocks = 1; | 
|  | data.data = response; | 
|  | data.timeout_ms = CONFIG_SD_DATA_TIMEOUT; | 
|  |  | 
|  | return sdhc_request(card->sdhc, &cmd, &data); | 
|  | } | 
|  |  | 
|  | static int sdmmc_read_switch(struct sd_card *card) | 
|  | { | 
|  | uint8_t *status; | 
|  | int ret; | 
|  |  | 
|  | if (card->sd_version < SD_SPEC_VER1_1) { | 
|  | /* Switch not supported */ | 
|  | LOG_INF("SD spec 1.01 does not support CMD6"); | 
|  | return 0; | 
|  | } | 
|  | /* Use card internal buffer to read 64 byte switch data */ | 
|  | status = card->card_buffer; | 
|  | /* | 
|  | * Setting switch to zero will read card's support values, | 
|  | * otherwise known as SD "check function" | 
|  | */ | 
|  | ret = sdmmc_switch(card, SD_SWITCH_CHECK, 0, 0, status); | 
|  | if (ret) { | 
|  | LOG_DBG("CMD6 failed %d", ret); | 
|  | return ret; | 
|  | } | 
|  | /* | 
|  | * See table 4-11 and 4.3.10.4 of physical layer specification for | 
|  | * bit definitions. Note that response is big endian, so index 13 will | 
|  | * read bits 400-408. | 
|  | * Bit n being set in support bit field indicates support for function | 
|  | * number n on the card. (So 0x3 indicates support for functions 0 and 1) | 
|  | */ | 
|  | /* Determine HS speed support, if any */ | 
|  | if (status[13] & HIGH_SPEED_BUS_SPEED) { | 
|  | card->switch_caps.hs_max_dtr = HS_MAX_DTR; | 
|  | } else { | 
|  | card->switch_caps.hs_max_dtr = HS_UNSUPPORTED; | 
|  | } | 
|  | /* Determine UHS speed support, if any */ | 
|  | if (status[13] & UHS_SDR104_BUS_SPEED) { | 
|  | card->switch_caps.uhs_max_dtr = UHS_SDR104_MAX_DTR; | 
|  | } else if (status[13] & UHS_DDR50_BUS_SPEED) { | 
|  | card->switch_caps.uhs_max_dtr = UHS_DDR50_MAX_DTR; | 
|  | } else if (status[13] & UHS_SDR50_BUS_SPEED) { | 
|  | card->switch_caps.uhs_max_dtr = UHS_SDR50_MAX_DTR; | 
|  | } else if (status[13] & UHS_SDR25_BUS_SPEED) { | 
|  | card->switch_caps.uhs_max_dtr = UHS_SDR25_MAX_DTR; | 
|  | } else if (status[13] & UHS_SDR12_BUS_SPEED) { | 
|  | card->switch_caps.uhs_max_dtr = UHS_SDR12_MAX_DTR; | 
|  | } else { | 
|  | card->switch_caps.uhs_max_dtr = UHS_UNSUPPORTED; | 
|  | } | 
|  | if (card->sd_version >= SD_SPEC_VER3_0) { | 
|  | card->switch_caps.bus_speed = status[13]; | 
|  | card->switch_caps.sd_drv_type = status[9]; | 
|  | card->switch_caps.sd_current_limit = status[7]; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static inline void sdmmc_select_bus_speed(struct sd_card *card) | 
|  | { | 
|  | /* | 
|  | * Note that function support is defined using bitfields, but function | 
|  | * selection is defined using values 0x0-0xF. | 
|  | */ | 
|  | if (IS_ENABLED(CONFIG_SD_UHS_PROTOCOL) && (card->flags & SD_1800MV_FLAG) && | 
|  | sdmmc_host_uhs(&card->host_props) && !(card->host_props.is_spi)) { | 
|  | /* Select UHS mode timing */ | 
|  | if (card->host_props.host_caps.sdr104_support && | 
|  | (card->switch_caps.bus_speed & UHS_SDR104_BUS_SPEED)) { | 
|  | card->card_speed = SD_TIMING_SDR104; | 
|  | } else if (card->host_props.host_caps.ddr50_support && | 
|  | (card->switch_caps.bus_speed & UHS_DDR50_BUS_SPEED)) { | 
|  | card->card_speed = SD_TIMING_DDR50; | 
|  | } else if (card->host_props.host_caps.sdr50_support && | 
|  | (card->switch_caps.bus_speed & UHS_SDR50_BUS_SPEED)) { | 
|  | card->card_speed = SD_TIMING_SDR50; | 
|  | } else if (card->switch_caps.bus_speed & UHS_SDR12_BUS_SPEED) { | 
|  | card->card_speed = SD_TIMING_SDR25; | 
|  | } else { | 
|  | card->card_speed = SD_TIMING_SDR12; | 
|  | } | 
|  | } else { | 
|  | /* Select HS mode timing */ | 
|  | if (card->host_props.host_caps.high_spd_support && | 
|  | (card->switch_caps.bus_speed & HIGH_SPEED_BUS_SPEED)) { | 
|  | card->card_speed = SD_TIMING_HIGH_SPEED; | 
|  | } else { | 
|  | card->card_speed = SD_TIMING_DEFAULT; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Selects driver type for SD card */ | 
|  | static int sdmmc_select_driver_type(struct sd_card *card) | 
|  | { | 
|  | int ret = 0; | 
|  | uint8_t *status = card->card_buffer; | 
|  |  | 
|  | /* | 
|  | * We will only attempt to use driver type C over the default of type B, | 
|  | * since it should result in lower current consumption if supported. | 
|  | */ | 
|  | if (card->host_props.host_caps.drv_type_c_support && | 
|  | (card->switch_caps.sd_drv_type & SD_DRIVER_TYPE_C)) { | 
|  | card->bus_io.driver_type = SD_DRIVER_TYPE_C; | 
|  | /* Change drive strength */ | 
|  | ret = sdmmc_switch(card, SD_SWITCH_SET, SD_GRP_DRIVER_STRENGTH_MODE, | 
|  | (find_msb_set(SD_DRIVER_TYPE_C) - 1), status); | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* Sets current limit for SD card */ | 
|  | static int sdmmc_set_current_limit(struct sd_card *card) | 
|  | { | 
|  | int ret; | 
|  | int max_current = -1; | 
|  | uint8_t *status = card->card_buffer; | 
|  |  | 
|  | if ((card->card_speed != SD_TIMING_SDR50) && (card->card_speed != SD_TIMING_SDR104) && | 
|  | (card->card_speed != SD_TIMING_DDR50)) { | 
|  | return 0; /* Cannot set current limit */ | 
|  | } else if (card->host_props.max_current_180 >= 800 && | 
|  | (card->switch_caps.sd_current_limit & SD_MAX_CURRENT_800MA)) { | 
|  | max_current = SD_SET_CURRENT_800MA; | 
|  | } else if (card->host_props.max_current_180 >= 600 && | 
|  | (card->switch_caps.sd_current_limit & SD_MAX_CURRENT_600MA)) { | 
|  | max_current = SD_SET_CURRENT_600MA; | 
|  | } else if (card->host_props.max_current_180 >= 400 && | 
|  | (card->switch_caps.sd_current_limit & SD_MAX_CURRENT_400MA)) { | 
|  | max_current = SD_SET_CURRENT_400MA; | 
|  | } else if (card->host_props.max_current_180 >= 200 && | 
|  | (card->switch_caps.sd_current_limit & SD_MAX_CURRENT_200MA)) { | 
|  | max_current = SD_SET_CURRENT_200MA; | 
|  | } | 
|  | if (max_current != -1) { | 
|  | LOG_DBG("Changing SD current limit: %d", max_current); | 
|  | /* Switch SD current */ | 
|  | ret = sdmmc_switch(card, SD_SWITCH_SET, SD_GRP_CURRENT_LIMIT_MODE, max_current, | 
|  | status); | 
|  | if (ret) { | 
|  | LOG_DBG("Failed to set SD current limit"); | 
|  | return ret; | 
|  | } | 
|  | if (((status[15] >> 4) & 0x0F) != max_current) { | 
|  | /* Status response indicates card did not select request limit */ | 
|  | LOG_WRN("Card did not accept current limit"); | 
|  | } | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Applies selected card bus speed to card and host */ | 
|  | static int sdmmc_set_bus_speed(struct sd_card *card) | 
|  | { | 
|  | int ret; | 
|  | uint8_t *status = card->card_buffer; | 
|  | enum sdhc_timing_mode timing; | 
|  | uint32_t card_clock; | 
|  |  | 
|  | /* Set card clock and host timing. Since the card's maximum clock | 
|  | * was calculated within sdmmc_read_switch(), we can safely use the | 
|  | * minimum between that clock and the host's highest clock supported. | 
|  | */ | 
|  | if (IS_ENABLED(CONFIG_SD_UHS_PROTOCOL) && (card->flags & SD_1800MV_FLAG) && | 
|  | sdmmc_host_uhs(&card->host_props) && !(card->host_props.is_spi)) { | 
|  | /* UHS mode */ | 
|  | card_clock = MIN(card->host_props.f_max, card->switch_caps.uhs_max_dtr); | 
|  | switch (card->card_speed) { | 
|  | case SD_TIMING_SDR104: | 
|  | timing = SDHC_TIMING_SDR104; | 
|  | break; | 
|  | case SD_TIMING_DDR50: | 
|  | timing = SDHC_TIMING_DDR50; | 
|  | break; | 
|  | case SD_TIMING_SDR50: | 
|  | timing = SDHC_TIMING_SDR50; | 
|  | break; | 
|  | case SD_TIMING_SDR25: | 
|  | timing = SDHC_TIMING_SDR25; | 
|  | break; | 
|  | case SD_TIMING_SDR12: | 
|  | timing = SDHC_TIMING_SDR12; | 
|  | break; | 
|  | default: | 
|  | /* No need to change bus speed */ | 
|  | return 0; | 
|  | } | 
|  | } else { | 
|  | /* High speed/default mode */ | 
|  | card_clock = MIN(card->host_props.f_max, card->switch_caps.hs_max_dtr); | 
|  | switch (card->card_speed) { | 
|  | case SD_TIMING_HIGH_SPEED: | 
|  | timing = SDHC_TIMING_HS; | 
|  | break; | 
|  | case SD_TIMING_DEFAULT: | 
|  | timing = SDHC_TIMING_LEGACY; | 
|  | break; | 
|  | default: | 
|  | /* No need to change bus speed */ | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Switch bus speed */ | 
|  | ret = sdmmc_switch(card, SD_SWITCH_SET, SD_GRP_TIMING_MODE, card->card_speed, status); | 
|  | if (ret) { | 
|  | LOG_DBG("Failed to switch SD card speed"); | 
|  | return ret; | 
|  | } | 
|  | if ((status[16] & 0xF) != card->card_speed) { | 
|  | LOG_WRN("Card did not accept new speed"); | 
|  | } else { | 
|  | /* Change host bus speed */ | 
|  | card->bus_io.timing = timing; | 
|  | card->bus_io.clock = card_clock; | 
|  | LOG_DBG("Setting bus clock to: %d", card->bus_io.clock); | 
|  | ret = sdhc_set_io(card->sdhc, &card->bus_io); | 
|  | if (ret) { | 
|  | LOG_ERR("Failed to change host bus speed"); | 
|  | return ret; | 
|  | } | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Init UHS capable SD card. Follows figure 3-16 in physical layer specification. | 
|  | */ | 
|  | static int sdmmc_init_uhs(struct sd_card *card) | 
|  | { | 
|  | int ret; | 
|  |  | 
|  | /* Raise bus width to 4 bits */ | 
|  | ret = sdmmc_set_bus_width(card, SDHC_BUS_WIDTH4BIT); | 
|  | if (ret) { | 
|  | LOG_ERR("Failed to change card bus width to 4 bits"); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* Select bus speed for card depending on host and card capability*/ | 
|  | sdmmc_select_bus_speed(card); | 
|  | /* Now, set the driver strength for the card */ | 
|  | ret = sdmmc_select_driver_type(card); | 
|  | if (ret) { | 
|  | LOG_DBG("Failed to select new driver type"); | 
|  | return ret; | 
|  | } | 
|  | ret = sdmmc_set_current_limit(card); | 
|  | if (ret) { | 
|  | LOG_DBG("Failed to set card current limit"); | 
|  | return ret; | 
|  | } | 
|  | /* Apply the bus speed selected earlier */ | 
|  | ret = sdmmc_set_bus_speed(card); | 
|  | if (ret) { | 
|  | LOG_DBG("Failed to set card bus speed"); | 
|  | return ret; | 
|  | } | 
|  | if (card->card_speed == SD_TIMING_SDR50 || card->card_speed == SD_TIMING_SDR104 || | 
|  | card->card_speed == SD_TIMING_DDR50) { | 
|  | /* SDR104, SDR50, and DDR50 mode need tuning */ | 
|  | ret = sdhc_execute_tuning(card->sdhc); | 
|  | if (ret) { | 
|  | LOG_ERR("SD tuning failed: %d", ret); | 
|  | } | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* Performs initialization for SD high speed cards */ | 
|  | static int sdmmc_init_hs(struct sd_card *card) | 
|  | { | 
|  | int ret; | 
|  |  | 
|  | if ((!card->host_props.host_caps.high_spd_support) || | 
|  | (card->sd_version < SD_SPEC_VER1_1) || | 
|  | (card->switch_caps.hs_max_dtr == HS_UNSUPPORTED)) { | 
|  | /* No high speed support. Leave card untouched */ | 
|  | return 0; | 
|  | } | 
|  | /* Select bus speed for card depending on host and card capability*/ | 
|  | sdmmc_select_bus_speed(card); | 
|  | /* Apply selected bus speed */ | 
|  | ret = sdmmc_set_bus_speed(card); | 
|  | if (ret) { | 
|  | LOG_ERR("Failed to switch card to HS mode"); | 
|  | return ret; | 
|  | } | 
|  | if (card->host_props.host_caps.bus_4_bit_support && (card->flags & SD_4BITS_WIDTH)) { | 
|  | /* Raise bus width to 4 bits */ | 
|  | ret = sdmmc_set_bus_width(card, SDHC_BUS_WIDTH4BIT); | 
|  | if (ret) { | 
|  | LOG_ERR("Failed to change card bus width to 4 bits"); | 
|  | return ret; | 
|  | } | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Initializes SDMMC card. Note that the common SD function has already | 
|  | * sent CMD0 and CMD8 to the card at function entry. | 
|  | */ | 
|  | int sdmmc_card_init(struct sd_card *card) | 
|  | { | 
|  | int ret; | 
|  | uint32_t ocr_arg = 0U; | 
|  |  | 
|  | /* First send a probing OCR */ | 
|  | if (IS_ENABLED(CONFIG_SDHC_SUPPORTS_SPI_MODE) && card->host_props.is_spi) { | 
|  | /* Probe SPI card with CMD58*/ | 
|  | ret = sdmmc_spi_send_ocr(card, ocr_arg); | 
|  | } else if (IS_ENABLED(CONFIG_SDHC_SUPPORTS_NATIVE_MODE)) { | 
|  | /* Probe Native card with ACMD41 */ | 
|  | ret = sdmmc_send_ocr(card, ocr_arg); | 
|  | } else { | 
|  | return -ENOTSUP; | 
|  | } | 
|  | if (ret) { | 
|  | return ret; | 
|  | } | 
|  | /* Card responded to ACMD41, type is SDMMC */ | 
|  | card->type = CARD_SDMMC; | 
|  |  | 
|  | if (card->flags & SD_SDHC_FLAG) { | 
|  | if (IS_ENABLED(CONFIG_SDHC_SUPPORTS_NATIVE_MODE)) { | 
|  | /* High capacity card. See if host supports 1.8V */ | 
|  | if (card->host_props.host_caps.vol_180_support) { | 
|  | ocr_arg |= SD_OCR_SWITCH_18_REQ_FLAG; | 
|  | } | 
|  | } | 
|  | /* Set host high capacity support flag */ | 
|  | ocr_arg |= SD_OCR_HOST_CAP_FLAG; | 
|  | } | 
|  | if (IS_ENABLED(CONFIG_SDHC_SUPPORTS_NATIVE_MODE)) { | 
|  | /* Set voltage window */ | 
|  | if (card->host_props.host_caps.vol_300_support) { | 
|  | ocr_arg |= SD_OCR_VDD29_30FLAG; | 
|  | } | 
|  | ocr_arg |= (SD_OCR_VDD32_33FLAG | SD_OCR_VDD33_34FLAG); | 
|  | } | 
|  | /* Momentary delay before initialization OCR. Some cards will | 
|  | * never leave busy state if init OCR is sent too soon after | 
|  | * probing OCR | 
|  | */ | 
|  | k_busy_wait(100); | 
|  | /* Send SD OCR to card to initialize it */ | 
|  | ret = sdmmc_send_ocr(card, ocr_arg); | 
|  | if (ret) { | 
|  | LOG_ERR("Failed to query card OCR"); | 
|  | return ret; | 
|  | } | 
|  | if (IS_ENABLED(CONFIG_SDHC_SUPPORTS_SPI_MODE) && card->host_props.is_spi) { | 
|  | /* Send second CMD58 to get CCS bit */ | 
|  | ret = sdmmc_spi_send_ocr(card, ocr_arg); | 
|  | if (ret) { | 
|  | return ret; | 
|  | } | 
|  | } | 
|  | /* Check SD high capacity and 1.8V support flags */ | 
|  | if (card->ocr & SD_OCR_CARD_CAP_FLAG) { | 
|  | card->flags |= SD_HIGH_CAPACITY_FLAG; | 
|  | } | 
|  | if (card->ocr & SD_OCR_SWITCH_18_ACCEPT_FLAG) { | 
|  | LOG_DBG("Card supports 1.8V signaling"); | 
|  | card->flags |= SD_1800MV_FLAG; | 
|  | } | 
|  | /* Check OCR voltage window */ | 
|  | if (card->ocr & SD_OCR_VDD29_30FLAG) { | 
|  | card->flags |= SD_3000MV_FLAG; | 
|  | } | 
|  | /* | 
|  | * If card is high capacity (SDXC or SDHC), and supports 1.8V signaling, | 
|  | * switch to new signal voltage using "signal voltage switch procedure" | 
|  | * described in SD specification | 
|  | */ | 
|  | if (IS_ENABLED(CONFIG_SD_UHS_PROTOCOL) && (card->flags & SD_1800MV_FLAG) && | 
|  | (card->host_props.host_caps.vol_180_support) && (!card->host_props.is_spi)) { | 
|  | ret = sdmmc_switch_voltage(card); | 
|  | if (ret) { | 
|  | /* Disable host support for 1.8 V */ | 
|  | card->host_props.host_caps.vol_180_support = false; | 
|  | /* | 
|  | * The host or SD card may have already switched to | 
|  | * 1.8V. Return SD_RESTART to indicate | 
|  | * negotiation should be restarted. | 
|  | */ | 
|  | card->status = CARD_ERROR; | 
|  | return SD_RESTART; | 
|  | } | 
|  | } | 
|  | /* Read the card's CID (card identification register) */ | 
|  | ret = card_read_cid(card); | 
|  | if (ret) { | 
|  | return ret; | 
|  | } | 
|  | if (IS_ENABLED(CONFIG_SDHC_SUPPORTS_NATIVE_MODE) && !card->host_props.is_spi) { | 
|  | /* | 
|  | * Request new relative card address. This moves the card from | 
|  | * identification mode to data transfer mode | 
|  | */ | 
|  | ret = sdmmc_request_rca(card); | 
|  | if (ret) { | 
|  | return ret; | 
|  | } | 
|  | } | 
|  | /* Card has entered data transfer mode. Get card specific data register */ | 
|  | ret = sdmmc_read_csd(card); | 
|  | if (ret) { | 
|  | return ret; | 
|  | } | 
|  | if (IS_ENABLED(CONFIG_SDHC_SUPPORTS_NATIVE_MODE) && !card->host_props.is_spi) { | 
|  | /* Move the card to transfer state (with CMD7) to run remaining commands */ | 
|  | ret = sdmmc_select_card(card); | 
|  | if (ret) { | 
|  | return ret; | 
|  | } | 
|  | } | 
|  | /* | 
|  | * With card in data transfer state, we can set SD clock to maximum | 
|  | * frequency for non high speed mode (25Mhz) | 
|  | */ | 
|  | if (card->host_props.f_max < SD_CLOCK_25MHZ) { | 
|  | LOG_INF("Maximum SD clock is under 25MHz, using clock of %dHz", | 
|  | card->host_props.f_max); | 
|  | card->bus_io.clock = card->host_props.f_max; | 
|  | } else { | 
|  | card->bus_io.clock = SD_CLOCK_25MHZ; | 
|  | } | 
|  | ret = sdhc_set_io(card->sdhc, &card->bus_io); | 
|  | if (ret) { | 
|  | LOG_ERR("Failed to raise bus frequency to 25MHz"); | 
|  | return ret; | 
|  | } | 
|  | /* Read SD SCR (SD configuration register), | 
|  | * to get supported bus width | 
|  | */ | 
|  | ret = sdmmc_read_scr(card); | 
|  | if (ret) { | 
|  | return ret; | 
|  | } | 
|  | /* Read switch capabilities to determine what speeds card supports */ | 
|  | if (IS_ENABLED(CONFIG_SDHC_SUPPORTS_NATIVE_MODE) && !card->host_props.is_spi) { | 
|  | ret = sdmmc_read_switch(card); | 
|  | if (ret) { | 
|  | LOG_ERR("Failed to read card functions"); | 
|  | return ret; | 
|  | } | 
|  | } | 
|  | if (IS_ENABLED(CONFIG_SD_UHS_PROTOCOL) && (card->flags & SD_1800MV_FLAG) && | 
|  | sdmmc_host_uhs(&card->host_props) && !(card->host_props.is_spi)) { | 
|  | ret = sdmmc_init_uhs(card); | 
|  | if (ret) { | 
|  | LOG_ERR("UHS card init failed"); | 
|  | } | 
|  | } else { | 
|  | if ((card->flags & SD_HIGH_CAPACITY_FLAG) == 0) { | 
|  | /* Standard capacity SDSC card. set block length to 512 */ | 
|  | ret = sdmmc_set_blocklen(card, SDMMC_DEFAULT_BLOCK_SIZE); | 
|  | if (ret) { | 
|  | LOG_ERR("Could not set SD blocklen to 512"); | 
|  | return ret; | 
|  | } | 
|  | card->block_size = 512; | 
|  | } | 
|  | /* Card is not UHS. Try to use high speed mode */ | 
|  | ret = sdmmc_init_hs(card); | 
|  | if (ret) { | 
|  | LOG_ERR("HS card init failed"); | 
|  | } | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | int sdmmc_ioctl(struct sd_card *card, uint8_t cmd, void *buf) | 
|  | { | 
|  | return card_ioctl(card, cmd, buf); | 
|  | } | 
|  |  | 
|  | int sdmmc_read_blocks(struct sd_card *card, uint8_t *rbuf, uint32_t start_block, | 
|  | uint32_t num_blocks) | 
|  | { | 
|  | return card_read_blocks(card, rbuf, start_block, num_blocks); | 
|  | } | 
|  |  | 
|  | int sdmmc_write_blocks(struct sd_card *card, const uint8_t *wbuf, uint32_t start_block, | 
|  | uint32_t num_blocks) | 
|  | { | 
|  | return card_write_blocks(card, wbuf, start_block, num_blocks); | 
|  | } |