L VD / sdio-glue

Dependents:   mbed-os-example-filesystem-sdio

Files at this revision

API Documentation at this revision

Comitter:
elelthvd
Date:
Wed Nov 11 03:05:14 2020 +0000
Commit message:
initial commit

Changed in this revision

configs/mbed-os-example-filesystem.json Show annotated file Show diff for this revision Revisions of this file
hal/include/hal/sdio_api.h Show annotated file Show diff for this revision Revisions of this file
sdio.cpp Show annotated file Show diff for this revision Revisions of this file
sdio.h Show annotated file Show diff for this revision Revisions of this file
storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp Show annotated file Show diff for this revision Revisions of this file
storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h Show annotated file Show diff for this revision Revisions of this file
storage/blockdevice/COMPONENT_SDIO/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c Show annotated file Show diff for this revision Revisions of this file
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/board.h Show annotated file Show diff for this revision Revisions of this file
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.c Show annotated file Show diff for this revision Revisions of this file
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.h Show annotated file Show diff for this revision Revisions of this file
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_common.c Show annotated file Show diff for this revision Revisions of this file
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_common.h Show annotated file Show diff for this revision Revisions of this file
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_host.c Show annotated file Show diff for this revision Revisions of this file
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_host.h Show annotated file Show diff for this revision Revisions of this file
targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_spec.h Show annotated file Show diff for this revision Revisions of this file
targets/TARGET_STM/TARGET_STM32F4/sdio_api.c Show annotated file Show diff for this revision Revisions of this file
targets/TARGET_STM/TARGET_STM32F7/sdio_api.c Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r d90c6c9a7600 configs/mbed-os-example-filesystem.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configs/mbed-os-example-filesystem.json	Wed Nov 11 03:05:14 2020 +0000
@@ -0,0 +1,18 @@
+{
+    "target_overrides": {
+        "*": {
+            "platform.stdio-baud-rate"                     : 115200,
+            "platform.stdio-convert-newlines"              : true,
+            "target.components_add"                        : ["SDIO"],
+            "target.device_has_add"                        : ["SDIO"]
+        },
+        "LPC55S69_NS": {
+            "target.components_remove"                     : ["SD"],
+	    "target.macros_add"                            : ["BUTTON1=SW2"]
+        },
+        "DISCO_F746NG": {
+            "target.components_remove"                     : ["SD"],
+            "target.device_has_add"                        : ["SDIO_ASYNC"]
+        }
+    }
+}
diff -r 000000000000 -r d90c6c9a7600 hal/include/hal/sdio_api.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hal/include/hal/sdio_api.h	Wed Nov 11 03:05:14 2020 +0000
@@ -0,0 +1,163 @@
+/** \addtogroup hal */
+/** @{*/
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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_API_H
+#define MBED_SDIO_API_H
+
+#include "device.h"
+#include "pinmap.h"
+
+#if DEVICE_SDIO
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * \defgroup SDIO Configuration Functions
+ * @{
+ */
+
+typedef struct {
+    uint32_t card_type;        /* Specifies the card Type                         */
+    uint32_t card_version;     /* Specifies the card version                      */
+    uint32_t card_class;       /* Specifies the class of the card class           */
+    uint32_t rel_card_addr;    /* Specifies the Relative Card Address             */
+    uint32_t block_count;      /* Specifies the Card Capacity in blocks           */
+    uint32_t block_size;       /* Specifies one block size in bytes               */
+    uint32_t log_block_count;  /* Specifies the Card logical Capacity in blocks   */
+    uint32_t log_block_size;   /* Specifies logical block size in bytes           */
+} sdio_card_info_t;
+
+/**
+  * @brief  SD status structure definition
+  */
+#define MSD_OK ((int)0x00)
+#define MSD_ERROR ((int)0x01)
+
+/**
+  * @brief  SD transfer state definition
+  */
+#define SD_TRANSFER_OK ((int)0x00)
+#define SD_TRANSFER_BUSY ((int)0x01)
+
+/**
+ * @brief  Initializes the SD card device.
+ * @retval SD status
+ */
+int sdio_init(void);
+
+/**
+ * @brief  DeInitializes the SD card device.
+ * @retval SD status
+ */
+int sdio_deinit(void);
+
+/**
+ * @brief  Reads block(s) from a specified address in an SD card, in polling mode.
+ * @param  data: Pointer to the buffer that will contain the data to transmit
+ * @param  address: Address from where data is to be read
+ * @param  block_count: Number of SD blocks to read
+ * @retval SD status
+ */
+int sdio_read_blocks(uint8_t *data, uint32_t address, uint32_t block_count);
+
+/**
+ * @brief  Writes block(s) to a specified address in an SD card, in polling mode.
+ * @param  data: Pointer to the buffer that will contain the data to transmit
+ * @param  address: Address from where data is to be written
+ * @param  block_count: Number of SD blocks to write
+ * @retval SD status
+ */
+int sdio_write_blocks(uint8_t *data, uint32_t address, uint32_t block_count);
+
+#if DEVICE_SDIO_ASYNC
+
+/**
+ * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.
+ * @param  data: Pointer to the buffer that will contain the data to transmit
+ * @param  address: Address from where data is to be read
+ * @param  block_count: Number of SD blocks to read
+ * @retval SD status
+ */
+int sdio_read_blocks_async(uint8_t *data, uint32_t address, uint32_t block_count);
+
+/**
+ * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.
+ * @param  data: Pointer to the buffer that will contain the data to transmit
+ * @param  address: Address from where data is to be written
+ * @param  block_count: Number of SD blocks to write
+ * @retval SD status
+ */
+int sdio_write_blocks_async(uint8_t *data, uint32_t address, uint32_t block_count);
+
+/**
+ * @brief  Check if a DMA operation is pending
+ * @retval DMA operation is pending
+ *          This value can be one of the following values:
+ *            @arg  SD_TRANSFER_OK: No data transfer is acting
+ *            @arg  SD_TRANSFER_BUSY: Data transfer is acting
+ */
+int sdio_read_pending(void);
+
+/**
+ * @brief  Check if a DMA operation is pending
+ * @retval DMA operation is pending
+ *          This value can be one of the following values:
+ *            @arg  SD_TRANSFER_OK: No data transfer is acting
+ *            @arg  SD_TRANSFER_BUSY: Data transfer is acting
+ */
+int sdio_write_pending(void);
+
+#endif // DEVICE_SDIO_ASYNC
+
+/**
+ * @brief  Erases the specified memory area of the given SD card.
+ * @param  start_address: Start byte address
+ * @param  end_address: End byte address
+ * @retval SD status
+ */
+int sdio_erase(uint32_t start_address, uint32_t end_address);
+
+/**
+ * @brief  Gets the current SD card data status.
+ * @param  None
+ * @retval Data transfer state.
+ *          This value can be one of the following values:
+ *            @arg  SD_TRANSFER_OK: No data transfer is acting
+ *            @arg  SD_TRANSFER_BUSY: Data transfer is acting
+ */
+int sdio_get_card_state(void);
+
+/**
+ * @brief  Get SD information about specific SD card.
+ * @param  card_info: Pointer to HAL_SD_CardInfoTypedef structure
+ * @retval None
+ */
+void sdio_get_card_info(sdio_card_info_t *card_info);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // DEVICE_SDIO
+
+#endif // MBED_SDIO_API_H
diff -r 000000000000 -r d90c6c9a7600 sdio.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sdio.cpp	Wed Nov 11 03:05:14 2020 +0000
@@ -0,0 +1,16 @@
+#if COMPONENT_SDIO
+#include "sdio.h"
+
+static SDIOBlockDevice bd;
+
+BlockDevice *BlockDevice::get_default_instance()
+{
+    return &bd;
+}
+
+BlockDevice *get_other_blockdevice()
+{
+    return &bd;
+}
+
+#endif
diff -r 000000000000 -r d90c6c9a7600 sdio.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sdio.h	Wed Nov 11 03:05:14 2020 +0000
@@ -0,0 +1,3 @@
+#if COMPONENT_SDIO
+#include "SDIOBlockDevice.h"
+#endif
diff -r 000000000000 -r d90c6c9a7600 storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp	Wed Nov 11 03:05:14 2020 +0000
@@ -0,0 +1,397 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2019 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 "sdio_api.h"
+#if DEVICE_SDIO_ASYNC
+#include "us_ticker_api.h"
+#endif
+#include "SDIOBlockDevice.h"
+#include "platform/mbed_debug.h"
+
+using namespace mbed;
+
+#if DEVICE_SDIO
+
+/*
+ *  defines
+ */
+
+#define SDIO_DBG 1       /*!< 1 - Enable debugging */
+#define SDIO_CMD_TRACE 0 /*!< 1 - Enable SD command tracing */
+
+#define SDIO_BLOCK_DEVICE_ERROR_WOULD_BLOCK -5001           /*!< operation would block */
+#define SDIO_BLOCK_DEVICE_ERROR_UNSUPPORTED -5002           /*!< unsupported operation */
+#define SDIO_BLOCK_DEVICE_ERROR_PARAMETER -5003             /*!< invalid parameter */
+#define SDIO_BLOCK_DEVICE_ERROR_NO_INIT -5004               /*!< uninitialized */
+#define SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE -5005             /*!< device is missing or not connected */
+#define SDIO_BLOCK_DEVICE_ERROR_WRITE_PROTECTED -5006       /*!< write protected */
+#define SDIO_BLOCK_DEVICE_ERROR_UNUSABLE -5007              /*!< unusable card */
+#define SDIO_BLOCK_DEVICE_ERROR_NO_RESPONSE -5008           /*!< No response from device */
+#define SDIO_BLOCK_DEVICE_ERROR_CRC -5009                   /*!< CRC error */
+#define SDIO_BLOCK_DEVICE_ERROR_ERASE -5010                 /*!< Erase error: reset/sequence */
+#define SDIO_BLOCK_DEVICE_ERROR_WRITE -5011                 /*!< SPI Write error: !SPI_DATA_ACCEPTED */
+#define SDIO_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE -5012 /*!< unsupported blocksize, only 512 byte supported */
+#define SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS -5013           /*!< read data blocks from SD failed */
+#define SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS -5014          /*!< write data blocks to SD failed */
+#define SDIO_BLOCK_DEVICE_ERROR_ERASE_BLOCKS -5015          /*!< erase data blocks to SD failed */
+
+#define BLOCK_SIZE_HC 512 /*!< Block size supported for SD card is 512 bytes  */
+
+// Types
+#define SDCARD_NONE 0  /**< No card is present */
+#define SDCARD_V1 1    /**< v1.x Standard Capacity */
+#define SDCARD_V2 2    /**< v2.x Standard capacity SD card */
+#define SDCARD_V2HC 3  /**< v2.x High capacity SD card */
+#define CARD_UNKNOWN 4 /**< Unknown or unsupported card */
+
+SDIOBlockDevice::SDIOBlockDevice(PinName card_detect) : _card_detect(card_detect),
+                                                        _is_initialized(0),
+                                                        _sectors(0),
+                                                        _init_ref_count(0)
+{
+    // Only HC block size is supported.
+    _block_size = BLOCK_SIZE_HC;
+    _erase_size = BLOCK_SIZE_HC;
+}
+
+SDIOBlockDevice::~SDIOBlockDevice()
+{
+    if (_is_initialized) {
+        deinit();
+    }
+}
+
+int SDIOBlockDevice::init()
+{
+    debug_if(SDIO_DBG, "init Card...\r\n");
+
+    lock();
+
+    if (!_is_initialized) {
+        _init_ref_count = 0;
+    }
+
+    _init_ref_count++;
+
+    if (_init_ref_count != 1) {
+        unlock();
+        return BD_ERROR_OK;
+    }
+
+    if (is_present() == false) {
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE;
+    }
+
+    int status = sdio_init();
+    if (BD_ERROR_OK != status) {
+        unlock();
+        return BD_ERROR_DEVICE_ERROR;
+    }
+
+    sdio_get_card_info(&_card_info);
+    _is_initialized = true;
+    debug_if(SDIO_DBG, "SDIO initialized: type: %lu  version: %lu  class: %lu\n",
+             _card_info.card_type, _card_info.card_version, _card_info.card_class);
+    debug_if(SDIO_DBG, "SDIO size: %lu MB\n",
+             _card_info.log_block_count / 2 / 1024);
+
+    // get sectors count from card_info
+    _sectors = _card_info.log_block_count;
+    if (BLOCK_SIZE_HC != _card_info.block_size) {
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE;
+    }
+
+    unlock();
+    return status;
+}
+
+int SDIOBlockDevice::deinit()
+{
+    debug_if(SDIO_DBG, "deinit SDIO Card...\r\n");
+    lock();
+
+    if (!_is_initialized) {
+        _init_ref_count = 0;
+        unlock();
+        return BD_ERROR_OK;
+    }
+
+    _init_ref_count--;
+
+    if (_init_ref_count) {
+        unlock();
+        return BD_ERROR_OK;
+    }
+
+    int status = sdio_deinit();
+    _is_initialized = false;
+
+    _sectors = 0;
+
+    unlock();
+    return status;
+}
+
+int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
+{
+    int status = 0;
+    lock();
+    if (is_present() == false) {
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE;
+    }
+
+    if (!_is_initialized) {
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_NO_INIT;
+    }
+
+    if (!is_valid_read(addr, size)) {
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_PARAMETER;
+    }
+
+    uint8_t *_buffer = static_cast<uint8_t *>(buffer);
+
+    // ReadBlocks uses byte unit address
+    // SDHC and SDXC Cards different addressing is handled in ReadBlocks()
+    bd_addr_t block_count = size / _block_size;
+    addr = addr / _block_size;
+
+#if DEVICE_SDIO_ASYNC
+    // make sure card is ready
+    {
+        uint32_t tickstart = us_ticker_read();
+        while (sdio_get_card_state() != SD_TRANSFER_OK) {
+            // wait until SD ready
+            if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) {
+                unlock();
+                return SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS;
+            }
+        }
+    }
+
+    // receive the data : one block/ multiple blocks is handled in ReadBlocks()
+    status = sdio_read_blocks_async(_buffer, addr, block_count);
+    debug_if(SDIO_DBG, "SDIO read blocks dbgtest addr: %lld  block_count: %lld \n", addr, block_count);
+
+    if (status == MSD_OK) {
+        // wait until DMA finished
+        uint32_t tickstart = us_ticker_read();
+        while (sdio_read_pending() != SD_TRANSFER_OK) {
+            if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) {
+                unlock();
+                return SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS;
+            }
+        }
+        // make sure card is ready
+        tickstart = us_ticker_read();
+        while (sdio_get_card_state() != SD_TRANSFER_OK) {
+            // wait until SD ready
+            if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) {
+                unlock();
+                return SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS;
+            }
+        }
+    } else {
+        debug_if(SDIO_DBG, "SDIO read_blocks failed! addr: %lld  block_count: %lld \n", addr, block_count);
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS;
+    }
+#else
+    status = sdio_read_blocks(_buffer, addr, block_count);
+    debug_if(SDIO_DBG, "SDIO read blocks dbgtest addr: %lld  block_count: %lld \n", addr, block_count);
+
+    if (status != MSD_OK) {
+        debug_if(SDIO_DBG, "SDIO read blocks failed! addr: %lld  block_count: %lld \n", addr, block_count);
+        status = SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS;
+    }
+#endif
+
+    unlock();
+    return status;
+}
+
+int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
+{
+    int status = 0;
+    lock();
+
+    if (is_present() == false) {
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE;
+    }
+
+    if (!_is_initialized) {
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_NO_INIT;
+    }
+
+    if (!is_valid_program(addr, size)) {
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_PARAMETER;
+    }
+
+    uint8_t *_buffer = (uint8_t *)(buffer);
+
+    // Get block count
+    bd_size_t block_count = size / _block_size;
+    addr = addr / _block_size;
+
+#if DEVICE_SDIO_ASYNC
+    // make sure card is ready
+    {
+        uint32_t tickstart = us_ticker_read();
+        while (sdio_get_card_state() != SD_TRANSFER_OK) {
+            // wait until SD ready
+            if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) {
+                unlock();
+                return SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS;
+            }
+        }
+    }
+
+    status = sdio_write_blocks_async(_buffer, addr, block_count);
+    debug_if(SDIO_DBG, "SDIO write blocks async dbgtest addr: %lld  block_count: %lld \n", addr, block_count);
+
+    if (status == MSD_OK) {
+        // wait until DMA finished
+        uint32_t tickstart = us_ticker_read();
+        while (sdio_write_pending() != SD_TRANSFER_OK) {
+            if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) {
+                unlock();
+                return SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS;
+            }
+        }
+        // make sure card is ready
+        tickstart = us_ticker_read();
+        while (sdio_get_card_state() != SD_TRANSFER_OK) {
+            // wait until SD ready
+            if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) {
+                unlock();
+                return SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS;
+            }
+        }
+    } else {
+        debug_if(SDIO_DBG, "SDIO write blocks async failed! addr: %lld  block_count: %lld \n", addr, block_count);
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS;
+    }
+#else
+    status = sdio_write_blocks(_buffer, addr, block_count);
+
+    debug_if(SDIO_DBG, "SDIO write blocks dbgtest addr: %lld  block_count: %lld \n", addr, block_count);
+
+    if (status != MSD_OK) {
+        debug_if(SDIO_DBG, "SDIO write blocks failed! addr: %lld  block_count: %lld \n", addr, block_count);
+        status = SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS;
+    }
+#endif
+
+    unlock();
+    return status;
+}
+
+int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size)
+{
+    debug_if(SDIO_DBG, "SDIO trim Card...\r\n");
+    lock();
+    if (is_present() == false) {
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE;
+    }
+
+    if (!_is_initialized) {
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_NO_INIT;
+    }
+
+    if (!_is_valid_trim(addr, size)) {
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_PARAMETER;
+    }
+
+    bd_size_t block_count = size / _block_size;
+    addr = addr / _block_size;
+
+    int status = sdio_erase(addr, block_count);
+    if (status != 0) {
+        debug_if(SDIO_DBG, "SDIO erase blocks failed! addr: %lld  block_count: %lld \n", addr, block_count);
+        unlock();
+        return SDIO_BLOCK_DEVICE_ERROR_ERASE_BLOCKS;
+#if DEVICE_SDIO_ASYNC
+    } else {
+        uint32_t tickstart = us_ticker_read();
+        while (sdio_get_card_state() != SD_TRANSFER_OK) {
+            // wait until SD ready
+            if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) {
+                unlock();
+                return SDIO_BLOCK_DEVICE_ERROR_ERASE_BLOCKS;
+            }
+        }
+#endif
+    }
+
+    unlock();
+    return status;
+}
+
+bd_size_t SDIOBlockDevice::get_read_size() const
+{
+    return _block_size;
+}
+
+bd_size_t SDIOBlockDevice::get_program_size() const
+{
+    return _block_size;
+}
+
+bd_size_t SDIOBlockDevice::size() const
+{
+    return _block_size * _sectors;
+}
+
+void SDIOBlockDevice::debug(bool dbg)
+{
+}
+
+bool SDIOBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size) const
+{
+    return (
+               addr % _erase_size == 0 &&
+               size % _erase_size == 0 &&
+               addr + size <= this->size());
+}
+
+bool SDIOBlockDevice::is_present(void)
+{
+    if (_card_detect.is_connected()) {
+        return (_card_detect.read() == 0);
+    } else {
+        return true;
+    }
+}
+
+const char *SDIOBlockDevice::get_type() const
+{
+    return "SDIO";
+}
+
+#endif //DEVICE_SDIO
diff -r 000000000000 -r d90c6c9a7600 storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h	Wed Nov 11 03:05:14 2020 +0000
@@ -0,0 +1,150 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2019 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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_OS_SDIO_BLOCK_DEVICE_H_
+#define MBED_OS_SDIO_BLOCK_DEVICE_H_
+
+#if DEVICE_SDIO
+
+#include "BlockDevice.h"
+#include "drivers/DigitalIn.h"
+#include "platform/PlatformMutex.h"
+#include "sdio_api.h"
+
+#ifndef MBED_CONF_SDIO_CD
+#define MBED_CONF_SDIO_CD NC
+#endif
+
+class SDIOBlockDevice : public mbed::BlockDevice {
+public:
+    SDIOBlockDevice(PinName card_detect = MBED_CONF_SDIO_CD);
+    virtual ~SDIOBlockDevice();
+    /** Initialize a block device
+     *
+     *  @return         0 on success or a negative error code on failure
+     */
+    virtual int init();
+
+    /** Deinitialize a block device
+     *
+     *  @return         0 on success or a negative error code on failure
+     */
+    virtual int deinit();
+
+    /** Read blocks from a block device
+     *
+     *  @param buffer   Buffer to write blocks to
+     *  @param addr     Address of block to begin reading from
+     *  @param size     Size to read in bytes, must be a multiple of read block size
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
+
+    /** Program blocks to a block device
+     *
+     *  The blocks must have been erased prior to being programmed
+     *
+     *  @param buffer   Buffer of data to write to blocks
+     *  @param addr     Address of block to begin writing to
+     *  @param size     Size to write in bytes, must be a multiple of program block size
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
+
+    /** Mark blocks as no longer in use
+     *
+     *  This function provides a hint to the underlying block device that a region of blocks
+     *  is no longer in use and may be erased without side effects. Erase must still be called
+     *  before programming, but trimming allows flash-translation-layers to schedule erases when
+     *  the device is not busy.
+     *
+     *  @param addr     Address of block to mark as unused
+     *  @param size     Size to mark as unused in bytes, must be a multiple of erase block size
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int trim(bd_addr_t addr, bd_size_t size);
+
+    /** Get the size of a readable block
+     *
+     *  @return         Size of a readable block in bytes
+     */
+    virtual bd_size_t get_read_size() const;
+
+    /** Get the size of a programable block
+     *
+     *  @return         Size of a programable block in bytes
+     *  @note Must be a multiple of the read size
+     */
+    virtual bd_size_t get_program_size() const;
+
+    /** Get the total size of the underlying device
+     *
+     *  @return         Size of the underlying device in bytes
+     */
+    virtual bd_size_t size() const;
+
+    /** Enable or disable debugging
+     *
+     *  @param dbg        State of debugging
+     */
+    virtual void debug(bool dbg);
+
+    /** Set the transfer frequency
+     *
+     *  @param freq     Transfer frequency
+     *  @note Max frequency supported is 25MHZ
+     */
+    virtual int frequency(uint64_t freq)
+    {
+        return BD_ERROR_OK;
+    };
+
+    /** check if SD is present
+     *
+     *  @note check physical present switch. Maybe not support by hardware, then function will always return true.
+     */
+    virtual bool is_present(void);
+
+    /** Get the BlockDevice class type.
+     *
+     *  @return         A string representation of the BlockDevice class type.
+     */
+    virtual const char *get_type() const;
+
+private:
+    mbed::DigitalIn _card_detect;
+    bool _is_initialized;
+    bd_size_t _block_size;
+    bd_size_t _erase_size;
+    bd_size_t _sectors;
+    uint32_t _init_ref_count;
+    sdio_card_info_t _card_info;
+
+    PlatformMutex _mutex;
+    virtual void lock() {
+        _mutex.lock();
+    }
+
+    virtual void unlock() {
+        _mutex.unlock();
+    }
+
+    bool _is_valid_trim(bd_addr_t addr, bd_size_t size) const;
+};
+
+#endif // DEVICE_SDIO
+#endif // MBED_OS_SDIO_BLOCK_DEVICE_H_
diff -r 000000000000 -r d90c6c9a7600 storage/blockdevice/COMPONENT_SDIO/mbed_lib.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/blockdevice/COMPONENT_SDIO/mbed_lib.json	Wed Nov 11 03:05:14 2020 +0000
@@ -0,0 +1,12 @@
+{
+    "name": "sdio",
+    "config": {
+        "CMD_TIMEOUT": 30000,
+        "CD": "NC"
+    },
+    "target_overrides": {
+        "DISCO_F469NI": {
+            "CMD_TIMEOUT": 30000
+        }
+    }
+}
diff -r 000000000000 -r d90c6c9a7600 targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c	Wed Nov 11 03:05:14 2020 +0000
@@ -0,0 +1,164 @@
+/* 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_api.h"
+
+#if DEVICE_SDIO
+
+static sd_card_t g_sd;
+
+extern void sdio_clock_setup(void);
+
+int 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;
+
+    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 MSD_ERROR;
+    }
+
+    return MSD_OK;
+}
+
+int sdio_deinit(void)
+{
+    SD_Deinit(&g_sd);
+
+    return MSD_OK;
+}
+
+int sdio_read_blocks(uint8_t *data, uint32_t address, uint32_t block_count)
+{
+    int sd_state = MSD_OK;
+
+    if (SD_ReadBlocks(&g_sd, data, address, block_count) != kStatus_Success) {
+        sd_state = MSD_ERROR;
+    }
+
+    return sd_state;
+}
+
+int sdio_write_blocks(uint8_t *data, uint32_t address, uint32_t block_count)
+{
+    int sd_state = MSD_OK;
+
+    if (SD_WriteBlocks(&g_sd, data, address, block_count) != kStatus_Success) {
+        sd_state = MSD_ERROR;
+    }
+
+    return sd_state;
+}
+
+int sdio_erase(uint32_t start_address, uint32_t end_address)
+{
+    int sd_state = MSD_OK;
+
+    uint32_t blocks = (end_address - start_address) / g_sd.blockSize;
+    if (SD_EraseBlocks(&g_sd, start_address, blocks) != kStatus_Success) {
+        sd_state = MSD_ERROR;
+    }
+
+    return sd_state;
+}
+
+int sdio_get_card_state(void)
+{
+    int sd_state = MSD_OK;
+
+    if (!SD_CheckReadOnly(&g_sd)) {
+        sd_state = MSD_ERROR;
+    }
+
+    return sd_state;
+}
+
+void sdio_get_card_info(sdio_card_info_t *card_info)
+{
+    card_info->card_type = 4;
+    card_info->card_version = g_sd.version;
+    card_info->card_class = 0;
+    card_info->rel_card_addr = g_sd.relativeAddress;
+    card_info->block_count = g_sd.blockCount;
+    card_info->block_size = g_sd.blockSize;
+    card_info->log_block_count = g_sd.blockCount;
+    card_info->log_block_size = g_sd.blockSize;
+}
+
+#endif // DEVICE_SDIO
diff -r 000000000000 -r d90c6c9a7600 targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/board.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/board.h	Wed Nov 11 03:05:14 2020 +0000
@@ -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 -r 000000000000 -r d90c6c9a7600 targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.c	Wed Nov 11 03:05:14 2020 +0000
@@ -0,0 +1,1973 @@
+/*
+ * 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 inline status_t 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 inline status_t 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 inline status_t 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 inline status_t 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 inline status_t SD_SendApplicationCmd(sd_card_t *card, uint32_t relativeAddress)
+{
+    assert(card);
+
+    return SDMMC_SendApplicationCommand(card->host.base, card->host.transfer, relativeAddress);
+}
+
+static inline status_t SD_GoIdle(sd_card_t *card)
+{
+    assert(card);
+
+    return SDMMC_GoIdle(card->host.base, card->host.transfer);
+}
+
+static inline status_t SD_SetBlockSize(sd_card_t *card, uint32_t blockSize)
+{
+    assert(card);
+
+    return SDMMC_SetBlockSize(card->host.base, card->host.transfer, blockSize);
+}
+
+static inline status_t 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");
+
+                /* FALLTHROUGH */
+
+            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");
+
+                /* FALLTHROUGH */
+
+            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");
+
+                /* FALLTHROUGH */
+
+            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 -r 000000000000 -r d90c6c9a7600 targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.h	Wed Nov 11 03:05:14 2020 +0000
@@ -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 -r 000000000000 -r d90c6c9a7600 targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_common.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_common.c	Wed Nov 11 03:05:14 2020 +0000
@@ -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 -r 000000000000 -r d90c6c9a7600 targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_common.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_common.h	Wed Nov 11 03:05:14 2020 +0000
@@ -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 -r 000000000000 -r d90c6c9a7600 targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_host.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_host.c	Wed Nov 11 03:05:14 2020 +0000
@@ -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 -r 000000000000 -r d90c6c9a7600 targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_host.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_host.h	Wed Nov 11 03:05:14 2020 +0000
@@ -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 -r 000000000000 -r d90c6c9a7600 targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_spec.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_spec.h	Wed Nov 11 03:05:14 2020 +0000
@@ -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 <stdint.h>
+
+/*******************************************************************************
+ * 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 -r 000000000000 -r d90c6c9a7600 targets/TARGET_STM/TARGET_STM32F4/sdio_api.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c	Wed Nov 11 03:05:14 2020 +0000
@@ -0,0 +1,439 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2017 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 "sdio_api.h"
+#include "platform/mbed_error.h"
+
+
+#if DEVICE_SDIO
+#define CMD_TIMEOUT 30000
+/* Extern variables ---------------------------------------------------------*/
+
+SD_HandleTypeDef hsd;
+DMA_HandleTypeDef hdma_sdio_rx;
+DMA_HandleTypeDef hdma_sdio_tx;
+
+// simple flags for DMA pending signaling
+volatile int SD_DMA_ReadPendingState = SD_TRANSFER_OK;
+volatile int SD_DMA_WritePendingState = SD_TRANSFER_OK;
+
+/* DMA Handlers are global, there is only one SDIO interface */
+
+/**
+* @brief This function handles SDIO global interrupt.
+*/
+void _SDIO_IRQHandler(void)
+{
+    HAL_SD_IRQHandler(&hsd);
+}
+
+/**
+* @brief This function handles DMAx stream_n global interrupt. DMA Rx
+*/
+void _DMA_Stream_Rx_IRQHandler(void)
+{
+    HAL_DMA_IRQHandler(hsd.hdmarx);
+}
+
+/**
+* @brief This function handles DMAx stream_n global interrupt. DMA Tx
+*/
+void _DMA_Stream_Tx_IRQHandler(void)
+{
+    HAL_DMA_IRQHandler(hsd.hdmatx);
+}
+
+/**
+ *
+ * @param hsd:  Handle for SD handle Structure definition
+ */
+void HAL_SD_MspInit(SD_HandleTypeDef *hsd)
+{
+    IRQn_Type IRQn;
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    if (hsd->Instance == SDIO)
+    {
+        /* Peripheral clock enable */
+        __HAL_RCC_SDIO_CLK_ENABLE();
+        __HAL_RCC_DMA2_CLK_ENABLE();
+
+        /* Enable GPIOs clock */
+        __HAL_RCC_GPIOC_CLK_ENABLE();
+        __HAL_RCC_GPIOD_CLK_ENABLE();
+
+        /**SDIO GPIO Configuration
+         PC12     ------> SDIO_CK
+         PC11     ------> SDIO_D3
+         PC10     ------> SDIO_D2
+         PD2     ------> SDIO_CMD
+         PC9     ------> SDIO_D1
+         PC8     ------> SDIO_D0
+         */
+        GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_11 | GPIO_PIN_10 | GPIO_PIN_9 | GPIO_PIN_8;
+        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+        GPIO_InitStruct.Pull = GPIO_PULLUP;
+        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+        GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
+        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+        GPIO_InitStruct.Pin = GPIO_PIN_2;
+        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+        GPIO_InitStruct.Pull = GPIO_PULLUP;
+        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+        GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
+        HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
+
+        /* NVIC configuration for SDIO interrupts */
+        IRQn = SDIO_IRQn;
+        HAL_NVIC_SetPriority(IRQn, 0x0E, 0);
+        NVIC_SetVector(IRQn, (uint32_t)&_SDIO_IRQHandler);
+        HAL_NVIC_EnableIRQ(IRQn);
+
+        /* SDIO DMA Init */
+        /* SDIO_RX Init */
+        hdma_sdio_rx.Instance = DMA2_Stream3;
+        hdma_sdio_rx.Init.Channel = DMA_CHANNEL_4;
+        hdma_sdio_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
+        hdma_sdio_rx.Init.PeriphInc = DMA_PINC_DISABLE;
+        hdma_sdio_rx.Init.MemInc = DMA_MINC_ENABLE;
+        hdma_sdio_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+        hdma_sdio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
+        hdma_sdio_rx.Init.Mode = DMA_PFCTRL;
+        hdma_sdio_rx.Init.Priority = DMA_PRIORITY_LOW;
+        hdma_sdio_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
+        hdma_sdio_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
+        hdma_sdio_rx.Init.MemBurst = DMA_MBURST_INC4;
+        hdma_sdio_rx.Init.PeriphBurst = DMA_PBURST_INC4;
+        if (HAL_DMA_Init(&hdma_sdio_rx) != HAL_OK)
+        {
+            error("SDIO DMA Init error at %d in %s", __LINE__, __FILE__);
+        }
+
+        __HAL_LINKDMA(hsd, hdmarx, hdma_sdio_rx);
+
+        /* Deinitialize the stream for new transfer */
+        HAL_DMA_DeInit(&hdma_sdio_rx);
+
+        /* Configure the DMA stream */
+        HAL_DMA_Init(&hdma_sdio_rx);
+
+        /* SDIO_TX Init */
+        hdma_sdio_tx.Instance = DMA2_Stream6;
+        hdma_sdio_tx.Init.Channel = DMA_CHANNEL_4;
+        hdma_sdio_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
+        hdma_sdio_tx.Init.PeriphInc = DMA_PINC_DISABLE;
+        hdma_sdio_tx.Init.MemInc = DMA_MINC_ENABLE;
+        hdma_sdio_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+        hdma_sdio_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
+        hdma_sdio_tx.Init.Mode = DMA_PFCTRL;
+        hdma_sdio_tx.Init.Priority = DMA_PRIORITY_LOW;
+        hdma_sdio_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
+        hdma_sdio_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
+        hdma_sdio_tx.Init.MemBurst = DMA_MBURST_INC4;
+        hdma_sdio_tx.Init.PeriphBurst = DMA_PBURST_INC4;
+        if (HAL_DMA_Init(&hdma_sdio_tx) != HAL_OK)
+        {
+            error("SDIO DMA Init error at %d in %s", __LINE__, __FILE__);
+        }
+
+        __HAL_LINKDMA(hsd, hdmatx, hdma_sdio_tx);
+
+        /* Deinitialize the stream for new transfer */
+        HAL_DMA_DeInit(&hdma_sdio_tx);
+
+        /* Configure the DMA stream */
+        HAL_DMA_Init(&hdma_sdio_tx);
+
+        /* Enable NVIC for DMA transfer complete interrupts */
+        IRQn = DMA2_Stream3_IRQn;
+        NVIC_SetVector(IRQn, (uint32_t)&_DMA_Stream_Rx_IRQHandler);
+        HAL_NVIC_SetPriority(IRQn, 0x0F, 0);
+        HAL_NVIC_EnableIRQ(IRQn);
+
+        IRQn = DMA2_Stream6_IRQn;
+        NVIC_SetVector(IRQn, (uint32_t)&_DMA_Stream_Tx_IRQHandler);
+        HAL_NVIC_SetPriority(IRQn, 0x0F, 0);
+        HAL_NVIC_EnableIRQ(IRQn);
+    }
+}
+
+/**
+ *
+ * @param hsd:  Handle for SD handle Structure definition
+ */
+void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd)
+{
+
+    if (hsd->Instance == SDIO)
+    {
+        /* Peripheral clock disable */
+        __HAL_RCC_SDIO_CLK_DISABLE();
+
+        /**SDIO GPIO Configuration
+         PC12     ------> SDIO_CK
+         PC11     ------> SDIO_D3
+         PC10     ------> SDIO_D2
+         PD2     ------> SDIO_CMD
+         PC9     ------> SDIO_D1
+         PC8     ------> SDIO_D0
+         */
+        HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12 | GPIO_PIN_11 | GPIO_PIN_10 | GPIO_PIN_9 | GPIO_PIN_8);
+
+        HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);
+
+        /* SDIO DMA DeInit */
+        HAL_DMA_DeInit(hsd->hdmarx);
+        HAL_DMA_DeInit(hsd->hdmatx);
+    }
+}
+
+/**
+ * @brief  DeInitializes the SD MSP.
+ * @param  hsd: SD handle
+ * @param  Params : pointer on additional configuration parameters, can be NULL.
+ */
+void SD_MspDeInit(SD_HandleTypeDef *hsd, void *Params)
+{
+    static DMA_HandleTypeDef dma_rx_handle;
+    static DMA_HandleTypeDef dma_tx_handle;
+
+    /* Disable NVIC for DMA transfer complete interrupts */
+    HAL_NVIC_DisableIRQ(DMA2_Stream3_IRQn);
+    HAL_NVIC_DisableIRQ(DMA2_Stream6_IRQn);
+
+    /* Deinitialize the stream for new transfer */
+    dma_rx_handle.Instance = DMA2_Stream3;
+    HAL_DMA_DeInit(&dma_rx_handle);
+
+    /* Deinitialize the stream for new transfer */
+    dma_tx_handle.Instance = DMA2_Stream6;
+    HAL_DMA_DeInit(&dma_tx_handle);
+
+    /* Disable NVIC for SDIO interrupts */
+    HAL_NVIC_DisableIRQ(SDIO_IRQn);
+
+    /* Disable SDIO clock */
+    __HAL_RCC_SDIO_CLK_DISABLE();
+}
+
+/**
+  * @brief  Enables the SDIO wide bus mode.
+  * @param  hsd pointer to SD handle
+  * @retval error state
+  */
+static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd)
+{
+    uint32_t errorstate = HAL_SD_ERROR_NONE;
+
+    if ((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
+    {
+        return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
+    }
+
+    /* Send CMD55 APP_CMD with argument as card's RCA.*/
+    errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
+    if (errorstate != HAL_OK)
+    {
+        return errorstate;
+    }
+
+    /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */
+    errorstate = SDMMC_CmdBusWidth(hsd->Instance, 2U);
+    if (errorstate != HAL_OK)
+    {
+        return errorstate;
+    }
+
+    hsd->Init.BusWide = SDIO_BUS_WIDE_4B;
+    SDIO_Init(hsd->Instance, hsd->Init);
+
+    return HAL_SD_ERROR_NONE;
+}
+
+int sdio_init(void)
+{
+    int sd_state = MSD_OK;
+
+    hsd.Instance = SDIO;
+    hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
+    hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
+    hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
+    hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
+    hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
+    hsd.Init.ClockDiv = 0;
+
+    /* HAL SD initialization */
+    sd_state = HAL_SD_Init(&hsd);
+    /* Configure SD Bus width (4 bits mode selected) */
+    if (sd_state == MSD_OK)
+    {
+        /* Enable wide operation */
+        if (SD_WideBus_Enable(&hsd) != HAL_OK)
+        {
+            sd_state = MSD_ERROR;
+        }
+    }
+
+    return sd_state;
+}
+
+int sdio_deinit(void)
+{
+    int sd_state = MSD_OK;
+
+    hsd.Instance = SDIO;
+
+    /* HAL SD deinitialization */
+    if (HAL_SD_DeInit(&hsd) != HAL_OK)
+    {
+        sd_state = MSD_ERROR;
+    }
+
+    /* Msp SD deinitialization */
+    hsd.Instance = SDIO;
+    SD_MspDeInit(&hsd, NULL);
+
+    return sd_state;
+}
+
+int sdio_read_blocks(uint8_t *data, uint32_t address, uint32_t block_count)
+{
+    int sd_state = MSD_OK;
+
+    if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)data, address, block_count, CMD_TIMEOUT) != HAL_OK)
+    {
+        sd_state = MSD_ERROR;
+    }
+
+    return sd_state;
+}
+
+int sdio_write_blocks(uint8_t *data, uint32_t address, uint32_t block_count)
+{
+    int sd_state = MSD_OK;
+
+    if (HAL_SD_WriteBlocks(&hsd, data, address, block_count, CMD_TIMEOUT) != HAL_OK)
+    {
+        sd_state = MSD_ERROR;
+    }
+
+    return sd_state;
+}
+
+#if DEVICE_SDIO_ASYNC
+
+int sdio_read_blocks_async(uint8_t *data, uint32_t address, uint32_t block_count)
+{
+    int sd_state = MSD_OK;
+    SD_DMA_ReadPendingState = SD_TRANSFER_BUSY;
+
+    /* Read block(s) in DMA transfer mode */
+    if (HAL_SD_ReadBlocks_DMA(&hsd, data, address, block_count) != HAL_OK)
+    {
+        sd_state = MSD_ERROR;
+        SD_DMA_ReadPendingState = SD_TRANSFER_OK;
+    }
+
+    return sd_state;
+}
+
+int sdio_write_blocks_async(uint8_t *data, uint32_t address, uint32_t block_count)
+{
+    int sd_state = MSD_OK;
+    SD_DMA_WritePendingState = SD_TRANSFER_BUSY;
+
+    /* Write block(s) in DMA transfer mode */
+    if (HAL_SD_WriteBlocks_DMA(&hsd, data, address, block_count) != HAL_OK)
+    {
+        sd_state = MSD_ERROR;
+        SD_DMA_WritePendingState = SD_TRANSFER_OK;
+    }
+
+    return sd_state;
+}
+
+#endif // DEVICE_SDIO_ASYNC
+
+int sdio_erase(uint32_t start_address, uint32_t end_address)
+{
+    int sd_state = MSD_OK;
+
+    if (HAL_SD_Erase(&hsd, start_address, end_address) != HAL_OK)
+    {
+        sd_state = MSD_ERROR;
+    }
+
+    return sd_state;
+}
+
+int sdio_get_card_state(void)
+{
+    return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY);
+}
+
+void sdio_get_card_info(sdio_card_info_t *card_info)
+{
+    /* Get SD card Information, copy structure for portability */
+    HAL_SD_CardInfoTypeDef HAL_CardInfo;
+
+    HAL_SD_GetCardInfo(&hsd, &HAL_CardInfo);
+
+    if (card_info)
+    {
+        card_info->card_type = HAL_CardInfo.CardType;
+        card_info->card_version = HAL_CardInfo.CardVersion;
+        card_info->card_class = HAL_CardInfo.Class;
+        card_info->rel_card_addr = HAL_CardInfo.RelCardAdd;
+        card_info->block_count = HAL_CardInfo.BlockNbr;
+        card_info->block_size = HAL_CardInfo.BlockSize;
+        card_info->log_block_count = HAL_CardInfo.LogBlockNbr;
+        card_info->log_block_size = HAL_CardInfo.LogBlockSize;
+    }
+}
+
+int sdio_read_pending(void)
+{
+    return SD_DMA_ReadPendingState;
+}
+
+int sdio_write_pending(void)
+{
+    return SD_DMA_WritePendingState;
+}
+
+/**
+  * @brief Rx Transfer completed callbacks
+  * @param hsd Pointer SD handle
+  * @retval None
+  */
+void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
+{
+    SD_DMA_ReadPendingState = SD_TRANSFER_OK;
+}
+
+/**
+  * @brief Tx Transfer completed callbacks
+  * @param hsd Pointer to SD handle
+  * @retval None
+  */
+void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
+{
+    SD_DMA_WritePendingState = SD_TRANSFER_OK;
+}
+
+#endif // DEVICE_SDIO
diff -r 000000000000 -r d90c6c9a7600 targets/TARGET_STM/TARGET_STM32F7/sdio_api.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c	Wed Nov 11 03:05:14 2020 +0000
@@ -0,0 +1,434 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2017 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 "sdio_api.h"
+#include "platform/mbed_error.h"
+
+#if DEVICE_SDIO
+#define CMD_TIMEOUT 30000
+/* Extern variables ---------------------------------------------------------*/
+
+SD_HandleTypeDef hsd;
+DMA_HandleTypeDef hdma_sdmmc_rx;
+DMA_HandleTypeDef hdma_sdmmc_tx;
+
+// simple flags for DMA pending signaling
+volatile int SD_DMA_ReadPendingState = SD_TRANSFER_OK;
+volatile int SD_DMA_WritePendingState = SD_TRANSFER_OK;
+
+/* DMA Handlers are global, there is only one SDIO interface */
+
+/**
+* @brief This function handles SDMMC global interrupt.
+*/
+void _SDMMC_IRQHandler(void)
+{
+    HAL_SD_IRQHandler(&hsd);
+}
+
+/**
+* @brief This function handles DMAx stream_n global interrupt. DMA Rx
+*/
+void _DMA_Stream_Rx_IRQHandler(void)
+{
+    HAL_DMA_IRQHandler(hsd.hdmarx);
+}
+
+/**
+* @brief This function handles DMAx stream_n global interrupt. DMA Tx
+*/
+void _DMA_Stream_Tx_IRQHandler(void)
+{
+    HAL_DMA_IRQHandler(hsd.hdmatx);
+}
+
+/**
+ *
+ * @param hsd:  Handle for SD handle Structure definition
+ */
+void HAL_SD_MspInit(SD_HandleTypeDef *hsd)
+{
+    IRQn_Type IRQn;
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    if (hsd->Instance == SDMMC1)
+    {
+        /* Peripheral clock enable */
+        __HAL_RCC_SDMMC1_CLK_ENABLE();
+        __HAL_RCC_DMA2_CLK_ENABLE();
+
+        /* Enable GPIOs clock */
+        __HAL_RCC_GPIOC_CLK_ENABLE();
+        __HAL_RCC_GPIOD_CLK_ENABLE();
+
+        /** SDMMC GPIO Configuration
+         PC12     ------> SDIO_CK
+         PC11     ------> SDIO_D3
+         PC10     ------> SDIO_D2
+         PD2     ------> SDIO_CMD
+         PC9     ------> SDIO_D1
+         PC8     ------> SDIO_D0
+         */
+        GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_11 | GPIO_PIN_10 | GPIO_PIN_9 | GPIO_PIN_8;
+        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+        GPIO_InitStruct.Pull = GPIO_PULLUP;
+        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+        GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
+        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+        GPIO_InitStruct.Pin = GPIO_PIN_2;
+        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+        GPIO_InitStruct.Pull = GPIO_PULLUP;
+        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+        GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
+        HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
+
+        /* NVIC configuration for SDMMC interrupts */
+        IRQn = SDMMC1_IRQn;
+        HAL_NVIC_SetPriority(IRQn, 0x0E, 0);
+        NVIC_SetVector(IRQn, (uint32_t)&_SDMMC_IRQHandler);
+        HAL_NVIC_EnableIRQ(IRQn);
+
+        /* SDMMC DMA Init */
+        /* SDMMC_RX Init */
+        hdma_sdmmc_rx.Instance = DMA2_Stream3;
+        hdma_sdmmc_rx.Init.Channel = DMA_CHANNEL_4;
+        hdma_sdmmc_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
+        hdma_sdmmc_rx.Init.PeriphInc = DMA_PINC_DISABLE;
+        hdma_sdmmc_rx.Init.MemInc = DMA_MINC_ENABLE;
+        hdma_sdmmc_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+        hdma_sdmmc_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
+        hdma_sdmmc_rx.Init.Mode = DMA_PFCTRL;
+        hdma_sdmmc_rx.Init.Priority = DMA_PRIORITY_LOW;
+        hdma_sdmmc_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
+        hdma_sdmmc_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
+        hdma_sdmmc_rx.Init.MemBurst = DMA_MBURST_INC4;
+        hdma_sdmmc_rx.Init.PeriphBurst = DMA_PBURST_INC4;
+        if (HAL_DMA_Init(&hdma_sdmmc_rx) != HAL_OK)
+        {
+            error("SDMMC DMA Init error at %d in %s", __LINE__, __FILE__);
+        }
+
+        __HAL_LINKDMA(hsd, hdmarx, hdma_sdmmc_rx);
+
+        /* Deinitialize the stream for new transfer */
+        HAL_DMA_DeInit(&hdma_sdmmc_rx);
+
+        /* Configure the DMA stream */
+        HAL_DMA_Init(&hdma_sdmmc_rx);
+
+        /* SDMMC_TX Init */
+        hdma_sdmmc_tx.Instance = DMA2_Stream6;
+        hdma_sdmmc_tx.Init.Channel = DMA_CHANNEL_4;
+        hdma_sdmmc_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
+        hdma_sdmmc_tx.Init.PeriphInc = DMA_PINC_DISABLE;
+        hdma_sdmmc_tx.Init.MemInc = DMA_MINC_ENABLE;
+        hdma_sdmmc_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+        hdma_sdmmc_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
+        hdma_sdmmc_tx.Init.Mode = DMA_PFCTRL;
+        hdma_sdmmc_tx.Init.Priority = DMA_PRIORITY_LOW;
+        hdma_sdmmc_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
+        hdma_sdmmc_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
+        hdma_sdmmc_tx.Init.MemBurst = DMA_MBURST_INC4;
+        hdma_sdmmc_tx.Init.PeriphBurst = DMA_PBURST_INC4;
+        if (HAL_DMA_Init(&hdma_sdmmc_tx) != HAL_OK)
+        {
+            error("SDMMC DMA Init error at %d in %s", __LINE__, __FILE__);
+        }
+
+        __HAL_LINKDMA(hsd, hdmatx, hdma_sdmmc_tx);
+
+        /* Deinitialize the stream for new transfer */
+        HAL_DMA_DeInit(&hdma_sdmmc_tx);
+
+        /* Configure the DMA stream */
+        HAL_DMA_Init(&hdma_sdmmc_tx);
+
+        /* Enable NVIC for DMA transfer complete interrupts */
+        IRQn = DMA2_Stream3_IRQn;
+        NVIC_SetVector(IRQn, (uint32_t)&_DMA_Stream_Rx_IRQHandler);
+        HAL_NVIC_SetPriority(IRQn, 0x0F, 0);
+        HAL_NVIC_EnableIRQ(IRQn);
+
+        IRQn = DMA2_Stream6_IRQn;
+        NVIC_SetVector(IRQn, (uint32_t)&_DMA_Stream_Tx_IRQHandler);
+        HAL_NVIC_SetPriority(IRQn, 0x0F, 0);
+        HAL_NVIC_EnableIRQ(IRQn);
+    }
+}
+
+/**
+ *
+ * @param hsd:  Handle for SD handle Structure definition
+ */
+void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd)
+{
+
+    if (hsd->Instance == SDMMC1)
+    {
+        /* Peripheral clock disable */
+        __HAL_RCC_SDMMC1_CLK_DISABLE();
+
+        /** SDSDMMC1 GPIO Configuration
+         PC12     ------> SDIO_CK
+         PC11     ------> SDIO_D3
+         PC10     ------> SDIO_D2
+         PD2     ------> SDIO_CMD
+         PC9     ------> SDIO_D1
+         PC8     ------> SDIO_D0
+         */
+        HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12 | GPIO_PIN_11 | GPIO_PIN_10 | GPIO_PIN_9 | GPIO_PIN_8);
+
+        HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);
+
+        /* SDMMC1 DMA DeInit */
+        HAL_DMA_DeInit(hsd->hdmarx);
+        HAL_DMA_DeInit(hsd->hdmatx);
+    }
+}
+
+/**
+ * @brief  DeInitializes the SD MSP.
+ * @param  hsd: SD handle
+ * @param  Params : pointer on additional configuration parameters, can be NULL.
+ */
+__weak void SD_MspDeInit(SD_HandleTypeDef *hsd, void *Params)
+{
+    static DMA_HandleTypeDef dma_rx_handle;
+    static DMA_HandleTypeDef dma_tx_handle;
+
+    /* Disable NVIC for DMA transfer complete interrupts */
+    HAL_NVIC_DisableIRQ(DMA2_Stream3_IRQn);
+    HAL_NVIC_DisableIRQ(DMA2_Stream6_IRQn);
+
+    /* Deinitialize the stream for new transfer */
+    dma_rx_handle.Instance = DMA2_Stream3;
+    HAL_DMA_DeInit(&dma_rx_handle);
+
+    /* Deinitialize the stream for new transfer */
+    dma_tx_handle.Instance = DMA2_Stream6;
+    HAL_DMA_DeInit(&dma_tx_handle);
+
+    /* Disable NVIC for SDMMC interrupts */
+    HAL_NVIC_DisableIRQ(SDMMC1_IRQn);
+
+    /* Disable SDMMC clock */
+    __HAL_RCC_SDMMC1_CLK_DISABLE();
+}
+
+/**
+  * @brief  Enables the SD wide bus mode.
+  * @param  hsd pointer to SD handle
+  * @retval error state
+  */
+static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd)
+{
+    uint32_t errorstate = HAL_SD_ERROR_NONE;
+
+    if ((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
+    {
+        return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
+    }
+
+    /* Send CMD55 APP_CMD with argument as card's RCA.*/
+    errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
+    if (errorstate != HAL_OK)
+    {
+        return errorstate;
+    }
+
+    /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */
+    errorstate = SDMMC_CmdBusWidth(hsd->Instance, 2U);
+    if (errorstate != HAL_OK)
+    {
+        return errorstate;
+    }
+
+    hsd->Init.BusWide = SDMMC_BUS_WIDE_4B;
+    SDMMC_Init(hsd->Instance, hsd->Init);
+
+    return HAL_SD_ERROR_NONE;
+}
+
+int sdio_init(void)
+{
+    int sd_state = MSD_OK;
+
+    hsd.Instance = SDMMC1;
+    hsd.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
+    hsd.Init.ClockBypass = SDMMC_CLOCK_BYPASS_DISABLE;
+    hsd.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
+    hsd.Init.BusWide = SDMMC_BUS_WIDE_1B;
+    hsd.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
+    hsd.Init.ClockDiv = 0;
+
+    /* HAL SD initialization */
+    sd_state = HAL_SD_Init(&hsd);
+    /* Configure SD Bus width (4 bits mode selected) */
+    if (sd_state == MSD_OK)
+    {
+        /* Enable wide operation */
+        if (SD_WideBus_Enable(&hsd) != HAL_OK)
+        {
+            sd_state = MSD_ERROR;
+        }
+    }
+
+    return sd_state;
+}
+
+int sdio_deinit(void)
+{
+    int sd_state = MSD_OK;
+
+    hsd.Instance = SDMMC1;
+
+    /* HAL SD deinitialization */
+    if (HAL_SD_DeInit(&hsd) != HAL_OK)
+    {
+        sd_state = MSD_ERROR;
+    }
+
+    /* Msp SD deinitialization */
+    hsd.Instance = SDMMC1;
+    SD_MspDeInit(&hsd, NULL);
+
+    return sd_state;
+}
+
+int sdio_read_blocks(uint8_t *data, uint32_t address, uint32_t block_count)
+{
+    int sd_state = MSD_OK;
+
+    if (HAL_SD_ReadBlocks(&hsd, data, address, block_count, CMD_TIMEOUT) != HAL_OK)
+    {
+        sd_state = MSD_ERROR;
+    }
+
+    return sd_state;
+}
+
+int sdio_write_blocks(uint8_t *data, uint32_t address, uint32_t block_count)
+{
+    int sd_state = MSD_OK;
+
+    if (HAL_SD_WriteBlocks(&hsd, data, address, block_count, CMD_TIMEOUT) != HAL_OK)
+    {
+        sd_state = MSD_ERROR;
+    }
+
+    return sd_state;
+}
+
+int sdio_read_blocks_async(uint8_t *data, uint32_t address, uint32_t block_count)
+{
+    int sd_state = MSD_OK;
+    SD_DMA_ReadPendingState = SD_TRANSFER_BUSY;
+
+    /* Read block(s) in DMA transfer mode */
+    if (HAL_SD_ReadBlocks_DMA(&hsd, data, address, block_count) != HAL_OK)
+    {
+        sd_state = MSD_ERROR;
+        SD_DMA_ReadPendingState = SD_TRANSFER_OK;
+    }
+
+    return sd_state;
+}
+
+int sdio_write_blocks_async(uint8_t *data, uint32_t address, uint32_t block_count)
+{
+    int sd_state = MSD_OK;
+    SD_DMA_WritePendingState = SD_TRANSFER_BUSY;
+
+    /* Write block(s) in DMA transfer mode */
+    if (HAL_SD_WriteBlocks_DMA(&hsd, data, address, block_count) != HAL_OK)
+    {
+        sd_state = MSD_ERROR;
+        SD_DMA_WritePendingState = SD_TRANSFER_OK;
+    }
+
+    return sd_state;
+}
+
+int sdio_erase(uint32_t start_address, uint32_t end_address)
+{
+    int sd_state = MSD_OK;
+
+    if (HAL_SD_Erase(&hsd, start_address, end_address) != HAL_OK)
+    {
+        sd_state = MSD_ERROR;
+    }
+
+    return sd_state;
+}
+
+int sdio_get_card_state(void)
+{
+    return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY);
+}
+
+void sdio_get_card_info(sdio_card_info_t *card_info)
+{
+    /* Get SD card Information, copy structure for portability */
+    HAL_SD_CardInfoTypeDef HAL_CardInfo;
+
+    HAL_SD_GetCardInfo(&hsd, &HAL_CardInfo);
+
+    if (card_info)
+    {
+        card_info->card_type = HAL_CardInfo.CardType;
+        card_info->card_version = HAL_CardInfo.CardVersion;
+        card_info->card_class = HAL_CardInfo.Class;
+        card_info->rel_card_addr = HAL_CardInfo.RelCardAdd;
+        card_info->block_count = HAL_CardInfo.BlockNbr;
+        card_info->block_size = HAL_CardInfo.BlockSize;
+        card_info->log_block_count = HAL_CardInfo.LogBlockNbr;
+        card_info->log_block_size = HAL_CardInfo.LogBlockSize;
+    }
+}
+
+int sdio_read_pending(void)
+{
+    return SD_DMA_ReadPendingState;
+}
+
+int sdio_write_pending(void)
+{
+    return SD_DMA_WritePendingState;
+}
+
+/**
+  * @brief Rx Transfer completed callbacks
+  * @param hsd Pointer SD handle
+  * @retval None
+  */
+void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
+{
+    SD_DMA_ReadPendingState = SD_TRANSFER_OK;
+}
+
+/**
+  * @brief Tx Transfer completed callbacks
+  * @param hsd Pointer to SD handle
+  * @retval None
+  */
+void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
+{
+    SD_DMA_WritePendingState = SD_TRANSFER_OK;
+}
+
+#endif // DEVICE_SDIO