From cc3e7e5e0d25483ceb5d47a658b8835beac9824c Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 18 Feb 2019 13:16:03 -0600 Subject: [PATCH] Add SDIO support for NXP LPC55S69 Tested this with the block device test inside features-storage-tests-blockdevice-general_block_device Below was the change made to add SDIO test --- a/features/storage/TESTS/blockdevice/general_block_device/main.cpp +++ b/features/storage/TESTS/blockdevice/general_block_device/main.cpp @@ -47,6 +47,8 @@ #include "FlashIAPBlockDevice.h" #endif +#include "SDIOBlockDevice.h" + using namespace utest::v1; #define TEST_BLOCK_COUNT 10 @@ -69,6 +71,7 @@ enum bd_type { dataflash, sd, flashiap, + sdio, default_bd }; @@ -90,6 +93,11 @@ static inline uint32_t align_up(uint32_t val, uint32_t size) static BlockDevice *get_bd_instance(uint8_t bd_type) { switch (bd_arr[bd_type]) { + case sdio: { + static SDIOBlockDevice default_bd(P0_17); + return &default_bd; + break; + } case spif: { #if COMPONENT_SPIF static SPIFBlockDevice default_bd( @@ -632,6 +640,8 @@ void test_get_type_functionality() const char *bd_type = block_device->get_type(); TEST_ASSERT_NOT_EQUAL(0, bd_type); + TEST_ASSERT_EQUAL(0, strcmp(bd_type, "SDIO")); + #if COMPONENT_QSPIF TEST_ASSERT_EQUAL(0, strcmp(bd_type, "QSPIF")); #elif COMPONENT_SPIF @@ -708,10 +718,12 @@ int get_bd_count() bd_arr[count++] = flashiap; //4 #endif + bd_arr[count++] = sdio; //5 + return count; } -static const char *prefix[] = {"SPIF ", "QSPIF ", "DATAFLASH ", "SD ", "FLASHIAP ", "DEFAULT "}; +static const char *prefix[] = {"SPIF ", "QSPIF ", "DATAFLASH ", "SD ", "FLASHIAP ", "SDIO ", "DEFAULT "}; int main() { Signed-off-by: Mahesh Mahadevan --- target/board.h | 41 + target/fsl_sd.c | 1967 +++++++++++++++++++++++++++++++++++++ target/fsl_sd.h | 322 ++++++ target/fsl_sdmmc_common.c | 298 ++++++ target/fsl_sdmmc_common.h | 236 +++++ target/fsl_sdmmc_host.c | 245 +++++ target/fsl_sdmmc_host.h | 736 ++++++++++++++ target/fsl_sdmmc_spec.h | 1164 ++++++++++++++++++++++ target/sdio_device.c | 188 ++++ target/sdio_device.h | 52 + 10 files changed, 5249 insertions(+) create mode 100644 target/board.h create mode 100644 target/fsl_sd.c create mode 100644 target/fsl_sd.h create mode 100644 target/fsl_sdmmc_common.c create mode 100644 target/fsl_sdmmc_common.h create mode 100644 target/fsl_sdmmc_host.c create mode 100644 target/fsl_sdmmc_host.h create mode 100644 target/fsl_sdmmc_spec.h create mode 100644 target/sdio_device.c create mode 100644 target/sdio_device.h diff --git a/target/board.h b/target/board.h new file mode 100644 index 0000000..560a1fc --- /dev/null +++ b/target/board.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +#include "fsl_common.h" +#include "fsl_gpio.h" +#include "fsl_iocon.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +#define BOARD_SDIF_BASEADDR SDIF +#define BOARD_SDIF_CLKSRC kCLOCK_SDio +#define BOARD_SDIF_CLK_FREQ CLOCK_GetFreq(kCLOCK_SDio) +#define BOARD_SDIF_CLK_ATTACH kMAIN_CLK_to_SDIO_CLK +#define BOARD_SDIF_IRQ SDIO_IRQn +#define BOARD_MMC_VCC_SUPPLY kMMC_VoltageWindows270to360 +#define BOARD_SD_CARD_DETECT_PIN 17 +#define BOARD_SD_CARD_DETECT_PORT 0 +#define BOARD_SD_CARD_DETECT_GPIO GPIO +#define BOARD_SD_DETECT_TYPE kSDMMCHOST_DetectCardByHostCD + +#define BOARD_SDIF_CD_GPIO_INIT() \ + { \ + CLOCK_EnableClock(kCLOCK_Gpio2); \ + GPIO_PinInit(BOARD_SD_CARD_DETECT_GPIO, BOARD_SD_CARD_DETECT_PORT, BOARD_SD_CARD_DETECT_PIN, \ + &(gpio_pin_config_t){kGPIO_DigitalInput, 0U}); \ + } +#define BOARD_SDIF_CD_STATUS() \ + GPIO_PinRead(BOARD_SD_CARD_DETECT_GPIO, BOARD_SD_CARD_DETECT_PORT, BOARD_SD_CARD_DETECT_PIN) + +#define BOARD_SDIF_CLK_ATTACH kMAIN_CLK_to_SDIO_CLK + +#endif /* _BOARD_H_ */ diff --git a/target/fsl_sd.c b/target/fsl_sd.c new file mode 100644 index 0000000..0cbb8b7 --- /dev/null +++ b/target/fsl_sd.c @@ -0,0 +1,1967 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include "fsl_sd.h" + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +/*! + * @brief Wait write process complete. + * + * @param card Card descriptor. + * @retval kStatus_Timeout Send command timeout. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_WaitWriteComplete(sd_card_t *card); + +/*! + * @brief send write success blocks. + * + * @param card Card descriptor. + * @param blocks blocks number wirte successed + * @retval kStatus_SDMMC_TransferFailed Send command failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SendWriteSuccessBlocks(sd_card_t *card, uint32_t *blocks); + +/*! + * @brief Send SEND_APPLICATION_COMMAND command. + * + * @param card Card descriptor. + * @param relativeaddress + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_CardNotSupport Card doesn't support. + * @retval kStatus_Success Operate successfully. + */ +static status_t inline SD_SendApplicationCmd(sd_card_t *card, uint32_t relativeAddress); + +/*! + * @brief Send GO_IDLE command to set the card to be idle state. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t inline SD_GoIdle(sd_card_t *card); + +/*! + * @brief Send STOP_TRANSMISSION command after multiple blocks read/write. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_StopTransmission(sd_card_t *card); + +/*! + * @brief Send SET_BLOCK_SIZE command. + * + * @param card Card descriptor. + * @param blockSize Block size. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t inline SD_SetBlockSize(sd_card_t *card, uint32_t blockSize); + +/*! + * @brief Send GET_RCA command to get card relative address. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SendRca(sd_card_t *card); + +/*! + * @brief Send SWITCH_FUNCTION command to switch the card function group. + * + * @param card Card descriptor. + * @param mode 0 to check function group. 1 to switch function group + * @param group Function group + * @param number Function number in the function group. + * @param status Switch function status. + * @retval kStatus_SDMMC_SetCardBlockSizeFailed Set card block size failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SwitchFunction(sd_card_t *card, uint32_t mode, uint32_t group, uint32_t number, uint32_t *status); + +/*! + * @brief Decode raw SCR register content in the data blocks. + * + * @param card Card descriptor. + * @param rawScr Raw SCR register content. + */ +static void SD_DecodeScr(sd_card_t *card, uint32_t *rawScr); + +/*! + * @brief Send GET_SCR command. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_SendApplicationCommandFailed Send application command failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_NotSupportYet Not support yet. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SendScr(sd_card_t *card); + +/*! + * @brief Switch the card to be high speed mode. + * + * @param card Card descriptor. + * @param group Group number. + * @param functio Function number. + * @retval kStatus_SDMMC_CardNotSupport Card not support. + * @retval kStatus_SDMMC_SwitchFailed Switch failed. + * @retval kStatus_SDMMC_NotSupportYet Not support yet. + * @retval kStatus_Fail Switch failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SelectFunction(sd_card_t *card, uint32_t group, uint32_t function); + +/*! + * @brief Send SET_DATA_WIDTH command to set SD bus width. + * + * @param card Card descriptor. + * @param width Data bus width. + * @retval kStatus_SDMMC_SendApplicationCommandFailed Send application command failed. + * @retval kStatus_InvalidArgument Invalid argument. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SetDataBusWidth(sd_card_t *card, sd_data_bus_width_t width); + +/*! + * @brief Decode raw CSD register content in the data blocks. + * + * @param card Card descriptor. + * @param rawCsd Raw CSD register content. + */ +static void SD_DecodeCsd(sd_card_t *card, uint32_t *rawCsd); + +/*! + * @brief Send SEND_CSD command to get CSD register content from Card. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SendCsd(sd_card_t *card); + +/*! + * @brief Decode raw CID register content in the data blocks. + * + * @param rawCid raw CID register content. + * @param card Card descriptor. + */ +static void SD_DecodeCid(sd_card_t *card, uint32_t *rawCid); + +/*! + * @brief Send GET_CID command to get CID from card. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_AllSendCid(sd_card_t *card); + +/*! + * @brief Send SEND_OPERATION_CONDITION command. + * + * This function sends host capacity support information and asks the accessed card to send its operating condition + * register content. + * + * @param card Card descriptor. + * @param argument The argument of the send operation condition ncomamnd. + * @retval kStatus_SDMMC_SendApplicationCommandFailed Send application command failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Timeout Timeout. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_ApplicationSendOperationCondition(sd_card_t *card, uint32_t argument); + +/*! + * @brief Send GET_INTERFACE_CONDITION command to get card interface condition. + * + * This function checks card interface condition, which includes host supply voltage information and asks the card + * whether card supports the specified host voltage. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_CardNotSupport Card doesn't support. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SendInterfaceCondition(sd_card_t *card); + +/*! + * @brief Send switch voltage command + * switch card voltage to 1.8v + * + * @param card Card descriptor. + */ +static status_t SD_SwitchVoltage(sd_card_t *card); + +/*! + * @brief select bus timing + * select card timing + * @param card Card descriptor. + */ +static status_t SD_SelectBusTiming(sd_card_t *card); + +/*! + * @brief Decode sd 512 bit status + * @param card Card descriptor. + * @param 512 bits satus raw data. + */ +static void SD_DecodeStatus(sd_card_t *card, uint32_t *src); + +/*! + * @brief Read data from specific SD card. + * + * @param card Card descriptor. + * @param buffer Buffer to save data blocks read. + * @param startBlock Card start block number to be read. + * @param blockSize Block size. + * @param blockCount Block count. + * @retval kStatus_SDMMC_CardNotSupport Card doesn't support. + * @retval kStatus_SDMMC_WaitWriteCompleteFailed Wait write complete failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_StopTransmissionFailed Stop transmission failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_Read(sd_card_t *card, uint8_t *buffer, uint32_t startBlock, uint32_t blockSize, uint32_t blockCount); + +/*! + * @brief Write data to specific card + * + * @param card Card descriptor. + * @param buffer Buffer to be sent. + * @param startBlock Card start block number to be written. + * @param blockSize Block size. + * @param blockCount Block count. + * @param blockWritten successfully write blocks + * @retval kStatus_SDMMC_CardNotSupport Card doesn't support. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_StopTransmissionFailed Stop transmission failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_Write(sd_card_t *card, + const uint8_t *buffer, + uint32_t startBlock, + uint32_t blockSize, + uint32_t blockCount, + uint32_t *blockWritten); + +/*! + * @brief Erase data for the given block range. + * + * @param card Card descriptor. + * @param startBlock Card start block number to be erased. + * @param blockCount The block count to be erased. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_Erase(sd_card_t *card, uint32_t startBlock, uint32_t blockCount); + +/*! + * @brief card transfer function. + * + * @param card Card descriptor. + * @param content Transfer content. + * @param retry Retry times + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + * @retval kStatus_SDMMC_TuningFail tuning fail + */ +static status_t SD_Transfer(sd_card_t *card, SDMMCHOST_TRANSFER *content, uint32_t retry); + +/*! + * @brief card execute tuning function. + * + * @param card Card descriptor. + * @retval kStatus_Success Operate successfully. + * @retval kStatus_SDMMC_TuningFail tuning fail. + * @retval kStatus_SDMMC_TransferFailed transfer fail + */ +static status_t inline SD_ExecuteTuning(sd_card_t *card); + +/******************************************************************************* + * Variables + ******************************************************************************/ +/* g_sdmmc statement */ +extern uint32_t g_sdmmc[SDK_SIZEALIGN(SDMMC_GLOBAL_BUFFER_SIZE, SDMMC_DATA_BUFFER_ALIGN_CACHE)]; +static uint32_t s_sdAuSizeMap[] = {0, + 16 * 1024, + 32 * 1024, + 64 * 1024, + 128 * 1024, + 256 * 1024, + 512 * 1024, + 1024 * 1024, + 2 * 1024 * 1024, + 4 * 1024 * 1024, + 8 * 1024 * 1024, + 12 * 1024 * 1024, + 16 * 1024 * 1024, + 24 * 1024 * 1024, + 32 * 1024 * 1024, + 64 * 1024 * 1024}; +/******************************************************************************* + * Code + ******************************************************************************/ +static status_t inline SD_SendApplicationCmd(sd_card_t *card, uint32_t relativeAddress) +{ + assert(card); + + return SDMMC_SendApplicationCommand(card->host.base, card->host.transfer, relativeAddress); +} + +static status_t inline SD_GoIdle(sd_card_t *card) +{ + assert(card); + + return SDMMC_GoIdle(card->host.base, card->host.transfer); +} + +static status_t inline SD_SetBlockSize(sd_card_t *card, uint32_t blockSize) +{ + assert(card); + + return SDMMC_SetBlockSize(card->host.base, card->host.transfer, blockSize); +} + +static status_t inline SD_ExecuteTuning(sd_card_t *card) +{ + assert(card); + + return SDMMC_ExecuteTuning(card->host.base, card->host.transfer, kSD_SendTuningBlock, 64U); +} + +static status_t SD_SwitchVoltage(sd_card_t *card) +{ + assert(card); + + return SDMMC_SwitchVoltage(card->host.base, card->host.transfer); +} + +static status_t SD_StopTransmission(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + command.index = kSDMMC_StopTransmission; + command.argument = 0U; + command.type = kCARD_CommandTypeAbort; + command.responseType = kCARD_ResponseTypeR1b; + command.responseErrorFlags = SDMMC_R1_ALL_ERROR_FLAG; + + content.command = &command; + content.data = 0U; + error = card->host.transfer(card->host.base, &content); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send CMD12 failed with host error %d, reponse %x\r\n", error, command.response[0U]); + return kStatus_SDMMC_TransferFailed; + } + + return kStatus_Success; +} + +static status_t SD_Transfer(sd_card_t *card, SDMMCHOST_TRANSFER *content, uint32_t retry) +{ + assert(card->host.transfer); + assert(content); + status_t error; + + do + { + error = card->host.transfer(card->host.base, content); +#if SDMMC_ENABLE_SOFTWARE_TUNING + if (((error == SDMMCHOST_RETUNING_REQUEST) || (error == SDMMCHOST_TUNING_ERROR)) && + (card->currentTiming == kSD_TimingSDR104Mode)) + { + /* tuning error need reset tuning circuit */ + if (error == SDMMCHOST_TUNING_ERROR) + { + SDMMCHOST_RESET_TUNING(card->host.base, 100U); + } + + /* execute re-tuning */ + if (SD_ExecuteTuning(card) != kStatus_Success) + { + error = kStatus_SDMMC_TuningFail; + break; + } + else + { + continue; + } + } + else +#endif + if (error != kStatus_Success) + { + /* if transfer data failed, send cmd12 to abort current transfer */ + if (content->data) + { + SD_StopTransmission(card); + } + } + + if (retry != 0U) + { + retry--; + } + else + { + break; + } + + } while (error != kStatus_Success); + + return error; +} + +static status_t SD_WaitWriteComplete(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + command.index = kSDMMC_SendStatus; + command.argument = card->relativeAddress << 16U; + command.responseType = kCARD_ResponseTypeR1; + + do + { + content.command = &command; + content.data = 0U; + error = SD_Transfer(card, &content, 2U); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send CMD13 failed with host error %d, response %x", error, command.response[0U]); + break; + } + + if ((command.response[0U] & SDMMC_MASK(kSDMMC_R1ReadyForDataFlag)) && + (SDMMC_R1_CURRENT_STATE(command.response[0U]) != kSDMMC_R1StateProgram)) + { + break; + } + } while (true); + + return error; +} + +static status_t SD_SendWriteSuccessBlocks(sd_card_t *card, uint32_t *blocks) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + SDMMCHOST_DATA data = {0}; + status_t error = kStatus_Success; + + memset(g_sdmmc, 0U, sizeof(g_sdmmc)); + + /* Wait for the card write process complete because of that card read process and write process use one buffer. */ + if (kStatus_Success != SD_WaitWriteComplete(card)) + { + return kStatus_SDMMC_WaitWriteCompleteFailed; + } + + if (kStatus_Success != SD_SendApplicationCmd(card, card->relativeAddress)) + { + return kStatus_SDMMC_SendApplicationCommandFailed; + } + + command.index = kSD_ApplicationSendNumberWriteBlocks; + command.responseType = kCARD_ResponseTypeR1; + + data.blockSize = 4U; + data.blockCount = 1U; + data.rxData = &g_sdmmc[0]; + + content.command = &command; + content.data = &data; + error = card->host.transfer(card->host.base, &content); + if ((kStatus_Success != error) || ((command.response[0U]) & SDMMC_R1_ALL_ERROR_FLAG)) + { + SDMMC_LOG("\r\nError: send ACMD13 failed with host error %d, response %x", error, command.response[0U]); + } + else + { + *blocks = SWAP_WORD_BYTE_SEQUENCE(g_sdmmc[0]); + } + + return error; +} + +static status_t SD_SendRca(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + command.index = kSD_SendRelativeAddress; + command.argument = 0U; + command.responseType = kCARD_ResponseTypeR6; + + content.command = &command; + content.data = NULL; + + error = card->host.transfer(card->host.base, &content); + if (kStatus_Success == error) + { + card->relativeAddress = (command.response[0U] >> 16U); + } + else + { + SDMMC_LOG("\r\nError: send CMD3 failed with host error %d, response %x", error, command.response[0U]); + } + + return error; +} + +static status_t SD_SwitchFunction(sd_card_t *card, uint32_t mode, uint32_t group, uint32_t number, uint32_t *status) +{ + assert(card); + assert(status); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + SDMMCHOST_DATA data = {0}; + status_t error = kStatus_Success; + + command.index = kSD_Switch; + command.argument = (mode << 31U | 0x00FFFFFFU); + command.argument &= ~((uint32_t)(0xFU) << (group * 4U)); + command.argument |= (number << (group * 4U)); + command.responseType = kCARD_ResponseTypeR1; + + data.blockSize = 64U; + data.blockCount = 1U; + data.rxData = status; + + content.command = &command; + content.data = &data; + error = card->host.transfer(card->host.base, &content); + if ((kStatus_Success != error) || ((command.response[0U]) & SDMMC_R1_ALL_ERROR_FLAG)) + { + SDMMC_LOG("\r\n\r\nError: send CMD6 failed with host error %d, response %x", error, command.response[0U]); + } + + return error; +} + +static void SD_DecodeScr(sd_card_t *card, uint32_t *rawScr) +{ + assert(card); + assert(rawScr); + + sd_scr_t *scr; + + scr = &(card->scr); + scr->scrStructure = (uint8_t)((rawScr[0U] & 0xF0000000U) >> 28U); + scr->sdSpecification = (uint8_t)((rawScr[0U] & 0xF000000U) >> 24U); + if ((uint8_t)((rawScr[0U] & 0x800000U) >> 23U)) + { + scr->flags |= kSD_ScrDataStatusAfterErase; + } + scr->sdSecurity = (uint8_t)((rawScr[0U] & 0x700000U) >> 20U); + scr->sdBusWidths = (uint8_t)((rawScr[0U] & 0xF0000U) >> 16U); + if ((uint8_t)((rawScr[0U] & 0x8000U) >> 15U)) + { + scr->flags |= kSD_ScrSdSpecification3; + } + scr->extendedSecurity = (uint8_t)((rawScr[0U] & 0x7800U) >> 10U); + scr->commandSupport = (uint8_t)(rawScr[0U] & 0x3U); + scr->reservedForManufacturer = rawScr[1U]; + /* Get specification version. */ + switch (scr->sdSpecification) + { + case 0U: + card->version = kSD_SpecificationVersion1_0; + break; + case 1U: + card->version = kSD_SpecificationVersion1_1; + break; + case 2U: + card->version = kSD_SpecificationVersion2_0; + if (card->scr.flags & kSD_ScrSdSpecification3) + { + card->version = kSD_SpecificationVersion3_0; + } + break; + default: + break; + } + if (card->scr.sdBusWidths & 0x4U) + { + card->flags |= kSD_Support4BitWidthFlag; + } + /* speed class control cmd */ + if (card->scr.commandSupport & 0x01U) + { + card->flags |= kSD_SupportSpeedClassControlCmd; + } + /* set block count cmd */ + if (card->scr.commandSupport & 0x02U) + { + card->flags |= kSD_SupportSetBlockCountCmd; + } +} + +static status_t SD_SendScr(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + SDMMCHOST_DATA data = {0}; + uint32_t *rawScr = g_sdmmc; + status_t error = kStatus_Success; + + /* memset the global buffer */ + memset(g_sdmmc, 0U, sizeof(g_sdmmc)); + + if (kStatus_Success != SD_SendApplicationCmd(card, card->relativeAddress)) + { + return kStatus_SDMMC_SendApplicationCommandFailed; + } + + command.index = kSD_ApplicationSendScr; + command.responseType = kCARD_ResponseTypeR1; + command.argument = 0U; + + data.blockSize = 8U; + data.blockCount = 1U; + data.rxData = rawScr; + + content.data = &data; + content.command = &command; + error = card->host.transfer(card->host.base, &content); + if ((kStatus_Success != error) || ((command.response[0U]) & SDMMC_R1_ALL_ERROR_FLAG)) + { + SDMMC_LOG("\r\nError: send ACMD51 failed with host error %d, response %x", error, command.response[0U]); + } + else + { + /* SCR register data byte sequence from card is big endian(MSB first). */ + switch (card->host.config.endianMode) + { + case kSDMMCHOST_EndianModeLittle: + /* In little endian mode, SD bus byte transferred first is the byte stored in lowest byte position in a + word which will cause 4 byte's sequence in a word is not consistent with their original sequence from + card. So the sequence of 4 bytes received in a word should be converted. */ + rawScr[0U] = SWAP_WORD_BYTE_SEQUENCE(rawScr[0U]); + rawScr[1U] = SWAP_WORD_BYTE_SEQUENCE(rawScr[1U]); + break; + case kSDMMCHOST_EndianModeBig: + break; /* Doesn't need to switch byte sequence when decodes bytes as big endian sequence. */ + case kSDMMCHOST_EndianModeHalfWordBig: + rawScr[0U] = SWAP_HALF_WROD_BYTE_SEQUENCE(rawScr[0U]); + rawScr[1U] = SWAP_HALF_WROD_BYTE_SEQUENCE(rawScr[1U]); + break; + default: + return kStatus_SDMMC_NotSupportYet; + } + memcpy(card->rawScr, rawScr, sizeof(card->rawScr)); + /* decode scr */ + SD_DecodeScr(card, rawScr); + } + + return error; +} + +static status_t SD_SelectFunction(sd_card_t *card, uint32_t group, uint32_t function) +{ + assert(card); + + uint32_t *functionStatus = g_sdmmc; + uint16_t functionGroupInfo[6U] = {0}; + uint32_t currentFunctionStatus = 0U; + + /* memset the global buffer */ + memset(g_sdmmc, 0, sizeof(g_sdmmc)); + + /* check if card support CMD6 */ + if ((card->version <= kSD_SpecificationVersion1_0) || (!(card->csd.cardCommandClass & kSDMMC_CommandClassSwitch))) + { + SDMMC_LOG("\r\nError: current card not support CMD6"); + return kStatus_SDMMC_NotSupportYet; + } + + /* Check if card support high speed mode. */ + if (kStatus_Success != SD_SwitchFunction(card, kSD_SwitchCheck, group, function, functionStatus)) + { + return kStatus_SDMMC_TransferFailed; + } + + /* Switch function status byte sequence from card is big endian(MSB first). */ + switch (card->host.config.endianMode) + { + case kSDMMCHOST_EndianModeLittle: + /* In little endian mode, SD bus byte transferred first is the byte stored in lowest byte position in + a word which will cause 4 byte's sequence in a word is not consistent with their original sequence from + card. So the sequence of 4 bytes received in a word should be converted. */ + functionStatus[0U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[0U]); + functionStatus[1U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[1U]); + functionStatus[2U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[2U]); + functionStatus[3U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[3U]); + functionStatus[4U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[4U]); + break; + case kSDMMCHOST_EndianModeBig: + break; /* Doesn't need to switch byte sequence when decodes bytes as big endian sequence. */ + case kSDMMCHOST_EndianModeHalfWordBig: + functionStatus[0U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[0U]); + functionStatus[1U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[1U]); + functionStatus[2U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[2U]); + functionStatus[3U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[3U]); + functionStatus[4U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[4U]); + break; + default: + return kStatus_SDMMC_NotSupportYet; + } + /* -functionStatus[0U]---bit511~bit480; + -functionStatus[1U]---bit479~bit448; + -functionStatus[2U]---bit447~bit416; + -functionStatus[3U]---bit415~bit384; + -functionStatus[4U]---bit383~bit352; + According to the "switch function status[bits 511~0]" return by switch command in mode "check function": + -Check if function 1(high speed) in function group 1 is supported by checking if bit 401 is set; + -check if function 1 is ready and can be switched by checking if bits 379~376 equal value 1; + */ + functionGroupInfo[5U] = (uint16_t)functionStatus[0U]; + functionGroupInfo[4U] = (uint16_t)(functionStatus[1U] >> 16U); + functionGroupInfo[3U] = (uint16_t)(functionStatus[1U]); + functionGroupInfo[2U] = (uint16_t)(functionStatus[2U] >> 16U); + functionGroupInfo[1U] = (uint16_t)(functionStatus[2U]); + functionGroupInfo[0U] = (uint16_t)(functionStatus[3U] >> 16U); + currentFunctionStatus = ((functionStatus[3U] & 0xFFU) << 8U) | (functionStatus[4U] >> 24U); + + /* check if function is support */ + if (((functionGroupInfo[group] & (1 << function)) == 0U) || + ((currentFunctionStatus >> (group * 4U)) & 0xFU) != function) + { + SDMMC_LOG("\r\nError: current card not support function %d", function); + return kStatus_SDMMC_NotSupportYet; + } + + /* Switch to high speed mode. */ + if (kStatus_Success != SD_SwitchFunction(card, kSD_SwitchSet, group, function, functionStatus)) + { + return kStatus_SDMMC_TransferFailed; + } + + /* Switch function status byte sequence from card is big endian(MSB first). */ + switch (card->host.config.endianMode) + { + case kSDMMCHOST_EndianModeLittle: + /* In little endian mode is little endian, SD bus byte transferred first is the byte stored in lowest byte + position in a word which will cause 4 byte's sequence in a word is not consistent with their original + sequence from card. So the sequence of 4 bytes received in a word should be converted. */ + functionStatus[3U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[3U]); + functionStatus[4U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[4U]); + break; + case kSDMMCHOST_EndianModeBig: + break; /* Doesn't need to switch byte sequence when decodes bytes as big endian sequence. */ + case kSDMMCHOST_EndianModeHalfWordBig: + functionStatus[3U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[3U]); + functionStatus[4U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[4U]); + break; + default: + return kStatus_SDMMC_NotSupportYet; + } + /* According to the "switch function status[bits 511~0]" return by switch command in mode "set function": + -check if group 1 is successfully changed to function 1 by checking if bits 379~376 equal value 1; + */ + currentFunctionStatus = ((functionStatus[3U] & 0xFFU) << 8U) | (functionStatus[4U] >> 24U); + + if (((currentFunctionStatus >> (group * 4U)) & 0xFU) != function) + { + SDMMC_LOG("\r\nError: switch to function %d failed", function); + return kStatus_SDMMC_SwitchFailed; + } + + return kStatus_Success; +} + +static status_t SD_SetDataBusWidth(sd_card_t *card, sd_data_bus_width_t width) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + if (kStatus_Success != SD_SendApplicationCmd(card, card->relativeAddress)) + { + return kStatus_SDMMC_SendApplicationCommandFailed; + } + + command.index = kSD_ApplicationSetBusWdith; + command.responseType = kCARD_ResponseTypeR1; + switch (width) + { + case kSD_DataBusWidth1Bit: + command.argument = 0U; + break; + case kSD_DataBusWidth4Bit: + command.argument = 2U; + break; + default: + return kStatus_InvalidArgument; + } + + content.command = &command; + content.data = NULL; + error = card->host.transfer(card->host.base, &content); + if ((kStatus_Success != error) || ((command.response[0U]) & SDMMC_R1_ALL_ERROR_FLAG)) + { + SDMMC_LOG("\r\nError: send ACMD6 failed with host error %d, response %x", error, command.response[0U]); + } + + return error; +} + +static void SD_DecodeCsd(sd_card_t *card, uint32_t *rawCsd) +{ + assert(card); + assert(rawCsd); + + sd_csd_t *csd; + + csd = &(card->csd); + csd->csdStructure = (uint8_t)((rawCsd[3U] & 0xC0000000U) >> 30U); + csd->dataReadAccessTime1 = (uint8_t)((rawCsd[3U] & 0xFF0000U) >> 16U); + csd->dataReadAccessTime2 = (uint8_t)((rawCsd[3U] & 0xFF00U) >> 8U); + csd->transferSpeed = (uint8_t)(rawCsd[3U] & 0xFFU); + csd->cardCommandClass = (uint16_t)((rawCsd[2U] & 0xFFF00000U) >> 20U); + csd->readBlockLength = (uint8_t)((rawCsd[2U] & 0xF0000U) >> 16U); + if (rawCsd[2U] & 0x8000U) + { + csd->flags |= kSD_CsdReadBlockPartialFlag; + } + if (rawCsd[2U] & 0x4000U) + { + csd->flags |= kSD_CsdReadBlockPartialFlag; + } + if (rawCsd[2U] & 0x2000U) + { + csd->flags |= kSD_CsdReadBlockMisalignFlag; + } + if (rawCsd[2U] & 0x1000U) + { + csd->flags |= kSD_CsdDsrImplementedFlag; + } + switch (csd->csdStructure) + { + case 0: + csd->deviceSize = (uint32_t)((rawCsd[2U] & 0x3FFU) << 2U); + csd->deviceSize |= (uint32_t)((rawCsd[1U] & 0xC0000000U) >> 30U); + csd->readCurrentVddMin = (uint8_t)((rawCsd[1U] & 0x38000000U) >> 27U); + csd->readCurrentVddMax = (uint8_t)((rawCsd[1U] & 0x7000000U) >> 24U); + csd->writeCurrentVddMin = (uint8_t)((rawCsd[1U] & 0xE00000U) >> 20U); + csd->writeCurrentVddMax = (uint8_t)((rawCsd[1U] & 0x1C0000U) >> 18U); + csd->deviceSizeMultiplier = (uint8_t)((rawCsd[1U] & 0x38000U) >> 15U); + + /* Get card total block count and block size. */ + card->blockCount = ((csd->deviceSize + 1U) << (csd->deviceSizeMultiplier + 2U)); + card->blockSize = (1U << (csd->readBlockLength)); + if (card->blockSize != FSL_SDMMC_DEFAULT_BLOCK_SIZE) + { + card->blockCount = (card->blockCount * card->blockSize); + card->blockSize = FSL_SDMMC_DEFAULT_BLOCK_SIZE; + card->blockCount = (card->blockCount / card->blockSize); + } + break; + case 1: + card->blockSize = FSL_SDMMC_DEFAULT_BLOCK_SIZE; + + csd->deviceSize = (uint32_t)((rawCsd[2U] & 0x3FU) << 16U); + csd->deviceSize |= (uint32_t)((rawCsd[1U] & 0xFFFF0000U) >> 16U); + if (csd->deviceSize >= 0xFFFFU) + { + card->flags |= kSD_SupportSdxcFlag; + } + + card->blockCount = ((csd->deviceSize + 1U) * 1024U); + break; + default: + break; + } + if ((uint8_t)((rawCsd[1U] & 0x4000U) >> 14U)) + { + csd->flags |= kSD_CsdEraseBlockEnabledFlag; + } + csd->eraseSectorSize = (uint8_t)((rawCsd[1U] & 0x3F80U) >> 7U); + csd->writeProtectGroupSize = (uint8_t)(rawCsd[1U] & 0x7FU); + if ((uint8_t)(rawCsd[0U] & 0x80000000U)) + { + csd->flags |= kSD_CsdWriteProtectGroupEnabledFlag; + } + csd->writeSpeedFactor = (uint8_t)((rawCsd[0U] & 0x1C000000U) >> 26U); + csd->writeBlockLength = (uint8_t)((rawCsd[0U] & 0x3C00000U) >> 22U); + if ((uint8_t)((rawCsd[0U] & 0x200000U) >> 21U)) + { + csd->flags |= kSD_CsdWriteBlockPartialFlag; + } + if ((uint8_t)((rawCsd[0U] & 0x8000U) >> 15U)) + { + csd->flags |= kSD_CsdFileFormatGroupFlag; + } + if ((uint8_t)((rawCsd[0U] & 0x4000U) >> 14U)) + { + csd->flags |= kSD_CsdCopyFlag; + } + if ((uint8_t)((rawCsd[0U] & 0x2000U) >> 13U)) + { + csd->flags |= kSD_CsdPermanentWriteProtectFlag; + } + if ((uint8_t)((rawCsd[0U] & 0x1000U) >> 12U)) + { + csd->flags |= kSD_CsdTemporaryWriteProtectFlag; + } + csd->fileFormat = (uint8_t)((rawCsd[0U] & 0xC00U) >> 10U); +} + +static status_t SD_SendCsd(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + command.index = kSDMMC_SendCsd; + command.argument = (card->relativeAddress << 16U); + command.responseType = kCARD_ResponseTypeR2; + + content.command = &command; + content.data = NULL; + error = card->host.transfer(card->host.base, &content); + if (kStatus_Success == error) + { + memcpy(card->rawCsd, command.response, sizeof(card->rawCsd)); + /* The response is from bit 127:8 in R2, corrisponding to command.response[3U]:command.response[0U][31U:8]. */ + SD_DecodeCsd(card, command.response); + } + else + { + error = kStatus_SDMMC_TransferFailed; + SDMMC_LOG("\r\nError: send CMD9(get csd) failed with host error %d, response %x", error, command.response[0U]); + } + + return error; +} + +static void SD_DecodeCid(sd_card_t *card, uint32_t *rawCid) +{ + assert(card); + assert(rawCid); + + sd_cid_t *cid; + + cid = &(card->cid); + cid->manufacturerID = (uint8_t)((rawCid[3U] & 0xFF000000U) >> 24U); + cid->applicationID = (uint16_t)((rawCid[3U] & 0xFFFF00U) >> 8U); + + cid->productName[0U] = (uint8_t)((rawCid[3U] & 0xFFU)); + cid->productName[1U] = (uint8_t)((rawCid[2U] & 0xFF000000U) >> 24U); + cid->productName[2U] = (uint8_t)((rawCid[2U] & 0xFF0000U) >> 16U); + cid->productName[3U] = (uint8_t)((rawCid[2U] & 0xFF00U) >> 8U); + cid->productName[4U] = (uint8_t)((rawCid[2U] & 0xFFU)); + + cid->productVersion = (uint8_t)((rawCid[1U] & 0xFF000000U) >> 24U); + + cid->productSerialNumber = (uint32_t)((rawCid[1U] & 0xFFFFFFU) << 8U); + cid->productSerialNumber |= (uint32_t)((rawCid[0U] & 0xFF000000U) >> 24U); + + cid->manufacturerData = (uint16_t)((rawCid[0U] & 0xFFF00U) >> 8U); +} + +static status_t SD_AllSendCid(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_AllSendCid; + command.argument = 0U; + command.responseType = kCARD_ResponseTypeR2; + + content.command = &command; + content.data = NULL; + if (kStatus_Success == card->host.transfer(card->host.base, &content)) + { + memcpy(card->rawCid, command.response, sizeof(card->rawCid)); + SD_DecodeCid(card, command.response); + + return kStatus_Success; + } + + return kStatus_SDMMC_TransferFailed; +} + +static status_t SD_ApplicationSendOperationCondition(sd_card_t *card, uint32_t argument) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Fail; + uint32_t i = FSL_SDMMC_MAX_VOLTAGE_RETRIES; + + command.index = kSD_ApplicationSendOperationCondition; + command.argument = argument; + command.responseType = kCARD_ResponseTypeR3; + + while (i--) + { + if (kStatus_Success != SD_SendApplicationCmd(card, 0U)) + { + continue; + } + + content.command = &command; + content.data = NULL; + error = card->host.transfer(card->host.base, &content); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send ACMD41 failed with host error %d, response %x", error, command.response[0U]); + return kStatus_SDMMC_TransferFailed; + } + + /* Wait until card exit busy state. */ + if (command.response[0U] & SDMMC_MASK(kSD_OcrPowerUpBusyFlag)) + { + /* high capacity check */ + if (command.response[0U] & SDMMC_MASK(kSD_OcrCardCapacitySupportFlag)) + { + card->flags |= kSD_SupportHighCapacityFlag; + } + /* 1.8V support */ + if (command.response[0U] & SDMMC_MASK(kSD_OcrSwitch18AcceptFlag)) + { + card->flags |= kSD_SupportVoltage180v; + } + card->ocr = command.response[0U]; + + return kStatus_Success; + } + } + + SDMMC_LOG("\r\nError: send ACMD41 timeout"); + + return error; +} + +static status_t SD_SendInterfaceCondition(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + uint32_t i = FSL_SDMMC_MAX_CMD_RETRIES; + status_t error = kStatus_Success; + + command.index = kSD_SendInterfaceCondition; + command.argument = 0x1AAU; + command.responseType = kCARD_ResponseTypeR7; + + content.command = &command; + content.data = NULL; + do + { + error = card->host.transfer(card->host.base, &content); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send CMD8 failed with host error %d, response %x", error, command.response[0U]); + } + else + { + if ((command.response[0U] & 0xFFU) != 0xAAU) + { + error = kStatus_SDMMC_CardNotSupport; + SDMMC_LOG("\r\nError: card not support CMD8"); + } + else + { + error = kStatus_Success; + } + } + } while (--i && (error != kStatus_Success)); + + return error; +} + +static status_t SD_SelectBusTiming(sd_card_t *card) +{ + assert(card); + + status_t error = kStatus_SDMMC_SwitchBusTimingFailed; + + if (card->operationVoltage != kCARD_OperationVoltage180V) + { + /* Switch the card to high speed mode */ + if (card->host.capability.flags & kSDMMCHOST_SupportHighSpeed) + { + /* group 1, function 1 ->high speed mode*/ + error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionSDR25HighSpeed); + /* If the result isn't "switching to high speed mode(50MHZ) successfully or card doesn't support high speed + * mode". Return failed status. */ + if (error == kStatus_Success) + { + card->currentTiming = kSD_TimingSDR25HighSpeedMode; + card->busClock_Hz = + SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, SD_CLOCK_50MHZ); + } + else if (error == kStatus_SDMMC_NotSupportYet) + { + /* if not support high speed, keep the card work at default mode */ + SDMMC_LOG("\r\nNote: High speed mode is not supported by card"); + return kStatus_Success; + } + } + else + { + /* if not support high speed, keep the card work at default mode */ + return kStatus_Success; + } + } + /* card is in UHS_I mode */ + else if ((kSDMMCHOST_SupportSDR104 != SDMMCHOST_NOT_SUPPORT) || + (kSDMMCHOST_SupportSDR50 != SDMMCHOST_NOT_SUPPORT) || (kSDMMCHOST_SupportDDR50 != SDMMCHOST_NOT_SUPPORT)) + { + switch (card->currentTiming) + { + /* if not select timing mode, sdmmc will handle it automatically*/ + case kSD_TimingSDR12DefaultMode: + case kSD_TimingSDR104Mode: + error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionSDR104); + if (error == kStatus_Success) + { + card->currentTiming = kSD_TimingSDR104Mode; + card->busClock_Hz = SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, + SDMMCHOST_SUPPORT_SDR104_FREQ); + break; + } + SDMMC_LOG("\r\nNote: SDR104 mode is not supported by card"); + + case kSD_TimingDDR50Mode: + error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionDDR50); + if (error == kStatus_Success) + { + card->currentTiming = kSD_TimingDDR50Mode; + card->busClock_Hz = + SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, SD_CLOCK_50MHZ); + SDMMCHOST_ENABLE_DDR_MODE(card->host.base, true, 0U); + break; + } + SDMMC_LOG("\r\nNote: DDR50 mode is not supported by card"); + + case kSD_TimingSDR50Mode: + error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionSDR50); + if (error == kStatus_Success) + { + card->currentTiming = kSD_TimingSDR50Mode; + card->busClock_Hz = + SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, SD_CLOCK_100MHZ); + break; + } + SDMMC_LOG("\r\nNote: SDR50 mode is not supported by card"); + + case kSD_TimingSDR25HighSpeedMode: + error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionSDR25HighSpeed); + if (error == kStatus_Success) + { + card->currentTiming = kSD_TimingSDR25HighSpeedMode; + card->busClock_Hz = + SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, SD_CLOCK_50MHZ); + } + break; + + default: + SDMMC_LOG("\r\nWarning: unknown timing mode"); + break; + } + } + else + { + } + + if (error == kStatus_Success) + { + /* SDR50 and SDR104 mode need tuning */ + if ((card->currentTiming == kSD_TimingSDR50Mode) || (card->currentTiming == kSD_TimingSDR104Mode)) + { + /* config IO strength in IOMUX*/ + if (card->currentTiming == kSD_TimingSDR50Mode) + { + SDMMCHOST_CONFIG_SD_IO(CARD_BUS_FREQ_100MHZ1, CARD_BUS_STRENGTH_7); + } + else + { + SDMMCHOST_CONFIG_SD_IO(CARD_BUS_FREQ_200MHZ, CARD_BUS_STRENGTH_7); + } + /* execute tuning */ + if (SD_ExecuteTuning(card) != kStatus_Success) + { + SDMMC_LOG("\r\nError: tuning failed for mode %d", card->currentTiming); + return kStatus_SDMMC_TuningFail; + } + } + else + { + /* set default IO strength to 4 to cover card adapter driver strength difference */ + SDMMCHOST_CONFIG_SD_IO(CARD_BUS_FREQ_100MHZ1, CARD_BUS_STRENGTH_4); + } + } + + return error; +} + +static void SD_DecodeStatus(sd_card_t *card, uint32_t *src) +{ + assert(card); + assert(src); + + card->stat.busWidth = (uint8_t)((src[0U] & 0xC0000000U) >> 30U); /* 511-510 */ + card->stat.secureMode = (uint8_t)((src[0U] & 0x20000000U) >> 29U); /* 509 */ + card->stat.cardType = (uint16_t)((src[0U] & 0x0000FFFFU)); /* 495-480 */ + card->stat.protectedSize = src[1U]; /* 479-448 */ + card->stat.speedClass = (uint8_t)((src[2U] & 0xFF000000U) >> 24U); /* 447-440 */ + card->stat.performanceMove = (uint8_t)((src[2U] & 0x00FF0000U) >> 16U); /* 439-432 */ + card->stat.auSize = (uint8_t)((src[2U] & 0x0000F000U) >> 12U); /* 431-428 */ + card->stat.eraseSize = (uint16_t)(((src[2U] & 0x000000FFU) << 8U) | ((src[3U] & 0xFF000000U) >> 24U)); /* 423-408 */ + card->stat.eraseTimeout = (((uint8_t)((src[3U] & 0x00FF0000U) >> 16U)) & 0xFCU) >> 2U; /* 407-402 */ + card->stat.eraseOffset = ((uint8_t)((src[3U] & 0x00FF0000U) >> 16U)) & 0x3U; /* 401-400 */ + card->stat.uhsSpeedGrade = (((uint8_t)((src[3U] & 0x0000FF00U) >> 8U)) & 0xF0U) >> 4U; /* 399-396 */ + card->stat.uhsAuSize = ((uint8_t)((src[3U] & 0x0000FF00U) >> 8U)) & 0xFU; /* 395-392 */ +} + +status_t SD_ReadStatus(sd_card_t *card) +{ + assert(card); + + uint32_t i = 0U; + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + SDMMCHOST_DATA data = {0}; + status_t error = kStatus_Success; + + memset(g_sdmmc, 0U, sizeof(g_sdmmc)); + + /* wait card status ready. */ + if (kStatus_Success != SD_WaitWriteComplete(card)) + { + return kStatus_SDMMC_WaitWriteCompleteFailed; + } + + if (kStatus_Success != SD_SendApplicationCmd(card, card->relativeAddress)) + { + return kStatus_SDMMC_SendApplicationCommandFailed; + } + + command.index = kSDMMC_SendStatus; + command.responseType = kCARD_ResponseTypeR1; + + data.blockSize = 64U; + data.blockCount = 1U; + data.rxData = &g_sdmmc[0]; + + content.command = &command; + content.data = &data; + error = card->host.transfer(card->host.base, &content); + if ((kStatus_Success != error) || ((command.response[0U]) & SDMMC_R1_ALL_ERROR_FLAG)) + { + SDMMC_LOG("\r\nError: send ACMD13 failed with host error %d, response %x", error, command.response[0U]); + + return kStatus_SDMMC_TransferFailed; + } + + switch (card->host.config.endianMode) + { + case kSDMMCHOST_EndianModeLittle: + /* In little endian mode, SD bus byte transferred first is the byte stored in lowest byte position in + a word which will cause 4 byte's sequence in a word is not consistent with their original sequence from + card. So the sequence of 4 bytes received in a word should be converted. */ + for (i = 0U; i < 16; i++) + { + g_sdmmc[i] = SWAP_WORD_BYTE_SEQUENCE(g_sdmmc[i]); + } + break; + case kSDMMCHOST_EndianModeBig: + break; /* Doesn't need to switch byte sequence when decodes bytes as big endian sequence. */ + case kSDMMCHOST_EndianModeHalfWordBig: + for (i = 0U; i < 16; i++) + { + g_sdmmc[i] = SWAP_HALF_WROD_BYTE_SEQUENCE(g_sdmmc[i]); + } + break; + default: + return kStatus_SDMMC_NotSupportYet; + } + + SD_DecodeStatus(card, g_sdmmc); + + return kStatus_Success; +} + +status_t SD_SelectCard(sd_card_t *card, bool isSelected) +{ + assert(card); + + return SDMMC_SelectCard(card->host.base, card->host.transfer, card->relativeAddress, isSelected); +} + +status_t SD_SetDriverStrength(sd_card_t *card, sd_driver_strength_t driverStrength) +{ + assert(card); + + status_t error; + uint32_t strength = driverStrength; + + error = SD_SelectFunction(card, kSD_GroupDriverStrength, strength); + + return error; +} + +status_t SD_SetMaxCurrent(sd_card_t *card, sd_max_current_t maxCurrent) +{ + assert(card); + + status_t error; + uint32_t current = maxCurrent; + + error = SD_SelectFunction(card, kSD_GroupCurrentLimit, current); + + return error; +} + +static status_t SD_Read(sd_card_t *card, uint8_t *buffer, uint32_t startBlock, uint32_t blockSize, uint32_t blockCount) +{ + assert(card); + assert(buffer); + assert(blockCount); + assert(blockSize == FSL_SDMMC_DEFAULT_BLOCK_SIZE); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + SDMMCHOST_DATA data = {0}; + + if (((card->flags & kSD_SupportHighCapacityFlag) && (blockSize != 512U)) || (blockSize > card->blockSize) || + (blockSize > card->host.capability.maxBlockLength) || (blockSize % 4)) + { + SDMMC_LOG("\r\nError: read with parameter, block size %d is not support", blockSize); + return kStatus_SDMMC_CardNotSupport; + } + + /* Wait for the card write process complete because of that card read process and write process use one buffer. */ + if (kStatus_Success != SD_WaitWriteComplete(card)) + { + return kStatus_SDMMC_WaitWriteCompleteFailed; + } + + data.blockSize = blockSize; + data.blockCount = blockCount; + data.rxData = (uint32_t *)buffer; + data.enableAutoCommand12 = true; + + command.index = (blockCount == 1U) ? kSDMMC_ReadSingleBlock : kSDMMC_ReadMultipleBlock; + command.argument = startBlock; + if (!(card->flags & kSD_SupportHighCapacityFlag)) + { + command.argument *= data.blockSize; + } + command.responseType = kCARD_ResponseTypeR1; + command.responseErrorFlags = SDMMC_R1_ALL_ERROR_FLAG; + + content.command = &command; + content.data = &data; + + return SD_Transfer(card, &content, 1U); +} + +static status_t SD_Write(sd_card_t *card, + const uint8_t *buffer, + uint32_t startBlock, + uint32_t blockSize, + uint32_t blockCount, + uint32_t *writtenBlocks) +{ + assert(card); + assert(buffer); + assert(blockCount); + assert(blockSize == FSL_SDMMC_DEFAULT_BLOCK_SIZE); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + SDMMCHOST_DATA data = {0}; + status_t error; + + if (((card->flags & kSD_SupportHighCapacityFlag) && (blockSize != 512U)) || (blockSize > card->blockSize) || + (blockSize > card->host.capability.maxBlockLength) || (blockSize % 4U)) + { + SDMMC_LOG("\r\nError: write with parameter, block size %d is not support", blockSize); + return kStatus_SDMMC_CardNotSupport; + } + + /* Wait for the card write process complete because of that card read process and write process use one buffer.*/ + if (kStatus_Success != SD_WaitWriteComplete(card)) + { + return kStatus_SDMMC_WaitWriteCompleteFailed; + } + + /* Wait for the card's buffer to be not full to write to improve the write performance. */ + while ((GET_SDMMCHOST_STATUS(card->host.base) & CARD_DATA0_STATUS_MASK) != CARD_DATA0_NOT_BUSY) + { + } + + data.enableAutoCommand12 = true; + data.blockSize = blockSize; + command.responseType = kCARD_ResponseTypeR1; + command.responseErrorFlags = SDMMC_R1_ALL_ERROR_FLAG; + + command.index = (blockCount == 1U) ? kSDMMC_WriteSingleBlock : kSDMMC_WriteMultipleBlock; + command.argument = startBlock; + if (!(card->flags & kSD_SupportHighCapacityFlag)) + { + command.argument *= data.blockSize; + } + + *writtenBlocks = blockCount; + data.blockCount = blockCount; + data.txData = (const uint32_t *)(buffer); + + content.command = &command; + content.data = &data; + + error = SD_Transfer(card, &content, 0U); + if (error != kStatus_Success) + { + /* check the successfully written block */ + if ((SD_SendWriteSuccessBlocks(card, writtenBlocks) == kStatus_Success)) + { + if (*writtenBlocks) + { + /* written success, but not all the blocks are written */ + error = kStatus_Success; + } + } + SDMMC_LOG("\r\nWarning: write failed with block count %d, successed %d", blockCount, *writtenBlocks); + } + + return error; +} + +static status_t SD_Erase(sd_card_t *card, uint32_t startBlock, uint32_t blockCount) +{ + assert(card); + assert(blockCount); + + uint32_t eraseBlockStart; + uint32_t eraseBlockEnd; + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + /* Wait for the card write process complete because of that card read process and write process use one buffer.*/ + if (kStatus_Success != SD_WaitWriteComplete(card)) + { + return kStatus_SDMMC_WaitWriteCompleteFailed; + } + /* Wait for the card's buffer to be not full to write to improve the write performance. */ + while ((GET_SDMMCHOST_STATUS(card->host.base) & CARD_DATA0_STATUS_MASK) != CARD_DATA0_NOT_BUSY) + { + } + + eraseBlockStart = startBlock; + eraseBlockEnd = eraseBlockStart + blockCount - 1U; + if (!(card->flags & kSD_SupportHighCapacityFlag)) + { + eraseBlockStart = eraseBlockStart * FSL_SDMMC_DEFAULT_BLOCK_SIZE; + eraseBlockEnd = eraseBlockEnd * FSL_SDMMC_DEFAULT_BLOCK_SIZE; + } + + /* Send ERASE_WRITE_BLOCK_START command to set the start block number to erase. */ + command.index = kSD_EraseWriteBlockStart; + command.argument = eraseBlockStart; + command.responseType = kCARD_ResponseTypeR1; + command.responseErrorFlags = SDMMC_R1_ALL_ERROR_FLAG; + + content.command = &command; + content.data = NULL; + error = SD_Transfer(card, &content, 1U); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send CMD32(erase start) failed with host error %d, response %x", error, + command.response[0U]); + return kStatus_SDMMC_TransferFailed; + } + + /* Send ERASE_WRITE_BLOCK_END command to set the end block number to erase. */ + command.index = kSD_EraseWriteBlockEnd; + command.argument = eraseBlockEnd; + + content.command = &command; + content.data = NULL; + error = SD_Transfer(card, &content, 0U); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send CMD33(erase end) failed with host error %d, response %x", error, + command.response[0U]); + return kStatus_SDMMC_TransferFailed; + } + + /* Send ERASE command to start erase process. */ + command.index = kSDMMC_Erase; + command.argument = 0U; + command.responseType = kCARD_ResponseTypeR1b; + command.responseErrorFlags = SDMMC_R1_ALL_ERROR_FLAG; + + content.command = &command; + content.data = NULL; + error = SD_Transfer(card, &content, 0U); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send CMD38(erase) failed with host error %d, response %x", error, command.response[0U]); + return kStatus_SDMMC_TransferFailed; + } + + return kStatus_Success; +} + +bool SD_CheckReadOnly(sd_card_t *card) +{ + assert(card); + + return ((card->csd.flags & kSD_CsdPermanentWriteProtectFlag) || + (card->csd.flags & kSD_CsdTemporaryWriteProtectFlag)); +} + +status_t SD_ReadBlocks(sd_card_t *card, uint8_t *buffer, uint32_t startBlock, uint32_t blockCount) +{ + assert(card); + assert(buffer); + assert(blockCount); + assert((blockCount + startBlock) <= card->blockCount); + + uint32_t blockCountOneTime; + uint32_t blockLeft; + uint32_t blockDone = 0U; + uint8_t *nextBuffer = buffer; + bool dataAddrAlign = true; + + blockLeft = blockCount; + + while (blockLeft) + { + nextBuffer = (buffer + blockDone * FSL_SDMMC_DEFAULT_BLOCK_SIZE); + if (!card->noInteralAlign && (!dataAddrAlign || (((uint32_t)nextBuffer) & (sizeof(uint32_t) - 1U)))) + { + blockLeft--; + blockCountOneTime = 1U; + memset(g_sdmmc, 0U, FSL_SDMMC_DEFAULT_BLOCK_SIZE); + dataAddrAlign = false; + } + else + { + if (blockLeft > card->host.capability.maxBlockCount) + { + blockLeft = (blockLeft - card->host.capability.maxBlockCount); + blockCountOneTime = card->host.capability.maxBlockCount; + } + else + { + blockCountOneTime = blockLeft; + blockLeft = 0U; + } + } + + if (kStatus_Success != SD_Read(card, dataAddrAlign ? nextBuffer : (uint8_t *)g_sdmmc, (startBlock + blockDone), + FSL_SDMMC_DEFAULT_BLOCK_SIZE, blockCountOneTime)) + { + return kStatus_SDMMC_TransferFailed; + } + + blockDone += blockCountOneTime; + + if (!card->noInteralAlign && (!dataAddrAlign)) + { + memcpy(nextBuffer, (uint8_t *)&g_sdmmc, FSL_SDMMC_DEFAULT_BLOCK_SIZE); + } + } + + return kStatus_Success; +} + +status_t SD_WriteBlocks(sd_card_t *card, const uint8_t *buffer, uint32_t startBlock, uint32_t blockCount) +{ + assert(card); + assert(buffer); + assert(blockCount); + assert((blockCount + startBlock) <= card->blockCount); + + uint32_t blockCountOneTime = 0U; /* The block count can be wrote in one time sending WRITE_BLOCKS command. */ + uint32_t blockWrittenOneTime = 0U; + uint32_t blockLeft = 0U; /* Left block count to be wrote. */ + const uint8_t *nextBuffer; + bool dataAddrAlign = true; + + blockLeft = blockCount; + while (blockLeft) + { + nextBuffer = (buffer + (blockCount - blockLeft) * FSL_SDMMC_DEFAULT_BLOCK_SIZE); + if (!card->noInteralAlign && (!dataAddrAlign || (((uint32_t)nextBuffer) & (sizeof(uint32_t) - 1U)))) + { + blockCountOneTime = 1U; + memcpy((uint8_t *)&g_sdmmc, nextBuffer, FSL_SDMMC_DEFAULT_BLOCK_SIZE); + dataAddrAlign = false; + } + else + { + if (blockLeft > card->host.capability.maxBlockCount) + { + blockCountOneTime = card->host.capability.maxBlockCount; + } + else + { + blockCountOneTime = blockLeft; + } + } + + if (kStatus_Success != SD_Write(card, dataAddrAlign ? nextBuffer : (uint8_t *)g_sdmmc, + (startBlock + blockCount - blockLeft), FSL_SDMMC_DEFAULT_BLOCK_SIZE, + blockCountOneTime, &blockWrittenOneTime)) + { + return kStatus_SDMMC_TransferFailed; + } + + blockLeft -= blockWrittenOneTime; + + if ((!card->noInteralAlign) && !dataAddrAlign) + { + memset(g_sdmmc, 0U, FSL_SDMMC_DEFAULT_BLOCK_SIZE); + } + } + + return kStatus_Success; +} + +status_t SD_EraseBlocks(sd_card_t *card, uint32_t startBlock, uint32_t blockCount) +{ + assert(card); + assert(blockCount); + assert((blockCount + startBlock) <= card->blockCount); + + uint32_t blockCountOneTime; /* The block count can be erased in one time sending ERASE_BLOCKS command. */ + uint32_t blockDone = 0U; /* The block count has been erased. */ + uint32_t blockLeft; /* Left block count to be erase. */ + status_t error; + uint32_t onetimeMaxEraseBlocks = 0U; + + /* sdsc card erasable sector is determined by CSD register */ + if (card->csd.csdStructure == 0U) + { + onetimeMaxEraseBlocks = card->csd.eraseSectorSize + 1U; + } + else + { + /* limit one time maximum erase size to 1 AU */ + if (card->stat.auSize >= SD_AU_START_VALUE) + { + onetimeMaxEraseBlocks = s_sdAuSizeMap[card->stat.auSize] / FSL_SDMMC_DEFAULT_BLOCK_SIZE; + } + } + + if (onetimeMaxEraseBlocks == 0U) + { + SDMMC_LOG( + "Warning: AU size in sd descriptor is not set properly, please check if SD_ReadStatus is called before\ + SD_EraseBlocks"); + return kStatus_SDMMC_AuSizeNotSetProperly; + } + + blockLeft = blockCount; + while (blockLeft) + { + if (blockLeft > onetimeMaxEraseBlocks) + { + blockCountOneTime = onetimeMaxEraseBlocks; + blockLeft = blockLeft - blockCountOneTime; + } + else + { + blockCountOneTime = blockLeft; + blockLeft = 0U; + } + + error = SD_Erase(card, (startBlock + blockDone), blockCountOneTime); + if (error != kStatus_Success) + { + return error; + } + + blockDone += blockCountOneTime; + } + + return kStatus_Success; +} + +status_t SD_ProbeBusVoltage(sd_card_t *card) +{ + assert(card); + + uint32_t applicationCommand41Argument = 0U; + status_t error = kStatus_Success; + + /* 3.3V voltage should be supported as default */ + applicationCommand41Argument |= + SDMMC_MASK(kSD_OcrVdd29_30Flag) | SDMMC_MASK(kSD_OcrVdd32_33Flag) | SDMMC_MASK(kSD_OcrVdd33_34Flag); + card->operationVoltage = kCARD_OperationVoltage330V; + + /* allow user select the work voltage, if not select, sdmmc will handle it automatically */ + if (kSDMMCHOST_SupportV180 != SDMMCHOST_NOT_SUPPORT) + { + applicationCommand41Argument |= SDMMC_MASK(kSD_OcrSwitch18RequestFlag); + } + + do + { + /* card go idle */ + if (kStatus_Success != SD_GoIdle(card)) + { + error = kStatus_SDMMC_GoIdleFailed; + break; + } + + /* Check card's supported interface condition. */ + if (kStatus_Success == SD_SendInterfaceCondition(card)) + { + /* SDHC or SDXC card */ + applicationCommand41Argument |= SDMMC_MASK(kSD_OcrHostCapacitySupportFlag); + card->flags |= kSD_SupportSdhcFlag; + } + else + { + /* SDSC card */ + if (kStatus_Success != SD_GoIdle(card)) + { + error = kStatus_SDMMC_GoIdleFailed; + break; + } + } + /* Set card interface condition according to SDHC capability and card's supported interface condition. */ + if (kStatus_Success != SD_ApplicationSendOperationCondition(card, applicationCommand41Argument)) + { + error = kStatus_SDMMC_HandShakeOperationConditionFailed; + break; + } + + /* check if card support 1.8V */ + if ((card->flags & kSD_SupportVoltage180v)) + { + error = SD_SwitchVoltage(card); + if (kStatus_SDMMC_SwitchVoltageFail == error) + { + break; + } + + if (error == kStatus_SDMMC_SwitchVoltage18VFail33VSuccess) + { + applicationCommand41Argument &= ~SDMMC_MASK(kSD_OcrSwitch18RequestFlag); + card->flags &= ~kSD_SupportVoltage180v; + continue; + } + else + { + card->operationVoltage = kCARD_OperationVoltage180V; + break; + } + } + + break; + } while (1U); + + return error; +} + +status_t SD_CardInit(sd_card_t *card) +{ + assert(card); + assert(card->isHostReady == true); + + /* reset variables */ + card->flags = 0U; + /* set DATA bus width */ + SDMMCHOST_SET_CARD_BUS_WIDTH(card->host.base, kSDMMCHOST_DATABUSWIDTH1BIT); + /*set card freq to 400KHZ*/ + card->busClock_Hz = SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, SDMMC_CLOCK_400KHZ); + /* send card active */ + SDMMCHOST_SEND_CARD_ACTIVE(card->host.base, 100U); + /* Get host capability. */ + GET_SDMMCHOST_CAPABILITY(card->host.base, &(card->host.capability)); + + /* probe bus voltage*/ + if (SD_ProbeBusVoltage(card) == kStatus_SDMMC_SwitchVoltageFail) + { + return kStatus_SDMMC_SwitchVoltageFail; + } + + /* Initialize card if the card is SD card. */ + if (kStatus_Success != SD_AllSendCid(card)) + { + return kStatus_SDMMC_AllSendCidFailed; + } + if (kStatus_Success != SD_SendRca(card)) + { + return kStatus_SDMMC_SendRelativeAddressFailed; + } + if (kStatus_Success != SD_SendCsd(card)) + { + return kStatus_SDMMC_SendCsdFailed; + } + if (kStatus_Success != SD_SelectCard(card, true)) + { + return kStatus_SDMMC_SelectCardFailed; + } + + /* Set to max frequency in non-high speed mode. */ + card->busClock_Hz = SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, SD_CLOCK_25MHZ); + + if (kStatus_Success != SD_SendScr(card)) + { + return kStatus_SDMMC_SendScrFailed; + } + /* Set to 4-bit data bus mode. */ + if (((card->host.capability.flags) & kSDMMCHOST_Support4BitBusWidth) && (card->flags & kSD_Support4BitWidthFlag)) + { + if (kStatus_Success != SD_SetDataBusWidth(card, kSD_DataBusWidth4Bit)) + { + return kStatus_SDMMC_SetDataBusWidthFailed; + } + SDMMCHOST_SET_CARD_BUS_WIDTH(card->host.base, kSDMMCHOST_DATABUSWIDTH4BIT); + } + + /* set block size */ + if (SD_SetBlockSize(card, FSL_SDMMC_DEFAULT_BLOCK_SIZE)) + { + return kStatus_SDMMC_SetCardBlockSizeFailed; + } + + /* select bus timing */ + if (kStatus_Success != SD_SelectBusTiming(card)) + { + return kStatus_SDMMC_SwitchBusTimingFailed; + } + + /* try to get card current status */ + SD_ReadStatus(card); + + return kStatus_Success; +} + +void SD_CardDeinit(sd_card_t *card) +{ + assert(card); + + SD_SelectCard(card, false); +} + +status_t SD_HostInit(sd_card_t *card) +{ + assert(card); + + if ((!card->isHostReady) && SDMMCHOST_Init(&(card->host), (void *)(card->usrParam.cd)) != kStatus_Success) + { + return kStatus_Fail; + } + + /* set the host status flag, after the card re-plug in, don't need init host again */ + card->isHostReady = true; + + return kStatus_Success; +} + +void SD_HostDeinit(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_Deinit(&(card->host)); + /* should re-init host */ + card->isHostReady = false; +} + +void SD_HostReset(SDMMCHOST_CONFIG *host) +{ + SDMMCHOST_Reset(host->base); +} + +void SD_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr) +{ + SDMMCHOST_PowerOnCard(base, pwr); +} + +void SD_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr) +{ + SDMMCHOST_PowerOffCard(base, pwr); +} + +status_t SD_WaitCardDetectStatus(SDMMCHOST_TYPE *hostBase, const sdmmchost_detect_card_t *cd, bool waitCardStatus) +{ + return SDMMCHOST_WaitCardDetectStatus(hostBase, cd, waitCardStatus); +} + +bool SD_IsCardPresent(sd_card_t *card) +{ + return SDMMCHOST_IsCardPresent(); +} + +status_t SD_Init(sd_card_t *card) +{ + assert(card); + + if (!card->isHostReady) + { + if (SD_HostInit(card) != kStatus_Success) + { + return kStatus_SDMMC_HostNotReady; + } + } + else + { + SD_HostReset(&(card->host)); + } + SD_PowerOffCard(card->host.base, card->usrParam.pwr); + + if (SD_WaitCardDetectStatus(card->host.base, card->usrParam.cd, true) != kStatus_Success) + { + return kStatus_SDMMC_CardDetectFailed; + } + SD_PowerOnCard(card->host.base, card->usrParam.pwr); + + return SD_CardInit(card); +} + +void SD_Deinit(sd_card_t *card) +{ + /* card deinitialize */ + SD_CardDeinit(card); + /* host deinitialize */ + SD_HostDeinit(card); +} diff --git a/target/fsl_sd.h b/target/fsl_sd.h new file mode 100644 index 0000000..128f935 --- /dev/null +++ b/target/fsl_sd.h @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_SD_H_ +#define _FSL_SD_H_ + +#include "fsl_sdmmc_common.h" +/*! + * @addtogroup SDCARD + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/*! @brief SD card flags */ +enum _sd_card_flag +{ + kSD_SupportHighCapacityFlag = (1U << 1U), /*!< Support high capacity */ + kSD_Support4BitWidthFlag = (1U << 2U), /*!< Support 4-bit data width */ + kSD_SupportSdhcFlag = (1U << 3U), /*!< Card is SDHC */ + kSD_SupportSdxcFlag = (1U << 4U), /*!< Card is SDXC */ + kSD_SupportVoltage180v = (1U << 5U), /*!< card support 1.8v voltage*/ + kSD_SupportSetBlockCountCmd = (1U << 6U), /*!< card support cmd23 flag*/ + kSD_SupportSpeedClassControlCmd = (1U << 7U), /*!< card support speed class control flag */ +}; + +/*! @brief card user parameter, user can define the parameter according the board, card capability */ +typedef struct _sdcard_usr_param +{ + const sdmmchost_detect_card_t *cd; /*!< card detect type */ + const sdmmchost_pwr_card_t *pwr; /*!< power control configuration */ +} sdcard_usr_param_t; + +/*! + * @brief SD card state + * + * Define the card structure including the necessary fields to identify and describe the card. + */ +typedef struct _sd_card +{ + SDMMCHOST_CONFIG host; /*!< Host information */ + + sdcard_usr_param_t usrParam; /*!< user parameter */ + bool isHostReady; /*!< use this flag to indicate if need host re-init or not*/ + bool noInteralAlign; /*!< use this flag to disable sdmmc align. If disable, sdmmc will not make sure the + data buffer address is word align, otherwise all the transfer are align to low level driver */ + uint32_t busClock_Hz; /*!< SD bus clock frequency united in Hz */ + uint32_t relativeAddress; /*!< Relative address of the card */ + uint32_t version; /*!< Card version */ + uint32_t flags; /*!< Flags in _sd_card_flag */ + uint32_t rawCid[4U]; /*!< Raw CID content */ + uint32_t rawCsd[4U]; /*!< Raw CSD content */ + uint32_t rawScr[2U]; /*!< Raw CSD content */ + uint32_t ocr; /*!< Raw OCR content */ + sd_cid_t cid; /*!< CID */ + sd_csd_t csd; /*!< CSD */ + sd_scr_t scr; /*!< SCR */ + sd_status_t stat; /*!< sd 512 bit status */ + uint32_t blockCount; /*!< Card total block number */ + uint32_t blockSize; /*!< Card block size */ + sd_timing_mode_t currentTiming; /*!< current timing mode */ + sd_driver_strength_t driverStrength; /*!< driver strength */ + sd_max_current_t maxCurrent; /*!< card current limit */ + sdmmc_operation_voltage_t operationVoltage; /*!< card operation voltage */ +} sd_card_t; + +/************************************************************************************************* + * API + ************************************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name SDCARD Function + * @{ + */ + +/*! + * @brief Initializes the card on a specific host controller. + * @deprecated Do not use this function. It has been superceded by @ref SD_HostInit,SD_CardInit. + + * This function initializes the card on a specific host controller, it is consist of + * host init, card detect, card init function, however user can ignore this high level function, + * instead of use the low level function, such as SD_CardInit, SD_HostInit, SD_CardDetect. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_HostNotReady host is not ready. + * @retval kStatus_SDMMC_GoIdleFailed Go idle failed. + * @retval kStatus_SDMMC_NotSupportYet Card not support. + * @retval kStatus_SDMMC_SendOperationConditionFailed Send operation condition failed. + * @retval kStatus_SDMMC_AllSendCidFailed Send CID failed. + * @retval kStatus_SDMMC_SendRelativeAddressFailed Send relative address failed. + * @retval kStatus_SDMMC_SendCsdFailed Send CSD failed. + * @retval kStatus_SDMMC_SelectCardFailed Send SELECT_CARD command failed. + * @retval kStatus_SDMMC_SendScrFailed Send SCR failed. + * @retval kStatus_SDMMC_SetBusWidthFailed Set bus width failed. + * @retval kStatus_SDMMC_SwitchHighSpeedFailed Switch high speed failed. + * @retval kStatus_SDMMC_SetCardBlockSizeFailed Set card block size failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_Init(sd_card_t *card); + +/*! + * @brief Deinitializes the card. + * @deprecated Do not use this function. It has been superceded by @ref SD_HostDeinit,SD_CardDeinit. + * This function deinitializes the specific card and host. + * + * @param card Card descriptor. + */ +void SD_Deinit(sd_card_t *card); + +/*! + * @brief Initializes the card. + * + * This function initializes the card only, make sure the host is ready when call this function, + * otherwise it will return kStatus_SDMMC_HostNotReady. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_HostNotReady host is not ready. + * @retval kStatus_SDMMC_GoIdleFailed Go idle failed. + * @retval kStatus_SDMMC_NotSupportYet Card not support. + * @retval kStatus_SDMMC_SendOperationConditionFailed Send operation condition failed. + * @retval kStatus_SDMMC_AllSendCidFailed Send CID failed. + * @retval kStatus_SDMMC_SendRelativeAddressFailed Send relative address failed. + * @retval kStatus_SDMMC_SendCsdFailed Send CSD failed. + * @retval kStatus_SDMMC_SelectCardFailed Send SELECT_CARD command failed. + * @retval kStatus_SDMMC_SendScrFailed Send SCR failed. + * @retval kStatus_SDMMC_SetBusWidthFailed Set bus width failed. + * @retval kStatus_SDMMC_SwitchHighSpeedFailed Switch high speed failed. + * @retval kStatus_SDMMC_SetCardBlockSizeFailed Set card block size failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_CardInit(sd_card_t *card); + +/*! + * @brief Deinitializes the card. + * + * This function deinitializes the specific card. + * + * @param card Card descriptor. + */ +void SD_CardDeinit(sd_card_t *card); + +/*! + * @brief initialize the host. + * + * This function deinitializes the specific host. + * + * @param card Card descriptor. + */ +status_t SD_HostInit(sd_card_t *card); + +/*! + * @brief Deinitializes the host. + * + * This function deinitializes the host. + * + * @param card Card descriptor. + */ +void SD_HostDeinit(sd_card_t *card); + +/*! + * @brief reset the host. + * + * This function reset the specific host. + * + * @param host host descriptor. + */ +void SD_HostReset(SDMMCHOST_CONFIG *host); + +/*! + * @brief power on card. + * + * The power on operation depend on host or the user define power on function. + * @param base host base address. + * @param pwr user define power control configuration + */ +void SD_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr); + +/*! + * @brief power off card. + * + * The power off operation depend on host or the user define power on function. + * @param base host base address. + * @param pwr user define power control configuration + */ +void SD_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr); + +/*! + * @brief sd wait card detect function. + * + * Detect card through GPIO, CD, DATA3. + * + * @param card card descriptor. + * @param card detect configuration + * @param waitCardStatus wait card detect status + */ +status_t SD_WaitCardDetectStatus(SDMMCHOST_TYPE *hostBase, const sdmmchost_detect_card_t *cd, bool waitCardStatus); + +/*! + * @brief sd card present check function. + * + * @param card card descriptor. + */ +bool SD_IsCardPresent(sd_card_t *card); + +/*! + * @brief Checks whether the card is write-protected. + * + * This function checks if the card is write-protected via the CSD register. + * + * @param card The specific card. + * @retval true Card is read only. + * @retval false Card isn't read only. + */ +bool SD_CheckReadOnly(sd_card_t *card); + +/*! + * @brief Send SELECT_CARD command to set the card to be transfer state or not. + * + * @param card Card descriptor. + * @param isSelected True to set the card into transfer state, false to disselect. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_SelectCard(sd_card_t *card, bool isSelected); + +/*! + * @brief Send ACMD13 to get the card current status. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_SendApplicationCommandFailed send application command failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_ReadStatus(sd_card_t *card); + +/*! + * @brief Reads blocks from the specific card. + * + * This function reads blocks from the specific card with default block size defined by the + * SDHC_CARD_DEFAULT_BLOCK_SIZE. + * + * @param card Card descriptor. + * @param buffer The buffer to save the data read from card. + * @param startBlock The start block index. + * @param blockCount The number of blocks to read. + * @retval kStatus_InvalidArgument Invalid argument. + * @retval kStatus_SDMMC_CardNotSupport Card not support. + * @retval kStatus_SDMMC_NotSupportYet Not support now. + * @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_StopTransmissionFailed Stop transmission failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_ReadBlocks(sd_card_t *card, uint8_t *buffer, uint32_t startBlock, uint32_t blockCount); + +/*! + * @brief Writes blocks of data to the specific card. + * + * This function writes blocks to the specific card with default block size 512 bytes. + * + * @param card Card descriptor. + * @param buffer The buffer holding the data to be written to the card. + * @param startBlock The start block index. + * @param blockCount The number of blocks to write. + * @retval kStatus_InvalidArgument Invalid argument. + * @retval kStatus_SDMMC_NotSupportYet Not support now. + * @retval kStatus_SDMMC_CardNotSupport Card not support. + * @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_StopTransmissionFailed Stop transmission failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_WriteBlocks(sd_card_t *card, const uint8_t *buffer, uint32_t startBlock, uint32_t blockCount); + +/*! + * @brief Erases blocks of the specific card. + * + * This function erases blocks of the specific card with default block size 512 bytes. + * + * @param card Card descriptor. + * @param startBlock The start block index. + * @param blockCount The number of blocks to erase. + * @retval kStatus_InvalidArgument Invalid argument. + * @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_EraseBlocks(sd_card_t *card, uint32_t startBlock, uint32_t blockCount); + +/*! + * @brief select card driver strength + * select card driver strength + * @param card Card descriptor. + * @param driverStrength Driver strength + */ +status_t SD_SetDriverStrength(sd_card_t *card, sd_driver_strength_t driverStrength); + +/*! + * @brief select max current + * select max operation current + * @param card Card descriptor. + * @param maxCurrent Max current + */ +status_t SD_SetMaxCurrent(sd_card_t *card, sd_max_current_t maxCurrent); + +/* @} */ + +#if defined(__cplusplus) +} +#endif +/*! @} */ +#endif /* _FSL_SD_H_*/ diff --git a/target/fsl_sdmmc_common.c b/target/fsl_sdmmc_common.c new file mode 100644 index 0000000..030f5e6 --- /dev/null +++ b/target/fsl_sdmmc_common.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_sdmmc_common.h" +/******************************************************************************* + * Variables + ******************************************************************************/ +SDK_ALIGN(uint32_t g_sdmmc[SDK_SIZEALIGN(SDMMC_GLOBAL_BUFFER_SIZE, SDMMC_DATA_BUFFER_ALIGN_CACHE)], + MAX(SDMMC_DATA_BUFFER_ALIGN_CACHE, SDMMCHOST_DMA_BUFFER_ADDR_ALIGN)); +/******************************************************************************* + * Code + ******************************************************************************/ +status_t SDMMC_SelectCard(SDMMCHOST_TYPE *base, + SDMMCHOST_TRANSFER_FUNCTION transfer, + uint32_t relativeAddress, + bool isSelected) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_SelectCard; + if (isSelected) + { + command.argument = relativeAddress << 16U; + command.responseType = kCARD_ResponseTypeR1; + } + else + { + command.argument = 0U; + command.responseType = kCARD_ResponseTypeNone; + } + + content.command = &command; + content.data = NULL; + if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & SDMMC_R1_ALL_ERROR_FLAG)) + { + return kStatus_SDMMC_TransferFailed; + } + + /* Wait until card to transfer state */ + return kStatus_Success; +} + +status_t SDMMC_SendApplicationCommand(SDMMCHOST_TYPE *base, + SDMMCHOST_TRANSFER_FUNCTION transfer, + uint32_t relativeAddress) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_ApplicationCommand; + command.argument = (relativeAddress << 16U); + command.responseType = kCARD_ResponseTypeR1; + + content.command = &command; + content.data = 0U; + if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & SDMMC_R1_ALL_ERROR_FLAG)) + { + return kStatus_SDMMC_TransferFailed; + } + + if (!(command.response[0U] & SDMMC_MASK(kSDMMC_R1ApplicationCommandFlag))) + { + return kStatus_SDMMC_CardNotSupport; + } + + return kStatus_Success; +} + +status_t SDMMC_SetBlockCount(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer, uint32_t blockCount) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_SetBlockCount; + command.argument = blockCount; + command.responseType = kCARD_ResponseTypeR1; + + content.command = &command; + content.data = 0U; + if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & SDMMC_R1_ALL_ERROR_FLAG)) + { + return kStatus_SDMMC_TransferFailed; + } + + return kStatus_Success; +} + +status_t SDMMC_GoIdle(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_GoIdleState; + + content.command = &command; + content.data = 0U; + if (kStatus_Success != transfer(base, &content)) + { + return kStatus_SDMMC_TransferFailed; + } + + return kStatus_Success; +} + +status_t SDMMC_SetBlockSize(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer, uint32_t blockSize) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_SetBlockLength; + command.argument = blockSize; + command.responseType = kCARD_ResponseTypeR1; + + content.command = &command; + content.data = 0U; + if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & SDMMC_R1_ALL_ERROR_FLAG)) + { + return kStatus_SDMMC_TransferFailed; + } + + return kStatus_Success; +} + +status_t SDMMC_SetCardInactive(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_GoInactiveState; + command.argument = 0U; + command.responseType = kCARD_ResponseTypeNone; + + content.command = &command; + content.data = 0U; + if ((kStatus_Success != transfer(base, &content))) + { + return kStatus_SDMMC_TransferFailed; + } + + return kStatus_Success; +} + +status_t SDMMC_SwitchVoltage(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + command.index = kSD_VoltageSwitch; + command.argument = 0U; + command.responseType = kCARD_ResponseTypeR1; + + content.command = &command; + content.data = NULL; + if (kStatus_Success != transfer(base, &content)) + { + return kStatus_SDMMC_TransferFailed; + } + /* disable card clock */ + SDMMCHOST_ENABLE_CARD_CLOCK(base, false); + + /* check data line and cmd line status */ + if ((GET_SDMMCHOST_STATUS(base) & + (CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY)) != 0U) + { + return kStatus_SDMMC_SwitchVoltageFail; + } + + /* host switch to 1.8V */ + SDMMCHOST_SWITCH_VOLTAGE180V(base, true); + + SDMMCHOST_Delay(100U); + + /*enable sd clock*/ + SDMMCHOST_ENABLE_CARD_CLOCK(base, true); + /*enable force clock on*/ + SDMMCHOST_FORCE_SDCLOCK_ON(base, true); + /* dealy 1ms,not exactly correct when use while */ + SDMMCHOST_Delay(10U); + /*disable force clock on*/ + SDMMCHOST_FORCE_SDCLOCK_ON(base, false); + + /* check data line and cmd line status */ + if ((GET_SDMMCHOST_STATUS(base) & + (CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY)) == 0U) + { + error = kStatus_SDMMC_SwitchVoltageFail; + /* power reset the card */ + SDMMCHOST_ENABLE_SD_POWER(false); + SDMMCHOST_Delay(10U); + SDMMCHOST_ENABLE_SD_POWER(true); + SDMMCHOST_Delay(10U); + /* re-check the data line status */ + if ((GET_SDMMCHOST_STATUS(base) & + (CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY))) + { + error = kStatus_SDMMC_SwitchVoltage18VFail33VSuccess; + SDMMC_LOG("\r\nNote: Current card support 1.8V, but board don't support, so sdmmc switch back to 3.3V."); + } + else + { + SDMMC_LOG( + "\r\nError: Current card support 1.8V, but board don't support, sdmmc tried to switch back\ + to 3.3V, but failed, please check board setting."); + } + } + + return error; +} + +status_t SDMMC_ExecuteTuning(SDMMCHOST_TYPE *base, + SDMMCHOST_TRANSFER_FUNCTION transfer, + uint32_t tuningCmd, + uint32_t blockSize) +{ + SDMMCHOST_TRANSFER content = {0U}; + SDMMCHOST_COMMAND command = {0U}; + SDMMCHOST_DATA data = {0U}; + uint32_t buffer[32U] = {0U}; + bool tuningError = true; + + command.index = tuningCmd; + command.argument = 0U; + command.responseType = kCARD_ResponseTypeR1; + + data.blockSize = blockSize; + data.blockCount = 1U; + data.rxData = buffer; + /* add this macro for adpter to different driver */ + SDMMCHOST_ENABLE_TUNING_FLAG(data); + + content.command = &command; + content.data = &data; + + /* enable the standard tuning */ + SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, true); + + while (true) + { + /* send tuning block */ + if ((kStatus_Success != transfer(base, &content))) + { + return kStatus_SDMMC_TransferFailed; + } + SDMMCHOST_Delay(1U); + + /*wait excute tuning bit clear*/ + if ((SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) != 0U)) + { + continue; + } + + /* if tuning error , re-tuning again */ + if ((SDMMCHOST_CHECK_TUNING_ERROR(base) != 0U) && tuningError) + { + tuningError = false; + /* enable the standard tuning */ + SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, true); + SDMMCHOST_ADJUST_TUNING_DELAY(base, SDMMCHOST_STANDARD_TUNING_START); + } + else + { + break; + } + } + + /* check tuning result*/ + if (SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) == 0U) + { + return kStatus_SDMMC_TuningFail; + } + +#if !SDMMC_ENABLE_SOFTWARE_TUNING + SDMMCHOST_AUTO_TUNING_ENABLE(base, true); +#endif + + return kStatus_Success; +} diff --git a/target/fsl_sdmmc_common.h b/target/fsl_sdmmc_common.h new file mode 100644 index 0000000..78ec1d0 --- /dev/null +++ b/target/fsl_sdmmc_common.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_SDMMC_COMMON_H_ +#define _FSL_SDMMC_COMMON_H_ + +#include "fsl_common.h" +#include "fsl_sdmmc_host.h" +#include "fsl_sdmmc_spec.h" +#include "stdlib.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/*! @brief Middleware version. */ +#define FSL_SDMMC_DRIVER_VERSION (MAKE_VERSION(2U, 2U, 6U)) /*2.2.6*/ + +/*! @brief Reverse byte sequence in uint32_t */ +#define SWAP_WORD_BYTE_SEQUENCE(x) (__REV(x)) +/*! @brief Reverse byte sequence for each half word in uint32_t */ +#define SWAP_HALF_WROD_BYTE_SEQUENCE(x) (__REV16(x)) +/*! @brief Maximum loop count to check the card operation voltage range */ +#define FSL_SDMMC_MAX_VOLTAGE_RETRIES (1000U) +/*! @brief Maximum loop count to send the cmd */ +#define FSL_SDMMC_MAX_CMD_RETRIES (10U) +/*! @brief Default block size */ +#define FSL_SDMMC_DEFAULT_BLOCK_SIZE (512U) +#ifndef SDMMC_GLOBAL_BUFFER_SIZE +/*! @brief SDMMC global data buffer size, word unit*/ +#define SDMMC_GLOBAL_BUFFER_SIZE (128U) +#endif +/*! @brief SDMMC enable software tuning */ +#define SDMMC_ENABLE_SOFTWARE_TUNING (0U) +/* Common definition for cache line size align */ +#if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL +#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) +#if defined(FSL_FEATURE_L2DCACHE_LINESIZE_BYTE) +#define SDMMC_DATA_BUFFER_ALIGN_CACHE MAX(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE, FSL_FEATURE_L2DCACHE_LINESIZE_BYTE) +#else +#define SDMMC_DATA_BUFFER_ALIGN_CACHE FSL_FEATURE_L1DCACHE_LINESIZE_BYTE +#endif +#else +#define SDMMC_DATA_BUFFER_ALIGN_CACHE 1 +#endif +#else +#define SDMMC_DATA_BUFFER_ALIGN_CACHE 1 +#endif + +/*! @brief SD/MMC error log. */ +#if defined SDMMC_ENABLE_LOG_PRINT +#include "fsl_debug_console.h" +#define SDMMC_LOG(...) PRINTF(__VA_ARGS__) +#else +#define SDMMC_LOG(format, ...) +#endif + +/*! @brief SD/MMC card API's running status. */ +enum _sdmmc_status +{ + kStatus_SDMMC_NotSupportYet = MAKE_STATUS(kStatusGroup_SDMMC, 0U), /*!< Haven't supported */ + kStatus_SDMMC_TransferFailed = MAKE_STATUS(kStatusGroup_SDMMC, 1U), /*!< Send command failed */ + kStatus_SDMMC_SetCardBlockSizeFailed = MAKE_STATUS(kStatusGroup_SDMMC, 2U), /*!< Set block size failed */ + kStatus_SDMMC_HostNotSupport = MAKE_STATUS(kStatusGroup_SDMMC, 3U), /*!< Host doesn't support */ + kStatus_SDMMC_CardNotSupport = MAKE_STATUS(kStatusGroup_SDMMC, 4U), /*!< Card doesn't support */ + kStatus_SDMMC_AllSendCidFailed = MAKE_STATUS(kStatusGroup_SDMMC, 5U), /*!< Send CID failed */ + kStatus_SDMMC_SendRelativeAddressFailed = MAKE_STATUS(kStatusGroup_SDMMC, 6U), /*!< Send relative address failed */ + kStatus_SDMMC_SendCsdFailed = MAKE_STATUS(kStatusGroup_SDMMC, 7U), /*!< Send CSD failed */ + kStatus_SDMMC_SelectCardFailed = MAKE_STATUS(kStatusGroup_SDMMC, 8U), /*!< Select card failed */ + kStatus_SDMMC_SendScrFailed = MAKE_STATUS(kStatusGroup_SDMMC, 9U), /*!< Send SCR failed */ + kStatus_SDMMC_SetDataBusWidthFailed = MAKE_STATUS(kStatusGroup_SDMMC, 10U), /*!< Set bus width failed */ + kStatus_SDMMC_GoIdleFailed = MAKE_STATUS(kStatusGroup_SDMMC, 11U), /*!< Go idle failed */ + kStatus_SDMMC_HandShakeOperationConditionFailed = + MAKE_STATUS(kStatusGroup_SDMMC, 12U), /*!< Send Operation Condition failed */ + kStatus_SDMMC_SendApplicationCommandFailed = + MAKE_STATUS(kStatusGroup_SDMMC, 13U), /*!< Send application command failed */ + kStatus_SDMMC_SwitchFailed = MAKE_STATUS(kStatusGroup_SDMMC, 14U), /*!< Switch command failed */ + kStatus_SDMMC_StopTransmissionFailed = MAKE_STATUS(kStatusGroup_SDMMC, 15U), /*!< Stop transmission failed */ + kStatus_SDMMC_WaitWriteCompleteFailed = MAKE_STATUS(kStatusGroup_SDMMC, 16U), /*!< Wait write complete failed */ + kStatus_SDMMC_SetBlockCountFailed = MAKE_STATUS(kStatusGroup_SDMMC, 17U), /*!< Set block count failed */ + kStatus_SDMMC_SetRelativeAddressFailed = MAKE_STATUS(kStatusGroup_SDMMC, 18U), /*!< Set relative address failed */ + kStatus_SDMMC_SwitchBusTimingFailed = MAKE_STATUS(kStatusGroup_SDMMC, 19U), /*!< Switch high speed failed */ + kStatus_SDMMC_SendExtendedCsdFailed = MAKE_STATUS(kStatusGroup_SDMMC, 20U), /*!< Send EXT_CSD failed */ + kStatus_SDMMC_ConfigureBootFailed = MAKE_STATUS(kStatusGroup_SDMMC, 21U), /*!< Configure boot failed */ + kStatus_SDMMC_ConfigureExtendedCsdFailed = MAKE_STATUS(kStatusGroup_SDMMC, 22U), /*!< Configure EXT_CSD failed */ + kStatus_SDMMC_EnableHighCapacityEraseFailed = + MAKE_STATUS(kStatusGroup_SDMMC, 23U), /*!< Enable high capacity erase failed */ + kStatus_SDMMC_SendTestPatternFailed = MAKE_STATUS(kStatusGroup_SDMMC, 24U), /*!< Send test pattern failed */ + kStatus_SDMMC_ReceiveTestPatternFailed = MAKE_STATUS(kStatusGroup_SDMMC, 25U), /*!< Receive test pattern failed */ + kStatus_SDMMC_SDIO_ResponseError = MAKE_STATUS(kStatusGroup_SDMMC, 26U), /*!< sdio response error */ + kStatus_SDMMC_SDIO_InvalidArgument = + MAKE_STATUS(kStatusGroup_SDMMC, 27U), /*!< sdio invalid argument response error */ + kStatus_SDMMC_SDIO_SendOperationConditionFail = + MAKE_STATUS(kStatusGroup_SDMMC, 28U), /*!< sdio send operation condition fail */ + kStatus_SDMMC_InvalidVoltage = MAKE_STATUS(kStatusGroup_SDMMC, 29U), /*!< invaild voltage */ + kStatus_SDMMC_SDIO_SwitchHighSpeedFail = MAKE_STATUS(kStatusGroup_SDMMC, 30U), /*!< switch to high speed fail */ + kStatus_SDMMC_SDIO_ReadCISFail = MAKE_STATUS(kStatusGroup_SDMMC, 31U), /*!< read CIS fail */ + kStatus_SDMMC_SDIO_InvalidCard = MAKE_STATUS(kStatusGroup_SDMMC, 32U), /*!< invaild SDIO card */ + kStatus_SDMMC_TuningFail = MAKE_STATUS(kStatusGroup_SDMMC, 33U), /*!< tuning fail */ + + kStatus_SDMMC_SwitchVoltageFail = MAKE_STATUS(kStatusGroup_SDMMC, 34U), /*!< switch voltage fail*/ + kStatus_SDMMC_SwitchVoltage18VFail33VSuccess = MAKE_STATUS(kStatusGroup_SDMMC, 35U), /*!< switch voltage fail*/ + + kStatus_SDMMC_ReTuningRequest = MAKE_STATUS(kStatusGroup_SDMMC, 36U), /*!< retuning request */ + kStatus_SDMMC_SetDriverStrengthFail = MAKE_STATUS(kStatusGroup_SDMMC, 37U), /*!< set driver strength fail */ + kStatus_SDMMC_SetPowerClassFail = MAKE_STATUS(kStatusGroup_SDMMC, 38U), /*!< set power class fail */ + kStatus_SDMMC_HostNotReady = MAKE_STATUS(kStatusGroup_SDMMC, 39U), /*!< host controller not ready */ + kStatus_SDMMC_CardDetectFailed = MAKE_STATUS(kStatusGroup_SDMMC, 40U), /*!< card detect failed */ + kStatus_SDMMC_AuSizeNotSetProperly = MAKE_STATUS(kStatusGroup_SDMMC, 41U), /*!< AU size not set properly */ + +}; + +/*! @brief card operation voltage */ +typedef enum _sdmmc_operation_voltage +{ + kCARD_OperationVoltageNone = 0U, /*!< indicate current voltage setting is not setting bu suser*/ + kCARD_OperationVoltage330V = 1U, /*!< card operation voltage around 3.3v */ + kCARD_OperationVoltage300V = 2U, /*!< card operation voltage around 3.0v */ + kCARD_OperationVoltage180V = 3U, /*!< card operation voltage around 31.8v */ +} sdmmc_operation_voltage_t; + +/************************************************************************************************* + * API + ************************************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @brief Selects the card to put it into transfer state. + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + * @param relativeAddress Relative address. + * @param isSelected True to put card into transfer state. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SDMMC_SelectCard(SDMMCHOST_TYPE *base, + SDMMCHOST_TRANSFER_FUNCTION transfer, + uint32_t relativeAddress, + bool isSelected); + +/*! + * @brief Sends an application command. + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + * @param relativeAddress Card relative address. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_CardNotSupport Card doesn't support. + * @retval kStatus_Success Operate successfully. + */ +status_t SDMMC_SendApplicationCommand(SDMMCHOST_TYPE *base, + SDMMCHOST_TRANSFER_FUNCTION transfer, + uint32_t relativeAddress); + +/*! + * @brief Sets the block count. + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + * @param blockCount Block count. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SDMMC_SetBlockCount(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer, uint32_t blockCount); + +/*! + * @brief Sets the card to be idle state. + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SDMMC_GoIdle(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer); + +/*! + * @brief Sets data block size. + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + * @param blockSize Block size. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SDMMC_SetBlockSize(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer, uint32_t blockSize); + +/*! + * @brief Sets card to inactive status + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SDMMC_SetCardInactive(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer); + +/*! + * @brief provide a simple delay function for sdmmc + * + * @param num Delay num*10000. + */ +void SDMMC_Delay(uint32_t num); + +/*! + * @brief provide a voltage switch function for SD/SDIO card + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + */ +status_t SDMMC_SwitchVoltage(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer); + +/*! + * @brief excute tuning + * + * @param base SDMMCHOST peripheral base address. + * @param transfer Host transfer function + * @param tuningCmd Tuning cmd + * @param blockSize Tuning block size + */ +status_t SDMMC_ExecuteTuning(SDMMCHOST_TYPE *base, + SDMMCHOST_TRANSFER_FUNCTION transfer, + uint32_t tuningCmd, + uint32_t blockSize); + +#if defined(__cplusplus) +} +#endif + +#endif /* _FSL_SDMMC_COMMON_H_ */ diff --git a/target/fsl_sdmmc_host.c b/target/fsl_sdmmc_host.c new file mode 100644 index 0000000..7d3ba77 --- /dev/null +++ b/target/fsl_sdmmc_host.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_sdmmc_host.h" +#include "mbed_wait_api.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +/*! + * @brief SDMMCHOST detect card insert status by host controller. + * @param base host base address. + * @param data3 flag indicate use data3 to detect card or not. + */ +static void SDMMCHOST_DetectCardInsertByHost(SDMMCHOST_TYPE *base, bool data3); + +/*! + * @brief SDMMCHOST detect card status by GPIO. + */ +static bool SDMMCHOST_DetectCardByGpio(void); + +/*! + * @brief SDMMCHOST transfer function. + * @param base host base address. + * @param content transfer configurations. + */ +static status_t SDMMCHOST_TransferFunction(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER *content); + +/*! + * @brief card detect deinit function. + */ +static void SDMMCHOST_CardDetectDeinit(void); + +/*! + * @brief card detect deinit function. + * @param host base address. + * @param host detect card configuration. + */ +static status_t SDMMCHOST_CardDetectInit(SDMMCHOST_TYPE *base, const sdmmchost_detect_card_t *cd); + +/******************************************************************************* + * Variables + ******************************************************************************/ +/*! @brief Card detect flag. */ +static volatile bool s_sdInsertedFlag = false; +/*! @brief DMA descriptor table. */ +static uint32_t s_sdifDmaTable[SDIF_DMA_TABLE_WORDS]; +/******************************************************************************* + * Code + ******************************************************************************/ +static bool SDMMCHOST_DetectCardByGpio(void) +{ + if (SDMMCHOST_CARD_DETECT_STATUS() != SDMMCHOST_CARD_INSERT_CD_LEVEL) + { + s_sdInsertedFlag = false; + } + else + { + s_sdInsertedFlag = true; + } + + return s_sdInsertedFlag; +} + +static void SDMMCHOST_DetectCardInsertByHost(SDMMCHOST_TYPE *base, bool data3) +{ + if (SDMMCHOST_CARD_DETECT_INSERT_STATUS(base, data3)) + { + s_sdInsertedFlag = true; + } +} + +/* User defined transfer function. */ +static status_t SDMMCHOST_TransferFunction(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER *content) +{ + status_t error = kStatus_Success; + + sdif_dma_config_t dmaConfig; + + memset(s_sdifDmaTable, 0, sizeof(s_sdifDmaTable)); + memset(&dmaConfig, 0, sizeof(dmaConfig)); + + if (content->data != NULL) + { + dmaConfig.enableFixBurstLen = true; + dmaConfig.mode = kSDIF_ChainDMAMode; + dmaConfig.dmaDesBufferStartAddr = s_sdifDmaTable; + dmaConfig.dmaDesBufferLen = SDIF_DMA_TABLE_WORDS; + } + + if (kStatus_Success != SDIF_TransferBlocking(base, &dmaConfig, content)) + { + error = kStatus_Fail; + } + + return error; +} + +static status_t SDMMCHOST_CardDetectInit(SDMMCHOST_TYPE *base, const sdmmchost_detect_card_t *cd) +{ + sdmmchost_detect_card_type_t cdType = kSDMMCHOST_DetectCardByGpioCD; + + if (cd != NULL) + { + cdType = cd->cdType; + } + + if (cdType == kSDMMCHOST_DetectCardByGpioCD) + { + SDMMCHOST_CARD_DETECT_INIT(); + SDMMCHOST_DetectCardByGpio(); + } + else + { + /* enable card detect status */ + SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base); + } + + return kStatus_Success; +} + +static void SDMMCHOST_CardDetectDeinit(void) +{ + s_sdInsertedFlag = false; +} + +void SDMMCHOST_Delay(uint32_t milliseconds) +{ + wait_ms(milliseconds); +} + +status_t SDMMCHOST_WaitCardDetectStatus(SDMMCHOST_TYPE *base, const sdmmchost_detect_card_t *cd, bool waitCardStatus) +{ + sdmmchost_detect_card_type_t cdType = kSDMMCHOST_DetectCardByGpioCD; + + if (cd != NULL) + { + cdType = cd->cdType; + } + + if (waitCardStatus != s_sdInsertedFlag) + { + /* Wait card inserted. */ + do + { + if (cdType == kSDMMCHOST_DetectCardByGpioCD) + { + SDMMCHOST_DetectCardByGpio(); + } + else + { + SDMMCHOST_DetectCardInsertByHost(base, cdType == kSDMMCHOST_DetectCardByHostDATA3); + } + + } while (waitCardStatus != s_sdInsertedFlag); + } + + return kStatus_Success; +} + +bool SDMMCHOST_IsCardPresent(void) +{ + return s_sdInsertedFlag; +} + +void SDMMCHOST_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr) +{ + if (pwr != NULL) + { + pwr->powerOff(); + SDMMCHOST_Delay(pwr->powerOffDelay_ms); + } + else + { + /* disable the card power */ + SDIF_EnableCardPower(base, false); + /* Delay several milliseconds to make card stable. */ + SDMMCHOST_Delay(500U); + } +} + +void SDMMCHOST_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr) +{ + /* use user define the power on function */ + if (pwr != NULL) + { + pwr->powerOn(); + SDMMCHOST_Delay(pwr->powerOnDelay_ms); + } + else + { + /* Enable the card power */ + SDIF_EnableCardPower(base, true); + /* Delay several milliseconds to make card stable. */ + SDMMCHOST_Delay(500U); + } +} + +status_t SDMMCHOST_Init(SDMMCHOST_CONFIG *host, void *userData) +{ + sdif_host_t *sdifHost = (sdif_host_t *)host; + + /* init event timer. */ + //SDMMCEVENT_InitTimer(); + + /* Initialize SDIF. */ + sdifHost->config.endianMode = kSDMMCHOST_EndianModeLittle; + sdifHost->config.responseTimeout = 0xFFU; + sdifHost->config.cardDetDebounce_Clock = 0xFFFFFFU; + sdifHost->config.dataTimeout = 0xFFFFFFU; + SDIF_Init(sdifHost->base, &(sdifHost->config)); + + /* Define transfer function. */ + sdifHost->transfer = SDMMCHOST_TransferFunction; + + SDMMCHOST_CardDetectInit(sdifHost->base, (sdmmchost_detect_card_t *)userData); + + return kStatus_Success; +} + +void SDMMCHOST_Reset(SDMMCHOST_TYPE *base) +{ + /* reserved for future */ +} + +void SDMMCHOST_Deinit(void *host) +{ + sdif_host_t *sdifHost = (sdif_host_t *)host; + SDIF_Deinit(sdifHost->base); + SDMMCHOST_CardDetectDeinit(); +} + +void SDMMCHOST_ErrorRecovery(SDMMCHOST_TYPE *base) +{ + /* reserved for future */ +} diff --git a/target/fsl_sdmmc_host.h b/target/fsl_sdmmc_host.h new file mode 100644 index 0000000..f6b47a0 --- /dev/null +++ b/target/fsl_sdmmc_host.h @@ -0,0 +1,736 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_SDMMC_HOST_H +#define _FSL_SDMMC_HOST_H + +#include "fsl_common.h" +#include "board.h" +#if defined(FSL_FEATURE_SOC_SDHC_COUNT) && FSL_FEATURE_SOC_SDHC_COUNT > 0U +#include "fsl_sdhc.h" +#elif defined(FSL_FEATURE_SOC_SDIF_COUNT) && FSL_FEATURE_SOC_SDIF_COUNT > 0U +#include "fsl_sdif.h" +#elif defined(FSL_FEATURE_SOC_USDHC_COUNT) && FSL_FEATURE_SOC_USDHC_COUNT > 0U +#include "fsl_usdhc.h" +#endif + +/*! + * @addtogroup CARD + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* Common definition for support and not support macro */ +#define SDMMCHOST_NOT_SUPPORT 0U /*!< use this define to indicate the host not support feature*/ +#define SDMMCHOST_SUPPORT 1U /*!< use this define to indicate the host support feature*/ + +/* Common definition for board support SDR104/HS200/HS400 frequency */ +/* SDR104 mode freq */ +#if defined BOARD_SD_HOST_SUPPORT_SDR104_FREQ +#define SDMMCHOST_SUPPORT_SDR104_FREQ BOARD_SD_HOST_SUPPORT_SDR104_FREQ +#else +#define SDMMCHOST_SUPPORT_SDR104_FREQ SD_CLOCK_208MHZ +#endif +/* HS200 mode freq */ +#if defined BOARD_SD_HOST_SUPPORT_HS200_FREQ +#define SDMMCHOST_SUPPORT_HS200_FREQ BOARD_SD_HOST_SUPPORT_HS200_FREQ +#else +#define SDMMCHOST_SUPPORT_HS200_FREQ MMC_CLOCK_HS200 +#endif +/* HS400 mode freq */ +#if defined BOARD_SD_HOST_SUPPORT_HS400_FREQ +#define SDMMCHOST_SUPPORT_HS400_FREQ BOARD_SD_HOST_SUPPORT_HS400_FREQ +#else +#define SDMMCHOST_SUPPORT_HS400_FREQ MMC_CLOCK_HS400 +#endif + +/* Common definition for SDMMCHOST transfer complete timeout */ +#define SDMMCHOST_TRANSFER_COMPLETE_TIMEOUT (500U) +/* Common definition for card detect timeout */ +#define SDMMCHOST_CARD_DETECT_TIMEOUT (~0U) + +/* Common definition for IRQ */ +#if defined(__CORTEX_M) +#define SDMMCHOST_SET_IRQ_PRIORITY(id, priority) (NVIC_SetPriority(id, priority)) +#else +#define SDMMCHOST_SET_IRQ_PRIORITY(id, priority) (GIC_SetPriority(id, priority)) +#endif + +#define SDMMCHOST_ENABLE_IRQ(id) (EnableIRQ(id)) + +/*********************************************************SDHC**********************************************************/ +#if (defined(FSL_FEATURE_SOC_SDHC_COUNT) && (FSL_FEATURE_SOC_SDHC_COUNT > 0U)) + +/*define host baseaddr ,clk freq, IRQ number*/ +#define MMC_HOST_BASEADDR BOARD_SDHC_BASEADDR +#define MMC_HOST_CLK_FREQ BOARD_SDHC_CLK_FREQ +#define MMC_HOST_IRQ BOARD_SDHC_IRQ +#define SD_HOST_BASEADDR BOARD_SDHC_BASEADDR +#define SD_HOST_CLK_FREQ BOARD_SDHC_CLK_FREQ +#define SD_HOST_IRQ BOARD_SDHC_IRQ + +/* define for card bus speed/strength cnofig */ +#define CARD_BUS_FREQ_50MHZ (0U) +#define CARD_BUS_FREQ_100MHZ0 (0U) +#define CARD_BUS_FREQ_100MHZ1 (0U) +#define CARD_BUS_FREQ_200MHZ (0U) + +#define CARD_BUS_STRENGTH_0 (0U) +#define CARD_BUS_STRENGTH_1 (0U) +#define CARD_BUS_STRENGTH_2 (0U) +#define CARD_BUS_STRENGTH_3 (0U) +#define CARD_BUS_STRENGTH_4 (0U) +#define CARD_BUS_STRENGTH_5 (0U) +#define CARD_BUS_STRENGTH_6 (0U) +#define CARD_BUS_STRENGTH_7 (0U) + +#define SDMMCHOST_TYPE SDHC_Type +#define SDMMCHOST_CONFIG sdhc_host_t +#define SDMMCHOST_TRANSFER sdhc_transfer_t +#define SDMMCHOST_COMMAND sdhc_command_t +#define SDMMCHOST_DATA sdhc_data_t +#define SDMMCHOST_BUS_WIDTH_TYPE sdhc_data_bus_width_t +#define SDMMCHOST_CAPABILITY sdhc_capability_t +#define SDMMCHOST_BOOT_CONFIG sdhc_boot_config_t + +#define CARD_DATA0_STATUS_MASK (1U << kSDHC_Data0LineLevelFlag) +#define CARD_DATA0_NOT_BUSY (1U << kSDHC_Data0LineLevelFlag) +#define CARD_DATA1_STATUS_MASK (1U << kSDHC_Data1LineLevelFlag) +#define CARD_DATA2_STATUS_MASK (1U << kSDHC_Data2LineLevelFlag) +#define CARD_DATA3_STATUS_MASK (1U << kSDHC_Data3LineLevelFlag) + +#define kSDMMCHOST_DATABUSWIDTH1BIT kSDHC_DataBusWidth1Bit /*!< 1-bit mode */ +#define kSDMMCHOST_DATABUSWIDTH4BIT kSDHC_DataBusWidth4Bit /*!< 4-bit mode */ +#define kSDMMCHOST_DATABUSWIDTH8BIT kSDHC_DataBusWidth8Bit /*!< 8-bit mode */ + +#define SDMMCHOST_STANDARD_TUNING_START (0U) /*!< standard tuning start point */ +#define SDMMCHOST_TUINIG_STEP (1U) /*!< standard tuning step */ +#define SDMMCHOST_RETUNING_TIMER_COUNT (4U) /*!< Re-tuning timer */ +#define SDMMCHOST_TUNING_DELAY_MAX (0x7FU) +#define SDMMCHOST_RETUNING_REQUEST (1U) +#define SDMMCHOST_TUNING_ERROR (2U) + +/* function pointer define */ +#define SDMMCHOST_TRANSFER_FUNCTION sdhc_transfer_function_t +#define GET_SDMMCHOST_CAPABILITY(base, capability) (SDHC_GetCapability(base, capability)) +#define GET_SDMMCHOST_STATUS(base) (SDHC_GetPresentStatusFlags(base)) +#define SDMMCHOST_SET_CARD_CLOCK(base, sourceClock_HZ, busClock_HZ) (SDHC_SetSdClock(base, sourceClock_HZ, busClock_HZ)) +#define SDMMCHOST_SET_CARD_BUS_WIDTH(base, busWidth) (SDHC_SetDataBusWidth(base, busWidth)) +#define SDMMCHOST_SEND_CARD_ACTIVE(base, timeout) (SDHC_SetCardActive(base, timeout)) +#define SDMMCHOST_SWITCH_VOLTAGE180V(base, enable18v) +#define SDMMCHOST_SWITCH_VOLTAGE120V(base, enable12v) +#define SDMMCHOST_CONFIG_IO_STRENGTH(speed, strength) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, flag) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) (0U) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) (1U) +#define SDMMCHOST_CONFIG_SD_IO(speed, strength) +#define SDMMCHOST_CONFIG_MMC_IO(speed, strength) +#define SDMMCHOST_ENABLE_DDR_MODE(base, flag, nibblePos) +#define SDMMCHOST_FORCE_SDCLOCK_ON(base, enable) +#define SDMMCHOST_EXECUTE_MANUAL_TUNING_ENABLE(base, flag) +#define SDMMCHOST_ADJUST_MANUAL_TUNING_DELAY(base, delay) +#define SDMMCHOST_AUTO_MANUAL_TUNING_ENABLE(base, flag) +#define SDMMCHOST_ENABLE_CARD_CLOCK(base, enable) (SDHC_EnableSdClock(base, enable)) +#define SDMMCHOST_RESET_TUNING(base, timeout) +#define SDMMCHOST_CHECK_TUNING_ERROR(base) (0U) +#define SDMMCHOST_ADJUST_TUNING_DELAY(base, delay) +#define SDMMCHOST_AUTO_STANDARD_RETUNING_TIMER(base) +#define SDMMCHOST_TRANSFER_DATA_ERROR kStatus_SDHC_TransferDataFailed +#define SDMMCHOST_TRANSFER_CMD_ERROR kStatus_SDHC_SendCommandFailed +#define SDMMCHOST_ENABLE_HS400_MODE(base, flag) +#define SDMMCHOST_RESET_STROBE_DLL(base) +#define SDMMCHOST_ENABLE_STROBE_DLL(base, flag) +#define SDMMCHOST_CONFIG_STROBE_DLL(base, delay, updateInterval) +#define SDMMCHOST_GET_STROBE_DLL_STATUS(base) +/* sd card power */ +#define SDMMCHOST_INIT_SD_POWER() +#define SDMMCHOST_ENABLE_SD_POWER(enable) +#define SDMMCHOST_SWITCH_VCC_TO_180V() +#define SDMMCHOST_SWITCH_VCC_TO_330V() +/* mmc card power */ +#define SDMMCHOST_INIT_MMC_POWER() +#define SDMMCHOST_ENABLE_MMC_POWER(enable) +#define SDMMCHOST_ENABLE_TUNING_FLAG(data) +#define SDMMCHOST_ENABLE_BOOT_FLAG(data) +#define SDMMCHOST_ENABLE_BOOT_CONTINOUS_FLAG(data) +#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_SIZE(config) (0U) +#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_COUNT(config) (0U) +#define SDMMCHOST_GET_HOST_CONFIG_BOOT_MODE(config) (0U) +#define SDMMCHOST_EMPTY_CMD_FLAG(command) +#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_HANDLER BOARD_SDHC_CD_PORT_IRQ_HANDLER +#define SDMMCHOST_CARD_DETECT_IRQ BOARD_SDHC_CD_PORT_IRQ +/* sd card detect through host CD */ +#define SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base) (SDHC_EnableInterruptStatus(base, kSDHC_CardInsertionFlag)) +#define SDMMCHOST_CARD_DETECT_REMOVE_ENABLE(base) (SDHC_EnableInterruptStatus(base, kSDHC_CardRemovalFlag)) +#define SDMMCHOST_CARD_DETECT_INSERT_STATUS(base) (SDHC_GetInterruptStatusFlags(base) & kSDHC_CardInsertionFlag) +#define SDMMCHOST_CARD_DETECT_REMOVE_STATUS(base) (SDHC_GetInterruptStatusFlags(base, kSDHC_CardRemovalFlag)) +#define SDMMCHOST_CARD_DETECT_INSERT_INTERRUPT_ENABLE(base) (SDHC_EnableInterruptSignal(base, kSDHC_CardInsertionFlag)) +#define SDMMCHOST_CARD_DETECT_INSERT_INTERRUPT_DISABLE(base) \ + (SDHC_DisableInterruptSignal(base, kSDHC_CardInsertionFlag)) +#define SDMMCHOST_CARD_DETECT_REMOVE_INTERRUPT_ENABLE(base) (SDHC_EnableInterruptSignal(base, kSDHC_CardRemovalFlag)) +#define SDMMCHOST_CARD_DETECT_DATA3_ENABLE(base, flag) (SDHC_CardDetectByData3(base, flag)) +#define SDMMCHOST_ENABLE_MMC_BOOT(base, flag) +#define SDMMCHOST_SETMMCBOOTCONFIG(base, config) (SDHC_SetMmcBootConfig(base, config)) +/* define card detect pin voltage level when card inserted */ +#if defined BOARD_SDHC_CARD_INSERT_CD_LEVEL +#define SDMMCHOST_CARD_INSERT_CD_LEVEL BOARD_SDHC_CARD_INSERT_CD_LEVEL +#else +#define SDMMCHOST_CARD_INSERT_CD_LEVEL (0U) +#endif +#define SDMMCHOST_AUTO_TUNING_ENABLE(base, flag) + +/*! @brief SDHC host capability*/ +enum _host_capability +{ + kSDMMCHOST_SupportAdma = kSDHC_SupportAdmaFlag, + kSDMMCHOST_SupportHighSpeed = kSDHC_SupportHighSpeedFlag, + kSDMMCHOST_SupportDma = kSDHC_SupportDmaFlag, + kSDMMCHOST_SupportSuspendResume = kSDHC_SupportSuspendResumeFlag, + kSDMMCHOST_SupportV330 = kSDHC_SupportV330Flag, + kSDMMCHOST_SupportV300 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportV180 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportV120 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_Support4BitBusWidth = kSDHC_Support4BitFlag, + kSDMMCHOST_Support8BitBusWidth = kSDHC_Support8BitFlag, + kSDMMCHOST_SupportDDR50 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportSDR104 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportSDR50 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportHS200 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportHS400 = SDMMCHOST_NOT_SUPPORT, +}; + +/* Endian mode. */ +#define SDHC_ENDIAN_MODE kSDHC_EndianModeLittle + +/* DMA mode */ +#define SDHC_DMA_MODE kSDHC_DmaModeAdma2 +/* address align */ +#define SDMMCHOST_DMA_BUFFER_ADDR_ALIGN (SDHC_ADMA2_ADDRESS_ALIGN) + +/* Read/write watermark level. The bigger value indicates DMA has higher read/write performance. */ +#define SDHC_READ_WATERMARK_LEVEL (0x80U) +#define SDHC_WRITE_WATERMARK_LEVEL (0x80U) + +/* ADMA table length united as word. + * + * SD card driver can't support ADMA1 transfer mode currently. + * One ADMA2 table item occupy two words which can transfer maximum 0xFFFFU bytes one time. + * The more data to be transferred in one time, the bigger value of SDHC_ADMA_TABLE_WORDS need to be set. + */ +#define SDHC_ADMA_TABLE_WORDS (8U) + +/*********************************************************SDIF**********************************************************/ +#elif(defined(FSL_FEATURE_SOC_SDIF_COUNT) && (FSL_FEATURE_SOC_SDIF_COUNT > 0U)) + +/*define host baseaddr ,clk freq, IRQ number*/ +#define MMC_HOST_BASEADDR BOARD_SDIF_BASEADDR +#define MMC_HOST_CLK_FREQ BOARD_SDIF_CLK_FREQ +#define MMC_HOST_IRQ BOARD_SDIF_IRQ +#define SD_HOST_BASEADDR BOARD_SDIF_BASEADDR +#define SD_HOST_CLK_FREQ BOARD_SDIF_CLK_FREQ +#define SD_HOST_IRQ BOARD_SDIF_IRQ + +/* define for card bus speed/strength cnofig */ +#define CARD_BUS_FREQ_50MHZ (0U) +#define CARD_BUS_FREQ_100MHZ0 (0U) +#define CARD_BUS_FREQ_100MHZ1 (0U) +#define CARD_BUS_FREQ_200MHZ (0U) + +#define CARD_BUS_STRENGTH_0 (0U) +#define CARD_BUS_STRENGTH_1 (0U) +#define CARD_BUS_STRENGTH_2 (0U) +#define CARD_BUS_STRENGTH_3 (0U) +#define CARD_BUS_STRENGTH_4 (0U) +#define CARD_BUS_STRENGTH_5 (0U) +#define CARD_BUS_STRENGTH_6 (0U) +#define CARD_BUS_STRENGTH_7 (0U) + +#define SDMMCHOST_TYPE SDIF_Type +#define SDMMCHOST_CONFIG sdif_host_t +#define SDMMCHOST_TRANSFER sdif_transfer_t +#define SDMMCHOST_COMMAND sdif_command_t +#define SDMMCHOST_DATA sdif_data_t +#define SDMMCHOST_BUS_WIDTH_TYPE sdif_bus_width_t +#define SDMMCHOST_CAPABILITY sdif_capability_t +#define SDMMCHOST_BOOT_CONFIG void + +#define CARD_DATA0_STATUS_MASK SDIF_STATUS_DATA_BUSY_MASK +#define CARD_DATA0_NOT_BUSY 0U + +#define CARD_DATA1_STATUS_MASK (0U) +#define CARD_DATA2_STATUS_MASK (0U) +#define CARD_DATA3_STATUS_MASK (0U) + +#define kSDMMCHOST_DATABUSWIDTH1BIT kSDIF_Bus1BitWidth /*!< 1-bit mode */ +#define kSDMMCHOST_DATABUSWIDTH4BIT kSDIF_Bus4BitWidth /*!< 4-bit mode */ +#define kSDMMCHOST_DATABUSWIDTH8BIT kSDIF_Bus8BitWidth /*!< 8-bit mode */ + +#define SDMMCHOST_STANDARD_TUNING_START (0U) /*!< standard tuning start point */ +#define SDMMCHOST_TUINIG_STEP (1U) /*!< standard tuning step */ +#define SDMMCHOST_RETUNING_TIMER_COUNT (4U) /*!< Re-tuning timer */ +#define SDMMCHOST_TUNING_DELAY_MAX (0x7FU) +#define SDMMCHOST_RETUNING_REQUEST (1U) +#define SDMMCHOST_TUNING_ERROR (2U) +/* function pointer define */ +#define SDMMCHOST_TRANSFER_FUNCTION sdif_transfer_function_t +#define GET_SDMMCHOST_CAPABILITY(base, capability) (SDIF_GetCapability(base, capability)) +#define GET_SDMMCHOST_STATUS(base) (SDIF_GetControllerStatus(base)) +#define SDMMCHOST_SET_CARD_CLOCK(base, sourceClock_HZ, busClock_HZ) \ + (SDIF_SetCardClock(base, sourceClock_HZ, busClock_HZ)) +#define SDMMCHOST_SET_CARD_BUS_WIDTH(base, busWidth) (SDIF_SetCardBusWidth(base, busWidth)) +#define SDMMCHOST_SEND_CARD_ACTIVE(base, timeout) (SDIF_SendCardActive(base, timeout)) +#define SDMMCHOST_SWITCH_VOLTAGE180V(base, enable18v) +#define SDMMCHOST_SWITCH_VOLTAGE120V(base, enable12v) +#define SDMMCHOST_CONFIG_IO_STRENGTH(speed, strength) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, flag) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) (0U) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) (1U) +#define SDMMCHOST_CONFIG_SD_IO(speed, strength) +#define SDMMCHOST_CONFIG_MMC_IO(speed, strength) +#define SDMMCHOST_ENABLE_DDR_MODE(base, flag, nibblePos) +#define SDMMCHOST_FORCE_SDCLOCK_ON(base, enable) +#define SDMMCHOST_EXECUTE_MANUAL_TUNING_ENABLE(base, flag) +#define SDMMCHOST_ADJUST_MANUAL_TUNING_DELAY(base, delay) +#define SDMMCHOST_AUTO_MANUAL_TUNING_ENABLE(base, flag) +#define SDMMCHOST_ENABLE_CARD_CLOCK(base, enable) (SDIF_EnableCardClock(base, enable)) +#define SDMMCHOST_RESET_TUNING(base, timeout) +#define SDMMCHOST_CHECK_TUNING_ERROR(base) (0U) +#define SDMMCHOST_ADJUST_TUNING_DELAY(base, delay) +#define SDMMCHOST_AUTO_STANDARD_RETUNING_TIMER(base) + +#define SDMMCHOST_ENABLE_HS400_MODE(base, flag) +#define SDMMCHOST_RESET_STROBE_DLL(base) +#define SDMMCHOST_ENABLE_STROBE_DLL(base, flag) +#define SDMMCHOST_CONFIG_STROBE_DLL(base, delay, updateInterval) +#define SDMMCHOST_GET_STROBE_DLL_STATUS(base) +/* sd card power */ +#define SDMMCHOST_INIT_SD_POWER() +#define SDMMCHOST_ENABLE_SD_POWER(enable) +#define SDMMCHOST_SWITCH_VCC_TO_180V() +#define SDMMCHOST_SWITCH_VCC_TO_330V() +/* mmc card power */ +#define SDMMCHOST_INIT_MMC_POWER() +#define SDMMCHOST_ENABLE_MMC_POWER(enable) +#define SDMMCHOST_ENABLE_TUNING_FLAG(data) +#define SDMMCHOST_ENABLE_MMC_BOOT(base, flag) +#define SDMMCHOST_SETMMCBOOTCONFIG(base, config) +#define SDMMCHOST_ENABLE_BOOT_FLAG(data) +#define SDMMCHOST_ENABLE_BOOT_CONTINOUS_FLAG(data) +#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_SIZE(config) (0U) +#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_COUNT(config) (0U) +#define SDMMCHOST_GET_HOST_CONFIG_BOOT_MODE(config) (0U) +#define SDMMCHOST_EMPTY_CMD_FLAG(command) +#define SDMMCHOST_CARD_DETECT_STATUS() BOARD_SDIF_CD_STATUS() +#define SDMMCHOST_CARD_DETECT_INIT() BOARD_SDIF_CD_GPIO_INIT() +#define SDMMCHOST_CARD_DETECT_INTERRUPT_STATUS() BOARD_SDIF_CD_INTERRUPT_STATUS() +#define SDMMCHOST_CARD_DETECT_INTERRUPT_CLEAR(flag) BOARD_SDIF_CD_CLEAR_INTERRUPT(flag) +#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_HANDLER BOARD_SDIF_CD_PORT_IRQ_HANDLER +#define SDMMCHOST_CARD_DETECT_IRQ BOARD_SDIF_CD_PORT_IRQ +#define SDMMCHOST_TRANSFER_DATA_ERROR kStatus_SDIF_DataTransferFail +#define SDMMCHOST_TRANSFER_CMD_ERROR kStatus_SDIF_SendCmdFail +/* define card detect pin voltage level when card inserted */ +#if defined BOARD_SDIF_CARD_INSERT_CD_LEVEL +#define SDMMCHOST_CARD_INSERT_CD_LEVEL BOARD_SDIF_CARD_INSERT_CD_LEVEL +#else +#define SDMMCHOST_CARD_INSERT_CD_LEVEL (0U) +#endif +#define SDMMCHOST_AUTO_TUNING_ENABLE(base, flag) +/* sd card detect through host CD */ +#define SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base) (SDIF_EnableInterrupt(base, kSDIF_CardDetect)) +#define SDMMCHOST_CARD_DETECT_INSERT_STATUS(base, data3) (SDIF_DetectCardInsert(base, data3)) + +/*! @brief SDIF host capability*/ +enum _host_capability +{ + kSDMMCHOST_SupportHighSpeed = kSDIF_SupportHighSpeedFlag, + kSDMMCHOST_SupportDma = kSDIF_SupportDmaFlag, + kSDMMCHOST_SupportSuspendResume = kSDIF_SupportSuspendResumeFlag, + kSDMMCHOST_SupportV330 = kSDIF_SupportV330Flag, + kSDMMCHOST_SupportV300 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportV180 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportV120 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_Support4BitBusWidth = kSDIF_Support4BitFlag, + kSDMMCHOST_Support8BitBusWidth = + SDMMCHOST_NOT_SUPPORT, /* mask the 8 bit here,user can change depend on your board */ + kSDMMCHOST_SupportDDR50 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportSDR104 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportSDR50 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportHS200 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportHS400 = SDMMCHOST_NOT_SUPPORT, + +}; + +/*! @brief DMA table length united as word + * One dma table item occupy four words which can transfer maximum 2*8188 bytes in dual DMA mode + * and 8188 bytes in chain mode + * The more data to be transferred in one time, the bigger value of SDHC_ADMA_TABLE_WORDS need to be set. + * user need check the DMA descriptor table lenght if bigger enough. + */ +#define SDIF_DMA_TABLE_WORDS (0x40U) +/* address align */ +#define SDMMCHOST_DMA_BUFFER_ADDR_ALIGN (4U) + +/*********************************************************USDHC**********************************************************/ +#elif(defined(FSL_FEATURE_SOC_USDHC_COUNT) && (FSL_FEATURE_SOC_USDHC_COUNT > 0U)) + +/*define host baseaddr ,clk freq, IRQ number*/ +#define MMC_HOST_BASEADDR BOARD_MMC_HOST_BASEADDR +#define MMC_HOST_CLK_FREQ BOARD_MMC_HOST_CLK_FREQ +#define MMC_HOST_IRQ BOARD_MMC_HOST_IRQ +#define SD_HOST_BASEADDR BOARD_SD_HOST_BASEADDR +#define SD_HOST_CLK_FREQ BOARD_SD_HOST_CLK_FREQ +#define SD_HOST_IRQ BOARD_SD_HOST_IRQ + +#define SDMMCHOST_TYPE USDHC_Type +#define SDMMCHOST_CONFIG usdhc_host_t +#define SDMMCHOST_TRANSFER usdhc_transfer_t +#define SDMMCHOST_COMMAND usdhc_command_t +#define SDMMCHOST_DATA usdhc_data_t +#define SDMMCHOST_BOOT_CONFIG usdhc_boot_config_t +#define CARD_DATA0_STATUS_MASK (1U << kUSDHC_Data0LineLevelFlag) +#define CARD_DATA1_STATUS_MASK (1U << kUSDHC_Data1LineLevelFlag) +#define CARD_DATA2_STATUS_MASK (1U << kUSDHC_Data2LineLevelFlag) +#define CARD_DATA3_STATUS_MASK (1U << kUSDHC_Data3LineLevelFlag) +#define CARD_DATA0_NOT_BUSY (1U << kUSDHC_Data0LineLevelFlag) + +#define SDMMCHOST_BUS_WIDTH_TYPE usdhc_data_bus_width_t +#define SDMMCHOST_CAPABILITY usdhc_capability_t + +#define kSDMMCHOST_DATABUSWIDTH1BIT kUSDHC_DataBusWidth1Bit /*!< 1-bit mode */ +#define kSDMMCHOST_DATABUSWIDTH4BIT kUSDHC_DataBusWidth4Bit /*!< 4-bit mode */ +#define kSDMMCHOST_DATABUSWIDTH8BIT kUSDHC_DataBusWidth8Bit /*!< 8-bit mode */ + +#define SDMMCHOST_STANDARD_TUNING_START (10U) /*!< standard tuning start point */ +#define SDMMCHOST_TUINIG_STEP (2U) /*!< standard tuning step */ +#define SDMMCHOST_RETUNING_TIMER_COUNT (0U) /*!< Re-tuning timer */ +#define SDMMCHOST_TUNING_DELAY_MAX (0x7FU) +#define SDMMCHOST_RETUNING_REQUEST kStatus_USDHC_ReTuningRequest +#define SDMMCHOST_TUNING_ERROR kStatus_USDHC_TuningError +#define SDMMCHOST_TRANSFER_DATA_ERROR kStatus_USDHC_TransferDataFailed +#define SDMMCHOST_TRANSFER_CMD_ERROR kStatus_USDHC_SendCommandFailed +/* define for card bus speed/strength cnofig */ +#define CARD_BUS_FREQ_50MHZ (0U) +#define CARD_BUS_FREQ_100MHZ0 (1U) +#define CARD_BUS_FREQ_100MHZ1 (2U) +#define CARD_BUS_FREQ_200MHZ (3U) + +#define CARD_BUS_STRENGTH_0 (0U) +#define CARD_BUS_STRENGTH_1 (1U) +#define CARD_BUS_STRENGTH_2 (2U) +#define CARD_BUS_STRENGTH_3 (3U) +#define CARD_BUS_STRENGTH_4 (4U) +#define CARD_BUS_STRENGTH_5 (5U) +#define CARD_BUS_STRENGTH_6 (6U) +#define CARD_BUS_STRENGTH_7 (7U) + +#define SDMMCHOST_STROBE_DLL_DELAY_TARGET (7U) +#define SDMMCHOST_STROBE_DLL_DELAY_UPDATE_INTERVAL (4U) + +/* function pointer define */ +#define SDMMCHOST_TRANSFER_FUNCTION usdhc_transfer_function_t +#define GET_SDMMCHOST_CAPABILITY(base, capability) (USDHC_GetCapability(base, capability)) +#define GET_SDMMCHOST_STATUS(base) (USDHC_GetPresentStatusFlags(base)) +#define SDMMCHOST_SET_CARD_CLOCK(base, sourceClock_HZ, busClock_HZ) \ + (USDHC_SetSdClock(base, sourceClock_HZ, busClock_HZ)) +#define SDMMCHOST_ENABLE_CARD_CLOCK(base, enable) +#define SDMMCHOST_FORCE_SDCLOCK_ON(base, enable) (USDHC_ForceClockOn(base, enable)) +#define SDMMCHOST_SET_CARD_BUS_WIDTH(base, busWidth) (USDHC_SetDataBusWidth(base, busWidth)) +#define SDMMCHOST_SEND_CARD_ACTIVE(base, timeout) (USDHC_SetCardActive(base, timeout)) +#define SDMMCHOST_SWITCH_VOLTAGE180V(base, enable18v) (UDSHC_SelectVoltage(base, enable18v)) +#define SDMMCHOST_SWITCH_VOLTAGE120V(base, enable12v) +#define SDMMCHOST_CONFIG_SD_IO(speed, strength) BOARD_SD_Pin_Config(speed, strength) +#define SDMMCHOST_CONFIG_MMC_IO(speed, strength) BOARD_MMC_Pin_Config(speed, strength) +#define SDMMCHOST_SWITCH_VCC_TO_180V() +#define SDMMCHOST_SWITCH_VCC_TO_330V() + +#if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (!FSL_FEATURE_USDHC_HAS_SDR50_MODE) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) (0U) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) (1U) +#define SDMMCHOST_AUTO_STANDARD_RETUNING_TIMER(base) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, flag) +#define SDMMCHOST_CHECK_TUNING_ERROR(base) (0U) +#define SDMMCHOST_ADJUST_TUNING_DELAY(base, delay) +#else +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, flag) \ + (USDHC_EnableStandardTuning(base, SDMMCHOST_STANDARD_TUNING_START, SDMMCHOST_TUINIG_STEP, flag)) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) (USDHC_GetExecuteStdTuningStatus(base)) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) (USDHC_CheckStdTuningResult(base)) +#define SDMMCHOST_AUTO_STANDARD_RETUNING_TIMER(base) (USDHC_SetRetuningTimer(base, SDMMCHOST_RETUNING_TIMER_COUNT)) +#define SDMMCHOST_EXECUTE_MANUAL_TUNING_ENABLE(base, flag) (USDHC_EnableManualTuning(base, flag)) +#define SDMMCHOST_ADJUST_TUNING_DELAY(base, delay) (USDHC_AdjustDelayForManualTuning(base, delay)) +#define SDMMCHOST_AUTO_TUNING_ENABLE(base, flag) (USDHC_EnableAutoTuning(base, flag)) +#define SDMMCHOST_CHECK_TUNING_ERROR(base) (USDHC_CheckTuningError(base)) +#endif + +#define SDMMCHOST_AUTO_TUNING_CONFIG(base) (USDHC_EnableAutoTuningForCmdAndData(base)) +#define SDMMCHOST_RESET_TUNING(base, timeout) \ + { \ + (USDHC_Reset(base, kUSDHC_ResetTuning | kUSDHC_ResetData | kUSDHC_ResetCommand, timeout)); \ + } + +#define SDMMCHOST_ENABLE_DDR_MODE(base, flag, nibblePos) (USDHC_EnableDDRMode(base, flag, nibblePos)) + +#if FSL_FEATURE_USDHC_HAS_HS400_MODE +#define SDMMCHOST_ENABLE_HS400_MODE(base, flag) (USDHC_EnableHS400Mode(base, flag)) +#define SDMMCHOST_RESET_STROBE_DLL(base) (USDHC_ResetStrobeDLL(base)) +#define SDMMCHOST_ENABLE_STROBE_DLL(base, flag) (USDHC_EnableStrobeDLL(base, flag)) +#define SDMMCHOST_CONFIG_STROBE_DLL(base, delay, updateInterval) (USDHC_ConfigStrobeDLL(base, delay, updateInterval)) +#define SDMMCHOST_GET_STROBE_DLL_STATUS (base)(USDHC_GetStrobeDLLStatus(base)) +#else +#define SDMMCHOST_ENABLE_HS400_MODE(base, flag) +#define SDMMCHOST_RESET_STROBE_DLL(base) +#define SDMMCHOST_ENABLE_STROBE_DLL(base, flag) +#define SDMMCHOST_CONFIG_STROBE_DLL(base, delay, updateInterval) +#define SDMMCHOST_GET_STROBE_DLL_STATUS(base) +#endif + +#define SDMMCHOST_ENABLE_MMC_BOOT(base, flag) (USDHC_EnableMmcBoot(base, flag)) +#define SDMMCHOST_SETMMCBOOTCONFIG(base, config) (USDHC_SetMmcBootConfig(base, config)) +/* sd card power */ +#define SDMMCHOST_INIT_SD_POWER() BOARD_USDHC_SDCARD_POWER_CONTROL_INIT() +#define SDMMCHOST_ENABLE_SD_POWER(enable) BOARD_USDHC_SDCARD_POWER_CONTROL(enable) +/* mmc card power */ +#define SDMMCHOST_INIT_MMC_POWER() BOARD_USDHC_MMCCARD_POWER_CONTROL_INIT() +#define SDMMCHOST_ENABLE_MMC_POWER(enable) BOARD_USDHC_MMCCARD_POWER_CONTROL(enable) +/* sd card detect through gpio */ +#define SDMMCHOST_CARD_DETECT_GPIO_STATUS() BOARD_USDHC_CD_STATUS() +#define SDMMCHOST_CARD_DETECT_GPIO_INIT() BOARD_USDHC_CD_GPIO_INIT() +#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_STATUS() BOARD_USDHC_CD_INTERRUPT_STATUS() +#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_STATUS_CLEAR(flag) BOARD_USDHC_CD_CLEAR_INTERRUPT(flag) +#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_HANDLER BOARD_USDHC_CD_PORT_IRQ_HANDLER +#define SDMMCHOST_CARD_DETECT_GPIO_IRQ BOARD_USDHC_CD_PORT_IRQ +/* sd card detect through host CD */ +#define SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base) (USDHC_EnableInterruptStatus(base, kUSDHC_CardInsertionFlag)) +#define SDMMCHOST_CARD_DETECT_REMOVE_ENABLE(base) (USDHC_EnableInterruptStatus(base, kUSDHC_CardRemovalFlag)) +#define SDMMCHOST_CARD_DETECT_INSERT_STATUS(base) (USDHC_DetectCardInsert(base)) +#define SDMMCHOST_CARD_DETECT_REMOVE_STATUS(base) (USDHC_GetInterruptStatusFlags(base, kUSDHC_CardRemovalFlag)) +#define SDMMCHOST_CARD_DETECT_INSERT_INTERRUPT_ENABLE(base) \ + (USDHC_EnableInterruptSignal(base, kUSDHC_CardInsertionFlag)) +#define SDMMCHOST_CARD_DETECT_REMOVE_INTERRUPT_ENABLE(base) (USDHC_EnableInterruptSignal(base, kUSDHC_CardRemovalFlag)) +#define SDMMCHOST_CARD_DETECT_DATA3_ENABLE(base, flag) (USDHC_CardDetectByData3(base, flag)) + +/* define card detect pin voltage level when card inserted */ +#if defined BOARD_USDHC_CARD_INSERT_CD_LEVEL +#define SDMMCHOST_CARD_INSERT_CD_LEVEL BOARD_USDHC_CARD_INSERT_CD_LEVEL +#else +#define SDMMCHOST_CARD_INSERT_CD_LEVEL (0U) +#endif +#define SDMMCHOST_ENABLE_TUNING_FLAG(data) (data.dataType = kUSDHC_TransferDataTuning) +#define SDMMCHOST_ENABLE_BOOT_FLAG(data) (data.dataType = kUSDHC_TransferDataBoot) +#define SDMMCHOST_ENABLE_BOOT_CONTINOUS_FLAG(data) (data.dataType = kUSDHC_TransferDataBootcontinous) +#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_SIZE(config) (config->blockSize) +#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_COUNT(config) (config->blockCount) +#define SDMMCHOST_GET_HOST_CONFIG_BOOT_MODE(config) (config->bootMode) +#define SDMMCHOST_EMPTY_CMD_FLAG(command) (command.type = kCARD_CommandTypeEmpty) +/*! @brief USDHC host capability*/ +enum _host_capability +{ + kSDMMCHOST_SupportAdma = kUSDHC_SupportAdmaFlag, + kSDMMCHOST_SupportHighSpeed = kUSDHC_SupportHighSpeedFlag, + kSDMMCHOST_SupportDma = kUSDHC_SupportDmaFlag, + kSDMMCHOST_SupportSuspendResume = kUSDHC_SupportSuspendResumeFlag, + kSDMMCHOST_SupportV330 = kUSDHC_SupportV330Flag, /* this define should depend on your board config */ + kSDMMCHOST_SupportV300 = kUSDHC_SupportV300Flag, /* this define should depend on your board config */ +#if defined(BOARD_SD_SUPPORT_180V) && !BOARD_SD_SUPPORT_180V + kSDMMCHOST_SupportV180 = SDMMCHOST_NOT_SUPPORT, /* this define should depend on you board config */ +#else + kSDMMCHOST_SupportV180 = kUSDHC_SupportV180Flag, /* this define should depend on you board config */ +#endif + kSDMMCHOST_SupportV120 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_Support4BitBusWidth = kUSDHC_Support4BitFlag, +#if defined(BOARD_MMC_SUPPORT_8BIT_BUS) +#if BOARD_MMC_SUPPORT_8BIT_BUS + kSDMMCHOST_Support8BitBusWidth = kUSDHC_Support8BitFlag, +#else + kSDMMCHOST_Support8BitBusWidth = SDMMCHOST_NOT_SUPPORT, +#endif +#else + kSDMMCHOST_Support8BitBusWidth = kUSDHC_Support8BitFlag, +#endif + kSDMMCHOST_SupportDDR50 = kUSDHC_SupportDDR50Flag, + kSDMMCHOST_SupportSDR104 = kUSDHC_SupportSDR104Flag, + kSDMMCHOST_SupportSDR50 = kUSDHC_SupportSDR50Flag, + kSDMMCHOST_SupportHS200 = kUSDHC_SupportSDR104Flag, +#if FSL_FEATURE_USDHC_HAS_HS400_MODE + kSDMMCHOST_SupportHS400 = SDMMCHOST_SUPPORT +#else + kSDMMCHOST_SupportHS400 = SDMMCHOST_NOT_SUPPORT, +#endif +}; + +/* Endian mode. */ +#define USDHC_ENDIAN_MODE kUSDHC_EndianModeLittle + +/* DMA mode */ +#define USDHC_DMA_MODE kUSDHC_DmaModeAdma2 +/* address align */ +#define SDMMCHOST_DMA_BUFFER_ADDR_ALIGN (USDHC_ADMA2_ADDRESS_ALIGN) + +/* Read/write watermark level. The bigger value indicates DMA has higher read/write performance. */ +#define USDHC_READ_WATERMARK_LEVEL (0x80U) +#define USDHC_WRITE_WATERMARK_LEVEL (0x80U) + +/* ADMA table length united as word. + * + * One ADMA2 table item occupy two words which can transfer maximum 0xFFFFU bytes one time. + * The more data to be transferred in one time, the bigger value of SDHC_ADMA_TABLE_WORDS need to be set. + */ +#define USDHC_ADMA_TABLE_WORDS (8U) /* define the ADMA descriptor table length */ +#define USDHC_ADMA2_ADDR_ALIGN (4U) /* define the ADMA2 descriptor table addr align size */ +#define USDHC_READ_BURST_LEN (8U) /*!< number of words USDHC read in a single burst */ +#define USDHC_WRITE_BURST_LEN (8U) /*!< number of words USDHC write in a single burst */ +#define USDHC_DATA_TIMEOUT (0xFU) /*!< data timeout counter value */ + +#endif /* (defined(FSL_FEATURE_SOC_SDHC_COUNT) && (FSL_FEATURE_SOC_SDHC_COUNT > 0U)) */ + +/*! @brief card detect callback definition */ +typedef void (*sdmmchost_cd_callback_t)(bool isInserted, void *userData); + +/*! @brief host Endian mode +* corresponding to driver define +*/ +enum _sdmmchost_endian_mode +{ + kSDMMCHOST_EndianModeBig = 0U, /*!< Big endian mode */ + kSDMMCHOST_EndianModeHalfWordBig = 1U, /*!< Half word big endian mode */ + kSDMMCHOST_EndianModeLittle = 2U, /*!< Little endian mode */ +}; + +/*! @brief sd card detect type */ +typedef enum _sdmmchost_detect_card_type +{ + kSDMMCHOST_DetectCardByGpioCD, /*!< sd card detect by CD pin through GPIO */ + kSDMMCHOST_DetectCardByHostCD, /*!< sd card detect by CD pin through host */ + kSDMMCHOST_DetectCardByHostDATA3, /*!< sd card detect by DAT3 pin through host */ +} sdmmchost_detect_card_type_t; + +/*! @brief sd card detect */ +typedef struct _sdmmchost_detect_card +{ + sdmmchost_detect_card_type_t cdType; /*!< card detect type */ + uint32_t cdTimeOut_ms; /*!< card detect timeout which allow 0 - 0xFFFFFFF, value 0 will return immediately, value + 0xFFFFFFFF will block until card is insert */ + + sdmmchost_cd_callback_t cardInserted; /*!< card inserted callback which is meaningful for interrupt case */ + sdmmchost_cd_callback_t cardRemoved; /*!< card removed callback which is meaningful for interrupt case */ + + void *userData; /*!< user data */ +} sdmmchost_detect_card_t; + +/*! @brief card power control function pointer */ +typedef void (*sdmmchost_pwr_t)(void); + +/*! @brief card power control */ +typedef struct _sdmmchost_pwr_card +{ + sdmmchost_pwr_t powerOn; /*!< power on function pointer */ + uint32_t powerOnDelay_ms; /*!< power on delay */ + + sdmmchost_pwr_t powerOff; /*!< power off function pointer */ + uint32_t powerOffDelay_ms; /*!< power off delay */ +} sdmmchost_pwr_card_t; + +/******************************************************************************* + * API + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name adaptor function + * @{ + */ + +/*! + * @brief host not support function, this function is used for host not support feature + * @param void parameter ,used to avoid build warning + * @retval kStatus_Fail ,host do not suppport + */ +static inline status_t SDMMCHOST_NotSupport(void *parameter) +{ + parameter = parameter; + return kStatus_Success; +} + +/*! + * @brief Detect card insert, only need for SD cases. + * @param base the pointer to host base address + * @param cd card detect configuration + * @param waitCardStatus status which user want to wait + * @retval kStatus_Success detect card insert + * @retval kStatus_Fail card insert event fail + */ +status_t SDMMCHOST_WaitCardDetectStatus(SDMMCHOST_TYPE *hostBase, + const sdmmchost_detect_card_t *cd, + bool waitCardStatus); + +/*! + * @brief check card is present or not. + * @retval true card is present + * @retval false card is not present + */ +bool SDMMCHOST_IsCardPresent(void); + +/*! + * @brief Init host controller. + * @param host the pointer to host structure in card structure. + * @param userData specific user data + * @retval kStatus_Success host init success + * @retval kStatus_Fail event fail + */ +status_t SDMMCHOST_Init(SDMMCHOST_CONFIG *host, void *userData); + +/*! + * @brief reset host controller. + * @param host base address. + */ +void SDMMCHOST_Reset(SDMMCHOST_TYPE *base); + +/*! + * @brief host controller error recovery. + * @param host base address. + */ +void SDMMCHOST_ErrorRecovery(SDMMCHOST_TYPE *base); + +/*! + * @brief Deinit host controller. + * @param host the pointer to host structure in card structure. + */ +void SDMMCHOST_Deinit(void *host); + +/*! + * @brief host power off card function. + * @param base host base address. + * @param pwr depend on user define power configuration. + */ +void SDMMCHOST_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr); + +/*! + * @brief host power on card function. + * @param base host base address. + * @param pwr depend on user define power configuration. + */ +void SDMMCHOST_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr); + +/*! + * @brief SDMMC host delay function. + * @param milliseconds delay counter. + */ +void SDMMCHOST_Delay(uint32_t milliseconds); + +/* @} */ + +#if defined(__cplusplus) +} +#endif + +#endif /* _FSL_SDMMC_HOST_H */ diff --git a/target/fsl_sdmmc_spec.h b/target/fsl_sdmmc_spec.h new file mode 100644 index 0000000..c20ec2e --- /dev/null +++ b/target/fsl_sdmmc_spec.h @@ -0,0 +1,1164 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_SDMMC_SPEC_H_ +#define _FSL_SDMMC_SPEC_H_ + +#include + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/*! @brief SD/MMC card initialization clock frequency */ +#define SDMMC_CLOCK_400KHZ (400000U) +/*! @brief SD card bus frequency 1 in high-speed mode */ +#define SD_CLOCK_25MHZ (25000000U) +/*! @brief SD card bus frequency 2 in high-speed mode */ +#define SD_CLOCK_50MHZ (50000000U) +/*! @brief SD card bus frequency in SDR50 mode */ +#define SD_CLOCK_100MHZ (100000000U) +/*! @brief SD card bus frequency in SDR104 mode */ +#define SD_CLOCK_208MHZ (208000000U) +/*! @brief MMC card bus frequency 1 in high-speed mode */ +#define MMC_CLOCK_26MHZ (26000000U) +/*! @brief MMC card bus frequency 2 in high-speed mode */ +#define MMC_CLOCK_52MHZ (52000000U) +/*! @brief MMC card bus frequency in high-speed DDR52 mode */ +#define MMC_CLOCK_DDR52 (52000000U) +/*! @brief MMC card bus frequency in high-speed HS200 mode */ +#define MMC_CLOCK_HS200 (200000000U) +/*! @brief MMC card bus frequency in high-speed HS400 mode */ +#define MMC_CLOCK_HS400 (400000000U) + +/*!@brief mask convert */ +#define SDMMC_MASK(bit) (1U << (bit)) + +/*! @brief Card status bit in R1 */ +enum _sdmmc_r1_card_status_flag +{ + kSDMMC_R1OutOfRangeFlag = 31, /*!< Out of range status bit */ + kSDMMC_R1AddressErrorFlag = 30, /*!< Address error status bit */ + kSDMMC_R1BlockLengthErrorFlag = 29, /*!< Block length error status bit */ + kSDMMC_R1EraseSequenceErrorFlag = 28, /*!< Erase sequence error status bit */ + kSDMMC_R1EraseParameterErrorFlag = 27, /*!< Erase parameter error status bit */ + kSDMMC_R1WriteProtectViolationFlag = 26, /*!< Write protection violation status bit */ + kSDMMC_R1CardIsLockedFlag = 25, /*!< Card locked status bit */ + kSDMMC_R1LockUnlockFailedFlag = 24, /*!< lock/unlock error status bit */ + kSDMMC_R1CommandCrcErrorFlag = 23, /*!< CRC error status bit */ + kSDMMC_R1IllegalCommandFlag = 22, /*!< Illegal command status bit */ + kSDMMC_R1CardEccFailedFlag = 21, /*!< Card ecc error status bit */ + kSDMMC_R1CardControllerErrorFlag = 20, /*!< Internal card controller error status bit */ + kSDMMC_R1ErrorFlag = 19, /*!< A general or an unknown error status bit */ + kSDMMC_R1CidCsdOverwriteFlag = 16, /*!< Cid/csd overwrite status bit */ + kSDMMC_R1WriteProtectEraseSkipFlag = 15, /*!< Write protection erase skip status bit */ + kSDMMC_R1CardEccDisabledFlag = 14, /*!< Card ecc disabled status bit */ + kSDMMC_R1EraseResetFlag = 13, /*!< Erase reset status bit */ + kSDMMC_R1ReadyForDataFlag = 8, /*!< Ready for data status bit */ + kSDMMC_R1SwitchErrorFlag = 7, /*!< Switch error status bit */ + kSDMMC_R1ApplicationCommandFlag = 5, /*!< Application command enabled status bit */ + kSDMMC_R1AuthenticationSequenceErrorFlag = 3, /*!< error in the sequence of authentication process */ +}; + +/*! @brief R1 all the error flag */ +#define SDMMC_R1_ALL_ERROR_FLAG \ + (SDMMC_MASK(kSDMMC_R1OutOfRangeFlag) | SDMMC_MASK(kSDMMC_R1AddressErrorFlag) | \ + SDMMC_MASK(kSDMMC_R1BlockLengthErrorFlag) | SDMMC_MASK(kSDMMC_R1EraseSequenceErrorFlag) | \ + SDMMC_MASK(kSDMMC_R1EraseParameterErrorFlag) | SDMMC_MASK(kSDMMC_R1WriteProtectViolationFlag) | \ + SDMMC_MASK(kSDMMC_R1CardIsLockedFlag) | SDMMC_MASK(kSDMMC_R1LockUnlockFailedFlag) | \ + SDMMC_MASK(kSDMMC_R1CommandCrcErrorFlag) | SDMMC_MASK(kSDMMC_R1IllegalCommandFlag) | \ + SDMMC_MASK(kSDMMC_R1CardEccFailedFlag) | SDMMC_MASK(kSDMMC_R1CardControllerErrorFlag) | \ + SDMMC_MASK(kSDMMC_R1ErrorFlag) | SDMMC_MASK(kSDMMC_R1CidCsdOverwriteFlag) | \ + SDMMC_MASK(kSDMMC_R1AuthenticationSequenceErrorFlag)) + +/*! @brief R1: current state */ +#define SDMMC_R1_CURRENT_STATE(x) (((x)&0x00001E00U) >> 9U) + +/*! @brief CURRENT_STATE filed in R1 */ +typedef enum _sdmmc_r1_current_state +{ + kSDMMC_R1StateIdle = 0U, /*!< R1: current state: idle */ + kSDMMC_R1StateReady = 1U, /*!< R1: current state: ready */ + kSDMMC_R1StateIdentify = 2U, /*!< R1: current state: identification */ + kSDMMC_R1StateStandby = 3U, /*!< R1: current state: standby */ + kSDMMC_R1StateTransfer = 4U, /*!< R1: current state: transfer */ + kSDMMC_R1StateSendData = 5U, /*!< R1: current state: sending data */ + kSDMMC_R1StateReceiveData = 6U, /*!< R1: current state: receiving data */ + kSDMMC_R1StateProgram = 7U, /*!< R1: current state: programming */ + kSDMMC_R1StateDisconnect = 8U, /*!< R1: current state: disconnect */ +} sdmmc_r1_current_state_t; + +/*! @brief Error bit in SPI mode R1 */ +enum _sdspi_r1_error_status_flag +{ + kSDSPI_R1InIdleStateFlag = (1U << 0U), /*!< In idle state */ + kSDSPI_R1EraseResetFlag = (1U << 1U), /*!< Erase reset */ + kSDSPI_R1IllegalCommandFlag = (1U << 2U), /*!< Illegal command */ + kSDSPI_R1CommandCrcErrorFlag = (1U << 3U), /*!< Com crc error */ + kSDSPI_R1EraseSequenceErrorFlag = (1U << 4U), /*!< Erase sequence error */ + kSDSPI_R1AddressErrorFlag = (1U << 5U), /*!< Address error */ + kSDSPI_R1ParameterErrorFlag = (1U << 6U), /*!< Parameter error */ +}; + +/*! @brief Error bit in SPI mode R2 */ +enum _sdspi_r2_error_status_flag +{ + kSDSPI_R2CardLockedFlag = (1U << 0U), /*!< Card is locked */ + kSDSPI_R2WriteProtectEraseSkip = (1U << 1U), /*!< Write protect erase skip */ + kSDSPI_R2LockUnlockFailed = (1U << 1U), /*!< Lock/unlock command failed */ + kSDSPI_R2ErrorFlag = (1U << 2U), /*!< Unknown error */ + kSDSPI_R2CardControllerErrorFlag = (1U << 3U), /*!< Card controller error */ + kSDSPI_R2CardEccFailedFlag = (1U << 4U), /*!< Card ecc failed */ + kSDSPI_R2WriteProtectViolationFlag = (1U << 5U), /*!< Write protect violation */ + kSDSPI_R2EraseParameterErrorFlag = (1U << 6U), /*!< Erase parameter error */ + kSDSPI_R2OutOfRangeFlag = (1U << 7U), /*!< Out of range */ + kSDSPI_R2CsdOverwriteFlag = (1U << 7U), /*!< CSD overwrite */ +}; + +/*! @brief The bit mask for COMMAND VERSION field in R7 */ +#define SDSPI_R7_VERSION_SHIFT (28U) +/*! @brief The bit mask for COMMAND VERSION field in R7 */ +#define SDSPI_R7_VERSION_MASK (0xFU) +/*! @brief The bit shift for VOLTAGE ACCEPTED field in R7 */ +#define SDSPI_R7_VOLTAGE_SHIFT (8U) +/*! @brief The bit mask for VOLTAGE ACCEPTED field in R7 */ +#define SDSPI_R7_VOLTAGE_MASK (0xFU) +/*! @brief The bit mask for VOLTAGE 2.7V to 3.6V field in R7 */ +#define SDSPI_R7_VOLTAGE_27_36_MASK (0x1U << SDSPI_R7_VOLTAGE_SHIFT) +/*! @brief The bit shift for ECHO field in R7 */ +#define SDSPI_R7_ECHO_SHIFT (0U) +/*! @brief The bit mask for ECHO field in R7 */ +#define SDSPI_R7_ECHO_MASK (0xFFU) + +/*! @brief Data error token mask */ +#define SDSPI_DATA_ERROR_TOKEN_MASK (0xFU) +/*! @brief Data Error Token mask bit */ +enum _sdspi_data_error_token +{ + kSDSPI_DataErrorTokenError = (1U << 0U), /*!< Data error */ + kSDSPI_DataErrorTokenCardControllerError = (1U << 1U), /*!< Card controller error */ + kSDSPI_DataErrorTokenCardEccFailed = (1U << 2U), /*!< Card ecc error */ + kSDSPI_DataErrorTokenOutOfRange = (1U << 3U), /*!< Out of range */ +}; + +/*! @brief Data Token */ +typedef enum _sdspi_data_token +{ + kSDSPI_DataTokenBlockRead = 0xFEU, /*!< Single block read, multiple block read */ + kSDSPI_DataTokenSingleBlockWrite = 0xFEU, /*!< Single block write */ + kSDSPI_DataTokenMultipleBlockWrite = 0xFCU, /*!< Multiple block write */ + kSDSPI_DataTokenStopTransfer = 0xFDU, /*!< Stop transmission */ +} sdspi_data_token_t; + +/* Data Response Token mask */ +#define SDSPI_DATA_RESPONSE_TOKEN_MASK (0x1FU) /*!< Mask for data response bits */ +/*! @brief Data Response Token */ +typedef enum _sdspi_data_response_token +{ + kSDSPI_DataResponseTokenAccepted = 0x05U, /*!< Data accepted */ + kSDSPI_DataResponseTokenCrcError = 0x0BU, /*!< Data rejected due to CRC error */ + kSDSPI_DataResponseTokenWriteError = 0x0DU, /*!< Data rejected due to write error */ +} sdspi_data_response_token_t; + +/*! @brief SD card individual commands */ +typedef enum _sd_command +{ + kSD_SendRelativeAddress = 3U, /*!< Send Relative Address */ + kSD_Switch = 6U, /*!< Switch Function */ + kSD_SendInterfaceCondition = 8U, /*!< Send Interface Condition */ + kSD_VoltageSwitch = 11U, /*!< Voltage Switch */ + kSD_SpeedClassControl = 20U, /*!< Speed Class control */ + kSD_EraseWriteBlockStart = 32U, /*!< Write Block Start */ + kSD_EraseWriteBlockEnd = 33U, /*!< Write Block End */ + kSD_SendTuningBlock = 19U, /*!< Send Tuning Block */ +} sd_command_t; + +/*! @brief SDSPI individual commands */ +typedef enum _sdspi_command +{ + kSDSPI_CommandCrc = 59U, /*!< Command crc protection on/off */ +} sdspi_command_t; + +/*! @brief SD card individual application commands */ +typedef enum _sd_application_command +{ + kSD_ApplicationSetBusWdith = 6U, /*!< Set Bus Width */ + kSD_ApplicationStatus = 13U, /*!< Send SD status */ + kSD_ApplicationSendNumberWriteBlocks = 22U, /*!< Send Number Of Written Blocks */ + kSD_ApplicationSetWriteBlockEraseCount = 23U, /*!< Set Write Block Erase Count */ + kSD_ApplicationSendOperationCondition = 41U, /*!< Send Operation Condition */ + kSD_ApplicationSetClearCardDetect = 42U, /*!< Set Connnect/Disconnect pull up on detect pin */ + kSD_ApplicationSendScr = 51U, /*!< Send Scr */ +} sd_application_command_t; + +/*! @brief SD card command class */ +enum _sdmmc_command_class +{ + kSDMMC_CommandClassBasic = (1U << 0U), /*!< Card command class 0 */ + kSDMMC_CommandClassBlockRead = (1U << 2U), /*!< Card command class 2 */ + kSDMMC_CommandClassBlockWrite = (1U << 4U), /*!< Card command class 4 */ + kSDMMC_CommandClassErase = (1U << 5U), /*!< Card command class 5 */ + kSDMMC_CommandClassWriteProtect = (1U << 6U), /*!< Card command class 6 */ + kSDMMC_CommandClassLockCard = (1U << 7U), /*!< Card command class 7 */ + kSDMMC_CommandClassApplicationSpecific = (1U << 8U), /*!< Card command class 8 */ + kSDMMC_CommandClassInputOutputMode = (1U << 9U), /*!< Card command class 9 */ + kSDMMC_CommandClassSwitch = (1U << 10U), /*!< Card command class 10 */ +}; + +/*! @brief OCR register in SD card */ +enum _sd_ocr_flag +{ + kSD_OcrPowerUpBusyFlag = 31, /*!< Power up busy status */ + kSD_OcrHostCapacitySupportFlag = 30, /*!< Card capacity status */ + kSD_OcrCardCapacitySupportFlag = kSD_OcrHostCapacitySupportFlag, /*!< Card capacity status */ + kSD_OcrSwitch18RequestFlag = 24, /*!< Switch to 1.8V request */ + kSD_OcrSwitch18AcceptFlag = kSD_OcrSwitch18RequestFlag, /*!< Switch to 1.8V accepted */ + kSD_OcrVdd27_28Flag = 15, /*!< VDD 2.7-2.8 */ + kSD_OcrVdd28_29Flag = 16, /*!< VDD 2.8-2.9 */ + kSD_OcrVdd29_30Flag = 17, /*!< VDD 2.9-3.0 */ + kSD_OcrVdd30_31Flag = 18, /*!< VDD 2.9-3.0 */ + kSD_OcrVdd31_32Flag = 19, /*!< VDD 3.0-3.1 */ + kSD_OcrVdd32_33Flag = 20, /*!< VDD 3.1-3.2 */ + kSD_OcrVdd33_34Flag = 21, /*!< VDD 3.2-3.3 */ + kSD_OcrVdd34_35Flag = 22, /*!< VDD 3.3-3.4 */ + kSD_OcrVdd35_36Flag = 23, /*!< VDD 3.4-3.5 */ +}; + +/*! @brief SD card specification version number */ +enum _sd_specification_version +{ + kSD_SpecificationVersion1_0 = (1U << 0U), /*!< SD card version 1.0-1.01 */ + kSD_SpecificationVersion1_1 = (1U << 1U), /*!< SD card version 1.10 */ + kSD_SpecificationVersion2_0 = (1U << 2U), /*!< SD card version 2.00 */ + kSD_SpecificationVersion3_0 = (1U << 3U), /*!< SD card version 3.0 */ +}; + +/*! @brief SD card bus width */ +typedef enum _sd_data_bus_width +{ + kSD_DataBusWidth1Bit = 0U, /*!< SD data bus width 1-bit mode */ + kSD_DataBusWidth4Bit = 1U, /*!< SD data bus width 4-bit mode */ +} sd_data_bus_width_t; + +/*! @brief SD card switch mode */ +typedef enum _sd_switch_mode +{ + kSD_SwitchCheck = 0U, /*!< SD switch mode 0: check function */ + kSD_SwitchSet = 1U, /*!< SD switch mode 1: set function */ +} sd_switch_mode_t; + +/*! @brief SD card CSD register flags */ +enum _sd_csd_flag +{ + kSD_CsdReadBlockPartialFlag = (1U << 0U), /*!< Partial blocks for read allowed [79:79] */ + kSD_CsdWriteBlockMisalignFlag = (1U << 1U), /*!< Write block misalignment [78:78] */ + kSD_CsdReadBlockMisalignFlag = (1U << 2U), /*!< Read block misalignment [77:77] */ + kSD_CsdDsrImplementedFlag = (1U << 3U), /*!< DSR implemented [76:76] */ + kSD_CsdEraseBlockEnabledFlag = (1U << 4U), /*!< Erase single block enabled [46:46] */ + kSD_CsdWriteProtectGroupEnabledFlag = (1U << 5U), /*!< Write protect group enabled [31:31] */ + kSD_CsdWriteBlockPartialFlag = (1U << 6U), /*!< Partial blocks for write allowed [21:21] */ + kSD_CsdFileFormatGroupFlag = (1U << 7U), /*!< File format group [15:15] */ + kSD_CsdCopyFlag = (1U << 8U), /*!< Copy flag [14:14] */ + kSD_CsdPermanentWriteProtectFlag = (1U << 9U), /*!< Permanent write protection [13:13] */ + kSD_CsdTemporaryWriteProtectFlag = (1U << 10U), /*!< Temporary write protection [12:12] */ +}; + +/*! @brief SD card SCR register flags */ +enum _sd_scr_flag +{ + kSD_ScrDataStatusAfterErase = (1U << 0U), /*!< Data status after erases [55:55] */ + kSD_ScrSdSpecification3 = (1U << 1U), /*!< Specification version 3.00 or higher [47:47]*/ +}; + +/*! @brief SD timing function number */ +enum _sd_timing_function +{ + kSD_FunctionSDR12Deafult = 0U, /*!< SDR12 mode & default*/ + kSD_FunctionSDR25HighSpeed = 1U, /*!< SDR25 & high speed*/ + kSD_FunctionSDR50 = 2U, /*!< SDR50 mode*/ + kSD_FunctionSDR104 = 3U, /*!< SDR104 mode*/ + kSD_FunctionDDR50 = 4U, /*!< DDR50 mode*/ +}; + +/*! @brief SD group number */ +enum _sd_group_num +{ + kSD_GroupTimingMode = 0U, /*!< acess mode group*/ + kSD_GroupCommandSystem = 1U, /*!< command system group*/ + kSD_GroupDriverStrength = 2U, /*!< driver strength group*/ + kSD_GroupCurrentLimit = 3U, /*!< current limit group*/ +}; + +/*! @brief SD card timing mode flags */ +typedef enum _sd_timing_mode +{ + kSD_TimingSDR12DefaultMode = 0U, /*!< Identification mode & SDR12 */ + kSD_TimingSDR25HighSpeedMode = 1U, /*!< High speed mode & SDR25 */ + kSD_TimingSDR50Mode = 2U, /*!< SDR50 mode*/ + kSD_TimingSDR104Mode = 3U, /*!< SDR104 mode */ + kSD_TimingDDR50Mode = 4U, /*!< DDR50 mode */ +} sd_timing_mode_t; + +/*! @brief SD card driver strength */ +typedef enum _sd_driver_strength +{ + kSD_DriverStrengthTypeB = 0U, /*!< default driver strength*/ + kSD_DriverStrengthTypeA = 1U, /*!< driver strength TYPE A */ + kSD_DriverStrengthTypeC = 2U, /*!< driver strength TYPE C */ + kSD_DriverStrengthTypeD = 3U, /*!< driver strength TYPE D */ +} sd_driver_strength_t; + +/*! @brief SD card current limit */ +typedef enum _sd_max_current +{ + kSD_CurrentLimit200MA = 0U, /*!< default current limit */ + kSD_CurrentLimit400MA = 1U, /*!< current limit to 400MA */ + kSD_CurrentLimit600MA = 2U, /*!< current limit to 600MA */ + kSD_CurrentLimit800MA = 3U, /*!< current limit to 800MA */ +} sd_max_current_t; + +/*! @brief SD/MMC card common commands */ +typedef enum _sdmmc_command +{ + kSDMMC_GoIdleState = 0U, /*!< Go Idle State */ + kSDMMC_AllSendCid = 2U, /*!< All Send CID */ + kSDMMC_SetDsr = 4U, /*!< Set DSR */ + kSDMMC_SelectCard = 7U, /*!< Select Card */ + kSDMMC_SendCsd = 9U, /*!< Send CSD */ + kSDMMC_SendCid = 10U, /*!< Send CID */ + kSDMMC_StopTransmission = 12U, /*!< Stop Transmission */ + kSDMMC_SendStatus = 13U, /*!< Send Status */ + kSDMMC_GoInactiveState = 15U, /*!< Go Inactive State */ + kSDMMC_SetBlockLength = 16U, /*!< Set Block Length */ + kSDMMC_ReadSingleBlock = 17U, /*!< Read Single Block */ + kSDMMC_ReadMultipleBlock = 18U, /*!< Read Multiple Block */ + kSDMMC_SetBlockCount = 23U, /*!< Set Block Count */ + kSDMMC_WriteSingleBlock = 24U, /*!< Write Single Block */ + kSDMMC_WriteMultipleBlock = 25U, /*!< Write Multiple Block */ + kSDMMC_ProgramCsd = 27U, /*!< Program CSD */ + kSDMMC_SetWriteProtect = 28U, /*!< Set Write Protect */ + kSDMMC_ClearWriteProtect = 29U, /*!< Clear Write Protect */ + kSDMMC_SendWriteProtect = 30U, /*!< Send Write Protect */ + kSDMMC_Erase = 38U, /*!< Erase */ + kSDMMC_LockUnlock = 42U, /*!< Lock Unlock */ + kSDMMC_ApplicationCommand = 55U, /*!< Send Application Command */ + kSDMMC_GeneralCommand = 56U, /*!< General Purpose Command */ + kSDMMC_ReadOcr = 58U, /*!< Read OCR */ +} sdmmc_command_t; + +/*! @brief sdio card cccr register addr */ +enum _sdio_cccr_reg +{ + kSDIO_RegCCCRSdioVer = 0x00U, /*!< CCCR & SDIO version*/ + kSDIO_RegSDVersion = 0x01U, /*!< SD version */ + kSDIO_RegIOEnable = 0x02U, /*!< io enable register */ + kSDIO_RegIOReady = 0x03U, /*!< io ready register */ + kSDIO_RegIOIntEnable = 0x04U, /*!< io interrupt enable register */ + kSDIO_RegIOIntPending = 0x05U, /*!< io interrupt pending register */ + kSDIO_RegIOAbort = 0x06U, /*!< io abort register */ + kSDIO_RegBusInterface = 0x07U, /*!< bus interface register */ + kSDIO_RegCardCapability = 0x08U, /*!< card capability register */ + kSDIO_RegCommonCISPointer = 0x09U, /*!< common CIS pointer register */ + kSDIO_RegBusSuspend = 0x0C, /*!< bus suspend register */ + kSDIO_RegFunctionSelect = 0x0DU, /*!< function select register */ + kSDIO_RegExecutionFlag = 0x0EU, /*!< execution flag register */ + kSDIO_RegReadyFlag = 0x0FU, /*!< ready flag register */ + kSDIO_RegFN0BlockSizeLow = 0x10U, /*!< FN0 block size register */ + kSDIO_RegFN0BlockSizeHigh = 0x11U, /*!< FN0 block size register */ + kSDIO_RegPowerControl = 0x12U, /*!< power control register */ + kSDIO_RegHighSpeed = 0x13U, /*!< high speed register */ +}; + +/*! @brief sdio card individual commands */ +typedef enum _sdio_command +{ + kSDIO_SendRelativeAddress = 3U, /*!< send relative address */ + kSDIO_SendOperationCondition = 5U, /*!< send operation condition */ + kSDIO_SendInterfaceCondition = 8U, /*!< send interface condition */ + kSDIO_RWIODirect = 52U, /*!< read/write IO direct command */ + kSDIO_RWIOExtended = 53U, /*!< read/write IO extended command */ +} sdio_command_t; + +/*! @brief sdio card individual commands */ +typedef enum _sdio_func_num +{ + kSDIO_FunctionNum0, /*!< sdio function0*/ + kSDIO_FunctionNum1, /*!< sdio function1*/ + kSDIO_FunctionNum2, /*!< sdio function2*/ + kSDIO_FunctionNum3, /*!< sdio function3*/ + kSDIO_FunctionNum4, /*!< sdio function4*/ + kSDIO_FunctionNum5, /*!< sdio function5*/ + kSDIO_FunctionNum6, /*!< sdio function6*/ + kSDIO_FunctionNum7, /*!< sdio function7*/ + kSDIO_FunctionMemory, /*!< for combo card*/ +} sdio_func_num_t; + +#define SDIO_CMD_ARGUMENT_RW_POS (31U) /*!< read/write flag position */ +#define SDIO_CMD_ARGUMENT_FUNC_NUM_POS (28U) /*!< function number position */ +#define SDIO_DIRECT_CMD_ARGUMENT_RAW_POS (27U) /*!< direct raw flag position */ +#define SDIO_CMD_ARGUMENT_REG_ADDR_POS (9U) /*!< direct reg addr position */ +#define SDIO_CMD_ARGUMENT_REG_ADDR_MASK (0x1FFFFU) /*!< direct reg addr mask */ +#define SDIO_DIRECT_CMD_DATA_MASK (0xFFU) /*!< data mask */ + +#define SDIO_EXTEND_CMD_ARGUMENT_BLOCK_MODE_POS (27U) /*!< extended command argument block mode bit position */ +#define SDIO_EXTEND_CMD_ARGUMENT_OP_CODE_POS (26U) /*!< extended command argument OP Code bit position */ +#define SDIO_EXTEND_CMD_BLOCK_MODE_MASK (0x08000000U) /*!< block mode mask */ +#define SDIO_EXTEND_CMD_OP_CODE_MASK (0x04000000U) /*!< op code mask */ +#define SDIO_EXTEND_CMD_COUNT_MASK (0x1FFU) /*!< byte/block count mask */ +#define SDIO_MAX_BLOCK_SIZE (2048U) /*!< max block size */ +#define SDIO_FBR_BASE(x) (x * 0x100U) /*!< function basic register */ +#define SDIO_TPL_CODE_END (0xFFU) /*!< tuple end */ +#define SDIO_TPL_CODE_MANIFID (0x20U) /*!< manufacturer ID */ +#define SDIO_TPL_CODE_FUNCID (0x21U) /*!< function ID */ +#define SDIO_TPL_CODE_FUNCE (0x22U) /*!< function extension tuple*/ +/*! @brief sdio command response flag */ +enum _sdio_status_flag +{ + kSDIO_StatusCmdCRCError = 0x8000U, /*!< the CRC check of the previous cmd fail*/ + kSDIO_StatusIllegalCmd = 0x4000U, /*!< cmd illegal for the card state */ + kSDIO_StatusR6Error = 0x2000U, /*!< special for R6 error status */ + kSDIO_StatusError = 0x0800U, /*!< A general or an unknown error occurred */ + kSDIO_StatusFunctionNumError = 0x0200U, /*!< invail function error */ + kSDIO_StatusOutofRange = 0x0100U, /*!< cmd argument was out of the allowed range*/ +}; + +/*! @brief sdio operation condition flag */ +enum _sdio_ocr_flag +{ + kSDIO_OcrPowerUpBusyFlag = 31, /*!< Power up busy status */ + kSDIO_OcrIONumber = 28, /*!< number of IO function */ + kSDIO_OcrMemPresent = 27, /*!< memory present flag */ + + kSDIO_OcrVdd20_21Flag = 8, /*!< VDD 2.0-2.1 */ + kSDIO_OcrVdd21_22Flag = 9, /*!< VDD 2.1-2.2 */ + kSDIO_OcrVdd22_23Flag = 10, /*!< VDD 2.2-2.3 */ + kSDIO_OcrVdd23_24Flag = 11, /*!< VDD 2.3-2.4 */ + kSDIO_OcrVdd24_25Flag = 12, /*!< VDD 2.4-2.5 */ + kSDIO_OcrVdd25_26Flag = 13, /*!< VDD 2.5-2.6 */ + kSDIO_OcrVdd26_27Flag = 14, /*!< VDD 2.6-2.7 */ + kSDIO_OcrVdd27_28Flag = 15, /*!< VDD 2.7-2.8 */ + kSDIO_OcrVdd28_29Flag = 16, /*!< VDD 2.8-2.9 */ + kSDIO_OcrVdd29_30Flag = 17, /*!< VDD 2.9-3.0 */ + kSDIO_OcrVdd30_31Flag = 18, /*!< VDD 2.9-3.0 */ + kSDIO_OcrVdd31_32Flag = 19, /*!< VDD 3.0-3.1 */ + kSDIO_OcrVdd32_33Flag = 20, /*!< VDD 3.1-3.2 */ + kSDIO_OcrVdd33_34Flag = 21, /*!< VDD 3.2-3.3 */ + kSDIO_OcrVdd34_35Flag = 22, /*!< VDD 3.3-3.4 */ + kSDIO_OcrVdd35_36Flag = 23, /*!< VDD 3.4-3.5 */ +}; + +/*! @brief sdio capability flag */ +enum _sdio_capability_flag +{ + kSDIO_CCCRSupportDirectCmdDuringDataTrans = (1U << 0U), /*!< support direct cmd during data transfer */ + kSDIO_CCCRSupportMultiBlock = (1U << 1U), /*!< support multi block mode */ + kSDIO_CCCRSupportReadWait = (1U << 2U), /*!< support read wait */ + kSDIO_CCCRSupportSuspendResume = (1U << 3U), /*!< support suspend resume */ + kSDIO_CCCRSupportIntDuring4BitDataTrans = (1U << 4U), /*!< support interrupt during 4-bit data transfer */ + kSDIO_CCCRSupportLowSpeed1Bit = (1U << 6U), /*!< support low speed 1bit mode */ + kSDIO_CCCRSupportLowSpeed4Bit = (1U << 7U), /*!< support low speed 4bit mode */ + kSDIO_CCCRSupportMasterPowerControl = (1U << 8U), /*!< support master power control */ + kSDIO_CCCRSupportHighSpeed = (1U << 9U), /*!< support high speed */ + kSDIO_CCCRSupportContinuousSPIInt = (1U << 10U), /*!< support continuous SPI interrupt */ +}; + +/*! @brief sdio fbr flag */ +enum _sdio_fbr_flag +{ + kSDIO_FBRSupportCSA = (1U << 0U), /*!< function support CSA */ + kSDIO_FBRSupportPowerSelection = (1U << 1U), /*!< function support power selection */ +}; + +/*! @brief sdio bus width */ +typedef enum _sdio_bus_width +{ + kSDIO_DataBus1Bit = 0x00U, /*!< 1bit bus mode */ + kSDIO_DataBus4Bit = 0X02U, /*!< 4 bit bus mode*/ +} sdio_bus_width_t; + +/*! @brief MMC card individual commands */ +typedef enum _mmc_command +{ + kMMC_SendOperationCondition = 1U, /*!< Send Operation Condition */ + kMMC_SetRelativeAddress = 3U, /*!< Set Relative Address */ + kMMC_SleepAwake = 5U, /*!< Sleep Awake */ + kMMC_Switch = 6U, /*!< Switch */ + kMMC_SendExtendedCsd = 8U, /*!< Send EXT_CSD */ + kMMC_ReadDataUntilStop = 11U, /*!< Read Data Until Stop */ + kMMC_BusTestRead = 14U, /*!< Test Read */ + kMMC_SendingBusTest = 19U, /*!< test bus width cmd*/ + kMMC_WriteDataUntilStop = 20U, /*!< Write Data Until Stop */ + kMMC_SendTuningBlock = 21U, /*!< MMC sending tuning block */ + kMMC_ProgramCid = 26U, /*!< Program CID */ + kMMC_EraseGroupStart = 35U, /*!< Erase Group Start */ + kMMC_EraseGroupEnd = 36U, /*!< Erase Group End */ + kMMC_FastInputOutput = 39U, /*!< Fast IO */ + kMMC_GoInterruptState = 40U, /*!< Go interrupt State */ +} mmc_command_t; + +/*! @brief MMC card classified as voltage range */ +typedef enum _mmc_classified_voltage +{ + kMMC_ClassifiedVoltageHigh = 0U, /*!< High-voltage MMC card */ + kMMC_ClassifiedVoltageDual = 1U, /*!< Dual-voltage MMC card */ +} mmc_classified_voltage_t; + +/*! @brief MMC card classified as density level */ +typedef enum _mmc_classified_density +{ + kMMC_ClassifiedDensityWithin2GB = 0U, /*!< Density byte is less than or equal 2GB */ + kMMC_ClassifiedDensityHigher2GB = 1U, /* Density byte is higher than 2GB */ +} mmc_classified_density_t; + +/*! @brief The bit mask for VOLTAGE WINDOW 1.70V to 1.95V field in OCR */ +#define MMC_OCR_V170TO195_SHIFT (7U) +/*! @brief The bit mask for VOLTAGE WINDOW 1.70V to 1.95V field in OCR */ +#define MMC_OCR_V170TO195_MASK (0x00000080U) +/*! @brief The bit shift for VOLTAGE WINDOW 2.00V to 2.60V field in OCR */ +#define MMC_OCR_V200TO260_SHIFT (8U) +/*! @brief The bit mask for VOLTAGE WINDOW 2.00V to 2.60V field in OCR */ +#define MMC_OCR_V200TO260_MASK (0x00007F00U) +/*! @brief The bit shift for VOLTAGE WINDOW 2.70V to 3.60V field in OCR */ +#define MMC_OCR_V270TO360_SHIFT (15U) +/*! @brief The bit mask for VOLTAGE WINDOW 2.70V to 3.60V field in OCR */ +#define MMC_OCR_V270TO360_MASK (0x00FF8000U) +/*! @brief The bit shift for ACCESS MODE field in OCR */ +#define MMC_OCR_ACCESS_MODE_SHIFT (29U) +/*! @brief The bit mask for ACCESS MODE field in OCR */ +#define MMC_OCR_ACCESS_MODE_MASK (0x60000000U) +/*! @brief The bit shift for BUSY field in OCR */ +#define MMC_OCR_BUSY_SHIFT (31U) +/*! @brief The bit mask for BUSY field in OCR */ +#define MMC_OCR_BUSY_MASK (1U << MMC_OCR_BUSY_SHIFT) + +/*! @brief MMC card access mode(Access mode in OCR). */ +typedef enum _mmc_access_mode +{ + kMMC_AccessModeByte = 0U, /*!< The card should be accessed as byte */ + kMMC_AccessModeSector = 2U, /*!< The card should be accessed as sector */ +} mmc_access_mode_t; + +/*! @brief MMC card voltage window(VDD voltage window in OCR). */ +typedef enum _mmc_voltage_window +{ + kMMC_VoltageWindowNone = 0U, /*!< voltage window is not define by user*/ + kMMC_VoltageWindow120 = 0x01U, /*!< Voltage window is 1.20V */ + kMMC_VoltageWindow170to195 = 0x02U, /*!< Voltage window is 1.70V to 1.95V */ + kMMC_VoltageWindows270to360 = 0x1FFU, /*!< Voltage window is 2.70V to 3.60V */ +} mmc_voltage_window_t; + +/*! @brief CSD structure version(CSD_STRUCTURE in CSD). */ +typedef enum _mmc_csd_structure_version +{ + kMMC_CsdStrucureVersion10 = 0U, /*!< CSD version No. 1.0 */ + kMMC_CsdStrucureVersion11 = 1U, /*!< CSD version No. 1.1 */ + kMMC_CsdStrucureVersion12 = 2U, /*!< CSD version No. 1.2 */ + kMMC_CsdStrucureVersionInExtcsd = 3U, /*!< Version coded in Extended CSD */ +} mmc_csd_structure_version_t; + +/*! @brief MMC card specification version(SPEC_VERS in CSD). */ +typedef enum _mmc_specification_version +{ + kMMC_SpecificationVersion0 = 0U, /*!< Allocated by MMCA */ + kMMC_SpecificationVersion1 = 1U, /*!< Allocated by MMCA */ + kMMC_SpecificationVersion2 = 2U, /*!< Allocated by MMCA */ + kMMC_SpecificationVersion3 = 3U, /*!< Allocated by MMCA */ + kMMC_SpecificationVersion4 = 4U, /*!< Version 4.1/4.2/4.3/4.41-4.5-4.51-5.0 */ +} mmc_specification_version_t; + +/*! @brief The bit shift for FREQUENCY UNIT field in TRANSFER SPEED(TRAN-SPEED in Extended CSD) */ +#define MMC_TRANSFER_SPEED_FREQUENCY_UNIT_SHIFT (0U) +/*! @brief The bit mask for FRQEUENCY UNIT in TRANSFER SPEED */ +#define MMC_TRANSFER_SPEED_FREQUENCY_UNIT_MASK (0x07U) +/*! @brief The bit shift for MULTIPLIER field in TRANSFER SPEED */ +#define MMC_TRANSFER_SPEED_MULTIPLIER_SHIFT (3U) +/*! @brief The bit mask for MULTIPLIER field in TRANSFER SPEED */ +#define MMC_TRANSFER_SPEED_MULTIPLIER_MASK (0x78U) + +/*! @brief Read the value of FREQUENCY UNIT in TRANSFER SPEED. */ +#define READ_MMC_TRANSFER_SPEED_FREQUENCY_UNIT(CSD) \ + (((CSD.transferSpeed) & MMC_TRANSFER_SPEED_FREQUENCY_UNIT_MASK) >> MMC_TRANSFER_SPEED_FREQUENCY_UNIT_SHIFT) +/*! @brief Read the value of MULTIPLER filed in TRANSFER SPEED. */ +#define READ_MMC_TRANSFER_SPEED_MULTIPLIER(CSD) \ + (((CSD.transferSpeed) & MMC_TRANSFER_SPEED_MULTIPLIER_MASK) >> MMC_TRANSFER_SPEED_MULTIPLIER_SHIFT) + +/*! @brief MMC card Extended CSD fix version(EXT_CSD_REV in Extended CSD) */ +enum _mmc_extended_csd_revision +{ + kMMC_ExtendedCsdRevision10 = 0U, /*!< Revision 1.0 */ + kMMC_ExtendedCsdRevision11 = 1U, /*!< Revision 1.1 */ + kMMC_ExtendedCsdRevision12 = 2U, /*!< Revision 1.2 */ + kMMC_ExtendedCsdRevision13 = 3U, /*!< Revision 1.3 MMC4.3*/ + kMMC_ExtendedCsdRevision14 = 4U, /*!< Revision 1.4 obsolete*/ + kMMC_ExtendedCsdRevision15 = 5U, /*!< Revision 1.5 MMC4.41*/ + kMMC_ExtendedCsdRevision16 = 6U, /*!< Revision 1.6 MMC4.5*/ + kMMC_ExtendedCsdRevision17 = 7U, /*!< Revision 1.7 MMC5.0 */ +}; + +/*! @brief MMC card command set(COMMAND_SET in Extended CSD) */ +typedef enum _mmc_command_set +{ + kMMC_CommandSetStandard = 0U, /*!< Standard MMC */ + kMMC_CommandSet1 = 1U, /*!< Command set 1 */ + kMMC_CommandSet2 = 2U, /*!< Command set 2 */ + kMMC_CommandSet3 = 3U, /*!< Command set 3 */ + kMMC_CommandSet4 = 4U, /*!< Command set 4 */ +} mmc_command_set_t; + +/*! @brief boot support(BOOT_INFO in Extended CSD) */ +enum _mmc_support_boot_mode +{ + kMMC_SupportAlternateBoot = 1U, /*!< support alternative boot mode*/ + kMMC_SupportDDRBoot = 2U, /*!< support DDR boot mode*/ + kMMC_SupportHighSpeedBoot = 4U, /*!< support high speed boot mode*/ +}; +/*! @brief The power class value bit mask when bus in 4 bit mode */ +#define MMC_POWER_CLASS_4BIT_MASK (0x0FU) +/*! @brief The power class current value bit mask when bus in 8 bit mode */ +#define MMC_POWER_CLASS_8BIT_MASK (0xF0U) + +/*! @brief MMC card high-speed timing(HS_TIMING in Extended CSD) */ +typedef enum _mmc_high_speed_timing +{ + kMMC_HighSpeedTimingNone = 0U, /*!< MMC card using none high-speed timing */ + kMMC_HighSpeedTiming = 1U, /*!< MMC card using high-speed timing */ + kMMC_HighSpeed200Timing = 2U, /*!< MMC card high speed 200 timing*/ + kMMC_HighSpeed400Timing = 3U, /*!< MMC card high speed 400 timing*/ +} mmc_high_speed_timing_t; + +/*! @brief The number of data bus width type */ +#define MMC_DATA_BUS_WIDTH_TYPE_NUMBER (3U) +/*! @brief MMC card data bus width(BUS_WIDTH in Extended CSD) */ +typedef enum _mmc_data_bus_width +{ + kMMC_DataBusWidth1bit = 0U, /*!< MMC data bus width is 1 bit */ + kMMC_DataBusWidth4bit = 1U, /*!< MMC data bus width is 4 bits */ + kMMC_DataBusWidth8bit = 2U, /*!< MMC data bus width is 8 bits */ + kMMC_DataBusWidth4bitDDR = 5U, /*!< MMC data bus width is 4 bits ddr */ + kMMC_DataBusWidth8bitDDR = 6U, /*!< MMC data bus width is 8 bits ddr */ +} mmc_data_bus_width_t; + +/*! @brief MMC card boot partition enabled(BOOT_PARTITION_ENABLE in Extended CSD) */ +typedef enum _mmc_boot_partition_enable +{ + kMMC_BootPartitionEnableNot = 0U, /*!< Device not boot enabled (default) */ + kMMC_BootPartitionEnablePartition1 = 1U, /*!< Boot partition 1 enabled for boot */ + kMMC_BootPartitionEnablePartition2 = 2U, /*!< Boot partition 2 enabled for boot */ + kMMC_BootPartitionEnableUserAera = 7U, /*!< User area enabled for boot */ +} mmc_boot_partition_enable_t; + +/*! @brief boot mode configuration + * Note: HS200 & HS400 is not support during BOOT operation. + */ +typedef enum _mmc_boot_timing_mode +{ + kMMC_BootModeSDRWithDefaultTiming = 0U << 3U, /*!< boot mode single data rate with backward compatiable timings */ + kMMC_BootModeSDRWithHighSpeedTiming = 1U << 3U, /*!< boot mode single data rate with high speed timing */ + kMMC_BootModeDDRTiming = 2U << 3U, /*!< boot mode dual date rate */ +} mmc_boot_timing_mode_t; + +/*! @brief MMC card boot partition write protect configurations + * All the bits in BOOT_WP register, except the two R/W bits B_PERM_WP_DIS + * and B_PERM_WP_EN, shall only be written once per power cycle.The protection + * mdde intended for both boot areas will be set with a single write. + */ +typedef enum _mmc_boot_partition_wp +{ + kMMC_BootPartitionWPDisable = 0x50U, /*!< boot partition write protection disable */ + kMMC_BootPartitionPwrWPToBothPartition = + 0x01U, /*!< power on period write protection apply to both boot partitions */ + kMMC_BootPartitionPermWPToBothPartition = 0x04U, /*!< permanent write protection apply to both boot partitions */ + + kMMC_BootPartitionPwrWPToPartition1 = (1U << 7U) | 1U, /*!< power on period write protection apply to partition1 */ + kMMC_BootPartitionPwrWPToPartition2 = (1U << 7U) | 3U, /*!< power on period write protection apply to partition2 */ + + kMMC_BootPartitionPermWPToPartition1 = + (1U << 7U) | (1U << 2U), /*!< permanent write protection apply to partition1 */ + kMMC_BootPartitionPermWPToPartition2 = + (1U << 7U) | (3U << 2U), /*!< permanent write protection apply to partition2 */ + + kMMC_BootPartitionPermWPToPartition1PwrWPToPartition2 = + (1U << 7U) | (1U << 2U) | + 3U, /*!< permanent write protection apply to partition1, power on period write protection apply to partition2 */ + kMMC_BootPartitionPermWPToPartition2PwrWPToPartition1 = + (1U << 7U) | (3U << 2U) | + 1U, /*!< permanent write protection apply to partition2, power on period write protection apply to partition1 */ +} mmc_boot_partition_wp_t; + +/*! @brief MMC card boot partition write protect status */ +enum _mmc_boot_partition_wp_status +{ + kMMC_BootPartitionNotProtected = 0U, /*!< boot partition not protected */ + kMMC_BootPartitionPwrProtected = 1U, /*!< boot partition is power on period write protected */ + kMMC_BootPartitionPermProtected = 2U, /*!< boot partition is permanently protected */ +}; + +/*! @brief MMC card partition to be accessed(BOOT_PARTITION_ACCESS in Extended CSD) */ +typedef enum _mmc_access_partition +{ + kMMC_AccessPartitionUserAera = 0U, /*!< No access to boot partition (default), normal partition */ + kMMC_AccessPartitionBoot1 = 1U, /*!< Read/Write boot partition 1 */ + kMMC_AccessPartitionBoot2 = 2U, /*!< Read/Write boot partition 2*/ + kMMC_AccessRPMB = 3U, /*!< Replay protected mem block */ + kMMC_AccessGeneralPurposePartition1 = 4U, /*!< access to general purpose partition 1 */ + kMMC_AccessGeneralPurposePartition2 = 5U, /*!< access to general purpose partition 2 */ + kMMC_AccessGeneralPurposePartition3 = 6U, /*!< access to general purpose partition 3 */ + kMMC_AccessGeneralPurposePartition4 = 7U, /*!< access to general purpose partition 4 */ +} mmc_access_partition_t; + +/*! @brief The bit shift for PARTITION ACCESS filed in BOOT CONFIG (BOOT_CONFIG in Extend CSD) */ +#define MMC_PARTITION_CONFIG_PARTITION_ACCESS_SHIFT (0U) +/*! @brief The bit mask for PARTITION ACCESS field in BOOT CONFIG */ +#define MMC_PARTITION_CONFIG_PARTITION_ACCESS_MASK (0x00000007U) +/*! @brief The bit shift for PARTITION ENABLE field in BOOT CONFIG */ +#define MMC_PARTITION_CONFIG_PARTITION_ENABLE_SHIFT (3U) +/*! @brief The bit mask for PARTITION ENABLE field in BOOT CONFIG */ +#define MMC_PARTITION_CONFIG_PARTITION_ENABLE_MASK (0x00000038U) +/*! @brief The bit shift for ACK field in BOOT CONFIG */ +#define MMC_PARTITION_CONFIG_BOOT_ACK_SHIFT (6U) +/*! @brief The bit mask for ACK field in BOOT CONFIG */ +#define MMC_PARTITION_CONFIG_BOOT_ACK_MASK (0x00000040U) +/*! @brief The bit shift for BOOT BUS WIDTH field in BOOT CONFIG */ +#define MMC_BOOT_BUS_CONDITION_BUS_WIDTH_SHIFT (0U) +/*! @brief The bit mask for BOOT BUS WIDTH field in BOOT CONFIG */ +#define MMC_BOOT_BUS_CONDITION_BUS_WIDTH_MASK (3U) +/*! @brief The bit shift for BOOT BUS WIDTH RESET field in BOOT CONFIG */ +#define MMC_BOOT_BUS_CONDITION_RESET_BUS_CONDITION_SHIFT (2U) +/*! @brief The bit mask for BOOT BUS WIDTH RESET field in BOOT CONFIG */ +#define MMC_BOOT_BUS_CONDITION_RESET_BUS_CONDITION_MASK (4U) +/*! @brief The bit mask for BOOT BUS WIDTH RESET field in BOOT CONFIG */ +#define MMC_BOOT_BUS_CONDITION_BOOT_MODE_MASK (0x18U) + +/*! @brief MMC card CSD register flags */ +enum _mmc_csd_flag +{ + kMMC_CsdReadBlockPartialFlag = (1U << 0U), /*!< Partial blocks for read allowed */ + kMMC_CsdWriteBlockMisalignFlag = (1U << 1U), /*!< Write block misalignment */ + kMMC_CsdReadBlockMisalignFlag = (1U << 2U), /*!< Read block misalignment */ + kMMC_CsdDsrImplementedFlag = (1U << 3U), /*!< DSR implemented */ + kMMC_CsdWriteProtectGroupEnabledFlag = (1U << 4U), /*!< Write protect group enabled */ + kMMC_CsdWriteBlockPartialFlag = (1U << 5U), /*!< Partial blocks for write allowed */ + kMMC_ContentProtectApplicationFlag = (1U << 6U), /*!< Content protect application */ + kMMC_CsdFileFormatGroupFlag = (1U << 7U), /*!< File format group */ + kMMC_CsdCopyFlag = (1U << 8U), /*!< Copy flag */ + kMMC_CsdPermanentWriteProtectFlag = (1U << 9U), /*!< Permanent write protection */ + kMMC_CsdTemporaryWriteProtectFlag = (1U << 10U), /*!< Temporary write protection */ +}; + +/*! @brief Extended CSD register access mode(Access mode in CMD6). */ +typedef enum _mmc_extended_csd_access_mode +{ + kMMC_ExtendedCsdAccessModeCommandSet = 0U, /*!< Command set related setting */ + kMMC_ExtendedCsdAccessModeSetBits = 1U, /*!< Set bits in specific byte in Extended CSD */ + kMMC_ExtendedCsdAccessModeClearBits = 2U, /*!< Clear bits in specific byte in Extended CSD */ + kMMC_ExtendedCsdAccessModeWriteBits = 3U, /*!< Write a value to specific byte in Extended CSD */ +} mmc_extended_csd_access_mode_t; + +/*! @brief EXT CSD byte index */ +typedef enum _mmc_extended_csd_index +{ + kMMC_ExtendedCsdIndexBootPartitionWP = 173U, /*!< Boot partition write protect */ + kMMC_ExtendedCsdIndexEraseGroupDefinition = 175U, /*!< Erase Group Def */ + kMMC_ExtendedCsdIndexBootBusConditions = 177U, /*!< Boot Bus conditions */ + kMMC_ExtendedCsdIndexBootConfigWP = 178U, /*!< Boot config write protect */ + kMMC_ExtendedCsdIndexPartitionConfig = 179U, /*!< Partition Config, before BOOT_CONFIG */ + kMMC_ExtendedCsdIndexBusWidth = 183U, /*!< Bus Width */ + kMMC_ExtendedCsdIndexHighSpeedTiming = 185U, /*!< High-speed Timing */ + kMMC_ExtendedCsdIndexPowerClass = 187U, /*!< Power Class */ + kMMC_ExtendedCsdIndexCommandSet = 191U, /*!< Command Set */ +} mmc_extended_csd_index_t; + +/*! @brief mmc driver strength */ +enum _mmc_driver_strength +{ + kMMC_DriverStrength0 = 0U, /*!< Driver type0 ,nominal impedance 50ohm */ + kMMC_DriverStrength1 = 1U, /*!< Driver type1 ,nominal impedance 33ohm */ + kMMC_DriverStrength2 = 2U, /*!< Driver type2 ,nominal impedance 66ohm */ + kMMC_DriverStrength3 = 3U, /*!< Driver type3 ,nominal impedance 100ohm */ + kMMC_DriverStrength4 = 4U, /*!< Driver type4 ,nominal impedance 40ohm */ +}; + +/*! @brief mmc extended csd flags*/ +typedef enum _mmc_extended_csd_flags +{ + kMMC_ExtCsdExtPartitionSupport = (1 << 0U), /*!< partitioning support[160] */ + kMMC_ExtCsdEnhancePartitionSupport = (1 << 1U), /*!< partitioning support[160] */ + kMMC_ExtCsdPartitioningSupport = (1 << 2U), /*!< partitioning support[160] */ + kMMC_ExtCsdPrgCIDCSDInDDRModeSupport = (1 << 3U), /*!< CMD26 and CMD27 are support dual data rate [130]*/ + kMMC_ExtCsdBKOpsSupport = (1 << 4U), /*!< background operation feature support [502]*/ + kMMC_ExtCsdDataTagSupport = (1 << 5U), /*!< data tag support[499]*/ + kMMC_ExtCsdModeOperationCodeSupport = (1 << 6U), /*!< mode operation code support[493]*/ +} mmc_extended_csd_flags_t; + +/*! @brief MMC card boot mode */ +enum _mmc_boot_mode +{ + kMMC_BootModeNormal = 0U, /*!< Normal boot */ + kMMC_BootModeAlternative = 1U, /*!< Alternative boot */ +}; + +/*! @brief The length of Extended CSD register, unit as bytes. */ +#define MMC_EXTENDED_CSD_BYTES (512U) + +/*! @brief MMC card default relative address */ +#define MMC_DEFAULT_RELATIVE_ADDRESS (2U) + +/*! @brief SD card product name length united as bytes. */ +#define SD_PRODUCT_NAME_BYTES (5U) + +/*! @brief sdio card FBR register */ +typedef struct _sdio_fbr +{ + uint8_t flags; /*!< current io flags */ + uint8_t ioStdFunctionCode; /*!< current io standard function code */ + uint8_t ioExtFunctionCode; /*!< current io extended function code*/ + uint32_t ioPointerToCIS; /*!< current io pointer to CIS */ + uint32_t ioPointerToCSA; /*!< current io pointer to CSA*/ + uint16_t ioBlockSize; /*!< current io block size */ +} sdio_fbr_t; + +/*! @brief sdio card common CIS */ +typedef struct _sdio_common_cis +{ + /* manufacturer identification string tuple */ + uint16_t mID; /*!< manufacturer code */ + uint16_t mInfo; /*!< manufacturer information */ + + /*function identification tuple */ + uint8_t funcID; /*!< function ID */ + + /* function extension tuple */ + uint16_t fn0MaxBlkSize; /*!< function 0 max block size */ + uint8_t maxTransSpeed; /*!< max data transfer speed for all function */ + +} sdio_common_cis_t; + +/*! @brief sdio card function CIS */ +typedef struct _sdio_func_cis +{ + /*function identification tuple */ + uint8_t funcID; /*!< function ID */ + + /* function extension tuple */ + uint8_t funcInfo; /*!< function info */ + uint8_t ioVersion; /*!< level of application specification this io support */ + uint32_t cardPSN; /*!< product serial number */ + uint32_t ioCSASize; /*!< avaliable CSA size for io */ + uint8_t ioCSAProperty; /*!< CSA property */ + uint16_t ioMaxBlockSize; /*!< io max transfer data size */ + uint32_t ioOCR; /*!< io ioeration condition */ + uint8_t ioOPMinPwr; /*!< min current in operation mode */ + uint8_t ioOPAvgPwr; /*!< average current in operation mode */ + uint8_t ioOPMaxPwr; /*!< max current in operation mode */ + uint8_t ioSBMinPwr; /*!< min current in standby mode */ + uint8_t ioSBAvgPwr; /*!< average current in standby mode */ + uint8_t ioSBMaxPwr; /*!< max current in standby mode */ + + uint16_t ioMinBandWidth; /*!< io min transfer bandwidth */ + uint16_t ioOptimumBandWidth; /*!< io optimum transfer bandwidth */ + uint16_t ioReadyTimeout; /*!< timeout value from enalbe to ready */ + uint16_t ioHighCurrentAvgCurrent; /*!< the average peak current (mA) + when IO operating in high current mode */ + uint16_t ioHighCurrentMaxCurrent; /*!< the max peak current (mA) + when IO operating in high current mode */ + uint16_t ioLowCurrentAvgCurrent; /*!< the average peak current (mA) + when IO operating in lower current mode */ + uint16_t ioLowCurrentMaxCurrent; /*!< the max peak current (mA) + when IO operating in lower current mode */ +} sdio_func_cis_t; + +/*! @brief SD AU start value */ +#define SD_AU_START_VALUE (1U) +/*! @brief SD UHS AU start value */ +#define SD_UHS_AU_START_VALUE (7U) + +/*! @brief SD card status */ +typedef struct _sd_status +{ + uint8_t busWidth; /*!< current buswidth */ + uint8_t secureMode; /*!< secured mode */ + uint16_t cardType; /*!< sdcard type */ + uint32_t protectedSize; /*!< size of protected area */ + uint8_t speedClass; /*!< speed class of card */ + uint8_t performanceMove; /*!< Performance of move indicated by 1[MB/S]step */ + uint8_t auSize; /*!< size of AU */ + uint16_t eraseSize; /*!< number of AUs to be erased at a time */ + uint8_t eraseTimeout; /*!< timeout value for erasing areas specified by UNIT OF ERASE AU */ + uint8_t eraseOffset; /*!< fixed offset value added to erase time */ + uint8_t uhsSpeedGrade; /*!< speed grade for UHS mode */ + uint8_t uhsAuSize; /*!< size of AU for UHS mode */ +} sd_status_t; + +/*! @brief SD card CID register */ +typedef struct _sd_cid +{ + uint8_t manufacturerID; /*!< Manufacturer ID [127:120] */ + uint16_t applicationID; /*!< OEM/Application ID [119:104] */ + uint8_t productName[SD_PRODUCT_NAME_BYTES]; /*!< Product name [103:64] */ + uint8_t productVersion; /*!< Product revision [63:56] */ + uint32_t productSerialNumber; /*!< Product serial number [55:24] */ + uint16_t manufacturerData; /*!< Manufacturing date [19:8] */ +} sd_cid_t; + +/*! @brief SD card CSD register */ +typedef struct _sd_csd +{ + uint8_t csdStructure; /*!< CSD structure [127:126] */ + uint8_t dataReadAccessTime1; /*!< Data read access-time-1 [119:112] */ + uint8_t dataReadAccessTime2; /*!< Data read access-time-2 in clock cycles (NSAC*100) [111:104] */ + uint8_t transferSpeed; /*!< Maximum data transfer rate [103:96] */ + uint16_t cardCommandClass; /*!< Card command classes [95:84] */ + uint8_t readBlockLength; /*!< Maximum read data block length [83:80] */ + uint16_t flags; /*!< Flags in _sd_csd_flag */ + uint32_t deviceSize; /*!< Device size [73:62] */ + /* Following fields from 'readCurrentVddMin' to 'deviceSizeMultiplier' exist in CSD version 1 */ + uint8_t readCurrentVddMin; /*!< Maximum read current at VDD min [61:59] */ + uint8_t readCurrentVddMax; /*!< Maximum read current at VDD max [58:56] */ + uint8_t writeCurrentVddMin; /*!< Maximum write current at VDD min [55:53] */ + uint8_t writeCurrentVddMax; /*!< Maximum write current at VDD max [52:50] */ + uint8_t deviceSizeMultiplier; /*!< Device size multiplier [49:47] */ + + uint8_t eraseSectorSize; /*!< Erase sector size [45:39] */ + uint8_t writeProtectGroupSize; /*!< Write protect group size [38:32] */ + uint8_t writeSpeedFactor; /*!< Write speed factor [28:26] */ + uint8_t writeBlockLength; /*!< Maximum write data block length [25:22] */ + uint8_t fileFormat; /*!< File format [11:10] */ +} sd_csd_t; + +/*! @brief The bit shift for RATE UNIT field in TRANSFER SPEED */ +#define SD_TRANSFER_SPEED_RATE_UNIT_SHIFT (0U) +/*! @brief The bit mask for RATE UNIT field in TRANSFER SPEED */ +#define SD_TRANSFER_SPEED_RATE_UNIT_MASK (0x07U) +/*! @brief The bit shift for TIME VALUE field in TRANSFER SPEED */ +#define SD_TRANSFER_SPEED_TIME_VALUE_SHIFT (2U) +/*! @brief The bit mask for TIME VALUE field in TRANSFER SPEED */ +#define SD_TRANSFER_SPEED_TIME_VALUE_MASK (0x78U) +/*! @brief Read the value of FREQUENCY UNIT in TRANSFER SPEED field */ +#define SD_RD_TRANSFER_SPEED_RATE_UNIT(x) \ + (((x.transferSpeed) & SD_TRANSFER_SPEED_RATE_UNIT_MASK) >> SD_TRANSFER_SPEED_RATE_UNIT_SHIFT) +/*! @brief Read the value of TIME VALUE in TRANSFER SPEED field */ +#define SD_RD_TRANSFER_SPEED_TIME_VALUE(x) \ + (((x.transferSpeed) & SD_TRANSFER_SPEED_TIME_VALUE_MASK) >> SD_TRANSFER_SPEED_TIME_VALUE_SHIFT) + +/*! @brief SD card SCR register */ +typedef struct _sd_scr +{ + uint8_t scrStructure; /*!< SCR Structure [63:60] */ + uint8_t sdSpecification; /*!< SD memory card specification version [59:56] */ + uint16_t flags; /*!< SCR flags in _sd_scr_flag */ + uint8_t sdSecurity; /*!< Security specification supported [54:52] */ + uint8_t sdBusWidths; /*!< Data bus widths supported [51:48] */ + uint8_t extendedSecurity; /*!< Extended security support [46:43] */ + uint8_t commandSupport; /*!< Command support bits [33:32] 33-support CMD23, 32-support cmd20*/ + uint32_t reservedForManufacturer; /*!< reserved for manufacturer usage [31:0] */ +} sd_scr_t; + +/*! @brief MMC card product name length united as bytes. */ +#define MMC_PRODUCT_NAME_BYTES (6U) +/*! @brief MMC card CID register. */ +typedef struct _mmc_cid +{ + uint8_t manufacturerID; /*!< Manufacturer ID */ + uint16_t applicationID; /*!< OEM/Application ID */ + uint8_t productName[MMC_PRODUCT_NAME_BYTES]; /*!< Product name */ + uint8_t productVersion; /*!< Product revision */ + uint32_t productSerialNumber; /*!< Product serial number */ + uint8_t manufacturerData; /*!< Manufacturing date */ +} mmc_cid_t; + +/*! @brief MMC card CSD register. */ +typedef struct _mmc_csd +{ + uint8_t csdStructureVersion; /*!< CSD structure [127:126] */ + uint8_t systemSpecificationVersion; /*!< System specification version [125:122] */ + uint8_t dataReadAccessTime1; /*!< Data read access-time 1 [119:112] */ + uint8_t dataReadAccessTime2; /*!< Data read access-time 2 in CLOCK cycles (NSAC*100) [111:104] */ + uint8_t transferSpeed; /*!< Max. bus clock frequency [103:96] */ + uint16_t cardCommandClass; /*!< card command classes [95:84] */ + uint8_t readBlockLength; /*!< Max. read data block length [83:80] */ + uint16_t flags; /*!< Contain flags in _mmc_csd_flag */ + uint16_t deviceSize; /*!< Device size [73:62] */ + uint8_t readCurrentVddMin; /*!< Max. read current @ VDD min [61:59] */ + uint8_t readCurrentVddMax; /*!< Max. read current @ VDD max [58:56] */ + uint8_t writeCurrentVddMin; /*!< Max. write current @ VDD min [55:53] */ + uint8_t writeCurrentVddMax; /*!< Max. write current @ VDD max [52:50] */ + uint8_t deviceSizeMultiplier; /*!< Device size multiplier [49:47] */ + uint8_t eraseGroupSize; /*!< Erase group size [46:42] */ + uint8_t eraseGroupSizeMultiplier; /*!< Erase group size multiplier [41:37] */ + uint8_t writeProtectGroupSize; /*!< Write protect group size [36:32] */ + uint8_t defaultEcc; /*!< Manufacturer default ECC [30:29] */ + uint8_t writeSpeedFactor; /*!< Write speed factor [28:26] */ + uint8_t maxWriteBlockLength; /*!< Max. write data block length [25:22] */ + uint8_t fileFormat; /*!< File format [11:10] */ + uint8_t eccCode; /*!< ECC code [9:8] */ +} mmc_csd_t; + +/*! @brief MMC card Extended CSD register (unit: byte). */ +typedef struct _mmc_extended_csd +{ + /*uint8_t SecureRemoveType;*/ /*!< secure removal type[16]*/ + /*uint8_t enProductStateAware;*/ /*!< product state awareness enablement[17]*/ + /*uint32_t maxPreLoadDataSize;*/ /*!< max preload data size[21-18]*/ + /*uint32_t preLoadDataSize;*/ /*!< pre-load data size[25-22]*/ + /*uint8_t ffuStatus;*/ /*!< FFU status [26]*/ + /*uint8_t modeOperationCode;*/ /*!< mode operation code[29]*/ + /*uint8_t modeConfig;*/ /*!< mode config [30]*/ + /*uint8_t cacheCtrl;*/ /*!< control to turn on/off cache[33]*/ + /*uint8_t pwroffNotify;*/ /*!< power off notification[34]*/ + /*uint8_t packedCmdFailIndex;*/ /*!< packed cmd fail index [35]*/ + /*uint8_t packedCmdStatus;*/ /*!< packed cmd status[36]*/ + /*uint32_t contextConfig[4U];*/ /*!< context configuration[51-37]*/ + /*uint16_t extPartitionAttr;*/ /*!< extended partitions attribut[53-52]*/ + /*uint16_t exceptEventStatus;*/ /*!< exception events status[55-54]*/ + /*uint16_t exceptEventControl;*/ /*!< exception events control[57-56]*/ + /*uint8_t toReleaseAddressedGroup;*/ /*!< number of group to be released[58]*/ + /*uint8_t class6CmdCtrl;*/ /*!< class 6 command control[59]*/ + /*uint8_t intTimeoutEmu;*/ /*!< 1st initiallization after disabling sector size emu[60]*/ + /*uint8_t sectorSize;*/ /*!< sector size[61] */ + /*uint8_t sectorSizeEmu;*/ /*!< sector size emulation[62]*/ + /*uint8_t nativeSectorSize;*/ /*!< native sector size[63]*/ + /*uint8_t periodWakeup;*/ /*!< period wakeup [131]*/ + /*uint8_t tCASESupport;*/ /*!< package case temperature is controlled[132]*/ + /*uint8_t productionStateAware;*/ /*!< production state awareness[133]*/ + /*uint32_t enhanceUsrDataStartAddr;*/ /*!< enhanced user data start addr [139-136]*/ + /*uint32_t enhanceUsrDataSize;*/ /*!< enhanced user data area size[142-140]*/ + /*uint32_t generalPartitionSize[3];*/ /*!< general purpose partition size[154-143]*/ + uint8_t partitionAttribute; /*!< partition attribute [156]*/ + /*uint32_t maxEnhanceAreaSize;*/ /*!< max enhance area size [159-157]*/ + /*uint8_t hpiManagementEn;*/ /*!< HPI management [161]*/ + /*uint8_t writeReliabilityParameter;*/ /*!< write reliability parameter register[166] */ + /*uint8_t writeReliabilitySet;*/ /*!< write reliability setting register[167] */ + /*uint8_t rpmbSizeMult;*/ /*!< RPMB size multi [168]*/ + /*uint8_t fwConfig;*/ /*!< FW configuration[169]*/ + uint8_t userWP; /*!< user write protect register[171] */ + uint8_t bootPartitionWP; /*!< boot write protect register[173]*/ + uint8_t bootWPStatus; /*!< boot write protect status register[174]*/ + uint8_t highDensityEraseGroupDefinition; /*!< High-density erase group definition [175] */ + uint8_t bootDataBusConditions; /*!< Boot bus conditions [177] */ + uint8_t bootConfigProtect; /*!< Boot config protection [178]*/ + uint8_t partitionConfig; /*!< Boot configuration [179] */ + uint8_t eraseMemoryContent; /*!< Erased memory content [181] */ + uint8_t dataBusWidth; /*!< Data bus width mode [183] */ + uint8_t highSpeedTiming; /*!< High-speed interface timing [185] */ + uint8_t powerClass; /*!< Power class [187] */ + uint8_t commandSetRevision; /*!< Command set revision [189] */ + uint8_t commandSet; /*!< Command set [191] */ + uint8_t extendecCsdVersion; /*!< Extended CSD revision [192] */ + uint8_t csdStructureVersion; /*!< CSD structure version [194] */ + uint8_t cardType; /*!< Card Type [196] */ + uint8_t ioDriverStrength; /*!< IO driver strength [197] */ + /*uint8_t OutofInterruptBusyTiming;*/ /*!< out of interrupt busy timing [198] */ + /*uint8_t partitionSwitchTiming;*/ /*!< partition switch timing [199] */ + uint8_t powerClass52MHz195V; /*!< Power Class for 52MHz @ 1.95V [200] */ + uint8_t powerClass26MHz195V; /*!< Power Class for 26MHz @ 1.95V [201] */ + uint8_t powerClass52MHz360V; /*!< Power Class for 52MHz @ 3.6V [202] */ + uint8_t powerClass26MHz360V; /*!< Power Class for 26MHz @ 3.6V [203] */ + uint8_t minimumReadPerformance4Bit26MHz; /*!< Minimum Read Performance for 4bit at 26MHz [205] */ + uint8_t minimumWritePerformance4Bit26MHz; /*!< Minimum Write Performance for 4bit at 26MHz [206] */ + uint8_t minimumReadPerformance8Bit26MHz4Bit52MHz; + /*!< Minimum read Performance for 8bit at 26MHz/4bit @52MHz [207] */ + uint8_t minimumWritePerformance8Bit26MHz4Bit52MHz; + /*!< Minimum Write Performance for 8bit at 26MHz/4bit @52MHz [208] */ + uint8_t minimumReadPerformance8Bit52MHz; /*!< Minimum Read Performance for 8bit at 52MHz [209] */ + uint8_t minimumWritePerformance8Bit52MHz; /*!< Minimum Write Performance for 8bit at 52MHz [210] */ + uint32_t sectorCount; /*!< Sector Count [215:212] */ + /*uint8_t sleepNotificationTimeout;*/ /*!< sleep notification timeout [216]*/ + uint8_t sleepAwakeTimeout; /*!< Sleep/awake timeout [217] */ + /*uint8_t productionStateAwareTimeout;*/ /*!< Production state awareness timeout [218]*/ + uint8_t sleepCurrentVCCQ; /*!< Sleep current (VCCQ) [219] */ + uint8_t sleepCurrentVCC; /*!< Sleep current (VCC) [220] */ + uint8_t highCapacityWriteProtectGroupSize; /*!< High-capacity write protect group size [221] */ + uint8_t reliableWriteSectorCount; /*!< Reliable write sector count [222] */ + uint8_t highCapacityEraseTimeout; /*!< High-capacity erase timeout [223] */ + uint8_t highCapacityEraseUnitSize; /*!< High-capacity erase unit size [224] */ + uint8_t accessSize; /*!< Access size [225] */ + /*uint8_t secureTrimMultiplier;*/ /*!< secure trim multiplier[229]*/ + /*uint8_t secureEraseMultiplier;*/ /*!< secure erase multiplier[230]*/ + /*uint8_t secureFeatureSupport;*/ /*!< secure feature support[231]*/ + /*uint32_t trimMultiplier;*/ /*!< trim multiplier[232]*/ + uint8_t minReadPerformance8bitAt52MHZDDR; /*!< Minimum read performance for 8bit at DDR 52MHZ[234]*/ + uint8_t minWritePerformance8bitAt52MHZDDR; /*!< Minimum write performance for 8bit at DDR 52MHZ[235]*/ + uint8_t powerClass200MHZVCCQ130VVCC360V; /*!< power class for 200MHZ, at VCCQ= 1.3V,VCC=3.6V[236]*/ + uint8_t powerClass200MHZVCCQ195VVCC360V; /*!< power class for 200MHZ, at VCCQ= 1.95V,VCC=3.6V[237]*/ + uint8_t powerClass52MHZDDR195V; /*!< power class for 52MHZ,DDR at Vcc 1.95V[238]*/ + uint8_t powerClass52MHZDDR360V; /*!< power class for 52MHZ,DDR at Vcc 3.6V[239]*/ + /*uint8_t iniTimeoutAP;*/ /*!< 1st initialization time after partitioning[241]*/ + /*uint32_t correctPrgSectorNum;*/ /*!< correct prg sectors number[245-242]*/ + /*uint8_t bkOpsStatus;*/ /*!< background operations status[246]*/ + /*uint8_t powerOffNotifyTimeout;*/ /*!< power off notification timeout[247]*/ + /*uint8_t genericCMD6Timeout;*/ /*!< generic CMD6 timeout[248]*/ + uint32_t cacheSize; /*!< cache size[252-249]*/ + uint8_t powerClass200MHZDDR360V; /*!< power class for 200MHZ, DDR at VCC=2.6V[253]*/ + /*uint32_t fwVer[2U];*/ /*!< fw VERSION [261-254]*/ + /*uint16_t deviceVer;*/ /*!< device version[263-262]*/ + /*uint8_t optimalTrimSize;*/ /*!< optimal trim size[264]*/ + /*uint8_t optimalWriteSize;*/ /*!< optimal write size[265]*/ + /*uint8_t optimalReadSize;*/ /*!< optimal read size[266]*/ + /*uint8_t preEolInfo;*/ /*!< pre EOL information[267]*/ + /*uint8_t deviceLifeTimeEstimationA;*/ /*!< device life time estimation typeA[268]*/ + /*uint8_t deviceLifeTimeEstimationB;*/ /*!< device life time estimation typeB[269]*/ + /*uint32_t correctPrgFWSectorNum;*/ /*!< number of FW sectors correctly programmed[305-302]*/ + /*uint32_t ffuArg;*/ /*!< FFU argument[490-487]*/ + /*uint8_t operationCodeTimeout;*/ /*!< operation code timeout[491]*/ + /*uint8_t supportMode;*/ /*!< support mode [493]*/ + uint8_t extPartitionSupport; /*!< extended partition attribute support[494]*/ + /*uint8_t largeUnitSize;*/ /*!< large unit size[495]*/ + /*uint8_t contextManageCap;*/ /*!< context management capability[496]*/ + /*uint8_t tagResourceSize;*/ /*!< tag resource size[497]*/ + /*uint8_t tagUnitSize;*/ /*!< tag unit size[498]*/ + /*uint8_t maxPackedWriteCmd;*/ /*!< max packed write cmd[500]*/ + /*uint8_t maxPackedReadCmd;*/ /*!< max packed read cmd[501]*/ + /*uint8_t hpiFeature;*/ /*!< HPI feature[503]*/ + uint8_t supportedCommandSet; /*!< Supported Command Sets [504] */ + /*uint8_t extSecurityCmdError;*/ /*!< extended security commands error[505]*/ +} mmc_extended_csd_t; + +/*! @brief The bit shift for COMMAND SET field in SWITCH command. */ +#define MMC_SWITCH_COMMAND_SET_SHIFT (0U) +/*! @brief The bit mask for COMMAND set field in SWITCH command. */ +#define MMC_SWITCH_COMMAND_SET_MASK (0x00000007U) +/*! @brief The bit shift for VALUE field in SWITCH command */ +#define MMC_SWITCH_VALUE_SHIFT (8U) +/*! @brief The bit mask for VALUE field in SWITCH command */ +#define MMC_SWITCH_VALUE_MASK (0x0000FF00U) +/*! @brief The bit shift for BYTE INDEX field in SWITCH command */ +#define MMC_SWITCH_BYTE_INDEX_SHIFT (16U) +/*! @brief The bit mask for BYTE INDEX field in SWITCH command */ +#define MMC_SWITCH_BYTE_INDEX_MASK (0x00FF0000U) +/*! @brief The bit shift for ACCESS MODE field in SWITCH command */ +#define MMC_SWITCH_ACCESS_MODE_SHIFT (24U) +/*! @brief The bit mask for ACCESS MODE field in SWITCH command */ +#define MMC_SWTICH_ACCESS_MODE_MASK (0x03000000U) + +/*! @brief MMC Extended CSD configuration. */ +typedef struct _mmc_extended_csd_config +{ + mmc_command_set_t commandSet; /*!< Command set */ + uint8_t ByteValue; /*!< The value to set */ + uint8_t ByteIndex; /*!< The byte index in Extended CSD(mmc_extended_csd_index_t) */ + mmc_extended_csd_access_mode_t accessMode; /*!< Access mode */ +} mmc_extended_csd_config_t; + +/*! @brief MMC card boot configuration definition. */ +typedef struct _mmc_boot_config +{ + bool enableBootAck; /*!< Enable boot ACK */ + mmc_boot_partition_enable_t bootPartition; /*!< Boot partition */ + + mmc_boot_timing_mode_t bootTimingMode; /*!< boot mode */ + mmc_data_bus_width_t bootDataBusWidth; /*!< Boot data bus width */ + bool retainBootbusCondition; /*!< If retain boot bus width and boot mode conditions */ + + bool pwrBootConfigProtection; /*!< Disable the change of boot configuration register bits from at this point + until next power cycle or next H/W reset operation */ + bool premBootConfigProtection; /*!< Disable the change of boot configuration register bits permanently */ + + mmc_boot_partition_wp_t bootPartitionWP; /*!< boot partition write protect configurations */ + +} mmc_boot_config_t; + +#endif /* _FSL_SDMMC_SPEC_H_ */ diff --git a/target/sdio_device.c b/target/sdio_device.c new file mode 100644 index 0000000..2519abd --- /dev/null +++ b/target/sdio_device.c @@ -0,0 +1,188 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "fsl_sd.h" +#include "pinmap.h" +#include "sdio_device.h" + +/* Array of SD peripheral base address. */ +static SDIF_Type *const sd_addrs[] = SDIF_BASE_PTRS; +static sd_card_t g_sd; + +extern void sdio_clock_setup(void); + +/** + * @brief Initializes the SD card device. + * @retval SD status + */ +uint8_t SDIO_Init(void) +{ + uint32_t reg; + + /*! @brief SDMMC host detect card configuration */ + sdmmchost_detect_card_t s_sdCardDetect = { + .cdType = kSDMMCHOST_DetectCardByGpioCD, + .cdTimeOut_ms = (~0U), + }; + + sdio_clock_setup(); + + /* SD POW_EN */ + pin_function(P0_9, 2); + pin_mode(P0_9, PullNone); + + /* SD DAT3 */ + pin_function(P1_0, 2); + pin_mode(P1_0, PullNone); + reg = IOCON->PIO[1][0]; + reg |= IOCON_PIO_SLEW_MASK; + IOCON->PIO[1][0] = reg; + + /* SD DAT2 */ + pin_function(P0_31, 2); + pin_mode(P0_31, PullNone); + reg = IOCON->PIO[0][31]; + reg |= IOCON_PIO_SLEW_MASK; + IOCON->PIO[0][31] = reg; + + /* SD DAT1 */ + pin_function(P0_25, 2); + pin_mode(P0_25, PullNone); + reg = IOCON->PIO[0][25]; + reg |= IOCON_PIO_SLEW_MASK; + IOCON->PIO[0][25] = reg; + + /* SD DAT0 */ + pin_function(P0_24, 2); + pin_mode(P0_24, PullNone); + reg = IOCON->PIO[0][24]; + reg |= IOCON_PIO_SLEW_MASK; + IOCON->PIO[0][24] = reg; + + /* SD CLK */ + pin_function(P0_7, 2); + pin_mode(P0_7, PullNone); + reg = IOCON->PIO[0][7]; + reg |= IOCON_PIO_SLEW_MASK; + IOCON->PIO[0][7] = reg; + + /* SD CMD */ + pin_function(P0_8, 2); + pin_mode(P0_8, PullNone); + reg = IOCON->PIO[0][8]; + reg |= IOCON_PIO_SLEW_MASK; + IOCON->PIO[0][8] = reg; + + /* SD Card Det */ + //pin_function(P0_17, 2); + //pin_mode(P0_17, PullNone); + + /* SD Write Protect */ + //pin_function(P0_15, 5); + //pin_mode(P0_15, PullNone); + g_sd.host.base = SD_HOST_BASEADDR; + g_sd.host.sourceClock_Hz = SD_HOST_CLK_FREQ; + /* card detect type */ + g_sd.usrParam.cd = &s_sdCardDetect; +#if defined DEMO_SDCARD_POWER_CTRL_FUNCTION_EXIST + g_sd.usrParam.pwr = &s_sdCardPwrCtrl; +#endif + + /* SD host init function */ + if (SD_Init(&g_sd) != kStatus_Success) { + return 1; + } + + return 0; +} + +/** + * @brief DeInitializes the SD card device. + * @retval SD status + */ +uint8_t SDIO_DeInit(void) +{ + SD_Deinit(&g_sd); + + return 0; +} + +/** + * @brief Reads block(s) from a specified address in an SD card, in polling mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param ReadAddr: Address from where data is to be read + * @param NumOfBlocks: Number of SD blocks to read + * @param Timeout: Timeout for read operation + * @retval SD status + */ +uint8_t SDIO_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +{ + uint8_t sd_state = MSD_OK; + + if (SD_ReadBlocks(&g_sd, (uint8_t *)pData, ReadAddr, NumOfBlocks) != kStatus_Success) { + sd_state = MSD_ERROR; + } + + return sd_state; +} + +/** + * @brief Writes block(s) to a specified address in an SD card, in polling mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param WriteAddr: Address from where data is to be written + * @param NumOfBlocks: Number of SD blocks to write + * @param Timeout: Timeout for write operation + * @retval SD status + */ +uint8_t SDIO_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +{ + uint8_t sd_state = MSD_OK; + + if (SD_WriteBlocks(&g_sd, (uint8_t *)pData, WriteAddr, NumOfBlocks) != kStatus_Success) { + sd_state = MSD_ERROR; + } + + return sd_state; +} + +/** + * @brief Erases the specified memory area of the given SD card. + * @param StartAddr: Start byte address + * @param NumOfBlocks: Number of SD blocks to erase + * @retval SD status + */ +uint8_t SDIO_Erase(uint32_t StartAddr, uint32_t NumOfBlocks) +{ + uint8_t sd_state = MSD_OK; + + if (SD_EraseBlocks(&g_sd, StartAddr, NumOfBlocks) != kStatus_Success) + { + sd_state = MSD_ERROR; + } + + return sd_state; +} + +uint32_t SDIO_GetBlockSize(void) +{ + return g_sd.blockSize; +} + +uint32_t SDIO_GetBlockCount(void) +{ + return g_sd.blockCount; +} + + diff --git a/target/sdio_device.h b/target/sdio_device.h new file mode 100644 index 0000000..db099f8 --- /dev/null +++ b/target/sdio_device.h @@ -0,0 +1,52 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __MBED_SDIO_DEVICE_H +#define __MBED_SDIO_DEVICE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Exported constants */ +/* + * @brief SD status structure definition + */ +#define MSD_OK ((uint8_t)0x00) +#define MSD_ERROR ((uint8_t)0x01) + +/* + * @brief SD transfer state definition + */ +#define SD_TRANSFER_OK ((uint8_t)0x00) +#define SD_TRANSFER_BUSY ((uint8_t)0x01) + +/* Exported functions */ +uint8_t SDIO_Init(void); +uint8_t SDIO_DeInit(void); +uint8_t SDIO_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); +uint8_t SDIO_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); +uint8_t SDIO_Erase(uint32_t StartAddr, uint32_t EndAddr); +uint32_t SDIO_GetBlockSize(void); +uint32_t SDIO_GetBlockCount(void); + +#ifdef __cplusplus +} +#endif + +#endif +