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