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     if ((cmd == NC) ||
273         (clk == NC) ||
274         (data0 == NC) ||
275         (data1 == NC) ||
276         (data2 == NC) ||
277         (data3 == NC))
278     {
279         return CYHAL_SDIO_RSLT_ERR_BAD_PARAM;
280     }
281 
282     cy_rslt_t retVal = SDIO_ReserveResources();
283 
284     /* Reserve the clk, cmd & 4 data pins */
285     if (retVal == CY_RSLT_SUCCESS)
286     {
287         retVal = _cyhal_sdio_configure_pin(clk, &obj->pin_clk, &_cyhal_sdio_pin_clk_config);
288     }
289     if (retVal == CY_RSLT_SUCCESS)
290     {
291         retVal = _cyhal_sdio_configure_pin(cmd, &obj->pin_cmd, &_cyhal_sdio_pin_config);
292     }
293     if (retVal == CY_RSLT_SUCCESS)
294     {
295         retVal = _cyhal_sdio_configure_pin(data0, &obj->pin_data0, &_cyhal_sdio_pin_config);
296     }
297     if (retVal == CY_RSLT_SUCCESS)
298     {
299         retVal = _cyhal_sdio_configure_pin(data1, &obj->pin_data1, &_cyhal_sdio_pin_config);
300     }
301     if (retVal == CY_RSLT_SUCCESS)
302     {
303         retVal = _cyhal_sdio_configure_pin(data2, &obj->pin_data2, &_cyhal_sdio_pin_config);
304     }
305     if (retVal == CY_RSLT_SUCCESS)
306     {
307         retVal = _cyhal_sdio_configure_pin(data3, &obj->pin_data3, &_cyhal_sdio_pin_config);
308     }
309 
310     /* Reserve UDB SDIO */
311     if (retVal == CY_RSLT_SUCCESS)
312     {
313         /* UDB SDIO resource */
314         cyhal_resource_inst_t udbRsc = { CYHAL_RSC_UDB, 0, 0 };
315 
316         retVal = cyhal_hwmgr_reserve(&udbRsc);
317         if (retVal == CY_RSLT_SUCCESS)
318         {
319             /* Update SDIO object */
320             obj->resource.type = udbRsc.type;
321             obj->resource.block_num = udbRsc.block_num;
322             obj->resource.channel_num = udbRsc.channel_num;
323 
324             /* Set default interrupt priority to default value */
325             _cyhal_irq_register(udb_interrupts_0_IRQn, CYHAL_ISR_PRIORITY_DEFAULT, SDIO_IRQ);
326             _cyhal_irq_enable(udb_interrupts_0_IRQn);
327 
328             /* Setup write DMA interrupt handler */
329             _cyhal_irq_register(cpuss_interrupts_dw1_1_IRQn, CYHAL_ISR_PRIORITY_DEFAULT, SDIO_WRITE_DMA_IRQ);
330             _cyhal_irq_enable(cpuss_interrupts_dw1_1_IRQn);
331 
332             /* Setup read DMA interrupt handler */
333             _cyhal_irq_register(cpuss_interrupts_dw1_3_IRQn, CYHAL_ISR_PRIORITY_DEFAULT, SDIO_READ_DMA_IRQ);
334             _cyhal_irq_enable(cpuss_interrupts_dw1_3_IRQn);
335 
336             stc_sdio_irq_cb_t   irq_cbs;
337             irq_cbs.pfnCardIntCb = _cyhal_sdio_interrupts_dispatcher_IRQHandler;
338 
339             SDIO_Init(&irq_cbs);
340 
341             /* SDIO_Init() configures the SDIO to 40 kHz */
342             obj->frequencyhal_hz = _CY_HAL_SDIO_DEF_FREQ;
343             obj->block_size   = _CY_HAL_SDIO_64B;
344 
345             /* Initialize interrupt cause and events */
346             obj->irq_cause = 0u;
347             obj->events = 0u;
348 
349             obj->pm_transition_pending = false;
350 
351             /* Register SDIO Deep Sleep Callback */
352             if (CY_RSLT_SUCCESS == retVal)
353             {
354                 obj->pm_callback_data.callback = &_cyhal_sdio_ds_callback;
355                 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);
356                 obj->pm_callback_data.next = NULL;
357                 obj->pm_callback_data.args = obj;
358                 /* The CYHAL_SYSPM_BEFORE_TRANSITION mode cannot be ignored because the PM handler
359                  * calls the SDIO host driver callback that saves UDB state in this mode before transitioning.
360                  */
361                 obj->pm_callback_data.ignore_modes = (cyhal_syspm_callback_mode_t)0;
362 
363                 _cyhal_syspm_register_peripheral_callback(&obj->pm_callback_data);
364             }
365         }
366     }
367 
368     if (retVal != CY_RSLT_SUCCESS)
369     {
370         cyhal_sdio_free(obj);
371     }
372 
373     return retVal;
374 }
375 
cyhal_sdio_free(cyhal_sdio_t * obj)376 void cyhal_sdio_free(cyhal_sdio_t *obj)
377 {
378     CY_ASSERT(NULL != obj);
379 
380     _cyhal_irq_free(udb_interrupts_0_IRQn);
381     _cyhal_irq_free(cpuss_interrupts_dw1_1_IRQn);
382     _cyhal_irq_free(cpuss_interrupts_dw1_3_IRQn);
383 
384     _cyhal_utils_release_if_used(&(obj->pin_clk));
385     _cyhal_utils_release_if_used(&(obj->pin_cmd));
386     _cyhal_utils_release_if_used(&(obj->pin_data0));
387     _cyhal_utils_release_if_used(&(obj->pin_data1));
388     _cyhal_utils_release_if_used(&(obj->pin_data2));
389     _cyhal_utils_release_if_used(&(obj->pin_data3));
390 
391     if (obj->resource.type != CYHAL_RSC_INVALID)
392     {
393         cyhal_hwmgr_free(&(obj->resource));
394     }
395     SDIO_Free();
396 
397     _cyhal_syspm_unregister_peripheral_callback(&obj->pm_callback_data);
398 }
399 
cyhal_sdio_configure(cyhal_sdio_t * obj,const cyhal_sdio_cfg_t * config)400 cy_rslt_t cyhal_sdio_configure(cyhal_sdio_t *obj, const cyhal_sdio_cfg_t *config)
401 {
402     CY_ASSERT(NULL != obj);
403 
404     /* Do not change frequency if requested value is zero */
405     if (config->frequencyhal_hz != 0)
406     {
407         SDIO_SetSdClkFrequency(config->frequencyhal_hz);
408         obj->frequencyhal_hz = config->frequencyhal_hz;
409     }
410 
411     /* Do not change block size if requested value is zero */
412     if (config->block_size != 0)
413     {
414         SDIO_SetBlockSize((uint8_t)config->block_size);
415         obj->block_size   = config->block_size;
416     }
417 
418     return CY_RSLT_SUCCESS;
419 }
420 
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)421 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)
422 {
423     CY_ASSERT(NULL != obj);
424     if (command == CYHAL_SDIO_CMD_IO_RW_EXTENDED)
425     {
426         return CYHAL_SDIO_RSLT_ERR_BAD_PARAM;
427     }
428 
429     if (obj->pm_transition_pending)
430     {
431         return CYHAL_SDIO_RSLT_ERR_PM_PENDING;
432     }
433 
434     uint32_t cmdResponse;
435     stc_sdio_cmd_t cmd;
436     cy_rslt_t retVal = CYHAL_SDIO_RSLT_CANCELED;
437 
438     /* Check other pending operations */
439     if (!_cyhal_sdio_op_pending)
440     {
441         /* Indicate pending operation to prevent entering into Deep Sleep */
442         _cyhal_sdio_op_pending = true;
443 
444         if (response != NULL)
445         {
446             *response = 0;
447         }
448 
449         cmd.u32CmdIdx = (uint32_t) command;
450         cmd.u32Arg = argument;
451         cmd.pu32Response = &cmdResponse;
452         cmd.pu8Data = NULL;              /* Not used */
453         cmd.bRead = (direction != CYHAL_SDIO_XFER_TYPE_READ) ? false : true;
454         cmd.u16BlockCnt = 0U;            /* Not used */
455         cmd.u16BlockSize = 0U;           /* Not used */
456 
457         /* Send command only if there is no attempts to enter into Deep Sleep */
458         retVal = (Ok == SDIO_SendCommandAndWait(&cmd)) ? CY_RSLT_SUCCESS : CYHAL_SDIO_RSLT_ERR_COMMAND_SEND;
459 
460         if (response != NULL)
461         {
462             *response = cmdResponse;
463         }
464 
465 
466         /*  Indicate finished operation */
467         _cyhal_sdio_op_pending = false;
468     }
469 
470     return retVal;
471 }
472 
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)473 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)
474 {
475     CY_ASSERT(NULL != obj);
476     if (obj->pm_transition_pending)
477     {
478         return CYHAL_SDIO_RSLT_ERR_PM_PENDING;
479     }
480 
481     cy_rslt_t retVal = CYHAL_SDIO_RSLT_CANCELED;
482 
483     /* Check other pending operations */
484     if (!_cyhal_sdio_op_pending)
485     {
486         /* Indicate pending operation to prevent entering into Deep Sleep */
487         _cyhal_sdio_op_pending = true;
488         stc_sdio_cmd_t cmd;
489         uint32_t cmdResponse;
490 
491         if (response != NULL)
492         {
493             *response = 0;
494         }
495 
496         cmd.u32CmdIdx = (uint32_t) CYHAL_SDIO_CMD_IO_RW_EXTENDED;
497         cmd.u32Arg = argument;
498         cmd.pu32Response = &cmdResponse;
499 
500         /* Note that this implementation uses 8b address */
501         cmd.pu8Data = (uint8_t *) data;
502         cmd.bRead = (direction != CYHAL_SDIO_XFER_TYPE_READ) ? false : true;
503 
504         if (length >= obj->block_size)
505         {
506             cmd.u16BlockCnt = (uint16_t) ((length + obj->block_size - 1)/obj->block_size);
507             cmd.u16BlockSize = obj->block_size;
508         }
509         else
510         {
511             /* Data will be sent as one packet */
512             cmd.u16BlockCnt = _CY_HAL_SDIO_1B;
513             cmd.u16BlockSize = length;
514         }
515 
516         retVal = (Ok == SDIO_SendCommandAndWait(&cmd)) ? CY_RSLT_SUCCESS : CYHAL_SDIO_RSLT_ERR_COMMAND_SEND;
517 
518         if (response != NULL)
519         {
520             *response = cmdResponse;
521         }
522 
523         /*  Indicate finished transfer */
524         _cyhal_sdio_op_pending = false;
525     }
526 
527     return retVal;
528 }
529 
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)530 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)
531 {
532     /* UDB SDIO implementation does not support async transfers */
533 
534     CY_UNUSED_PARAMETER(obj);
535     CY_ASSERT(NULL != obj);
536     /* Just add check to suppress warning about unused arguments */
537     if ((data == NULL) && (length == 0) && (argument == 0) && (direction == ((cyhal_sdio_transfer_type_t) 0x3)))
538     {
539         return CYHAL_SDIO_RSLT_ERR_BAD_PARAM;
540     }
541 
542     return CYHAL_SDIO_RSLT_ERR_UNSUPPORTED;
543 }
544 
cyhal_sdio_is_busy(const cyhal_sdio_t * obj)545 bool cyhal_sdio_is_busy(const cyhal_sdio_t *obj)
546 {
547     /* UDB SDIO does not support async transfers */
548     CY_UNUSED_PARAMETER(obj);
549     return false;
550 }
551 
cyhal_sdio_abort_async(cyhal_sdio_t * obj)552 cy_rslt_t cyhal_sdio_abort_async(cyhal_sdio_t *obj)
553 {
554     /* Reset UDB SDIO */
555     CY_UNUSED_PARAMETER(obj);
556     SDIO_Reset();
557     return CY_RSLT_SUCCESS;
558 }
559 
cyhal_sdio_register_callback(cyhal_sdio_t * obj,cyhal_sdio_event_callback_t callback,void * callback_arg)560 void cyhal_sdio_register_callback(cyhal_sdio_t *obj, cyhal_sdio_event_callback_t callback, void *callback_arg)
561 {
562     _cyhal_sdio_config_struct = obj;
563     _cyhal_sdio_callback      = callback;
564     _cyhal_sdio_callback_args = callback_arg;
565 }
566 
cyhal_sdio_enable_event(cyhal_sdio_t * obj,cyhal_sdio_event_t event,uint8_t intr_priority,bool enable)567 void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_event_t event, uint8_t intr_priority, bool enable)
568 {
569     /* Only CYHAL_SDIO_CARD_INTERRUPT event can be registered */
570     if (event == CYHAL_SDIO_CARD_INTERRUPT)
571     {
572         if (enable)
573         {
574             obj->irq_cause = event;
575 
576             if (_cyhal_sdio_config_struct != NULL)
577             {
578                 _cyhal_sdio_config_struct->irq_cause = event;
579             }
580 
581             SDIO_EnableChipInt();
582         }
583         else
584         {
585             obj->irq_cause = 0U;
586 
587             if (_cyhal_sdio_config_struct != NULL)
588             {
589                 _cyhal_sdio_config_struct->irq_cause = 0U;
590             }
591 
592             SDIO_DisableChipInt();
593         }
594     }
595 
596     /* Enable/disable non-interrupt based event */
597     if (0u != ((uint32_t) event & _CYHAL_SDIO_INTERFACE_CHANGE_MASK))
598     {
599         if (enable)
600         {
601             obj->events |= (uint32_t) event;
602         }
603         else
604         {
605             obj->events &= (uint32_t) ~((uint32_t) event);
606         }
607 
608         _cyhal_sdio_config_struct->events = obj->events;
609     }
610 
611     _cyhal_irq_set_priority(udb_interrupts_0_IRQn, intr_priority);
612 }
613 
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)614 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,
615                                     cyhal_sdio_host_io_volt_action_type_t io_switch_type)
616 {
617     /* UDB SDIO Does not support IO voltage switch */
618     CY_UNUSED_PARAMETER(obj);
619     CY_UNUSED_PARAMETER(io_volt_sel);
620     CY_UNUSED_PARAMETER(io_voltage);
621     CY_UNUSED_PARAMETER(io_switch_type);
622     return CYHAL_SDIO_RSLT_ERR_UNSUPPORTED;
623 }
624 
cyhal_sdio_init_cfg(cyhal_sdio_t * obj,const cyhal_sdio_configurator_t * cfg)625 cy_rslt_t cyhal_sdio_init_cfg(cyhal_sdio_t *obj, const cyhal_sdio_configurator_t *cfg)
626 {
627     /* Configurator initialization is not supported on UDB-based SDIO */
628     CY_UNUSED_PARAMETER(obj);
629     CY_UNUSED_PARAMETER(cfg);
630     return CYHAL_SDIO_RSLT_ERR_UNSUPPORTED;
631 }
632 
633 #if defined(__cplusplus)
634 }
635 #endif
636 
637 #endif /* (CYHAL_DRIVER_AVAILABLE_SDIO) && defined(CYHAL_UDB_SDIO) */
638