added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Fri Sep 02 15:07:44 2016 +0100
Revision:
144:ef7eb2e8f9f7
This updates the lib to the mbed lib v125

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /*
<> 144:ef7eb2e8f9f7 2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
<> 144:ef7eb2e8f9f7 3 * All rights reserved.
<> 144:ef7eb2e8f9f7 4 *
<> 144:ef7eb2e8f9f7 5 * Redistribution and use in source and binary forms, with or without
<> 144:ef7eb2e8f9f7 6 * modification,
<> 144:ef7eb2e8f9f7 7 * are permitted provided that the following conditions are met:
<> 144:ef7eb2e8f9f7 8 *
<> 144:ef7eb2e8f9f7 9 * o Redistributions of source code must retain the above copyright notice, this
<> 144:ef7eb2e8f9f7 10 * list
<> 144:ef7eb2e8f9f7 11 * of conditions and the following disclaimer.
<> 144:ef7eb2e8f9f7 12 *
<> 144:ef7eb2e8f9f7 13 * o Redistributions in binary form must reproduce the above copyright notice,
<> 144:ef7eb2e8f9f7 14 * this
<> 144:ef7eb2e8f9f7 15 * list of conditions and the following disclaimer in the documentation and/or
<> 144:ef7eb2e8f9f7 16 * other materials provided with the distribution.
<> 144:ef7eb2e8f9f7 17 *
<> 144:ef7eb2e8f9f7 18 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
<> 144:ef7eb2e8f9f7 19 * contributors may be used to endorse or promote products derived from this
<> 144:ef7eb2e8f9f7 20 * software without specific prior written permission.
<> 144:ef7eb2e8f9f7 21 *
<> 144:ef7eb2e8f9f7 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
<> 144:ef7eb2e8f9f7 23 * AND
<> 144:ef7eb2e8f9f7 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
<> 144:ef7eb2e8f9f7 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
<> 144:ef7eb2e8f9f7 26 * DISCLAIMED. IN NO EVENT SL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
<> 144:ef7eb2e8f9f7 27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
<> 144:ef7eb2e8f9f7 28 * DAMAGES
<> 144:ef7eb2e8f9f7 29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
<> 144:ef7eb2e8f9f7 30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
<> 144:ef7eb2e8f9f7 31 * ON
<> 144:ef7eb2e8f9f7 32 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
<> 144:ef7eb2e8f9f7 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
<> 144:ef7eb2e8f9f7 34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<> 144:ef7eb2e8f9f7 35 */
<> 144:ef7eb2e8f9f7 36
<> 144:ef7eb2e8f9f7 37 #include "fsl_sdhc.h"
<> 144:ef7eb2e8f9f7 38
<> 144:ef7eb2e8f9f7 39 /*******************************************************************************
<> 144:ef7eb2e8f9f7 40 * Definitions
<> 144:ef7eb2e8f9f7 41 ******************************************************************************/
<> 144:ef7eb2e8f9f7 42 /*! @brief Clock setting */
<> 144:ef7eb2e8f9f7 43 /* Max SD clock divisor from base clock */
<> 144:ef7eb2e8f9f7 44 #define SDHC_MAX_DVS ((SDHC_SYSCTL_DVS_MASK >> SDHC_SYSCTL_DVS_SHIFT) + 1U)
<> 144:ef7eb2e8f9f7 45 #define SDHC_INITIAL_DVS (1U) /* Initial value of SD clock divisor */
<> 144:ef7eb2e8f9f7 46 #define SDHC_INITIAL_CLKFS (2U) /* Initial value of SD clock frequency selector */
<> 144:ef7eb2e8f9f7 47 #define SDHC_NEXT_DVS(x) ((x) += 1U)
<> 144:ef7eb2e8f9f7 48 #define SDHC_PREV_DVS(x) ((x) -= 1U)
<> 144:ef7eb2e8f9f7 49 #define SDHC_MAX_CLKFS ((SDHC_SYSCTL_SDCLKFS_MASK >> SDHC_SYSCTL_SDCLKFS_SHIFT) + 1U)
<> 144:ef7eb2e8f9f7 50 #define SDHC_NEXT_CLKFS(x) ((x) <<= 1U)
<> 144:ef7eb2e8f9f7 51 #define SDHC_PREV_CLKFS(x) ((x) >>= 1U)
<> 144:ef7eb2e8f9f7 52
<> 144:ef7eb2e8f9f7 53 /*! @brief ADMA table configuration */
<> 144:ef7eb2e8f9f7 54 typedef struct _sdhc_adma_table_config
<> 144:ef7eb2e8f9f7 55 {
<> 144:ef7eb2e8f9f7 56 uint32_t *admaTable; /*!< ADMA table address, can't be null if transfer way is ADMA1/ADMA2 */
<> 144:ef7eb2e8f9f7 57 uint32_t admaTableWords; /*!< ADMA table length united as words, can't be 0 if transfer way is ADMA1/ADMA2 */
<> 144:ef7eb2e8f9f7 58 } sdhc_adma_table_config_t;
<> 144:ef7eb2e8f9f7 59
<> 144:ef7eb2e8f9f7 60 /*******************************************************************************
<> 144:ef7eb2e8f9f7 61 * Prototypes
<> 144:ef7eb2e8f9f7 62 ******************************************************************************/
<> 144:ef7eb2e8f9f7 63 /*!
<> 144:ef7eb2e8f9f7 64 * @brief Get the instance.
<> 144:ef7eb2e8f9f7 65 *
<> 144:ef7eb2e8f9f7 66 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 67 * @return Instance number.
<> 144:ef7eb2e8f9f7 68 */
<> 144:ef7eb2e8f9f7 69 static uint32_t SDHC_GetInstance(SDHC_Type *base);
<> 144:ef7eb2e8f9f7 70
<> 144:ef7eb2e8f9f7 71 /*!
<> 144:ef7eb2e8f9f7 72 * @brief Set transfer interrupt.
<> 144:ef7eb2e8f9f7 73 *
<> 144:ef7eb2e8f9f7 74 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 75 * @param usingInterruptSignal True to use IRQ signal.
<> 144:ef7eb2e8f9f7 76 */
<> 144:ef7eb2e8f9f7 77 static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal);
<> 144:ef7eb2e8f9f7 78
<> 144:ef7eb2e8f9f7 79 /*!
<> 144:ef7eb2e8f9f7 80 * @brief Start transfer according to current transfer state
<> 144:ef7eb2e8f9f7 81 *
<> 144:ef7eb2e8f9f7 82 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 83 * @param command Command to be sent.
<> 144:ef7eb2e8f9f7 84 * @param data Data to be transferred.
<> 144:ef7eb2e8f9f7 85 */
<> 144:ef7eb2e8f9f7 86 static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data);
<> 144:ef7eb2e8f9f7 87
<> 144:ef7eb2e8f9f7 88 /*!
<> 144:ef7eb2e8f9f7 89 * @brief Receive command response
<> 144:ef7eb2e8f9f7 90 *
<> 144:ef7eb2e8f9f7 91 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 92 * @param command Command to be sent.
<> 144:ef7eb2e8f9f7 93 */
<> 144:ef7eb2e8f9f7 94 static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command);
<> 144:ef7eb2e8f9f7 95
<> 144:ef7eb2e8f9f7 96 /*!
<> 144:ef7eb2e8f9f7 97 * @brief Read DATAPORT when buffer enable bit is set.
<> 144:ef7eb2e8f9f7 98 *
<> 144:ef7eb2e8f9f7 99 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 100 * @param data Data to be read.
<> 144:ef7eb2e8f9f7 101 * @param transferredWords The number of data words have been transferred last time transaction.
<> 144:ef7eb2e8f9f7 102 * @return The number of total data words have been transferred after this time transaction.
<> 144:ef7eb2e8f9f7 103 */
<> 144:ef7eb2e8f9f7 104 static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords);
<> 144:ef7eb2e8f9f7 105
<> 144:ef7eb2e8f9f7 106 /*!
<> 144:ef7eb2e8f9f7 107 * @brief Read data by using DATAPORT polling way.
<> 144:ef7eb2e8f9f7 108 *
<> 144:ef7eb2e8f9f7 109 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 110 * @param data Data to be read.
<> 144:ef7eb2e8f9f7 111 * @retval kStatus_Fail Read DATAPORT failed.
<> 144:ef7eb2e8f9f7 112 * @retval kStatus_Success Operate successfully.
<> 144:ef7eb2e8f9f7 113 */
<> 144:ef7eb2e8f9f7 114 static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data);
<> 144:ef7eb2e8f9f7 115
<> 144:ef7eb2e8f9f7 116 /*!
<> 144:ef7eb2e8f9f7 117 * @brief Write DATAPORT when buffer enable bit is set.
<> 144:ef7eb2e8f9f7 118 *
<> 144:ef7eb2e8f9f7 119 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 120 * @param data Data to be read.
<> 144:ef7eb2e8f9f7 121 * @param transferredWords The number of data words have been transferred last time.
<> 144:ef7eb2e8f9f7 122 * @return The number of total data words have been transferred after this time transaction.
<> 144:ef7eb2e8f9f7 123 */
<> 144:ef7eb2e8f9f7 124 static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords);
<> 144:ef7eb2e8f9f7 125
<> 144:ef7eb2e8f9f7 126 /*!
<> 144:ef7eb2e8f9f7 127 * @brief Write data by using DATAPORT polling way.
<> 144:ef7eb2e8f9f7 128 *
<> 144:ef7eb2e8f9f7 129 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 130 * @param data Data to be transferred.
<> 144:ef7eb2e8f9f7 131 * @retval kStatus_Fail Write DATAPORT failed.
<> 144:ef7eb2e8f9f7 132 * @retval kStatus_Success Operate successfully.
<> 144:ef7eb2e8f9f7 133 */
<> 144:ef7eb2e8f9f7 134 static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data);
<> 144:ef7eb2e8f9f7 135
<> 144:ef7eb2e8f9f7 136 /*!
<> 144:ef7eb2e8f9f7 137 * @brief Send command by using polling way.
<> 144:ef7eb2e8f9f7 138 *
<> 144:ef7eb2e8f9f7 139 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 140 * @param command Command to be sent.
<> 144:ef7eb2e8f9f7 141 * @retval kStatus_Fail Send command failed.
<> 144:ef7eb2e8f9f7 142 * @retval kStatus_Success Operate successfully.
<> 144:ef7eb2e8f9f7 143 */
<> 144:ef7eb2e8f9f7 144 static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *command);
<> 144:ef7eb2e8f9f7 145
<> 144:ef7eb2e8f9f7 146 /*!
<> 144:ef7eb2e8f9f7 147 * @brief Transfer data by DATAPORT and polling way.
<> 144:ef7eb2e8f9f7 148 *
<> 144:ef7eb2e8f9f7 149 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 150 * @param data Data to be transferred.
<> 144:ef7eb2e8f9f7 151 * @retval kStatus_Fail Transfer data failed.
<> 144:ef7eb2e8f9f7 152 * @retval kStatus_Success Operate successfully.
<> 144:ef7eb2e8f9f7 153 */
<> 144:ef7eb2e8f9f7 154 static status_t SDHC_TransferByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data);
<> 144:ef7eb2e8f9f7 155
<> 144:ef7eb2e8f9f7 156 /*!
<> 144:ef7eb2e8f9f7 157 * @brief Transfer data by ADMA2 and polling way.
<> 144:ef7eb2e8f9f7 158 *
<> 144:ef7eb2e8f9f7 159 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 160 * @param data Data to be transferred.
<> 144:ef7eb2e8f9f7 161 * @retval kStatus_Fail Transfer data failed.
<> 144:ef7eb2e8f9f7 162 * @retval kStatus_Success Operate successfully.
<> 144:ef7eb2e8f9f7 163 */
<> 144:ef7eb2e8f9f7 164 static status_t SDHC_TransferByAdma2Blocking(SDHC_Type *base, sdhc_data_t *data);
<> 144:ef7eb2e8f9f7 165
<> 144:ef7eb2e8f9f7 166 /*!
<> 144:ef7eb2e8f9f7 167 * @brief Transfer data by polling way.
<> 144:ef7eb2e8f9f7 168 *
<> 144:ef7eb2e8f9f7 169 * @param dmaMode DMA mode.
<> 144:ef7eb2e8f9f7 170 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 171 * @param data Data to be transferred.
<> 144:ef7eb2e8f9f7 172 * @retval kStatus_Fail Transfer data failed.
<> 144:ef7eb2e8f9f7 173 * @retval kStatus_InvalidArgument Argument is invalid.
<> 144:ef7eb2e8f9f7 174 * @retval kStatus_Success Operate successfully.
<> 144:ef7eb2e8f9f7 175 */
<> 144:ef7eb2e8f9f7 176 static status_t SDHC_TransferDataBlocking(sdhc_dma_mode_t dmaMode, SDHC_Type *base, sdhc_data_t *data);
<> 144:ef7eb2e8f9f7 177
<> 144:ef7eb2e8f9f7 178 /*!
<> 144:ef7eb2e8f9f7 179 * @brief Handle card detect interrupt.
<> 144:ef7eb2e8f9f7 180 *
<> 144:ef7eb2e8f9f7 181 * @param handle SDHC handle.
<> 144:ef7eb2e8f9f7 182 * @param interruptFlags Card detect related interrupt flags.
<> 144:ef7eb2e8f9f7 183 */
<> 144:ef7eb2e8f9f7 184 static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interruptFlags);
<> 144:ef7eb2e8f9f7 185
<> 144:ef7eb2e8f9f7 186 /*!
<> 144:ef7eb2e8f9f7 187 * @brief Handle command interrupt.
<> 144:ef7eb2e8f9f7 188 *
<> 144:ef7eb2e8f9f7 189 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 190 * @param handle SDHC handle.
<> 144:ef7eb2e8f9f7 191 * @param interruptFlags Command related interrupt flags.
<> 144:ef7eb2e8f9f7 192 */
<> 144:ef7eb2e8f9f7 193 static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags);
<> 144:ef7eb2e8f9f7 194
<> 144:ef7eb2e8f9f7 195 /*!
<> 144:ef7eb2e8f9f7 196 * @brief Handle data interrupt.
<> 144:ef7eb2e8f9f7 197 *
<> 144:ef7eb2e8f9f7 198 * @param base SDHC peripheral base address.
<> 144:ef7eb2e8f9f7 199 * @param handle SDHC handle.
<> 144:ef7eb2e8f9f7 200 * @param interruptFlags Data related interrupt flags.
<> 144:ef7eb2e8f9f7 201 */
<> 144:ef7eb2e8f9f7 202 static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags);
<> 144:ef7eb2e8f9f7 203
<> 144:ef7eb2e8f9f7 204 /*!
<> 144:ef7eb2e8f9f7 205 * @brief Handle SDIO card interrupt signal.
<> 144:ef7eb2e8f9f7 206 *
<> 144:ef7eb2e8f9f7 207 * @param handle SDHC handle.
<> 144:ef7eb2e8f9f7 208 */
<> 144:ef7eb2e8f9f7 209 static void SDHC_TransferHandleSdioInterrupt(sdhc_handle_t *handle);
<> 144:ef7eb2e8f9f7 210
<> 144:ef7eb2e8f9f7 211 /*!
<> 144:ef7eb2e8f9f7 212 * @brief Handle SDIO block gap event.
<> 144:ef7eb2e8f9f7 213 *
<> 144:ef7eb2e8f9f7 214 * @param handle SDHC handle.
<> 144:ef7eb2e8f9f7 215 */
<> 144:ef7eb2e8f9f7 216 static void SDHC_TransferHandleSdioBlockGap(sdhc_handle_t *handle);
<> 144:ef7eb2e8f9f7 217
<> 144:ef7eb2e8f9f7 218 /*******************************************************************************
<> 144:ef7eb2e8f9f7 219 * Variables
<> 144:ef7eb2e8f9f7 220 ******************************************************************************/
<> 144:ef7eb2e8f9f7 221 /*! @brief SDHC internal handle pointer array */
<> 144:ef7eb2e8f9f7 222 static sdhc_handle_t *s_sdhcHandle[FSL_FEATURE_SOC_SDHC_COUNT];
<> 144:ef7eb2e8f9f7 223
<> 144:ef7eb2e8f9f7 224 /*! @brief SDHC base pointer array */
<> 144:ef7eb2e8f9f7 225 static SDHC_Type *const s_sdhcBase[] = SDHC_BASE_PTRS;
<> 144:ef7eb2e8f9f7 226
<> 144:ef7eb2e8f9f7 227 /*! @brief SDHC IRQ name array */
<> 144:ef7eb2e8f9f7 228 static const IRQn_Type s_sdhcIRQ[] = SDHC_IRQS;
<> 144:ef7eb2e8f9f7 229
<> 144:ef7eb2e8f9f7 230 /*! @brief SDHC clock array name */
<> 144:ef7eb2e8f9f7 231 static const clock_ip_name_t s_sdhcClock[] = SDHC_CLOCKS;
<> 144:ef7eb2e8f9f7 232
<> 144:ef7eb2e8f9f7 233 /*******************************************************************************
<> 144:ef7eb2e8f9f7 234 * Code
<> 144:ef7eb2e8f9f7 235 ******************************************************************************/
<> 144:ef7eb2e8f9f7 236 static uint32_t SDHC_GetInstance(SDHC_Type *base)
<> 144:ef7eb2e8f9f7 237 {
<> 144:ef7eb2e8f9f7 238 uint8_t instance = 0;
<> 144:ef7eb2e8f9f7 239
<> 144:ef7eb2e8f9f7 240 while ((instance < FSL_FEATURE_SOC_SDHC_COUNT) && (s_sdhcBase[instance] != base))
<> 144:ef7eb2e8f9f7 241 {
<> 144:ef7eb2e8f9f7 242 instance++;
<> 144:ef7eb2e8f9f7 243 }
<> 144:ef7eb2e8f9f7 244
<> 144:ef7eb2e8f9f7 245 assert(instance < FSL_FEATURE_SOC_SDHC_COUNT);
<> 144:ef7eb2e8f9f7 246
<> 144:ef7eb2e8f9f7 247 return instance;
<> 144:ef7eb2e8f9f7 248 }
<> 144:ef7eb2e8f9f7 249
<> 144:ef7eb2e8f9f7 250 static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal)
<> 144:ef7eb2e8f9f7 251 {
<> 144:ef7eb2e8f9f7 252 uint32_t interruptEnabled; /* The Interrupt status flags to be enabled */
<> 144:ef7eb2e8f9f7 253 sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT);
<> 144:ef7eb2e8f9f7 254 bool cardDetectDat3 = (bool)(base->PROCTL & SDHC_PROCTL_D3CD_MASK);
<> 144:ef7eb2e8f9f7 255
<> 144:ef7eb2e8f9f7 256 /* Disable all interrupts */
<> 144:ef7eb2e8f9f7 257 SDHC_DisableInterruptStatus(base, (uint32_t)kSDHC_AllInterruptFlags);
<> 144:ef7eb2e8f9f7 258 SDHC_DisableInterruptSignal(base, (uint32_t)kSDHC_AllInterruptFlags);
<> 144:ef7eb2e8f9f7 259 DisableIRQ(s_sdhcIRQ[SDHC_GetInstance(base)]);
<> 144:ef7eb2e8f9f7 260
<> 144:ef7eb2e8f9f7 261 interruptEnabled =
<> 144:ef7eb2e8f9f7 262 (kSDHC_CommandIndexErrorFlag | kSDHC_CommandCrcErrorFlag | kSDHC_CommandEndBitErrorFlag |
<> 144:ef7eb2e8f9f7 263 kSDHC_CommandTimeoutFlag | kSDHC_CommandCompleteFlag | kSDHC_DataTimeoutFlag | kSDHC_DataCrcErrorFlag |
<> 144:ef7eb2e8f9f7 264 kSDHC_DataEndBitErrorFlag | kSDHC_DataCompleteFlag | kSDHC_AutoCommand12ErrorFlag);
<> 144:ef7eb2e8f9f7 265 if (cardDetectDat3)
<> 144:ef7eb2e8f9f7 266 {
<> 144:ef7eb2e8f9f7 267 interruptEnabled |= (kSDHC_CardInsertionFlag | kSDHC_CardRemovalFlag);
<> 144:ef7eb2e8f9f7 268 }
<> 144:ef7eb2e8f9f7 269 switch (dmaMode)
<> 144:ef7eb2e8f9f7 270 {
<> 144:ef7eb2e8f9f7 271 case kSDHC_DmaModeAdma1:
<> 144:ef7eb2e8f9f7 272 case kSDHC_DmaModeAdma2:
<> 144:ef7eb2e8f9f7 273 interruptEnabled |= (kSDHC_DmaErrorFlag | kSDHC_DmaCompleteFlag);
<> 144:ef7eb2e8f9f7 274 break;
<> 144:ef7eb2e8f9f7 275 case kSDHC_DmaModeNo:
<> 144:ef7eb2e8f9f7 276 interruptEnabled |= (kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag);
<> 144:ef7eb2e8f9f7 277 break;
<> 144:ef7eb2e8f9f7 278 default:
<> 144:ef7eb2e8f9f7 279 break;
<> 144:ef7eb2e8f9f7 280 }
<> 144:ef7eb2e8f9f7 281
<> 144:ef7eb2e8f9f7 282 SDHC_EnableInterruptStatus(base, interruptEnabled);
<> 144:ef7eb2e8f9f7 283 if (usingInterruptSignal)
<> 144:ef7eb2e8f9f7 284 {
<> 144:ef7eb2e8f9f7 285 SDHC_EnableInterruptSignal(base, interruptEnabled);
<> 144:ef7eb2e8f9f7 286 }
<> 144:ef7eb2e8f9f7 287 }
<> 144:ef7eb2e8f9f7 288
<> 144:ef7eb2e8f9f7 289 static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data)
<> 144:ef7eb2e8f9f7 290 {
<> 144:ef7eb2e8f9f7 291 assert(command);
<> 144:ef7eb2e8f9f7 292
<> 144:ef7eb2e8f9f7 293 uint32_t flags = 0U;
<> 144:ef7eb2e8f9f7 294 sdhc_transfer_config_t sdhcTransferConfig;
<> 144:ef7eb2e8f9f7 295 sdhc_dma_mode_t dmaMode;
<> 144:ef7eb2e8f9f7 296
<> 144:ef7eb2e8f9f7 297 /* Define the flag corresponding to each response type. */
<> 144:ef7eb2e8f9f7 298 switch (command->responseType)
<> 144:ef7eb2e8f9f7 299 {
<> 144:ef7eb2e8f9f7 300 case kSDHC_ResponseTypeNone:
<> 144:ef7eb2e8f9f7 301 break;
<> 144:ef7eb2e8f9f7 302 case kSDHC_ResponseTypeR1: /* Response 1 */
<> 144:ef7eb2e8f9f7 303 flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
<> 144:ef7eb2e8f9f7 304 break;
<> 144:ef7eb2e8f9f7 305 case kSDHC_ResponseTypeR1b: /* Response 1 with busy */
<> 144:ef7eb2e8f9f7 306 flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
<> 144:ef7eb2e8f9f7 307 break;
<> 144:ef7eb2e8f9f7 308 case kSDHC_ResponseTypeR2: /* Response 2 */
<> 144:ef7eb2e8f9f7 309 flags |= (kSDHC_ResponseLength136Flag | kSDHC_EnableCrcCheckFlag);
<> 144:ef7eb2e8f9f7 310 break;
<> 144:ef7eb2e8f9f7 311 case kSDHC_ResponseTypeR3: /* Response 3 */
<> 144:ef7eb2e8f9f7 312 flags |= (kSDHC_ResponseLength48Flag);
<> 144:ef7eb2e8f9f7 313 break;
<> 144:ef7eb2e8f9f7 314 case kSDHC_ResponseTypeR4: /* Response 4 */
<> 144:ef7eb2e8f9f7 315 flags |= (kSDHC_ResponseLength48Flag);
<> 144:ef7eb2e8f9f7 316 break;
<> 144:ef7eb2e8f9f7 317 case kSDHC_ResponseTypeR5: /* Response 5 */
<> 144:ef7eb2e8f9f7 318 flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag);
<> 144:ef7eb2e8f9f7 319 break;
<> 144:ef7eb2e8f9f7 320 case kSDHC_ResponseTypeR5b: /* Response 5 with busy */
<> 144:ef7eb2e8f9f7 321 flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
<> 144:ef7eb2e8f9f7 322 break;
<> 144:ef7eb2e8f9f7 323 case kSDHC_ResponseTypeR6: /* Response 6 */
<> 144:ef7eb2e8f9f7 324 flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
<> 144:ef7eb2e8f9f7 325 break;
<> 144:ef7eb2e8f9f7 326 case kSDHC_ResponseTypeR7: /* Response 7 */
<> 144:ef7eb2e8f9f7 327 flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag);
<> 144:ef7eb2e8f9f7 328 break;
<> 144:ef7eb2e8f9f7 329 default:
<> 144:ef7eb2e8f9f7 330 break;
<> 144:ef7eb2e8f9f7 331 }
<> 144:ef7eb2e8f9f7 332 if (command->type == kSDHC_CommandTypeAbort)
<> 144:ef7eb2e8f9f7 333 {
<> 144:ef7eb2e8f9f7 334 flags |= kSDHC_CommandTypeAbortFlag;
<> 144:ef7eb2e8f9f7 335 }
<> 144:ef7eb2e8f9f7 336
<> 144:ef7eb2e8f9f7 337 if (data)
<> 144:ef7eb2e8f9f7 338 {
<> 144:ef7eb2e8f9f7 339 flags |= kSDHC_DataPresentFlag;
<> 144:ef7eb2e8f9f7 340 dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT);
<> 144:ef7eb2e8f9f7 341 if (dmaMode != kSDHC_DmaModeNo)
<> 144:ef7eb2e8f9f7 342 {
<> 144:ef7eb2e8f9f7 343 flags |= kSDHC_EnableDmaFlag;
<> 144:ef7eb2e8f9f7 344 }
<> 144:ef7eb2e8f9f7 345 if (data->rxData)
<> 144:ef7eb2e8f9f7 346 {
<> 144:ef7eb2e8f9f7 347 flags |= kSDHC_DataReadFlag;
<> 144:ef7eb2e8f9f7 348 }
<> 144:ef7eb2e8f9f7 349 if (data->blockCount > 1U)
<> 144:ef7eb2e8f9f7 350 {
<> 144:ef7eb2e8f9f7 351 flags |= (kSDHC_MultipleBlockFlag | kSDHC_EnableBlockCountFlag);
<> 144:ef7eb2e8f9f7 352 if (data->enableAutoCommand12)
<> 144:ef7eb2e8f9f7 353 {
<> 144:ef7eb2e8f9f7 354 /* Enable Auto command 12. */
<> 144:ef7eb2e8f9f7 355 flags |= kSDHC_EnableAutoCommand12Flag;
<> 144:ef7eb2e8f9f7 356 }
<> 144:ef7eb2e8f9f7 357 }
<> 144:ef7eb2e8f9f7 358 if (data->blockCount > SDHC_MAX_BLOCK_COUNT)
<> 144:ef7eb2e8f9f7 359 {
<> 144:ef7eb2e8f9f7 360 sdhcTransferConfig.dataBlockSize = data->blockSize;
<> 144:ef7eb2e8f9f7 361 sdhcTransferConfig.dataBlockCount = SDHC_MAX_BLOCK_COUNT;
<> 144:ef7eb2e8f9f7 362
<> 144:ef7eb2e8f9f7 363 flags &= ~(uint32_t)kSDHC_EnableBlockCountFlag;
<> 144:ef7eb2e8f9f7 364 }
<> 144:ef7eb2e8f9f7 365 else
<> 144:ef7eb2e8f9f7 366 {
<> 144:ef7eb2e8f9f7 367 sdhcTransferConfig.dataBlockSize = data->blockSize;
<> 144:ef7eb2e8f9f7 368 sdhcTransferConfig.dataBlockCount = data->blockCount;
<> 144:ef7eb2e8f9f7 369 }
<> 144:ef7eb2e8f9f7 370 }
<> 144:ef7eb2e8f9f7 371 else
<> 144:ef7eb2e8f9f7 372 {
<> 144:ef7eb2e8f9f7 373 sdhcTransferConfig.dataBlockSize = 0U;
<> 144:ef7eb2e8f9f7 374 sdhcTransferConfig.dataBlockCount = 0U;
<> 144:ef7eb2e8f9f7 375 }
<> 144:ef7eb2e8f9f7 376
<> 144:ef7eb2e8f9f7 377 sdhcTransferConfig.commandArgument = command->argument;
<> 144:ef7eb2e8f9f7 378 sdhcTransferConfig.commandIndex = command->index;
<> 144:ef7eb2e8f9f7 379 sdhcTransferConfig.flags = flags;
<> 144:ef7eb2e8f9f7 380 SDHC_SetTransferConfig(base, &sdhcTransferConfig);
<> 144:ef7eb2e8f9f7 381 }
<> 144:ef7eb2e8f9f7 382
<> 144:ef7eb2e8f9f7 383 static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command)
<> 144:ef7eb2e8f9f7 384 {
<> 144:ef7eb2e8f9f7 385 assert(command);
<> 144:ef7eb2e8f9f7 386
<> 144:ef7eb2e8f9f7 387 uint32_t i;
<> 144:ef7eb2e8f9f7 388
<> 144:ef7eb2e8f9f7 389 if (command->responseType != kSDHC_ResponseTypeNone)
<> 144:ef7eb2e8f9f7 390 {
<> 144:ef7eb2e8f9f7 391 command->response[0U] = SDHC_GetCommandResponse(base, 0U);
<> 144:ef7eb2e8f9f7 392 if (command->responseType == kSDHC_ResponseTypeR2)
<> 144:ef7eb2e8f9f7 393 {
<> 144:ef7eb2e8f9f7 394 command->response[1U] = SDHC_GetCommandResponse(base, 1U);
<> 144:ef7eb2e8f9f7 395 command->response[2U] = SDHC_GetCommandResponse(base, 2U);
<> 144:ef7eb2e8f9f7 396 command->response[3U] = SDHC_GetCommandResponse(base, 3U);
<> 144:ef7eb2e8f9f7 397
<> 144:ef7eb2e8f9f7 398 i = 4U;
<> 144:ef7eb2e8f9f7 399 /* R3-R2-R1-R0(lowest 8 bit is invalid bit) has the same format as R2 format in SD specification document
<> 144:ef7eb2e8f9f7 400 after removed internal CRC7 and end bit. */
<> 144:ef7eb2e8f9f7 401 do
<> 144:ef7eb2e8f9f7 402 {
<> 144:ef7eb2e8f9f7 403 command->response[i - 1U] <<= 8U;
<> 144:ef7eb2e8f9f7 404 if (i > 1U)
<> 144:ef7eb2e8f9f7 405 {
<> 144:ef7eb2e8f9f7 406 command->response[i - 1U] |= ((command->response[i - 2U] & 0xFF000000U) >> 24U);
<> 144:ef7eb2e8f9f7 407 }
<> 144:ef7eb2e8f9f7 408 } while (i--);
<> 144:ef7eb2e8f9f7 409 }
<> 144:ef7eb2e8f9f7 410 }
<> 144:ef7eb2e8f9f7 411 }
<> 144:ef7eb2e8f9f7 412
<> 144:ef7eb2e8f9f7 413 static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords)
<> 144:ef7eb2e8f9f7 414 {
<> 144:ef7eb2e8f9f7 415 assert(data);
<> 144:ef7eb2e8f9f7 416
<> 144:ef7eb2e8f9f7 417 uint32_t i;
<> 144:ef7eb2e8f9f7 418 uint32_t totalWords;
<> 144:ef7eb2e8f9f7 419 uint32_t wordsCanBeRead; /* The words can be read at this time. */
<> 144:ef7eb2e8f9f7 420 uint32_t readWatermark = ((base->WML & SDHC_WML_RDWML_MASK) >> SDHC_WML_RDWML_SHIFT);
<> 144:ef7eb2e8f9f7 421
<> 144:ef7eb2e8f9f7 422 totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
<> 144:ef7eb2e8f9f7 423
<> 144:ef7eb2e8f9f7 424 /* If watermark level is equal or bigger than totalWords, transfers totalWords data. */
<> 144:ef7eb2e8f9f7 425 if (readWatermark >= totalWords)
<> 144:ef7eb2e8f9f7 426 {
<> 144:ef7eb2e8f9f7 427 wordsCanBeRead = totalWords;
<> 144:ef7eb2e8f9f7 428 }
<> 144:ef7eb2e8f9f7 429 /* If watermark level is less than totalWords and left words to be sent is equal or bigger than readWatermark,
<> 144:ef7eb2e8f9f7 430 transfers watermark level words. */
<> 144:ef7eb2e8f9f7 431 else if ((readWatermark < totalWords) && ((totalWords - transferredWords) >= readWatermark))
<> 144:ef7eb2e8f9f7 432 {
<> 144:ef7eb2e8f9f7 433 wordsCanBeRead = readWatermark;
<> 144:ef7eb2e8f9f7 434 }
<> 144:ef7eb2e8f9f7 435 /* If watermark level is less than totalWords and left words to be sent is less than readWatermark, transfers left
<> 144:ef7eb2e8f9f7 436 words. */
<> 144:ef7eb2e8f9f7 437 else
<> 144:ef7eb2e8f9f7 438 {
<> 144:ef7eb2e8f9f7 439 wordsCanBeRead = (totalWords - transferredWords);
<> 144:ef7eb2e8f9f7 440 }
<> 144:ef7eb2e8f9f7 441
<> 144:ef7eb2e8f9f7 442 i = 0U;
<> 144:ef7eb2e8f9f7 443 while (i < wordsCanBeRead)
<> 144:ef7eb2e8f9f7 444 {
<> 144:ef7eb2e8f9f7 445 data->rxData[transferredWords++] = SDHC_ReadData(base);
<> 144:ef7eb2e8f9f7 446 i++;
<> 144:ef7eb2e8f9f7 447 }
<> 144:ef7eb2e8f9f7 448
<> 144:ef7eb2e8f9f7 449 return transferredWords;
<> 144:ef7eb2e8f9f7 450 }
<> 144:ef7eb2e8f9f7 451
<> 144:ef7eb2e8f9f7 452 static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
<> 144:ef7eb2e8f9f7 453 {
<> 144:ef7eb2e8f9f7 454 assert(data);
<> 144:ef7eb2e8f9f7 455
<> 144:ef7eb2e8f9f7 456 uint32_t totalWords;
<> 144:ef7eb2e8f9f7 457 uint32_t transferredWords = 0U;
<> 144:ef7eb2e8f9f7 458 status_t error = kStatus_Success;
<> 144:ef7eb2e8f9f7 459
<> 144:ef7eb2e8f9f7 460 totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
<> 144:ef7eb2e8f9f7 461
<> 144:ef7eb2e8f9f7 462 while ((error == kStatus_Success) && (transferredWords < totalWords))
<> 144:ef7eb2e8f9f7 463 {
<> 144:ef7eb2e8f9f7 464 while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_BufferReadReadyFlag | kSDHC_DataErrorFlag)))
<> 144:ef7eb2e8f9f7 465 {
<> 144:ef7eb2e8f9f7 466 }
<> 144:ef7eb2e8f9f7 467
<> 144:ef7eb2e8f9f7 468 if (SDHC_GetInterruptStatusFlags(base) & kSDHC_DataErrorFlag)
<> 144:ef7eb2e8f9f7 469 {
<> 144:ef7eb2e8f9f7 470 if (!(data->enableIgnoreError))
<> 144:ef7eb2e8f9f7 471 {
<> 144:ef7eb2e8f9f7 472 error = kStatus_Fail;
<> 144:ef7eb2e8f9f7 473 }
<> 144:ef7eb2e8f9f7 474 }
<> 144:ef7eb2e8f9f7 475 if (error == kStatus_Success)
<> 144:ef7eb2e8f9f7 476 {
<> 144:ef7eb2e8f9f7 477 transferredWords = SDHC_ReadDataPort(base, data, transferredWords);
<> 144:ef7eb2e8f9f7 478 }
<> 144:ef7eb2e8f9f7 479
<> 144:ef7eb2e8f9f7 480 /* Clear buffer enable flag to trigger transfer. Clear data error flag when SDHC encounter error */
<> 144:ef7eb2e8f9f7 481 SDHC_ClearInterruptStatusFlags(base, (kSDHC_BufferReadReadyFlag | kSDHC_DataErrorFlag));
<> 144:ef7eb2e8f9f7 482 }
<> 144:ef7eb2e8f9f7 483
<> 144:ef7eb2e8f9f7 484 /* Clear data complete flag after the last read operation. */
<> 144:ef7eb2e8f9f7 485 SDHC_ClearInterruptStatusFlags(base, kSDHC_DataCompleteFlag);
<> 144:ef7eb2e8f9f7 486
<> 144:ef7eb2e8f9f7 487 return error;
<> 144:ef7eb2e8f9f7 488 }
<> 144:ef7eb2e8f9f7 489
<> 144:ef7eb2e8f9f7 490 static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords)
<> 144:ef7eb2e8f9f7 491 {
<> 144:ef7eb2e8f9f7 492 assert(data);
<> 144:ef7eb2e8f9f7 493
<> 144:ef7eb2e8f9f7 494 uint32_t i;
<> 144:ef7eb2e8f9f7 495 uint32_t totalWords;
<> 144:ef7eb2e8f9f7 496 uint32_t wordsCanBeWrote; /* Words can be wrote at this time. */
<> 144:ef7eb2e8f9f7 497 uint32_t writeWatermark = ((base->WML & SDHC_WML_WRWML_MASK) >> SDHC_WML_WRWML_SHIFT);
<> 144:ef7eb2e8f9f7 498
<> 144:ef7eb2e8f9f7 499 totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t));
<> 144:ef7eb2e8f9f7 500
<> 144:ef7eb2e8f9f7 501 /* If watermark level is equal or bigger than totalWords, transfers totalWords data.*/
<> 144:ef7eb2e8f9f7 502 if (writeWatermark >= totalWords)
<> 144:ef7eb2e8f9f7 503 {
<> 144:ef7eb2e8f9f7 504 wordsCanBeWrote = totalWords;
<> 144:ef7eb2e8f9f7 505 }
<> 144:ef7eb2e8f9f7 506 /* If watermark level is less than totalWords and left words to be sent is equal or bigger than watermark,
<> 144:ef7eb2e8f9f7 507 transfers watermark level words. */
<> 144:ef7eb2e8f9f7 508 else if ((writeWatermark < totalWords) && ((totalWords - transferredWords) >= writeWatermark))
<> 144:ef7eb2e8f9f7 509 {
<> 144:ef7eb2e8f9f7 510 wordsCanBeWrote = writeWatermark;
<> 144:ef7eb2e8f9f7 511 }
<> 144:ef7eb2e8f9f7 512 /* If watermark level is less than totalWords and left words to be sent is less than watermark, transfers left
<> 144:ef7eb2e8f9f7 513 words. */
<> 144:ef7eb2e8f9f7 514 else
<> 144:ef7eb2e8f9f7 515 {
<> 144:ef7eb2e8f9f7 516 wordsCanBeWrote = (totalWords - transferredWords);
<> 144:ef7eb2e8f9f7 517 }
<> 144:ef7eb2e8f9f7 518
<> 144:ef7eb2e8f9f7 519 i = 0U;
<> 144:ef7eb2e8f9f7 520 while (i < wordsCanBeWrote)
<> 144:ef7eb2e8f9f7 521 {
<> 144:ef7eb2e8f9f7 522 SDHC_WriteData(base, data->txData[transferredWords++]);
<> 144:ef7eb2e8f9f7 523 i++;
<> 144:ef7eb2e8f9f7 524 }
<> 144:ef7eb2e8f9f7 525
<> 144:ef7eb2e8f9f7 526 return transferredWords;
<> 144:ef7eb2e8f9f7 527 }
<> 144:ef7eb2e8f9f7 528
<> 144:ef7eb2e8f9f7 529 static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
<> 144:ef7eb2e8f9f7 530 {
<> 144:ef7eb2e8f9f7 531 assert(data);
<> 144:ef7eb2e8f9f7 532
<> 144:ef7eb2e8f9f7 533 uint32_t totalWords;
<> 144:ef7eb2e8f9f7 534 uint32_t transferredWords = 0U;
<> 144:ef7eb2e8f9f7 535 status_t error = kStatus_Success;
<> 144:ef7eb2e8f9f7 536
<> 144:ef7eb2e8f9f7 537 totalWords = (data->blockCount * data->blockSize) / sizeof(uint32_t);
<> 144:ef7eb2e8f9f7 538
<> 144:ef7eb2e8f9f7 539 while ((error == kStatus_Success) && (transferredWords < totalWords))
<> 144:ef7eb2e8f9f7 540 {
<> 144:ef7eb2e8f9f7 541 while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_BufferWriteReadyFlag | kSDHC_DataErrorFlag)))
<> 144:ef7eb2e8f9f7 542 {
<> 144:ef7eb2e8f9f7 543 }
<> 144:ef7eb2e8f9f7 544
<> 144:ef7eb2e8f9f7 545 if (SDHC_GetInterruptStatusFlags(base) & kSDHC_DataErrorFlag)
<> 144:ef7eb2e8f9f7 546 {
<> 144:ef7eb2e8f9f7 547 if (!(data->enableIgnoreError))
<> 144:ef7eb2e8f9f7 548 {
<> 144:ef7eb2e8f9f7 549 error = kStatus_Fail;
<> 144:ef7eb2e8f9f7 550 }
<> 144:ef7eb2e8f9f7 551 }
<> 144:ef7eb2e8f9f7 552 if (error == kStatus_Success)
<> 144:ef7eb2e8f9f7 553 {
<> 144:ef7eb2e8f9f7 554 transferredWords = SDHC_WriteDataPort(base, data, transferredWords);
<> 144:ef7eb2e8f9f7 555 }
<> 144:ef7eb2e8f9f7 556
<> 144:ef7eb2e8f9f7 557 /* Clear buffer enable flag to trigger transfer. Clear error flag when SDHC encounter error. */
<> 144:ef7eb2e8f9f7 558 SDHC_ClearInterruptStatusFlags(base, (kSDHC_BufferWriteReadyFlag | kSDHC_DataErrorFlag));
<> 144:ef7eb2e8f9f7 559 }
<> 144:ef7eb2e8f9f7 560
<> 144:ef7eb2e8f9f7 561 /* Wait write data complete or data transfer error after the last writing operation. */
<> 144:ef7eb2e8f9f7 562 while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag)))
<> 144:ef7eb2e8f9f7 563 {
<> 144:ef7eb2e8f9f7 564 }
<> 144:ef7eb2e8f9f7 565 if (SDHC_GetInterruptStatusFlags(base) & kSDHC_DataErrorFlag)
<> 144:ef7eb2e8f9f7 566 {
<> 144:ef7eb2e8f9f7 567 if (!(data->enableIgnoreError))
<> 144:ef7eb2e8f9f7 568 {
<> 144:ef7eb2e8f9f7 569 error = kStatus_Fail;
<> 144:ef7eb2e8f9f7 570 }
<> 144:ef7eb2e8f9f7 571 }
<> 144:ef7eb2e8f9f7 572 SDHC_ClearInterruptStatusFlags(base, (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag));
<> 144:ef7eb2e8f9f7 573
<> 144:ef7eb2e8f9f7 574 return error;
<> 144:ef7eb2e8f9f7 575 }
<> 144:ef7eb2e8f9f7 576
<> 144:ef7eb2e8f9f7 577 static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *command)
<> 144:ef7eb2e8f9f7 578 {
<> 144:ef7eb2e8f9f7 579 assert(command);
<> 144:ef7eb2e8f9f7 580
<> 144:ef7eb2e8f9f7 581 status_t error = kStatus_Success;
<> 144:ef7eb2e8f9f7 582
<> 144:ef7eb2e8f9f7 583 /* Wait command complete or SDHC encounters error. */
<> 144:ef7eb2e8f9f7 584 while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_CommandCompleteFlag | kSDHC_CommandErrorFlag)))
<> 144:ef7eb2e8f9f7 585 {
<> 144:ef7eb2e8f9f7 586 }
<> 144:ef7eb2e8f9f7 587
<> 144:ef7eb2e8f9f7 588 if (SDHC_GetInterruptStatusFlags(base) & kSDHC_CommandErrorFlag)
<> 144:ef7eb2e8f9f7 589 {
<> 144:ef7eb2e8f9f7 590 error = kStatus_Fail;
<> 144:ef7eb2e8f9f7 591 }
<> 144:ef7eb2e8f9f7 592 /* Receive response when command completes successfully. */
<> 144:ef7eb2e8f9f7 593 if (error == kStatus_Success)
<> 144:ef7eb2e8f9f7 594 {
<> 144:ef7eb2e8f9f7 595 SDHC_ReceiveCommandResponse(base, command);
<> 144:ef7eb2e8f9f7 596 }
<> 144:ef7eb2e8f9f7 597
<> 144:ef7eb2e8f9f7 598 SDHC_ClearInterruptStatusFlags(base, (kSDHC_CommandCompleteFlag | kSDHC_CommandErrorFlag));
<> 144:ef7eb2e8f9f7 599
<> 144:ef7eb2e8f9f7 600 return error;
<> 144:ef7eb2e8f9f7 601 }
<> 144:ef7eb2e8f9f7 602
<> 144:ef7eb2e8f9f7 603 static status_t SDHC_TransferByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data)
<> 144:ef7eb2e8f9f7 604 {
<> 144:ef7eb2e8f9f7 605 assert(data);
<> 144:ef7eb2e8f9f7 606
<> 144:ef7eb2e8f9f7 607 status_t error = kStatus_Success;
<> 144:ef7eb2e8f9f7 608
<> 144:ef7eb2e8f9f7 609 if (data->rxData)
<> 144:ef7eb2e8f9f7 610 {
<> 144:ef7eb2e8f9f7 611 error = SDHC_ReadByDataPortBlocking(base, data);
<> 144:ef7eb2e8f9f7 612 }
<> 144:ef7eb2e8f9f7 613 else
<> 144:ef7eb2e8f9f7 614 {
<> 144:ef7eb2e8f9f7 615 error = SDHC_WriteByDataPortBlocking(base, data);
<> 144:ef7eb2e8f9f7 616 }
<> 144:ef7eb2e8f9f7 617
<> 144:ef7eb2e8f9f7 618 return error;
<> 144:ef7eb2e8f9f7 619 }
<> 144:ef7eb2e8f9f7 620
<> 144:ef7eb2e8f9f7 621 static status_t SDHC_TransferByAdma2Blocking(SDHC_Type *base, sdhc_data_t *data)
<> 144:ef7eb2e8f9f7 622 {
<> 144:ef7eb2e8f9f7 623 status_t error = kStatus_Success;
<> 144:ef7eb2e8f9f7 624
<> 144:ef7eb2e8f9f7 625 /* Wait data complete or SDHC encounters error. */
<> 144:ef7eb2e8f9f7 626 while (!(SDHC_GetInterruptStatusFlags(base) & (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag)))
<> 144:ef7eb2e8f9f7 627 {
<> 144:ef7eb2e8f9f7 628 }
<> 144:ef7eb2e8f9f7 629 if (SDHC_GetInterruptStatusFlags(base) & (kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag))
<> 144:ef7eb2e8f9f7 630 {
<> 144:ef7eb2e8f9f7 631 if (!(data->enableIgnoreError))
<> 144:ef7eb2e8f9f7 632 {
<> 144:ef7eb2e8f9f7 633 error = kStatus_Fail;
<> 144:ef7eb2e8f9f7 634 }
<> 144:ef7eb2e8f9f7 635 }
<> 144:ef7eb2e8f9f7 636 SDHC_ClearInterruptStatusFlags(
<> 144:ef7eb2e8f9f7 637 base, (kSDHC_DataCompleteFlag | kSDHC_DmaCompleteFlag | kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag));
<> 144:ef7eb2e8f9f7 638 return error;
<> 144:ef7eb2e8f9f7 639 }
<> 144:ef7eb2e8f9f7 640
<> 144:ef7eb2e8f9f7 641 #if defined FSL_SDHC_ENABLE_ADMA1
<> 144:ef7eb2e8f9f7 642 #define SDHC_TransferByAdma1Blocking(base, data) SDHC_TransferByAdma2Blocking(base, data)
<> 144:ef7eb2e8f9f7 643 #endif /* FSL_SDHC_ENABLE_ADMA1 */
<> 144:ef7eb2e8f9f7 644
<> 144:ef7eb2e8f9f7 645 static status_t SDHC_TransferDataBlocking(sdhc_dma_mode_t dmaMode, SDHC_Type *base, sdhc_data_t *data)
<> 144:ef7eb2e8f9f7 646 {
<> 144:ef7eb2e8f9f7 647 status_t error = kStatus_Success;
<> 144:ef7eb2e8f9f7 648
<> 144:ef7eb2e8f9f7 649 switch (dmaMode)
<> 144:ef7eb2e8f9f7 650 {
<> 144:ef7eb2e8f9f7 651 case kSDHC_DmaModeNo:
<> 144:ef7eb2e8f9f7 652 error = SDHC_TransferByDataPortBlocking(base, data);
<> 144:ef7eb2e8f9f7 653 break;
<> 144:ef7eb2e8f9f7 654 #if defined FSL_SDHC_ENABLE_ADMA1
<> 144:ef7eb2e8f9f7 655 case kSDHC_DmaModeAdma1:
<> 144:ef7eb2e8f9f7 656 error = SDHC_TransferByAdma1Blocking(base, data);
<> 144:ef7eb2e8f9f7 657 break;
<> 144:ef7eb2e8f9f7 658 #endif /* FSL_SDHC_ENABLE_ADMA1 */
<> 144:ef7eb2e8f9f7 659 case kSDHC_DmaModeAdma2:
<> 144:ef7eb2e8f9f7 660 error = SDHC_TransferByAdma2Blocking(base, data);
<> 144:ef7eb2e8f9f7 661 break;
<> 144:ef7eb2e8f9f7 662 default:
<> 144:ef7eb2e8f9f7 663 error = kStatus_InvalidArgument;
<> 144:ef7eb2e8f9f7 664 break;
<> 144:ef7eb2e8f9f7 665 }
<> 144:ef7eb2e8f9f7 666
<> 144:ef7eb2e8f9f7 667 return error;
<> 144:ef7eb2e8f9f7 668 }
<> 144:ef7eb2e8f9f7 669
<> 144:ef7eb2e8f9f7 670 static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interruptFlags)
<> 144:ef7eb2e8f9f7 671 {
<> 144:ef7eb2e8f9f7 672 assert(interruptFlags & kSDHC_CardDetectFlag);
<> 144:ef7eb2e8f9f7 673
<> 144:ef7eb2e8f9f7 674 if (interruptFlags & kSDHC_CardInsertionFlag)
<> 144:ef7eb2e8f9f7 675 {
<> 144:ef7eb2e8f9f7 676 if (handle->callback.CardInserted)
<> 144:ef7eb2e8f9f7 677 {
<> 144:ef7eb2e8f9f7 678 handle->callback.CardInserted();
<> 144:ef7eb2e8f9f7 679 }
<> 144:ef7eb2e8f9f7 680 }
<> 144:ef7eb2e8f9f7 681 else
<> 144:ef7eb2e8f9f7 682 {
<> 144:ef7eb2e8f9f7 683 if (handle->callback.CardRemoved)
<> 144:ef7eb2e8f9f7 684 {
<> 144:ef7eb2e8f9f7 685 handle->callback.CardRemoved();
<> 144:ef7eb2e8f9f7 686 }
<> 144:ef7eb2e8f9f7 687 }
<> 144:ef7eb2e8f9f7 688 }
<> 144:ef7eb2e8f9f7 689
<> 144:ef7eb2e8f9f7 690 static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags)
<> 144:ef7eb2e8f9f7 691 {
<> 144:ef7eb2e8f9f7 692 assert(interruptFlags & kSDHC_CommandFlag);
<> 144:ef7eb2e8f9f7 693
<> 144:ef7eb2e8f9f7 694 if ((interruptFlags & kSDHC_CommandErrorFlag) && (!(handle->data)) && (handle->callback.TransferComplete))
<> 144:ef7eb2e8f9f7 695 {
<> 144:ef7eb2e8f9f7 696 handle->callback.TransferComplete(base, handle, kStatus_SDHC_SendCommandFailed, handle->userData);
<> 144:ef7eb2e8f9f7 697 }
<> 144:ef7eb2e8f9f7 698 else
<> 144:ef7eb2e8f9f7 699 {
<> 144:ef7eb2e8f9f7 700 /* Receive response */
<> 144:ef7eb2e8f9f7 701 SDHC_ReceiveCommandResponse(base, handle->command);
<> 144:ef7eb2e8f9f7 702 if ((!(handle->data)) && (handle->callback.TransferComplete))
<> 144:ef7eb2e8f9f7 703 {
<> 144:ef7eb2e8f9f7 704 handle->callback.TransferComplete(base, handle, kStatus_Success, handle->userData);
<> 144:ef7eb2e8f9f7 705 }
<> 144:ef7eb2e8f9f7 706 }
<> 144:ef7eb2e8f9f7 707 }
<> 144:ef7eb2e8f9f7 708
<> 144:ef7eb2e8f9f7 709 static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags)
<> 144:ef7eb2e8f9f7 710 {
<> 144:ef7eb2e8f9f7 711 assert(handle->data);
<> 144:ef7eb2e8f9f7 712 assert(interruptFlags & kSDHC_DataFlag);
<> 144:ef7eb2e8f9f7 713
<> 144:ef7eb2e8f9f7 714 if ((!(handle->data->enableIgnoreError)) && (interruptFlags & (kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag)) &&
<> 144:ef7eb2e8f9f7 715 (handle->callback.TransferComplete))
<> 144:ef7eb2e8f9f7 716 {
<> 144:ef7eb2e8f9f7 717 handle->callback.TransferComplete(base, handle, kStatus_SDHC_TransferDataFailed, handle->userData);
<> 144:ef7eb2e8f9f7 718 }
<> 144:ef7eb2e8f9f7 719 else
<> 144:ef7eb2e8f9f7 720 {
<> 144:ef7eb2e8f9f7 721 if (interruptFlags & kSDHC_BufferReadReadyFlag)
<> 144:ef7eb2e8f9f7 722 {
<> 144:ef7eb2e8f9f7 723 handle->transferredWords = SDHC_ReadDataPort(base, handle->data, handle->transferredWords);
<> 144:ef7eb2e8f9f7 724 }
<> 144:ef7eb2e8f9f7 725 else if (interruptFlags & kSDHC_BufferWriteReadyFlag)
<> 144:ef7eb2e8f9f7 726 {
<> 144:ef7eb2e8f9f7 727 handle->transferredWords = SDHC_WriteDataPort(base, handle->data, handle->transferredWords);
<> 144:ef7eb2e8f9f7 728 }
<> 144:ef7eb2e8f9f7 729 else if ((interruptFlags & kSDHC_DataCompleteFlag) && (handle->callback.TransferComplete))
<> 144:ef7eb2e8f9f7 730 {
<> 144:ef7eb2e8f9f7 731 handle->callback.TransferComplete(base, handle, kStatus_Success, handle->userData);
<> 144:ef7eb2e8f9f7 732 }
<> 144:ef7eb2e8f9f7 733 else
<> 144:ef7eb2e8f9f7 734 {
<> 144:ef7eb2e8f9f7 735 /* Do nothing when DMA complete flag is set. Wait until data complete flag is set. */
<> 144:ef7eb2e8f9f7 736 }
<> 144:ef7eb2e8f9f7 737 }
<> 144:ef7eb2e8f9f7 738 }
<> 144:ef7eb2e8f9f7 739
<> 144:ef7eb2e8f9f7 740 static void SDHC_TransferHandleSdioInterrupt(sdhc_handle_t *handle)
<> 144:ef7eb2e8f9f7 741 {
<> 144:ef7eb2e8f9f7 742 if (handle->callback.SdioInterrupt)
<> 144:ef7eb2e8f9f7 743 {
<> 144:ef7eb2e8f9f7 744 handle->callback.SdioInterrupt();
<> 144:ef7eb2e8f9f7 745 }
<> 144:ef7eb2e8f9f7 746 }
<> 144:ef7eb2e8f9f7 747
<> 144:ef7eb2e8f9f7 748 static void SDHC_TransferHandleSdioBlockGap(sdhc_handle_t *handle)
<> 144:ef7eb2e8f9f7 749 {
<> 144:ef7eb2e8f9f7 750 if (handle->callback.SdioBlockGap)
<> 144:ef7eb2e8f9f7 751 {
<> 144:ef7eb2e8f9f7 752 handle->callback.SdioBlockGap();
<> 144:ef7eb2e8f9f7 753 }
<> 144:ef7eb2e8f9f7 754 }
<> 144:ef7eb2e8f9f7 755
<> 144:ef7eb2e8f9f7 756 void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config)
<> 144:ef7eb2e8f9f7 757 {
<> 144:ef7eb2e8f9f7 758 assert(config);
<> 144:ef7eb2e8f9f7 759 #if !defined FSL_SDHC_ENABLE_ADMA1
<> 144:ef7eb2e8f9f7 760 assert(config->dmaMode != kSDHC_DmaModeAdma1);
<> 144:ef7eb2e8f9f7 761 #endif /* FSL_SDHC_ENABLE_ADMA1 */
<> 144:ef7eb2e8f9f7 762
<> 144:ef7eb2e8f9f7 763 uint32_t proctl;
<> 144:ef7eb2e8f9f7 764 uint32_t wml;
<> 144:ef7eb2e8f9f7 765
<> 144:ef7eb2e8f9f7 766 /* Enable SDHC clock. */
<> 144:ef7eb2e8f9f7 767 CLOCK_EnableClock(s_sdhcClock[SDHC_GetInstance(base)]);
<> 144:ef7eb2e8f9f7 768
<> 144:ef7eb2e8f9f7 769 /* Reset SDHC. */
<> 144:ef7eb2e8f9f7 770 SDHC_Reset(base, kSDHC_ResetAll, 100);
<> 144:ef7eb2e8f9f7 771
<> 144:ef7eb2e8f9f7 772 proctl = base->PROCTL;
<> 144:ef7eb2e8f9f7 773 wml = base->WML;
<> 144:ef7eb2e8f9f7 774
<> 144:ef7eb2e8f9f7 775 proctl &= ~(SDHC_PROCTL_D3CD_MASK | SDHC_PROCTL_EMODE_MASK | SDHC_PROCTL_DMAS_MASK);
<> 144:ef7eb2e8f9f7 776 /* Set DAT3 as card detection pin */
<> 144:ef7eb2e8f9f7 777 if (config->cardDetectDat3)
<> 144:ef7eb2e8f9f7 778 {
<> 144:ef7eb2e8f9f7 779 proctl |= SDHC_PROCTL_D3CD_MASK;
<> 144:ef7eb2e8f9f7 780 }
<> 144:ef7eb2e8f9f7 781 /* Endian mode and DMA mode */
<> 144:ef7eb2e8f9f7 782 proctl |= (SDHC_PROCTL_EMODE(config->endianMode) | SDHC_PROCTL_DMAS(config->dmaMode));
<> 144:ef7eb2e8f9f7 783
<> 144:ef7eb2e8f9f7 784 /* Watermark level */
<> 144:ef7eb2e8f9f7 785 wml &= ~(SDHC_WML_RDWML_MASK | SDHC_WML_WRWML_MASK);
<> 144:ef7eb2e8f9f7 786 wml |= (SDHC_WML_RDWML(config->readWatermarkLevel) | SDHC_WML_WRWML(config->writeWatermarkLevel));
<> 144:ef7eb2e8f9f7 787
<> 144:ef7eb2e8f9f7 788 base->WML = wml;
<> 144:ef7eb2e8f9f7 789 base->PROCTL = proctl;
<> 144:ef7eb2e8f9f7 790
<> 144:ef7eb2e8f9f7 791 /* Disable all clock auto gated off feature because of DAT0 line logic(card buffer full status) can't be updated
<> 144:ef7eb2e8f9f7 792 correctly when clock auto gated off is enabled. */
<> 144:ef7eb2e8f9f7 793 base->SYSCTL |= (SDHC_SYSCTL_PEREN_MASK | SDHC_SYSCTL_HCKEN_MASK | SDHC_SYSCTL_IPGEN_MASK);
<> 144:ef7eb2e8f9f7 794
<> 144:ef7eb2e8f9f7 795 /* Enable interrupt status but doesn't enable interrupt signal. */
<> 144:ef7eb2e8f9f7 796 SDHC_SetTransferInterrupt(base, false);
<> 144:ef7eb2e8f9f7 797 }
<> 144:ef7eb2e8f9f7 798
<> 144:ef7eb2e8f9f7 799 void SDHC_Deinit(SDHC_Type *base)
<> 144:ef7eb2e8f9f7 800 {
<> 144:ef7eb2e8f9f7 801 /* Disable clock. */
<> 144:ef7eb2e8f9f7 802 CLOCK_DisableClock(s_sdhcClock[SDHC_GetInstance(base)]);
<> 144:ef7eb2e8f9f7 803 }
<> 144:ef7eb2e8f9f7 804
<> 144:ef7eb2e8f9f7 805 bool SDHC_Reset(SDHC_Type *base, uint32_t mask, uint32_t timeout)
<> 144:ef7eb2e8f9f7 806 {
<> 144:ef7eb2e8f9f7 807 base->SYSCTL |= (mask & (SDHC_SYSCTL_RSTA_MASK | SDHC_SYSCTL_RSTC_MASK | SDHC_SYSCTL_RSTD_MASK));
<> 144:ef7eb2e8f9f7 808 /* Delay some time to wait reset success. */
<> 144:ef7eb2e8f9f7 809 while ((base->SYSCTL & mask))
<> 144:ef7eb2e8f9f7 810 {
<> 144:ef7eb2e8f9f7 811 if (!timeout)
<> 144:ef7eb2e8f9f7 812 {
<> 144:ef7eb2e8f9f7 813 break;
<> 144:ef7eb2e8f9f7 814 }
<> 144:ef7eb2e8f9f7 815 timeout--;
<> 144:ef7eb2e8f9f7 816 }
<> 144:ef7eb2e8f9f7 817
<> 144:ef7eb2e8f9f7 818 return ((!timeout) ? false : true);
<> 144:ef7eb2e8f9f7 819 }
<> 144:ef7eb2e8f9f7 820
<> 144:ef7eb2e8f9f7 821 void SDHC_GetCapability(SDHC_Type *base, sdhc_capability_t *capability)
<> 144:ef7eb2e8f9f7 822 {
<> 144:ef7eb2e8f9f7 823 assert(capability);
<> 144:ef7eb2e8f9f7 824
<> 144:ef7eb2e8f9f7 825 uint32_t htCapability;
<> 144:ef7eb2e8f9f7 826 uint32_t hostVer;
<> 144:ef7eb2e8f9f7 827 uint32_t maxBlockLength;
<> 144:ef7eb2e8f9f7 828
<> 144:ef7eb2e8f9f7 829 hostVer = base->HOSTVER;
<> 144:ef7eb2e8f9f7 830 htCapability = base->HTCAPBLT;
<> 144:ef7eb2e8f9f7 831
<> 144:ef7eb2e8f9f7 832 /* Get the capability of SDHC. */
<> 144:ef7eb2e8f9f7 833 capability->specVersion = ((hostVer & SDHC_HOSTVER_SVN_MASK) >> SDHC_HOSTVER_SVN_SHIFT);
<> 144:ef7eb2e8f9f7 834 capability->vendorVersion = ((hostVer & SDHC_HOSTVER_VVN_MASK) >> SDHC_HOSTVER_VVN_SHIFT);
<> 144:ef7eb2e8f9f7 835 maxBlockLength = ((htCapability & SDHC_HTCAPBLT_MBL_MASK) >> SDHC_HTCAPBLT_MBL_SHIFT);
<> 144:ef7eb2e8f9f7 836 capability->maxBlockLength = (512U << maxBlockLength);
<> 144:ef7eb2e8f9f7 837 /* Other attributes not in HTCAPBLT register. */
<> 144:ef7eb2e8f9f7 838 capability->maxBlockCount = SDHC_MAX_BLOCK_COUNT;
<> 144:ef7eb2e8f9f7 839 capability->flags = (htCapability & (kSDHC_SupportAdmaFlag | kSDHC_SupportHighSpeedFlag | kSDHC_SupportDmaFlag |
<> 144:ef7eb2e8f9f7 840 kSDHC_SupportSuspendResumeFlag | kSDHC_SupportV330Flag));
<> 144:ef7eb2e8f9f7 841 #if defined FSL_FEATURE_SDHC_HAS_V300_SUPPORT && FSL_FEATURE_SDHC_HAS_V300_SUPPORT
<> 144:ef7eb2e8f9f7 842 capability->flags |= (htCapability & kSDHC_SupportV300Flag);
<> 144:ef7eb2e8f9f7 843 #endif
<> 144:ef7eb2e8f9f7 844 #if defined FSL_FEATURE_SDHC_HAS_V180_SUPPORT && FSL_FEATURE_SDHC_HAS_V180_SUPPORT
<> 144:ef7eb2e8f9f7 845 capability->flags |= (htCapability & kSDHC_SupportV180Flag);
<> 144:ef7eb2e8f9f7 846 #endif
<> 144:ef7eb2e8f9f7 847 /* eSDHC on all kinetis boards will support 4/8 bit data bus width. */
<> 144:ef7eb2e8f9f7 848 capability->flags |= (kSDHC_Support4BitFlag | kSDHC_Support8BitFlag);
<> 144:ef7eb2e8f9f7 849 }
<> 144:ef7eb2e8f9f7 850
<> 144:ef7eb2e8f9f7 851 uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz)
<> 144:ef7eb2e8f9f7 852 {
<> 144:ef7eb2e8f9f7 853 assert(busClock_Hz && (busClock_Hz < srcClock_Hz));
<> 144:ef7eb2e8f9f7 854
<> 144:ef7eb2e8f9f7 855 uint32_t divisor;
<> 144:ef7eb2e8f9f7 856 uint32_t prescaler;
<> 144:ef7eb2e8f9f7 857 uint32_t sysctl;
<> 144:ef7eb2e8f9f7 858 uint32_t nearestFrequency = 0;
<> 144:ef7eb2e8f9f7 859
<> 144:ef7eb2e8f9f7 860 divisor = SDHC_INITIAL_DVS;
<> 144:ef7eb2e8f9f7 861 prescaler = SDHC_INITIAL_CLKFS;
<> 144:ef7eb2e8f9f7 862
<> 144:ef7eb2e8f9f7 863 /* Disable SD clock. It should be disabled before changing the SD clock frequency.*/
<> 144:ef7eb2e8f9f7 864 base->SYSCTL &= ~SDHC_SYSCTL_SDCLKEN_MASK;
<> 144:ef7eb2e8f9f7 865
<> 144:ef7eb2e8f9f7 866 if (busClock_Hz > 0U)
<> 144:ef7eb2e8f9f7 867 {
<> 144:ef7eb2e8f9f7 868 while ((srcClock_Hz / prescaler / SDHC_MAX_DVS > busClock_Hz) && (prescaler < SDHC_MAX_CLKFS))
<> 144:ef7eb2e8f9f7 869 {
<> 144:ef7eb2e8f9f7 870 SDHC_NEXT_CLKFS(prescaler);
<> 144:ef7eb2e8f9f7 871 }
<> 144:ef7eb2e8f9f7 872 while ((srcClock_Hz / prescaler / divisor > busClock_Hz) && (divisor < SDHC_MAX_DVS))
<> 144:ef7eb2e8f9f7 873 {
<> 144:ef7eb2e8f9f7 874 SDHC_NEXT_DVS(divisor);
<> 144:ef7eb2e8f9f7 875 }
<> 144:ef7eb2e8f9f7 876 nearestFrequency = srcClock_Hz / prescaler / divisor;
<> 144:ef7eb2e8f9f7 877 SDHC_PREV_CLKFS(prescaler);
<> 144:ef7eb2e8f9f7 878 SDHC_PREV_DVS(divisor);
<> 144:ef7eb2e8f9f7 879
<> 144:ef7eb2e8f9f7 880 /* Set the SD clock frequency divisor, SD clock frequency select, data timeout counter value. */
<> 144:ef7eb2e8f9f7 881 sysctl = base->SYSCTL;
<> 144:ef7eb2e8f9f7 882 sysctl &= ~(SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK | SDHC_SYSCTL_DTOCV_MASK);
<> 144:ef7eb2e8f9f7 883 sysctl |= (SDHC_SYSCTL_DVS(divisor) | SDHC_SYSCTL_SDCLKFS(prescaler) | SDHC_SYSCTL_DTOCV(0xEU));
<> 144:ef7eb2e8f9f7 884 base->SYSCTL = sysctl;
<> 144:ef7eb2e8f9f7 885
<> 144:ef7eb2e8f9f7 886 /* Wait until the SD clock is stable. */
<> 144:ef7eb2e8f9f7 887 while (!(base->PRSSTAT & SDHC_PRSSTAT_SDSTB_MASK))
<> 144:ef7eb2e8f9f7 888 {
<> 144:ef7eb2e8f9f7 889 }
<> 144:ef7eb2e8f9f7 890 /* Enable the SD clock. */
<> 144:ef7eb2e8f9f7 891 base->SYSCTL |= SDHC_SYSCTL_SDCLKEN_MASK;
<> 144:ef7eb2e8f9f7 892 }
<> 144:ef7eb2e8f9f7 893
<> 144:ef7eb2e8f9f7 894 return nearestFrequency;
<> 144:ef7eb2e8f9f7 895 }
<> 144:ef7eb2e8f9f7 896
<> 144:ef7eb2e8f9f7 897 bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout)
<> 144:ef7eb2e8f9f7 898 {
<> 144:ef7eb2e8f9f7 899 base->SYSCTL |= SDHC_SYSCTL_INITA_MASK;
<> 144:ef7eb2e8f9f7 900 /* Delay some time to wait card become active state. */
<> 144:ef7eb2e8f9f7 901 while (!(base->SYSCTL & SDHC_SYSCTL_INITA_MASK))
<> 144:ef7eb2e8f9f7 902 {
<> 144:ef7eb2e8f9f7 903 if (!timeout)
<> 144:ef7eb2e8f9f7 904 {
<> 144:ef7eb2e8f9f7 905 break;
<> 144:ef7eb2e8f9f7 906 }
<> 144:ef7eb2e8f9f7 907 timeout--;
<> 144:ef7eb2e8f9f7 908 }
<> 144:ef7eb2e8f9f7 909
<> 144:ef7eb2e8f9f7 910 return ((!timeout) ? false : true);
<> 144:ef7eb2e8f9f7 911 }
<> 144:ef7eb2e8f9f7 912
<> 144:ef7eb2e8f9f7 913 void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config)
<> 144:ef7eb2e8f9f7 914 {
<> 144:ef7eb2e8f9f7 915 assert(config);
<> 144:ef7eb2e8f9f7 916
<> 144:ef7eb2e8f9f7 917 base->BLKATTR = ((base->BLKATTR & ~(SDHC_BLKATTR_BLKSIZE_MASK | SDHC_BLKATTR_BLKCNT_MASK)) |
<> 144:ef7eb2e8f9f7 918 (SDHC_BLKATTR_BLKSIZE(config->dataBlockSize) | SDHC_BLKATTR_BLKCNT(config->dataBlockCount)));
<> 144:ef7eb2e8f9f7 919 base->CMDARG = config->commandArgument;
<> 144:ef7eb2e8f9f7 920 base->XFERTYP = (((config->commandIndex << SDHC_XFERTYP_CMDINX_SHIFT) & SDHC_XFERTYP_CMDINX_MASK) |
<> 144:ef7eb2e8f9f7 921 (config->flags & (SDHC_XFERTYP_DMAEN_MASK | SDHC_XFERTYP_MSBSEL_MASK | SDHC_XFERTYP_DPSEL_MASK |
<> 144:ef7eb2e8f9f7 922 SDHC_XFERTYP_CMDTYP_MASK | SDHC_XFERTYP_BCEN_MASK | SDHC_XFERTYP_CICEN_MASK |
<> 144:ef7eb2e8f9f7 923 SDHC_XFERTYP_CCCEN_MASK | SDHC_XFERTYP_RSPTYP_MASK | SDHC_XFERTYP_DTDSEL_MASK |
<> 144:ef7eb2e8f9f7 924 SDHC_XFERTYP_AC12EN_MASK)));
<> 144:ef7eb2e8f9f7 925 }
<> 144:ef7eb2e8f9f7 926
<> 144:ef7eb2e8f9f7 927 void SDHC_EnableSdioControl(SDHC_Type *base, uint32_t mask, bool enable)
<> 144:ef7eb2e8f9f7 928 {
<> 144:ef7eb2e8f9f7 929 uint32_t proctl = base->PROCTL;
<> 144:ef7eb2e8f9f7 930 uint32_t vendor = base->VENDOR;
<> 144:ef7eb2e8f9f7 931
<> 144:ef7eb2e8f9f7 932 if (enable)
<> 144:ef7eb2e8f9f7 933 {
<> 144:ef7eb2e8f9f7 934 if (mask & kSDHC_StopAtBlockGapFlag)
<> 144:ef7eb2e8f9f7 935 {
<> 144:ef7eb2e8f9f7 936 proctl |= SDHC_PROCTL_SABGREQ_MASK;
<> 144:ef7eb2e8f9f7 937 }
<> 144:ef7eb2e8f9f7 938 if (mask & kSDHC_ReadWaitControlFlag)
<> 144:ef7eb2e8f9f7 939 {
<> 144:ef7eb2e8f9f7 940 proctl |= SDHC_PROCTL_RWCTL_MASK;
<> 144:ef7eb2e8f9f7 941 }
<> 144:ef7eb2e8f9f7 942 if (mask & kSDHC_InterruptAtBlockGapFlag)
<> 144:ef7eb2e8f9f7 943 {
<> 144:ef7eb2e8f9f7 944 proctl |= SDHC_PROCTL_IABG_MASK;
<> 144:ef7eb2e8f9f7 945 }
<> 144:ef7eb2e8f9f7 946 if (mask & kSDHC_ExactBlockNumberReadFlag)
<> 144:ef7eb2e8f9f7 947 {
<> 144:ef7eb2e8f9f7 948 vendor |= SDHC_VENDOR_EXBLKNU_MASK;
<> 144:ef7eb2e8f9f7 949 }
<> 144:ef7eb2e8f9f7 950 }
<> 144:ef7eb2e8f9f7 951 else
<> 144:ef7eb2e8f9f7 952 {
<> 144:ef7eb2e8f9f7 953 if (mask & kSDHC_StopAtBlockGapFlag)
<> 144:ef7eb2e8f9f7 954 {
<> 144:ef7eb2e8f9f7 955 proctl &= ~SDHC_PROCTL_SABGREQ_MASK;
<> 144:ef7eb2e8f9f7 956 }
<> 144:ef7eb2e8f9f7 957 if (mask & kSDHC_ReadWaitControlFlag)
<> 144:ef7eb2e8f9f7 958 {
<> 144:ef7eb2e8f9f7 959 proctl &= ~SDHC_PROCTL_RWCTL_MASK;
<> 144:ef7eb2e8f9f7 960 }
<> 144:ef7eb2e8f9f7 961 if (mask & kSDHC_InterruptAtBlockGapFlag)
<> 144:ef7eb2e8f9f7 962 {
<> 144:ef7eb2e8f9f7 963 proctl &= ~SDHC_PROCTL_IABG_MASK;
<> 144:ef7eb2e8f9f7 964 }
<> 144:ef7eb2e8f9f7 965 if (mask & kSDHC_ExactBlockNumberReadFlag)
<> 144:ef7eb2e8f9f7 966 {
<> 144:ef7eb2e8f9f7 967 vendor &= ~SDHC_VENDOR_EXBLKNU_MASK;
<> 144:ef7eb2e8f9f7 968 }
<> 144:ef7eb2e8f9f7 969 }
<> 144:ef7eb2e8f9f7 970
<> 144:ef7eb2e8f9f7 971 base->PROCTL = proctl;
<> 144:ef7eb2e8f9f7 972 base->VENDOR = vendor;
<> 144:ef7eb2e8f9f7 973 }
<> 144:ef7eb2e8f9f7 974
<> 144:ef7eb2e8f9f7 975 void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config)
<> 144:ef7eb2e8f9f7 976 {
<> 144:ef7eb2e8f9f7 977 assert(config);
<> 144:ef7eb2e8f9f7 978
<> 144:ef7eb2e8f9f7 979 uint32_t mmcboot;
<> 144:ef7eb2e8f9f7 980
<> 144:ef7eb2e8f9f7 981 mmcboot = base->MMCBOOT;
<> 144:ef7eb2e8f9f7 982 mmcboot |= (SDHC_MMCBOOT_DTOCVACK(config->ackTimeoutCount) | SDHC_MMCBOOT_BOOTMODE(config->bootMode) |
<> 144:ef7eb2e8f9f7 983 SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount));
<> 144:ef7eb2e8f9f7 984 if (config->enableBootAck)
<> 144:ef7eb2e8f9f7 985 {
<> 144:ef7eb2e8f9f7 986 mmcboot |= SDHC_MMCBOOT_BOOTACK_MASK;
<> 144:ef7eb2e8f9f7 987 }
<> 144:ef7eb2e8f9f7 988 if (config->enableBoot)
<> 144:ef7eb2e8f9f7 989 {
<> 144:ef7eb2e8f9f7 990 mmcboot |= SDHC_MMCBOOT_BOOTEN_MASK;
<> 144:ef7eb2e8f9f7 991 }
<> 144:ef7eb2e8f9f7 992 if (config->enableAutoStopAtBlockGap)
<> 144:ef7eb2e8f9f7 993 {
<> 144:ef7eb2e8f9f7 994 mmcboot |= SDHC_MMCBOOT_AUTOSABGEN_MASK;
<> 144:ef7eb2e8f9f7 995 }
<> 144:ef7eb2e8f9f7 996 base->MMCBOOT = mmcboot;
<> 144:ef7eb2e8f9f7 997 }
<> 144:ef7eb2e8f9f7 998
<> 144:ef7eb2e8f9f7 999 status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
<> 144:ef7eb2e8f9f7 1000 sdhc_dma_mode_t dmaMode,
<> 144:ef7eb2e8f9f7 1001 uint32_t *table,
<> 144:ef7eb2e8f9f7 1002 uint32_t tableWords,
<> 144:ef7eb2e8f9f7 1003 const uint32_t *data,
<> 144:ef7eb2e8f9f7 1004 uint32_t dataBytes)
<> 144:ef7eb2e8f9f7 1005 {
<> 144:ef7eb2e8f9f7 1006 status_t error = kStatus_Success;
<> 144:ef7eb2e8f9f7 1007 const uint32_t *startAddress;
<> 144:ef7eb2e8f9f7 1008 uint32_t entries;
<> 144:ef7eb2e8f9f7 1009 uint32_t i;
<> 144:ef7eb2e8f9f7 1010 #if defined FSL_SDHC_ENABLE_ADMA1
<> 144:ef7eb2e8f9f7 1011 sdhc_adma1_descriptor_t *adma1EntryAddress;
<> 144:ef7eb2e8f9f7 1012 #endif
<> 144:ef7eb2e8f9f7 1013 sdhc_adma2_descriptor_t *adma2EntryAddress;
<> 144:ef7eb2e8f9f7 1014
<> 144:ef7eb2e8f9f7 1015 if ((((!table) || (!tableWords)) && ((dmaMode == kSDHC_DmaModeAdma1) || (dmaMode == kSDHC_DmaModeAdma2))) ||
<> 144:ef7eb2e8f9f7 1016 (!data) || (!dataBytes)
<> 144:ef7eb2e8f9f7 1017 #if !defined FSL_SDHC_ENABLE_ADMA1
<> 144:ef7eb2e8f9f7 1018 || (dmaMode == kSDHC_DmaModeAdma1)
<> 144:ef7eb2e8f9f7 1019 #endif /* FSL_SDHC_ENABLE_ADMA1 */
<> 144:ef7eb2e8f9f7 1020 )
<> 144:ef7eb2e8f9f7 1021 {
<> 144:ef7eb2e8f9f7 1022 error = kStatus_InvalidArgument;
<> 144:ef7eb2e8f9f7 1023 }
<> 144:ef7eb2e8f9f7 1024 else
<> 144:ef7eb2e8f9f7 1025 {
<> 144:ef7eb2e8f9f7 1026 switch (dmaMode)
<> 144:ef7eb2e8f9f7 1027 {
<> 144:ef7eb2e8f9f7 1028 case kSDHC_DmaModeNo:
<> 144:ef7eb2e8f9f7 1029 break;
<> 144:ef7eb2e8f9f7 1030 #if defined FSL_SDHC_ENABLE_ADMA1
<> 144:ef7eb2e8f9f7 1031 case kSDHC_DmaModeAdma1:
<> 144:ef7eb2e8f9f7 1032 startAddress = data;
<> 144:ef7eb2e8f9f7 1033 /* Check if ADMA descriptor's number is enough. */
<> 144:ef7eb2e8f9f7 1034 entries = ((dataBytes / SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U);
<> 144:ef7eb2e8f9f7 1035 /* ADMA1 needs two descriptors to finish a transfer */
<> 144:ef7eb2e8f9f7 1036 entries <<= 1U;
<> 144:ef7eb2e8f9f7 1037 if (entries > ((tableWords * sizeof(uint32_t)) / sizeof(sdhc_adma1_descriptor_t)))
<> 144:ef7eb2e8f9f7 1038 {
<> 144:ef7eb2e8f9f7 1039 error = kStatus_OutOfRange;
<> 144:ef7eb2e8f9f7 1040 }
<> 144:ef7eb2e8f9f7 1041 else
<> 144:ef7eb2e8f9f7 1042 {
<> 144:ef7eb2e8f9f7 1043 adma1EntryAddress = (sdhc_adma1_descriptor_t *)(table);
<> 144:ef7eb2e8f9f7 1044 for (i = 0U; i < entries; i += 2U)
<> 144:ef7eb2e8f9f7 1045 {
<> 144:ef7eb2e8f9f7 1046 /* Each descriptor for ADMA1 is 32-bit in length */
<> 144:ef7eb2e8f9f7 1047 if ((dataBytes - sizeof(uint32_t) * (startAddress - data)) <=
<> 144:ef7eb2e8f9f7 1048 SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY)
<> 144:ef7eb2e8f9f7 1049 {
<> 144:ef7eb2e8f9f7 1050 /* The last piece of data, setting end flag in descriptor */
<> 144:ef7eb2e8f9f7 1051 adma1EntryAddress[i] = ((uint32_t)(dataBytes - sizeof(uint32_t) * (startAddress - data))
<> 144:ef7eb2e8f9f7 1052 << SDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT);
<> 144:ef7eb2e8f9f7 1053 adma1EntryAddress[i] |= kSDHC_Adma1DescriptorTypeSetLength;
<> 144:ef7eb2e8f9f7 1054 adma1EntryAddress[i + 1U] =
<> 144:ef7eb2e8f9f7 1055 ((uint32_t)(startAddress) << SDHC_ADMA1_DESCRIPTOR_ADDRESS_SHIFT);
<> 144:ef7eb2e8f9f7 1056 adma1EntryAddress[i + 1U] |=
<> 144:ef7eb2e8f9f7 1057 (SDHC_ADMA1_DESCRIPTOR_TYPE_TRANSFER | SDHC_ADMA1_DESCRIPTOR_END_MASK);
<> 144:ef7eb2e8f9f7 1058 }
<> 144:ef7eb2e8f9f7 1059 else
<> 144:ef7eb2e8f9f7 1060 {
<> 144:ef7eb2e8f9f7 1061 adma1EntryAddress[i] = ((uint32_t)SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY
<> 144:ef7eb2e8f9f7 1062 << SDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT);
<> 144:ef7eb2e8f9f7 1063 adma1EntryAddress[i] |= kSDHC_Adma1DescriptorTypeSetLength;
<> 144:ef7eb2e8f9f7 1064 adma1EntryAddress[i + 1U] =
<> 144:ef7eb2e8f9f7 1065 ((uint32_t)(startAddress) << SDHC_ADMA1_DESCRIPTOR_ADDRESS_SHIFT);
<> 144:ef7eb2e8f9f7 1066 adma1EntryAddress[i + 1U] |= kSDHC_Adma1DescriptorTypeTransfer;
<> 144:ef7eb2e8f9f7 1067 startAddress += SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY / sizeof(uint32_t);
<> 144:ef7eb2e8f9f7 1068 }
<> 144:ef7eb2e8f9f7 1069 }
<> 144:ef7eb2e8f9f7 1070
<> 144:ef7eb2e8f9f7 1071 /* When use ADMA, disable simple DMA */
<> 144:ef7eb2e8f9f7 1072 base->DSADDR = 0U;
<> 144:ef7eb2e8f9f7 1073 base->ADSADDR = (uint32_t)table;
<> 144:ef7eb2e8f9f7 1074 }
<> 144:ef7eb2e8f9f7 1075 break;
<> 144:ef7eb2e8f9f7 1076 #endif /* FSL_SDHC_ENABLE_ADMA1 */
<> 144:ef7eb2e8f9f7 1077 case kSDHC_DmaModeAdma2:
<> 144:ef7eb2e8f9f7 1078 startAddress = data;
<> 144:ef7eb2e8f9f7 1079 /* Check if ADMA descriptor's number is enough. */
<> 144:ef7eb2e8f9f7 1080 entries = ((dataBytes / SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U);
<> 144:ef7eb2e8f9f7 1081 if (entries > ((tableWords * sizeof(uint32_t)) / sizeof(sdhc_adma2_descriptor_t)))
<> 144:ef7eb2e8f9f7 1082 {
<> 144:ef7eb2e8f9f7 1083 error = kStatus_OutOfRange;
<> 144:ef7eb2e8f9f7 1084 }
<> 144:ef7eb2e8f9f7 1085 else
<> 144:ef7eb2e8f9f7 1086 {
<> 144:ef7eb2e8f9f7 1087 adma2EntryAddress = (sdhc_adma2_descriptor_t *)(table);
<> 144:ef7eb2e8f9f7 1088 for (i = 0U; i < entries; i++)
<> 144:ef7eb2e8f9f7 1089 {
<> 144:ef7eb2e8f9f7 1090 /* Each descriptor for ADMA2 is 64-bit in length */
<> 144:ef7eb2e8f9f7 1091 if ((dataBytes - sizeof(uint32_t) * (startAddress - data)) <=
<> 144:ef7eb2e8f9f7 1092 SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY)
<> 144:ef7eb2e8f9f7 1093 {
<> 144:ef7eb2e8f9f7 1094 /* The last piece of data, setting end flag in descriptor */
<> 144:ef7eb2e8f9f7 1095 adma2EntryAddress[i].address = startAddress;
<> 144:ef7eb2e8f9f7 1096 adma2EntryAddress[i].attribute = ((dataBytes - sizeof(uint32_t) * (startAddress - data))
<> 144:ef7eb2e8f9f7 1097 << SDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT);
<> 144:ef7eb2e8f9f7 1098 adma2EntryAddress[i].attribute |=
<> 144:ef7eb2e8f9f7 1099 (kSDHC_Adma2DescriptorTypeTransfer | kSDHC_Adma2DescriptorEndFlag);
<> 144:ef7eb2e8f9f7 1100 }
<> 144:ef7eb2e8f9f7 1101 else
<> 144:ef7eb2e8f9f7 1102 {
<> 144:ef7eb2e8f9f7 1103 adma2EntryAddress[i].address = startAddress;
<> 144:ef7eb2e8f9f7 1104 adma2EntryAddress[i].attribute =
<> 144:ef7eb2e8f9f7 1105 (((SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY / sizeof(uint32_t)) * sizeof(uint32_t))
<> 144:ef7eb2e8f9f7 1106 << SDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT);
<> 144:ef7eb2e8f9f7 1107 adma2EntryAddress[i].attribute |= kSDHC_Adma2DescriptorTypeTransfer;
<> 144:ef7eb2e8f9f7 1108 startAddress += (SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY / sizeof(uint32_t));
<> 144:ef7eb2e8f9f7 1109 }
<> 144:ef7eb2e8f9f7 1110 }
<> 144:ef7eb2e8f9f7 1111
<> 144:ef7eb2e8f9f7 1112 /* When use ADMA, disable simple DMA */
<> 144:ef7eb2e8f9f7 1113 base->DSADDR = 0U;
<> 144:ef7eb2e8f9f7 1114 base->ADSADDR = (uint32_t)table;
<> 144:ef7eb2e8f9f7 1115 }
<> 144:ef7eb2e8f9f7 1116 break;
<> 144:ef7eb2e8f9f7 1117 default:
<> 144:ef7eb2e8f9f7 1118 break;
<> 144:ef7eb2e8f9f7 1119 }
<> 144:ef7eb2e8f9f7 1120 }
<> 144:ef7eb2e8f9f7 1121
<> 144:ef7eb2e8f9f7 1122 return error;
<> 144:ef7eb2e8f9f7 1123 }
<> 144:ef7eb2e8f9f7 1124
<> 144:ef7eb2e8f9f7 1125 status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer)
<> 144:ef7eb2e8f9f7 1126 {
<> 144:ef7eb2e8f9f7 1127 assert(transfer);
<> 144:ef7eb2e8f9f7 1128 assert(transfer->command); /* Command must not be NULL, data can be NULL. */
<> 144:ef7eb2e8f9f7 1129
<> 144:ef7eb2e8f9f7 1130 status_t error = kStatus_Success;
<> 144:ef7eb2e8f9f7 1131 sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT);
<> 144:ef7eb2e8f9f7 1132 sdhc_command_t *command = transfer->command;
<> 144:ef7eb2e8f9f7 1133 sdhc_data_t *data = transfer->data;
<> 144:ef7eb2e8f9f7 1134
<> 144:ef7eb2e8f9f7 1135 /* DATA-PORT is 32-bit align, ADMA2 4 bytes align, ADMA1 is 4096 bytes align */
<> 144:ef7eb2e8f9f7 1136 if ((!command) || (data && (data->blockSize % 4U)))
<> 144:ef7eb2e8f9f7 1137 {
<> 144:ef7eb2e8f9f7 1138 error = kStatus_InvalidArgument;
<> 144:ef7eb2e8f9f7 1139 }
<> 144:ef7eb2e8f9f7 1140 else
<> 144:ef7eb2e8f9f7 1141 {
<> 144:ef7eb2e8f9f7 1142 /* Wait until command/data bus out of busy status. */
<> 144:ef7eb2e8f9f7 1143 while (SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag)
<> 144:ef7eb2e8f9f7 1144 {
<> 144:ef7eb2e8f9f7 1145 }
<> 144:ef7eb2e8f9f7 1146 while (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag))
<> 144:ef7eb2e8f9f7 1147 {
<> 144:ef7eb2e8f9f7 1148 }
<> 144:ef7eb2e8f9f7 1149
<> 144:ef7eb2e8f9f7 1150 /* Update ADMA descriptor table if data isn't NULL. */
<> 144:ef7eb2e8f9f7 1151 if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords,
<> 144:ef7eb2e8f9f7 1152 (data->rxData ? data->rxData : data->txData),
<> 144:ef7eb2e8f9f7 1153 (data->blockCount * data->blockSize))))
<> 144:ef7eb2e8f9f7 1154 {
<> 144:ef7eb2e8f9f7 1155 error = kStatus_SDHC_PrepareAdmaDescriptorFailed;
<> 144:ef7eb2e8f9f7 1156 }
<> 144:ef7eb2e8f9f7 1157 else
<> 144:ef7eb2e8f9f7 1158 {
<> 144:ef7eb2e8f9f7 1159 SDHC_StartTransfer(base, command, data);
<> 144:ef7eb2e8f9f7 1160
<> 144:ef7eb2e8f9f7 1161 /* Send command and receive data. */
<> 144:ef7eb2e8f9f7 1162 if (kStatus_Success != SDHC_SendCommandBlocking(base, command))
<> 144:ef7eb2e8f9f7 1163 {
<> 144:ef7eb2e8f9f7 1164 error = kStatus_SDHC_SendCommandFailed;
<> 144:ef7eb2e8f9f7 1165 }
<> 144:ef7eb2e8f9f7 1166 else if (data && (kStatus_Success != SDHC_TransferDataBlocking(dmaMode, base, data)))
<> 144:ef7eb2e8f9f7 1167 {
<> 144:ef7eb2e8f9f7 1168 error = kStatus_SDHC_TransferDataFailed;
<> 144:ef7eb2e8f9f7 1169 }
<> 144:ef7eb2e8f9f7 1170 else
<> 144:ef7eb2e8f9f7 1171 {
<> 144:ef7eb2e8f9f7 1172 }
<> 144:ef7eb2e8f9f7 1173 }
<> 144:ef7eb2e8f9f7 1174 }
<> 144:ef7eb2e8f9f7 1175
<> 144:ef7eb2e8f9f7 1176 return error;
<> 144:ef7eb2e8f9f7 1177 }
<> 144:ef7eb2e8f9f7 1178
<> 144:ef7eb2e8f9f7 1179 void SDHC_TransferCreateHandle(SDHC_Type *base,
<> 144:ef7eb2e8f9f7 1180 sdhc_handle_t *handle,
<> 144:ef7eb2e8f9f7 1181 const sdhc_transfer_callback_t *callback,
<> 144:ef7eb2e8f9f7 1182 void *userData)
<> 144:ef7eb2e8f9f7 1183 {
<> 144:ef7eb2e8f9f7 1184 assert(handle);
<> 144:ef7eb2e8f9f7 1185 assert(callback);
<> 144:ef7eb2e8f9f7 1186
<> 144:ef7eb2e8f9f7 1187 /* Zero the handle. */
<> 144:ef7eb2e8f9f7 1188 memset(handle, 0, sizeof(*handle));
<> 144:ef7eb2e8f9f7 1189
<> 144:ef7eb2e8f9f7 1190 /* Set the callback. */
<> 144:ef7eb2e8f9f7 1191 handle->callback.CardInserted = callback->CardInserted;
<> 144:ef7eb2e8f9f7 1192 handle->callback.CardRemoved = callback->CardRemoved;
<> 144:ef7eb2e8f9f7 1193 handle->callback.SdioInterrupt = callback->SdioInterrupt;
<> 144:ef7eb2e8f9f7 1194 handle->callback.SdioBlockGap = callback->SdioBlockGap;
<> 144:ef7eb2e8f9f7 1195 handle->callback.TransferComplete = callback->TransferComplete;
<> 144:ef7eb2e8f9f7 1196 handle->userData = userData;
<> 144:ef7eb2e8f9f7 1197
<> 144:ef7eb2e8f9f7 1198 /* Save the handle in global variables to support the double weak mechanism. */
<> 144:ef7eb2e8f9f7 1199 s_sdhcHandle[SDHC_GetInstance(base)] = handle;
<> 144:ef7eb2e8f9f7 1200
<> 144:ef7eb2e8f9f7 1201 /* Enable interrupt in NVIC. */
<> 144:ef7eb2e8f9f7 1202 SDHC_SetTransferInterrupt(base, true);
<> 144:ef7eb2e8f9f7 1203 EnableIRQ(s_sdhcIRQ[SDHC_GetInstance(base)]);
<> 144:ef7eb2e8f9f7 1204 }
<> 144:ef7eb2e8f9f7 1205
<> 144:ef7eb2e8f9f7 1206 status_t SDHC_TransferNonBlocking(
<> 144:ef7eb2e8f9f7 1207 SDHC_Type *base, sdhc_handle_t *handle, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer)
<> 144:ef7eb2e8f9f7 1208 {
<> 144:ef7eb2e8f9f7 1209 assert(transfer);
<> 144:ef7eb2e8f9f7 1210
<> 144:ef7eb2e8f9f7 1211 sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT);
<> 144:ef7eb2e8f9f7 1212 status_t error = kStatus_Success;
<> 144:ef7eb2e8f9f7 1213 sdhc_command_t *command = transfer->command;
<> 144:ef7eb2e8f9f7 1214 sdhc_data_t *data = transfer->data;
<> 144:ef7eb2e8f9f7 1215
<> 144:ef7eb2e8f9f7 1216 /* DATA-PORT is 32-bit align, ADMA2 4 bytes align, ADMA1 is 4096 bytes align */
<> 144:ef7eb2e8f9f7 1217 if ((!(transfer->command)) || ((transfer->data) && (transfer->data->blockSize % 4U)))
<> 144:ef7eb2e8f9f7 1218 {
<> 144:ef7eb2e8f9f7 1219 error = kStatus_InvalidArgument;
<> 144:ef7eb2e8f9f7 1220 }
<> 144:ef7eb2e8f9f7 1221 else
<> 144:ef7eb2e8f9f7 1222 {
<> 144:ef7eb2e8f9f7 1223 /* Wait until command/data bus out of busy status. */
<> 144:ef7eb2e8f9f7 1224 if ((SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) ||
<> 144:ef7eb2e8f9f7 1225 (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag)))
<> 144:ef7eb2e8f9f7 1226 {
<> 144:ef7eb2e8f9f7 1227 error = kStatus_SDHC_BusyTransferring;
<> 144:ef7eb2e8f9f7 1228 }
<> 144:ef7eb2e8f9f7 1229 else
<> 144:ef7eb2e8f9f7 1230 {
<> 144:ef7eb2e8f9f7 1231 /* Update ADMA descriptor table and reset transferred words if data isn't NULL. */
<> 144:ef7eb2e8f9f7 1232 if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords,
<> 144:ef7eb2e8f9f7 1233 (data->rxData ? data->rxData : data->txData),
<> 144:ef7eb2e8f9f7 1234 (data->blockCount * data->blockSize))))
<> 144:ef7eb2e8f9f7 1235 {
<> 144:ef7eb2e8f9f7 1236 error = kStatus_SDHC_PrepareAdmaDescriptorFailed;
<> 144:ef7eb2e8f9f7 1237 }
<> 144:ef7eb2e8f9f7 1238 else
<> 144:ef7eb2e8f9f7 1239 {
<> 144:ef7eb2e8f9f7 1240 /* Save command and data into handle before transferring. */
<> 144:ef7eb2e8f9f7 1241 handle->command = command;
<> 144:ef7eb2e8f9f7 1242 handle->data = data;
<> 144:ef7eb2e8f9f7 1243 handle->interruptFlags = 0U;
<> 144:ef7eb2e8f9f7 1244 /* transferredWords will only be updated in ISR when transfer way is DATAPORT. */
<> 144:ef7eb2e8f9f7 1245 handle->transferredWords = 0U;
<> 144:ef7eb2e8f9f7 1246 SDHC_StartTransfer(base, command, data);
<> 144:ef7eb2e8f9f7 1247 }
<> 144:ef7eb2e8f9f7 1248 }
<> 144:ef7eb2e8f9f7 1249 }
<> 144:ef7eb2e8f9f7 1250
<> 144:ef7eb2e8f9f7 1251 return error;
<> 144:ef7eb2e8f9f7 1252 }
<> 144:ef7eb2e8f9f7 1253
<> 144:ef7eb2e8f9f7 1254 void SDHC_TransferHandleIRQ(SDHC_Type *base, sdhc_handle_t *handle)
<> 144:ef7eb2e8f9f7 1255 {
<> 144:ef7eb2e8f9f7 1256 assert(handle);
<> 144:ef7eb2e8f9f7 1257
<> 144:ef7eb2e8f9f7 1258 uint32_t interruptFlags;
<> 144:ef7eb2e8f9f7 1259
<> 144:ef7eb2e8f9f7 1260 interruptFlags = SDHC_GetInterruptStatusFlags(base);
<> 144:ef7eb2e8f9f7 1261 handle->interruptFlags = interruptFlags;
<> 144:ef7eb2e8f9f7 1262
<> 144:ef7eb2e8f9f7 1263 if (interruptFlags & kSDHC_CardDetectFlag)
<> 144:ef7eb2e8f9f7 1264 {
<> 144:ef7eb2e8f9f7 1265 SDHC_TransferHandleCardDetect(handle, (interruptFlags & kSDHC_CardDetectFlag));
<> 144:ef7eb2e8f9f7 1266 }
<> 144:ef7eb2e8f9f7 1267 if (interruptFlags & kSDHC_CommandFlag)
<> 144:ef7eb2e8f9f7 1268 {
<> 144:ef7eb2e8f9f7 1269 SDHC_TransferHandleCommand(base, handle, (interruptFlags & kSDHC_CommandFlag));
<> 144:ef7eb2e8f9f7 1270 }
<> 144:ef7eb2e8f9f7 1271 if (interruptFlags & kSDHC_DataFlag)
<> 144:ef7eb2e8f9f7 1272 {
<> 144:ef7eb2e8f9f7 1273 SDHC_TransferHandleData(base, handle, (interruptFlags & kSDHC_DataFlag));
<> 144:ef7eb2e8f9f7 1274 }
<> 144:ef7eb2e8f9f7 1275 if (interruptFlags & kSDHC_CardInterruptFlag)
<> 144:ef7eb2e8f9f7 1276 {
<> 144:ef7eb2e8f9f7 1277 SDHC_TransferHandleSdioInterrupt(handle);
<> 144:ef7eb2e8f9f7 1278 }
<> 144:ef7eb2e8f9f7 1279 if (interruptFlags & kSDHC_BlockGapEventFlag)
<> 144:ef7eb2e8f9f7 1280 {
<> 144:ef7eb2e8f9f7 1281 SDHC_TransferHandleSdioBlockGap(handle);
<> 144:ef7eb2e8f9f7 1282 }
<> 144:ef7eb2e8f9f7 1283
<> 144:ef7eb2e8f9f7 1284 SDHC_ClearInterruptStatusFlags(base, interruptFlags);
<> 144:ef7eb2e8f9f7 1285 }
<> 144:ef7eb2e8f9f7 1286
<> 144:ef7eb2e8f9f7 1287 #if defined(SDHC)
<> 144:ef7eb2e8f9f7 1288 void SDHC_DriverIRQHandler(void)
<> 144:ef7eb2e8f9f7 1289 {
<> 144:ef7eb2e8f9f7 1290 assert(s_sdhcHandle[0]);
<> 144:ef7eb2e8f9f7 1291
<> 144:ef7eb2e8f9f7 1292 SDHC_TransferHandleIRQ(SDHC, s_sdhcHandle[0]);
<> 144:ef7eb2e8f9f7 1293 }
<> 144:ef7eb2e8f9f7 1294 #endif