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