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