1 /*
2 * Copyright 2021 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_os_abstraction.h"
9 #include "fsl_debug_console.h"
10 #include "fsl_adapter_sdu.h"
11
12 /*******************************************************************************
13 * Definitions
14 ******************************************************************************/
15 #define os_InterruptMaskClear(irq_num) DisableIRQ(irq_num)
16 #define os_InterruptMaskSet(irq_num) EnableIRQ(irq_num)
17 #define os_ClearPendingISR(irq_num) NVIC_ClearPendingIRQ(irq_num)
18
19 #define SDU_TRANSFER_TASK_STACK_SIZE (1000U)
20
21 #define SDU_DEFAULT_BLOCK_SIZE (512U)
22
23 #define SDU_CMD_EVENT_BLOCK_COUNT (8U)
24 #define SDU_DATA_BLOCK_COUNT (8U)
25
26 #define SDU_BUFF_ALIGN (32U)
27 #define SDU_SIZE_ALIGN (32U)
28
29 #define SDU_SDIO_HDR_EXTRA (sizeof(sdio_header_t) + 4U)
30
31 #define SDU_ACTUAL_USE_PORT_NUM (1U)
32
33 #define SDU_MAX_CMD_BUFFER (2U)
34 #define SDU_CMD_BUFFER_SIZE (SDU_DEFAULT_BLOCK_SIZE * SDU_CMD_EVENT_BLOCK_COUNT)//(4096U + SDU_SDIO_HDR_EXTRA)
35
36 #define SDU_MAX_EVENT_BUFFER (2U)
37 #define SDU_EVENT_BUFFER_SIZE (SDU_DEFAULT_BLOCK_SIZE * SDU_CMD_EVENT_BLOCK_COUNT)//(4096U + SDU_SDIO_HDR_EXTRA)
38
39 #define SDU_MAX_DATA_BUFFER (SDU_PORT_MAX_TRANSFER * 16U * SDU_ACTUAL_USE_PORT_NUM)
40 #define SDU_DATA_BUFFER_SIZE (SDU_DEFAULT_BLOCK_SIZE * SDU_DATA_BLOCK_COUNT)//(4096U + SDU_SDIO_HDR_EXTRA)
41
42 /*! @brief Constants for transfer direction */
43 #define SDU_PORT_FOR_READ (0U) /*!< For command/data upload */
44 #define SDU_PORT_FOR_WRITE (1U) /*!< For command/data download */
45 #define SDU_PORT_MAX_TRANSFER (2U) /*!< Maximum transfer direction */
46
47
48 #define ROM_SDIO_VID 0x0471UL
49 #define ROM_SDIO_PID0 0x0208UL
50 #define ROM_SDIO_PID1 0x0209UL
51
52 static const uint32_t SD_CIS_DATA0_FN0 = 0x800u;
53
54 static const uint32_t SD_CIS_DATA0_FN1 = 0x880u;
55
56 /** Type command */
57 #define SDU_TYPE_CMD (1U)
58 /** Type data */
59 #define SDU_TYPE_DATA (0U)
60 /** Type event */
61 #define SDU_TYPE_EVENT (3U)
62
63 #define CRC_LEN (4U)
64
65 /*! @brief Buffer structure used for transfer */
66 typedef struct _transfer_buffer
67 {
68 uint32_t user_data; /*!< User data attached with this buffer */
69 uint16_t data_size; /*!< Data buffer full size */
70 uint16_t data_len; /*!< Valid data length */
71 uint8_t *data_addr; /*!< Data address. */
72 } transfer_buffer_t;
73
74 /*! @brief SDIO transfer callback structure. */
75 typedef void (*sdioslv_transfer_callback_t)(
76 status_t status, sdioslv_func_t func, sdioslv_port_t port, transfer_buffer_t *buffer, void *user_data);
77
78 /*! @brief Data structure to configure SDIO handle for specific function */
79 typedef struct _sdioslv_handle_config
80 {
81 uint8_t fun_num; /*!< SDIO function number (1..7). */
82 uint8_t used_port_num; /*!< How many data ports are used inside this function */
83 uint8_t cpu_num; /*!< Specify interrupt should be generated to which CPU */
84 uint8_t reserved; /*!< Reserved */
85 uint8_t cmd_tx_format; /*!< Command Tx length format. 0: no tx_len, 1: 2 bytes, 2: 3 bytes */
86 uint8_t cmd_rd_format; /*!< Command Rx length format. 0: blk_num * blk_size, 1: CMD_PORT_RD_LEN */
87 uint8_t data_tx_format; /*!< Data Tx length format. 0: no tx_len, 1: 2 bytes, 2: 3 bytes */
88 uint8_t data_rd_format; /*!< Data Rx length format.
89 0: blk_num * blk_size, 1: PORT_RD_LEN[15:0], 2: PORT1_RD_LEN[7:0] && PORT0_RD_LEN[15:0] */
90 /* Callback function for command */
91 sdioslv_transfer_callback_t cmd_callback; /*!< Command callback function. */
92 void *cmd_user_data; /*!< Parameter passed to the callback. */
93 /* Callback function for data */
94 sdioslv_transfer_callback_t data_callback; /*!< Data callback function. */
95 void *data_user_data; /*!< Parameter passed to the callback. */
96 } sdioslv_handle_config_t;
97
98
99 /*! @brief Data structure used to handle command or data port */
100 typedef struct _sdioslv_port_ctrl
101 {
102 uint8_t valid; /*!< Indicate if this port is valid, 1 means valid */
103 uint8_t occupied; /*!< Indicate if this port is occupied for transfer, 1 means occupied */
104 uint8_t reserved[2]; /*!< Reserved */
105 transfer_buffer_t *buffer; /*!< Assigned buffer */
106 } sdioslv_port_ctrl_t;
107
108 /*! @brief Data structure used to handle SDU fucntion */
109 typedef struct _sdioslv_fun_ctrl
110 {
111 uint8_t initialized; /*!< Indicate if this function is initialized, 1 means initialized */
112 uint8_t enable; /*!< Indicate if this function is enabled, 1 means enabled */
113 uint8_t curr_data_tx_port; /*!< current available data tx port */
114 uint8_t reserved; /*!< Reserved */
115 sdioslv_sdu_regmap_t *regmap; /*!< SDU register map */
116 sdioslv_port_ctrl_t cmd_port[SDU_PORT_MAX_TRANSFER]; /*!< command port */
117 sdioslv_port_ctrl_t data_port[SDU_PORT_MAX_TRANSFER][SDU_MAX_PORT_NUM]; /*!< data ports */
118 sdioslv_handle_config_t config; /*!< User configurations */
119 } sdioslv_fun_ctrl_t;
120
121 /*! @brief Data structure used to handle SDU chip */
122 typedef struct _sdioslv_sdu_ctrl
123 {
124 uint8_t initialized; /*!< Indicate if SDU is initialized, 1 means initialized */
125 uint8_t cpu_num; /*!< Specify interrupt should be generated to which CPU */
126 uint8_t used_fun_num; /*!< How many functions will be used */
127 uint8_t reserved; /*!< Reserved */
128 sdioslv_fun_ctrl_t *func_ctrl[SDU_MAX_FUNCTION_NUM]; /*!< Pointer to function handle */
129 } sdioslv_sdu_ctrl_t;
130
131 typedef struct _sdu_buffer
132 {
133 list_element_t link;
134 transfer_buffer_t buffer;
135 } sdu_buffer_t;
136
137 typedef struct _sdu_stat
138 {
139 uint32_t err_tx_cmd_sdio_hdr;
140 uint32_t err_tx_cmd_call_cb;
141 uint32_t drop_tx_cmd;
142 uint32_t succ_tx_cmd;
143 uint32_t err_tx_data_sdio_hdr;
144 uint32_t err_tx_data_call_cb;
145 uint32_t drop_tx_data;
146 uint32_t succ_tx_data;
147 } sdu_stat_t;
148
149
150 /*! @brief SDU initialization state. */
151 typedef enum _sdu_state_t
152 {
153 SDU_UNINITIALIZED,
154 SDU_INITIALIZING,
155 SDU_INITIALIZED
156 }sdu_state_t;
157
158
159 typedef void *sdioslv_handle_t;
160
161 typedef struct _sdu_ctrl
162 {
163 sdu_state_t sdu_state;
164 sdioslv_handle_t handle;
165 list_label_t cmd_q[SDU_PORT_MAX_TRANSFER];
166 list_label_t cmd_free_buffer[SDU_PORT_MAX_TRANSFER];
167 list_label_t event_q;
168 list_label_t event_free_buffer;
169 list_label_t data_q[SDU_PORT_MAX_TRANSFER];
170 list_label_t data_free_buffer;
171 sdu_callback_t sdu_cb_fn[SDU_TYPE_FOR_WRITE_MAX];
172 sdu_stat_t stat;
173 OSA_TASK_HANDLE_DEFINE(recvTaskId);
174 OSA_EVENT_HANDLE_DEFINE(event);
175 } sdu_ctrl_t;
176
177
178 /*******************************************************************************
179 * Prototypes
180 ******************************************************************************/
181
182
183 /*******************************************************************************
184 * Variables
185 ******************************************************************************/
186 #define SDU_TASK_PRIORITY (6U)
187 static void SDU_RecvTask(void *param);
188 static OSA_TASK_DEFINE(SDU_RecvTask, SDU_TASK_PRIORITY, 1, SDU_TRANSFER_TASK_STACK_SIZE, false);
189
190 static sdu_ctrl_t ctrl_sdu;
191 static sdu_buffer_t cmd_buffer[SDU_PORT_MAX_TRANSFER][SDU_MAX_CMD_BUFFER];
192 static sdu_buffer_t event_buffer[SDU_MAX_EVENT_BUFFER];
193 static sdu_buffer_t data_buffer[SDU_MAX_DATA_BUFFER];
194
195 typedef uint8_t cmd_trans_buffer_t[SDK_SIZEALIGN(SDU_CMD_BUFFER_SIZE, SDU_SIZE_ALIGN)];
196 typedef uint8_t event_trans_buffer_t[SDK_SIZEALIGN(SDU_EVENT_BUFFER_SIZE, SDU_SIZE_ALIGN)];
197 typedef uint8_t data_trans_buffer_t[SDK_SIZEALIGN(SDU_DATA_BUFFER_SIZE, SDU_SIZE_ALIGN)];
198
199 SDK_ALIGN(static cmd_trans_buffer_t cmd_trans_buffer[SDU_MAX_CMD_BUFFER], SDU_BUFF_ALIGN);
200 SDK_ALIGN(static cmd_trans_buffer_t cmdrsp_trans_buffer[SDU_MAX_CMD_BUFFER], SDU_BUFF_ALIGN);
201 SDK_ALIGN(static event_trans_buffer_t event_trans_buffer[SDU_MAX_EVENT_BUFFER], SDU_BUFF_ALIGN);
202 SDK_ALIGN(static data_trans_buffer_t data_trans_buffer[SDU_MAX_DATA_BUFFER], SDU_BUFF_ALIGN);
203
204 static sdioslv_sdu_ctrl_t sdu_ctrl;
205
206 #ifndef BIT
207 #define BIT(n) (1U << (n))
208 #endif
209
210 #define SDU_DBG_LEVEL_WARN BIT(3U)
211 #define SDU_DBG_LEVEL_ERROR BIT(2U)
212 #define SDU_DBG_LEVEL_DEBUG BIT(1U)
213 #define SDU_DBG_LEVEL_DUMP BIT(0U)
214
215 static uint32_t sdu_dbg_level = SDU_DBG_LEVEL_WARN | SDU_DBG_LEVEL_ERROR;
216
217 #define sdu_e(_fmt_, ...) \
218 if (((uint32_t)(sdu_dbg_level) & (uint32_t)(SDU_DBG_LEVEL_ERROR)) != 0U) \
219 {(void)PRINTF("[SDU]Error: " _fmt_ "\n\r", ##__VA_ARGS__);}
220 #define sdu_w(_fmt_, ...) \
221 if (((uint32_t)(sdu_dbg_level) & (uint32_t)(SDU_DBG_LEVEL_WARN)) != 0U) \
222 {(void)PRINTF("[SDU]Warn: " _fmt_ "\n\r", ##__VA_ARGS__);}
223
224 #define CONFIG_ADAPTER_SDU_DEBUG
225 #ifdef CONFIG_ADAPTER_SDU_DEBUG
226 #define sdu_d(_fmt_, ...) \
227 if (((uint32_t)(sdu_dbg_level) & (uint32_t)(SDU_DBG_LEVEL_DEBUG)) != 0U) \
228 {(void)PRINTF("[SDU]Debug: " _fmt_ "\n\r", ##__VA_ARGS__);}
229 #else
230 #define sdu_d(_fmt_, ...)
231 #endif
232
233
234 /*******************************************************************************
235 * Public Functions
236 ******************************************************************************/
237
238
239 /*******************************************************************************
240 * Private Functions
241 ******************************************************************************/
242 static status_t SDU_InnerInit(void);
243 static void SDU_InnerDeinit(void);
244 static bool SDU_IsLinkUp(void);
245
246 static void SDU_CmdCallback(
247 status_t status, sdioslv_func_t func, sdioslv_port_t port, transfer_buffer_t *buffer, void *user_data);
248 static void SDU_DataCallback(
249 status_t status, sdioslv_func_t func, sdioslv_port_t port, transfer_buffer_t *buffer, void *user_data);
250
251 static status_t SDU_SendCmdNonBlocking(sdioslv_handle_t handle, transfer_buffer_t *buffer);
252 static status_t SDU_RefillCmdBuffer(sdu_ctrl_t *ctrl);
253 static status_t SDU_SendDataNonBlocking(sdioslv_handle_t handle, transfer_buffer_t *buffer);
254 static status_t SDU_RefillDataBuffer(sdu_ctrl_t *ctrl, sdioslv_port_t port);
255 static status_t SDU_RefillFreePortsDataBuffer(sdu_ctrl_t *ctrl);
256
257 static status_t SDU_RecvCmdProcess(void);
258 static status_t SDU_RecvDataProcess(void);
259
260 #define DUMP_WRAPAROUND 16U
261 /** Dump buffer in hex format on console
262 *
263 * This function prints the received buffer in HEX format on the console
264 *
265 * \param[in] data Pointer to the data buffer
266 * \param[in] len Length of the data
267 */
SDU_dump_hex(uint32_t level,const void * data,unsigned len)268 static inline void SDU_dump_hex(uint32_t level, const void *data, unsigned len)
269 {
270 unsigned int i = 0;
271 const char *data8 = (const char *)data;
272
273 if ((level & SDU_DBG_LEVEL_DUMP) == 0U)
274 {
275 return;
276 }
277
278 (void)PRINTF("**** Dump @ %p Len: %d ****\n\r", data, len);
279 while (i < len)
280 {
281 (void)PRINTF("%02x ", data8[i++]);
282 if ((i % DUMP_WRAPAROUND) == 0U)
283 {
284 (void)PRINTF("\n\r");
285 }
286 }
287
288 (void)PRINTF("\n\r******** End Dump *******\n\r");
289 }
290
291
292 /*!
293 * @brief SDU data initialization function.
294 *
295 * @param fun_num Specify how many functions will be used.
296 . @param cpu_num Specify interrupt should be generated to which CPU.
297 * @retval #kStatus_Success Initialize SDU sucessfully.
298 * @retval #kStatus_InvalidArgument Invalid argument.
299 * @retval #kStatus_Fail Fail to initialize SDU.
300 */
SDU_InitData(uint32_t used_fun_num,sdioslv_int_cpu_num_t cpu_num)301 static status_t SDU_InitData(uint32_t used_fun_num, sdioslv_int_cpu_num_t cpu_num)
302 {
303 uint32_t fun_num = 0U;
304 sdioslv_fun_ctrl_t *fun_ctrl;
305 OSA_SR_ALLOC();
306
307 if (used_fun_num > (uint32_t)SDU_MAX_FUNCTION_NUM)
308 {
309 return (status_t)kStatus_InvalidArgument;
310 }
311
312 if (sdu_ctrl.initialized != 0U)
313 {
314 return (status_t)kStatus_Success;
315 }
316
317 OSA_ENTER_CRITICAL();
318 for (fun_num = 0; fun_num < used_fun_num; fun_num++)
319 {
320 fun_ctrl = (sdioslv_fun_ctrl_t *)OSA_MemoryAllocate(sizeof(sdioslv_fun_ctrl_t));
321 if (fun_ctrl == NULL)
322 {
323 break;
324 }
325 /* OSA_MemoryAllocate() sets contents of allocated memory to be zero */
326 fun_ctrl->regmap = (sdioslv_sdu_regmap_t *)((uint32_t)SDU_SDIO_CFG_BASE + (uint32_t)(SDIO_CCR_FUNC_OFFSET *(uint32_t)(fun_num + 1U)));
327 sdu_ctrl.func_ctrl[fun_num] = fun_ctrl;
328 }
329
330 if (fun_num < used_fun_num)
331 {
332 while(fun_num > 0U)
333 {
334 OSA_MemoryFree(sdu_ctrl.func_ctrl[fun_num - 1U]);
335 fun_num--;
336 }
337 OSA_EXIT_CRITICAL();
338 return (status_t)kStatus_Fail;
339 }
340
341 SDU_REGS8_SETBITS(SDIO_CCR_FUNC0_CARD_INT_MSK, cpu_num);
342
343 sdu_ctrl.used_fun_num = (uint8_t)used_fun_num;
344 sdu_ctrl.cpu_num = (uint8_t)cpu_num;
345 sdu_ctrl.initialized = 1;
346 OSA_EXIT_CRITICAL();
347 return (status_t)kStatus_Success;
348 }
349
350 /*!
351 * @brief SDU data deinitialization function.
352 *
353 * @param void None.
354 */
SDU_DeinitData(void)355 static void SDU_DeinitData(void)
356 {
357 uint8_t fun_num;
358 OSA_SR_ALLOC();
359
360 if (sdu_ctrl.initialized == 0U)
361 {
362 return;
363 }
364 OSA_ENTER_CRITICAL();
365 for (fun_num = 0U; fun_num < sdu_ctrl.used_fun_num; fun_num++)
366 {
367 if (sdu_ctrl.func_ctrl[fun_num] != NULL)
368 {
369 OSA_MemoryFree(sdu_ctrl.func_ctrl[fun_num]);
370 }
371 }
372 sdu_ctrl.used_fun_num = 0;
373 sdu_ctrl.cpu_num = 0;
374 sdu_ctrl.initialized = 0;
375 OSA_EXIT_CRITICAL();
376 }
377
378 /*!
379 * @brief Create handle for specified function.
380 *
381 * @param config Configuration used to create this handle.
382 * @retval !NULL Created handle pointer.
383 * @retval NULL Fail to create handle.
384 */
SDU_CreateHandle(sdioslv_handle_config_t * config)385 static sdioslv_handle_t SDU_CreateHandle(sdioslv_handle_config_t *config)
386 {
387 uint8_t fun_num;
388 sdioslv_fun_ctrl_t *fun_ctrl;
389 sdioslv_sdu_regmap_t *sdu_fsr;
390 uint8_t i, j;
391 OSA_SR_ALLOC();
392
393 fun_num = config->fun_num;
394 if ((fun_num < 1U) || (fun_num > sdu_ctrl.used_fun_num))
395 {
396 return NULL;
397 }
398
399 if (config->used_port_num > (uint8_t)(SDU_MAX_PORT_NUM))
400 {
401 return NULL;
402 }
403
404 if ((config->cpu_num != (uint8_t)kSDIOSLV_INT_CPUNum1) && (config->cpu_num != (uint8_t)kSDIOSLV_INT_CPUNum2) &&
405 (config->cpu_num != (uint8_t)kSDIOSLV_INT_CPUNum3))
406 {
407 return NULL;
408 }
409
410 if ((config->cmd_tx_format > 2U) || (config->cmd_rd_format > 1U))
411 {
412 return NULL;
413 }
414
415 if ((config->data_tx_format > 2U) || (config->data_rd_format > 2U))
416 {
417 return NULL;
418 }
419
420 if ((config->cmd_callback == NULL) || (config->data_callback == NULL))
421 {
422 return NULL;
423 }
424
425 OSA_ENTER_CRITICAL();
426 fun_ctrl = sdu_ctrl.func_ctrl[fun_num - 1U];
427 if (fun_ctrl == NULL)
428 {
429 goto create_err;
430 }
431
432 sdu_fsr = fun_ctrl->regmap;
433 sdu_fsr->RdBitMap = 0;
434 sdu_fsr->WrBitMap = 0;
435 sdu_fsr->FunctionCardIntMsk = config->cpu_num;
436 sdu_fsr->CardIntMask = SDIO_CCR_CIM_MASK ;//SDIO_CCR_CIM_MASK | SDIO_CCR_CIM_PwrUp;
437 /* toggle SDIO_CCR_CIC_DnLdOvr */
438 sdu_fsr->CardIntStatus = SDIO_CCR_CIC_DnLdOvr;
439 sdu_fsr->CardIntStatus = 0;
440 sdu_fsr->CardIntMode = 0;//0x00000C02;//CARD_INT_MODE_MSK;
441 sdu_fsr->CmdPortConfig =
442 (uint32_t)((config->cmd_tx_format << (uint8_t)CMD_TX_LEN_BIT_OFFSET) | (config->cmd_rd_format << (uint8_t)CMD_RD_LEN_BIT_OFFSET));
443 sdu_fsr->Config2 = (uint32_t)((uint8_t)CONFIG2_DEFAULT_SETTING | (config->data_tx_format << (uint8_t)(CONFIG2_TX_LEN_BIT_OFFSET)) |
444 (config->data_rd_format << (uint8_t)(CONFIG2_RD_LEN_BIT_OFFSET)));
445
446 for (i = 0; i < SDU_PORT_MAX_TRANSFER; i++)
447 {
448 fun_ctrl->cmd_port[i].valid = 1;
449 for (j = 0; j < config->used_port_num; j++)
450 {
451 fun_ctrl->data_port[i][j].valid = 1;
452 }
453 }
454
455 (void)memcpy(&fun_ctrl->config, config, sizeof(*config));
456 fun_ctrl->initialized = 1;
457 fun_ctrl->enable = 1;
458 OSA_EXIT_CRITICAL();
459
460 return (sdioslv_handle_t)fun_ctrl;
461
462 create_err:
463 OSA_EXIT_CRITICAL();
464 return NULL;
465 }
466
467
SDU_InnerInit(void)468 static status_t SDU_InnerInit(void)
469 {
470 sdioslv_handle_config_t config;
471 status_t rc;
472 uint32_t i = 0;
473 uint32_t direction = 0;
474 transfer_buffer_t *trans_buf;
475
476 rc = SDU_InitData(SDU_USED_FUN_NUM, SDU_INT_CPU_NUM);
477 if (rc != kStatus_Success)
478 {
479 sdu_e("Fail to initialize SDU: %d\r\n", (uint32_t)rc);
480 return rc;
481 }
482 config.fun_num = 1;
483 config.used_port_num = SDU_ACTUAL_USE_PORT_NUM;
484 config.cpu_num = 1;//kSDIOSLV_INT_CPUNum3;
485 config.cmd_tx_format = 2;
486 config.cmd_rd_format = 1;
487 config.data_tx_format = 2;
488 config.data_rd_format = 1;
489 config.cmd_callback = SDU_CmdCallback;
490 config.cmd_user_data = &ctrl_sdu;
491 config.data_callback = SDU_DataCallback;
492 config.data_user_data = &ctrl_sdu;
493
494 for (direction = 0; direction < SDU_PORT_MAX_TRANSFER; direction++)
495 {
496 LIST_Init(&ctrl_sdu.cmd_q[direction], 0);
497 LIST_Init(&ctrl_sdu.cmd_free_buffer[direction], SDU_MAX_CMD_BUFFER);
498 LIST_Init(&ctrl_sdu.data_q[direction], 0);
499 }
500 LIST_Init(&ctrl_sdu.data_free_buffer, SDU_MAX_DATA_BUFFER);
501 LIST_Init(&ctrl_sdu.event_q, 0);
502 LIST_Init(&ctrl_sdu.event_free_buffer, SDU_MAX_EVENT_BUFFER);
503
504 for (direction = 0; direction < SDU_PORT_MAX_TRANSFER; direction++)
505 {
506 for (i = 0; i < SDU_MAX_CMD_BUFFER; i++)
507 {
508 trans_buf = &cmd_buffer[direction][i].buffer;
509 if (direction == SDU_PORT_FOR_WRITE)
510 {
511 trans_buf->data_addr = (uint8_t *)cmd_trans_buffer[i];
512 trans_buf->data_size = (uint16_t)sizeof(cmd_trans_buffer[i]);
513 sdu_d("%s: cmd_trans_buffer[%u]=%p sizeof=%lu\r\n", __FUNCTION__, i, cmd_trans_buffer[i], sizeof(cmd_trans_buffer[i]));
514 }
515 else
516 {
517 trans_buf->data_addr = (uint8_t *)cmdrsp_trans_buffer[i];
518 trans_buf->data_size = (uint16_t)sizeof(cmdrsp_trans_buffer[i]);
519 sdu_d("%s: cmdrsp_trans_buffer[%u]=%p sizeof=%lu\r\n", __FUNCTION__, i, cmdrsp_trans_buffer[i], sizeof(cmdrsp_trans_buffer[i]));
520 }
521 if (trans_buf->data_addr == NULL)
522 {
523 sdu_e("%s: cmd free list buffer alloc fail!\r\n", __FUNCTION__);
524 rc = kStatus_Fail;
525 goto done;
526 }
527 trans_buf->data_len = 0;
528 trans_buf->user_data = 0;
529 (void)LIST_AddTail(&ctrl_sdu.cmd_free_buffer[direction], &cmd_buffer[direction][i].link);
530 sdu_d("%s: trans_buf: data_addr=%p data_size=%u\r\n", __FUNCTION__, trans_buf->data_addr, trans_buf->data_size);
531 }
532 }
533
534 for (i = 0; i < SDU_MAX_EVENT_BUFFER; i++)
535 {
536 trans_buf = &event_buffer[i].buffer;
537 trans_buf->data_addr = (uint8_t *)event_trans_buffer[i];
538 if (trans_buf->data_addr == NULL)
539 {
540 sdu_e("%s: event free list buffer alloc fail!\r\n", __FUNCTION__);
541 rc = kStatus_Fail;
542 goto done;
543 }
544 trans_buf->data_size = (uint16_t)sizeof(event_trans_buffer[i]);
545 trans_buf->data_len = 0;
546 trans_buf->user_data = 0;
547 (void)LIST_AddTail(&ctrl_sdu.event_free_buffer, &event_buffer[i].link);
548 sdu_d("%s: event_trans_buffer[%u]=%p sizeof=%lu\r\n", __FUNCTION__, i, event_trans_buffer[i], sizeof(event_trans_buffer[i]));
549 sdu_d("%s: trans_buf: data_addr=%p data_size=%u\r\n", __FUNCTION__, trans_buf->data_addr, trans_buf->data_size);
550 }
551
552 for (i = 0; i < (uint32_t)SDU_MAX_DATA_BUFFER; i++)
553 {
554 trans_buf = &data_buffer[i].buffer;
555 trans_buf->data_addr = (uint8_t *)data_trans_buffer[i];
556 if (trans_buf->data_addr == NULL)
557 {
558 sdu_e("%s: data free list buffer alloc fail!\r\n", __FUNCTION__);
559 rc = kStatus_Fail;
560 goto done;
561 }
562 trans_buf->data_size = (uint16_t)sizeof(data_trans_buffer[i]);
563 trans_buf->data_len = 0;
564 trans_buf->user_data = 0;
565 (void)LIST_AddTail(&ctrl_sdu.data_free_buffer, &data_buffer[i].link);
566 sdu_d("%s: data_trans_buffer[%u]=%p sizeof=%lu\r\n", __FUNCTION__, i, data_trans_buffer[i], sizeof(data_trans_buffer[i]));
567 sdu_d("%s: trans_buf: data_addr=%p data_size=%u\r\n", __FUNCTION__, trans_buf->data_addr, trans_buf->data_size);
568 }
569
570 ctrl_sdu.handle = SDU_CreateHandle(&config);
571 if (ctrl_sdu.handle == NULL)
572 {
573 sdu_e("Fail to create handle for function %d\r\n", config.fun_num);
574 rc = kStatus_Fail;
575 goto done;
576 }
577
578 /* reguest for command buffer */
579 config.cmd_callback(kStatus_SDIOSLV_FuncRequestBuffer, (sdioslv_func_t)(config.fun_num), kSDIOSLV_CmdPortNum0, NULL,
580 config.cmd_user_data);
581
582 /* request for data buffer */
583 for (i = 0; i < config.used_port_num; i++)
584 {
585 config.data_callback(kStatus_SDIOSLV_FuncRequestBuffer, (sdioslv_func_t)(config.fun_num), (sdioslv_port_t)i, NULL,
586 config.data_user_data);
587 }
588 done:
589 if (rc != kStatus_Success)
590 {
591 SDU_DeinitData();
592 }
593
594 return rc;
595 }
596
SDU_InnerDeinit(void)597 static void SDU_InnerDeinit(void)
598 {
599 SDU_DeinitData();
600
601 ctrl_sdu.sdu_state = SDU_UNINITIALIZED;
602 }
603
SDU_CmdCallback(status_t status,sdioslv_func_t func,sdioslv_port_t port,transfer_buffer_t * buffer,void * user_data)604 static void SDU_CmdCallback(
605 status_t status, sdioslv_func_t func, sdioslv_port_t port, transfer_buffer_t *buffer, void *user_data)
606 {
607 sdu_ctrl_t *ctrl = (sdu_ctrl_t *)user_data;
608 sdu_buffer_t *cmd_event_buf = NULL;
609
610 switch (status)
611 {
612 case (status_t)kStatus_SDIOSLV_FuncRequestBuffer:
613 (void)SDU_RefillCmdBuffer(ctrl);
614 break;
615 case (status_t)kStatus_SDIOSLV_FuncReadComplete:
616 cmd_event_buf = (sdu_buffer_t *)buffer->user_data;
617 (void)LIST_AddTail(&ctrl_sdu.cmd_q[SDU_PORT_FOR_WRITE], &cmd_event_buf->link);
618 (void)OSA_EventSet(ctrl->event, SDU_CMD_RECEIVED);
619 break;
620 case (status_t)kStatus_SDIOSLV_FuncSendComplete:
621 cmd_event_buf = (sdu_buffer_t *)buffer->user_data;
622 if (&(cmd_event_buf->link) == LIST_GetHead(&ctrl_sdu.cmd_q[SDU_PORT_FOR_READ]))
623 {
624 (void)LIST_RemoveElement(&cmd_event_buf->link);
625 (void)LIST_AddTail(&ctrl_sdu.cmd_free_buffer[SDU_PORT_FOR_READ], &cmd_event_buf->link);
626 }
627 else if (&(cmd_event_buf->link) == LIST_GetHead(&ctrl_sdu.event_q))
628 {
629 (void)LIST_RemoveElement(&cmd_event_buf->link);
630 (void)LIST_AddTail(&ctrl_sdu.event_free_buffer, &cmd_event_buf->link);
631 }
632 else
633 {
634 sdu_e("%s: Unknown cmd_event_buf=%p buffer=%p.\n\r", __func__, cmd_event_buf, buffer);
635 }
636 break;
637 default:
638 sdu_e("%s: Unknown callback status %d.\n\r", __func__, status);
639 break;
640 }
641
642 return;
643 }
644
SDU_DataCallback(status_t status,sdioslv_func_t func,sdioslv_port_t port,transfer_buffer_t * buffer,void * user_data)645 static void SDU_DataCallback(
646 status_t status, sdioslv_func_t func, sdioslv_port_t port, transfer_buffer_t *buffer, void *user_data)
647 {
648 sdu_ctrl_t *ctrl = (sdu_ctrl_t *)user_data;
649 sdu_buffer_t *data_buf = NULL;
650 sdio_header_t *sdio_hdr = (sdio_header_t *)(buffer->data_addr);
651
652 switch (status)
653 {
654 case (status_t)kStatus_SDIOSLV_FuncRequestBuffer:
655 (void)SDU_RefillDataBuffer(ctrl, port);
656 break;
657 #if 0
658 case kStatus_SDIOSLV_FuncRequestFreePortsBuffer:
659 SDU_RefillFreePortsDataBuffer(ctrl);
660 break;
661 #endif
662 case (status_t)kStatus_SDIOSLV_FuncReadComplete:
663 sdu_d("Dump %p %p len=%u\n\r", buffer, buffer->data_addr, MIN(sdio_hdr->len, buffer->data_size));
664 SDU_dump_hex(sdu_dbg_level, buffer->data_addr, sdio_hdr->len);
665 data_buf = (sdu_buffer_t *)buffer->user_data;
666 (void)LIST_AddTail(&ctrl_sdu.data_q[SDU_PORT_FOR_WRITE], &data_buf->link);
667 (void)OSA_EventSet(ctrl->event, SDU_DATA_RECEIVED);
668 break;
669 case (status_t)kStatus_SDIOSLV_FuncSendComplete:
670 data_buf = (sdu_buffer_t *)buffer->user_data;
671 (void)LIST_RemoveElement(&data_buf->link);
672 (void)LIST_AddTail(&ctrl_sdu.data_free_buffer, &data_buf->link);
673 break;
674 default:
675 sdu_e("Unknown callback status %d (%s).\n\r", status, __func__);
676 break;
677 }
678 return;
679 }
680
681
682 #ifdef CONFIG_SDIO_TEST_LOOPBACK
683
684 #if 0
685 static void SDU_TransferCmdRecv(sdu_ctrl_t *ctrl)
686 {
687 sdu_buffer_t *cmd_rcv = NULL;
688
689 OSA_SR_ALLOC();
690
691 OSA_ENTER_CRITICAL();
692 while (1)
693 {
694 cmd_rcv = (sdu_buffer_t *)LIST_RemoveHead(&ctrl->cmd_q[SDU_PORT_FOR_WRITE]);
695 if (!cmd_rcv)
696 break;
697
698 //cmd_send = (sdu_buffer_t *)LIST_RemoveHead(&ctrl->cmd_free_buffer[SDU_PORT_FOR_READ]);
699 cmd_rcv->buffer.data_len = ((sdio_header_t *)(cmd_rcv->buffer.data_addr))->len;
700 //*(uint16_t *)((uint8_t *)(cmd_rcv->buffer.data_addr) + 4) |= 0x8000;
701 sdu_d("CmdRecv data_len: %d", cmd_rcv->buffer.data_len);
702 SDU_dump_hex(sdu_dbg_level, cmd_rcv->buffer.data_addr, cmd_rcv->buffer.data_len);
703
704 //cmd_send->buffer.data_len = cmd_rcv->buffer.data_len;
705 //memcpy(cmd_send->buffer.data_addr, cmd_rcv->buffer.data_addr, cmd_send->buffer.data_len);
706 //cmd_send->buffer.user_data = (uint32_t)cmd_send;
707 //SDU_SendCmdNonBlocking(ctrl->handle, &cmd_send->buffer);
708
709 SDU_Send(SDU_TYPE_FOR_READ_CMD, cmd_rcv->buffer.data_addr + sizeof(sdio_header_t),
710 cmd_rcv->buffer.data_len - sizeof(sdio_header_t));
711
712 (void)LIST_AddTail(&ctrl->cmd_free_buffer[SDU_PORT_FOR_WRITE], &cmd_rcv->link);
713 SDU_RefillCmdBuffer(&ctrl_sdu);
714 }
715 OSA_EXIT_CRITICAL();
716 }
717
718 static void SDU_TransferDataRecv(sdu_ctrl_t *ctrl)
719 {
720 sdu_buffer_t *data_rcv = NULL;
721 OSA_SR_ALLOC();
722
723 OSA_ENTER_CRITICAL();
724 while (1)
725 {
726 data_rcv = (sdu_buffer_t *)LIST_RemoveHead(&ctrl->data_q[SDU_PORT_FOR_WRITE]);
727 if (!data_rcv)
728 break;
729
730 //data_send = (sdu_buffer_t *)LIST_RemoveHead(&ctrl->data_free_buffer);
731 data_rcv->buffer.data_len = ((sdio_header_t *)(data_rcv->buffer.data_addr))->len;
732 sdu_d("DataRecv data_len: %d\r\n", data_rcv->buffer.data_len);
733 SDU_dump_hex(sdu_dbg_level, data_rcv->buffer.data_addr, data_rcv->buffer.data_len);
734
735 //data_send->buffer.data_len = data_rcv->buffer.data_len;
736 //memcpy(data_send->buffer.data_addr, data_rcv->buffer.data_addr, data_send->buffer.data_len);
737 //data_send->buffer.user_data = (uint32_t)data_send;
738 //SDU_SendDataNonBlocking(ctrl->handle, &data_send->buffer);
739
740 SDU_Send(SDU_TYPE_FOR_READ_DATA, data_rcv->buffer.data_addr + sizeof(sdio_header_t),
741 data_rcv->buffer.data_len - sizeof(sdio_header_t));
742
743 (void)LIST_AddTail(&ctrl->data_free_buffer, &data_rcv->link);
744 SDU_RefillFreePortsDataBuffer(&ctrl_sdu);
745
746 if (!LIST_GetSize(&ctrl->data_q[SDU_PORT_FOR_WRITE]))
747 break;
748
749 /* Let command get priority */
750 if (LIST_GetSize(&ctrl->cmd_q[SDU_PORT_FOR_WRITE]))
751 {
752 OSA_EventSet(ctrl->event, SDU_DATA_RECEIVED);
753 break;
754 }
755 }
756 OSA_EXIT_CRITICAL();
757 }
758
759 static void SDU_TransferTask(void *param)
760 {
761 sdu_ctrl_t *ctrl = (sdu_ctrl_t *)param;
762 osa_event_flags_t ev = 0;
763
764 do
765 {
766 if (KOSA_StatusSuccess ==
767 OSA_EventWait((osa_event_handle_t)ctrl->event, osaEventFlagsAll_c, 0U, osaWaitForever_c, &ev))
768 {
769 if (ev & SDU_CMD_RECEIVED)
770 SDU_TransferCmdRecv(ctrl);
771
772 if (ev & SDU_DATA_RECEIVED)
773 SDU_TransferDataRecv(ctrl);
774 }
775 } while (0U != gUseRtos_c);
776 }
777 #endif
778
SDU_LoopbackRecvCmdHandler(void * tlv,size_t tlv_sz)779 static void SDU_LoopbackRecvCmdHandler(void *tlv, size_t tlv_sz)
780 {
781 assert(NULL != tlv);
782 assert(0U != tlv_sz);
783
784 sdu_d("RecvCmd len: %d", tlv_sz);
785 SDU_dump_hex(sdu_dbg_level, tlv, tlv_sz);
786
787 (void)SDU_Send(SDU_TYPE_FOR_READ_CMD, (uint8_t *)tlv, (uint16_t)(tlv_sz + CRC_LEN));
788 }
789
SDU_LoopbackRecvDataHandler(void * tlv,size_t tlv_sz)790 static void SDU_LoopbackRecvDataHandler(void *tlv, size_t tlv_sz)
791 {
792 assert(NULL != tlv);
793 assert(0U != tlv_sz);
794
795 sdu_d("RecvData len: %d\r\n", tlv_sz);
796 SDU_dump_hex(sdu_dbg_level, tlv, tlv_sz);
797
798 (void)SDU_Send(SDU_TYPE_FOR_READ_DATA, (uint8_t *)tlv, (uint16_t)(tlv_sz + CRC_LEN));
799 }
800 #endif
801
SDU_RecvTask(void * param)802 static void SDU_RecvTask(void *param)
803 {
804 sdu_ctrl_t *ctrl = (sdu_ctrl_t *)param;
805 osa_event_flags_t ev = 0;
806
807 do
808 {
809 if (KOSA_StatusSuccess ==
810 OSA_EventWait((osa_event_handle_t)ctrl->event, osaEventFlagsAll_c, 0U, osaWaitForever_c, &ev))
811 {
812 if ((ev & SDU_CMD_RECEIVED) != 0U)
813 {
814 (void)SDU_RecvCmdProcess();
815 }
816
817 if ((ev & SDU_DATA_RECEIVED) != 0U)
818 {
819 (void)SDU_RecvDataProcess();
820 }
821 }
822 } while (0U != gUseRtos_c);
823
824 }
825
826 /*!
827 * @brief SDU Link is up or not.
828 *
829 * Call this API to check if SDU Link is up or not.
830 *
831 * @param void.
832 * @retval TRUE SDU Link is UP.
833 * @retval FALSE SDU Link is not UP.
834 */
SDU_IsLinkUp(void)835 static bool SDU_IsLinkUp(void)
836 {
837 if (SDU_INITIALIZED == ctrl_sdu.sdu_state)
838 {
839 return true;
840 }
841
842 return false;
843 }
844
845 #if 0
846 /*!
847 * @brief SDU send data transfer checking.
848 *
849 * Call this API to check if tranmist is available.
850 *
851 * @param void.
852 * @retval TRUE all data slots are occupied.
853 * @retval FALSE data transmit is availalbe.
854 */
855 bool SDU_IsSendDataFull(void)
856 {
857 sdioslv_fun_ctrl_t *fun_ctrl = NULL;
858 bool data_full;
859 OSA_SR_ALLOC();
860
861 OSA_ENTER_CRITICAL();
862 fun_ctrl = (sdioslv_fun_ctrl_t *)&(ctrl_sdu.handle);
863 if (fun_ctrl->curr_data_tx_port >= fun_ctrl->config.used_port_num)
864 data_full = true;
865 else
866 data_full = false;
867 OSA_EXIT_CRITICAL();
868
869 return data_full;
870 }
871
872 /*!
873 * @brief SDU check and move available data port pointer.
874 *
875 * @param fun_ctrl Spcified which function to be adjusted for available data port pointer.
876 * @retval None.
877 */
878 static inline void SDU_AdjustAvailDataPort(sdioslv_fun_ctrl_t *fun_ctrl)
879 {
880 int i;
881 OSA_SR_ALLOC();
882
883 if (!fun_ctrl)
884 return;
885
886 OSA_ENTER_CRITICAL();
887 for (i = 0; i < fun_ctrl->config.used_port_num; i++)
888 {
889 if (!fun_ctrl->data_port[SDU_PORT_FOR_READ][i].occupied)
890 {
891 fun_ctrl->curr_data_tx_port = i;
892 break;
893 }
894 }
895 if (i == fun_ctrl->config.used_port_num)
896 fun_ctrl->curr_data_tx_port = SDU_MAX_PORT_NUM;
897 OSA_EXIT_CRITICAL();
898 }
899 #endif
900
901 /*!
902 * @brief SDU process interrupt status 'SDIO_CCR_CIC_CmdUpLdOvr'.
903 *
904 * @param fun_ctrl Spcified which function to be processed.
905 * @retval None.
906 */
SDU_ProcessCmdUpLdOvr(sdioslv_fun_ctrl_t * fun_ctrl)907 static inline void SDU_ProcessCmdUpLdOvr(sdioslv_fun_ctrl_t *fun_ctrl)
908 {
909 sdioslv_port_ctrl_t *port_ctrl = NULL;
910 sdu_buffer_t *send_buffer = NULL;
911 //sdu_buffer_t *return_buf = NULL;
912 status_t status = kStatus_Success;
913
914 port_ctrl = &fun_ctrl->cmd_port[SDU_PORT_FOR_READ];
915
916 if ((port_ctrl->valid == 0U) || (port_ctrl->occupied == 0U))
917 {
918 return;
919 }
920
921 fun_ctrl->config.cmd_callback(kStatus_SDIOSLV_FuncSendComplete, (sdioslv_func_t)fun_ctrl->config.fun_num,
922 kSDIOSLV_CmdPortNum0, port_ctrl->buffer, fun_ctrl->config.cmd_user_data);
923
924 port_ctrl->buffer = NULL;
925 port_ctrl->occupied = 0;
926
927 /* If any pending cmdrsp or event in q, send one of them here */
928 if ((send_buffer = (sdu_buffer_t *)LIST_GetHead(&ctrl_sdu.cmd_q[SDU_PORT_FOR_READ])) != NULL)
929 {
930 status = SDU_SendCmdNonBlocking(ctrl_sdu.handle, &send_buffer->buffer);
931 if (status != kStatus_Success)
932 {
933 //return_buf = (sdu_buffer_t *)LIST_RemoveHead(&ctrl_sdu.cmd_q[SDU_PORT_FOR_READ]);
934 //assert(return_buf == send_buffer);
935 //(void)LIST_AddTail(&ctrl_sdu.cmd_free_buffer[SDU_PORT_FOR_READ], &return_buf->link);
936 sdu_e("%s: cmd SendCmdNonBlocking fail 0x%x!\r\n", __FUNCTION__, status);
937 }
938 }
939 else if ((send_buffer = (sdu_buffer_t *)LIST_GetHead(&ctrl_sdu.event_q)) != NULL)
940 {
941 status = SDU_SendCmdNonBlocking(ctrl_sdu.handle, &send_buffer->buffer);
942 if (status != kStatus_Success)
943 {
944 //return_buf = (sdu_buffer_t *)LIST_RemoveHead(&ctrl_sdu.event_q);
945 //assert(return_buf == send_buffer);
946 //(void)LIST_AddTail(&ctrl_sdu.event_free_buffer, &return_buf->link);
947 sdu_e("%s: event SendCmdNonBlocking fail 0x%x!\r\n", __FUNCTION__, status);
948 }
949 }
950 else
951 {
952 ;
953 }
954 }
955
956 /*!
957 * @brief SDU process interrupt status 'SDIO_CCR_CIC_CmdDnLdOvr'.
958 *
959 * @param fun_ctrl Spcified which function to be processed.
960 * @retval None.
961 */
SDU_ProcessCmdDnLdOvr(sdioslv_fun_ctrl_t * fun_ctrl)962 static inline void SDU_ProcessCmdDnLdOvr(sdioslv_fun_ctrl_t *fun_ctrl)
963 {
964 sdioslv_port_ctrl_t *port_ctrl;
965
966 port_ctrl = &fun_ctrl->cmd_port[SDU_PORT_FOR_WRITE];
967
968 if ((port_ctrl->valid == 0U) || (port_ctrl->occupied == 0U))
969 {
970 return;
971 }
972
973 fun_ctrl->config.cmd_callback(kStatus_SDIOSLV_FuncReadComplete, (sdioslv_func_t)fun_ctrl->config.fun_num,
974 kSDIOSLV_CmdPortNum0, port_ctrl->buffer, fun_ctrl->config.cmd_user_data);
975
976 port_ctrl->buffer = NULL;
977 port_ctrl->occupied = 0;
978
979 #if 0
980 fun_ctrl->config.cmd_callback(kStatus_SDIOSLV_FuncRequestBuffer, (sdioslv_func_t)fun_ctrl->config.fun_num,
981 kSDIOSLV_CmdPortNum0, NULL, fun_ctrl->config.cmd_user_data);
982 #endif
983 }
984
985 /*!
986 * @brief SDU process interrupt status 'SDIO_CCR_CIC_UpLdOvr'.
987 *
988 * @param fun_ctrl Spcified which function to be processed.
989 * @retval None.
990 */
SDU_ProcessDataUpLdOvr(sdioslv_fun_ctrl_t * fun_ctrl)991 static inline void SDU_ProcessDataUpLdOvr(sdioslv_fun_ctrl_t *fun_ctrl)
992 {
993 sdioslv_port_ctrl_t *port_ctrl;
994 sdioslv_sdu_regmap_t *sdu_fsr;
995 uint32_t rd_bit_map;
996 uint32_t i = 0;
997 sdu_buffer_t *send_buffer = NULL;
998 status_t status = kStatus_Success;
999
1000 sdu_fsr = fun_ctrl->regmap;
1001 rd_bit_map = sdu_fsr->RdBitMap;
1002
1003 for (i = 0; i < fun_ctrl->config.used_port_num; i++)
1004 {
1005 if ((rd_bit_map & ((uint32_t)(1U << i))) == 0U)
1006 {
1007 port_ctrl = &fun_ctrl->data_port[SDU_PORT_FOR_READ][i];
1008 if ((port_ctrl->valid == 0U) || (port_ctrl->occupied == 0U))
1009 {
1010 continue;
1011 }
1012
1013 fun_ctrl->config.data_callback(kStatus_SDIOSLV_FuncSendComplete, (sdioslv_func_t)fun_ctrl->config.fun_num,
1014 (sdioslv_port_t)i, port_ctrl->buffer, fun_ctrl->config.cmd_user_data);
1015
1016 port_ctrl->buffer = NULL;
1017 port_ctrl->occupied = 0;
1018 }
1019 }
1020
1021 #if 0
1022 SDU_AdjustAvailDataPort(fun_ctrl);
1023 #endif
1024
1025 if ((send_buffer = (sdu_buffer_t *)LIST_GetHead(&ctrl_sdu.data_q[SDU_PORT_FOR_READ])) != NULL)
1026 {
1027 status = SDU_SendDataNonBlocking(ctrl_sdu.handle, &send_buffer->buffer);
1028 if (status != kStatus_Success)
1029 {
1030 sdu_e("%s: SDU_SendDataNonBlocking fail 0x%x!send_buffer %p [%p %u]\r\n", __FUNCTION__,
1031 status, send_buffer, send_buffer->buffer.data_addr, send_buffer->buffer.data_len);
1032 }
1033 }
1034
1035 }
1036
1037 /*!
1038 * @brief SDU process interrupt status 'SDIO_CCR_CIC_DnLdOvr'.
1039 *
1040 * @param fun_ctrl Spcified which function to be processed.
1041 * @retval None.
1042 */
SDU_ProcessDataDnLdOvr(sdioslv_fun_ctrl_t * fun_ctrl)1043 static inline void SDU_ProcessDataDnLdOvr(sdioslv_fun_ctrl_t *fun_ctrl)
1044 {
1045 sdioslv_port_ctrl_t *port_ctrl;
1046 sdioslv_sdu_regmap_t *sdu_fsr;
1047 uint32_t wr_bit_map;
1048 uint32_t i;
1049
1050 sdu_fsr = fun_ctrl->regmap;
1051 wr_bit_map = sdu_fsr->WrBitMap;
1052
1053 for (i = 0; i < (uint32_t)fun_ctrl->config.used_port_num; i++)
1054 {
1055 if ((wr_bit_map & (uint32_t)(1U << i)) == (uint32_t)0U)
1056 {
1057 port_ctrl = &fun_ctrl->data_port[SDU_PORT_FOR_WRITE][i];
1058 if ((port_ctrl->valid == 0U) || (port_ctrl->occupied == 0U))
1059 {
1060 continue;
1061 }
1062
1063 fun_ctrl->config.data_callback(kStatus_SDIOSLV_FuncReadComplete, (sdioslv_func_t)fun_ctrl->config.fun_num,
1064 (sdioslv_port_t)i, port_ctrl->buffer, fun_ctrl->config.cmd_user_data);
1065
1066 port_ctrl->buffer = NULL;
1067 port_ctrl->occupied = 0;
1068
1069 #if 0
1070 fun_ctrl->config.data_callback(kStatus_SDIOSLV_FuncRequestBuffer, (sdioslv_func_t)fun_ctrl->config.fun_num,
1071 (sdioslv_port_t)i, NULL, fun_ctrl->config.cmd_user_data);
1072 #endif
1073 }
1074 }
1075 }
1076
1077 /*!
1078 * @brief SDU send command.
1079 *
1080 * Call this API after calling the SDU_InitData() and SDU_CreateHandle()
1081 * to send command to host driver. The callback is always invoked from the
1082 * interrupt context.
1083 *
1084 * @param handle Created by SDIOSLV_CreateHanle().
1085 * @param buffer Buffer used to exchange command to SDIO host driver.
1086 * @retval #kStatus_Success command is ready to be sent to host driver.
1087 * @retval #kStatus_InvalidArgument Invalid argument.
1088 * @retval #kStatus_SDIOSLV_CmdPending previous command is still under working.
1089 * @retval #kStatus_Fail Fail to send command.
1090 */
SDU_SendCmdNonBlocking(sdioslv_handle_t handle,transfer_buffer_t * buffer)1091 static status_t SDU_SendCmdNonBlocking(sdioslv_handle_t handle, transfer_buffer_t *buffer)
1092 {
1093 sdioslv_fun_ctrl_t *fun_ctrl;
1094 sdioslv_port_ctrl_t *port_ctrl;
1095
1096 OSA_SR_ALLOC();
1097
1098 if ((handle == NULL) || (buffer == NULL))
1099 {
1100 return (status_t)kStatus_InvalidArgument;
1101 }
1102
1103 OSA_ENTER_CRITICAL();
1104 fun_ctrl = (sdioslv_fun_ctrl_t *)handle;
1105 port_ctrl = &fun_ctrl->cmd_port[SDU_PORT_FOR_READ];
1106
1107 if (port_ctrl->valid == 0U)
1108 {
1109 OSA_EXIT_CRITICAL();
1110 return (status_t)kStatus_Fail;
1111 }
1112
1113 if (port_ctrl->occupied != 0U )
1114 {
1115 OSA_EXIT_CRITICAL();
1116 return (status_t)kStatus_SDIOSLV_CmdPending;
1117 }
1118
1119 port_ctrl->buffer = buffer;
1120 port_ctrl->occupied = 1;
1121 if (SDIOSLV_SendCmdNonBlocking(fun_ctrl->regmap, buffer->data_addr, buffer->data_len) != kStatus_Success)
1122 {
1123 port_ctrl->buffer = NULL;
1124 port_ctrl->occupied = 0;
1125 OSA_EXIT_CRITICAL();
1126 return (status_t)kStatus_InvalidArgument;
1127 }
1128
1129 OSA_EXIT_CRITICAL();
1130 return (status_t)kStatus_Success;
1131 }
1132
1133 /*!
1134 * @brief SDU provide command buffer.
1135 *
1136 * Call this API after receiving #kStatus_SDIOSLV_FuncRequestBuffer from command
1137 * callback function to provide receive command buffer to SDU driver.
1138 *
1139 * @param handle Created by SDIOSLV_CreateHanle().
1140 * @param buffer Buffer used to refill receive command buffer.
1141 * @retval #kStatus_Success buffer refill sucessfully.
1142 * @retval #kStatus_Fail fail to refill buffer.
1143 */
SDU_RefillCmdBuffer(sdu_ctrl_t * ctrl)1144 static status_t SDU_RefillCmdBuffer(sdu_ctrl_t *ctrl)
1145 {
1146 sdioslv_fun_ctrl_t *fun_ctrl = NULL;
1147 sdioslv_port_ctrl_t *port_ctrl = NULL;
1148 sdu_buffer_t *sdu_node_buf = NULL;
1149 OSA_SR_ALLOC();
1150
1151 if ((ctrl == NULL) || (ctrl->handle == NULL))
1152 {
1153 return (status_t)kStatus_InvalidArgument;
1154 }
1155
1156 sdu_node_buf = (sdu_buffer_t *)LIST_RemoveHead(&ctrl->cmd_free_buffer[SDU_PORT_FOR_WRITE]);
1157 if (sdu_node_buf == NULL)
1158 {
1159 sdu_e("%s: No cmd free buffer for cmd_buf!\r\n", __FUNCTION__);
1160 return (status_t)kStatus_NoData;
1161 }
1162 sdu_node_buf->buffer.data_len = 0;
1163 sdu_node_buf->buffer.user_data = (uint32_t)sdu_node_buf;
1164
1165 OSA_ENTER_CRITICAL();
1166 fun_ctrl = (sdioslv_fun_ctrl_t *)(ctrl->handle);
1167 port_ctrl = &fun_ctrl->cmd_port[SDU_PORT_FOR_WRITE];
1168
1169 if (port_ctrl->valid == 0U)
1170 {
1171 goto refill_cmd_err;
1172 }
1173
1174 if (port_ctrl->occupied != 0U)
1175 {
1176 goto refill_cmd_err;
1177 }
1178
1179 port_ctrl->buffer = &(sdu_node_buf->buffer);
1180 port_ctrl->occupied = 1;
1181 if (SDIOSLV_RefillCmdBuffer(fun_ctrl->regmap, port_ctrl->buffer->data_addr) != kStatus_Success)
1182 {
1183 sdu_e("%s: SDIOSLV_RefillCmdBuffer fail!\r\n", __FUNCTION__);
1184 port_ctrl->buffer = NULL;
1185 port_ctrl->occupied = 0;
1186 goto refill_cmd_err;
1187 }
1188
1189 OSA_EXIT_CRITICAL();
1190 return (status_t)kStatus_Success;
1191
1192 refill_cmd_err:
1193 OSA_EXIT_CRITICAL();
1194 (void)LIST_AddTail(&ctrl->cmd_free_buffer[SDU_PORT_FOR_WRITE], &sdu_node_buf->link);
1195 return (status_t)kStatus_Fail;
1196 }
1197
1198 /*!
1199 * @brief SDU send data transfer.
1200 *
1201 * Call this API after calling the SDU_InitData() and SDU_CreateHandle()
1202 * to send data to host driver. The callback is always invoked from the
1203 * interrupt context.
1204 *
1205 * @param handle Created by SDIOSLV_CreateHanle().
1206 * @param buffer Buffer used to exchange to data SDIO host driver.
1207 * @retval #kStatus_Success buffer is added to data slot with problem.
1208 * @retval #kStatus_InvalidArgument Invalid argument.
1209 * @retval #kStatus_SDIOSLV_SendFull all data slots are occupied, application
1210 * should check and wait until data slot is available.
1211 * @retval #kStatus_Fail Fail to send data.
1212 */
SDU_SendDataNonBlocking(sdioslv_handle_t handle,transfer_buffer_t * buffer)1213 static status_t SDU_SendDataNonBlocking(sdioslv_handle_t handle, transfer_buffer_t *buffer)
1214 {
1215 sdioslv_fun_ctrl_t *fun_ctrl;
1216 sdioslv_port_ctrl_t *port_ctrl;
1217 uint8_t tx_port;
1218 OSA_SR_ALLOC();
1219
1220 if ((handle == NULL) || (buffer == NULL))
1221 {
1222 return (status_t)kStatus_InvalidArgument;
1223 }
1224
1225 OSA_ENTER_CRITICAL();
1226 fun_ctrl = (sdioslv_fun_ctrl_t *)handle;
1227 tx_port = fun_ctrl->curr_data_tx_port;
1228 if (tx_port >= fun_ctrl->config.used_port_num)
1229 {
1230 OSA_EXIT_CRITICAL();
1231 return (status_t)kStatus_SDIOSLV_SendFull;
1232 }
1233 port_ctrl = &fun_ctrl->data_port[SDU_PORT_FOR_READ][tx_port];
1234
1235 port_ctrl->buffer = buffer;
1236 port_ctrl->occupied = 1;
1237 if (SDIOSLV_SendDataNonBlocking(fun_ctrl->regmap, (sdioslv_port_t)tx_port, buffer->data_addr, buffer->data_len) != kStatus_Success)
1238 {
1239 port_ctrl->buffer = NULL;
1240 port_ctrl->occupied = 0;
1241 OSA_EXIT_CRITICAL();
1242 return (status_t)kStatus_InvalidArgument;
1243 }
1244
1245 OSA_EXIT_CRITICAL();
1246 #if 0
1247 SDU_AdjustAvailDataPort(fun_ctrl);
1248 #endif
1249 return (status_t)kStatus_Success;
1250 }
1251
1252 /*!
1253 * @brief SDU provide receive data buffer.
1254 *
1255 * Call this API after receiving #kStatus_SDIOSLV_FuncRequestBuffer from data
1256 * callback function to provide receive data buffer to SDU driver.
1257 *
1258 * @param handle Created by SDIOSLV_CreateHanle().
1259 * @param buffer Buffer used to refill receive data slots.
1260 * @param which slot should be refilled (got from kStatus_SDIOSLV_FuncRequestBuffer).
1261 * @retval #kStatus_Success refill buffer sucessfully.
1262 * @retval #kStatus_Fail fail to refill buffer.
1263 */
SDU_RefillDataBuffer(sdu_ctrl_t * ctrl,sdioslv_port_t port)1264 static status_t SDU_RefillDataBuffer(sdu_ctrl_t *ctrl, sdioslv_port_t port)
1265 {
1266 sdioslv_fun_ctrl_t *fun_ctrl = NULL;
1267 sdioslv_port_ctrl_t *port_ctrl = NULL;
1268 sdu_buffer_t *data_buf = NULL;
1269 OSA_SR_ALLOC();
1270
1271 if ((ctrl == NULL) || (ctrl->handle == NULL))
1272 {
1273 return (status_t)kStatus_InvalidArgument;
1274 }
1275
1276 if ((uint32_t)port >= SDU_MAX_PORT_NUM)
1277 {
1278 return (status_t)kStatus_InvalidArgument;
1279 }
1280
1281 data_buf = (sdu_buffer_t *)LIST_RemoveHead(&ctrl->data_free_buffer);
1282 if (data_buf == NULL)
1283 {
1284 sdu_e("%s: No free buffer for data_buf!\r\n", __FUNCTION__);
1285 return (status_t)kStatus_NoData;
1286 }
1287
1288 data_buf->buffer.data_len = 0;
1289 data_buf->buffer.user_data = (uint32_t)data_buf;
1290
1291 OSA_ENTER_CRITICAL();
1292 fun_ctrl = (sdioslv_fun_ctrl_t *)(ctrl->handle);
1293 port_ctrl = &fun_ctrl->data_port[SDU_PORT_FOR_WRITE][port];
1294
1295 if (port_ctrl->valid == 0U)
1296 {
1297 goto refill_data_err;
1298 }
1299
1300 if (port_ctrl->occupied != 0U)
1301 {
1302 goto refill_data_err;
1303 }
1304
1305 port_ctrl->buffer = &(data_buf->buffer);
1306 port_ctrl->occupied = 1;
1307 if (SDIOSLV_RefillDataBuffer(fun_ctrl->regmap, port, port_ctrl->buffer->data_addr) != kStatus_Success)
1308 {
1309 sdu_e("%s: SDIOSLV_RefillDataBuffer on port %x fail!\r\n", __FUNCTION__, port);
1310 port_ctrl->buffer = NULL;
1311 port_ctrl->occupied = 0;
1312 goto refill_data_err;
1313 }
1314
1315 OSA_EXIT_CRITICAL();
1316 return (status_t)kStatus_Success;
1317
1318 refill_data_err:
1319 OSA_EXIT_CRITICAL();
1320 (void)LIST_AddTail(&ctrl->data_free_buffer, &data_buf->link);
1321 return (status_t)kStatus_Fail;
1322 }
1323
1324 /*!
1325 * @brief SDU provide all free ports receive data buffer.
1326 *
1327 * @param ctrl Pointer to sdu_ctrl_t .
1328 * @retval #kStatus_Success refill buffer sucessfully.
1329 * @retval #kStatus_Fail fail to refill buffer.
1330 */
SDU_RefillFreePortsDataBuffer(sdu_ctrl_t * ctrl)1331 static status_t SDU_RefillFreePortsDataBuffer(sdu_ctrl_t *ctrl)
1332 {
1333 sdioslv_fun_ctrl_t *fun_ctrl = NULL;
1334 sdioslv_sdu_regmap_t *sdu_fsr = NULL;
1335 uint32_t wr_bit_map = 0;
1336 uint32_t i = 0;
1337 OSA_SR_ALLOC();
1338
1339 if (ctrl_sdu.sdu_state != SDU_INITIALIZED)
1340 {
1341 sdu_e("%s: return for sdu_state %d!\r\n", __FUNCTION__, ctrl_sdu.sdu_state);
1342 return (status_t)kStatus_Fail;
1343 }
1344
1345 OSA_ENTER_CRITICAL();
1346 fun_ctrl = (sdioslv_fun_ctrl_t *)(ctrl_sdu.handle);
1347 sdu_fsr = fun_ctrl->regmap;
1348 wr_bit_map = sdu_fsr->WrBitMap;
1349 for (i = 0; i < (uint32_t)fun_ctrl->config.used_port_num; i++)
1350 {
1351 if ((wr_bit_map & (uint32_t)(1U << i)) == (uint32_t)0U)
1352 {
1353 (void)SDU_RefillDataBuffer(&ctrl_sdu, (sdioslv_port_t)i);
1354 }
1355 }
1356
1357 OSA_EXIT_CRITICAL();
1358 return (status_t)kStatus_Success;
1359 }
1360
SDU_RecvCmdProcess(void)1361 static status_t SDU_RecvCmdProcess(void)
1362 {
1363 sdu_buffer_t *cmd_rcv = NULL;
1364 sdio_header_t *sdio_hdr = NULL;
1365 status_t ret = kStatus_Fail;
1366
1367 cmd_rcv = (sdu_buffer_t *)LIST_RemoveHead(&ctrl_sdu.cmd_q[SDU_PORT_FOR_WRITE]);
1368 if (cmd_rcv == NULL)
1369 {
1370 sdu_e("%s: NO buffer on cmd_rcv list!\r\n", __FUNCTION__);
1371 return ret;
1372 }
1373
1374 sdio_hdr = (sdio_header_t *)(cmd_rcv->buffer.data_addr);
1375 if ((sdio_hdr->len <= sizeof(sdio_header_t)) || (sdio_hdr->len > SDU_CMD_BUFFER_SIZE)
1376 || (sdio_hdr->type != SDU_TYPE_CMD))
1377 {
1378 sdu_e("%s: bad sdio_hdr: len=0x%x type=0x%x!\r\n", __FUNCTION__, sdio_hdr->len, sdio_hdr->type);
1379 ctrl_sdu.stat.err_tx_cmd_sdio_hdr++;
1380 }
1381 else
1382 {
1383 sdu_d("%s: SDIO hdr: len=%d type=%d!\r\n", __FUNCTION__, sdio_hdr->len, sdio_hdr->type);
1384 if (ctrl_sdu.sdu_cb_fn[SDU_TYPE_FOR_WRITE_CMD] != NULL)
1385 {
1386 //memcpy(data_addr, cmd_rcv->buffer.data_addr + sizeof(sdio_header_t), MIN(sdio_hdr->len, data_size));
1387 ctrl_sdu.sdu_cb_fn[SDU_TYPE_FOR_WRITE_CMD](cmd_rcv->buffer.data_addr + sizeof(sdio_header_t), sdio_hdr->len - sizeof(sdio_header_t) - CRC_LEN);
1388 ret = kStatus_Success;
1389 }
1390 if (kStatus_Success == ret)
1391 {
1392 ctrl_sdu.stat.succ_tx_cmd++;
1393 }
1394 else
1395 {
1396 ctrl_sdu.stat.err_tx_cmd_call_cb++;
1397 }
1398 }
1399 (void)LIST_AddTail(&ctrl_sdu.cmd_free_buffer[SDU_PORT_FOR_WRITE], &cmd_rcv->link);
1400 (void)SDU_RefillCmdBuffer(&ctrl_sdu);
1401
1402 return ret;
1403 }
1404
SDU_RecvCmd(void)1405 status_t SDU_RecvCmd(void)
1406 {
1407 osa_event_flags_t ev = 0;
1408 osa_status_t status = KOSA_StatusSuccess;
1409 status_t ret = kStatus_Fail;
1410
1411 while(true)
1412 {
1413 status = OSA_EventWait((osa_event_handle_t)(ctrl_sdu.event), SDU_CMD_RECEIVED, 0U, osaWaitForever_c, &ev);
1414
1415 if (KOSA_StatusSuccess == status)
1416 {
1417 if ((ev & SDU_CMD_RECEIVED) != 0U)
1418 {
1419 ret = SDU_RecvCmdProcess();
1420
1421 if (kStatus_Success == ret)
1422 {
1423 return ret;
1424 }
1425 }
1426 else
1427 {
1428 sdu_e("%s: wrong ev 0x%x!\r\n", __FUNCTION__, ev);
1429 }
1430 }
1431 else
1432 {
1433 sdu_e("%s: OSA_EventWait fail status=0x%x!\r\n", __FUNCTION__, status);
1434 }
1435 }
1436 }
1437
SDU_RecvDataProcess(void)1438 static status_t SDU_RecvDataProcess(void)
1439 {
1440 sdu_buffer_t *data_rcv = NULL;
1441 sdio_header_t *sdio_hdr = NULL;
1442 status_t ret = kStatus_Fail;
1443
1444 data_rcv = (sdu_buffer_t *)LIST_RemoveHead(&ctrl_sdu.data_q[SDU_PORT_FOR_WRITE]);
1445 if (data_rcv == NULL)
1446 {
1447 sdu_e("%s: NO buffer on data_rcv list!\r\n", __FUNCTION__);
1448 return ret;
1449 }
1450
1451 sdio_hdr = (sdio_header_t *)(data_rcv->buffer.data_addr);
1452 if ((sdio_hdr->len <= sizeof(sdio_header_t)) || (sdio_hdr->len > SDU_DATA_BUFFER_SIZE)
1453 || (sdio_hdr->type != SDU_TYPE_DATA))
1454 {
1455 sdu_e("%s: bad sdio_hdr: len=0x%x type=0x%x!\r\n", __FUNCTION__, sdio_hdr->len, sdio_hdr->type);
1456 ctrl_sdu.stat.err_tx_data_sdio_hdr++;
1457 }
1458 else
1459 {
1460 sdu_d("%s: SDIO hdr: len=%d type=%d!\r\n", __FUNCTION__, sdio_hdr->len, sdio_hdr->type);
1461 if (ctrl_sdu.sdu_cb_fn[SDU_TYPE_FOR_WRITE_DATA] != NULL)
1462 {
1463 //memcpy(data_addr, data_rcv->buffer.data_addr + sizeof(sdio_header_t), MIN(sdio_hdr->len, data_size));
1464 ctrl_sdu.sdu_cb_fn[SDU_TYPE_FOR_WRITE_DATA](data_rcv->buffer.data_addr + sizeof(sdio_header_t), sdio_hdr->len - sizeof(sdio_header_t) - CRC_LEN);
1465 ret = kStatus_Success;
1466 }
1467 }
1468 (void)LIST_AddTail(&ctrl_sdu.data_free_buffer, &data_rcv->link);
1469 //SDU_RefillDataBuffer(&ctrl_sdu);
1470 (void)SDU_RefillFreePortsDataBuffer(&ctrl_sdu);
1471
1472 return ret;
1473 }
1474
SDU_RecvData(void)1475 status_t SDU_RecvData(void)
1476 {
1477 osa_event_flags_t ev = 0;
1478 osa_status_t status = KOSA_StatusSuccess;
1479 status_t ret = kStatus_Fail;
1480 uint32_t succ_count = 0;
1481
1482 while(true)
1483 {
1484 status = OSA_EventWait((osa_event_handle_t)(ctrl_sdu.event), SDU_DATA_RECEIVED, 0U, osaWaitForever_c, &ev);
1485
1486 if (KOSA_StatusSuccess == status)
1487 {
1488 if ((ev & SDU_DATA_RECEIVED) != 0U)
1489 {
1490 while (LIST_GetHead(&ctrl_sdu.data_q[SDU_PORT_FOR_WRITE]) != NULL)
1491 {
1492 ret = SDU_RecvDataProcess();
1493 if (kStatus_Success == ret)
1494 {
1495 succ_count++;
1496 ctrl_sdu.stat.succ_tx_data++;
1497 }
1498 else
1499 {
1500 ctrl_sdu.stat.err_tx_data_call_cb++;
1501 }
1502 }
1503
1504 if (succ_count != 0U)
1505 {
1506 return ret;
1507 }
1508 }
1509 else
1510 {
1511 sdu_e("%s: wrong ev 0x%x!\r\n", __FUNCTION__, ev);
1512 }
1513 }
1514 else
1515 {
1516 sdu_e("%s: OSA_EventWait fail status=0x%x!\r\n", __FUNCTION__, status);
1517 }
1518 }
1519
1520 }
1521
1522 /*!
1523 * @brief SDU send cmd/event/data.
1524 *
1525 * @param sdu_for_read_type_t type for cmd/event/data.
1526 * @param data_addr Data Address.
1527 * @param data_len Data Length.
1528 * @retval #kStatus_Success buffer is added to data slot with problem.
1529 * @retval #kStatus_InvalidArgument Invalid argument.
1530 * @retval #kStatus_NoData No free buffer to use.
1531 * @retval #kStatus_Fail Fail to send data.
1532 */
SDU_Send(sdu_for_read_type_t type,uint8_t * data_addr,uint16_t data_len)1533 status_t SDU_Send(sdu_for_read_type_t type, uint8_t *data_addr, uint16_t data_len)
1534 {
1535 sdu_buffer_t *send_buffer = NULL;
1536 status_t status = kStatus_Fail;
1537 sdio_header_t *sdio_hdr = NULL;
1538
1539 if ((data_addr == NULL) || (data_len == 0U))
1540 {
1541 return (status_t)kStatus_InvalidArgument;
1542 }
1543
1544 if (type >= SDU_TYPE_FOR_READ_MAX)
1545 {
1546 return (status_t)kStatus_InvalidArgument;
1547 }
1548
1549 if (SDU_IsLinkUp() != true)
1550 {
1551 return (status_t)kStatus_Fail;
1552 }
1553
1554 switch (type)
1555 {
1556 case SDU_TYPE_FOR_READ_CMD:
1557 send_buffer = (sdu_buffer_t *)LIST_RemoveHead(&ctrl_sdu.cmd_free_buffer[SDU_PORT_FOR_READ]);
1558 break;
1559 case SDU_TYPE_FOR_READ_EVENT:
1560 send_buffer = (sdu_buffer_t *)LIST_RemoveHead(&ctrl_sdu.event_free_buffer);
1561 break;
1562 case SDU_TYPE_FOR_READ_DATA:
1563 send_buffer = (sdu_buffer_t *)LIST_RemoveHead(&ctrl_sdu.data_free_buffer);
1564 break;
1565 default:
1566 sdu_e("%s: Unknown type %d.\n\r", __func__, type);
1567 break;
1568 }
1569
1570 if (send_buffer == NULL)
1571 {
1572 if (type == SDU_TYPE_FOR_READ_DATA)
1573 {
1574 ctrl_sdu.stat.drop_tx_data++;
1575 }
1576 else
1577 {
1578 ctrl_sdu.stat.drop_tx_cmd++;
1579 }
1580
1581 sdu_d("%s: NO free_buffer for type %d!\r\n", __FUNCTION__, type);
1582 return (status_t)kStatus_NoData;
1583 }
1584
1585 if (data_len + sizeof(sdio_header_t) > send_buffer->buffer.data_size)
1586 {
1587 sdu_e("%s: data_len(%u) + sdiohdr(%lu) > buffersize(%u)!\r\n", __FUNCTION__,
1588 data_len, sizeof(sdio_header_t), send_buffer->buffer.data_size);
1589 return (status_t)kStatus_InvalidArgument;
1590 }
1591
1592 sdio_hdr = (sdio_header_t *)(send_buffer->buffer.data_addr);
1593 switch (type)
1594 {
1595 case SDU_TYPE_FOR_READ_CMD:
1596 sdio_hdr->type = SDU_TYPE_CMD;
1597 break;
1598 case SDU_TYPE_FOR_READ_EVENT:
1599 sdio_hdr->type = SDU_TYPE_EVENT;
1600 break;
1601 case SDU_TYPE_FOR_READ_DATA:
1602 sdio_hdr->type = SDU_TYPE_DATA;
1603 break;
1604 default:
1605 sdu_e("%s: Unknown type %d.\n\r", __func__, type);
1606 break;
1607 }
1608 sdio_hdr->len = (uint16_t)MIN(data_len + sizeof(sdio_header_t), send_buffer->buffer.data_size);
1609
1610 sdu_d("%s: buffer.data_size=%u data_len=%u sdio_hdr->len=%u\r\n", __FUNCTION__,
1611 send_buffer->buffer.data_size, data_len, sdio_hdr->len);
1612 (void)memcpy(send_buffer->buffer.data_addr + sizeof(sdio_header_t), data_addr, sdio_hdr->len - sizeof(sdio_header_t));
1613 send_buffer->buffer.data_len = sdio_hdr->len;
1614 send_buffer->buffer.user_data = (uint32_t)send_buffer;
1615
1616 switch (type)
1617 {
1618 case SDU_TYPE_FOR_READ_CMD:
1619 (void)LIST_AddTail(&ctrl_sdu.cmd_q[SDU_PORT_FOR_READ], &send_buffer->link);
1620 status = SDU_SendCmdNonBlocking(ctrl_sdu.handle, &send_buffer->buffer);
1621 if ((status == (status_t)kStatus_Success) || (status == (status_t)kStatus_SDIOSLV_CmdPending))
1622 {
1623 sdu_d("%s: %d SendCmdNonBlocking ok 0x%x!\r\n", __FUNCTION__, type, status);
1624 }
1625 else
1626 {
1627 sdu_e("%s: %d SendCmdNonBlocking fail 0x%x!\r\n", __FUNCTION__, type, status);
1628 (void)LIST_RemoveElement(&send_buffer->link);
1629 (void)LIST_AddTail(&ctrl_sdu.cmd_free_buffer[SDU_PORT_FOR_READ], &send_buffer->link);
1630 return (status_t)kStatus_Fail;
1631 }
1632 break;
1633 case SDU_TYPE_FOR_READ_EVENT:
1634 (void)LIST_AddTail(&ctrl_sdu.event_q, &send_buffer->link);
1635 status = SDU_SendCmdNonBlocking(ctrl_sdu.handle, &send_buffer->buffer);
1636 if ((status == (status_t)kStatus_Success) || (status == (status_t)kStatus_SDIOSLV_CmdPending))
1637 {
1638 sdu_d("%s: %d SendCmdNonBlocking ok 0x%x!\r\n", __FUNCTION__, type, status);
1639 }
1640 else
1641 {
1642 sdu_e("%s: %d SendCmdNonBlocking fail 0x%x!\r\n", __FUNCTION__, type, status);
1643 (void)LIST_RemoveElement(&send_buffer->link);
1644 (void)LIST_AddTail(&ctrl_sdu.event_free_buffer, &send_buffer->link);
1645 return (status_t)kStatus_Fail;
1646 }
1647 break;
1648 case SDU_TYPE_FOR_READ_DATA:
1649 (void)LIST_AddTail(&ctrl_sdu.data_q[SDU_PORT_FOR_READ], &send_buffer->link);
1650 status = SDU_SendDataNonBlocking(ctrl_sdu.handle, &send_buffer->buffer);
1651 if ((status == (status_t)kStatus_Success) || (status == (status_t)kStatus_SDIOSLV_SendFull))
1652 {
1653 sdu_d("%s: SendDataNonBlocking ok 0x%x!\r\n", __FUNCTION__, status);
1654 }
1655 else
1656 {
1657 sdu_e("%s: SendDataNonBlocking fail 0x%x!\r\n", __FUNCTION__, status);
1658 (void)LIST_RemoveElement(&send_buffer->link);
1659 (void)LIST_AddTail(&ctrl_sdu.data_free_buffer, &send_buffer->link);
1660 return (status_t)kStatus_Fail;
1661 }
1662 break;
1663 default:
1664 sdu_e("%s: Unknown type %d.\n\r", __func__, type);
1665 break;
1666 }
1667
1668 return (status_t)kStatus_Success;
1669 }
1670
1671
1672 /*!
1673 * @brief SDU interrupt service routine.
1674 *
1675 * @param void None.
1676 */
1677 static uint32_t g_SDU_IRQHandler_cnt = 0;
1678
SDU_SLV_IRQHandler(void)1679 static void SDU_SLV_IRQHandler(void)
1680 {
1681 sdioslv_fun_ctrl_t *fun_ctrl;
1682 sdioslv_sdu_regmap_t *sdu_fsr;
1683 uint32_t int_status;
1684 uint8_t i, crc_err;
1685
1686 g_SDU_IRQHandler_cnt++;
1687
1688 for (i = 0; i < sdu_ctrl.used_fun_num; i++)
1689 {
1690 fun_ctrl = sdu_ctrl.func_ctrl[i];
1691 if ((fun_ctrl->initialized != 0U) && (fun_ctrl->enable != 0U))
1692 {
1693 sdu_fsr = fun_ctrl->regmap;
1694 int_status = sdu_fsr->CardIntStatus;
1695 crc_err = sdu_fsr->HostTransferStatus;
1696
1697 if ((int_status & (uint32_t)SDIO_CCR_CIC_CmdUpLdOvr) != 0U)
1698 {
1699 SDU_ProcessCmdUpLdOvr(fun_ctrl);
1700 sdu_fsr->CardIntStatus &= ~((uint32_t)SDIO_CCR_CIC_CmdUpLdOvr);
1701 }
1702
1703 if (((int_status & (uint32_t)SDIO_CCR_CIC_CmdDnLdOvr) != 0U) && ((crc_err & (uint32_t)SDIO_CCR_HOST_DnLdCRC_err) == 0U))
1704 {
1705 SDU_ProcessCmdDnLdOvr(fun_ctrl);
1706 sdu_fsr->CardIntStatus &= ~((uint32_t)SDIO_CCR_CIC_CmdDnLdOvr);
1707 }
1708
1709 if ((int_status & (uint32_t)SDIO_CCR_CIC_UpLdOvr) != 0U)
1710 {
1711 SDU_ProcessDataUpLdOvr(fun_ctrl);
1712 sdu_fsr->CardIntStatus &= ~((uint32_t)SDIO_CCR_CIC_UpLdOvr);
1713 }
1714
1715 if (((int_status & (uint32_t)SDIO_CCR_CIC_DnLdOvr) != 0U) && ((crc_err & (uint32_t)SDIO_CCR_HOST_DnLdCRC_err) == 0U))
1716 {
1717 SDU_ProcessDataDnLdOvr(fun_ctrl);
1718 sdu_fsr->CardIntStatus &= ~((uint32_t)SDIO_CCR_CIC_DnLdOvr);
1719 }
1720
1721 if ((int_status & ((uint32_t)SDIO_CCR_CIC_PwrUp)) != 0U)
1722 {
1723 sdu_fsr->CardIntStatus &= ~((uint32_t)SDIO_CCR_CIC_PwrUp);
1724 }
1725 }
1726 }
1727 }
1728
SDU_DriverIRQHandler(void)1729 void SDU_DriverIRQHandler(void)
1730 {
1731 SDU_SLV_IRQHandler();
1732 }
1733
SDU_GetDefaultCISTable(const uint32_t SDU_BASE)1734 static void SDU_GetDefaultCISTable(const uint32_t SDU_BASE)
1735 {
1736 //uint32_t vid = ROM_SDIO_VID; // 0x1;
1737 uint32_t pid;
1738 uint32_t i;
1739 uint32_t curr_offset;
1740 uint32_t cis_addr;
1741
1742 char *vers[4] = {"NXP\000Wireless Device ID: XX\000\000\377", "NXP WiFi Device\000\000\377",
1743 "NXP Bluetooth Device\000\000\377", "NXP 802.15.4 Device\000\000\377"};
1744
1745 curr_offset = SDU_BASE + SD_CIS_DATA0_FN0;
1746
1747 for (i = 0; i < 4U; i++)
1748 {
1749 (void)memset((uint8_t *)curr_offset, 0, 0x80);
1750 REG8(curr_offset + 0U) = 0xffU;
1751 curr_offset += 0x80U;
1752 }
1753
1754 // FN0
1755 cis_addr = SDU_BASE + SD_CIS_DATA0_FN0;
1756 pid = ROM_SDIO_PID0; // 0; // FIXME g_SDIO_pid[0];
1757 emitvers(&cis_addr, (uint8_t *)vers[0], 1);
1758 emitvidpid(&cis_addr, ROM_SDIO_VID, pid);
1759 emitfuncid(&cis_addr);
1760 emitfunce(&cis_addr);
1761 emit1(&cis_addr, 0xff);
1762 emit1(&cis_addr, 0x00);
1763
1764 // FN1
1765 cis_addr = SDU_BASE + SD_CIS_DATA0_FN1;
1766 pid = ROM_SDIO_PID1; // 0; // FIXME g_SDIO_pid[1];
1767 emitvers(&cis_addr, (uint8_t *)vers[1], 0);
1768 emitvidpid(&cis_addr, ROM_SDIO_VID, pid);
1769 emitfuncid(&cis_addr);
1770 emitfunce_extended(&cis_addr, 1);
1771 emit1(&cis_addr, 0xff);
1772 emit1(&cis_addr, 0x00);
1773 }
1774
SDU_GetDefaultConfig(sdio_slave_config_t * config)1775 static void SDU_GetDefaultConfig(sdio_slave_config_t *config)
1776 {
1777 assert(NULL != config);
1778
1779 config->cpu_num = SDU_INT_CPU_NUM;
1780 config->cis_table_callback = SDU_GetDefaultCISTable;
1781 config->cmd_tx_format = 2;
1782 config->cmd_rd_format = 1;
1783 config->data_tx_format = 2;
1784 config->data_rd_format = 1;
1785 }
1786
SDU_SDIOSLVInit(void)1787 static status_t SDU_SDIOSLVInit(void)
1788 {
1789 sdio_slave_config_t config;
1790 status_t rc;
1791
1792 SDIOSLV_Init0();
1793
1794 SDU_GetDefaultConfig(&config);
1795 rc = SDIOSLV_Init1(SDU_FN_CARD, &config);
1796 if (rc != kStatus_Success)
1797 {
1798 sdu_e("%s: SDIOSLV_Init1 fail: %d\r\n", __FUNCTION__, rc);
1799 return rc;
1800 }
1801
1802 return rc;
1803 }
1804
SDU_SetFwReady(void)1805 static status_t SDU_SetFwReady(void)
1806 {
1807 status_t ret = kStatus_Fail;
1808
1809 ret = SDIOSLV_WriteScratchRegister(kSDIOSLV_FunctionNum1,
1810 kSDIOSLV_ScratchGroup2, kSDIOSLV_ScratchOffset0, 0xdc);
1811 if (ret != kStatus_Success) {
1812 sdu_e("%s: SDIOSLV_WriteScratchRegister Group%u Offset%u fail: %d\r\n",
1813 __FUNCTION__, kSDIOSLV_ScratchGroup2, kSDIOSLV_ScratchOffset0, ret);
1814 goto done;
1815 }
1816
1817 ret = SDIOSLV_WriteScratchRegister(kSDIOSLV_FunctionNum1,
1818 kSDIOSLV_ScratchGroup2, kSDIOSLV_ScratchOffset1, 0xfe);
1819 if (ret != kStatus_Success) {
1820 sdu_e("%s: SDIOSLV_WriteScratchRegister Group%u Offset%u fail: %d\r\n",
1821 __FUNCTION__, kSDIOSLV_ScratchGroup2, kSDIOSLV_ScratchOffset1, ret);
1822 goto done;
1823 }
1824
1825 done:
1826 return ret;
1827 }
1828
SDU_ClrFwReady(void)1829 static status_t SDU_ClrFwReady(void)
1830 {
1831 status_t ret = kStatus_Fail;
1832
1833 ret = SDIOSLV_WriteScratchRegister(kSDIOSLV_FunctionNum1,
1834 kSDIOSLV_ScratchGroup2, kSDIOSLV_ScratchOffset0, 0x00);
1835 if (ret != kStatus_Success) {
1836 sdu_e("%s: SDIOSLV_WriteScratchRegister Group%u Offset%u fail: %d\r\n",
1837 __FUNCTION__, kSDIOSLV_ScratchGroup2, kSDIOSLV_ScratchOffset0, ret);
1838 goto done;
1839 }
1840
1841 ret = SDIOSLV_WriteScratchRegister(kSDIOSLV_FunctionNum1,
1842 kSDIOSLV_ScratchGroup2, kSDIOSLV_ScratchOffset1, 0x00);
1843 if (ret != kStatus_Success) {
1844 sdu_e("%s: SDIOSLV_WriteScratchRegister Group%u Offset%u fail: %d\r\n",
1845 __FUNCTION__, kSDIOSLV_ScratchGroup2, kSDIOSLV_ScratchOffset1, ret);
1846 goto done;
1847 }
1848
1849 done:
1850 return ret;
1851 }
1852
SDU_Init(void)1853 status_t SDU_Init(void)
1854 {
1855 status_t rc = kStatus_Success;
1856 OSA_SR_ALLOC();
1857
1858 OSA_ENTER_CRITICAL();
1859 sdu_d("Enter %s: sdu_state=%d.\r\n", __FUNCTION__, ctrl_sdu.sdu_state);
1860
1861 if (ctrl_sdu.sdu_state != SDU_UNINITIALIZED)
1862 {
1863 sdu_e("%s: ctrl_sdu.sdu_state=0x%x\r\n", __FUNCTION__, ctrl_sdu.sdu_state);
1864 goto done;
1865 }
1866 ctrl_sdu.sdu_state = SDU_INITIALIZING;
1867
1868 sdu_d("SDIOSLV Init.\r\n");
1869 rc = SDU_SDIOSLVInit();
1870 if (kStatus_Success != rc)
1871 {
1872 sdu_e("%s: SDU_SDIOSLVInit fail: 0x%x\r\n", __FUNCTION__, rc);
1873 goto done;
1874 }
1875
1876 sdu_d("SDU Inner Init.\r\n");
1877 rc = SDU_InnerInit();
1878 if (kStatus_Success != rc)
1879 {
1880 sdu_e("%s: SDU_InnerInit fail: 0x%x\r\n", __FUNCTION__, rc);
1881 goto done;
1882 }
1883
1884 sdu_d("Create Data Recv Task.\r\n");
1885 if (KOSA_StatusSuccess != OSA_TaskCreate((osa_task_handle_t)ctrl_sdu.recvTaskId, OSA_TASK(SDU_RecvTask), &ctrl_sdu))
1886 {
1887 sdu_e("Can't create SDU data recv task.\r\n");
1888 rc = kStatus_Fail;
1889 goto done;
1890 }
1891
1892 sdu_d("Create SDU event.\r\n");
1893 if (KOSA_StatusSuccess != OSA_EventCreate((osa_event_handle_t)ctrl_sdu.event, 1U))
1894 {
1895 sdu_e("Can't create SDU event.\r\n");
1896 (void)OSA_TaskDestroy((osa_task_handle_t)ctrl_sdu.recvTaskId);
1897 rc = kStatus_Fail;
1898 goto done;
1899 }
1900
1901 os_ClearPendingISR(SDU_IRQn);
1902 /* Interrupt must be maskable by FreeRTOS critical section */
1903 NVIC_SetPriority(SDU_IRQn, 2);
1904 (void)os_InterruptMaskSet(SDU_IRQn);
1905
1906 rc = SDU_SetFwReady();
1907 if (kStatus_Success != rc)
1908 {
1909 sdu_e("%s: SDU_SetFwReady fail: 0x%x\r\n", __FUNCTION__, rc);
1910 goto done;
1911 }
1912
1913 ctrl_sdu.sdu_state = SDU_INITIALIZED;
1914
1915 #ifdef CONFIG_SDIO_TEST_LOOPBACK
1916 (void)SDU_InstallCallback(SDU_TYPE_FOR_WRITE_CMD, SDU_LoopbackRecvCmdHandler);
1917 (void)SDU_InstallCallback(SDU_TYPE_FOR_WRITE_DATA, SDU_LoopbackRecvDataHandler);
1918 #endif
1919
1920 done:
1921 if (kStatus_Success != rc)
1922 {
1923 SDU_InnerDeinit();
1924 }
1925
1926 sdu_d("Leave %s: sdu_state=%d rc=0x%x.\r\n", __FUNCTION__, ctrl_sdu.sdu_state, rc);
1927 OSA_EXIT_CRITICAL();
1928 return rc;
1929 }
1930
SDU_Deinit(void)1931 void SDU_Deinit(void)
1932 {
1933 OSA_SR_ALLOC();
1934
1935 OSA_ENTER_CRITICAL();
1936
1937 sdu_d("Enter %s: sdu_state=%d.\r\n", __FUNCTION__, ctrl_sdu.sdu_state);
1938 if (ctrl_sdu.sdu_state == SDU_UNINITIALIZED)
1939 {
1940 sdu_e("%s: ctrl_sdu.sdu_state=0x%x\r\n", __FUNCTION__, ctrl_sdu.sdu_state);
1941 goto done;
1942 }
1943
1944 (void)SDU_ClrFwReady();
1945
1946 (void)OSA_TaskDestroy((osa_task_handle_t)ctrl_sdu.recvTaskId);
1947 (void)OSA_EventDestroy((osa_event_handle_t)ctrl_sdu.event);
1948
1949 SDU_InnerDeinit();
1950
1951 done:
1952 sdu_d("Leave %s: sdu_state=%d.\r\n", __FUNCTION__, ctrl_sdu.sdu_state);
1953 OSA_EXIT_CRITICAL();
1954 }
1955
SDU_InstallCallback(sdu_for_write_type_t type,sdu_callback_t callback)1956 status_t SDU_InstallCallback(sdu_for_write_type_t type, sdu_callback_t callback)
1957 {
1958 assert(SDU_TYPE_FOR_WRITE_MAX > type);
1959
1960 ctrl_sdu.sdu_cb_fn[type] = callback;
1961
1962 return (status_t)kStatus_Success;
1963 }
1964
1965