1 /*******************************************************************************
2 * File Name: cyhal_udb_sdio.c
3 *
4 * Description:
5 * Provides a high level interface for interacting with the Infineon UDB SDIO.
6 * This is a wrapper around the lower level UDB SDIO API.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
11 * an affiliate of Cypress Semiconductor Corporation
12 *
13 * SPDX-License-Identifier: Apache-2.0
14 *
15 * Licensed under the Apache License, Version 2.0 (the "License");
16 * you may not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 * http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS,
23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 *******************************************************************************/
27
28 /**
29 * \addtogroup group_hal_impl_udb_sdio UDB SDIO (Secure Digital Input Output)
30 * \ingroup group_hal_impl
31 * \{
32 * The UDB based SDIO interface allows for communicating between a CAT1 and a
33 * Cypress wireless device such as the CYW4343W, CYW43438, or CYW43012. This
34 * library allows CAT1 devices that do not have a dedicated SDHC hardware block,
35 * but do have UDBs, to work with the
36 * <a href="https://github.com/infineon/wifi-host-driver">Wi-Fi
37 * Host Driver (WHD)</a> library.
38 *
39 * \warning This library does not provide a complete SDIO implementation. It is
40 * only intended for use with a Infineon wireless device. Additionally, using this
41 * driver imposes a few system wide requirements, described below, that must be
42 * met to work properly.
43 *
44 * \section section_psoc6_udb_sdio_restrictions Restrictions
45 * The optimal configuration is to have ClkSlow & ClkPeri running at 100 MHz
46 * and for the SDIO to run at 25 MHz. For Infineon provided Board Support Packages
47 * (BSPs) that use this driver the necessary configuration is done automatically.
48 *
49 * To use this library, the following must be true:
50 * 1. ClkSlow & ClkPeri must both run at the same speed
51 * 2. ClkSlow & ClkPeri must run at 4x the desired SDIO speed
52 * 3. The first 8-bit peripheral clock divider must be reserved for use by this driver
53 * 4. The following DMA channels must be reserved for use by this driver
54 * * DataWire 0 channel 0
55 * * DataWire 0 channel 1
56 * * DataWire 1 channel 1
57 * * DataWire 1 channel 3
58 *
59 * \} group_hal_impl_udb_sdio
60 */
61
62 #include "cyhal_hwmgr.h"
63 #include "cy_utils.h"
64
65 #if (CYHAL_DRIVER_AVAILABLE_SDIO) && defined(CYHAL_UDB_SDIO)
66
67 #if defined(__cplusplus)
68 extern "C"
69 {
70 #endif
71
72 #include <stdlib.h>
73 #include "SDIO_HOST_cfg.h"
74 #include "cyhal_utils.h"
75 #include "cyhal_irq_impl.h"
76 #include "cyhal_sdio.h"
77 #include "cyhal_gpio.h"
78 #include "cyhal_interconnect.h"
79 #include "cyhal_syspm.h"
80 #include "cyhal_clock.h"
81
82 #define _CY_HAL_SDIO_CLK_DIV_VALUE ((uint8_t) 0xFF)
83
84 /* Not configured clock divider define*/
85 #define _CY_HAL_SDIO_CLK_DIV_NC ((cy_en_divider_types_t) _CY_HAL_SDIO_CLK_DIV_VALUE)
86
87 /* Define for default SDIO frequency */
88 #define _CY_HAL_SDIO_DEF_FREQ (400000U)
89
90 /* The 64b block transition mode define */
91 #define _CY_HAL_SDIO_64B (64u)
92
93 /* The 1 byte transition mode define */
94 #define _CY_HAL_SDIO_1B (1u)
95
96 /* Mask which indicates interface change */
97 #define _CYHAL_SDIO_INTERFACE_CHANGE_MASK ((uint32_t) ((uint32_t) CYHAL_SDIO_GOING_DOWN) | ((uint32_t) CYHAL_SDIO_COMING_UP))
98
99 #if !defined(CYHAL_SDIO_DS_CB_ORDER)
100 /* The order value for SDIO Deep Sleep callback */
101 #define CYHAL_SDIO_DS_CB_ORDER (0u)
102 #endif /* !defined(CYHAL_SDIO_DS_CB_ORDER) */
103
104 /* Callback pointers */
105 static cyhal_sdio_event_callback_t _cyhal_sdio_callback = NULL;
106 static cyhal_sdio_t *_cyhal_sdio_config_struct = NULL;
107 static void *_cyhal_sdio_callback_args = NULL;
108 static bool _cyhal_sdio_op_pending = false;
109
110 /*******************************************************************************
111 * (Internal) Configuration structures for SDIO pins
112 *******************************************************************************/
113 static const cy_stc_gpio_pin_config_t _cyhal_sdio_pin_config =
114 {
115 .outVal = 1,
116 .driveMode = CY_GPIO_DM_STRONG,
117 .hsiom = HSIOM_SEL_DSI_DSI, /* DSI controls 'out' and 'output enable' */
118 .intEdge = CY_GPIO_INTR_DISABLE,
119 .intMask = 0UL,
120 .vtrip = CY_GPIO_VTRIP_CMOS,
121 .slewRate = CY_GPIO_SLEW_FAST,
122 .driveSel = CY_GPIO_DRIVE_1_2,
123 .vregEn = 0UL,
124 .ibufMode = 0UL,
125 .vtripSel = 0UL,
126 .vrefSel = 0UL,
127 .vohSel = 0UL,
128 };
129
130 static const cy_stc_gpio_pin_config_t _cyhal_sdio_pin_clk_config =
131 {
132 .outVal = 1,
133 .driveMode = CY_GPIO_DM_STRONG_IN_OFF,
134 .hsiom = HSIOM_SEL_DSI_GPIO, /* DSI controls 'out', GPIO controls 'output enable' */
135 .intEdge = CY_GPIO_INTR_DISABLE,
136 .intMask = 0UL,
137 .vtrip = CY_GPIO_VTRIP_CMOS,
138 .slewRate = CY_GPIO_SLEW_FAST,
139 .driveSel = CY_GPIO_DRIVE_1_2,
140 .vregEn = 0UL,
141 .ibufMode = 0UL,
142 .vtripSel = 0UL,
143 .vrefSel = 0UL,
144 .vohSel = 0UL,
145 };
146
147 /*******************************************************************************
148 * Internal functions
149 *******************************************************************************/
150
151 /* Internal deep sleep callback, which does following:
152 * 1. Save/restore not retained configuration registers in the Deep Sleep
153 * 2. Execute registered callback with CYHAL_SDIO_GOING_DOWN event, before
154 * entering into Deep Sleep
155 * 3. Execute registered callback with CYHAL_SDIO_COMING_UP event, after
156 * exit from Deep Sleep
157 * */
_cyhal_sdio_ds_callback(cyhal_syspm_callback_state_t state,cyhal_syspm_callback_mode_t mode,void * callback_arg)158 static bool _cyhal_sdio_ds_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
159 {
160 static cy_stc_syspm_callback_params_t cyhal_sdio_pm_callback_params = { NULL, NULL };
161 bool allow = true;
162 cyhal_sdio_t *obj = (cyhal_sdio_t *)callback_arg;
163 CY_ASSERT(obj != NULL);
164
165 if(state == CYHAL_SYSPM_CB_CPU_DEEPSLEEP)
166 {
167 allow = (SDIO_DeepSleepCallback(&cyhal_sdio_pm_callback_params, _cyhal_utils_convert_haltopdl_pm_mode(mode)) == CY_SYSPM_SUCCESS);
168 }
169
170 if (allow)
171 {
172 switch (mode)
173 {
174 case CYHAL_SYSPM_CHECK_READY:
175 {
176 /* Check if transfer is pending */
177 allow = !_cyhal_sdio_op_pending;
178 if (allow)
179 {
180 /* Execute callback to indicate that interface is going down */
181 if ((_cyhal_sdio_callback != NULL) && (0U != (_cyhal_sdio_config_struct->events & (uint32_t) CYHAL_SDIO_GOING_DOWN)))
182 {
183 (void)(_cyhal_sdio_callback)(_cyhal_sdio_callback_args, CYHAL_SDIO_GOING_DOWN);
184 }
185
186 /* Indicate Deep Sleep entering */
187 obj->pm_transition_pending = true;
188 }
189
190 break;
191 }
192
193 case CYHAL_SYSPM_BEFORE_TRANSITION:
194 case CYHAL_SYSPM_AFTER_DS_WFI_TRANSITION:
195 {
196 /* Nothing to do */
197 break;
198 }
199
200 case CYHAL_SYSPM_AFTER_TRANSITION:
201 case CYHAL_SYSPM_CHECK_FAIL:
202 {
203 /* Execute this only if check ready case was executed */
204 if (obj->pm_transition_pending)
205 {
206 /* Execute callback to indicate that interface is coming up */
207 if ((_cyhal_sdio_callback != NULL) && (0U != (_cyhal_sdio_config_struct->events & (uint32_t) CYHAL_SDIO_COMING_UP)))
208 {
209 (void)(_cyhal_sdio_callback)(_cyhal_sdio_callback_args, CYHAL_SDIO_COMING_UP);
210 }
211
212 /* Indicate PM mode transition exit */
213 obj->pm_transition_pending = false;
214 }
215 break;
216 }
217
218 default:
219 CY_ASSERT(false);
220 break;
221 }
222 }
223 return allow;
224 }
225
226
227 /*******************************************************************************
228 * Dispatcher Interrupt Callbacks Service Routine
229 *******************************************************************************/
_cyhal_sdio_interrupts_dispatcher_IRQHandler(void)230 static void _cyhal_sdio_interrupts_dispatcher_IRQHandler(void)
231 {
232 /* Only CYHAL_SDIO_CARD_INTERRUPT event can be registered and executed */
233 if ((_cyhal_sdio_callback != NULL) && (_cyhal_sdio_config_struct->irq_cause != 0U))
234 {
235 (void)(_cyhal_sdio_callback)(_cyhal_sdio_callback_args, CYHAL_SDIO_CARD_INTERRUPT);
236 }
237 }
238
_cyhal_sdio_configure_pin(cyhal_gpio_t pin,cyhal_gpio_t * pin_ref,const cy_stc_gpio_pin_config_t * cfg)239 static cy_rslt_t _cyhal_sdio_configure_pin(
240 cyhal_gpio_t pin, cyhal_gpio_t *pin_ref, const cy_stc_gpio_pin_config_t* cfg)
241 {
242 cyhal_resource_inst_t pinRsc = _cyhal_utils_get_gpio_resource(pin);
243 cy_rslt_t result = cyhal_hwmgr_reserve(&pinRsc);
244 if (result == CY_RSLT_SUCCESS)
245 {
246 *pin_ref = pin;
247 Cy_GPIO_Pin_Init(CYHAL_GET_PORTADDR(pin), CYHAL_GET_PIN(pin), cfg);
248 }
249 return result;
250 }
251
cyhal_sdio_init(cyhal_sdio_t * obj,cyhal_gpio_t cmd,cyhal_gpio_t clk,cyhal_gpio_t data0,cyhal_gpio_t data1,cyhal_gpio_t data2,cyhal_gpio_t data3)252 cy_rslt_t cyhal_sdio_init(cyhal_sdio_t *obj, cyhal_gpio_t cmd, cyhal_gpio_t clk, cyhal_gpio_t data0, cyhal_gpio_t data1, cyhal_gpio_t data2, cyhal_gpio_t data3)
253 {
254 CY_ASSERT(NULL != obj);
255
256 /* If something goes wrong, any resource not marked as invalid will be freed.
257 * We explicitly mark unallocated resources as invalid to prevent freeing
258 * them.
259 *
260 * Before we reserve UDB at all we need try to reserve clock divider, then
261 * DMAs and pins. If all these resources are reserved only then reserve UDB
262 * SDIO.
263 */
264 obj->resource.type = CYHAL_RSC_INVALID;
265 obj->pin_cmd = CYHAL_NC_PIN_VALUE;
266 obj->pin_clk = CYHAL_NC_PIN_VALUE;
267 obj->pin_data0 = CYHAL_NC_PIN_VALUE;
268 obj->pin_data1 = CYHAL_NC_PIN_VALUE;
269 obj->pin_data2 = CYHAL_NC_PIN_VALUE;
270 obj->pin_data3 = CYHAL_NC_PIN_VALUE;
271
272 cy_rslt_t retVal = SDIO_ReserveResources();
273
274 /* Reserve the clk, cmd & 4 data pins */
275 if (retVal == CY_RSLT_SUCCESS)
276 {
277 retVal = _cyhal_sdio_configure_pin(clk, &obj->pin_clk, &_cyhal_sdio_pin_clk_config);
278 }
279 if (retVal == CY_RSLT_SUCCESS)
280 {
281 retVal = _cyhal_sdio_configure_pin(cmd, &obj->pin_cmd, &_cyhal_sdio_pin_config);
282 }
283 if (retVal == CY_RSLT_SUCCESS)
284 {
285 retVal = _cyhal_sdio_configure_pin(data0, &obj->pin_data0, &_cyhal_sdio_pin_config);
286 }
287 if (retVal == CY_RSLT_SUCCESS)
288 {
289 retVal = _cyhal_sdio_configure_pin(data1, &obj->pin_data1, &_cyhal_sdio_pin_config);
290 }
291 if (retVal == CY_RSLT_SUCCESS)
292 {
293 retVal = _cyhal_sdio_configure_pin(data2, &obj->pin_data2, &_cyhal_sdio_pin_config);
294 }
295 if (retVal == CY_RSLT_SUCCESS)
296 {
297 retVal = _cyhal_sdio_configure_pin(data3, &obj->pin_data3, &_cyhal_sdio_pin_config);
298 }
299
300 /* Reserve UDB SDIO */
301 if (retVal == CY_RSLT_SUCCESS)
302 {
303 /* UDB SDIO resource */
304 cyhal_resource_inst_t udbRsc = { CYHAL_RSC_UDB, 0, 0 };
305
306 retVal = cyhal_hwmgr_reserve(&udbRsc);
307 if (retVal == CY_RSLT_SUCCESS)
308 {
309 /* Update SDIO object */
310 obj->resource.type = udbRsc.type;
311 obj->resource.block_num = udbRsc.block_num;
312 obj->resource.channel_num = udbRsc.channel_num;
313
314 /* Set default interrupt priority to default value */
315 _cyhal_irq_register(udb_interrupts_0_IRQn, CYHAL_ISR_PRIORITY_DEFAULT, SDIO_IRQ);
316 _cyhal_irq_enable(udb_interrupts_0_IRQn);
317
318 /* Setup write DMA interrupt handler */
319 _cyhal_irq_register(cpuss_interrupts_dw1_1_IRQn, CYHAL_ISR_PRIORITY_DEFAULT, SDIO_WRITE_DMA_IRQ);
320 _cyhal_irq_enable(cpuss_interrupts_dw1_1_IRQn);
321
322 /* Setup read DMA interrupt handler */
323 _cyhal_irq_register(cpuss_interrupts_dw1_3_IRQn, CYHAL_ISR_PRIORITY_DEFAULT, SDIO_READ_DMA_IRQ);
324 _cyhal_irq_enable(cpuss_interrupts_dw1_3_IRQn);
325
326 stc_sdio_irq_cb_t irq_cbs;
327 irq_cbs.pfnCardIntCb = _cyhal_sdio_interrupts_dispatcher_IRQHandler;
328
329 SDIO_Init(&irq_cbs);
330
331 /* SDIO_Init() configures the SDIO to 40 kHz */
332 obj->frequencyhal_hz = _CY_HAL_SDIO_DEF_FREQ;
333 obj->block_size = _CY_HAL_SDIO_64B;
334
335 /* Initialize interrupt cause and events */
336 obj->irq_cause = 0u;
337 obj->events = 0u;
338
339 obj->pm_transition_pending = false;
340
341 /* Register SDIO Deep Sleep Callback */
342 if (CY_RSLT_SUCCESS == retVal)
343 {
344 obj->pm_callback_data.callback = &_cyhal_sdio_ds_callback;
345 obj->pm_callback_data.states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_CPU_DEEPSLEEP_RAM | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE);
346 obj->pm_callback_data.next = NULL;
347 obj->pm_callback_data.args = obj;
348 /* The CYHAL_SYSPM_BEFORE_TRANSITION mode cannot be ignored because the PM handler
349 * calls the SDIO host driver callback that saves UDB state in this mode before transitioning.
350 */
351 obj->pm_callback_data.ignore_modes = (cyhal_syspm_callback_mode_t)0;
352
353 _cyhal_syspm_register_peripheral_callback(&obj->pm_callback_data);
354 }
355 }
356 }
357
358 if (retVal != CY_RSLT_SUCCESS)
359 {
360 cyhal_sdio_free(obj);
361 }
362
363 return retVal;
364 }
365
cyhal_sdio_free(cyhal_sdio_t * obj)366 void cyhal_sdio_free(cyhal_sdio_t *obj)
367 {
368 CY_ASSERT(NULL != obj);
369
370 _cyhal_irq_free(udb_interrupts_0_IRQn);
371 _cyhal_irq_free(cpuss_interrupts_dw1_1_IRQn);
372 _cyhal_irq_free(cpuss_interrupts_dw1_3_IRQn);
373
374 _cyhal_utils_release_if_used(&(obj->pin_clk));
375 _cyhal_utils_release_if_used(&(obj->pin_cmd));
376 _cyhal_utils_release_if_used(&(obj->pin_data0));
377 _cyhal_utils_release_if_used(&(obj->pin_data1));
378 _cyhal_utils_release_if_used(&(obj->pin_data2));
379 _cyhal_utils_release_if_used(&(obj->pin_data3));
380
381 if (obj->resource.type != CYHAL_RSC_INVALID)
382 {
383 cyhal_hwmgr_free(&(obj->resource));
384 }
385 SDIO_Free();
386
387 _cyhal_syspm_unregister_peripheral_callback(&obj->pm_callback_data);
388 }
389
cyhal_sdio_configure(cyhal_sdio_t * obj,const cyhal_sdio_cfg_t * config)390 cy_rslt_t cyhal_sdio_configure(cyhal_sdio_t *obj, const cyhal_sdio_cfg_t *config)
391 {
392 CY_ASSERT(NULL != obj);
393
394 /* Do not change frequency if requested value is zero */
395 if (config->frequencyhal_hz != 0)
396 {
397 SDIO_SetSdClkFrequency(config->frequencyhal_hz);
398 obj->frequencyhal_hz = config->frequencyhal_hz;
399 }
400
401 /* Do not change block size if requested value is zero */
402 if (config->block_size != 0)
403 {
404 SDIO_SetBlockSize((uint8_t)config->block_size);
405 obj->block_size = config->block_size;
406 }
407
408 return CY_RSLT_SUCCESS;
409 }
410
cyhal_sdio_host_send_cmd(cyhal_sdio_t * obj,cyhal_sdio_host_transfer_type_t direction,cyhal_sdio_host_command_t command,uint32_t argument,uint32_t * response)411 cy_rslt_t cyhal_sdio_host_send_cmd(cyhal_sdio_t *obj, cyhal_sdio_host_transfer_type_t direction, cyhal_sdio_host_command_t command, uint32_t argument, uint32_t* response)
412 {
413 CY_ASSERT(NULL != obj);
414 if (command == CYHAL_SDIO_CMD_IO_RW_EXTENDED)
415 {
416 return CYHAL_SDIO_RSLT_ERR_BAD_PARAM;
417 }
418
419 if (obj->pm_transition_pending)
420 {
421 return CYHAL_SDIO_RSLT_ERR_PM_PENDING;
422 }
423
424 uint32_t cmdResponse;
425 stc_sdio_cmd_t cmd;
426 cy_rslt_t retVal = CYHAL_SDIO_RSLT_CANCELED;
427
428 /* Check other pending operations */
429 if (!_cyhal_sdio_op_pending)
430 {
431 /* Indicate pending operation to prevent entering into Deep Sleep */
432 _cyhal_sdio_op_pending = true;
433
434 if (response != NULL)
435 {
436 *response = 0;
437 }
438
439 cmd.u32CmdIdx = (uint32_t) command;
440 cmd.u32Arg = argument;
441 cmd.pu32Response = &cmdResponse;
442 cmd.pu8Data = NULL; /* Not used */
443 cmd.bRead = (direction != CYHAL_SDIO_XFER_TYPE_READ) ? false : true;
444 cmd.u16BlockCnt = 0U; /* Not used */
445 cmd.u16BlockSize = 0U; /* Not used */
446
447 /* Send command only if there is no attempts to enter into Deep Sleep */
448 retVal = (Ok == SDIO_SendCommandAndWait(&cmd)) ? CY_RSLT_SUCCESS : CYHAL_SDIO_RSLT_ERR_COMMAND_SEND;
449
450 if (response != NULL)
451 {
452 *response = cmdResponse;
453 }
454
455
456 /* Indicate finished operation */
457 _cyhal_sdio_op_pending = false;
458 }
459
460 return retVal;
461 }
462
cyhal_sdio_host_bulk_transfer(cyhal_sdio_t * obj,cyhal_sdio_host_transfer_type_t direction,uint32_t argument,const uint32_t * data,uint16_t length,uint32_t * response)463 cy_rslt_t cyhal_sdio_host_bulk_transfer(cyhal_sdio_t *obj, cyhal_sdio_host_transfer_type_t direction, uint32_t argument, const uint32_t* data, uint16_t length, uint32_t* response)
464 {
465 CY_ASSERT(NULL != obj);
466 if (obj->pm_transition_pending)
467 {
468 return CYHAL_SDIO_RSLT_ERR_PM_PENDING;
469 }
470
471 cy_rslt_t retVal = CYHAL_SDIO_RSLT_CANCELED;
472
473 /* Check other pending operations */
474 if (!_cyhal_sdio_op_pending)
475 {
476 /* Indicate pending operation to prevent entering into Deep Sleep */
477 _cyhal_sdio_op_pending = true;
478 stc_sdio_cmd_t cmd;
479 uint32_t cmdResponse;
480
481 if (response != NULL)
482 {
483 *response = 0;
484 }
485
486 cmd.u32CmdIdx = (uint32_t) CYHAL_SDIO_CMD_IO_RW_EXTENDED;
487 cmd.u32Arg = argument;
488 cmd.pu32Response = &cmdResponse;
489
490 /* Note that this implementation uses 8b address */
491 cmd.pu8Data = (uint8_t *) data;
492 cmd.bRead = (direction != CYHAL_SDIO_XFER_TYPE_READ) ? false : true;
493
494 if (length >= obj->block_size)
495 {
496 cmd.u16BlockCnt = (uint16_t) ((length + obj->block_size - 1)/obj->block_size);
497 cmd.u16BlockSize = obj->block_size;
498 }
499 else
500 {
501 /* Data will be sent as one packet */
502 cmd.u16BlockCnt = _CY_HAL_SDIO_1B;
503 cmd.u16BlockSize = length;
504 }
505
506 retVal = (Ok == SDIO_SendCommandAndWait(&cmd)) ? CY_RSLT_SUCCESS : CYHAL_SDIO_RSLT_ERR_COMMAND_SEND;
507
508 if (response != NULL)
509 {
510 *response = cmdResponse;
511 }
512
513 /* Indicate finished transfer */
514 _cyhal_sdio_op_pending = false;
515 }
516
517 return retVal;
518 }
519
cyhal_sdio_host_transfer_async(cyhal_sdio_t * obj,cyhal_sdio_host_transfer_type_t direction,uint32_t argument,const uint32_t * data,uint16_t length)520 cy_rslt_t cyhal_sdio_host_transfer_async(cyhal_sdio_t *obj, cyhal_sdio_host_transfer_type_t direction, uint32_t argument, const uint32_t* data, uint16_t length)
521 {
522 /* UDB SDIO implementation does not support async transfers */
523
524 CY_UNUSED_PARAMETER(obj);
525 CY_ASSERT(NULL != obj);
526 /* Just add check to suppress warning about unused arguments */
527 if ((data == NULL) && (length == 0) && (argument == 0) && (direction == ((cyhal_sdio_transfer_type_t) 0x3)))
528 {
529 return CYHAL_SDIO_RSLT_ERR_BAD_PARAM;
530 }
531
532 return CYHAL_SDIO_RSLT_ERR_UNSUPPORTED;
533 }
534
cyhal_sdio_is_busy(const cyhal_sdio_t * obj)535 bool cyhal_sdio_is_busy(const cyhal_sdio_t *obj)
536 {
537 /* UDB SDIO does not support async transfers */
538 CY_UNUSED_PARAMETER(obj);
539 return false;
540 }
541
cyhal_sdio_abort_async(cyhal_sdio_t * obj)542 cy_rslt_t cyhal_sdio_abort_async(cyhal_sdio_t *obj)
543 {
544 /* Reset UDB SDIO */
545 CY_UNUSED_PARAMETER(obj);
546 SDIO_Reset();
547 return CY_RSLT_SUCCESS;
548 }
549
cyhal_sdio_register_callback(cyhal_sdio_t * obj,cyhal_sdio_event_callback_t callback,void * callback_arg)550 void cyhal_sdio_register_callback(cyhal_sdio_t *obj, cyhal_sdio_event_callback_t callback, void *callback_arg)
551 {
552 _cyhal_sdio_config_struct = obj;
553 _cyhal_sdio_callback = callback;
554 _cyhal_sdio_callback_args = callback_arg;
555 }
556
cyhal_sdio_enable_event(cyhal_sdio_t * obj,cyhal_sdio_event_t event,uint8_t intr_priority,bool enable)557 void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_event_t event, uint8_t intr_priority, bool enable)
558 {
559 /* Only CYHAL_SDIO_CARD_INTERRUPT event can be registered */
560 if (event == CYHAL_SDIO_CARD_INTERRUPT)
561 {
562 if (enable)
563 {
564 obj->irq_cause = event;
565
566 if (_cyhal_sdio_config_struct != NULL)
567 {
568 _cyhal_sdio_config_struct->irq_cause = event;
569 }
570
571 SDIO_EnableChipInt();
572 }
573 else
574 {
575 obj->irq_cause = 0U;
576
577 if (_cyhal_sdio_config_struct != NULL)
578 {
579 _cyhal_sdio_config_struct->irq_cause = 0U;
580 }
581
582 SDIO_DisableChipInt();
583 }
584 }
585
586 /* Enable/disable non-interrupt based event */
587 if (0u != ((uint32_t) event & _CYHAL_SDIO_INTERFACE_CHANGE_MASK))
588 {
589 if (enable)
590 {
591 obj->events |= (uint32_t) event;
592 }
593 else
594 {
595 obj->events &= (uint32_t) ~((uint32_t) event);
596 }
597
598 _cyhal_sdio_config_struct->events = obj->events;
599 }
600
601 _cyhal_irq_set_priority(udb_interrupts_0_IRQn, intr_priority);
602 }
603
cyhal_sdio_host_set_io_voltage(cyhal_sdio_t * obj,cyhal_gpio_t io_volt_sel,cyhal_sdio_host_io_voltage_t io_voltage,cyhal_sdio_host_io_volt_action_type_t io_switch_type)604 cy_rslt_t cyhal_sdio_host_set_io_voltage(cyhal_sdio_t *obj, cyhal_gpio_t io_volt_sel, cyhal_sdio_host_io_voltage_t io_voltage,
605 cyhal_sdio_host_io_volt_action_type_t io_switch_type)
606 {
607 /* UDB SDIO Does not support IO voltage switch */
608 CY_UNUSED_PARAMETER(obj);
609 CY_UNUSED_PARAMETER(io_volt_sel);
610 CY_UNUSED_PARAMETER(io_voltage);
611 CY_UNUSED_PARAMETER(io_switch_type);
612 return CYHAL_SDIO_RSLT_ERR_UNSUPPORTED;
613 }
614
cyhal_sdio_init_cfg(cyhal_sdio_t * obj,const cyhal_sdio_configurator_t * cfg)615 cy_rslt_t cyhal_sdio_init_cfg(cyhal_sdio_t *obj, const cyhal_sdio_configurator_t *cfg)
616 {
617 /* Configurator initialization is not supported on UDB-based SDIO */
618 CY_UNUSED_PARAMETER(obj);
619 CY_UNUSED_PARAMETER(cfg);
620 return CYHAL_SDIO_RSLT_ERR_UNSUPPORTED;
621 }
622
623 #if defined(__cplusplus)
624 }
625 #endif
626
627 #endif /* (CYHAL_DRIVER_AVAILABLE_SDIO) && defined(CYHAL_UDB_SDIO) */
628