summaryrefslogtreecommitdiff
path: root/drivers/fsl_sdhc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/fsl_sdhc.c')
-rw-r--r--drivers/fsl_sdhc.c1416
1 files changed, 0 insertions, 1416 deletions
diff --git a/drivers/fsl_sdhc.c b/drivers/fsl_sdhc.c
deleted file mode 100644
index 3151cd2..0000000
--- a/drivers/fsl_sdhc.c
+++ /dev/null
@@ -1,1416 +0,0 @@
-/*
- * Copyright (c) 2016, Freescale Semiconductor, Inc.
- * Copyright 2016-2017 NXP
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * o Redistributions of source code must retain the above copyright notice, this list
- * of conditions and the following disclaimer.
- *
- * o Redistributions in binary form must reproduce the above copyright notice, this
- * list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * o Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "fsl_sdhc.h"
-
-/*******************************************************************************
- * Definitions
- ******************************************************************************/
-/*! @brief Clock setting */
-/* Max SD clock divisor from base clock */
-#define SDHC_MAX_DVS ((SDHC_SYSCTL_DVS_MASK >> SDHC_SYSCTL_DVS_SHIFT) + 1U)
-#define SDHC_PREV_DVS(x) ((x) -= 1U)
-#define SDHC_MAX_CLKFS ((SDHC_SYSCTL_SDCLKFS_MASK >> SDHC_SYSCTL_SDCLKFS_SHIFT) + 1U)
-#define SDHC_PREV_CLKFS(x) ((x) >>= 1U)
-
-/* Typedef for interrupt handler. */
-typedef void (*sdhc_isr_t)(SDHC_Type *base, sdhc_handle_t *handle);
-
-/*! @brief ADMA table configuration */
-typedef struct _sdhc_adma_table_config
-{
- uint32_t *admaTable; /*!< ADMA table address, can't be null if transfer way is ADMA1/ADMA2 */
- uint32_t admaTableWords; /*!< ADMA table length united as words, can't be 0 if transfer way is ADMA1/ADMA2 */
-} sdhc_adma_table_config_t;
-
-/*******************************************************************************
- * Prototypes
- ******************************************************************************/
-/*!
- * @brief Get the instance.
- *
- * @param base SDHC peripheral base address.
- * @return Instance number.
- */
-static uint32_t SDHC_GetInstance(SDHC_Type *base);
-
-/*!
- * @brief Set transfer interrupt.
- *
- * @param base SDHC peripheral base address.
- * @param usingInterruptSignal True to use IRQ signal.
- */
-static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal);
-
-/*!
- * @brief Start transfer according to current transfer state
- *
- * @param base SDHC peripheral base address.
- * @param command Command to be sent.
- * @param data Data to be transferred.
- * @param DMA mode selection
- */
-static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data, sdhc_dma_mode_t dmaMode);
-
-/*!
- * @brief Receive command response
- *
- * @param base SDHC peripheral base address.
- * @param command Command to be sent.
- */
-static status_t SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command);
-
-/*!
- * @brief Read DATAPORT when buffer enable bit is set.
- *
- * @param base SDHC peripheral base address.
- * @param data Data to be read.
- * @param transferredWords The number of data words have been transferred last time transaction.
- * @return The number of total data words have been transferred after this time transaction.
- */
-static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords);
-
-/*!
- * @brief Read data by using DATAPORT polling way.
- *
- * @param base SDHC peripheral base address.
- * @param data Data to be read.
- * @retval kStatus_Fail Read DATAPORT failed.
- * @retval kStatus_Success Operate successfully.
- */
-static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data);
-
-/*!
- * @brief Write DATAPORT when buffer enable bit is set.
- *
- * @param base SDHC peripheral base address.
- * @param data Data to be read.
- * @param transferredWords The number of data words have been transferred last time.
- * @return The number of total data words have been transferred after this time transaction.
- */
-static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords);
-
-/*!
- * @brief Write data by using DATAPORT polling way.
- *
- * @param base SDHC peripheral base address.
- * @param data Data to be transferred.
- * @retval kStatus_Fail Write DATAPORT failed.
- * @retval kStatus_Success Operate successfully.
- */
-static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data);
-
-/*!
- * @brief Send command by using polling way.
- *
- * @param base SDHC peripheral base address.
- * @param command Command to be sent.
- * @retval kStatus_Fail Send command failed.
- * @retval kStatus_Success Operate successfully.
- */
-static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *command);
-
-/*!
- * @brief Transfer data by DATAPORT and polling way.
- *
- * @param base SDHC peripheral base address.
- * @param data Data to be transferred.
- * @retval kStatus_Fail Transfer data failed.
- * @retval kStatus_Success Operate successfully.
- */
-static status_t SDHC_TransferByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data);
-
-/*!
- * @brief Transfer data by ADMA2 and polling way.
- *
- * @param base SDHC peripheral base address.
- * @param data Data to be transferred.
- * @retval kStatus_Fail Transfer data failed.
- * @retval kStatus_Success Operate successfully.
- */
-static status_t SDHC_TransferByAdma2Blocking(SDHC_Type *base, sdhc_data_t *data);
-
-/*!
- * @brief Transfer data by polling way.
- *
- * @param dmaMode DMA mode.
- * @param base SDHC peripheral base address.
- * @param data Data to be transferred.
- * @retval kStatus_Fail Transfer data failed.
- * @retval kStatus_InvalidArgument Argument is invalid.
- * @retval kStatus_Success Operate successfully.
- */
-static status_t SDHC_TransferDataBlocking(sdhc_dma_mode_t dmaMode, SDHC_Type *base, sdhc_data_t *data);
-
-/*!
- * @brief Handle card detect interrupt.
- *
- * @param handle SDHC handle.
- * @param interruptFlags Card detect related interrupt flags.
- */
-static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interruptFlags);
-
-/*!
- * @brief Handle command interrupt.
- *
- * @param base SDHC peripheral base address.
- * @param handle SDHC handle.
- * @param interruptFlags Command related interrupt flags.
- */
-static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags);
-
-/*!
- * @brief Handle data interrupt.
- *
- * @param base SDHC peripheral base address.
- * @param handle SDHC handle.
- * @param interruptFlags Data related interrupt flags.
- */
-static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags);
-
-/*!
- * @brief Handle SDIO card interrupt signal.
- *
- * @param handle SDHC handle.
- */
-static void SDHC_TransferHandleSdioInterrupt(sdhc_handle_t *handle);
-
-/*!
- * @brief Handle SDIO block gap event.
- *
- * @param handle SDHC handle.
- */
-static void SDHC_TransferHandleSdioBlockGap(sdhc_handle_t *handle);
-
-/*******************************************************************************
- * Variables
- ******************************************************************************/
-/*! @brief SDHC internal handle pointer array */
-static sdhc_handle_t *s_sdhcHandle[FSL_FEATURE_SOC_SDHC_COUNT];
-
-/*! @brief SDHC base pointer array */
-static SDHC_Type *const s_sdhcBase[] = SDHC_BASE_PTRS;
-
-/*! @brief SDHC IRQ name array */
-static const IRQn_Type s_sdhcIRQ[] = SDHC_IRQS;
-
-#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
-/*! @brief SDHC clock array name */
-static const clock_ip_name_t s_sdhcClock[] = SDHC_CLOCKS;
-#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
-
-/* SDHC ISR for transactional APIs. */
-static sdhc_isr_t s_sdhcIsr;
-
-/*******************************************************************************
- * Code
- ******************************************************************************/
-static uint32_t SDHC_GetInstance(SDHC_Type *base)
-{
- uint8_t instance = 0;
-
- while ((instance < ARRAY_SIZE(s_sdhcBase)) && (s_sdhcBase[instance] != base))
- {
- instance++;
- }
-
- assert(instance < ARRAY_SIZE(s_sdhcBase));
-
- return instance;
-}
-
-static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal)
-{
- uint32_t interruptEnabled; /* The Interrupt status flags to be enabled */
- bool cardDetectDat3 = (bool)(base->PROCTL & SDHC_PROCTL_D3CD_MASK);
-
- /* Disable all interrupts */
- SDHC_DisableInterruptStatus(base, (uint32_t)kSDHC_AllInterruptFlags);
- SDHC_DisableInterruptSignal(base, (uint32_t)kSDHC_AllInterruptFlags);
- DisableIRQ(s_sdhcIRQ[SDHC_GetInstance(base)]);
-
- interruptEnabled =
- (kSDHC_CommandIndexErrorFlag | kSDHC_CommandCrcErrorFlag | kSDHC_CommandEndBitErrorFlag |
- kSDHC_CommandTimeoutFlag | kSDHC_CommandCompleteFlag | kSDHC_DataTimeoutFlag | kSDHC_DataCrcErrorFlag |
- kSDHC_DataEndBitErrorFlag | kSDHC_DataCompleteFlag | kSDHC_AutoCommand12ErrorFlag | kSDHC_BufferReadReadyFlag |
- kSDHC_BufferWriteReadyFlag | kSDHC_DmaErrorFlag | kSDHC_DmaCompleteFlag);
- if (cardDetectDat3)
- {
- interruptEnabled |= (kSDHC_CardInsertionFlag | kSDHC_CardRemovalFlag);
- }
-
- SDHC_EnableInterruptStatus(base, interruptEnabled);
- if (usingInterruptSignal)
- {
- SDHC_EnableInterruptSignal(base, interruptEnabled);
- }
-}
-
-static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data, sdhc_dma_mode_t dmaMode)
-{
- uint32_t flags = 0U;
- sdhc_transfer_config_t sdhcTransferConfig = {0};
-
- /* Define the flag corresponding to each response type. */
- switch (command->responseType)
- {
- case kCARD_ResponseTypeNone:
- break;
- case kCARD_ResponseTypeR1: /* Response 1 */
- flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
- break;
- case kCARD_ResponseTypeR1b: /* Response 1 with busy */
- flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
- break;
- case kCARD_ResponseTypeR2: /* Response 2 */
- flags |= (kSDHC_ResponseLength136Flag | kSDHC_EnableCrcCheckFlag);
- break;
- case kCARD_ResponseTypeR3: /* Response 3 */
- flags |= (kSDHC_ResponseLength48Flag);
- break;
- case kCARD_ResponseTypeR4: /* Response 4 */
- flags |= (kSDHC_ResponseLength48Flag);
- break;
- case kCARD_ResponseTypeR5: /* Response 5 */
- flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
- break;
- case kCARD_ResponseTypeR5b: /* Response 5 with busy */
- flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
- break;
- case kCARD_ResponseTypeR6: /* Response 6 */
- flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
- break;
- case kCARD_ResponseTypeR7: /* Response 7 */
- flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
- break;
- default:
- break;
- }
- if (command->type == kCARD_CommandTypeAbort)
- {
- flags |= kSDHC_CommandTypeAbortFlag;
- }
-
- if (data)
- {
- flags |= kSDHC_DataPresentFlag;
-
- if (dmaMode != kSDHC_DmaModeNo)
- {
- flags |= kSDHC_EnableDmaFlag;
- }
- if (data->rxData)
- {
- flags |= kSDHC_DataReadFlag;
- }
- if (data->blockCount > 1U)
- {
- flags |= (kSDHC_MultipleBlockFlag | kSDHC_EnableBlockCountFlag);
- if (data->enableAutoCommand12)
- {
- /* Enable Auto command 12. */
- flags |= kSDHC_EnableAutoCommand12Flag;
- }
- }
-
- sdhcTransferConfig.dataBlockSize = data->blockSize;
- sdhcTransferConfig.dataBlockCount = data->blockCount;
- }
- else
- {
- sdhcTransferConfig.dataBlockSize = 0U;
- sdhcTransferConfig.dataBlockCount = 0U;
- }
-
- sdhcTransferConfig.commandArgument = command->argument;
- sdhcTransferConfig.commandIndex = command->index;
- sdhcTransferConfig.flags = flags;
- SDHC_SetTransferConfig(base, &sdhcTransferConfig);
-}
-
-static status_t SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command)
-{
- uint32_t i;
-
- if (command->responseType != kCARD_ResponseTypeNone)
- {
- command->response[0U] = SDHC_GetCommandResponse(base, 0U);
- if (command->responseType == kCARD_ResponseTypeR2)
- {
- command->response[1U] = SDHC_GetCommandResponse(base, 1U);
- command->response[2U] = SDHC_GetCommandResponse(base, 2U);
- command->response[3U] = SDHC_GetCommandResponse(base, 3U);
-
- i = 4U;
- /* R3-R2-R1-R0(lowest 8 bit is invalid bit) has the same format as R2 format in SD specification document
- after removed internal CRC7 and end bit. */
- do
- {
- command->response[i - 1U] <<= 8U;
- if (i > 1U)
- {
- command->response[i - 1U] |= ((command->response[i - 2U] & 0xFF000000U) >> 24U);
- }
- } while (i--);
- }
- }
- /* check response error flag */
- if ((command->responseErrorFlags != 0U) &&
- ((command->responseType == kCARD_ResponseTypeR1) || (command->responseType == kCARD_ResponseTypeR1b) ||
- (command->responseType == kCARD_ResponseTypeR6) || (command->responseType == kCARD_ResponseTypeR5)))
- {
- if (((command->responseErrorFlags) & (command->response[0U])) != 0U)
- {
- return kStatus_SDHC_SendCommandFailed;
- }
- }
-
- return kStatus_Success;
-}
-
-static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords)
-{
- uint32_t i;
- uint32_t totalWords;
- uint32_t wordsCanBeRead; /* The words can be read at this time. */
- uint32_t readWatermark = ((base->WML & SDHC_WML_RDWML_MASK) >> SDHC_WML_RDWML_SHIFT);
-
- /*
- * Add non aligned access support ,user need make sure your buffer size is big
- * enough to hold the data,in other words,user need make sure the buffer size
- * is 4 byte aligned
- */
- if (data->blockSize % sizeof(uint32_t) != 0U)
- {
- data->blockSize +=
- sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
- }
-
- totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
-
- /* If watermark level is equal or bigger than totalWords, transfers totalWords data. */
- if (readWatermark >= totalWords)
- {
- wordsCanBeRead = totalWords;
- }
- /* If watermark level is less than totalWords and left words to be sent is equal or bigger than readWatermark,
- transfers watermark level words. */
- else if ((readWatermark < totalWords) && ((totalWords - transferredWords) >= readWatermark))
- {
- wordsCanBeRead = readWatermark;
- }
- /* If watermark level is less than totalWords and left words to be sent is less than readWatermark, transfers left
- words. */
- else
- {
- wordsCanBeRead = (totalWords - transferredWords);
- }
-
- i = 0U;
- while (i < wordsCanBeRead)
- {
- data->rxData[transferredWords++] = SDHC_ReadData(base);
- i++;
- }
-
- return transferredWords;
-}
-
-static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
-{
- uint32_t totalWords;
- uint32_t transferredWords = 0U;
- status_t error = kStatus_Success;
-
- /*
- * Add non aligned access support ,user need make sure your buffer size is big
- * enough to hold the data,in other words,user need make sure the buffer size
- * is 4 byte aligned
- */
- if (data->blockSize % sizeof(uint32_t) != 0U)
- {
- data->blockSize +=
- sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
- }
-
- totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
-
- while ((error == kStatus_Success) && (transferredWords < totalWords))
- {
- while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_BufferReadReadyFlag | kSDHC_DataErrorFlag)))
- {
- }
-
- if (SDHC_GetInterruptStatusFlags(base) & kSDHC_DataErrorFlag)
- {
- if (!(data->enableIgnoreError))
- {
- error = kStatus_Fail;
- }
- }
- if (error == kStatus_Success)
- {
- transferredWords = SDHC_ReadDataPort(base, data, transferredWords);
- }
- /* clear buffer ready and error */
- SDHC_ClearInterruptStatusFlags(base, kSDHC_BufferReadReadyFlag | kSDHC_DataErrorFlag);
- }
-
- /* Clear data complete flag after the last read operation. */
- SDHC_ClearInterruptStatusFlags(base, kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag);
-
- return error;
-}
-
-static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords)
-{
- uint32_t i;
- uint32_t totalWords;
- uint32_t wordsCanBeWrote; /* Words can be wrote at this time. */
- uint32_t writeWatermark = ((base->WML & SDHC_WML_WRWML_MASK) >> SDHC_WML_WRWML_SHIFT);
-
- /*
- * Add non aligned access support ,user need make sure your buffer size is big
- * enough to hold the data,in other words,user need make sure the buffer size
- * is 4 byte aligned
- */
- if (data->blockSize % sizeof(uint32_t) != 0U)
- {
- data->blockSize +=
- sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
- }
-
- totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
-
- /* If watermark level is equal or bigger than totalWords, transfers totalWords data.*/
- if (writeWatermark >= totalWords)
- {
- wordsCanBeWrote = totalWords;
- }
- /* If watermark level is less than totalWords and left words to be sent is equal or bigger than watermark,
- transfers watermark level words. */
- else if ((writeWatermark < totalWords) && ((totalWords - transferredWords) >= writeWatermark))
- {
- wordsCanBeWrote = writeWatermark;
- }
- /* If watermark level is less than totalWords and left words to be sent is less than watermark, transfers left
- words. */
- else
- {
- wordsCanBeWrote = (totalWords - transferredWords);
- }
-
- i = 0U;
- while (i < wordsCanBeWrote)
- {
- SDHC_WriteData(base, data->txData[transferredWords++]);
- i++;
- }
-
- return transferredWords;
-}
-
-static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
-{
- uint32_t totalWords;
- uint32_t transferredWords = 0U;
- status_t error = kStatus_Success;
-
- /*
- * Add non aligned access support ,user need make sure your buffer size is big
- * enough to hold the data,in other words,user need make sure the buffer size
- * is 4 byte aligned
- */
- if (data->blockSize % sizeof(uint32_t) != 0U)
- {
- data->blockSize +=
- sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */
- }
-
- totalWords = (data->blockCount * data->blockSize) / sizeof(uint32_t);
-
- while ((error == kStatus_Success) && (transferredWords < totalWords))
- {
- while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_BufferWriteReadyFlag | kSDHC_DataErrorFlag)))
- {
- }
-
- if (SDHC_GetInterruptStatusFlags(base) & kSDHC_DataErrorFlag)
- {
- if (!(data->enableIgnoreError))
- {
- error = kStatus_Fail;
- }
- }
- if (error == kStatus_Success)
- {
- transferredWords = SDHC_WriteDataPort(base, data, transferredWords);
- }
-
- /* Clear buffer enable flag to trigger transfer. Clear error flag when SDHC encounter error. */
- SDHC_ClearInterruptStatusFlags(base, (kSDHC_BufferWriteReadyFlag | kSDHC_DataErrorFlag));
- }
-
- /* Wait write data complete or data transfer error after the last writing operation. */
- while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag)))
- {
- }
- if (SDHC_GetInterruptStatusFlags(base) & kSDHC_DataErrorFlag)
- {
- if (!(data->enableIgnoreError))
- {
- error = kStatus_Fail;
- }
- }
-
- SDHC_ClearInterruptStatusFlags(base, (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag));
-
- return error;
-}
-
-static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *command)
-{
- status_t error = kStatus_Success;
-
- /* Wait command complete or SDHC encounters error. */
- while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_CommandCompleteFlag | kSDHC_CommandErrorFlag)))
- {
- }
-
- if (SDHC_GetInterruptStatusFlags(base) & kSDHC_CommandErrorFlag)
- {
- error = kStatus_Fail;
- }
- /* Receive response when command completes successfully. */
- if (error == kStatus_Success)
- {
- error = SDHC_ReceiveCommandResponse(base, command);
- }
-
- SDHC_ClearInterruptStatusFlags(base, (kSDHC_CommandCompleteFlag | kSDHC_CommandErrorFlag));
-
- return error;
-}
-
-static status_t SDHC_TransferByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
-{
- status_t error = kStatus_Success;
-
- if (data->rxData)
- {
- error = SDHC_ReadByDataPortBlocking(base, data);
- }
- else
- {
- error = SDHC_WriteByDataPortBlocking(base, data);
- }
-
- return error;
-}
-
-static status_t SDHC_TransferByAdma2Blocking(SDHC_Type *base, sdhc_data_t *data)
-{
- status_t error = kStatus_Success;
-
- /* Wait data complete or SDHC encounters error. */
- while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag)))
- {
- }
- if (SDHC_GetInterruptStatusFlags(base) & (kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag))
- {
- if (!(data->enableIgnoreError))
- {
- error = kStatus_Fail;
- }
- }
- SDHC_ClearInterruptStatusFlags(
- base, (kSDHC_DataCompleteFlag | kSDHC_DmaCompleteFlag | kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag));
- return error;
-}
-
-#if defined FSL_SDHC_ENABLE_ADMA1
-#define SDHC_TransferByAdma1Blocking(base, data) SDHC_TransferByAdma2Blocking(base, data)
-#endif /* FSL_SDHC_ENABLE_ADMA1 */
-
-static status_t SDHC_TransferDataBlocking(sdhc_dma_mode_t dmaMode, SDHC_Type *base, sdhc_data_t *data)
-{
- status_t error = kStatus_Success;
-
- switch (dmaMode)
- {
- case kSDHC_DmaModeNo:
- error = SDHC_TransferByDataPortBlocking(base, data);
- break;
-#if defined FSL_SDHC_ENABLE_ADMA1
- case kSDHC_DmaModeAdma1:
- error = SDHC_TransferByAdma1Blocking(base, data);
- break;
-#endif /* FSL_SDHC_ENABLE_ADMA1 */
- case kSDHC_DmaModeAdma2:
- error = SDHC_TransferByAdma2Blocking(base, data);
- break;
- default:
- error = kStatus_InvalidArgument;
- break;
- }
-
- return error;
-}
-
-static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interruptFlags)
-{
- if (interruptFlags & kSDHC_CardInsertionFlag)
- {
- if (handle->callback.CardInserted)
- {
- handle->callback.CardInserted();
- }
- }
- else
- {
- if (handle->callback.CardRemoved)
- {
- handle->callback.CardRemoved();
- }
- }
-}
-
-static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags)
-{
- assert(handle->command);
-
- if ((interruptFlags & kSDHC_CommandErrorFlag) && (!(handle->data)) && (handle->callback.TransferComplete))
- {
- handle->callback.TransferComplete(base, handle, kStatus_SDHC_SendCommandFailed, handle->userData);
- }
- else
- {
- /* Receive response */
- SDHC_ReceiveCommandResponse(base, handle->command);
- if ((!(handle->data)) && (handle->callback.TransferComplete))
- {
- handle->callback.TransferComplete(base, handle, kStatus_Success, handle->userData);
- }
- }
-}
-
-static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags)
-{
- assert(handle->data);
-
- if ((!(handle->data->enableIgnoreError)) && (interruptFlags & (kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag)) &&
- (handle->callback.TransferComplete))
- {
- handle->callback.TransferComplete(base, handle, kStatus_SDHC_TransferDataFailed, handle->userData);
- }
- else
- {
- if (interruptFlags & kSDHC_BufferReadReadyFlag)
- {
- handle->transferredWords = SDHC_ReadDataPort(base, handle->data, handle->transferredWords);
- }
- else if (interruptFlags & kSDHC_BufferWriteReadyFlag)
- {
- handle->transferredWords = SDHC_WriteDataPort(base, handle->data, handle->transferredWords);
- }
- else
- {
- }
-
- if ((interruptFlags & kSDHC_DataCompleteFlag) && (handle->callback.TransferComplete))
- {
- handle->callback.TransferComplete(base, handle, kStatus_Success, handle->userData);
- }
- else
- {
- /* Do nothing when DMA complete flag is set. Wait until data complete flag is set. */
- }
- }
-}
-
-static void SDHC_TransferHandleSdioInterrupt(sdhc_handle_t *handle)
-{
- if (handle->callback.SdioInterrupt)
- {
- handle->callback.SdioInterrupt();
- }
-}
-
-static void SDHC_TransferHandleSdioBlockGap(sdhc_handle_t *handle)
-{
- if (handle->callback.SdioBlockGap)
- {
- handle->callback.SdioBlockGap();
- }
-}
-
-void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config)
-{
- assert(config);
-#if !defined FSL_SDHC_ENABLE_ADMA1
- assert(config->dmaMode != kSDHC_DmaModeAdma1);
-#endif /* FSL_SDHC_ENABLE_ADMA1 */
- assert((config->writeWatermarkLevel >= 1U) && (config->writeWatermarkLevel <= 128U));
- assert((config->readWatermarkLevel >= 1U) && (config->readWatermarkLevel <= 128U));
-
- uint32_t proctl;
- uint32_t wml;
-
-#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
- /* Enable SDHC clock. */
- CLOCK_EnableClock(s_sdhcClock[SDHC_GetInstance(base)]);
-#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
-
- /* Reset SDHC. */
- SDHC_Reset(base, kSDHC_ResetAll, 100);
-
- proctl = base->PROCTL;
- wml = base->WML;
-
- proctl &= ~(SDHC_PROCTL_D3CD_MASK | SDHC_PROCTL_EMODE_MASK | SDHC_PROCTL_DMAS_MASK);
- /* Set DAT3 as card detection pin */
- if (config->cardDetectDat3)
- {
- proctl |= SDHC_PROCTL_D3CD_MASK;
- }
- /* Endian mode and DMA mode */
- proctl |= (SDHC_PROCTL_EMODE(config->endianMode) | SDHC_PROCTL_DMAS(config->dmaMode));
-
- /* Watermark level */
- wml &= ~(SDHC_WML_RDWML_MASK | SDHC_WML_WRWML_MASK);
- wml |= (SDHC_WML_RDWML(config->readWatermarkLevel) | SDHC_WML_WRWML(config->writeWatermarkLevel));
-
- base->WML = wml;
- base->PROCTL = proctl;
-
- /* Disable all clock auto gated off feature because of DAT0 line logic(card buffer full status) can't be updated
- correctly when clock auto gated off is enabled. */
- base->SYSCTL |= (SDHC_SYSCTL_PEREN_MASK | SDHC_SYSCTL_HCKEN_MASK | SDHC_SYSCTL_IPGEN_MASK);
-
- /* Enable interrupt status but doesn't enable interrupt signal. */
- SDHC_SetTransferInterrupt(base, false);
-}
-
-void SDHC_Deinit(SDHC_Type *base)
-{
-#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
- /* Disable clock. */
- CLOCK_DisableClock(s_sdhcClock[SDHC_GetInstance(base)]);
-#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
-}
-
-bool SDHC_Reset(SDHC_Type *base, uint32_t mask, uint32_t timeout)
-{
- base->SYSCTL |= (mask & (SDHC_SYSCTL_RSTA_MASK | SDHC_SYSCTL_RSTC_MASK | SDHC_SYSCTL_RSTD_MASK));
- /* Delay some time to wait reset success. */
- while ((base->SYSCTL & mask))
- {
- if (!timeout)
- {
- break;
- }
- timeout--;
- }
-
- return ((!timeout) ? false : true);
-}
-
-void SDHC_GetCapability(SDHC_Type *base, sdhc_capability_t *capability)
-{
- assert(capability);
-
- uint32_t htCapability;
- uint32_t hostVer;
- uint32_t maxBlockLength;
-
- hostVer = base->HOSTVER;
- htCapability = base->HTCAPBLT;
-
- /* Get the capability of SDHC. */
- capability->specVersion = ((hostVer & SDHC_HOSTVER_SVN_MASK) >> SDHC_HOSTVER_SVN_SHIFT);
- capability->vendorVersion = ((hostVer & SDHC_HOSTVER_VVN_MASK) >> SDHC_HOSTVER_VVN_SHIFT);
- maxBlockLength = ((htCapability & SDHC_HTCAPBLT_MBL_MASK) >> SDHC_HTCAPBLT_MBL_SHIFT);
- capability->maxBlockLength = (512U << maxBlockLength);
- /* Other attributes not in HTCAPBLT register. */
- capability->maxBlockCount = SDHC_MAX_BLOCK_COUNT;
- capability->flags = (htCapability & (kSDHC_SupportAdmaFlag | kSDHC_SupportHighSpeedFlag | kSDHC_SupportDmaFlag |
- kSDHC_SupportSuspendResumeFlag | kSDHC_SupportV330Flag));
-#if defined FSL_FEATURE_SDHC_HAS_V300_SUPPORT && FSL_FEATURE_SDHC_HAS_V300_SUPPORT
- capability->flags |= (htCapability & kSDHC_SupportV300Flag);
-#endif
-#if defined FSL_FEATURE_SDHC_HAS_V180_SUPPORT && FSL_FEATURE_SDHC_HAS_V180_SUPPORT
- capability->flags |= (htCapability & kSDHC_SupportV180Flag);
-#endif
- /* eSDHC on all kinetis boards will support 4/8 bit data bus width. */
- capability->flags |= (kSDHC_Support4BitFlag | kSDHC_Support8BitFlag);
-}
-
-uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz)
-{
- assert(srcClock_Hz != 0U);
- assert((busClock_Hz != 0U) && (busClock_Hz <= srcClock_Hz));
-
- uint32_t totalDiv = 0U;
- uint32_t divisor = 0U;
- uint32_t prescaler = 0U;
- uint32_t sysctl = 0U;
- uint32_t nearestFrequency = 0U;
-
- /* calucate total divisor first */
- totalDiv = srcClock_Hz / busClock_Hz;
-
- if (totalDiv != 0U)
- {
- /* calucate the divisor (srcClock_Hz / divisor) <= busClock_Hz */
- if ((srcClock_Hz / totalDiv) > busClock_Hz)
- {
- totalDiv++;
- }
-
- /* divide the total divisor to div and prescaler */
- if (totalDiv > SDHC_MAX_DVS)
- {
- prescaler = totalDiv / SDHC_MAX_DVS;
- /* prescaler must be a value which equal 2^n and smaller than SDHC_MAX_CLKFS */
- while (((SDHC_MAX_CLKFS % prescaler) != 0U) || (prescaler == 1U))
- {
- prescaler++;
- }
- /* calucate the divisor */
- divisor = totalDiv / prescaler;
- /* fine tuning the divisor until divisor * prescaler >= totalDiv */
- while ((divisor * prescaler) < totalDiv)
- {
- divisor++;
- }
- nearestFrequency = srcClock_Hz / divisor / prescaler;
- }
- else
- {
- divisor = totalDiv;
- prescaler = 0U;
- nearestFrequency = srcClock_Hz / divisor;
- }
- }
- /* in this condition , srcClock_Hz = busClock_Hz, */
- else
- {
- /* total divider = 1U */
- divisor = 0U;
- prescaler = 0U;
- nearestFrequency = srcClock_Hz;
- }
-
- /* calucate the value write to register */
- if (divisor != 0U)
- {
- SDHC_PREV_DVS(divisor);
- }
- /* calucate the value write to register */
- if (prescaler != 0U)
- {
- SDHC_PREV_CLKFS(prescaler);
- }
-
- /* Disable SD clock. It should be disabled before changing the SD clock frequency.*/
- base->SYSCTL &= ~SDHC_SYSCTL_SDCLKEN_MASK;
-
- /* Set the SD clock frequency divisor, SD clock frequency select, data timeout counter value. */
- sysctl = base->SYSCTL;
- sysctl &= ~(SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK | SDHC_SYSCTL_DTOCV_MASK);
- sysctl |= (SDHC_SYSCTL_DVS(divisor) | SDHC_SYSCTL_SDCLKFS(prescaler) | SDHC_SYSCTL_DTOCV(0xEU));
- base->SYSCTL = sysctl;
-
- /* Wait until the SD clock is stable. */
- while (!(base->PRSSTAT & SDHC_PRSSTAT_SDSTB_MASK))
- {
- }
- /* Enable the SD clock. */
- base->SYSCTL |= SDHC_SYSCTL_SDCLKEN_MASK;
-
- return nearestFrequency;
-}
-
-bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout)
-{
- base->SYSCTL |= SDHC_SYSCTL_INITA_MASK;
- /* Delay some time to wait card become active state. */
- while (base->SYSCTL & SDHC_SYSCTL_INITA_MASK)
- {
- if (!timeout)
- {
- break;
- }
- timeout--;
- }
-
- return ((!timeout) ? false : true);
-}
-
-void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config)
-{
- assert(config);
- assert(config->dataBlockSize <= (SDHC_BLKATTR_BLKSIZE_MASK >> SDHC_BLKATTR_BLKSIZE_SHIFT));
- assert(config->dataBlockCount <= (SDHC_BLKATTR_BLKCNT_MASK >> SDHC_BLKATTR_BLKCNT_SHIFT));
-
- base->BLKATTR = ((base->BLKATTR & ~(SDHC_BLKATTR_BLKSIZE_MASK | SDHC_BLKATTR_BLKCNT_MASK)) |
- (SDHC_BLKATTR_BLKSIZE(config->dataBlockSize) | SDHC_BLKATTR_BLKCNT(config->dataBlockCount)));
- base->CMDARG = config->commandArgument;
- base->XFERTYP = (((config->commandIndex << SDHC_XFERTYP_CMDINX_SHIFT) & SDHC_XFERTYP_CMDINX_MASK) |
- (config->flags & (SDHC_XFERTYP_DMAEN_MASK | SDHC_XFERTYP_MSBSEL_MASK | SDHC_XFERTYP_DPSEL_MASK |
- SDHC_XFERTYP_CMDTYP_MASK | SDHC_XFERTYP_BCEN_MASK | SDHC_XFERTYP_CICEN_MASK |
- SDHC_XFERTYP_CCCEN_MASK | SDHC_XFERTYP_RSPTYP_MASK | SDHC_XFERTYP_DTDSEL_MASK |
- SDHC_XFERTYP_AC12EN_MASK)));
-}
-
-void SDHC_EnableSdioControl(SDHC_Type *base, uint32_t mask, bool enable)
-{
- uint32_t proctl = base->PROCTL;
- uint32_t vendor = base->VENDOR;
-
- if (enable)
- {
- if (mask & kSDHC_StopAtBlockGapFlag)
- {
- proctl |= SDHC_PROCTL_SABGREQ_MASK;
- }
- if (mask & kSDHC_ReadWaitControlFlag)
- {
- proctl |= SDHC_PROCTL_RWCTL_MASK;
- }
- if (mask & kSDHC_InterruptAtBlockGapFlag)
- {
- proctl |= SDHC_PROCTL_IABG_MASK;
- }
- if (mask & kSDHC_ExactBlockNumberReadFlag)
- {
- vendor |= SDHC_VENDOR_EXBLKNU_MASK;
- }
- }
- else
- {
- if (mask & kSDHC_StopAtBlockGapFlag)
- {
- proctl &= ~SDHC_PROCTL_SABGREQ_MASK;
- }
- if (mask & kSDHC_ReadWaitControlFlag)
- {
- proctl &= ~SDHC_PROCTL_RWCTL_MASK;
- }
- if (mask & kSDHC_InterruptAtBlockGapFlag)
- {
- proctl &= ~SDHC_PROCTL_IABG_MASK;
- }
- if (mask & kSDHC_ExactBlockNumberReadFlag)
- {
- vendor &= ~SDHC_VENDOR_EXBLKNU_MASK;
- }
- }
-
- base->PROCTL = proctl;
- base->VENDOR = vendor;
-}
-
-void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config)
-{
- assert(config);
- assert(config->ackTimeoutCount <= (SDHC_MMCBOOT_DTOCVACK_MASK >> SDHC_MMCBOOT_DTOCVACK_SHIFT));
- assert(config->blockCount <= (SDHC_MMCBOOT_BOOTBLKCNT_MASK >> SDHC_MMCBOOT_BOOTBLKCNT_SHIFT));
-
- uint32_t mmcboot = 0U;
-
- mmcboot = (SDHC_MMCBOOT_DTOCVACK(config->ackTimeoutCount) | SDHC_MMCBOOT_BOOTMODE(config->bootMode) |
- SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount));
- if (config->enableBootAck)
- {
- mmcboot |= SDHC_MMCBOOT_BOOTACK_MASK;
- }
- if (config->enableBoot)
- {
- mmcboot |= SDHC_MMCBOOT_BOOTEN_MASK;
- }
- if (config->enableAutoStopAtBlockGap)
- {
- mmcboot |= SDHC_MMCBOOT_AUTOSABGEN_MASK;
- }
- base->MMCBOOT = mmcboot;
-}
-
-status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
- sdhc_dma_mode_t dmaMode,
- uint32_t *table,
- uint32_t tableWords,
- const uint32_t *data,
- uint32_t dataBytes)
-{
- status_t error = kStatus_Success;
- const uint32_t *startAddress = data;
- uint32_t entries;
- uint32_t i;
-#if defined FSL_SDHC_ENABLE_ADMA1
- sdhc_adma1_descriptor_t *adma1EntryAddress;
-#endif
- sdhc_adma2_descriptor_t *adma2EntryAddress;
-
- if ((((!table) || (!tableWords)) && ((dmaMode == kSDHC_DmaModeAdma1) || (dmaMode == kSDHC_DmaModeAdma2))) ||
- (!data) || (!dataBytes)
-#if !defined FSL_SDHC_ENABLE_ADMA1
- || (dmaMode == kSDHC_DmaModeAdma1)
-#endif
- )
- {
- error = kStatus_InvalidArgument;
- }
- else if (((dmaMode == kSDHC_DmaModeAdma2) && (((uint32_t)startAddress % SDHC_ADMA2_LENGTH_ALIGN) != 0U))
-#if defined FSL_SDHC_ENABLE_ADMA1
- || ((dmaMode == kSDHC_DmaModeAdma1) && (((uint32_t)startAddress % SDHC_ADMA1_LENGTH_ALIGN) != 0U))
-#endif
- )
- {
- error = kStatus_SDHC_DMADataBufferAddrNotAlign;
- }
- else
- {
- switch (dmaMode)
- {
- case kSDHC_DmaModeNo:
- break;
-#if defined FSL_SDHC_ENABLE_ADMA1
- case kSDHC_DmaModeAdma1:
- /*
- * Add non aligned access support ,user need make sure your buffer size is big
- * enough to hold the data,in other words,user need make sure the buffer size
- * is 4 byte aligned
- */
- if (dataBytes % sizeof(uint32_t) != 0U)
- {
- dataBytes +=
- sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */
- }
-
- /* Check if ADMA descriptor's number is enough. */
- entries = ((dataBytes / SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U);
- /* ADMA1 needs two descriptors to finish a transfer */
- entries <<= 1U;
- if (entries > ((tableWords * sizeof(uint32_t)) / sizeof(sdhc_adma1_descriptor_t)))
- {
- error = kStatus_OutOfRange;
- }
- else
- {
- adma1EntryAddress = (sdhc_adma1_descriptor_t *)(table);
- for (i = 0U; i < entries; i += 2U)
- {
- /* Each descriptor for ADMA1 is 32-bit in length */
- if ((dataBytes - sizeof(uint32_t) * (startAddress - data)) <=
- SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY)
- {
- /* The last piece of data, setting end flag in descriptor */
- adma1EntryAddress[i] = ((uint32_t)(dataBytes - sizeof(uint32_t) * (startAddress - data))
- << SDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT);
- adma1EntryAddress[i] |= kSDHC_Adma1DescriptorTypeSetLength;
- adma1EntryAddress[i + 1U] =
- ((uint32_t)(startAddress) << SDHC_ADMA1_DESCRIPTOR_ADDRESS_SHIFT);
- adma1EntryAddress[i + 1U] |=
- (kSDHC_Adma1DescriptorTypeTransfer | kSDHC_Adma1DescriptorEndFlag);
- }
- else
- {
- adma1EntryAddress[i] = ((uint32_t)SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY
- << SDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT);
- adma1EntryAddress[i] |= kSDHC_Adma1DescriptorTypeSetLength;
- adma1EntryAddress[i + 1U] =
- ((uint32_t)(startAddress) << SDHC_ADMA1_DESCRIPTOR_ADDRESS_SHIFT);
- adma1EntryAddress[i + 1U] |= kSDHC_Adma1DescriptorTypeTransfer;
- startAddress += SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY / sizeof(uint32_t);
- }
- }
-
- /* When use ADMA, disable simple DMA */
- base->DSADDR = 0U;
- base->ADSADDR = (uint32_t)table;
- /* disable the buffer ready flag in DMA mode */
- SDHC_DisableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
- SDHC_DisableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
- }
- break;
-#endif /* FSL_SDHC_ENABLE_ADMA1 */
- case kSDHC_DmaModeAdma2:
- /*
- * Add non aligned access support ,user need make sure your buffer size is big
- * enough to hold the data,in other words,user need make sure the buffer size
- * is 4 byte aligned
- */
- if (dataBytes % sizeof(uint32_t) != 0U)
- {
- dataBytes +=
- sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */
- }
-
- /* Check if ADMA descriptor's number is enough. */
- entries = ((dataBytes / SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U);
- if (entries > ((tableWords * sizeof(uint32_t)) / sizeof(sdhc_adma2_descriptor_t)))
- {
- error = kStatus_OutOfRange;
- }
- else
- {
- adma2EntryAddress = (sdhc_adma2_descriptor_t *)(table);
- for (i = 0U; i < entries; i++)
- {
- /* Each descriptor for ADMA2 is 64-bit in length */
- if ((dataBytes - sizeof(uint32_t) * (startAddress - data)) <=
- SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY)
- {
- /* The last piece of data, setting end flag in descriptor */
- adma2EntryAddress[i].address = startAddress;
- adma2EntryAddress[i].attribute = ((dataBytes - sizeof(uint32_t) * (startAddress - data))
- << SDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT);
- adma2EntryAddress[i].attribute |=
- (kSDHC_Adma2DescriptorTypeTransfer | kSDHC_Adma2DescriptorEndFlag);
- }
- else
- {
- adma2EntryAddress[i].address = startAddress;
- adma2EntryAddress[i].attribute =
- (((SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY / sizeof(uint32_t)) * sizeof(uint32_t))
- << SDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT);
- adma2EntryAddress[i].attribute |= kSDHC_Adma2DescriptorTypeTransfer;
- startAddress += (SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY / sizeof(uint32_t));
- }
- }
-
- /* When use ADMA, disable simple DMA */
- base->DSADDR = 0U;
- base->ADSADDR = (uint32_t)table;
- /* disable the buffer read flag in DMA mode */
- SDHC_DisableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
- SDHC_DisableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
- }
- break;
- default:
- break;
- }
- }
-
- return error;
-}
-
-status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer)
-{
- assert(transfer);
-
- status_t error = kStatus_Success;
- sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT);
- sdhc_command_t *command = transfer->command;
- sdhc_data_t *data = transfer->data;
-
- /* make sure the cmd/block count is valid */
- if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT)))
- {
- return kStatus_InvalidArgument;
- }
-
- /* Wait until command/data bus out of busy status. */
- while (SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag)
- {
- }
- while (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag))
- {
- }
-
- /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/
- if (data && (NULL != admaTable))
- {
- error =
- SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords,
- (data->rxData ? data->rxData : data->txData), (data->blockCount * data->blockSize));
- /* in this situation , we disable the DMA instead of polling transfer mode */
- if (error == kStatus_SDHC_DMADataBufferAddrNotAlign)
- {
- dmaMode = kSDHC_DmaModeNo;
- SDHC_EnableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
- }
- else if (error != kStatus_Success)
- {
- return error;
- }
- else
- {
- }
- }
-
- /* Send command and receive data. */
- SDHC_StartTransfer(base, command, data, dmaMode);
- if (kStatus_Success != SDHC_SendCommandBlocking(base, command))
- {
- return kStatus_SDHC_SendCommandFailed;
- }
- else if (data && (kStatus_Success != SDHC_TransferDataBlocking(dmaMode, base, data)))
- {
- return kStatus_SDHC_TransferDataFailed;
- }
- else
- {
- }
-
- return kStatus_Success;
-}
-
-void SDHC_TransferCreateHandle(SDHC_Type *base,
- sdhc_handle_t *handle,
- const sdhc_transfer_callback_t *callback,
- void *userData)
-{
- assert(handle);
- assert(callback);
-
- /* Zero the handle. */
- memset(handle, 0, sizeof(*handle));
-
- /* Set the callback. */
- handle->callback.CardInserted = callback->CardInserted;
- handle->callback.CardRemoved = callback->CardRemoved;
- handle->callback.SdioInterrupt = callback->SdioInterrupt;
- handle->callback.SdioBlockGap = callback->SdioBlockGap;
- handle->callback.TransferComplete = callback->TransferComplete;
- handle->userData = userData;
-
- /* Save the handle in global variables to support the double weak mechanism. */
- s_sdhcHandle[SDHC_GetInstance(base)] = handle;
-
- /* Enable interrupt in NVIC. */
- SDHC_SetTransferInterrupt(base, true);
-
- /* save IRQ handler */
- s_sdhcIsr = SDHC_TransferHandleIRQ;
-
- EnableIRQ(s_sdhcIRQ[SDHC_GetInstance(base)]);
-}
-
-status_t SDHC_TransferNonBlocking(
- SDHC_Type *base, sdhc_handle_t *handle, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer)
-{
- assert(transfer);
-
- sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT);
- status_t error = kStatus_Success;
- sdhc_command_t *command = transfer->command;
- sdhc_data_t *data = transfer->data;
-
- /* make sure cmd/block count is valid */
- if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT)))
- {
- return kStatus_InvalidArgument;
- }
-
- /* Wait until command/data bus out of busy status. */
- if ((SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) ||
- (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag)))
- {
- return kStatus_SDHC_BusyTransferring;
- }
-
- /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/
- if (data && (NULL != admaTable))
- {
- error =
- SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords,
- (data->rxData ? data->rxData : data->txData), (data->blockCount * data->blockSize));
- /* in this situation , we disable the DMA instead of polling transfer mode */
- if (error == kStatus_SDHC_DMADataBufferAddrNotAlign)
- {
- /* change to polling mode */
- dmaMode = kSDHC_DmaModeNo;
- SDHC_EnableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
- SDHC_EnableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
- }
- else if (error != kStatus_Success)
- {
- return error;
- }
- else
- {
- }
- }
-
- /* Save command and data into handle before transferring. */
- handle->command = command;
- handle->data = data;
- handle->interruptFlags = 0U;
- /* transferredWords will only be updated in ISR when transfer way is DATAPORT. */
- handle->transferredWords = 0U;
-
- SDHC_StartTransfer(base, command, data, dmaMode);
-
- return kStatus_Success;
-}
-
-void SDHC_TransferHandleIRQ(SDHC_Type *base, sdhc_handle_t *handle)
-{
- assert(handle);
-
- uint32_t interruptFlags;
-
- interruptFlags = SDHC_GetInterruptStatusFlags(base);
- handle->interruptFlags = interruptFlags;
-
- if (interruptFlags & kSDHC_CardDetectFlag)
- {
- SDHC_TransferHandleCardDetect(handle, (interruptFlags & kSDHC_CardDetectFlag));
- }
- if (interruptFlags & kSDHC_CommandFlag)
- {
- SDHC_TransferHandleCommand(base, handle, (interruptFlags & kSDHC_CommandFlag));
- }
- if (interruptFlags & kSDHC_DataFlag)
- {
- SDHC_TransferHandleData(base, handle, (interruptFlags & kSDHC_DataFlag));
- }
- if (interruptFlags & kSDHC_CardInterruptFlag)
- {
- SDHC_TransferHandleSdioInterrupt(handle);
- }
- if (interruptFlags & kSDHC_BlockGapEventFlag)
- {
- SDHC_TransferHandleSdioBlockGap(handle);
- }
-
- SDHC_ClearInterruptStatusFlags(base, interruptFlags);
-}
-
-#if defined(SDHC)
-void SDHC_DriverIRQHandler(void)
-{
- assert(s_sdhcHandle[0]);
-
- s_sdhcIsr(SDHC, s_sdhcHandle[0]);
-}
-#endif