1
2 /**
3 * @file xmc_sdmmc.h
4 * @date 2019-05-07
5 *
6 * @cond
7 *********************************************************************************************************************
8 * XMClib v2.1.24 - XMC Peripheral Driver Library
9 *
10 * Copyright (c) 2015-2019, Infineon Technologies AG
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
14 * following conditions are met:
15 *
16 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
17 * disclaimer.
18 *
19 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials provided with the distribution.
21 *
22 * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
23 * products derived from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
34 * Infineon Technologies AG dave@infineon.com).
35 *********************************************************************************************************************
36 *
37 * Change History
38 * --------------
39 *
40 * 2015-02-20:
41 * - Initial version
42 * - Documentation updates
43 *
44 * 2015-06-20:
45 * - Removed version macros and declaration of GetDriverVersion API <br>
46 *
47 * 2016-01-16:
48 * - Added the following APIs to the XMC_SDMMC low level driver <br>
49 * 1) XMC_SDMMC_EnableDelayCmdDatLines <br>
50 * 2) XMC_SDMMC_DisableDelayCmdDatLines <br>
51 * 3) XMC_SDMMC_SetDelay <br>
52 * 4) XMC_SDMMC_EnableHighSpeed <br>
53 * 5) XMC_SDMMC_DisableHighSpeed <br>
54 *
55 * 2016-04-07:
56 * - Added XMC_SDMMC_COMMAND_RESPONSE_t <br>
57 *
58 * 2016-07-11:
59 * - Adjust masks for the following functions: <br>
60 * 1) XMC_SDMMC_SetBusVoltage <br>
61 * 2) XMC_SDMMC_SetDataLineTimeout <br>
62 * 3) XMC_SDMMC_SDClockFreqSelect <br>
63 *
64 * 2017-02-14:
65 * - Added: <br>
66 * 1) XMC_SDMMC_SetCardDetectionStatus() <br>
67 * 2) XMC_SDMMC_SetCardDetectionSource() <br>
68 *
69 * 2018-08-29:
70 * - XMC_SDMMC_SetCardDetectionStatus() and XMC_SDMMC_SetCardDetectionSource()
71 * Changed for XMC43/XMC47/XMC48 to use SDMMC Write Protection and Card Detection Control register instead of the test register of SDMMC host controller
72 * - Added for XMC43/XMC47/XMC48:
73 * 1) XMC_SDMMC_SetWriteProtectionSource()
74 * 2) XMC_SDMMC_SetWriteProtectionStatus()
75 *
76 * 2019-05-07:
77 * - Fix compilation issues on XMC45
78 * - Fix compilation warnings
79 *
80 * @endcond
81 */
82
83 #ifndef XMC_SDMMC_H
84 #define XMC_SDMMC_H
85
86 /*******************************************************************************
87 * HEADER FILES
88 *******************************************************************************/
89
90 #include "xmc_common.h"
91
92 #if defined (SDMMC)
93
94 #if (UC_SERIES != XMC45)
95 #define SDMMC_CON_WPSEL_Pos 0
96 #define SDMMC_CON_WPSEL_Msk 0x00000001UL
97 #define SDMMC_CON_WPSVAL_Pos 4
98 #define SDMMC_CON_WPSVAL_Msk 0x00000010UL
99 #define SDMMC_CON_CDSEL_Pos 16
100 #define SDMMC_CON_CDSEL_Msk 0x00010000UL
101 #define SDMMC_CON_CDSVAL_Pos 20
102 #define SDMMC_CON_CDSVAL_Msk 0x00100000UL
103 #endif
104
105 /**
106 * @addtogroup XMClib XMC Peripheral Library
107 * @{
108 */
109
110 /**
111 * @addtogroup SDMMC
112 * @brief Secure Digital/Multi Media Card (SDMMC) driver for the XMC4500 microcontroller
113 *
114 * The SDMMC peripheral provides an interface between SD/SDIO/MMC cards and the AHB. It handles
115 * the SD/SDIO protocol at transmission level. It automatically packs data and checks for CRC,
116 * start/end bits and format correctness. For SD cards, a maximum transfer rate of 24MB/sec is
117 * supported and for MMC cards, 48MB/sec.
118 *
119 * The peripheral can be used for applications that require large storage memory; e.g. Data logging,
120 * firmware updates or an embedded database.
121 *
122 * The SDMMC low level driver provides functions to configure and initialize the SDMMC hardware
123 * peripheral.
124 * @{
125 */
126
127 /*******************************************************************************
128 * MACROS
129 *******************************************************************************/
130
131 /**
132 * A convenient symbol for the SDMMC peripheral base address
133 */
134 #if defined (SDMMC)
135 # define XMC_SDMMC ((XMC_SDMMC_t *)SDMMC_BASE)
136 #else
137 # error 'SDMMC' base peripheral pointer not defined
138 #endif
139
140 /*
141 * Check for valid ACMD errors <br>
142 *
143 * This macro is used in the LLD for assertion checks (XMC_ASSERT).
144 */
145 #define XMC_SDMMC_CHECK_MODULE_PTR(p) ((p) == XMC_SDMMC)
146
147 /*
148 * Check for valid ACMD errors <br>
149 *
150 * This macro is used in the LLD for assertion checks (XMC_ASSERT).
151 */
152 #define XMC_SDMMC_CHECK_ACMD_ERR(v)\
153 ((v == XMC_SDMMC_ACMD12_NOT_EXEC_ERR) ||\
154 (v == XMC_SDMMC_ACMD_TIMEOUT_ERR) ||\
155 (v == XMC_SDMMC_ACMD_CRC_ERR) ||\
156 (v == XMC_SDMMC_ACMD_END_BIT_ERR) ||\
157 (v == XMC_SDMMC_ACMD_IND_ERR) ||\
158 (v == XMC_SDMMC_CMD_NOT_ISSUED_BY_ACMD12_ERR))
159
160 /*
161 * Check for valid SDCLK divider frequency <br>
162 *
163 * This macro is used in the LLD for assertion checks (XMC_ASSERT).
164 */
165 #define XMC_SDMMC_CHECK_SDCLK_FREQ(f)\
166 ((f == XMC_SDMMC_CLK_DIV_1) ||\
167 (f == XMC_SDMMC_CLK_DIV_2) ||\
168 (f == XMC_SDMMC_CLK_DIV_4) ||\
169 (f == XMC_SDMMC_CLK_DIV_8) ||\
170 (f == XMC_SDMMC_CLK_DIV_16) ||\
171 (f == XMC_SDMMC_CLK_DIV_32) ||\
172 (f == XMC_SDMMC_CLK_DIV_64) ||\
173 (f == XMC_SDMMC_CLK_DIV_128) ||\
174 (f == XMC_SDMMC_CLK_DIV_256))
175
176 /*
177 * Check for valid bus voltage levels <br>
178 *
179 * This macro is used in the LLD for assertion checks (XMC_ASSERT).
180 */
181 #define XMC_SDMMC_CHECK_BUS_VOLTAGE(v)\
182 (v == XMC_SDMMC_BUS_VOLTAGE_3_3_VOLTS)
183
184 /*
185 * Check for valid data timeout counter values <br>
186 *
187 * This macro is used in the LLD for assertion checks (XMC_ASSERT).
188 */
189 #define XMC_SDMMC_CHECK_DAT_TIMEOUT_COUNTER(c)\
190 ((c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_13) ||\
191 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_14) ||\
192 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_15) ||\
193 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_16) ||\
194 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_17) ||\
195 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_18) ||\
196 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_19) ||\
197 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_20) ||\
198 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_21) ||\
199 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_22) ||\
200 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_23) ||\
201 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_24) ||\
202 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_25) ||\
203 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_26) ||\
204 (c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_27))
205
206 /*
207 * Valid number of data lines <br>
208 *
209 * This macro is used in the LLD for assertion checks (XMC_ASSERT).
210 */
211 #define XMC_SDMMC_CHECK_DATA_LINES(l)\
212 ((l == XMC_SDMMC_DATA_LINES_1) ||\
213 (l == XMC_SDMMC_DATA_LINES_4) ||\
214 (l == XMC_SDMMC_DATA_LINES_8))
215
216 /*
217 * Check data transfer dir: Host to card and vice-versa <br>
218 *
219 * This macro is used in the LLD for assertion checks (XMC_ASSERT).
220 */
221 #define XMC_SDMMC_CHECK_DATA_TRANSFER_DIR(d)\
222 ((d == XMC_SDMMC_DATA_TRANSFER_HOST_TO_CARD) ||\
223 (d == XMC_SDMMC_DATA_TRANSFER_CARD_TO_HOST))
224
225 /*
226 * Min and max number of delay elements <br>
227 *
228 * This macro is used in the LLD for assertion checks (XMC_ASSERT).
229 */
230 #define XMC_SDMMC_MIN_DELAY_ELEMENTS (0U)
231 #define XMC_SDMMC_MAX_DELAY_ELEMENTS (15U)
232
233 /*******************************************************************************
234 * ENUMS
235 *******************************************************************************/
236
237 /**
238 * Number of data lines for SDMMC data transfer
239 */
240 typedef enum XMC_SDMMC_DATA_LINES
241 {
242 XMC_SDMMC_DATA_LINES_1 = 0x00U, /**< Single data line mode */
243 XMC_SDMMC_DATA_LINES_4 = 0x02U, /**< 4-bit mode */
244 XMC_SDMMC_DATA_LINES_8 = 0x20U /**< SD 8-bit mode */
245 } XMC_SDMMC_DATA_LINES_t;
246
247 /**
248 * Valid SD clock frequency divider selection
249 */
250 typedef enum XMC_SDMMC_SDCLK_FREQ_SEL
251 {
252 XMC_SDMMC_CLK_DIV_1 = 0x00U, /**< Base clock (10 Mhz -> 63 Mhz) */
253 XMC_SDMMC_CLK_DIV_2 = 0x01U, /**< Base clock divided by 2 */
254 XMC_SDMMC_CLK_DIV_4 = 0x02U, /**< Base clock divided by 4 */
255 XMC_SDMMC_CLK_DIV_8 = 0x04U, /**< Base clock divided by 8 */
256 XMC_SDMMC_CLK_DIV_16 = 0x08U, /**< Base clock divided by 16 */
257 XMC_SDMMC_CLK_DIV_32 = 0x10U, /**< Base clock divided by 32 */
258 XMC_SDMMC_CLK_DIV_64 = 0x20U, /**< Base clock divided by 64 */
259 XMC_SDMMC_CLK_DIV_128 = 0x40U, /**< Base clock divided by 128 */
260 XMC_SDMMC_CLK_DIV_256 = 0x80U /**< Base clock divided by 256 */
261 } XMC_SDMMC_SDCLK_FREQ_SEL_t;
262
263 /**
264 * Status return values for the SDMMC low level driver
265 */
266 typedef enum XMC_SDMMC_STATUS
267 {
268 XMC_SDMMC_STATUS_SUCCESS = 0U, /**< Operation successful */
269 XMC_SDMMC_STATUS_CMD_LINE_BUSY, /**< Command line busy */
270 XMC_SDMMC_STATUS_DAT_LINE_BUSY /**< Data line busy */
271 } XMC_SDMMC_STATUS_t;
272
273 /**
274 * SDMMC events (Normal and error events)
275 */
276 typedef enum XMC_SDMMC_EVENT
277 {
278 XMC_SDMMC_CMD_COMPLETE = 0x01U, /**< Command complete event */
279 XMC_SDMMC_TX_COMPLETE = 0x02U, /**< Transmit complete event */
280 XMC_SDMMC_BLOCK_GAP_EVENT = 0x04U, /**< Block gap event */
281 XMC_SDMMC_BUFFER_WRITE_READY = 0x10U, /**< Buffer write ready event */
282 XMC_SDMMC_BUFFER_READ_READY = 0x20U, /**< Buffer read ready event */
283 XMC_SDMMC_CARD_INS = 0x40U, /**< Card insert event */
284 XMC_SDMMC_CARD_REMOVAL = 0x80U, /**< Card removal event */
285 XMC_SDMMC_CARD_INT = 0x100U, /**< Card INT event */
286 XMC_SDMMC_CARD_ERR = 0x8000U, /**< Card error interrupt */
287 XMC_SDMMC_CMD_TIMEOUT_ERR = ((uint32_t)0x01 << 16U), /**< Command time-out error */
288 XMC_SDMMC_CMD_CRC_ERR = ((uint32_t)0x02U << 16U), /**< Command CRC error */
289 XMC_SDMMC_CMD_END_BIT_ERR = ((uint32_t)0x04U << 16U), /**< Command end bit error */
290 XMC_SDMMC_CMD_IND_ERR = ((uint32_t)0x08U << 16U), /**< Command index error */
291 XMC_SDMMC_DATA_TIMEOUT_ERR = ((uint32_t)0x10U << 16U), /**< Data time-out error */
292 XMC_SDMMC_DATA_CRC_ERR = ((uint32_t)0x20U << 16U), /**< Data CRC error */
293 XMC_SDMMC_DATA_END_BIT_ERR = ((uint32_t)0x40U << 16U), /**< Data end bit error */
294 XMC_SDMMC_CURRENT_LIMIT_ERR = ((uint32_t)0x80U << 16U), /**< Current limit error */
295 XMC_SDMMC_ACMD_ERR = ((uint32_t)0x100U << 16U), /**< ACMD error */
296 XMC_SDMMC_TARGET_RESP_ERR = ((uint32_t)0x1000U << 16U) /**< Target response error */
297 } XMC_SDMMC_EVENT_t;
298
299 /**
300 * SDMMC wakeup events
301 */
302 typedef enum XMC_SDMMC_WAKEUP_EVENT
303 {
304 XMC_SDMMC_WAKEUP_EN_CARD_INT = SDMMC_WAKEUP_CTRL_WAKEUP_EVENT_EN_INT_Msk, /**< Wakeup on card interrupt */
305 XMC_SDMMC_WAKEUP_EN_CARD_INS = SDMMC_WAKEUP_CTRL_WAKEUP_EVENT_EN_INS_Msk, /**< Wakeup on SD card insertion */
306 XMC_SDMMC_WAKEUP_EN_CARD_REM = SDMMC_WAKEUP_CTRL_WAKEUP_EVENT_EN_REM_Msk /**< Wakeup SD card removal */
307 } XMC_SDMMC_WAKEUP_EVENT_t;
308
309 /**
310 * SDMMC software reset modes
311 */
312 typedef enum XMC_SDMMC_SW_RESET
313 {
314 XMC_SDMMC_SW_RESET_ALL = SDMMC_SW_RESET_SW_RST_ALL_Msk, /**< Software reset all */
315 XMC_SDMMC_SW_RST_CMD_LINE = SDMMC_SW_RESET_SW_RST_CMD_LINE_Msk, /**< Software reset command line */
316 XMC_SDMMC_SW_RST_DAT_LINE = SDMMC_SW_RESET_SW_RST_DAT_LINE_Msk /**< Software reset data line */
317 } XMC_SDMMC_SW_RESET_t;
318
319 /**
320 * CMD12 response errors of Auto CMD12
321 */
322 typedef enum XMC_SDMMC_ACMD_ERR
323 {
324 XMC_SDMMC_ACMD12_NOT_EXEC_ERR = SDMMC_ACMD_ERR_STATUS_ACMD12_NOT_EXEC_ERR_Msk, /**< ACMD12 not executed error */
325 XMC_SDMMC_ACMD_TIMEOUT_ERR = SDMMC_ACMD_ERR_STATUS_ACMD_TIMEOUT_ERR_Msk, /**< ACMD timeout error */
326 XMC_SDMMC_ACMD_CRC_ERR = SDMMC_ACMD_ERR_STATUS_ACMD_CRC_ERR_Msk, /**< ACMD CRC error */
327 XMC_SDMMC_ACMD_END_BIT_ERR = SDMMC_ACMD_ERR_STATUS_ACMD_END_BIT_ERR_Msk, /**< ACMD end bit error */
328 XMC_SDMMC_ACMD_IND_ERR = SDMMC_ACMD_ERR_STATUS_ACMD_IND_ERR_Msk, /**< ACMD IND error */
329 XMC_SDMMC_CMD_NOT_ISSUED_BY_ACMD12_ERR = SDMMC_ACMD_ERR_STATUS_CMD_NOT_ISSUED_BY_ACMD12_ERR_Msk /**< CMD not issued by ACMD12 */
330 } XMC_SDMMC_ACMD_ERR_t;
331
332 /**
333 * SDMMC response types
334 */
335 typedef enum XMC_SDMMC_RESPONSE_TYPE
336 {
337 XMC_SDMMC_RESPONSE_TYPE_NO_RESPONSE = 0U, /**< No response */
338 XMC_SDMMC_RESPONSE_TYPE_R1, /**< Response type: R1 */
339 XMC_SDMMC_RESPONSE_TYPE_R1b, /**< Response type: R1b */
340 XMC_SDMMC_RESPONSE_TYPE_R2, /**< Response type: R2 */
341 XMC_SDMMC_RESPONSE_TYPE_R3, /**< Response type: R3 */
342 XMC_SDMMC_RESPONSE_TYPE_R6, /**< Response type: R6 */
343 XMC_SDMMC_RESPONSE_TYPE_R7 /**< Response type: R7 */
344 } XMC_SDMMC_RESPONSE_TYPE_t;
345
346 /**
347 * Command response selection
348 */
349 typedef enum XMC_SDMMC_COMMAND_RESPONSE
350 {
351 XMC_SDMMC_COMMAND_RESPONSE_NONE = 0, /**< No Response */
352 XMC_SDMMC_COMMAND_RESPONSE_LONG = 1, /**< Response length 136 */
353 XMC_SDMMC_COMMAND_RESPONSE_SHORT = 2, /**< Response length 48 */
354 XMC_SDMMC_COMMAND_RESPONSE_SHORT_BUSY = 3, /**< Response length 48 check Busy after response */
355 } XMC_SDMMC_COMMAND_RESPONSE_t;
356
357 /**
358 * Types of SDMMC commands
359 */
360 typedef enum XMC_SDMMC_COMMAND_TYPE
361 {
362 XMC_SDMMC_COMMAND_TYPE_NORMAL = 0U, /**< Command normal */
363 XMC_SDMMC_COMMAND_TYPE_SUSPEND, /**< Command suspend */
364 XMC_SDMMC_COMMAND_TYPE_RESUME, /**< Command resume */
365 XMC_SDMMC_COMMAND_TYPE_ABORT /**< Command abort */
366 } XMC_SDMMC_COMMAND_TYPE_t;
367
368 /**
369 * SDMMC transfer modes
370 */
371 typedef enum XMC_SDMMC_TRANSFER_MODE_TYPE
372 {
373 XMC_SDMMC_TRANSFER_MODE_TYPE_SINGLE = 0x00U, /**< Transfer mode type: single */
374 XMC_SDMMC_TRANSFER_MODE_TYPE_INFINITE = 0x20U, /**< Transfer mode type: infinite */
375 XMC_SDMMC_TRANSFER_MODE_TYPE_MULTIPLE = 0x22U, /**< Transfer mode type: multiple */
376 XMC_SDMMC_TRANSFER_MODE_TYPE_STOP_MULTIPLE = 0x22U /**< Transfer mode type: multiple stop */
377 } XMC_SDMMC_TRANSFER_MODE_TYPE_t;
378
379 /**
380 * Auto command transfer modes
381 */
382 typedef enum XMC_SDMMC_TRANSFER_MODE_AUTO_CMD
383 {
384 XMC_SDMMC_TRANSFER_MODE_AUTO_CMD_DISABLED = 0x00U, /**< ACMD mode disabled */
385 XMC_SDMMC_TRANSFER_MODE_AUTO_CMD_12 /**< ACMD12 mode */
386 } XMC_SDMMC_TRANSFER_MODE_AUTO_CMD_t;
387
388 /**
389 * SDMMC bus voltage level
390 */
391 typedef enum XMC_SDMMC_BUS_VOLTAGE
392 {
393 XMC_SDMMC_BUS_VOLTAGE_3_3_VOLTS = 0x07U /**< 3.3V */
394 } XMC_SDMMC_BUS_VOLTAGE_t;
395
396 /**
397 * Data line timeout counter values
398 */
399 typedef enum XMC_SDMMC_DAT_TIMEOUT_COUNTER
400 {
401 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_13 = 0U, /**< SDCLK * (2 ^ 13) */
402 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_14 = 1U, /**< SDCLK * (2 ^ 14) */
403 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_15 = 2U, /**< SDCLK * (2 ^ 15) */
404 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_16 = 3U, /**< SDCLK * (2 ^ 16) */
405 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_17 = 4U, /**< SDCLK * (2 ^ 17) */
406 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_18 = 5U, /**< SDCLK * (2 ^ 18) */
407 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_19 = 6U, /**< SDCLK * (2 ^ 19) */
408 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_20 = 7U, /**< SDCLK * (2 ^ 20) */
409 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_21 = 8U, /**< SDCLK * (2 ^ 21) */
410 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_22 = 9U, /**< SDCLK * (2 ^ 22) */
411 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_23 = 10U, /**< SDCLK * (2 ^ 23) */
412 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_24 = 11U, /**< SDCLK * (2 ^ 24) */
413 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_25 = 12U, /**< SDCLK * (2 ^ 25) */
414 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_26 = 13U, /**< SDCLK * (2 ^ 26) */
415 XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_27 = 14U, /**< SDCLK * (2 ^ 27) */
416 } XMC_SDMMC_DAT_TIMEOUT_COUNTER_t;
417
418 /**
419 * SDMMC data transfer direction
420 */
421 typedef enum XMC_SDMMC_DATA_TRANSFER_DIR
422 {
423 XMC_SDMMC_DATA_TRANSFER_HOST_TO_CARD = 0U, /**< Host to card */
424 XMC_SDMMC_DATA_TRANSFER_CARD_TO_HOST /**< Card to host */
425 } XMC_SDMMC_DATA_TRANSFER_DIR_t;
426
427 /**
428 * SDMMC card detection signal source
429 */
430 typedef enum XMC_SDMMC_CD_SOURCE
431 {
432 #if UC_SERIES == XMC45 || defined(DOXYGEN)
433 XMC_SDMMC_CD_SOURCE_PIN = 0 << SDMMC_HOST_CTRL_CARD_DET_SIGNAL_DETECT_Pos, /**< P1.10 input pin selected */
434 XMC_SDMMC_CD_SOURCE_SW = 1 << SDMMC_HOST_CTRL_CARD_DET_SIGNAL_DETECT_Pos /**< Software is selected */
435 #else
436 XMC_SDMMC_CD_SOURCE_PIN = 0 << SDMMC_CON_CDSEL_Pos, /**< P1.10 input pin selected */
437 XMC_SDMMC_CD_SOURCE_SW = 1 << SDMMC_CON_CDSEL_Pos /**< Software is selected */
438 #endif
439 } XMC_SDMMC_CD_SOURCE_t;
440
441 /**
442 * Used to set the SDMMC card detection status when the card detection status source input is set to software
443 */
444 typedef enum XMC_SDMMC_CD_STATUS
445 {
446 #if UC_SERIES == XMC45 || defined(DOXYGEN)
447 XMC_SDMMC_CD_STATUS_NO_CARD = 0 << SDMMC_HOST_CTRL_CARD_DETECT_TEST_LEVEL_Pos, /**< No card detected */
448 XMC_SDMMC_CD_STATUS_INSERTED = 1 << SDMMC_HOST_CTRL_CARD_DETECT_TEST_LEVEL_Pos /**< Card detected */
449 #else
450 XMC_SDMMC_CD_STATUS_NO_CARD = 0 << SDMMC_CON_CDSVAL_Pos, /**< No card detected */
451 XMC_SDMMC_CD_STATUS_INSERTED = 1 << SDMMC_CON_CDSVAL_Pos /**< Card detected */
452 #endif
453 } XMC_SDMMC_CD_STATUS_t;
454
455 #if UC_SERIES != XMC45 || defined(DOXYGEN)
456 /**
457 * SDMMC card write protection signal source
458 * @note Only available for XMC4300, XMC4800 and XMC4700 series
459 */
460 typedef enum XMC_SDMMC_WP_SOURCE
461 {
462 XMC_SDMMC_WP_SOURCE_PIN = 0 << SDMMC_CON_WPSEL_Pos, /**< P1.1 input pin selected */
463 XMC_SDMMC_WP_SOURCE_SW = 1 << SDMMC_CON_WPSEL_Pos /**< Software is selected */
464 } XMC_SDMMC_WP_SOURCE_t;
465
466 /**
467 * Used to set the SDMMC card protection status when the card protection status source input is set to software
468 * @note Only available for XMC4300, XMC4800 and XMC4700 series
469 */
470 typedef enum XMC_SDMMC_WP_STATUS
471 {
472 XMC_SDMMC_WP_STATUS_NO_WRITE_PROTECTION = 0 << SDMMC_CON_WPSVAL_Pos, /**< No write protection */
473 XMC_SDMMC_WP_STATUS_WRITE_PROTECTION = 1 << SDMMC_CON_WPSVAL_Pos /**< Write protection active */
474 } XMC_SDMMC_WP_STATUS_t;
475 #endif
476
477 /*******************************************************************************
478 * DATA STRUCTURES
479 *******************************************************************************/
480
481 /**
482 * SDMMC device structure <br>
483 *
484 * The structure represents a collection of all hardware registers used
485 * to configure the SDMMC peripheral on the XMC4500 microcontroller. The
486 * registers can be accessed with ::XMC_SDMMC.
487 */
488 typedef struct
489 {
490 __I uint32_t RESERVED0;
491 __IO uint16_t BLOCK_SIZE;
492 __IO uint16_t BLOCK_COUNT;
493 __IO uint32_t ARGUMENT1;
494 __IO uint16_t TRANSFER_MODE;
495 __IO uint16_t COMMAND;
496 __I uint32_t RESPONSE[4];
497 __IO uint32_t DATA_BUFFER;
498 __I uint32_t PRESENT_STATE;
499 __IO uint8_t HOST_CTRL;
500 __IO uint8_t POWER_CTRL;
501 __IO uint8_t BLOCK_GAP_CTRL;
502 __IO uint8_t WAKEUP_CTRL;
503 __IO uint16_t CLOCK_CTRL;
504 __IO uint8_t TIMEOUT_CTRL;
505 __IO uint8_t SW_RESET;
506 __IO uint16_t INT_STATUS_NORM;
507 __IO uint16_t INT_STATUS_ERR;
508 __IO uint16_t EN_INT_STATUS_NORM;
509 __IO uint16_t EN_INT_STATUS_ERR;
510 __IO uint16_t EN_INT_SIGNAL_NORM;
511 __IO uint16_t EN_INT_SIGNAL_ERR;
512 __I uint16_t ACMD_ERR_STATUS;
513 __I uint16_t RESERVED1[9];
514 __O uint16_t FORCE_EVENT_ACMD_ERR_STATUS;
515 __O uint16_t FORCE_EVENT_ERR_STATUS;
516 __I uint32_t RESERVED2[8];
517 __O uint32_t DEBUG_SEL;
518 __I uint32_t RESERVED3[30];
519 __IO uint32_t SPI;
520 __I uint32_t RESERVED4[2];
521 __I uint16_t SLOT_INT_STATUS;
522 } XMC_SDMMC_t;
523
524 /* Anonymous structure/union guard start */
525 #if defined (__CC_ARM)
526 #pragma push
527 #pragma anon_unions
528 #elif defined (__TASKING__)
529 #pragma warning 586
530 #endif
531
532 /**
533 * Present state of the SDMMC host controller <br>
534 *
535 * The structure presents a convenient way to obtain the SDMMC peripheral's
536 * present state information (for example, the write protect pin level). The
537 * XMC_SDMMC_GetPresentState() API can be used to populate the structure
538 * with the state of the SD host controller.
539 */
540 typedef union XMC_SDMMC_PRESENT_STATE
541 {
542 struct
543 {
544 uint32_t command_inihibit_cmd : 1; /**< Command: Inhibit command */
545 uint32_t command_inihibit_dat : 1; /**< Command: Inhibit data */
546 uint32_t dat_line_active : 1; /**< Data line active */
547 uint32_t : 5;
548 uint32_t write_transfer_active : 1; /**< Write transfer active */
549 uint32_t read_transfer_active : 1; /**< Read transfer active */
550 uint32_t buffer_write_enable : 1; /**< Buffer write enable */
551 uint32_t buffer_read_enable : 1; /**< Buffer read enable */
552 uint32_t : 4;
553 uint32_t card_inserted : 1; /**< Card inserted */
554 uint32_t card_state_stable : 1; /**< Card state stable */
555 uint32_t card_detect_pin_level : 1; /**< Card detect pin level */
556 uint32_t write_protect_pin_level : 1; /**< Write protect pin level */
557 uint32_t dat_3_0_pin_level : 4; /**< Data 3_0 pin level */
558 uint32_t cmd_line_level : 1; /**< Command line level */
559 uint32_t dat7_4_pin_level : 4; /**< Data 7_4 pin level */
560 uint32_t : 3;
561 };
562 uint32_t b32;
563 } XMC_SDMMC_PRESENT_STATE_t;
564
565 /**
566 * SDMMC transfer mode configuration
567 */
568 typedef struct XMC_SDMMC_TRANSFER_MODE
569 {
570 uint32_t block_size;
571 uint32_t num_blocks;
572 XMC_SDMMC_TRANSFER_MODE_TYPE_t type;
573 XMC_SDMMC_TRANSFER_MODE_AUTO_CMD_t auto_cmd;
574 XMC_SDMMC_DATA_TRANSFER_DIR_t direction;
575 } XMC_SDMMC_TRANSFER_MODE_t;
576
577 /**
578 * Represent an SDMMC command <br>
579 *
580 * The structure holds the configuration for an SDMMC command. The SDMMC
581 * COMMAND register is a 16-bit register which is responsible for enabling
582 * configuration parameters like command type, response type, index check
583 * enable (and a few more). Once SDMMC.COMMAND is configured, the
584 * XMC_SDMMC_SendCommand() function can be used to send the command.
585 */
586 typedef union XMC_SDMMC_COMMAND
587 {
588 struct
589 {
590 uint16_t response_type_sel : 2; /**< Response type select ::XMC_SDMMC_COMMAND_RESPONSE_t */
591 uint16_t : 1;
592 uint16_t crc_check_en : 1; /**< Command CRC check enable */
593 uint16_t index_check_en : 1; /**< Command index check enable */
594 uint16_t dat_present_sel : 1; /**< Data present select */
595 uint16_t cmd_type : 2; /**< Command type ::XMC_SDMMC_COMMAND_TYPE_t */
596 uint16_t cmd_index : 6; /**< Command index */
597 uint16_t : 2;
598 };
599 uint16_t cmd;
600 } XMC_SDMMC_COMMAND_t;
601
602 /* Anonymous structure/union guard end */
603 #if defined (__CC_ARM)
604 #pragma pop
605 #elif defined (__TASKING__)
606 #pragma warning restore
607 #endif
608
609 /**
610 * Card response structure
611 */
612 typedef struct XMC_SDMMC_RESPONSE
613 {
614 uint32_t response_0;
615 uint32_t response_2;
616 uint32_t response_4;
617 uint32_t response_6;
618 } XMC_SDMMC_RESPONSE_t;
619
620 /**
621 * SDMMC configuration data structure <br>
622 *
623 * The structure is used to configure the bus width and the clock divider.
624 */
625 typedef struct XMC_SDMMC_CONFIG
626 {
627 uint8_t bus_width; /**< SDMMC bus width */
628 XMC_SDMMC_SDCLK_FREQ_SEL_t clock_divider; /**< SDMMC clock divider */
629 } XMC_SDMMC_CONFIG_t;
630
631 /*******************************************************************************
632 * API PROTOTYPES
633 *******************************************************************************/
634
635 #ifdef __cplusplus
636 extern "C" {
637 #endif
638
639 /**
640 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
641 * @return bool
642 *
643 * \par<b>Description: </b><br>
644 * Get power status of the SDMMC peripheral <br>
645 *
646 * \par
647 * The function checks the SD_BUS_POWER bit-field of the POWER_CTRL register and returns
648 * a boolean value - "on" or "off".
649 */
650 bool XMC_SDMMC_GetPowerStatus(XMC_SDMMC_t *const sdmmc);
651
652 /**
653 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
654 * @return None
655 *
656 * \par<b>Description: </b><br>
657 * Enable SDMMC peripheral <br>
658 *
659 * \par
660 * The function de-asserts the peripheral reset. The peripheral needs to be initialized.
661 */
662 void XMC_SDMMC_Enable(XMC_SDMMC_t *const sdmmc);
663
664 /**
665 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
666 * @return None
667 *
668 * \par<b>Description: </b><br>
669 * Disable SDMMC peripheral <br>
670 *
671 * \par
672 * The function asserts the peripheral reset.
673 */
674 void XMC_SDMMC_Disable(XMC_SDMMC_t *const sdmmc);
675
676 /**
677 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
678 * @param config A pointer to a constant XMC_SDMMC_CONFIG_t structure containing the
679 * bus width and clock divider configuration
680 * @return ::XMC_SDMMC_STATUS_SUCCESS
681 *
682 * \par<b>Description: </b><br>
683 * Initialize the SDMMC peripheral <br>
684 *
685 * \par
686 * The function enables the SDMMC peripheral, sets the internal clock divider register
687 * and sets the bus width.
688 */
689 XMC_SDMMC_STATUS_t XMC_SDMMC_Init(XMC_SDMMC_t *const sdmmc, const XMC_SDMMC_CONFIG_t *config);
690
691 /**
692 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
693 * @param event A valid SDMMC event (XMC_SDMMC_EVENT_t) or a valid combination of
694 * logically OR'd events
695 * @return None
696 *
697 * \par<b>Description: </b><br>
698 * Enable SDMMC normal and error event(s) <br>
699 *
700 * \par
701 * The function first sets the bit-fields of EN_INT_STATUS_NORM and EN_INT_STATUS_ERR
702 * registers to enable interrupt status for requested normal/error SDMMC events. It then
703 * sets the bit-fields of EN_INT_SIGNAL_NORM and EN_INT_SIGNAL_ERR to enable the
704 * interrupt generation for the requested events.
705 */
706 void XMC_SDMMC_EnableEvent(XMC_SDMMC_t *const sdmmc, uint32_t event);
707
708 /**
709 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
710 * @param event A valid SDMMC event (XMC_SDMMC_EVENT_t) or a valid combination of
711 * logically OR'd events
712 * @return None
713 *
714 * \par<b>Description: </b><br>
715 * Disable normal and error SDMMC event(s) <br>
716 *
717 * \par
718 * The function disables the interrupt generation for the requested events by clearing
719 * the bit-fields of EN_INT_SIGNAL_NORM and EN_INT_SIGNAL_ERR registers.
720 *
721 * \par<b>Note:</b><br>
722 * The XMC_SDMMC_DisableEvent() function doesn't reset the the interrupt status. One
723 * may still use XMC_SDMMC_GetEvent() to check the status of requested events even if
724 * the interrupt generation is already disabled.
725 */
726 void XMC_SDMMC_DisableEvent(XMC_SDMMC_t *const sdmmc, uint32_t event);
727
728 /**
729 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
730 * @param event A valid SDMMC event (XMC_SDMMC_EVENT_t) or a valid combination of
731 * logically OR'd events
732 * @return None
733 *
734 * \par<b>Description: </b><br>
735 * Clear SDMMC event(s) <br>
736 *
737 * \par
738 * The function clears requested normal/error events by settings the bit-fields of
739 * the INT_STATUS register. Please check SDMMC_INT_STATUS_NORM in the XMC45000
740 * manual for more details.
741 */
742 void XMC_SDMMC_ClearEvent(XMC_SDMMC_t *const sdmmc, uint32_t event);
743
744 /**
745 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
746 * @param event A valid SDMMC event (XMC_SDMMC_EVENT_t)
747 * @return bool
748 *
749 * \par<b>Description: </b><br>
750 * Get SDMMC event status <br>
751 *
752 * \par
753 * The function returns the status of a single requested (normal/error) event by
754 * reading the appropriate bit-fields of the INT_STATUS register.
755 */
756 bool XMC_SDMMC_GetEvent(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_EVENT_t event);
757
758 /**
759 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
760 * @param event A valid SDMMC event (XMC_SDMMC_EVENT_t) or a valid combination of
761 * logically OR'd events
762 * @return None
763 *
764 * \par<b>Description: </b><br>
765 * Enable event status <br>
766 *
767 * \par
768 * The function sets the bit-fields of EN_INT_STATUS_NORM and EN_INT_STATUS_ERR
769 * registers to enable interrupt status for requested normal/error SDMMC events.
770 */
771 void XMC_SDMMC_EnableEventStatus(XMC_SDMMC_t *const sdmmc, uint32_t event);
772
773 /**
774 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
775 * @param event A valid SDMMC event (XMC_SDMMC_EVENT_t) or a valid combination of
776 * logically OR'd events
777 * @return None
778 *
779 * \par<b>Description: </b><br>
780 * Disable event status <br>
781 *
782 * \par
783 * The function resets the bit-fields of EN_INT_STATUS_NORM and EN_INT_STATUS_ERR
784 * registers to disable interrupt status for requested normal/error SDMMC events.
785 */
786 void XMC_SDMMC_DisableEventStatus(XMC_SDMMC_t *const sdmmc, uint32_t event);
787
788 /**
789 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
790 * @param event A valid SDMMC event (::XMC_SDMMC_EVENT_t) or a valid combination of
791 * logically OR'd events
792 * @return None
793 *
794 * \par<b>Description: </b><br>
795 * Trigger SDMMC error events <br>
796 *
797 * \par
798 * The SDMMC peripheral supports triggering of following error events: <br>
799 *
800 * ::XMC_SDMMC_CMD_TIMEOUT_ERR, ::XMC_SDMMC_CMD_CRC_ERR, ::XMC_SDMMC_CMD_END_BIT_ERR,
801 * ::XMC_SDMMC_CMD_IND_ERR, ::XMC_SDMMC_DATA_TIMEOUT_ERR, ::XMC_SDMMC_DATA_CRC_ERR,
802 * ::XMC_SDMMC_DATA_END_BIT_ERR, ::XMC_SDMMC_CURRENT_LIMIT_ERR, ::XMC_SDMMC_ACMD_ERR,
803 * ::XMC_SDMMC_TARGET_RESP_ERR
804 *
805 * For triggering Auto CMD12 error, see XMC_SDMMC_TriggerACMDErr()
806 */
XMC_SDMMC_TriggerEvent(XMC_SDMMC_t * const sdmmc,uint32_t event)807 __STATIC_INLINE void XMC_SDMMC_TriggerEvent(XMC_SDMMC_t *const sdmmc, uint32_t event)
808 {
809 XMC_ASSERT("XMC_SDMMC_TriggerEvent: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
810
811 sdmmc->FORCE_EVENT_ERR_STATUS |= (uint16_t)(event >> 16U);
812 }
813
814 /**
815 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
816 * @param source A valid SDMMC card detection signal source (::XMC_SDMMC_CD_SOURCE_t)
817 * @return None
818 *
819 * \par<b>Description: </b><br>
820 * Selects source for card detection
821 */
XMC_SDMMC_SetCardDetectionSource(XMC_SDMMC_t * const sdmmc,XMC_SDMMC_CD_SOURCE_t source)822 __STATIC_INLINE void XMC_SDMMC_SetCardDetectionSource(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_CD_SOURCE_t source)
823 {
824 XMC_ASSERT("XMC_SDMMC_SetCardDetectionSource: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
825
826 #if UC_SERIES == XMC45
827 sdmmc->HOST_CTRL |= (sdmmc->HOST_CTRL & (uint32_t)~SDMMC_HOST_CTRL_CARD_DET_SIGNAL_DETECT_Msk) | source;
828 #else
829 XMC_UNUSED_ARG(sdmmc);
830 *(uint32_t *)SDMMC_CON = (*(uint32_t *)SDMMC_CON & (uint32_t)~SDMMC_CON_CDSEL_Msk) | source;
831 #endif
832
833 }
834
835
836 /**
837 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
838 * @param status A valid SDMMC card detection status (::XMC_SDMMC_CD_STATUS_t)
839 * @return None
840 *
841 * \par<b>Description: </b><br>
842 * Sets the card detection status indicating whether card is inserted or not.
843 * Generates (card ins or card removal) interrupt when the normal interrupt is enabled.
844 * @note Only valid if SDMMC card detection signal source is set to XMC_SDMMC_CD_SOURCE_SW <br>
845 *
846 */
XMC_SDMMC_SetCardDetectionStatus(XMC_SDMMC_t * const sdmmc,XMC_SDMMC_CD_STATUS_t status)847 __STATIC_INLINE void XMC_SDMMC_SetCardDetectionStatus(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_CD_STATUS_t status)
848 {
849 XMC_ASSERT("XMC_SDMMC_SetCardDetectionStatus: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
850
851 #if UC_SERIES == XMC45
852 sdmmc->HOST_CTRL |= (sdmmc->HOST_CTRL & (uint32_t)~SDMMC_HOST_CTRL_CARD_DETECT_TEST_LEVEL_Msk) | status;
853 #else
854 XMC_UNUSED_ARG(sdmmc);
855 *(uint32_t *)SDMMC_CON = (*(uint32_t *)SDMMC_CON & (uint32_t)~SDMMC_CON_CDSVAL_Msk) | status;
856 #endif
857 }
858
859 #if (UC_SERIES != XMC45) || defined(DOXYGEN)
860 /**
861 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
862 * @param source A valid SDMMC card detection signal source (::XMC_SDMMC_WP_SOURCE_t)
863 * @return None
864 *
865 * \par<b>Description: </b><br>
866 * Selects input for card write protection status
867 */
XMC_SDMMC_SetWriteProtectionSource(XMC_SDMMC_t * const sdmmc,XMC_SDMMC_WP_SOURCE_t source)868 __STATIC_INLINE void XMC_SDMMC_SetWriteProtectionSource(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_WP_SOURCE_t source)
869 {
870 XMC_ASSERT("XMC_SDMMC_SetWriteProtectionSource: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
871 XMC_UNUSED_ARG(sdmmc);
872
873 #if UC_SERIES != XMC45
874 *(uint32_t *)SDMMC_CON = (*(uint32_t *)SDMMC_CON & (uint32_t)~SDMMC_CON_WPSEL_Msk) | source;
875 #endif
876 }
877
878 /**
879 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
880 * @param status A valid SDMMC card detection status (::XMC_SDMMC_WP_STATUS_t)
881 * @return None
882 *
883 * \par<b>Description: </b><br>
884 * Sets the card write protection status indicating whether card is write protected or not.
885 * @note Only valid if SDMMC card detection signal source is set to XMC_SDMMC_WP_SOURCE_SW <br>
886 *
887 */
XMC_SDMMC_SetWriteProtectionStatus(XMC_SDMMC_t * const sdmmc,XMC_SDMMC_WP_STATUS_t status)888 __STATIC_INLINE void XMC_SDMMC_SetWriteProtectionStatus(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_WP_STATUS_t status)
889 {
890 XMC_ASSERT("XMC_SDMMC_SetWriteProtectionStatus: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
891 XMC_UNUSED_ARG(sdmmc);
892
893 #if UC_SERIES != XMC45
894 *(uint32_t *)SDMMC_CON = (*(uint32_t *)SDMMC_CON & (uint32_t)~SDMMC_CON_WPSVAL_Msk) | status;
895 #endif
896 }
897 #endif
898
899 /**
900 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
901 * @return bool
902 *
903 * \par<b>Description: </b><br>
904 * Check if any error event has occured <br>
905 *
906 * \par
907 * The function can typically be used for writing an error interrupt recovery routine.
908 * Should any error be indicated (If XMC_SDMMC_IsAnyErrorEvent() returns true), the
909 * routine may then clear the event after indicating the error event and reset the
910 * SDMMC command and data lines.
911 */
XMC_SDMMC_IsAnyErrorEvent(XMC_SDMMC_t * const sdmmc)912 __STATIC_INLINE bool XMC_SDMMC_IsAnyErrorEvent(XMC_SDMMC_t *const sdmmc)
913 {
914 XMC_ASSERT("XMC_SDMMC_IsAnyErrorEvent: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
915
916 return (bool)(sdmmc->INT_STATUS_ERR);
917 }
918
919 /**
920 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
921 * @param event A valid SDMMC wakeup event (::XMC_SDMMC_WAKEUP_EVENT_t) or a valid combination
922 * of logically OR'd wakeup events
923 * @return None
924 *
925 * \par<b>Description: </b><br>
926 * Enable wakeup event(s) <br>
927 *
928 * \par
929 * The function enables SDMMC wakeup events by setting appropriate bit-fields of the WAKEUP_CTRL
930 * register. <br>
931 *
932 * List of supported wakeup events -> Wakeup on: <br>
933 * 1) Card interrupt <br>
934 * 2) SD card insertion <br>
935 * 3) SD card removal <br>
936 */
XMC_SDMMC_EnableWakeupEvent(XMC_SDMMC_t * const sdmmc,uint32_t event)937 __STATIC_INLINE void XMC_SDMMC_EnableWakeupEvent(XMC_SDMMC_t *const sdmmc, uint32_t event)
938 {
939 XMC_ASSERT("XMC_SDMMC_EnableWakeupEvent: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
940
941 sdmmc->WAKEUP_CTRL |= (uint8_t)event;
942 }
943
944 /**
945 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
946 * @param event A valid SDMMC wakeup event (::XMC_SDMMC_WAKEUP_EVENT_t) or a valid combination
947 * of logically OR'd wakeup events
948 * @return None
949 *
950 * \par<b>Description: </b><br>
951 * Disable wakeup event(s) <br>
952 *
953 * \par
954 * The function disables SDMMC wakeup events by clearing appropriate bit-fields of the WAKEUP_CTRL
955 * register. <br>
956 *
957 * List of supported wakeup events -> Wakeup on: <br>
958 * 1) Card interrupt <br>
959 * 2) SD card insertion <br>
960 * 3) SD card removal <br>
961 */
XMC_SDMMC_DisableWakeupEvent(XMC_SDMMC_t * const sdmmc,uint32_t event)962 __STATIC_INLINE void XMC_SDMMC_DisableWakeupEvent(XMC_SDMMC_t *const sdmmc, uint32_t event)
963 {
964 XMC_ASSERT("XMC_SDMMC_DisableWakeupEvent: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
965
966 sdmmc->WAKEUP_CTRL &= (uint8_t)~event;
967 }
968
969 /**
970 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
971 * @param error A valid SDMMC ACMD error (::XMC_SDMMC_ACMD_ERR_t)
972 * @return bool
973 *
974 * \par<b>Description: </b><br>
975 * Get status of Auto CMD12 errors <br>
976 *
977 * \par
978 * The function detects the presence of an Auto CMD12 error. A boolean is returned to
979 * indicate if an error is detected.
980 */
XMC_SDMMC_GetACMDErrStatus(XMC_SDMMC_t * const sdmmc,XMC_SDMMC_ACMD_ERR_t error)981 __STATIC_INLINE bool XMC_SDMMC_GetACMDErrStatus(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_ACMD_ERR_t error)
982 {
983 XMC_ASSERT("XMC_SDMMC_GetACMDErrStatus: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
984 XMC_ASSERT("XMC_SDMMC_GetACMDErrStatus: Invalid ACMD response error", XMC_SDMMC_CHECK_ACMD_ERR(error));
985
986 return (bool)(sdmmc->ACMD_ERR_STATUS & (uint16_t)error);
987 }
988
989 /**
990 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
991 * @param error A valid SDMMC ACMD error (::XMC_SDMMC_ACMD_ERR_t) or a valid combination
992 * of logically OR'd ACMD error events
993 * @return None
994 *
995 * \par<b>Description: </b><br>
996 * Triggers Auto CMD12 error(s) <br>
997 *
998 * \par
999 * This function triggers Auto CMD12 error(s) by setting appropriate bit-fields of the
1000 * FORCE_EVENT_ACMD_ERR_STATUS register.
1001 *
1002 * \par<b>Related APIs: </b><br>
1003 * XMC_SDMMC_TriggerEvent()
1004 */
XMC_SDMMC_TriggerACMDErr(XMC_SDMMC_t * const sdmmc,uint32_t error)1005 __STATIC_INLINE void XMC_SDMMC_TriggerACMDErr(XMC_SDMMC_t *const sdmmc, uint32_t error)
1006 {
1007 XMC_ASSERT("XMC_SDMMC_TriggerACMDErr: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1008
1009 sdmmc->FORCE_EVENT_ACMD_ERR_STATUS |= (uint16_t)error;
1010 }
1011
1012 /**
1013 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1014 * @return uint32_t The value held in the SDMMC FIFO
1015 *
1016 * \par<b>Description: </b><br>
1017 * Use this function to read a single word (32 bits) from the SDMMC FIFO. <br>
1018 */
XMC_SDMMC_ReadFIFO(XMC_SDMMC_t * const sdmmc)1019 __STATIC_INLINE uint32_t XMC_SDMMC_ReadFIFO(XMC_SDMMC_t *const sdmmc)
1020 {
1021 XMC_ASSERT("XMC_SDMMC_ReadFIFO: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1022
1023 return (sdmmc->DATA_BUFFER);
1024 }
1025
1026 /**
1027 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1028 * @param data Pointer to a data word (32 bits) that needs to be written to the FIFO
1029 * @return None
1030 *
1031 * \par<b>Description: </b><br>
1032 * Use this function to write a single word (32 bits) to the SDMMC FIFO. <br>
1033 */
XMC_SDMMC_WriteFIFO(XMC_SDMMC_t * const sdmmc,uint32_t * data)1034 __STATIC_INLINE void XMC_SDMMC_WriteFIFO(XMC_SDMMC_t *const sdmmc, uint32_t *data)
1035 {
1036 XMC_ASSERT("XMC_SDMMC_WriteFIFO: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1037
1038 sdmmc->DATA_BUFFER = *data;
1039 }
1040
1041 /**
1042 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1043 * @return None
1044 *
1045 * \par<b>Description: </b><br>
1046 * Enable SDMMC bus power <br>
1047 *
1048 * \par
1049 * The function sets the SD_BUS_POWER bit-field in the POWER_CTRL register, enabling the
1050 * bus power. It may be invoked after enabling the SD clock (XMC_SDMMC_SDClockEnable()).
1051 */
XMC_SDMMC_BusPowerOn(XMC_SDMMC_t * const sdmmc)1052 __STATIC_INLINE void XMC_SDMMC_BusPowerOn(XMC_SDMMC_t *const sdmmc)
1053 {
1054 XMC_ASSERT("XMC_SDMMC_BusPowerOn: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1055
1056 sdmmc->POWER_CTRL |= (uint8_t)(SDMMC_POWER_CTRL_SD_BUS_POWER_Msk);
1057 }
1058
1059 /**
1060 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1061 * @return None
1062 *
1063 * \par<b>Description: </b><br>
1064 * Disable SDMMC bus power <br>
1065 *
1066 * \par
1067 * The function resets the SD_BUS_POWER bit-field in the POWER_CTRL register, disabling the
1068 * bus power.
1069 */
XMC_SDMMC_BusPowerOff(XMC_SDMMC_t * const sdmmc)1070 __STATIC_INLINE void XMC_SDMMC_BusPowerOff(XMC_SDMMC_t *const sdmmc)
1071 {
1072 XMC_ASSERT("XMC_SDMMC_BusPowerOff: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1073
1074 sdmmc->POWER_CTRL &= (uint8_t)~SDMMC_POWER_CTRL_SD_BUS_POWER_Msk;
1075 }
1076
1077 /**
1078 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1079 * @return None
1080 *
1081 * \par<b>Description: </b><br>
1082 * Enable the internal SDMMC clock <br>
1083 *
1084 * \par
1085 * The function enables the internal clock of the SDMMC peripheral. To check if the
1086 * clock is stable, use XMC_SDMMC_GetClockStability().
1087 *
1088 * \par<b>Note: </b><br>
1089 * Invoke XMC_SDMMC_Init() before using this function.
1090 */
XMC_SDMMC_Start(XMC_SDMMC_t * const sdmmc)1091 __STATIC_INLINE void XMC_SDMMC_Start(XMC_SDMMC_t *const sdmmc)
1092 {
1093 XMC_ASSERT("XMC_SDMMC_Start: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1094
1095 /* Enable internal clock */
1096 sdmmc->CLOCK_CTRL |= (uint16_t)SDMMC_CLOCK_CTRL_INTERNAL_CLOCK_EN_Msk;
1097 }
1098
1099 /**
1100 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1101 * @return bool
1102 *
1103 * \par<b>Description: </b><br>
1104 * Check internal clock stability <br>
1105 *
1106 * \par
1107 * Use this function to check the internal SDMMC clock stability. The function returns a
1108 * boolean value indicating internal clock stability (true = stable)
1109 */
XMC_SDMMC_GetClockStability(XMC_SDMMC_t * const sdmmc)1110 __STATIC_INLINE bool XMC_SDMMC_GetClockStability(XMC_SDMMC_t *const sdmmc)
1111 {
1112 XMC_ASSERT("XMC_SDMMC_GetClockStability: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1113
1114 /* Return clock stability */
1115 return (bool)(sdmmc->CLOCK_CTRL & SDMMC_CLOCK_CTRL_INTERNAL_CLOCK_STABLE_Msk);
1116 }
1117
1118 /**
1119 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1120 * @return None
1121 *
1122 * \par<b>Description: </b><br>
1123 * Disable internal SDMMC clock <br>
1124 *
1125 * \par
1126 * The function disables the internal clock of the SDMMC peripheral. The SDMMC registers
1127 * can still be read and written even if the internal clock is disabled.
1128 */
XMC_SDMMC_Stop(XMC_SDMMC_t * const sdmmc)1129 __STATIC_INLINE void XMC_SDMMC_Stop(XMC_SDMMC_t *const sdmmc)
1130 {
1131 XMC_ASSERT("XMC_SDMMC_Stop: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1132
1133 sdmmc->CLOCK_CTRL &= (uint16_t)~SDMMC_CLOCK_CTRL_INTERNAL_CLOCK_EN_Msk;
1134 }
1135
1136 /**
1137 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1138 * @return None
1139 *
1140 * \par<b>Description: </b><br>
1141 * Enable the SD clock <br>
1142 *
1143 * \par
1144 * The function sets the SDCLOCK_EN bit-field of the CLOCK_CTRL register, enabling the
1145 * SD clock. It can be invoked after the internal clock has achieved stability. SD card
1146 * initialization process may then follow.
1147 */
XMC_SDMMC_SDClockEnable(XMC_SDMMC_t * const sdmmc)1148 __STATIC_INLINE void XMC_SDMMC_SDClockEnable(XMC_SDMMC_t *const sdmmc)
1149 {
1150 XMC_ASSERT("XMC_SDMMC_SDClockEnable: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1151
1152 sdmmc->CLOCK_CTRL |= (uint16_t)SDMMC_CLOCK_CTRL_SDCLOCK_EN_Msk;
1153 }
1154
1155 /**
1156 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1157 * @return None
1158 *
1159 * \par<b>Description: </b><br>
1160 * Disable the SD clock <br>
1161 *
1162 * \par
1163 * The function resets the SDCLOCK_EN bit-field of the CLOCK_CTRL register, disabling the
1164 * SD clock. It can be used alongside a SD card information reset routine (if required).
1165 */
XMC_SDMMC_SDClockDisable(XMC_SDMMC_t * const sdmmc)1166 __STATIC_INLINE void XMC_SDMMC_SDClockDisable(XMC_SDMMC_t *const sdmmc)
1167 {
1168 XMC_ASSERT("XMC_SDMMC_SDClockDisable: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1169
1170 sdmmc->CLOCK_CTRL &= (uint16_t)~SDMMC_CLOCK_CTRL_SDCLOCK_EN_Msk;
1171 }
1172
1173 /**
1174 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1175 * @param reset_mode Reset mode or a bitwise combination of modes
1176 * @return None
1177 *
1178 * \par<b>Description: </b><br>
1179 * Set SDMMC software reset request <br>
1180 *
1181 * \par
1182 * The function sets in the SDMMC SW_RESET register: <br>
1183 * 1) bit 0 to reset all <br>
1184 * 2) bit 1 to reset CMD line <br>
1185 * 3) bit 2 reset DAT line <br>
1186 *
1187 * It is typically used to reset the SD HOST controller's registers.
1188 */
XMC_SDMMC_SetSWReset(XMC_SDMMC_t * const sdmmc,uint32_t reset_mode)1189 __STATIC_INLINE void XMC_SDMMC_SetSWReset(XMC_SDMMC_t *const sdmmc, uint32_t reset_mode)
1190 {
1191 XMC_ASSERT("XMC_SDMMC_SetSWReset: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1192
1193 sdmmc->SW_RESET |= (uint8_t)reset_mode;
1194 }
1195
1196 /**
1197 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1198 * @return Software reset status
1199 *
1200 * \par<b>Description: </b><br>
1201 * Get SDMMC software reset status <br>
1202 *
1203 * \par
1204 * The SD host takes some time to reset its registers after invoking XMC_SDMMC_SetSWReset().
1205 * Since XMC_SDMMC_SetSWReset() is a non-blocking function, XMC_SDMMC_GetSWResetStatus() has
1206 * been provided to check the software reset status. The return value needs to be masked
1207 * with the reset mode (XMC_SDMMC_SW_RESET_t) to get a specific software reset status value.
1208 */
XMC_SDMMC_GetSWResetStatus(XMC_SDMMC_t * const sdmmc)1209 __STATIC_INLINE uint32_t XMC_SDMMC_GetSWResetStatus(XMC_SDMMC_t *const sdmmc)
1210 {
1211 XMC_ASSERT("XMC_SDMMC_GetSWResetStatus: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1212
1213 return (uint32_t)(sdmmc->SW_RESET);
1214 }
1215
1216 /**
1217 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1218 * @return XMC_SDMMC_PRESENT_STATE_t A structure storing the present state of the host controller
1219 *
1220 * \par<b>Description: </b><br>
1221 * Get the present state of the SDMMC host controller <br>
1222 *
1223 * \par
1224 * Get the values of each bit-field in SDMMC_PRESENT_STATE register
1225 * The function call populates an instance of the XMC_SDMMC_PRESENT_STATE_t structure with
1226 * the state of the SD host controller and returns it to the caller.
1227 */
XMC_SDMMC_GetPresentState(const XMC_SDMMC_t * const sdmmc)1228 __STATIC_INLINE XMC_SDMMC_PRESENT_STATE_t XMC_SDMMC_GetPresentState(const XMC_SDMMC_t *const sdmmc)
1229 {
1230 XMC_SDMMC_PRESENT_STATE_t result;
1231
1232 XMC_ASSERT("XMC_SDMMC_GetPresentState: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1233
1234 result.b32 = (uint32_t)sdmmc->PRESENT_STATE;
1235
1236 return result;
1237 }
1238
1239 /**
1240 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1241 * @return bool SDMMC command line status
1242 *
1243 * \par<b>Description: </b><br>
1244 * Check if the command line is busy <br>
1245 *
1246 * \par
1247 * The function reads the SDMMC PRESENT_STATE register and returns "true" if the command
1248 * line is busy ("false" otherwise). The command line must be free before sending an SDMMC
1249 * command with XMC_SDMMC_SendCommand().
1250 */
XMC_SDMMC_IsCommandLineBusy(XMC_SDMMC_t * const sdmmc)1251 __STATIC_INLINE bool XMC_SDMMC_IsCommandLineBusy(XMC_SDMMC_t *const sdmmc)
1252 {
1253 XMC_ASSERT("XMC_SDMMC_IsCommandLineBusy: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1254
1255 return (bool)(sdmmc->PRESENT_STATE & SDMMC_PRESENT_STATE_COMMAND_INHIBIT_CMD_Msk);
1256 }
1257
1258 /**
1259 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1260 * @return bool SDMMC data line status
1261 *
1262 * \par<b>Description: </b><br>
1263 * Check if the data line is busy <br>
1264 *
1265 * \par
1266 * The function reads the SDMMC PRESENT_STATE register and returns "true" if the data
1267 * line is busy ("false" otherwise). The data line must be free before sending an SDMMC
1268 * command with XMC_SDMMC_SendCommand().
1269 */
XMC_SDMMC_IsDataLineBusy(XMC_SDMMC_t * const sdmmc)1270 __STATIC_INLINE bool XMC_SDMMC_IsDataLineBusy(XMC_SDMMC_t *const sdmmc)
1271 {
1272 XMC_ASSERT("XMC_SDMMC_IsDataLineBusy: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1273
1274 return (bool)(sdmmc->PRESENT_STATE & SDMMC_PRESENT_STATE_COMMAND_INHIBIT_DAT_Msk);
1275 }
1276
1277 /**
1278 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1279 * @return bool Status of all data lines
1280 *
1281 * \par<b>Description: </b><br>
1282 * Check if all data line are high <br>
1283 *
1284 * \par
1285 * The function reads the SDMMC PRESENT_STATE register and returns "true" if all data
1286 * lines are high. It can be used to handle SDMMC error conditions. For example, if an
1287 * error event (XMC_SDMMC_IsAnyErrorEvent()) is detected and all data lines are high,
1288 * the user code can conclude that the error is of a "recoverable" type.
1289 */
XMC_SDMMC_IsAllDataLinesHigh(XMC_SDMMC_t * const sdmmc)1290 __STATIC_INLINE bool XMC_SDMMC_IsAllDataLinesHigh(XMC_SDMMC_t *const sdmmc)
1291 {
1292 XMC_ASSERT("XMC_SDMMC_IsAllDataLinesHigh: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1293
1294 return ((((sdmmc->PRESENT_STATE & SDMMC_PRESENT_STATE_DAT_3_0_PIN_LEVEL_Msk) >>
1295 SDMMC_PRESENT_STATE_DAT_3_0_PIN_LEVEL_Pos) == 0x0FU) ? true : false);
1296 }
1297
1298 /**
1299 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1300 * @param command A pointer to a constant of type XMC_SDMMC_COMMAND_t, pointing to the command configuration
1301 * @param arg Command argument
1302 * @return ::XMC_SDMMC_STATUS_SUCCESS
1303 *
1304 * \par<b>Description: </b><br>
1305 * Send normal SDMMC command <br>
1306 *
1307 * \par
1308 * Use this function to send a normal SDMMC command. This non-blocking function sets the
1309 * ARGUMENT1 and COMMAND registers. It is the user's responsibility to check if the command
1310 * and data lines are busy (XMC_SDMMC_IsDataLineBusy(), XMC_SDMMC_IsCommandLineBusy()).
1311 */
1312 XMC_SDMMC_STATUS_t XMC_SDMMC_SendCommand(XMC_SDMMC_t *const sdmmc, const XMC_SDMMC_COMMAND_t *command, uint32_t arg);
1313
1314 /**
1315 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1316 * @return uint32_t SDMMC command response
1317 *
1318 * \par<b>Description: </b><br>
1319 * Get card response (no Auto command) <br>
1320 *
1321 * \par
1322 * This function returns [39:8] bits of the card response. The others are checked automatically
1323 * by the peripheral. This function can be used with response type R1, R1b, R3, R4, R5, R5b, R6
1324 * but it doesn't support the retrieving of R1 of Auto CMD 23 and R1b of Auto CMD 12. To get
1325 * these responses, use XMC_SDMMC_GetAutoCommandResponse().
1326 */
XMC_SDMMC_GetCommandResponse(XMC_SDMMC_t * const sdmmc)1327 __STATIC_INLINE uint32_t XMC_SDMMC_GetCommandResponse(XMC_SDMMC_t *const sdmmc)
1328 {
1329 XMC_ASSERT("XMC_SDMMC_GetCommandResponse: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1330
1331 return (sdmmc->RESPONSE[0]);
1332 }
1333
1334 /**
1335 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1336 * @return uint32_t Auto command response value
1337 *
1338 * \par<b>Description: </b><br>
1339 * Get card response of Auto commands <br>
1340 *
1341 * \par
1342 * This function returns card response [39:8] bits of auto commands: R1 of Auto CMD 23 and
1343 * R1b of Auto CMD 12.
1344 */
XMC_SDMMC_GetAutoCommandResponse(const XMC_SDMMC_t * const sdmmc)1345 __STATIC_INLINE uint32_t XMC_SDMMC_GetAutoCommandResponse(const XMC_SDMMC_t *const sdmmc)
1346 {
1347 XMC_ASSERT("XMC_SDMMC_GetAutoCommandResponse: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1348
1349 return (sdmmc->RESPONSE[3]);
1350 }
1351
1352 /**
1353 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1354 * @param response Pointer to structure type XMC_SDMMC_RESPONSE_t to store the full response
1355 * @return None
1356 *
1357 * \par<b>Description: </b><br>
1358 * Get card R2 response <br>
1359 *
1360 * \par
1361 * The R2 response is 120 bits wide. The function reads all peripheral registers and store in
1362 * the response data structure.
1363 */
1364 void XMC_SDMMC_GetR2Response(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_RESPONSE_t *const response);
1365
1366 /**
1367 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1368 * @param transfer_mode Transfer mode configuration
1369 * @return None
1370 *
1371 * \par<b>Description: </b><br>
1372 * Configure data transfer mode <br>
1373 *
1374 * \par
1375 * The function configures block size, block count, type of data transfer, response type
1376 * and sets the auto command configuration. Use this function to configure a multi-block
1377 * SDMMC transfer.
1378 */
1379 void XMC_SDMMC_SetDataTransferMode(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_TRANSFER_MODE_t *const transfer_mode);
1380
1381 /**
1382 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1383 * @return uint32_t Number of blocks that need to be transferred
1384 *
1385 * \par<b>Description: </b><br>
1386 * Get the number of blocks that need to be transferred <br>
1387 *
1388 * \par
1389 * This function is valid only for multiple block transfers. The host controller
1390 * decrements the block count after each block transfer and stops when the count reaches
1391 * zero. It can only be accessed when no transaction is happening (i.e after a transaction
1392 * has stopped). This function returns an invalid value during the transfer. <br>
1393 *
1394 * When saving transfer context as a result of the suspend command, the number of blocks
1395 * yet to be transferred can be determined by using this function.
1396 */
XMC_SDMMC_GetTransferBlocksNum(XMC_SDMMC_t * const sdmmc)1397 __STATIC_INLINE uint32_t XMC_SDMMC_GetTransferBlocksNum(XMC_SDMMC_t *const sdmmc)
1398 {
1399 XMC_ASSERT("XMC_SDMMC_GetTransferBlocksNum: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1400
1401 return (uint32_t)(sdmmc->BLOCK_COUNT);
1402 }
1403
1404 /**
1405 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1406 * @param enabled "true" to enable read wait control, "false" to disable read wait control.
1407 * @return None
1408 *
1409 * \par<b>Description: </b><br>
1410 * Configure read wait control <br>
1411 *
1412 * \par
1413 * The read wait function is optional for SDIO cards. If the card supports read wait and
1414 * XMC_SDMMC_GetTransferBlocksNum() is executed, the SDMMC peripheral will stop read data
1415 * using DAT[2] line. If this feature is not enabled the peripheral has to stop the SD
1416 * clock to hold read data, restricting commands generation. <br>
1417 *
1418 * When the host driver detects an SD card insertion, it sets this bit according to the
1419 * CCCR of the SDIO card. If the card does not support read wait, this feature shall
1420 * never be enabled otherwise a DAT line conflict may occur. If this feature is disabled,
1421 * Suspend/Resume cannot be supported.
1422 */
XMC_SDMMC_SetReadWaitControl(XMC_SDMMC_t * const sdmmc,bool enabled)1423 __STATIC_INLINE void XMC_SDMMC_SetReadWaitControl(XMC_SDMMC_t *const sdmmc, bool enabled)
1424 {
1425 XMC_ASSERT("XMC_SDMMC_SetReadWaitControl: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1426
1427 sdmmc->BLOCK_GAP_CTRL = (uint8_t)((sdmmc->BLOCK_GAP_CTRL & (uint8_t)~SDMMC_BLOCK_GAP_CTRL_READ_WAIT_CTRL_Msk) |
1428 (uint8_t)((uint8_t)enabled << SDMMC_BLOCK_GAP_CTRL_READ_WAIT_CTRL_Pos));
1429 }
1430
1431 /**
1432 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1433 * @param enabled "true" to set stop at block gap, "false" for transfer
1434 * @return None
1435 *
1436 * \par<b>Description: </b><br>
1437 * Stop at block gap request <br>
1438 *
1439 * \par
1440 * The function is used to terminate a transaction execution at the next block gap for
1441 * non-DMA transfers.
1442 */
XMC_SDMMC_SetStopAtBlockGap(XMC_SDMMC_t * const sdmmc,bool enabled)1443 __STATIC_INLINE void XMC_SDMMC_SetStopAtBlockGap(XMC_SDMMC_t *const sdmmc, bool enabled)
1444 {
1445 XMC_ASSERT("XMC_SDMMC_SetStopAtBlockGap: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1446
1447 sdmmc->BLOCK_GAP_CTRL = (uint8_t)((sdmmc->BLOCK_GAP_CTRL & (uint8_t)~SDMMC_BLOCK_GAP_CTRL_STOP_AT_BLOCK_GAP_Msk) |
1448 (uint8_t)((uint8_t)enabled << SDMMC_BLOCK_GAP_CTRL_STOP_AT_BLOCK_GAP_Pos));
1449 }
1450
1451 /**
1452 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1453 * @param enabled "true" to restart transaction, "false" is ignored
1454 * @return None
1455 *
1456 * \par<b>Description: </b><br>
1457 * Issue a continue request <br>
1458 *
1459 * \par
1460 * The function is used to restart a transaction which was stopped using the "Stop at
1461 * block gap" request. (XMC_SDMMC_SetStopAtBlockGap())
1462 */
XMC_SDMMC_SetContinueRequest(XMC_SDMMC_t * const sdmmc,bool enabled)1463 __STATIC_INLINE void XMC_SDMMC_SetContinueRequest(XMC_SDMMC_t *const sdmmc, bool enabled)
1464 {
1465 XMC_ASSERT("XMC_SDMMC_SetContinueRequest: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1466
1467 sdmmc->BLOCK_GAP_CTRL = ((sdmmc->BLOCK_GAP_CTRL & (uint8_t)~SDMMC_BLOCK_GAP_CTRL_CONTINUE_REQ_Msk) |
1468 (uint8_t)((uint8_t)enabled << SDMMC_BLOCK_GAP_CTRL_CONTINUE_REQ_Pos));
1469 }
1470
1471 /**
1472 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1473 * @return bool
1474 *
1475 * \par<b>Description: </b><br>
1476 * Get continue request <br>
1477 *
1478 * \par
1479 * The function returns the status of the BLOCK_GAP_CTRL.CONTINUE_REQ bit-field. It
1480 * returns "true" if the transaction is restarted after a "stop at block gap" request.
1481 */
XMC_SDMMC_GetContinueRequest(XMC_SDMMC_t * const sdmmc)1482 __STATIC_INLINE bool XMC_SDMMC_GetContinueRequest(XMC_SDMMC_t *const sdmmc)
1483 {
1484 XMC_ASSERT("XMC_SDMMC_GetContinueRequest: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1485
1486 return (bool)(sdmmc->BLOCK_GAP_CTRL & (uint8_t)(1U << SDMMC_BLOCK_GAP_CTRL_CONTINUE_REQ_Pos));
1487 }
1488
1489 /**
1490 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1491 * @param config A pointer to the SDMMC configuration structure (::XMC_SDMMC_CONFIG_t)
1492 * @return None
1493 *
1494 * \par<b>Description: </b><br>
1495 * Enable interrupt at block gap <br>
1496 *
1497 * \par
1498 * The function sets the BLOCK_GAP_CTRL.INT_AT_BLOCK_GAP bit-field to enable interrupt
1499 * at block gap for a multi-block transfer. This bit is only valid in a 4-bit mode of
1500 * the SDIO card.
1501 */
XMC_SDMMC_EnableInterruptAtBlockGap(XMC_SDMMC_t * const sdmmc,const XMC_SDMMC_CONFIG_t * config)1502 __STATIC_INLINE void XMC_SDMMC_EnableInterruptAtBlockGap(XMC_SDMMC_t *const sdmmc, const XMC_SDMMC_CONFIG_t *config)
1503 {
1504 XMC_ASSERT("XMC_SDMMC_EnableInterruptAtBlockGap: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1505 XMC_ASSERT("XMC_SDMMC_EnableInterruptAtBlockGap: This operation is only valid in 4-bit mode",
1506 (config->bus_width == XMC_SDMMC_DATA_LINES_1));
1507
1508 XMC_UNUSED_ARG(config);
1509 sdmmc->BLOCK_GAP_CTRL |= (uint8_t)SDMMC_BLOCK_GAP_CTRL_INT_AT_BLOCK_GAP_Msk;
1510 }
1511
1512 /**
1513 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1514 * @param config A pointer to the SDMMC configuration structure (::XMC_SDMMC_CONFIG_t)
1515 * @return None
1516 *
1517 * \par<b>Description: </b><br>
1518 * Disable interrupt at block gap <br>
1519 *
1520 * \par
1521 * The function resets the BLOCK_GAP_CTRL.INT_AT_BLOCK_GAP bit-field to disable interrupt
1522 * at block gap. This bit is only valid in a 4-bit mode of the SDIO card.
1523 */
XMC_SDMMC_DisableInterruptAtBlockGap(XMC_SDMMC_t * const sdmmc,const XMC_SDMMC_CONFIG_t * config)1524 __STATIC_INLINE void XMC_SDMMC_DisableInterruptAtBlockGap(XMC_SDMMC_t *const sdmmc,
1525 const XMC_SDMMC_CONFIG_t *config)
1526
1527 {
1528 XMC_ASSERT("XMC_SDMMC_EnableInterruptAtBlockGap: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1529 XMC_ASSERT("XMC_SDMMC_EnableInterruptAtBlockGap: This operation is only valid in 4-bit mode",
1530 (config->bus_width == XMC_SDMMC_DATA_LINES_1));
1531
1532 XMC_UNUSED_ARG(config);
1533 sdmmc->BLOCK_GAP_CTRL &= (uint8_t)~SDMMC_BLOCK_GAP_CTRL_INT_AT_BLOCK_GAP_Msk;
1534 }
1535
1536 /**
1537 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1538 * @param clk Desired clock frequency (::XMC_SDMMC_SDCLK_FREQ_SEL_t)
1539 * @return None
1540 *
1541 * \par<b>Description: </b><br>
1542 * Set SD clock frequency <br>
1543 *
1544 * \par
1545 * The function sets the CLOCK_CTRL register to configure the frequency of the SD clock
1546 * pin. The register is programmed with the divisor of the base clock frequency (clk).
1547 *
1548 * The following settings are permitted (8-bit divided clock mode): <br>
1549 * 00H: base clock (10MHz->63MHz) <br>
1550 * 01H: base clock divided by 2 <br>
1551 * 10H: base clock divided by 32 <br>
1552 * 02H: base clock divided by 4 <br>
1553 * 04H: base clock divided by 8 <br>
1554 * 08H: base clock divided by 16 <br>
1555 * 20H: base clock divided by 64 <br>
1556 * 40H: base clock divided by 128 <br>
1557 * 80H: base clock divided by 256 <br>
1558 *
1559 * \par<b>Note: </b><br>
1560 * The internal clock should be disabled before updating frequency clock select. Please
1561 * see section 2.2.14 -> "Clock Control Register" in the SD HOST specification for more
1562 * information.
1563 */
XMC_SDMMC_SDClockFreqSelect(XMC_SDMMC_t * const sdmmc,XMC_SDMMC_SDCLK_FREQ_SEL_t clk)1564 __STATIC_INLINE void XMC_SDMMC_SDClockFreqSelect(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_SDCLK_FREQ_SEL_t clk)
1565 {
1566 XMC_ASSERT("XMC_SDMMC_SDClockFreqSelect: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1567 XMC_ASSERT("XMC_SDMMC_SDClockFreqSelect: Invalid clock frequency selection", XMC_SDMMC_CHECK_SDCLK_FREQ(clk));
1568
1569 sdmmc->CLOCK_CTRL = (uint16_t)((sdmmc->CLOCK_CTRL & (uint32_t)~SDMMC_CLOCK_CTRL_SDCLK_FREQ_SEL_Msk) |
1570 (uint32_t)(clk << SDMMC_CLOCK_CTRL_SDCLK_FREQ_SEL_Pos));
1571 }
1572
1573 /**
1574 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1575 * @param bus_voltage Desired bus voltage (::XMC_SDMMC_BUS_VOLTAGE_t)
1576 * @return None
1577 *
1578 * \par<b>Description: </b><br>
1579 * Set SDMMC bus voltage <br>
1580 *
1581 * \par
1582 * The function sets the CLOCK_CTRL register to configure the bus voltage. Currently,
1583 * 3.3 volts is the supported voltage level. This function is relevant within the host
1584 * controller initialization routine.
1585 */
XMC_SDMMC_SetBusVoltage(XMC_SDMMC_t * const sdmmc,XMC_SDMMC_BUS_VOLTAGE_t bus_voltage)1586 __STATIC_INLINE void XMC_SDMMC_SetBusVoltage(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_BUS_VOLTAGE_t bus_voltage)
1587 {
1588 XMC_ASSERT("XMC_SDMMC_SetBusVoltage: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1589 XMC_ASSERT("XMC_SDMMC_SetBusVoltage: Invalid bus voltage", XMC_SDMMC_CHECK_BUS_VOLTAGE(bus_voltage));
1590
1591 sdmmc->POWER_CTRL = (uint8_t)((sdmmc->POWER_CTRL & (uint32_t)~SDMMC_POWER_CTRL_SD_BUS_VOLTAGE_SEL_Msk) |
1592 (uint32_t)(bus_voltage << SDMMC_POWER_CTRL_SD_BUS_VOLTAGE_SEL_Pos));
1593 }
1594
1595 /**
1596 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1597 * @param timeout Data line timeout value
1598 * @return None
1599 *
1600 * \par<b>Description: </b><br>
1601 * Set data line timeout <br>
1602 *
1603 * \par
1604 * Use the function to set the interval by which the data line timeouts are detected. The
1605 * timeout clock frequency is generated by dividing the SD clock (TMCLK) by the timeout argument.
1606 * This function must be called before setting the bus voltage (XMC_SDMMC_SetBusVoltage()).
1607 */
XMC_SDMMC_SetDataLineTimeout(XMC_SDMMC_t * const sdmmc,XMC_SDMMC_DAT_TIMEOUT_COUNTER_t timeout)1608 __STATIC_INLINE void XMC_SDMMC_SetDataLineTimeout(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_DAT_TIMEOUT_COUNTER_t timeout)
1609 {
1610 XMC_ASSERT("XMC_SDMMC_SetDataLineTimeout: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1611 XMC_ASSERT("XMC_SDMMC_SetDataLineTimeout: Invalid timeout", XMC_SDMMC_CHECK_DAT_TIMEOUT_COUNTER(timeout));
1612
1613 sdmmc->TIMEOUT_CTRL = (uint8_t)((sdmmc->TIMEOUT_CTRL & (uint32_t)~SDMMC_TIMEOUT_CTRL_DAT_TIMEOUT_CNT_VAL_Msk) |
1614 (uint32_t)(timeout << SDMMC_TIMEOUT_CTRL_DAT_TIMEOUT_CNT_VAL_Pos));
1615 }
1616
1617 /**
1618 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1619 * @param lines Number of data lines to use (::XMC_SDMMC_DATA_LINES_t)
1620 * @return None
1621 *
1622 * \par<b>Description: </b><br>
1623 * Set data transfer width <br>
1624 *
1625 * \par
1626 * Use the function to set the data transfer width. Before using this function, an ACMD6
1627 * command (with R1 response type) must be sent to switch the bus width.
1628 */
XMC_SDMMC_SetDataTransferWidth(XMC_SDMMC_t * const sdmmc,XMC_SDMMC_DATA_LINES_t lines)1629 __STATIC_INLINE void XMC_SDMMC_SetDataTransferWidth(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_DATA_LINES_t lines)
1630 {
1631 XMC_ASSERT("XMC_SDMMC_SetDataTransferWidth: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1632 XMC_ASSERT("XMC_SDMMC_SetDataTransferWidth: Invalid no. of data lines", XMC_SDMMC_CHECK_DATA_LINES(lines));
1633
1634 sdmmc->HOST_CTRL &= (uint8_t)~(XMC_SDMMC_DATA_LINES_1 | XMC_SDMMC_DATA_LINES_4 | XMC_SDMMC_DATA_LINES_8);
1635 sdmmc->HOST_CTRL |= (uint8_t)lines;
1636 }
1637
1638 /**
1639 * @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
1640 * @param dir Transfer direction (::XMC_SDMMC_DATA_TRANSFER_DIR_t)
1641 * @return None
1642 *
1643 * \par<b>Description: </b><br>
1644 * Set data transfer direction <br>
1645 *
1646 * \par
1647 * Use the function to set the data transfer direction: host to card OR card to host. It
1648 * is typically used to configure block operations (read/write) on the SD card. For
1649 * example, XMC_SDMMC_DATA_TRANSFER_HOST_TO_CARD must be used for a write block operation.
1650 */
XMC_SDMMC_SetDataTransferDirection(XMC_SDMMC_t * const sdmmc,XMC_SDMMC_DATA_TRANSFER_DIR_t dir)1651 __STATIC_INLINE void XMC_SDMMC_SetDataTransferDirection(XMC_SDMMC_t *const sdmmc,
1652 XMC_SDMMC_DATA_TRANSFER_DIR_t dir)
1653 {
1654 XMC_ASSERT("XMC_SDMMC_SetDataTransferDirection: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1655 XMC_ASSERT("XMC_SDMMC_SetDataTransferDirection: Invalid direction", XMC_SDMMC_CHECK_DATA_TRANSFER_DIR(dir));
1656
1657 sdmmc->TRANSFER_MODE = (uint16_t)((sdmmc->TRANSFER_MODE & (uint16_t)~SDMMC_TRANSFER_MODE_TX_DIR_SELECT_Msk) |
1658 (uint16_t)((uint16_t)dir << SDMMC_TRANSFER_MODE_TX_DIR_SELECT_Pos));
1659 }
1660
1661 /**
1662 * @param None
1663 * @return None
1664 *
1665 * \par<b>Description: </b><br>
1666 * Enable delay on the command/data out lines <br>
1667 *
1668 * \par
1669 * Use the function to enable delay on the command/data out lines. Invoke this function
1670 * before selecting the number of delay elements.
1671 */
XMC_SDMMC_EnableDelayCmdDatLines(void)1672 __STATIC_INLINE void XMC_SDMMC_EnableDelayCmdDatLines(void)
1673 {
1674 SCU_GENERAL->SDMMCDEL |= (uint32_t)SCU_GENERAL_SDMMCDEL_TAPEN_Msk;
1675 }
1676
1677 /**
1678 * @param None
1679 * @return None
1680 *
1681 * \par<b>Description: </b><br>
1682 * Disable delay on the command/data out lines <br>
1683 *
1684 * \par
1685 * Use the function to disable delay on the command/data out lines.
1686 */
XMC_SDMMC_DisableDelayCmdDatLines(void)1687 __STATIC_INLINE void XMC_SDMMC_DisableDelayCmdDatLines(void)
1688 {
1689 SCU_GENERAL->SDMMCDEL &= (uint32_t)~SCU_GENERAL_SDMMCDEL_TAPEN_Msk;
1690 }
1691
1692 /**
1693 * @param tapdel Number of delay elements to select
1694 * @return None
1695 *
1696 * \par<b>Description: </b><br>
1697 * Set number of delay elements on the command/data out lines <br>
1698 *
1699 * \par
1700 * Use the function to set the number of delay elements on the command/data out lines.
1701 * The function writes the delay value to the SDMMC delay control register (SDMMCDEL)
1702 * within the realm of the SCU peripheral. A delay of tapdel + 1 is considered as the
1703 * final selected number of delay elements.
1704 */
XMC_SDMMC_SetDelay(uint8_t tapdel)1705 __STATIC_INLINE void XMC_SDMMC_SetDelay(uint8_t tapdel)
1706 {
1707 SCU_GENERAL->SDMMCDEL = (uint32_t)((SCU_GENERAL->SDMMCDEL & (uint32_t)~SCU_GENERAL_SDMMCDEL_TAPDEL_Msk) |
1708 (uint32_t)(tapdel << SCU_GENERAL_SDMMCDEL_TAPDEL_Pos));
1709 }
1710
1711 /**
1712 * @param None
1713 * @return None
1714 *
1715 * \par<b>Description: </b><br>
1716 * High speed enable <br>
1717 *
1718 * \par
1719 * Use the function to enable high speed operation. The default is a normal speed operation.
1720 * Once enabled, the host controller outputs command and data lines at the rising edge of the
1721 * SD clock (up to 50 MHz for SD).
1722 */
XMC_SDMMC_EnableHighSpeed(XMC_SDMMC_t * const sdmmc)1723 __STATIC_INLINE void XMC_SDMMC_EnableHighSpeed(XMC_SDMMC_t *const sdmmc)
1724 {
1725 XMC_ASSERT("XMC_SDMMC_EnableHighSpeed: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1726
1727 sdmmc->HOST_CTRL |= (uint8_t)SDMMC_HOST_CTRL_HIGH_SPEED_EN_Msk;
1728 }
1729
1730 /**
1731 * @param None
1732 * @return None
1733 *
1734 * \par<b>Description: </b><br>
1735 * High speed disable <br>
1736 *
1737 * \par
1738 * Use the function to disable high speed operation. The host controller will switch back
1739 * to a normal speed mode. In this mode, the host controller outputs command and data lines
1740 * at 25 MHz for SD.
1741 */
XMC_SDMMC_DisableHighSpeed(XMC_SDMMC_t * const sdmmc)1742 __STATIC_INLINE void XMC_SDMMC_DisableHighSpeed(XMC_SDMMC_t *const sdmmc)
1743 {
1744 XMC_ASSERT("XMC_SDMMC_DisableHighSpeed: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
1745
1746 sdmmc->HOST_CTRL &= (uint8_t)~SDMMC_HOST_CTRL_HIGH_SPEED_EN_Msk;
1747 }
1748
1749 #ifdef __cplusplus
1750 }
1751 #endif
1752
1753 /**
1754 * @}
1755 */
1756
1757 /**
1758 * @}
1759 */
1760
1761 #endif /* #if defined (SDMMC) */
1762
1763 #endif
1764