added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Committer:
JojoS
Date:
Sat Sep 10 15:32:04 2016 +0000
Revision:
147:ba84b7dc41a7
Parent:
144:ef7eb2e8f9f7
added prescaler for 16 bit timers (solution as in LPC11xx), default prescaler 31 for max 28 ms period time

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