1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 #ifndef _FSL_SDHC_H_
9 #define _FSL_SDHC_H_
10 
11 #include "fsl_common.h"
12 
13 /*!
14  * @addtogroup sdhc
15  * @{
16  */
17 
18 /******************************************************************************
19  * Definitions.
20  *****************************************************************************/
21 
22 /*! @name Driver version */
23 /*@{*/
24 /*! @brief Driver version 2.1.13. */
25 #define FSL_SDHC_DRIVER_VERSION (MAKE_VERSION(2U, 1U, 13U))
26 /*@}*/
27 
28 /*! @brief Maximum block count can be set one time */
29 #define SDHC_MAX_BLOCK_COUNT (SDHC_BLKATTR_BLKCNT_MASK >> SDHC_BLKATTR_BLKCNT_SHIFT)
30 
31 /*! @brief _sdhc_status SDHC status */
32 enum
33 {
34     kStatus_SDHC_BusyTransferring            = MAKE_STATUS(kStatusGroup_SDHC, 0U), /*!< Transfer is on-going */
35     kStatus_SDHC_PrepareAdmaDescriptorFailed = MAKE_STATUS(kStatusGroup_SDHC, 1U), /*!< Set DMA descriptor failed */
36     kStatus_SDHC_SendCommandFailed           = MAKE_STATUS(kStatusGroup_SDHC, 2U), /*!< Send command failed */
37     kStatus_SDHC_TransferDataFailed          = MAKE_STATUS(kStatusGroup_SDHC, 3U), /*!< Transfer data failed */
38     kStatus_SDHC_DMADataBufferAddrNotAlign =
39         MAKE_STATUS(kStatusGroup_SDHC, 4U), /*!< data buffer addr not align in DMA mode */
40     kStatus_SDHC_TransferCommandComplete = MAKE_STATUS(kStatusGroup_SDHC, 5U), /*!< command transfer complete */
41     kStatus_SDHC_TransferDataComplete    = MAKE_STATUS(kStatusGroup_SDHC, 6U), /*!< data transfer complete */
42 };
43 
44 /*! @brief _sdhc_capability_flag Host controller capabilities flag mask */
45 enum
46 {
47     kSDHC_SupportAdmaFlag          = SDHC_HTCAPBLT_ADMAS_MASK, /*!< Support ADMA */
48     kSDHC_SupportHighSpeedFlag     = SDHC_HTCAPBLT_HSS_MASK,   /*!< Support high-speed */
49     kSDHC_SupportDmaFlag           = SDHC_HTCAPBLT_DMAS_MASK,  /*!< Support DMA */
50     kSDHC_SupportSuspendResumeFlag = SDHC_HTCAPBLT_SRS_MASK,   /*!< Support suspend/resume */
51     kSDHC_SupportV330Flag          = SDHC_HTCAPBLT_VS33_MASK,  /*!< Support voltage 3.3V */
52 #if defined FSL_FEATURE_SDHC_HAS_V300_SUPPORT && FSL_FEATURE_SDHC_HAS_V300_SUPPORT
53     kSDHC_SupportV300Flag = SDHC_HTCAPBLT_VS30_MASK, /*!< Support voltage 3.0V */
54 #endif
55 #if defined FSL_FEATURE_SDHC_HAS_V180_SUPPORT && FSL_FEATURE_SDHC_HAS_V180_SUPPORT
56     kSDHC_SupportV180Flag = SDHC_HTCAPBLT_VS18_MASK, /*!< Support voltage 1.8V */
57 #endif
58     /* Put additional two flags in HTCAPBLT_MBL's position. */
59     kSDHC_Support4BitFlag = (SDHC_HTCAPBLT_MBL_SHIFT << 0U), /*!< Support 4 bit mode */
60     kSDHC_Support8BitFlag = (SDHC_HTCAPBLT_MBL_SHIFT << 1U), /*!< Support 8 bit mode */
61 };
62 
63 /*! @brief _sdhc_wakeup_event Wakeup event mask */
64 enum
65 {
66     kSDHC_WakeupEventOnCardInt    = SDHC_PROCTL_WECINT_MASK, /*!< Wakeup on card interrupt */
67     kSDHC_WakeupEventOnCardInsert = SDHC_PROCTL_WECINS_MASK, /*!< Wakeup on card insertion */
68     kSDHC_WakeupEventOnCardRemove = SDHC_PROCTL_WECRM_MASK,  /*!< Wakeup on card removal */
69 
70     kSDHC_WakeupEventsAll = (kSDHC_WakeupEventOnCardInt | kSDHC_WakeupEventOnCardInsert |
71                              kSDHC_WakeupEventOnCardRemove), /*!< All wakeup events */
72 };
73 
74 /*! @brief _sdhc_reset Reset type mask */
75 enum
76 {
77     kSDHC_ResetAll     = SDHC_SYSCTL_RSTA_MASK, /*!< Reset all except card detection */
78     kSDHC_ResetCommand = SDHC_SYSCTL_RSTC_MASK, /*!< Reset command line */
79     kSDHC_ResetData    = SDHC_SYSCTL_RSTD_MASK, /*!< Reset data line */
80 
81     kSDHC_ResetsAll = (kSDHC_ResetAll | kSDHC_ResetCommand | kSDHC_ResetData), /*!< All reset types */
82 };
83 
84 /*! @brief _sdhc_transfer_flag Transfer flag mask */
85 enum
86 {
87     kSDHC_EnableDmaFlag = SDHC_XFERTYP_DMAEN_MASK, /*!< Enable DMA */
88 
89     kSDHC_CommandTypeSuspendFlag = (SDHC_XFERTYP_CMDTYP(1U)), /*!< Suspend command */
90     kSDHC_CommandTypeResumeFlag  = (SDHC_XFERTYP_CMDTYP(2U)), /*!< Resume command */
91     kSDHC_CommandTypeAbortFlag   = (SDHC_XFERTYP_CMDTYP(3U)), /*!< Abort command */
92 
93     kSDHC_EnableBlockCountFlag    = SDHC_XFERTYP_BCEN_MASK,   /*!< Enable block count */
94     kSDHC_EnableAutoCommand12Flag = SDHC_XFERTYP_AC12EN_MASK, /*!< Enable auto CMD12 */
95     kSDHC_DataReadFlag            = SDHC_XFERTYP_DTDSEL_MASK, /*!< Enable data read */
96     kSDHC_MultipleBlockFlag       = SDHC_XFERTYP_MSBSEL_MASK, /*!< Multiple block data read/write */
97 
98     kSDHC_ResponseLength136Flag    = SDHC_XFERTYP_RSPTYP(1U), /*!< 136 bit response length */
99     kSDHC_ResponseLength48Flag     = SDHC_XFERTYP_RSPTYP(2U), /*!< 48 bit response length */
100     kSDHC_ResponseLength48BusyFlag = SDHC_XFERTYP_RSPTYP(3U), /*!< 48 bit response length with busy status */
101 
102     kSDHC_EnableCrcCheckFlag   = SDHC_XFERTYP_CCCEN_MASK, /*!< Enable CRC check */
103     kSDHC_EnableIndexCheckFlag = SDHC_XFERTYP_CICEN_MASK, /*!< Enable index check */
104     kSDHC_DataPresentFlag      = SDHC_XFERTYP_DPSEL_MASK, /*!< Data present flag */
105 };
106 
107 /*! @brief _sdhc_present_status_flag Present status flag mask */
108 enum
109 {
110     kSDHC_CommandInhibitFlag      = SDHC_PRSSTAT_CIHB_MASK,  /*!< Command inhibit */
111     kSDHC_DataInhibitFlag         = SDHC_PRSSTAT_CDIHB_MASK, /*!< Data inhibit */
112     kSDHC_DataLineActiveFlag      = SDHC_PRSSTAT_DLA_MASK,   /*!< Data line active */
113     kSDHC_SdClockStableFlag       = SDHC_PRSSTAT_SDSTB_MASK, /*!< SD bus clock stable */
114     kSDHC_WriteTransferActiveFlag = SDHC_PRSSTAT_WTA_MASK,   /*!< Write transfer active */
115     kSDHC_ReadTransferActiveFlag  = SDHC_PRSSTAT_RTA_MASK,   /*!< Read transfer active */
116     kSDHC_BufferWriteEnableFlag   = SDHC_PRSSTAT_BWEN_MASK,  /*!< Buffer write enable */
117     kSDHC_BufferReadEnableFlag    = SDHC_PRSSTAT_BREN_MASK,  /*!< Buffer read enable */
118     kSDHC_CardInsertedFlag        = SDHC_PRSSTAT_CINS_MASK,  /*!< Card inserted */
119     kSDHC_CommandLineLevelFlag    = SDHC_PRSSTAT_CLSL_MASK,  /*!< Command line signal level */
120 
121     kSDHC_Data0LineLevelFlag = (1U << 24U),      /*!< Data0 line signal level */
122     kSDHC_Data1LineLevelFlag = (1U << 25U),      /*!< Data1 line signal level */
123     kSDHC_Data2LineLevelFlag = (1U << 26U),      /*!< Data2 line signal level */
124     kSDHC_Data3LineLevelFlag = (1U << 27U),      /*!< Data3 line signal level */
125     kSDHC_Data4LineLevelFlag = (1U << 28U),      /*!< Data4 line signal level */
126     kSDHC_Data5LineLevelFlag = (1U << 29U),      /*!< Data5 line signal level */
127     kSDHC_Data6LineLevelFlag = (1U << 30U),      /*!< Data6 line signal level */
128     kSDHC_Data7LineLevelFlag = (int)(1U << 31U), /*!< Data7 line signal level */
129 };
130 
131 /*! @brief _sdhc_interrupt_status_flag Interrupt status flag mask */
132 enum
133 {
134     kSDHC_CommandCompleteFlag    = SDHC_IRQSTAT_CC_MASK,    /*!< Command complete */
135     kSDHC_DataCompleteFlag       = SDHC_IRQSTAT_TC_MASK,    /*!< Data complete */
136     kSDHC_BlockGapEventFlag      = SDHC_IRQSTAT_BGE_MASK,   /*!< Block gap event */
137     kSDHC_DmaCompleteFlag        = SDHC_IRQSTAT_DINT_MASK,  /*!< DMA interrupt */
138     kSDHC_BufferWriteReadyFlag   = SDHC_IRQSTAT_BWR_MASK,   /*!< Buffer write ready */
139     kSDHC_BufferReadReadyFlag    = SDHC_IRQSTAT_BRR_MASK,   /*!< Buffer read ready */
140     kSDHC_CardInsertionFlag      = SDHC_IRQSTAT_CINS_MASK,  /*!< Card inserted */
141     kSDHC_CardRemovalFlag        = SDHC_IRQSTAT_CRM_MASK,   /*!< Card removed */
142     kSDHC_CardInterruptFlag      = SDHC_IRQSTAT_CINT_MASK,  /*!< Card interrupt */
143     kSDHC_CommandTimeoutFlag     = SDHC_IRQSTAT_CTOE_MASK,  /*!< Command timeout error */
144     kSDHC_CommandCrcErrorFlag    = SDHC_IRQSTAT_CCE_MASK,   /*!< Command CRC error */
145     kSDHC_CommandEndBitErrorFlag = SDHC_IRQSTAT_CEBE_MASK,  /*!< Command end bit error */
146     kSDHC_CommandIndexErrorFlag  = SDHC_IRQSTAT_CIE_MASK,   /*!< Command index error */
147     kSDHC_DataTimeoutFlag        = SDHC_IRQSTAT_DTOE_MASK,  /*!< Data timeout error */
148     kSDHC_DataCrcErrorFlag       = SDHC_IRQSTAT_DCE_MASK,   /*!< Data CRC error */
149     kSDHC_DataEndBitErrorFlag    = SDHC_IRQSTAT_DEBE_MASK,  /*!< Data end bit error */
150     kSDHC_AutoCommand12ErrorFlag = SDHC_IRQSTAT_AC12E_MASK, /*!< Auto CMD12 error */
151     kSDHC_DmaErrorFlag           = SDHC_IRQSTAT_DMAE_MASK,  /*!< DMA error */
152 
153     kSDHC_CommandErrorFlag = (kSDHC_CommandTimeoutFlag | kSDHC_CommandCrcErrorFlag | kSDHC_CommandEndBitErrorFlag |
154                               kSDHC_CommandIndexErrorFlag), /*!< Command error */
155     kSDHC_DataErrorFlag    = (kSDHC_DataTimeoutFlag | kSDHC_DataCrcErrorFlag | kSDHC_DataEndBitErrorFlag |
156                            kSDHC_AutoCommand12ErrorFlag),                                      /*!< Data error */
157     kSDHC_ErrorFlag        = (kSDHC_CommandErrorFlag | kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag), /*!< All error */
158     kSDHC_DataFlag         = (kSDHC_DataCompleteFlag | kSDHC_BufferWriteReadyFlag | kSDHC_BufferReadReadyFlag |
159                       kSDHC_DataErrorFlag),                                             /*!< Data interrupts */
160     kSDHC_DataDMAFlag    = (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag), /*!< Data interrupts */
161     kSDHC_CommandFlag    = (kSDHC_CommandErrorFlag | kSDHC_CommandCompleteFlag), /*!< Command interrupts */
162     kSDHC_CardDetectFlag = (kSDHC_CardInsertionFlag | kSDHC_CardRemovalFlag),    /*!< Card detection interrupts */
163 
164     kSDHC_AllInterruptFlags = (kSDHC_BlockGapEventFlag | kSDHC_CardInterruptFlag | kSDHC_CommandFlag | kSDHC_DataFlag |
165                                kSDHC_ErrorFlag), /*!< All flags mask */
166 };
167 
168 /*! @brief _sdhc_auto_command12_error_status_flag Auto CMD12 error status flag mask */
169 enum
170 {
171     kSDHC_AutoCommand12NotExecutedFlag = SDHC_AC12ERR_AC12NE_MASK,    /*!< Not executed error */
172     kSDHC_AutoCommand12TimeoutFlag     = SDHC_AC12ERR_AC12TOE_MASK,   /*!< Timeout error */
173     kSDHC_AutoCommand12EndBitErrorFlag = SDHC_AC12ERR_AC12EBE_MASK,   /*!< End bit error */
174     kSDHC_AutoCommand12CrcErrorFlag    = SDHC_AC12ERR_AC12CE_MASK,    /*!< CRC error */
175     kSDHC_AutoCommand12IndexErrorFlag  = SDHC_AC12ERR_AC12IE_MASK,    /*!< Index error */
176     kSDHC_AutoCommand12NotIssuedFlag   = SDHC_AC12ERR_CNIBAC12E_MASK, /*!< Not issued error */
177 };
178 
179 /*! @brief _sdhc_adma_error_status_flag ADMA error status flag mask */
180 enum
181 {
182     kSDHC_AdmaLenghMismatchFlag   = SDHC_ADMAES_ADMALME_MASK, /*!< Length mismatch error */
183     kSDHC_AdmaDescriptorErrorFlag = SDHC_ADMAES_ADMADCE_MASK, /*!< Descriptor error */
184 };
185 
186 /*!
187  * @brief ADMA error state
188  *
189  * This state is the detail state when ADMA error has occurred.
190  */
191 typedef enum _sdhc_adma_error_state
192 {
193     kSDHC_AdmaErrorStateStopDma         = 0x00U, /*!< Stop DMA */
194     kSDHC_AdmaErrorStateFetchDescriptor = 0x01U, /*!< Fetch descriptor */
195     kSDHC_AdmaErrorStateChangeAddress   = 0x02U, /*!< Change address */
196     kSDHC_AdmaErrorStateTransferData    = 0x03U, /*!< Transfer data */
197 } sdhc_adma_error_state_t;
198 
199 /*! @brief _sdhc_force_event Force event bit position */
200 enum
201 {
202     kSDHC_ForceEventAutoCommand12NotExecuted = SDHC_FEVT_AC12NE_MASK,    /*!< Auto CMD12 not executed error */
203     kSDHC_ForceEventAutoCommand12Timeout     = SDHC_FEVT_AC12TOE_MASK,   /*!< Auto CMD12 timeout error */
204     kSDHC_ForceEventAutoCommand12CrcError    = SDHC_FEVT_AC12CE_MASK,    /*!< Auto CMD12 CRC error */
205     kSDHC_ForceEventEndBitError              = SDHC_FEVT_AC12EBE_MASK,   /*!< Auto CMD12 end bit error */
206     kSDHC_ForceEventAutoCommand12IndexError  = SDHC_FEVT_AC12IE_MASK,    /*!< Auto CMD12 index error */
207     kSDHC_ForceEventAutoCommand12NotIssued   = SDHC_FEVT_CNIBAC12E_MASK, /*!< Auto CMD12 not issued error */
208     kSDHC_ForceEventCommandTimeout           = SDHC_FEVT_CTOE_MASK,      /*!< Command timeout error */
209     kSDHC_ForceEventCommandCrcError          = SDHC_FEVT_CCE_MASK,       /*!< Command CRC error */
210     kSDHC_ForceEventCommandEndBitError       = SDHC_FEVT_CEBE_MASK,      /*!< Command end bit error */
211     kSDHC_ForceEventCommandIndexError        = SDHC_FEVT_CIE_MASK,       /*!< Command index error */
212     kSDHC_ForceEventDataTimeout              = SDHC_FEVT_DTOE_MASK,      /*!< Data timeout error */
213     kSDHC_ForceEventDataCrcError             = SDHC_FEVT_DCE_MASK,       /*!< Data CRC error */
214     kSDHC_ForceEventDataEndBitError          = SDHC_FEVT_DEBE_MASK,      /*!< Data end bit error */
215     kSDHC_ForceEventAutoCommand12Error       = SDHC_FEVT_AC12E_MASK,     /*!< Auto CMD12 error */
216     kSDHC_ForceEventCardInt                  = (int)SDHC_FEVT_CINT_MASK, /*!< Card interrupt */
217     kSDHC_ForceEventDmaError                 = SDHC_FEVT_DMAE_MASK,      /*!< Dma error */
218 
219     kSDHC_ForceEventsAll = (int)(SDHC_FEVT_AC12NE_MASK | SDHC_FEVT_AC12TOE_MASK | SDHC_FEVT_AC12CE_MASK |
220                                  SDHC_FEVT_AC12EBE_MASK | SDHC_FEVT_AC12IE_MASK | SDHC_FEVT_CNIBAC12E_MASK |
221                                  SDHC_FEVT_CTOE_MASK | SDHC_FEVT_CCE_MASK | SDHC_FEVT_CEBE_MASK | SDHC_FEVT_CIE_MASK |
222                                  SDHC_FEVT_DTOE_MASK | SDHC_FEVT_DCE_MASK | SDHC_FEVT_DEBE_MASK | SDHC_FEVT_AC12E_MASK |
223                                  SDHC_FEVT_CINT_MASK | SDHC_FEVT_DMAE_MASK), /*!< All force event flags mask */
224 };
225 
226 /*! @brief Data transfer width */
227 typedef enum _sdhc_data_bus_width
228 {
229     kSDHC_DataBusWidth1Bit = 0U, /*!< 1-bit mode */
230     kSDHC_DataBusWidth4Bit = 1U, /*!< 4-bit mode */
231     kSDHC_DataBusWidth8Bit = 2U, /*!< 8-bit mode */
232 } sdhc_data_bus_width_t;
233 
234 /*! @brief Endian mode */
235 typedef enum _sdhc_endian_mode
236 {
237     kSDHC_EndianModeBig         = 0U, /*!< Big endian mode */
238     kSDHC_EndianModeHalfWordBig = 1U, /*!< Half word big endian mode */
239     kSDHC_EndianModeLittle      = 2U, /*!< Little endian mode */
240 } sdhc_endian_mode_t;
241 
242 /*! @brief DMA mode */
243 typedef enum _sdhc_dma_mode
244 {
245     kSDHC_DmaModeNo    = 0U, /*!< No DMA */
246     kSDHC_DmaModeAdma1 = 1U, /*!< ADMA1 is selected */
247     kSDHC_DmaModeAdma2 = 2U, /*!< ADMA2 is selected */
248 } sdhc_dma_mode_t;
249 
250 /*! @brief _sdhc_sdio_control_flag SDIO control flag mask */
251 enum
252 {
253     kSDHC_StopAtBlockGapFlag       = 0x01, /*!< Stop at block gap */
254     kSDHC_ReadWaitControlFlag      = 0x02, /*!< Read wait control */
255     kSDHC_InterruptAtBlockGapFlag  = 0x04, /*!< Interrupt at block gap */
256     kSDHC_ExactBlockNumberReadFlag = 0x08, /*!< Exact block number read */
257 };
258 
259 /*! @brief MMC card boot mode */
260 typedef enum _sdhc_boot_mode
261 {
262     kSDHC_BootModeNormal      = 0U, /*!< Normal boot */
263     kSDHC_BootModeAlternative = 1U, /*!< Alternative boot */
264 } sdhc_boot_mode_t;
265 
266 /*! @brief The command type */
267 typedef enum _sdhc_card_command_type
268 {
269     kCARD_CommandTypeNormal  = 0U, /*!< Normal command */
270     kCARD_CommandTypeSuspend = 1U, /*!< Suspend command */
271     kCARD_CommandTypeResume  = 2U, /*!< Resume command */
272     kCARD_CommandTypeAbort   = 3U, /*!< Abort command */
273 } sdhc_card_command_type_t;
274 
275 /*!
276  * @brief The command response type.
277  *
278  * Define the command response type from card to host controller.
279  */
280 typedef enum _sdhc_card_response_type
281 {
282     kCARD_ResponseTypeNone = 0U, /*!< Response type: none */
283     kCARD_ResponseTypeR1   = 1U, /*!< Response type: R1 */
284     kCARD_ResponseTypeR1b  = 2U, /*!< Response type: R1b */
285     kCARD_ResponseTypeR2   = 3U, /*!< Response type: R2 */
286     kCARD_ResponseTypeR3   = 4U, /*!< Response type: R3 */
287     kCARD_ResponseTypeR4   = 5U, /*!< Response type: R4 */
288     kCARD_ResponseTypeR5   = 6U, /*!< Response type: R5 */
289     kCARD_ResponseTypeR5b  = 7U, /*!< Response type: R5b */
290     kCARD_ResponseTypeR6   = 8U, /*!< Response type: R6 */
291     kCARD_ResponseTypeR7   = 9U, /*!< Response type: R7 */
292 } sdhc_card_response_type_t;
293 
294 /*! @brief The alignment size for ADDRESS filed in ADMA1's descriptor */
295 #define SDHC_ADMA1_ADDRESS_ALIGN (4096U)
296 /*! @brief The alignment size for LENGTH field in ADMA1's descriptor */
297 #define SDHC_ADMA1_LENGTH_ALIGN (4096U)
298 /*! @brief The alignment size for ADDRESS field in ADMA2's descriptor */
299 #define SDHC_ADMA2_ADDRESS_ALIGN (4U)
300 /*! @brief The alignment size for LENGTH filed in ADMA2's descriptor */
301 #define SDHC_ADMA2_LENGTH_ALIGN (4U)
302 
303 /* ADMA1 descriptor table
304  * |------------------------|---------|--------------------------|
305  * | Address/page field     |Reserved |         Attribute        |
306  * |------------------------|---------|--------------------------|
307  * |31                    12|11      6|05  |04  |03|02 |01 |00   |
308  * |------------------------|---------|----|----|--|---|---|-----|
309  * | address or data length | 000000  |Act2|Act1| 0|Int|End|Valid|
310  * |------------------------|---------|----|----|--|---|---|-----|
311  *
312  *
313  * |------|------|-----------------|-------|-------------|
314  * | Act2 | Act1 |     Comment     | 31-28 | 27 - 12     |
315  * |------|------|-----------------|---------------------|
316  * |   0  |   0  | No op           | Don't care          |
317  * |------|------|-----------------|-------|-------------|
318  * |   0  |   1  | Set data length |  0000 | Data Length |
319  * |------|------|-----------------|-------|-------------|
320  * |   1  |   0  | Transfer data   | Data address        |
321  * |------|------|-----------------|---------------------|
322  * |   1  |   1  | Link descriptor | Descriptor address  |
323  * |------|------|-----------------|---------------------|
324  */
325 /*! @brief The bit shift for ADDRESS filed in ADMA1's descriptor */
326 #define SDHC_ADMA1_DESCRIPTOR_ADDRESS_SHIFT (12U)
327 /*! @brief The bit mask for ADDRESS field in ADMA1's descriptor */
328 #define SDHC_ADMA1_DESCRIPTOR_ADDRESS_MASK (0xFFFFFU)
329 /*! @brief The bit shift for LENGTH filed in ADMA1's descriptor */
330 #define SDHC_ADMA1_DESCRIPTOR_LENGTH_SHIFT (12U)
331 /*! @brief The mask for LENGTH field in ADMA1's descriptor */
332 #define SDHC_ADMA1_DESCRIPTOR_LENGTH_MASK (0xFFFFU)
333 /*! @brief The maximum value of LENGTH filed in ADMA1's descriptor */
334 #define SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY (SDHC_ADMA1_DESCRIPTOR_LENGTH_MASK + 1U - 4096U)
335 
336 /*! @brief _sdhc_adma1_descriptor_flag The mask for the control/status field in ADMA1 descriptor */
337 enum
338 {
339     kSDHC_Adma1DescriptorValidFlag     = (1U << 0U),                       /*!< Valid flag */
340     kSDHC_Adma1DescriptorEndFlag       = (1U << 1U),                       /*!< End flag */
341     kSDHC_Adma1DescriptorInterrupFlag  = (1U << 2U),                       /*!< Interrupt flag */
342     kSDHC_Adma1DescriptorActivity1Flag = (1U << 4U),                       /*!< Activity 1 flag */
343     kSDHC_Adma1DescriptorActivity2Flag = (1U << 5U),                       /*!< Activity 2 flag */
344     kSDHC_Adma1DescriptorTypeNop       = (kSDHC_Adma1DescriptorValidFlag), /*!< No operation */
345     kSDHC_Adma1DescriptorTypeTransfer =
346         (kSDHC_Adma1DescriptorActivity2Flag | kSDHC_Adma1DescriptorValidFlag), /*!< Transfer data */
347     kSDHC_Adma1DescriptorTypeLink = (kSDHC_Adma1DescriptorActivity1Flag | kSDHC_Adma1DescriptorActivity2Flag |
348                                      kSDHC_Adma1DescriptorValidFlag), /*!< Link descriptor */
349     kSDHC_Adma1DescriptorTypeSetLength =
350         (kSDHC_Adma1DescriptorActivity1Flag | kSDHC_Adma1DescriptorValidFlag), /*!< Set data length */
351 };
352 
353 /* ADMA2 descriptor table
354  * |----------------|---------------|-------------|--------------------------|
355  * | Address field  |     Length    | Reserved    |         Attribute        |
356  * |----------------|---------------|-------------|--------------------------|
357  * |63            32|31           16|15         06|05  |04  |03|02 |01 |00   |
358  * |----------------|---------------|-------------|----|----|--|---|---|-----|
359  * | 32-bit address | 16-bit length | 0000000000  |Act2|Act1| 0|Int|End|Valid|
360  * |----------------|---------------|-------------|----|----|--|---|---|-----|
361  *
362  *
363  * | Act2 | Act1 |     Comment     | Operation                                                         |
364  * |------|------|-----------------|-------------------------------------------------------------------|
365  * |   0  |   0  | No op           | Don't care                                                        |
366  * |------|------|-----------------|-------------------------------------------------------------------|
367  * |   0  |   1  | Reserved        | Read this line and go to next one                                 |
368  * |------|------|-----------------|-------------------------------------------------------------------|
369  * |   1  |   0  | Transfer data   | Transfer data with address and length set in this descriptor line |
370  * |------|------|-----------------|-------------------------------------------------------------------|
371  * |   1  |   1  | Link descriptor | Link to another descriptor                                        |
372  * |------|------|-----------------|-------------------------------------------------------------------|
373  */
374 /*! @brief The bit shift for LENGTH field in ADMA2's descriptor */
375 #define SDHC_ADMA2_DESCRIPTOR_LENGTH_SHIFT (16U)
376 /*! @brief The bit mask for LENGTH field in ADMA2's descriptor */
377 #define SDHC_ADMA2_DESCRIPTOR_LENGTH_MASK (0xFFFFUL)
378 /*! @brief The maximum value of LENGTH field in ADMA2's descriptor */
379 #define SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY (SDHC_ADMA2_DESCRIPTOR_LENGTH_MASK)
380 
381 /*! @brief _sdhc_adma2_descriptor_flag ADMA1 descriptor control and status mask */
382 enum
383 {
384     kSDHC_Adma2DescriptorValidFlag     = (1U << 0U), /*!< Valid flag */
385     kSDHC_Adma2DescriptorEndFlag       = (1U << 1U), /*!< End flag */
386     kSDHC_Adma2DescriptorInterruptFlag = (1U << 2U), /*!< Interrupt flag */
387     kSDHC_Adma2DescriptorActivity1Flag = (1U << 4U), /*!< Activity 1 mask */
388     kSDHC_Adma2DescriptorActivity2Flag = (1U << 5U), /*!< Activity 2 mask */
389 
390     kSDHC_Adma2DescriptorTypeNop = (kSDHC_Adma2DescriptorValidFlag), /*!< No operation */
391     kSDHC_Adma2DescriptorTypeReserved =
392         (kSDHC_Adma2DescriptorActivity1Flag | kSDHC_Adma2DescriptorValidFlag), /*!< Reserved */
393     kSDHC_Adma2DescriptorTypeTransfer =
394         (kSDHC_Adma2DescriptorActivity2Flag | kSDHC_Adma2DescriptorValidFlag), /*!< Transfer type */
395     kSDHC_Adma2DescriptorTypeLink = (kSDHC_Adma2DescriptorActivity1Flag | kSDHC_Adma2DescriptorActivity2Flag |
396                                      kSDHC_Adma2DescriptorValidFlag), /*!< Link type */
397 };
398 
399 /*! @brief Defines the adma1 descriptor structure. */
400 typedef uint32_t sdhc_adma1_descriptor_t;
401 
402 /*! @brief Defines the ADMA2 descriptor structure. */
403 typedef struct _sdhc_adma2_descriptor
404 {
405     uint32_t attribute;      /*!< The control and status field */
406     const uint32_t *address; /*!< The address field */
407 } sdhc_adma2_descriptor_t;
408 
409 /*!
410  * @brief SDHC capability information.
411  *
412  * Defines a structure to save the capability information of SDHC.
413  */
414 typedef struct _sdhc_capability
415 {
416     uint32_t specVersion;    /*!< Specification version */
417     uint32_t vendorVersion;  /*!< Vendor version */
418     uint32_t maxBlockLength; /*!< Maximum block length united as byte */
419     uint32_t maxBlockCount;  /*!< Maximum block count can be set one time */
420     uint32_t flags;          /*!< Capability flags to indicate the support information(_sdhc_capability_flag) */
421 } sdhc_capability_t;
422 
423 /*! @brief Card transfer configuration.
424  *
425  * Define structure to configure the transfer-related command index/argument/flags and data block
426  * size/data block numbers. This structure needs to be filled each time a command is sent to the card.
427  */
428 typedef struct _sdhc_transfer_config
429 {
430     size_t dataBlockSize;     /*!< Data block size */
431     uint32_t dataBlockCount;  /*!< Data block count */
432     uint32_t commandArgument; /*!< Command argument */
433     uint32_t commandIndex;    /*!< Command index */
434     uint32_t flags;           /*!< Transfer flags(_sdhc_transfer_flag) */
435 } sdhc_transfer_config_t;
436 
437 /*! @brief Data structure to configure the MMC boot feature */
438 typedef struct _sdhc_boot_config
439 {
440     uint32_t ackTimeoutCount;      /*!< Timeout value for the boot ACK. The available range is 0 ~ 15. */
441     sdhc_boot_mode_t bootMode;     /*!< Boot mode selection. */
442     uint32_t blockCount;           /*!< Stop at block gap value of automatic mode. Available range is 0 ~ 65535. */
443     bool enableBootAck;            /*!< Enable or disable boot ACK */
444     bool enableBoot;               /*!< Enable or disable fast boot */
445     bool enableAutoStopAtBlockGap; /*!< Enable or disable auto stop at block gap function in boot period */
446 } sdhc_boot_config_t;
447 
448 /*! @brief Data structure to initialize the SDHC */
449 typedef struct _sdhc_config
450 {
451     bool cardDetectDat3;           /*!< Enable DAT3 as card detection pin */
452     sdhc_endian_mode_t endianMode; /*!< Endian mode */
453     sdhc_dma_mode_t dmaMode;       /*!< DMA mode */
454     uint32_t readWatermarkLevel;   /*!< Watermark level for DMA read operation. Available range is 1 ~ 128. */
455     uint32_t writeWatermarkLevel;  /*!< Watermark level for DMA write operation. Available range is 1 ~ 128. */
456 } sdhc_config_t;
457 
458 /*!
459  * @brief Card data descriptor
460  *
461  * Defines a structure to contain data-related attribute. 'enableIgnoreError' is used for the case that upper card
462  * driver
463  * want to ignore the error event to read/write all the data not to stop read/write immediately when error event
464  * happen for example bus testing procedure for MMC card.
465  */
466 typedef struct _sdhc_data
467 {
468     bool enableAutoCommand12; /*!< Enable auto CMD12 */
469     bool enableIgnoreError;   /*!< Enable to ignore error event to read/write all the data */
470     size_t blockSize;         /*!< Block size */
471     uint32_t blockCount;      /*!< Block count */
472     uint32_t *rxData;         /*!< Buffer to save data read */
473     const uint32_t *txData;   /*!< Data buffer to write */
474 } sdhc_data_t;
475 
476 /*!
477  * @brief Card command descriptor
478  *
479  * Define card command-related attribute.
480  */
481 typedef struct _sdhc_command
482 {
483     uint32_t index;                         /*!< Command index */
484     uint32_t argument;                      /*!< Command argument */
485     sdhc_card_command_type_t type;          /*!< Command type */
486     sdhc_card_response_type_t responseType; /*!< Command response type */
487     uint32_t response[4U];                  /*!< Response for this command */
488     uint32_t responseErrorFlags;            /*!< response error flag, the flag which need to check
489                                                 the command reponse*/
490 } sdhc_command_t;
491 
492 /*! @brief Transfer state */
493 typedef struct _sdhc_transfer
494 {
495     sdhc_data_t *data;       /*!< Data to transfer */
496     sdhc_command_t *command; /*!< Command to send */
497 } sdhc_transfer_t;
498 
499 /*! @brief SDHC handle typedef */
500 typedef struct _sdhc_handle sdhc_handle_t;
501 
502 /*! @brief SDHC callback functions. */
503 typedef struct _sdhc_transfer_callback
504 {
505     void (*CardInserted)(SDHC_Type *base,
506                          void *userData); /*!< Card inserted occurs when DAT3/CD pin is for card detect */
507     void (*CardRemoved)(SDHC_Type *base, void *userData);   /*!< Card removed occurs */
508     void (*SdioInterrupt)(SDHC_Type *base, void *userData); /*!< SDIO card interrupt occurs */
509     void (*SdioBlockGap)(SDHC_Type *base, void *userData);  /*!< SDIO card stopped at block gap occurs */
510     void (*TransferComplete)(SDHC_Type *base,
511                              sdhc_handle_t *handle,
512                              status_t status,
513                              void *userData); /*!< Transfer complete callback */
514 } sdhc_transfer_callback_t;
515 
516 /*!
517  * @brief SDHC handle
518  *
519  * Defines the structure to save the SDHC state information and callback function. The detailed interrupt status when
520  * sending a command or transfering data can be obtained from the interruptFlags field by using the mask defined in
521  * sdhc_interrupt_flag_t.
522  *
523  * @note All the fields except interruptFlags and transferredWords must be allocated by the user.
524  */
525 struct _sdhc_handle
526 {
527     /* Transfer parameter */
528     sdhc_data_t *volatile data;       /*!< Data to transfer */
529     sdhc_command_t *volatile command; /*!< Command to send */
530 
531     /* Transfer status */
532     volatile uint32_t transferredWords; /*!< Words transferred by DATAPORT way */
533 
534     /* Callback functions */
535     sdhc_transfer_callback_t callback; /*!< Callback function */
536     void *userData;                    /*!< Parameter for transfer complete callback */
537 };
538 
539 /*! @brief SDHC transfer function. */
540 typedef status_t (*sdhc_transfer_function_t)(SDHC_Type *base, sdhc_transfer_t *content);
541 
542 /*! @brief SDHC host descriptor */
543 typedef struct _sdhc_host
544 {
545     SDHC_Type *base;                   /*!< SDHC peripheral base address */
546     uint32_t sourceClock_Hz;           /*!< SDHC source clock frequency united in Hz */
547     sdhc_config_t config;              /*!< SDHC configuration */
548     sdhc_capability_t capability;      /*!< SDHC capability information */
549     sdhc_transfer_function_t transfer; /*!< SDHC transfer function */
550 } sdhc_host_t;
551 
552 /*************************************************************************************************
553  * API
554  ************************************************************************************************/
555 #if defined(__cplusplus)
556 extern "C" {
557 #endif
558 
559 /*!
560  * @name Initialization and deinitialization
561  * @{
562  */
563 
564 /*!
565  * @brief SDHC module initialization function.
566  *
567  * Configures the SDHC according to the user configuration.
568  *
569  * Example:
570    @code
571    sdhc_config_t config;
572    config.cardDetectDat3 = false;
573    config.endianMode = kSDHC_EndianModeLittle;
574    config.dmaMode = kSDHC_DmaModeAdma2;
575    config.readWatermarkLevel = 128U;
576    config.writeWatermarkLevel = 128U;
577    SDHC_Init(SDHC, &config);
578    @endcode
579  *
580  * @param base SDHC peripheral base address.
581  * @param config SDHC configuration information.
582  * @retval kStatus_Success Operate successfully.
583  */
584 void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config);
585 
586 /*!
587  * @brief Deinitializes the SDHC.
588  *
589  * @param base SDHC peripheral base address.
590  */
591 void SDHC_Deinit(SDHC_Type *base);
592 
593 /*!
594  * @brief Resets the SDHC.
595  *
596  * @param base SDHC peripheral base address.
597  * @param mask The reset type mask(_sdhc_reset).
598  * @param timeout Timeout for reset.
599  * @retval true Reset successfully.
600  * @retval false Reset failed.
601  */
602 bool SDHC_Reset(SDHC_Type *base, uint32_t mask, uint32_t timeout);
603 
604 /* @} */
605 
606 /*!
607  * @name DMA Control
608  * @{
609  */
610 
611 /*!
612  * @brief Sets the ADMA descriptor table configuration.
613  *
614  * @param base SDHC peripheral base address.
615  * @param dmaMode DMA mode.
616  * @param table ADMA table address.
617  * @param tableWords ADMA table buffer length united as Words.
618  * @param data Data buffer address.
619  * @param dataBytes Data length united as bytes.
620  * @retval kStatus_OutOfRange ADMA descriptor table length isn't enough to describe data.
621  * @retval kStatus_Success Operate successfully.
622  */
623 status_t SDHC_SetAdmaTableConfig(SDHC_Type *base,
624                                  sdhc_dma_mode_t dmaMode,
625                                  uint32_t *table,
626                                  uint32_t tableWords,
627                                  const uint32_t *data,
628                                  uint32_t dataBytes);
629 
630 /* @} */
631 
632 /*!
633  * @name Interrupts
634  * @{
635  */
636 
637 /*!
638  * @brief Enables the interrupt status.
639  *
640  * @param base SDHC peripheral base address.
641  * @param mask Interrupt status flags mask(_sdhc_interrupt_status_flag).
642  */
SDHC_EnableInterruptStatus(SDHC_Type * base,uint32_t mask)643 static inline void SDHC_EnableInterruptStatus(SDHC_Type *base, uint32_t mask)
644 {
645     base->IRQSTATEN |= mask;
646 }
647 
648 /*!
649  * @brief Disables the interrupt status.
650  *
651  * @param base SDHC peripheral base address.
652  * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag).
653  */
SDHC_DisableInterruptStatus(SDHC_Type * base,uint32_t mask)654 static inline void SDHC_DisableInterruptStatus(SDHC_Type *base, uint32_t mask)
655 {
656     base->IRQSTATEN &= ~mask;
657 }
658 
659 /*!
660  * @brief Enables the interrupt signal corresponding to the interrupt status flag.
661  *
662  * @param base SDHC peripheral base address.
663  * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag).
664  */
SDHC_EnableInterruptSignal(SDHC_Type * base,uint32_t mask)665 static inline void SDHC_EnableInterruptSignal(SDHC_Type *base, uint32_t mask)
666 {
667     base->IRQSIGEN |= mask;
668 }
669 
670 /*!
671  * @brief Disables the interrupt signal corresponding to the interrupt status flag.
672  *
673  * @param base SDHC peripheral base address.
674  * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag).
675  */
SDHC_DisableInterruptSignal(SDHC_Type * base,uint32_t mask)676 static inline void SDHC_DisableInterruptSignal(SDHC_Type *base, uint32_t mask)
677 {
678     base->IRQSIGEN &= ~mask;
679 }
680 
681 /* @} */
682 
683 /*!
684  * @name Status
685  * @{
686  */
687 
688 /*!
689  * @brief Gets the enabled interrupt status.
690  *
691  * @param base SDHC peripheral base address.
692  * @return Current interrupt status flags mask(_sdhc_interrupt_status_flag).
693  */
SDHC_GetEnabledInterruptStatusFlags(SDHC_Type * base)694 static inline uint32_t SDHC_GetEnabledInterruptStatusFlags(SDHC_Type *base)
695 {
696     uint32_t intStatus = base->IRQSTAT;
697 
698     return intStatus & base->IRQSIGEN;
699 }
700 
701 /*!
702  * @brief Gets the current interrupt status.
703  *
704  * @param base SDHC peripheral base address.
705  * @return Current interrupt status flags mask(_sdhc_interrupt_status_flag).
706  */
SDHC_GetInterruptStatusFlags(SDHC_Type * base)707 static inline uint32_t SDHC_GetInterruptStatusFlags(SDHC_Type *base)
708 {
709     return base->IRQSTAT;
710 }
711 
712 /*!
713  * @brief Clears a specified interrupt status.
714  *
715  * @param base SDHC peripheral base address.
716  * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag).
717  */
SDHC_ClearInterruptStatusFlags(SDHC_Type * base,uint32_t mask)718 static inline void SDHC_ClearInterruptStatusFlags(SDHC_Type *base, uint32_t mask)
719 {
720     base->IRQSTAT = mask;
721 }
722 
723 /*!
724  * @brief Gets the status of auto command 12 error.
725  *
726  * @param base SDHC peripheral base address.
727  * @return Auto command 12 error status flags mask(_sdhc_auto_command12_error_status_flag).
728  */
SDHC_GetAutoCommand12ErrorStatusFlags(SDHC_Type * base)729 static inline uint32_t SDHC_GetAutoCommand12ErrorStatusFlags(SDHC_Type *base)
730 {
731     return base->AC12ERR;
732 }
733 
734 /*!
735  * @brief Gets the status of the ADMA error.
736  *
737  * @param base SDHC peripheral base address.
738  * @return ADMA error status flags mask(_sdhc_adma_error_status_flag).
739  */
SDHC_GetAdmaErrorStatusFlags(SDHC_Type * base)740 static inline uint32_t SDHC_GetAdmaErrorStatusFlags(SDHC_Type *base)
741 {
742     return base->ADMAES;
743 }
744 
745 /*!
746  * @brief Gets a present status.
747  *
748  * This function gets the present SDHC's status except for an interrupt status and an error status.
749  *
750  * @param base SDHC peripheral base address.
751  * @return Present SDHC's status flags mask(_sdhc_present_status_flag).
752  */
SDHC_GetPresentStatusFlags(SDHC_Type * base)753 static inline uint32_t SDHC_GetPresentStatusFlags(SDHC_Type *base)
754 {
755     return base->PRSSTAT;
756 }
757 
758 /* @} */
759 
760 /*!
761  * @name Bus Operations
762  * @{
763  */
764 
765 /*!
766  * @brief Gets the capability information.
767  *
768  * @param base SDHC peripheral base address.
769  * @param capability Structure to save capability information.
770  */
771 void SDHC_GetCapability(SDHC_Type *base, sdhc_capability_t *capability);
772 
773 /*!
774  * @brief Enables or disables the SD bus clock.
775  *
776  * @param base SDHC peripheral base address.
777  * @param enable True to enable, false to disable.
778  */
SDHC_EnableSdClock(SDHC_Type * base,bool enable)779 static inline void SDHC_EnableSdClock(SDHC_Type *base, bool enable)
780 {
781     if (enable)
782     {
783         base->SYSCTL |= SDHC_SYSCTL_SDCLKEN_MASK;
784     }
785     else
786     {
787         base->SYSCTL &= ~SDHC_SYSCTL_SDCLKEN_MASK;
788     }
789 }
790 
791 /*!
792  * @brief Sets the SD bus clock frequency.
793  *
794  * @param base SDHC peripheral base address.
795  * @param srcClock_Hz SDHC source clock frequency united in Hz.
796  * @param busClock_Hz SD bus clock frequency united in Hz.
797  *
798  * @return The nearest frequency of busClock_Hz configured to SD bus.
799  */
800 uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz);
801 
802 /*!
803  * @brief Sends 80 clocks to the card to set it to the active state.
804  *
805  * This function must be called each time the card is inserted to ensure that the card can receive the command
806  * correctly.
807  *
808  * @param base SDHC peripheral base address.
809  * @param timeout Timeout to initialize card.
810  * @retval true Set card active successfully.
811  * @retval false Set card active failed.
812  */
813 bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout);
814 
815 /*!
816  * @brief Sets the data transfer width.
817  *
818  * @param base SDHC peripheral base address.
819  * @param width Data transfer width.
820  */
SDHC_SetDataBusWidth(SDHC_Type * base,sdhc_data_bus_width_t width)821 static inline void SDHC_SetDataBusWidth(SDHC_Type *base, sdhc_data_bus_width_t width)
822 {
823     base->PROCTL = ((base->PROCTL & ~SDHC_PROCTL_DTW_MASK) | SDHC_PROCTL_DTW(width));
824 }
825 
826 /*!
827  * @brief detect card insert status.
828  *
829  * @param base SDHC peripheral base address.
830  * @param enable Enable/disable flag.
831  */
SDHC_CardDetectByData3(SDHC_Type * base,bool enable)832 static inline void SDHC_CardDetectByData3(SDHC_Type *base, bool enable)
833 {
834     if (enable)
835     {
836         base->PROCTL |= SDHC_PROCTL_D3CD_MASK;
837     }
838     else
839     {
840         base->PROCTL &= ~SDHC_PROCTL_D3CD_MASK;
841     }
842 }
843 
844 /*!
845  * @brief Sets the card transfer-related configuration.
846  *
847  * This function fills the card transfer-related command argument/transfer flag/data size. The command and data are
848  sent by
849  * SDHC after calling this function.
850  *
851  * Example:
852    @code
853    sdhc_transfer_config_t transferConfig;
854    transferConfig.dataBlockSize = 512U;
855    transferConfig.dataBlockCount = 2U;
856    transferConfig.commandArgument = 0x01AAU;
857    transferConfig.commandIndex = 8U;
858    transferConfig.flags |= (kSDHC_EnableDmaFlag | kSDHC_EnableAutoCommand12Flag | kSDHC_MultipleBlockFlag);
859    SDHC_SetTransferConfig(SDHC, &transferConfig);
860    @endcode
861  *
862  * @param base SDHC peripheral base address.
863  * @param config Command configuration structure.
864  */
865 void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config);
866 
867 /*!
868  * @brief Gets the command response.
869  *
870  * @param base SDHC peripheral base address.
871  * @param index The index of response register, range from 0 to 3.
872  * @return Response register transfer.
873  */
SDHC_GetCommandResponse(SDHC_Type * base,uint32_t index)874 static inline uint32_t SDHC_GetCommandResponse(SDHC_Type *base, uint32_t index)
875 {
876     assert(index < 4UL);
877 
878     return base->CMDRSP[index];
879 }
880 
881 /*!
882  * @brief Fills the data port.
883  *
884  * This function is used to implement the data transfer by Data Port instead of DMA.
885  *
886  * @param base SDHC peripheral base address.
887  * @param data The data about to be sent.
888  */
SDHC_WriteData(SDHC_Type * base,uint32_t data)889 static inline void SDHC_WriteData(SDHC_Type *base, uint32_t data)
890 {
891     base->DATPORT = data;
892 }
893 
894 /*!
895  * @brief Retrieves the data from the data port.
896  *
897  * This function is used to implement the data transfer by Data Port instead of DMA.
898  *
899  * @param base SDHC peripheral base address.
900  * @return The data has been read.
901  */
SDHC_ReadData(SDHC_Type * base)902 static inline uint32_t SDHC_ReadData(SDHC_Type *base)
903 {
904     return base->DATPORT;
905 }
906 
907 /*!
908  * @brief Enables or disables a wakeup event in low-power mode.
909  *
910  * @param base SDHC peripheral base address.
911  * @param mask Wakeup events mask(_sdhc_wakeup_event).
912  * @param enable True to enable, false to disable.
913  */
SDHC_EnableWakeupEvent(SDHC_Type * base,uint32_t mask,bool enable)914 static inline void SDHC_EnableWakeupEvent(SDHC_Type *base, uint32_t mask, bool enable)
915 {
916     if (enable)
917     {
918         base->PROCTL |= mask;
919     }
920     else
921     {
922         base->PROCTL &= ~mask;
923     }
924 }
925 
926 /*!
927  * @brief Enables or disables the card detection level for testing.
928  *
929  * @param base SDHC peripheral base address.
930  * @param enable True to enable, false to disable.
931  */
SDHC_EnableCardDetectTest(SDHC_Type * base,bool enable)932 static inline void SDHC_EnableCardDetectTest(SDHC_Type *base, bool enable)
933 {
934     if (enable)
935     {
936         base->PROCTL |= SDHC_PROCTL_CDSS_MASK;
937     }
938     else
939     {
940         base->PROCTL &= ~SDHC_PROCTL_CDSS_MASK;
941     }
942 }
943 
944 /*!
945  * @brief Sets the card detection test level.
946  *
947  * This function sets the card detection test level to indicate whether the card is inserted into the SDHC when
948  * DAT[3]/ CD pin is selected as a card detection pin. This function can also assert the pin logic when DAT[3]/CD
949  * pin is selected as the card detection pin.
950  *
951  * @param base SDHC peripheral base address.
952  * @param high True to set the card detect level to high.
953  */
SDHC_SetCardDetectTestLevel(SDHC_Type * base,bool high)954 static inline void SDHC_SetCardDetectTestLevel(SDHC_Type *base, bool high)
955 {
956     if (high)
957     {
958         base->PROCTL |= SDHC_PROCTL_CDTL_MASK;
959     }
960     else
961     {
962         base->PROCTL &= ~SDHC_PROCTL_CDTL_MASK;
963     }
964 }
965 
966 /*!
967  * @brief Enables or disables the SDIO card control.
968  *
969  * @param base SDHC peripheral base address.
970  * @param mask SDIO card control flags mask(_sdhc_sdio_control_flag).
971  * @param enable True to enable, false to disable.
972  */
973 void SDHC_EnableSdioControl(SDHC_Type *base, uint32_t mask, bool enable);
974 
975 /*!
976  * @brief Restarts a transaction which has stopped at the block GAP for the SDIO card.
977  *
978  * @param base SDHC peripheral base address.
979  */
SDHC_SetContinueRequest(SDHC_Type * base)980 static inline void SDHC_SetContinueRequest(SDHC_Type *base)
981 {
982     base->PROCTL |= SDHC_PROCTL_CREQ_MASK;
983 }
984 
985 /*!
986  * @brief Configures the MMC boot feature.
987  *
988  * Example:
989    @code
990    sdhc_boot_config_t config;
991    config.ackTimeoutCount = 4;
992    config.bootMode = kSDHC_BootModeNormal;
993    config.blockCount = 5;
994    config.enableBootAck = true;
995    config.enableBoot = true;
996    config.enableAutoStopAtBlockGap = true;
997    SDHC_SetMmcBootConfig(SDHC, &config);
998    @endcode
999  *
1000  * @param base SDHC peripheral base address.
1001  * @param config The MMC boot configuration information.
1002  */
1003 void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config);
1004 
1005 /*!
1006  * @brief Forces generating events according to the given mask.
1007  *
1008  * @param base SDHC peripheral base address.
1009  * @param mask The force events mask(_sdhc_force_event).
1010  */
SDHC_SetForceEvent(SDHC_Type * base,uint32_t mask)1011 static inline void SDHC_SetForceEvent(SDHC_Type *base, uint32_t mask)
1012 {
1013     base->FEVT = mask;
1014 }
1015 
1016 /* @} */
1017 
1018 /*!
1019  * @name Transactional
1020  * @{
1021  */
1022 
1023 /*!
1024  * @brief Transfers the command/data using a blocking method.
1025  *
1026  * This function waits until the command response/data is received or the SDHC encounters an error by polling the
1027  * status flag. This function support non word align data addr transfer support, if data buffer addr is not align in
1028  * DMA mode, the API will continue finish the transfer by polling IO directly The application must not call this API
1029  * in multiple threads at the same time. Because of that this API doesn't support the re-entry mechanism.
1030  *
1031  * @note There is no need to call the API 'SDHC_TransferCreateHandle' when calling this API.
1032  *
1033  * @param base SDHC peripheral base address.
1034  * @param admaTable ADMA table address, can't be null if transfer way is ADMA1/ADMA2.
1035  * @param admaTableWords ADMA table length united as words, can't be 0 if transfer way is ADMA1/ADMA2.
1036  * @param transfer Transfer content.
1037  * @retval kStatus_InvalidArgument Argument is invalid.
1038  * @retval kStatus_SDHC_PrepareAdmaDescriptorFailed Prepare ADMA descriptor failed.
1039  * @retval kStatus_SDHC_SendCommandFailed Send command failed.
1040  * @retval kStatus_SDHC_TransferDataFailed Transfer data failed.
1041  * @retval kStatus_Success Operate successfully.
1042  */
1043 status_t SDHC_TransferBlocking(SDHC_Type *base,
1044                                uint32_t *admaTable,
1045                                uint32_t admaTableWords,
1046                                sdhc_transfer_t *transfer);
1047 
1048 /*!
1049  * @brief Creates the SDHC handle.
1050  *
1051  * @param base SDHC peripheral base address.
1052  * @param handle SDHC handle pointer.
1053  * @param callback Structure pointer to contain all callback functions.
1054  * @param userData Callback function parameter.
1055  */
1056 void SDHC_TransferCreateHandle(SDHC_Type *base,
1057                                sdhc_handle_t *handle,
1058                                const sdhc_transfer_callback_t *callback,
1059                                void *userData);
1060 
1061 /*!
1062  * @brief Transfers the command/data using an interrupt and an asynchronous method.
1063  *
1064  * This function sends a command and data and returns immediately. It doesn't wait the transfer complete or
1065  * encounter an error. This function support non word align data addr transfer support, if data buffer addr is not
1066  * align in DMA mode, the API will continue finish the transfer by polling IO directly The application must not call
1067  * this API in multiple threads at the same time. Because of that this API doesn't support the re-entry mechanism.
1068  *
1069  * @note Call the API 'SDHC_TransferCreateHandle' when calling this API.
1070  *
1071  * @param base SDHC peripheral base address.
1072  * @param handle SDHC handle.
1073  * @param admaTable ADMA table address, can't be null if transfer way is ADMA1/ADMA2.
1074  * @param admaTableWords ADMA table length united as words, can't be 0 if transfer way is ADMA1/ADMA2.
1075  * @param transfer Transfer content.
1076  * @retval kStatus_InvalidArgument Argument is invalid.
1077  * @retval kStatus_SDHC_BusyTransferring Busy transferring.
1078  * @retval kStatus_SDHC_PrepareAdmaDescriptorFailed Prepare ADMA descriptor failed.
1079  * @retval kStatus_Success Operate successfully.
1080  */
1081 status_t SDHC_TransferNonBlocking(
1082     SDHC_Type *base, sdhc_handle_t *handle, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer);
1083 
1084 /*!
1085  * @brief IRQ handler for the SDHC.
1086  *
1087  * This function deals with the IRQs on the given host controller.
1088  *
1089  * @param base SDHC peripheral base address.
1090  * @param handle SDHC handle.
1091  */
1092 void SDHC_TransferHandleIRQ(SDHC_Type *base, sdhc_handle_t *handle);
1093 
1094 /* @} */
1095 
1096 #if defined(__cplusplus)
1097 }
1098 #endif
1099 /*! @} */
1100 
1101 #endif /* _FSL_SDHC_H_*/
1102