1 /***********************************************************************************************//**
2  * \file cybsp_wifi.c
3  *
4  * \brief
5  * Provides utility functions that are used by board support packages.
6  *
7  ***************************************************************************************************
8  * \copyright
9  * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
10  * an affiliate of Cypress Semiconductor Corporation
11  *
12  * SPDX-License-Identifier: Apache-2.0
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  *     http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  **************************************************************************************************/
26 
27 #include "cybsp.h"
28 #include "cybsp_wifi.h"
29 #include "cy_network_buffer.h"
30 #include "cyabs_rtos.h"
31 #include "whd_types.h"
32 #include "cyhal.h"
33 
34 #if defined(__cplusplus)
35 extern "C" {
36 #endif
37 
38 /**
39  * \addtogroup group_bsp_wifi
40  * \{
41  * Macros to abstract out whether the LEDs & Buttons are wired high or active low.
42  */
43 
44 /** Defines the amount of stack memory available for the wifi thread. */
45 #if !defined(CY_WIFI_THREAD_STACK_SIZE)
46 #define CY_WIFI_THREAD_STACK_SIZE           (5120)
47 #endif
48 
49 /** Defines the priority of the thread that services wifi packets. Legal values are defined by the
50  *  RTOS being used.
51  */
52 #if !defined(CY_WIFI_THREAD_PRIORITY)
53 #define CY_WIFI_THREAD_PRIORITY             (CY_RTOS_PRIORITY_HIGH)
54 #endif
55 
56 /** Defines the country this will operate in for wifi initialization parameters. See the
57  *  wifi-host-driver's whd_country_code_t for legal options.
58  */
59 #if !defined(CY_WIFI_COUNTRY)
60 #define CY_WIFI_COUNTRY                     (WHD_COUNTRY_AUSTRALIA)
61 #endif
62 
63 /** Defines the priority of the interrupt that handles out-of-band notifications from the wifi
64  *  chip. Legal values are defined by the MCU running this code.
65  */
66 #if !defined(CY_WIFI_OOB_INTR_PRIORITY)
67     #define CY_WIFI_OOB_INTR_PRIORITY       (2)
68 #endif
69 
70 /** Defines whether to use the out-of-band pin to allow the WIFI chip to wake up the MCU. */
71 #if defined(CY_WIFI_HOST_WAKE_SW_FORCE)
72     #define CY_USE_OOB_INTR                 (CY_WIFI_HOST_WAKE_SW_FORCE)
73 #else
74     #define CY_USE_OOB_INTR                 (1u)
75 #endif // defined(CY_WIFI_HOST_WAKE_SW_FORCE)
76 
77 /** \} group_bsp_wifi */
78 
79 #define DEFAULT_OOB_PIN                     (0)
80 #define WLAN_POWER_UP_DELAY_MS              (250)
81 #define WLAN_CBUCK_DISCHARGE_MS             (10)
82 
83 #if defined(COMPONENT_WIFI_INTERFACE_SDIO) || \
84     defined(COMPONENT_WIFI_INTERFACE_SPI) || \
85     defined(COMPONENT_WIFI_INTERFACE_M2M)
86 
87 // Old versions of the BSP performed WIFI SDIO init as part of cybsp_init() this has been replaced
88 // with just minimal resource reservation when needed in the latest versions of BSPs.
89 #define CYBSP_WIFI_SDIO_NEEDS_INIT          (1)
90 
91 #else
92 
93 #if (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_SDIO_INTERFACE)
94 #define COMPONENT_WIFI_INTERFACE_SDIO
95 #elif (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_SPI_INTERFACE)
96 #define COMPONENT_WIFI_INTERFACE_SPI
97 #elif (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_M2M_INTERFACE)
98 #define COMPONENT_WIFI_INTERFACE_M2M
99 #else
100 // For old versions of HAL/BSP fallback to the default interface
101 #define COMPONENT_WIFI_INTERFACE_SDIO
102 #endif
103 
104 #endif // if defined(COMPONENT_WIFI_INTERFACE_SDIO) || defined(COMPONENT_WIFI_INTERFACE_SPI) ||
105 // defined(COMPONENT_WIFI_INTERFACE_M2M)
106 
107 #if !defined(COMPONENT_WIFI_INTERFACE_M2M)
108 
109 #define SDIO_ENUMERATION_TRIES              (500)
110 #define SDIO_RETRY_DELAY_MS                 (1)
111 #define SDIO_BUS_LEVEL_MAX_RETRIES          (5)
112 
113 #define SDIO_FREQ_25MHZ                     (25000000)
114 #define SDIO_FREQ_50MHZ                     (50000000)
115 
116 // Switching to 1.8 Request / Switching to 1.8V Accepted
117 #define SDIO_CMD5_S18R_BIT                  (1UL << 24)
118 // Number of I/O functions position in CMD5 response (R4)
119 #define SDIO_CMD5_RESP_IO_FUNC_POS          (28)
120 // Mask of I/O Number in CMD5 response (R4). This field is 3-bit wide
121 #define SDIO_CMD5_RESP_IO_FUNC_MSK          (0x7)
122 // The IO OCR register mask in CMD5 request / response (R4)
123 #define SDIO_CMD5_IO_OCR_MSK                (0x00FFFFFFUL)
124 // C bit in CMD5 response. Set to 1 if Card is ready to operate after initialization
125 #define SDIO_CMD5_RESP_IORDY                (1UL << 31)
126 
127 // Per SDIO Specification - IO_RW_DIRECT Command (CMD52)
128 
129 // This bit determines the direction of the I/O operation. If this bit is 0, this command shall read
130 // data from the SDIO
131 #define SDIO_CMD52_ARG_RW_READ              (0)
132 #define SDIO_CMD52_ARG_RW_WRITE             (1)
133 // The Read after Write flag. If this bit is set to 1 and the R/W flag is set to 1, then the command
134 // shall read the value of the register after the write
135 #define SDIO_CMD52_ARG_RAW_NOT_SET          (0)
136 #define SDIO_CMD52_ARG_RAW_SET              (1)
137 // The number of the function within the I/O card you wish to read or write. Function 0 selects the
138 // common I/O area (CIA)
139 #define SDIO_FUNC_NUM_0                     (0)
140 
141 // Per SDIO Specification -Card Common Control Registers (CCCR)
142 
143 // Bus Speed Select register
144 #define SDIO_CMD52_CCCR_SPEED_SLCT_ADDR     (0x00013)
145 // Select High Speed by setting BSS0 bit
146 #define SDIO_CMD52_CCCR_SPEED_SLCT_HS       (0x2)
147 
148 // Per SDIO specification - IO_RW_DIRECT Response (R5)
149 
150 // | Start | Dir | CMD Index | Stuff | Response Flags Bit | Read or Write Data | CRC7 | End |
151 // ------------------------------------------------------------------------------------------
152 // |   1   |  1  |     6     |  16   |          8         |         8          |  7   |  1  |
153 
154 // Expected response for High Speed support check command
155 //                                   | CMD=DAT lines free | High-Speed support |
156 //                                   |     00010000b      |     00000001b      |
157 #define SDIO_CMD52_CCCR_SPEED_SELECT_RESP_HS_SUPPORTED  (0x00001001)
158 // Expected response for High Speed support check command
159 //                                   | CMD=DAT lines free | HS/SDR25 activated |
160 //                                   |     00010000b      |     00000010b      |
161 #define SDIO_CMD52_CCCR_SPEED_SELECT_RESP_HS_SELECTED   (0x00001002)
162 
163 // *SUSPEND-FORMATTING*
164 #if (CY_USE_OOB_INTR != 0)
165     // Setup configuration based on configurator or BSP, where configurator has precedence.
166     #if defined(CYCFG_WIFI_HOST_WAKE_ENABLED)
167         #define CY_WIFI_HOST_WAKE_GPIO  CYCFG_WIFI_HOST_WAKE_GPIO
168         #define CY_WIFI_HOST_WAKE_IRQ_EVENT CYCFG_WIFI_HOST_WAKE_IRQ_EVENT
169     #else
170         // Setup host-wake pin
171         #if defined(CYBSP_WIFI_HOST_WAKE)
172             #define CY_WIFI_HOST_WAKE_GPIO CYBSP_WIFI_HOST_WAKE
173         #else
174             #error "CYBSP_WIFI_HOST_WAKE must be defined"
175         #endif
176         // Setup host-wake irq
177         #if defined(CYBSP_WIFI_HOST_WAKE_IRQ_EVENT)
178             #define CY_WIFI_HOST_WAKE_IRQ_EVENT CYBSP_WIFI_HOST_WAKE_IRQ_EVENT
179         #else
180             #error "CYBSP_WIFI_HOST_WAKE_IRQ_EVENT must be defined"
181         #endif
182     #endif // if defined(CYCFG_WIFI_HOST_WAKE_ENABLED)
183 #else // if (CY_USE_OOB_INTR != 0)
184     #define CY_WIFI_HOST_WAKE_GPIO      CYHAL_NC_PIN_VALUE
185     #define CY_WIFI_HOST_WAKE_IRQ_EVENT 0
186 #endif // (CY_USE_OOB_INTR != 0)
187 // *RESUME-FORMATTING*
188 
189 // Add compatability for HAL 1.x
190 #if !defined(CYHAL_API_VERSION)
191 typedef cyhal_transfer_t            cyhal_sdio_transfer_type_t;
192 #define CYHAL_SDIO_XFER_TYPE_READ   CYHAL_READ
193 #define CYHAL_SDIO_XFER_TYPE_WRITE  CYHAL_WRITE
194 #endif
195 
196 #endif // if !defined(COMPONENT_WIFI_INTERFACE_M2M)
197 
198 static whd_driver_t whd_drv;
199 
200 extern whd_resource_source_t resource_ops;
201 
202 static whd_init_config_t init_config_default =
203 {
204     .thread_stack_size  = CY_WIFI_THREAD_STACK_SIZE,
205     .thread_stack_start = NULL,
206     .thread_priority    = (uint32_t)CY_WIFI_THREAD_PRIORITY,
207     .country            = CY_WIFI_COUNTRY
208 };
209 
210 static whd_buffer_funcs_t buffer_if_default =
211 {
212     .whd_host_buffer_get                       = cy_host_buffer_get,
213     .whd_buffer_release                        = cy_buffer_release,
214     .whd_buffer_get_current_piece_data_pointer = cy_buffer_get_current_piece_data_pointer,
215     .whd_buffer_get_current_piece_size         = cy_buffer_get_current_piece_size,
216     .whd_buffer_set_size                       = cy_buffer_set_size,
217     .whd_buffer_add_remove_at_front            = cy_buffer_add_remove_at_front,
218 };
219 
220 static whd_netif_funcs_t netif_if_default =
221 {
222     .whd_network_process_ethernet_data = cy_network_process_ethernet_data,
223 };
224 
225 #if !defined(COMPONENT_WIFI_INTERFACE_M2M)
226 static const whd_oob_config_t OOB_CONFIG =
227 {
228     .host_oob_pin      = CY_WIFI_HOST_WAKE_GPIO,
229     .dev_gpio_sel      = DEFAULT_OOB_PIN,
230     .is_falling_edge   = (CY_WIFI_HOST_WAKE_IRQ_EVENT == CYHAL_GPIO_IRQ_FALL)
231         ? WHD_TRUE
232         : WHD_FALSE,
233     .intr_priority     = CY_WIFI_OOB_INTR_PRIORITY
234 };
235 
236 
237 //--------------------------------------------------------------------------------------------------
238 // _cybsp_wifi_reset_wifi_chip
239 //--------------------------------------------------------------------------------------------------
_cybsp_wifi_reset_wifi_chip(void)240 static void _cybsp_wifi_reset_wifi_chip(void)
241 {
242     // WiFi into reset
243     // Allow CBUCK regulator to discharge
244     (void)cyhal_system_delay_ms(WLAN_CBUCK_DISCHARGE_MS);
245     // WiFi out of reset
246     cyhal_gpio_write(CYBSP_WIFI_WL_REG_ON, true);
247     (void)cyhal_system_delay_ms(WLAN_POWER_UP_DELAY_MS);
248 }
249 
250 
251 #endif // if !defined(COMPONENT_WIFI_INTERFACE_M2M)
252 
253 
254 #if defined(COMPONENT_WIFI_INTERFACE_SDIO)
255 //--------------------------------------------------------------------------------------------------
256 // _cybsp_wifi_sdio_try_send_cmd
257 //--------------------------------------------------------------------------------------------------
_cybsp_wifi_sdio_try_send_cmd(cyhal_sdio_t * sdio_object,cyhal_sdio_transfer_type_t direction,cyhal_sdio_command_t command,uint32_t argument,uint32_t * response)258 static cy_rslt_t _cybsp_wifi_sdio_try_send_cmd(cyhal_sdio_t* sdio_object,
259                                                cyhal_sdio_transfer_type_t direction,
260                                                cyhal_sdio_command_t command, uint32_t argument,
261                                                uint32_t* response)
262 {
263     uint8_t   loop_count = 0;
264     cy_rslt_t result     = CYBSP_RSLT_WIFI_SDIO_ENUM_TIMEOUT;
265     do
266     {
267         result = cyhal_sdio_send_cmd(sdio_object, direction, command, argument, response);
268         if (result != CY_RSLT_SUCCESS)
269         {
270             cyhal_system_delay_ms(SDIO_RETRY_DELAY_MS);
271         }
272         loop_count++;
273     } while((result != CY_RSLT_SUCCESS) && (loop_count <= SDIO_BUS_LEVEL_MAX_RETRIES));
274     return result;
275 }
276 
277 
278 #if !defined(CYHAL_UDB_SDIO)
279 //--------------------------------------------------------------------------------------------------
280 // _cybsp_wifi_create_cmd_52_arg
281 //--------------------------------------------------------------------------------------------------
_cybsp_wifi_create_cmd_52_arg(uint8_t rw,uint8_t func,uint8_t raw,uint32_t addr,uint8_t data)282 static uint32_t _cybsp_wifi_create_cmd_52_arg(uint8_t rw, uint8_t func, uint8_t raw, uint32_t addr,
283                                               uint8_t data)
284 {
285     return (((rw & 0x01) << 31)      /* set R/W flag */
286             | ((func & 0x07) << 28)  /* set the function number */
287             | ((raw & 0x01) << 27)   /* set the RAW flag */
288             | ((addr & 0x1FFFF) << 9) /* set the address */
289             | data);                 /* set the data */
290 }
291 
292 
293 #endif /* !defined(CYHAL_UDB_SDIO) */
294 
295 //--------------------------------------------------------------------------------------------------
296 // _cybsp_wifi_sdio_card_init
297 //--------------------------------------------------------------------------------------------------
_cybsp_wifi_sdio_card_init(cyhal_sdio_t * sdio_object)298 static cy_rslt_t _cybsp_wifi_sdio_card_init(cyhal_sdio_t* sdio_object)
299 {
300     cy_rslt_t result;
301     uint32_t  loop_count = 0;
302     uint32_t  rel_addr;
303 
304     uint32_t response       = 0;
305     uint32_t no_argument    = 0;
306 
307     #if !defined(CYHAL_UDB_SDIO)
308     uint32_t argument       = 0;
309     uint32_t io_num         = 0;
310     bool     abort_sdio     = false;
311     #else
312     const bool abort_sdio   = false;
313     #endif /* !defined(CYHAL_UDB_SDIO) */
314 
315     do
316     {
317         // Send CMD0 to set it to idle state
318         result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_WRITE,
319                                                CYHAL_SDIO_CMD_GO_IDLE_STATE,
320                                                no_argument, &response /*ignored*/);
321 
322         // CMD5.
323         if (result == CY_RSLT_SUCCESS)
324         {
325             result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_READ,
326                                                    CYHAL_SDIO_CMD_IO_SEND_OP_COND,
327                                                    no_argument,
328                                                    &response /*ignored on UDB-based SDIO*/);
329         }
330 
331         // UDB-based SDIO does not support io volt switch sequence
332         #if !defined(CYHAL_UDB_SDIO)
333         if (result == CY_RSLT_SUCCESS)
334         {
335             // Check number of IO functions, that are supported by device
336             io_num = (response >> SDIO_CMD5_RESP_IO_FUNC_POS) & SDIO_CMD5_RESP_IO_FUNC_MSK;
337             if (io_num > 0)
338             {
339                 // Sending 1.8V switch request
340                 argument = (response & SDIO_CMD5_IO_OCR_MSK) | SDIO_CMD5_S18R_BIT;
341 
342                 // CMD5.
343                 result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_WRITE,
344                                                        CYHAL_SDIO_CMD_IO_SEND_OP_COND,
345                                                        argument, &response);
346 
347                 if (CY_RSLT_SUCCESS == result)
348                 {
349                     // IORDY = 1 (Card is ready to operate)
350                     if (response & SDIO_CMD5_RESP_IORDY)
351                     {
352                         // Switching to 1.8V accepted
353                         if (response & SDIO_CMD5_S18R_BIT)
354                         {
355                             // CMD11.
356                             result = _cybsp_wifi_sdio_try_send_cmd(sdio_object,
357                                                                    CYHAL_SDIO_XFER_TYPE_WRITE,
358                                                                    CYHAL_SDIO_CMD_VOLTAGE_SWITCH,
359                                                                    no_argument,
360                                                                    &response);
361 
362                             if (CY_RSLT_SUCCESS == result)
363                             {
364                                 #if defined(CYBSP_WIFI_SDIO_VOLT_SEL)
365                                 cyhal_gpio_t io_volt_sel_pin = CYBSP_WIFI_SDIO_VOLT_SEL;
366                                 #else
367                                 // No actual voltage switch will be done as no pin provided.
368                                 cyhal_gpio_t io_volt_sel_pin = NC;
369                                 #endif /* defined(CYBSP_WIFI_SDIO_VOLT_SEL) */
370 
371                                 // Perform voltage switch sequence
372                                 // And, if pin provided, switch the voltage
373                                 result = cyhal_sdio_set_io_voltage(sdio_object, io_volt_sel_pin,
374                                                                    CYHAL_SDIO_IO_VOLTAGE_1_8V,
375                                                                    CYHAL_SDIO_IO_VOLT_ACTION_SWITCH_SEQ_ONLY);
376 
377                                 if (CYHAL_SDIO_RSLT_ERR_UNSUPPORTED == result)
378                                 {
379                                     // Changing IO voltage is not supported by current
380                                     // implementation. No reason to try again.
381                                     abort_sdio = true;
382                                 }
383                             }
384                         }
385                         // Nothing to do for 'else'. 1.8V is not supported.
386                     }
387                     else
388                     {
389                         result = CYBSP_RSLT_WIFI_SDIO_ENUM_NOT_READY;
390                     }
391                 }
392             }
393             else
394             {
395                 result = CYBSP_RSLT_WIFI_SDIO_ENUM_IO_NOT_SUPPORTED;
396                 // IO is not supported by this SD device, no reason to try enumeration again
397                 abort_sdio = true;
398             }
399         }
400         #endif /* !defined(CYHAL_UDB_SDIO) */
401 
402         if (CY_RSLT_SUCCESS == result)
403         {
404             // Send CMD3 to get RCA.
405             result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_READ,
406                                                    CYHAL_SDIO_CMD_SEND_RELATIVE_ADDR,
407                                                    no_argument, &rel_addr);
408         }
409 
410         if ((!abort_sdio) && (result != CY_RSLT_SUCCESS))
411         {
412             cyhal_system_delay_ms(SDIO_RETRY_DELAY_MS);
413         }
414         loop_count++;
415     } while ((!abort_sdio) && (result != CY_RSLT_SUCCESS) &&
416              (loop_count <= SDIO_ENUMERATION_TRIES));
417 
418     if (result == CY_RSLT_SUCCESS)
419     {
420         // Send CMD7 with the returned RCA to select the card
421         result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_WRITE,
422                                                CYHAL_SDIO_CMD_SELECT_CARD,
423                                                rel_addr,
424                                                &response /*ignored*/);
425     }
426 
427     uint32_t sdio_frequency = SDIO_FREQ_25MHZ;
428 
429     // use constant 25 MHz frequency for UDB-based SDIO
430     // and perform supported speed check and switch for SDHC-based SDIO
431     #if !defined(CYHAL_UDB_SDIO)
432     if (result == CY_RSLT_SUCCESS)
433     {
434         uint32_t tmp_arg = _cybsp_wifi_create_cmd_52_arg(SDIO_CMD52_ARG_RW_READ, SDIO_FUNC_NUM_0,
435                                                          SDIO_CMD52_ARG_RAW_NOT_SET,
436                                                          SDIO_CMD52_CCCR_SPEED_SLCT_ADDR, 0x00);
437         result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_WRITE,
438                                                CYHAL_SDIO_CMD_IO_RW_DIRECT,
439                                                tmp_arg, &response);
440 
441         if (result == CY_RSLT_SUCCESS)
442         {
443             if (SDIO_CMD52_CCCR_SPEED_SELECT_RESP_HS_SUPPORTED == response)
444             {
445                 tmp_arg = _cybsp_wifi_create_cmd_52_arg(SDIO_CMD52_ARG_RW_WRITE, SDIO_FUNC_NUM_0,
446                                                         SDIO_CMD52_ARG_RAW_NOT_SET,
447                                                         SDIO_CMD52_CCCR_SPEED_SLCT_ADDR,
448                                                         SDIO_CMD52_CCCR_SPEED_SLCT_HS);
449                 result = _cybsp_wifi_sdio_try_send_cmd(sdio_object, CYHAL_SDIO_XFER_TYPE_WRITE,
450                                                        CYHAL_SDIO_CMD_IO_RW_DIRECT,
451                                                        tmp_arg, &response);
452 
453                 if (result == CY_RSLT_SUCCESS)
454                 {
455                     if (SDIO_CMD52_CCCR_SPEED_SELECT_RESP_HS_SELECTED == response)
456                     {
457                         // High Speed mode switch allowed, configure clock frequency for 50 MHz
458                         sdio_frequency = SDIO_FREQ_50MHZ;
459                     }
460                 }
461                 else
462                 {
463                     result = CYBSP_RSLT_WIFI_SDIO_HS_SWITCH_FAILED;
464                 }
465             }
466         }
467     }
468     #endif /* !defined(CYHAL_UDB_SDIO) */
469 
470     if (result == CY_RSLT_SUCCESS)
471     {
472         cyhal_sdio_cfg_t config = { .frequencyhal_hz = sdio_frequency, .block_size = 0 };
473         result = cyhal_sdio_configure(sdio_object, &config);
474     }
475     return result;
476 }
477 
478 
479 //--------------------------------------------------------------------------------------------------
480 // _cybsp_wifi_sdio_init_bus2
481 //--------------------------------------------------------------------------------------------------
_cybsp_wifi_sdio_init_bus2(cyhal_sdio_t * obj)482 static cy_rslt_t _cybsp_wifi_sdio_init_bus2(cyhal_sdio_t* obj)
483 {
484     cy_rslt_t result = _cybsp_wifi_sdio_card_init(obj);
485     if (result == CY_RSLT_SUCCESS)
486     {
487         // If the configurator reserved the pin, we need to release it here since
488         // WHD will try to reserve it again. WHD has no idea about configurators
489         // and expects it can reserve the pin that it is going to manage.
490         #if defined(CYCFG_WIFI_HOST_WAKE_ENABLED)
491         cyhal_resource_inst_t pinRsc = cyhal_utils_get_gpio_resource(CY_WIFI_HOST_WAKE_GPIO);
492         cyhal_hwmgr_free(&pinRsc);
493         #endif
494 
495         whd_sdio_config_t whd_sdio_config =
496         {
497             .sdio_1bit_mode        = WHD_FALSE,
498             .high_speed_sdio_clock = WHD_FALSE,
499             .oob_config            = OOB_CONFIG
500         };
501         whd_bus_sdio_attach(whd_drv, &whd_sdio_config, obj);
502     }
503     return result;
504 }
505 
506 
507 #if defined(CYBSP_WIFI_SDIO_NEEDS_INIT)
508 static cyhal_sdio_t sdio_obj;
509 #endif
510 
511 //--------------------------------------------------------------------------------------------------
512 // _cybsp_wifi_sdio_init_bus
513 //--------------------------------------------------------------------------------------------------
_cybsp_wifi_sdio_init_bus(void)514 static cy_rslt_t _cybsp_wifi_sdio_init_bus(void)
515 {
516     #if defined(CYBSP_WIFI_SDIO_NEEDS_INIT)
517     cy_rslt_t result = cyhal_sdio_init(&sdio_obj, CYBSP_WIFI_SDIO_CMD, CYBSP_WIFI_SDIO_CLK,
518                                        CYBSP_WIFI_SDIO_D0, CYBSP_WIFI_SDIO_D1, CYBSP_WIFI_SDIO_D2,
519                                        CYBSP_WIFI_SDIO_D3);
520 
521     if (result == CY_RSLT_SUCCESS)
522     {
523         result = _cybsp_wifi_sdio_init_bus2(&sdio_obj);
524         if (result != CY_RSLT_SUCCESS)
525         {
526             cyhal_sdio_free(&sdio_obj);
527         }
528     }
529     #else // if defined(CYBSP_WIFI_SDIO_NEEDS_INIT)
530     cyhal_sdio_t* sdio_p = cybsp_get_wifi_sdio_obj();
531     cy_rslt_t result = _cybsp_wifi_sdio_init_bus2(sdio_p);
532     #endif // if defined(CYBSP_WIFI_SDIO_NEEDS_INIT)
533 
534     return result;
535 }
536 
537 
538 #elif defined(COMPONENT_WIFI_INTERFACE_SPI)
539 
540 //--------------------------------------------------------------------------------------------------
541 // _cybsp_wifi_spi_init_bus
542 //--------------------------------------------------------------------------------------------------
_cybsp_wifi_spi_init_bus(void)543 static cy_rslt_t _cybsp_wifi_spi_init_bus(void)
544 {
545     static cyhal_spi_t spi_obj;
546     cy_rslt_t rslt = cyhal_spi_init(&spi_obj,
547                                     CYBSP_WIFI_SPI_MOSI, CYBSP_WIFI_SPI_MISO, CYBSP_WIFI_SPI_SCLK,
548                                     CYBSP_WIFI_SPI_SSEL,
549                                     NULL, 32, CYHAL_SPI_MODE_00_MSB, false);
550     if (CY_RSLT_SUCCESS == rslt)
551     {
552         rslt = cyhal_spi_set_frequency(&spi_obj, 50000000); // 50 MHz operation
553         if (CY_RSLT_SUCCESS == rslt)
554         {
555             whd_spi_config_t whd_spi_config =
556             {
557                 .is_normal_mode      = false,
558                 .oob_config          = OOB_CONFIG
559             };
560             rslt = whd_bus_spi_attach(whd_drv, &whd_spi_config, &spi_obj);
561         }
562         else
563         {
564             cyhal_spi_free(&spi_obj);
565         }
566     }
567 
568     return rslt;
569 }
570 
571 
572 #elif defined(COMPONENT_WIFI_INTERFACE_M2M)
573 
574 static cyhal_m2m_t m2m_obj;
575 
576 //--------------------------------------------------------------------------------------------------
577 // _cybsp_wifi_m2m_init_bus
578 //--------------------------------------------------------------------------------------------------
_cybsp_wifi_m2m_init_bus(void)579 static cy_rslt_t _cybsp_wifi_m2m_init_bus(void)
580 {
581     cy_rslt_t rslt;
582 
583     whd_m2m_config_t whd_m2m_config =
584     {
585         .is_normal_mode = false,
586     };
587     // Note: The m2m itself is initialized in the WHD
588     rslt = whd_bus_m2m_attach(whd_drv, &whd_m2m_config, &m2m_obj);
589 
590     return rslt;
591 }
592 
593 
594 #endif // defined(COMPONENT_WIFI_INTERFACE_M2M)
595 
596 
597 //--------------------------------------------------------------------------------------------------
598 // _cybsp_wifi_bus_init
599 //--------------------------------------------------------------------------------------------------
_cybsp_wifi_bus_init(void)600 static inline cy_rslt_t _cybsp_wifi_bus_init(void)
601 {
602     #if !defined(COMPONENT_WIFI_INTERFACE_M2M)
603     _cybsp_wifi_reset_wifi_chip();
604     #endif
605     #if defined(COMPONENT_WIFI_INTERFACE_SDIO)
606     return _cybsp_wifi_sdio_init_bus();
607     #elif defined(COMPONENT_WIFI_INTERFACE_SPI)
608     return _cybsp_wifi_spi_init_bus();
609     #elif defined(COMPONENT_WIFI_INTERFACE_M2M)
610     return _cybsp_wifi_m2m_init_bus();
611     #endif
612 }
613 
614 
615 //--------------------------------------------------------------------------------------------------
616 // _cybsp_wifi_bus_detach
617 //--------------------------------------------------------------------------------------------------
_cybsp_wifi_bus_detach(void)618 static inline void _cybsp_wifi_bus_detach(void)
619 {
620     #if defined(COMPONENT_WIFI_INTERFACE_SDIO)
621     whd_bus_sdio_detach(whd_drv);
622     #elif defined(COMPONENT_WIFI_INTERFACE_SPI)
623     whd_bus_spi_detach(whd_drv);
624     #elif defined(COMPONENT_WIFI_INTERFACE_M2M)
625     whd_bus_m2m_detach(whd_drv);
626     #endif
627 }
628 
629 
630 //--------------------------------------------------------------------------------------------------
631 // cybsp_wifi_init_primary_extended
632 //--------------------------------------------------------------------------------------------------
cybsp_wifi_init_primary_extended(whd_interface_t * interface,whd_init_config_t * init_config,whd_resource_source_t * resource_if,whd_buffer_funcs_t * buffer_if,whd_netif_funcs_t * netif_if)633 cy_rslt_t cybsp_wifi_init_primary_extended(whd_interface_t* interface,
634                                            whd_init_config_t* init_config,
635                                            whd_resource_source_t* resource_if,
636                                            whd_buffer_funcs_t* buffer_if,
637                                            whd_netif_funcs_t* netif_if)
638 {
639     #if defined(COMPONENT_WIFI_INTERFACE_M2M)
640     cy_rslt_t result = CY_RSLT_SUCCESS;
641     #else
642     cy_rslt_t result = cyhal_gpio_init(CYBSP_WIFI_WL_REG_ON, CYHAL_GPIO_DIR_OUTPUT,
643                                        CYHAL_GPIO_DRIVE_PULLUP, false);
644     #endif
645 
646     if (result == CY_RSLT_SUCCESS)
647     {
648         if (init_config == NULL)
649         {
650             init_config = &init_config_default;
651         }
652         if (resource_if == NULL)
653         {
654             resource_if = &resource_ops;
655         }
656         if (buffer_if == NULL)
657         {
658             buffer_if = &buffer_if_default;
659         }
660         if (netif_if == NULL)
661         {
662             netif_if = &netif_if_default;
663         }
664 
665         result = whd_init(&whd_drv, init_config, resource_if, buffer_if, netif_if);
666         if (result == CY_RSLT_SUCCESS)
667         {
668             result = _cybsp_wifi_bus_init();
669 
670             if (result == CY_RSLT_SUCCESS)
671             {
672                 result = whd_wifi_on(whd_drv, interface);
673 
674                 if (result != CY_RSLT_SUCCESS)
675                 {
676                     _cybsp_wifi_bus_detach();
677                 }
678             }
679 
680             if (result != CY_RSLT_SUCCESS)
681             {
682                 whd_deinit(*interface);
683             }
684         }
685 
686         #if !defined(COMPONENT_WIFI_INTERFACE_M2M)
687         if (result != CY_RSLT_SUCCESS)
688         {
689             cyhal_gpio_free(CYBSP_WIFI_WL_REG_ON);
690         }
691         #endif
692     }
693 
694     return result;
695 }
696 
697 
698 //--------------------------------------------------------------------------------------------------
699 // cybsp_wifi_init_secondary
700 //--------------------------------------------------------------------------------------------------
cybsp_wifi_init_secondary(whd_interface_t * interface,whd_mac_t * mac_address)701 cy_rslt_t cybsp_wifi_init_secondary(whd_interface_t* interface, whd_mac_t* mac_address)
702 {
703     return whd_add_secondary_interface(whd_drv, mac_address, interface);
704 }
705 
706 
707 //--------------------------------------------------------------------------------------------------
708 // cybsp_wifi_deinit
709 //--------------------------------------------------------------------------------------------------
cybsp_wifi_deinit(whd_interface_t interface)710 cy_rslt_t cybsp_wifi_deinit(whd_interface_t interface)
711 {
712     cy_rslt_t result = whd_wifi_off(interface);
713 
714     if (result == CY_RSLT_SUCCESS)
715     {
716         _cybsp_wifi_bus_detach();
717         #if !defined(COMPONENT_WIFI_INTERFACE_M2M)
718         cyhal_gpio_free(CYBSP_WIFI_WL_REG_ON);
719         #endif
720         // While deinit() takes an interface, it only uses it to get the underlying whd driver to
721         // cleanup. As a result, we only need to call this on one of the interfaces.
722         result = whd_deinit(interface);
723 
724         #if defined(CYBSP_WIFI_SDIO_NEEDS_INIT)
725         if (result == CY_RSLT_SUCCESS)
726         {
727             cyhal_sdio_free(&sdio_obj);
728         }
729         #endif
730     }
731     return result;
732 }
733 
734 
735 //--------------------------------------------------------------------------------------------------
736 // cybsp_get_wifi_driver
737 //--------------------------------------------------------------------------------------------------
cybsp_get_wifi_driver(void)738 whd_driver_t cybsp_get_wifi_driver(void)
739 {
740     return whd_drv;
741 }
742 
743 
744 #if defined(__cplusplus)
745 }
746 #endif
747