1 /*
2  * Copyright 2023, Cypress Semiconductor Corporation (an Infineon company)
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <stdlib.h>
19 #include "bus_protocols/whd_chip_reg.h"
20 #include "bus_protocols/whd_sdio.h"
21 #include "bus_protocols/whd_bus_common.h"
22 #include "bus_protocols/whd_bus_protocol_interface.h"
23 #include "whd_chip_constants.h"
24 #include "whd_cdc_bdc.h"
25 #include "whd_thread_internal.h"
26 #include "whd_buffer_api.h"
27 #include "whd_debug.h"
28 #include "whd_utils.h"
29 #include "whd_wifi_api.h"
30 #include "whd_chip.h"
31 #include "whd.h"
32 #include "whd_wlioctl.h"
33 
34 /******************************************************
35 *                      Macros
36 ******************************************************/
37 #define SPINWAIT_POLL_PERIOD    10
38 
39 #define SPINWAIT(exp, us) { \
40         uint countdown = (us) + (SPINWAIT_POLL_PERIOD - 1); \
41         while ( (exp) && (countdown >= SPINWAIT_POLL_PERIOD) ){ \
42             cy_rtos_delay_milliseconds(SPINWAIT_POLL_PERIOD); \
43             countdown -= SPINWAIT_POLL_PERIOD; \
44         } \
45 }
46 /******************************************************
47 *             Constants
48 ******************************************************/
49 
50 #define PLATFORM_WLAN_RAM_BASE      (0x0)
51 #define WLAN_BUS_UP_ATTEMPTS        (1000)
52 #define HT_AVAIL_WAIT_MS            (1)
53 #define KSO_WAIT_MS                 (1)
54 #define KSO_WAKE_MS                 (3)
55 #define MAX_KSO_ATTEMPTS            (64)
56 #define MAX_CAPS_BUFFER_SIZE        (768)
57 
58 #define AI_IOCTRL_OFFSET            (0x408)
59 #define SICF_FGC                    (0x0002)
60 #define SICF_CLOCK_EN               (0x0001)
61 #define AI_RESETCTRL_OFFSET         (0x800)
62 #define AI_RESETSTATUS_OFFSET       (0x804)
63 #define AIRC_RESET                  (1)
64 #define WRAPPER_REGISTER_OFFSET     (0x100000)
65 
66 #define WLAN_SHARED_VERSION_MASK    (0x00ff)
67 #define WLAN_SHARED_VERSION         (0x0001)
68 #define WPRINT_WHD_DEBUG_DS(args) WPRINT_WHD_DEBUG(args)
69 
70 /******************************************************
71 *             Structures
72 ******************************************************/
73 
74 /******************************************************
75 *             Variables
76 ******************************************************/
77 static const whd_fwcap_t whd_fwcap_map[] =
78 {
79     {WHD_FWCAP_SAE, "sae "},
80     {WHD_FWCAP_SAE_EXT, "sae_ext "},
81 };
82 
83 /******************************************************
84 *             Static Function Declarations
85 ******************************************************/
86 static whd_bool_t whd_is_fw_sr_capable(whd_driver_t whd_driver);
87 static whd_result_t whd_kso_enable(whd_driver_t whd_driver, whd_bool_t enable);
88 static uint32_t whd_get_core_address(whd_driver_t whd_driver, device_core_t core_id);
89 
90 static whd_result_t whd_enable_save_restore(whd_driver_t whd_driver);
91 
92 /******************************************************
93 *             Function definitions
94 ******************************************************/
whd_internal_info_init(whd_driver_t whd_driver)95 whd_result_t whd_internal_info_init(whd_driver_t whd_driver)
96 {
97     whd_internal_info_t *internal_info = &whd_driver->internal_info;
98 
99     internal_info->whd_wlan_status.state = WLAN_OFF;
100     internal_info->whd_wlan_status.country_code = WHD_COUNTRY_AUSTRALIA;
101     internal_info->whd_wlan_status.aggregate_code = WHD_COUNTRY_AGGREGATE_XV_0;
102     internal_info->whd_wlan_status.keep_wlan_awake = 0;
103     internal_info->console_addr = 0;
104     internal_info->scan_result_callback = NULL;
105     internal_info->whd_scan_result_ptr = NULL;
106     internal_info->active_join_mutex_initted = WHD_FALSE;
107     internal_info->active_join_semaphore = NULL;
108     internal_info->con_lastpos = 0;
109     internal_info->whd_wifi_p2p_go_is_up = WHD_FALSE;
110 
111     /* Create the mutex protecting whd_log structure */
112     if (cy_rtos_init_semaphore(&whd_driver->whd_log_mutex, 1, 0) != WHD_SUCCESS)
113     {
114         return WHD_SEMAPHORE_ERROR;
115     }
116     if (cy_rtos_set_semaphore(&whd_driver->whd_log_mutex, WHD_FALSE) != WHD_SUCCESS)
117     {
118         WPRINT_WHD_ERROR( ("Error setting semaphore in %s at %d \n", __func__, __LINE__) );
119         return WHD_SEMAPHORE_ERROR;
120     }
121     return WHD_SUCCESS;
122 }
123 
whd_internal_info_deinit(whd_driver_t whd_driver)124 whd_result_t whd_internal_info_deinit(whd_driver_t whd_driver)
125 {
126     /* Delete the whd_log mutex */
127     (void)cy_rtos_deinit_semaphore(&whd_driver->whd_log_mutex);
128     return WHD_SUCCESS;
129 }
130 
131 /*
132  * Returns the base address of the core identified by the provided coreId
133  */
whd_get_core_address(whd_driver_t whd_driver,device_core_t core_id)134 uint32_t whd_get_core_address(whd_driver_t whd_driver, device_core_t core_id)
135 {
136     if (core_id == WLAN_ARM_CORE)
137     {
138         return GET_C_VAR(whd_driver, ARM_CORE_BASE_ADDRESS);
139     }
140     else if (core_id == SOCRAM_CORE)
141     {
142         return GET_C_VAR(whd_driver, SOCSRAM_WRAPPER_BASE_ADDRESS);
143     }
144     else if (core_id == SDIOD_CORE)
145     {
146         return GET_C_VAR(whd_driver, SDIOD_CORE_BASE_ADDRESS);
147     }
148     else
149     {
150         WPRINT_WHD_ERROR( ("%s:%d Invalid core ID(%d)\n", __FUNCTION__, __LINE__, core_id) );
151     }
152 
153     return WHD_BADARG;
154 
155 }
156 
157 /*
158  * Returns WHD_SUCCESS is the core identified by the provided coreId is up, otherwise WHD result code
159  */
whd_device_core_is_up(whd_driver_t whd_driver,device_core_t core_id)160 whd_result_t whd_device_core_is_up(whd_driver_t whd_driver, device_core_t core_id)
161 {
162     uint8_t regdata;
163     uint32_t base;
164     whd_result_t result;
165 
166     base = whd_get_core_address(whd_driver, core_id);
167 
168     /* Read the IO control register */
169     result = whd_bus_read_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, &regdata);
170     if (result != WHD_SUCCESS)
171     {
172         WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) );
173         return result;
174     }
175 
176     /* Verify that the clock is enabled and something else is not on */
177     if ( (regdata & (SICF_FGC | SICF_CLOCK_EN) ) != ( uint8_t )SICF_CLOCK_EN )
178     {
179         return WHD_CORE_CLOCK_NOT_ENABLED;
180     }
181 
182     /* Read the reset control and verify it is not in reset */
183     result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, &regdata);
184     if (result != WHD_SUCCESS)
185     {
186         WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) );
187         return result;
188     }
189     if ( (regdata & AIRC_RESET) != 0 )
190     {
191         return WHD_CORE_IN_RESET;
192     }
193 
194     return WHD_SUCCESS;
195 }
196 
197 /*
198  * Resets the core identified by the provided coreId
199  */
whd_reset_core(whd_driver_t whd_driver,device_core_t core_id,uint32_t bits,uint32_t resetbits)200 whd_result_t whd_reset_core(whd_driver_t whd_driver, device_core_t core_id, uint32_t bits, uint32_t resetbits)
201 {
202     uint32_t base = whd_get_core_address(whd_driver, core_id);
203     whd_result_t result;
204     uint8_t regdata;
205     uint32_t loop_counter = 10;
206     /* ensure there are no pending backplane operations */
207     SPINWAIT( ( ( (result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETSTATUS_OFFSET, (uint8_t)1,
208                                                          &regdata) ) == WHD_SUCCESS ) && regdata != 0 ), 300 );
209 
210     /* put core into reset state */
211     result = whd_bus_write_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, ( uint32_t )AIRC_RESET);
212     (void)cy_rtos_delay_milliseconds( (uint32_t)10 );   /* Ignore return - nothing can be done if it fails */
213 
214     /* ensure there are no pending backplane operations */
215     SPINWAIT( ( ( (result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETSTATUS_OFFSET, (uint8_t)1,
216                                                          &regdata) ) == WHD_SUCCESS ) && regdata != 0 ), 300 );
217 
218     result = whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1,
219                                            (bits | resetbits | SICF_FGC | SICF_CLOCK_EN) );
220 
221     /* ensure there are no pending backplane operations */
222     SPINWAIT( ( ( (result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETSTATUS_OFFSET, (uint8_t)1,
223                                                          &regdata) ) == WHD_SUCCESS ) && regdata != 0 ), 300 );
224 
225     while ( ( (result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1,
226                                                      &regdata) ) == WHD_SUCCESS ) && regdata != 0 &&
227             --loop_counter != 0 )
228     {
229         /* ensure there are no pending backplane operations */
230         SPINWAIT( ( ( (result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETSTATUS_OFFSET, (uint8_t)1,
231                                                              &regdata) ) == WHD_SUCCESS ) && regdata != 0 ), 300 );
232         /* take core out of reset */
233         result = whd_bus_write_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, (uint32_t)0);
234         if (result != WHD_SUCCESS)
235         {
236             WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) );
237             return result;
238         }
239 
240         /* ensure there are no pending backplane operations */
241         SPINWAIT( ( ( (result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETSTATUS_OFFSET, (uint8_t)1,
242                                                              &regdata) ) == WHD_SUCCESS ) && regdata != 0 ), 300 );
243     }
244 
245     result = whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, (bits | SICF_CLOCK_EN) );
246 
247     (void)cy_rtos_delay_milliseconds( (uint32_t)1 );   /* Ignore return - nothing can be done if it fails */
248 
249     if (result != WHD_SUCCESS)
250     {
251         WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) );
252         return result;
253     }
254     return WHD_SUCCESS;
255 }
256 
257 /*
258  * Disables the core identified by the provided coreId
259  */
whd_disable_device_core(whd_driver_t whd_driver,device_core_t core_id,wlan_core_flag_t core_flag)260 whd_result_t whd_disable_device_core(whd_driver_t whd_driver, device_core_t core_id, wlan_core_flag_t core_flag)
261 {
262     uint32_t base = whd_get_core_address(whd_driver, core_id);
263     whd_result_t result;
264     uint8_t junk;
265     uint8_t regdata;
266 
267     /* Read the reset control */
268     result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, &junk);
269     if (result != WHD_SUCCESS)
270     {
271         WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) );
272         return result;
273     }
274 
275     /* Read the reset control and check if it is already in reset */
276     result = whd_bus_read_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, &regdata);
277     if (result != WHD_SUCCESS)
278     {
279         WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) );
280         return result;
281     }
282     if ( (regdata & AIRC_RESET) != 0 )
283     {
284         /* Core already in reset */
285         return WHD_SUCCESS;
286     }
287 
288     /* Write 0 to the IO control and read it back */
289     result =
290         whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1,
291                                       (core_flag == WLAN_CORE_FLAG_CPU_HALT) ? SICF_CPUHALT : 0);
292     if (result != WHD_SUCCESS)
293     {
294         WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) );
295         return result;
296     }
297 
298     result = whd_bus_read_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, &junk);
299     if (result != WHD_SUCCESS)
300     {
301         WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) );
302         return result;
303     }
304 
305     (void)cy_rtos_delay_milliseconds( (uint32_t)1 );
306 
307     result = whd_bus_write_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, ( uint32_t )AIRC_RESET);
308     if (result != WHD_SUCCESS)
309     {
310         WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) );
311         return result;
312     }
313 
314     (void)cy_rtos_delay_milliseconds( (uint32_t)1 );
315 
316     return result;
317 }
318 
319 /*
320  * Resets the core identified by the provided coreId
321  */
whd_reset_device_core(whd_driver_t whd_driver,device_core_t core_id,wlan_core_flag_t core_flag)322 whd_result_t whd_reset_device_core(whd_driver_t whd_driver, device_core_t core_id, wlan_core_flag_t core_flag)
323 {
324     uint32_t base = whd_get_core_address(whd_driver, core_id);
325     whd_result_t result;
326     uint8_t junk;
327 
328     result = whd_disable_device_core(whd_driver, core_id, core_flag);
329     if (result != WHD_SUCCESS)
330     {
331         return result;
332     }
333 
334     result =
335         whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1,
336                                       ( uint32_t )(SICF_FGC | SICF_CLOCK_EN |
337                                                    ( (core_flag == WLAN_CORE_FLAG_CPU_HALT) ? SICF_CPUHALT : 0 ) ) );
338     if (result != WHD_SUCCESS)
339     {
340         WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) );
341         return result;
342     }
343 
344     result = whd_bus_read_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, &junk);
345     if (result != WHD_SUCCESS)
346     {
347         WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) );
348         return result;
349     }
350 
351     result = whd_bus_write_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, 0);
352     if (result != WHD_SUCCESS)
353     {
354         WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) );
355         return result;
356     }
357 
358     (void)cy_rtos_delay_milliseconds( (uint32_t)1 );
359 
360     result =
361         whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1,
362                                       ( uint32_t )(SICF_CLOCK_EN |
363                                                    ( (core_flag == WLAN_CORE_FLAG_CPU_HALT) ? SICF_CPUHALT : 0 ) ) );
364     if (result != WHD_SUCCESS)
365     {
366         WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) );
367         return result;
368     }
369 
370     result = whd_bus_read_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, &junk);
371     if (result != WHD_SUCCESS)
372     {
373         WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) )
374         return result;
375     }
376 
377     (void)cy_rtos_delay_milliseconds( (uint32_t)1 );
378 
379     return result;
380 }
381 
382 /*
383  * Release ARM core to run instructions
384  */
whd_wlan_armcore_run(whd_driver_t whd_driver,device_core_t core_id,wlan_core_flag_t core_flag)385 whd_result_t whd_wlan_armcore_run(whd_driver_t whd_driver, device_core_t core_id, wlan_core_flag_t core_flag)
386 {
387     uint32_t base = whd_get_core_address(whd_driver, core_id);
388     whd_result_t result;
389     uint8_t junk;
390 
391     /* Only work for WLAN arm core! */
392     if (WLAN_ARM_CORE != core_id)
393     {
394         return WHD_UNSUPPORTED;
395     }
396 
397     result =
398         whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1,
399                                       ( uint32_t )(SICF_FGC | SICF_CLOCK_EN |
400                                                    ( (core_flag == WLAN_CORE_FLAG_CPU_HALT) ? SICF_CPUHALT : 0 ) ) );
401     if (result != WHD_SUCCESS)
402     {
403         WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) )
404         return result;
405     }
406 
407     result = whd_bus_read_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, &junk);
408     if (result != WHD_SUCCESS)
409     {
410         WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) )
411         return result;
412     }
413 
414     result = whd_bus_write_backplane_value(whd_driver, base + AI_RESETCTRL_OFFSET, (uint8_t)1, 0);
415     if (result != WHD_SUCCESS)
416     {
417         WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) )
418         return result;
419     }
420 
421     (void)cy_rtos_delay_milliseconds( (uint32_t)1 );
422 
423     result =
424         whd_bus_write_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1,
425                                       ( uint32_t )(SICF_CLOCK_EN |
426                                                    ( (core_flag == WLAN_CORE_FLAG_CPU_HALT) ? SICF_CPUHALT : 0 ) ) );
427     if (result != WHD_SUCCESS)
428     {
429         WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) );
430         return result;
431     }
432 
433     result = whd_bus_read_backplane_value(whd_driver, base + AI_IOCTRL_OFFSET, (uint8_t)1, &junk);
434     if (result != WHD_SUCCESS)
435     {
436         WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) );
437         return result;
438     }
439 
440     (void)cy_rtos_delay_milliseconds( (uint32_t)1 );
441 
442     return result;
443 }
444 
whd_wifi_read_wlan_log_unsafe(whd_driver_t whd_driver,uint32_t wlan_shared_address,char * buffer,uint32_t buffer_size)445 whd_result_t whd_wifi_read_wlan_log_unsafe(whd_driver_t whd_driver, uint32_t wlan_shared_address, char *buffer,
446                                            uint32_t buffer_size)
447 {
448     char ch;
449     uint32_t n;
450     uint32_t index;
451     uint32_t address;
452     whd_result_t result = WHD_WLAN_ERROR;
453     whd_internal_info_t *internal_info = &whd_driver->internal_info;
454     wifi_console_t *c = internal_info->c;
455 
456     c = &internal_info->console;
457 
458     if (internal_info->console_addr == 0)
459     {
460         uint shared_addr;
461 
462         address = wlan_shared_address;
463         result = whd_bus_read_backplane_value(whd_driver, address, 4, (uint8_t *)&shared_addr);
464         if (result != WHD_SUCCESS)
465         {
466             WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) );
467             goto done;
468         }
469 
470         result = whd_bus_transfer_backplane_bytes(whd_driver, BUS_READ, shared_addr, sizeof(wlan_shared_t),
471                                                   (uint8_t *)&internal_info->sh);
472         if (result != WHD_SUCCESS)
473         {
474             WPRINT_WHD_ERROR( ("%s:%d whd_bus_transfer_backplane_bytes failed\n", __FUNCTION__, __LINE__) );
475             goto done;
476         }
477 
478         internal_info->sh.flags = dtoh32(internal_info->sh.flags);
479         internal_info->sh.trap_addr = dtoh32(internal_info->sh.trap_addr);
480         internal_info->sh.assert_exp_addr = dtoh32(internal_info->sh.assert_exp_addr);
481         internal_info->sh.assert_file_addr = dtoh32(internal_info->sh.assert_file_addr);
482         internal_info->sh.assert_line = dtoh32(internal_info->sh.assert_line);
483         internal_info->sh.console_addr = dtoh32(internal_info->sh.console_addr);
484         internal_info->sh.msgtrace_addr = dtoh32(internal_info->sh.msgtrace_addr);
485 
486         if ( (internal_info->sh.flags & WLAN_SHARED_VERSION_MASK) != WLAN_SHARED_VERSION )
487         {
488             WPRINT_WHD_ERROR( ("Readconsole: WLAN shared version is not valid sh.flags %x\n\r",
489                                internal_info->sh.flags) );
490             result = WHD_WLAN_INVALID;
491             goto done;
492         }
493         internal_info->console_addr = internal_info->sh.console_addr;
494     }
495 
496     /* Read console log struct */
497     address = internal_info->console_addr + offsetof(hnd_cons_t, log);
498     result = whd_bus_transfer_backplane_bytes(whd_driver, BUS_READ, address, sizeof(c->log), (uint8_t *)&c->log);
499     if (result != WHD_SUCCESS)
500     {
501         WPRINT_WHD_ERROR( ("%s:%d whd_bus_transfer_backplane_bytes failed\n", __FUNCTION__, __LINE__) );
502         goto done;
503     }
504 
505     /* Allocate console buffer (one time only) */
506     if (c->buf == NULL)
507     {
508         c->bufsize = dtoh32(c->log.buf_size);
509         c->buf = whd_mem_malloc(c->bufsize);
510         if (c->buf == NULL)
511         {
512             WPRINT_WHD_ERROR( ("%s:%d c->buf IS null \n", __FUNCTION__, __LINE__) );
513             result = WHD_WLAN_NOMEM;
514             goto done;
515         }
516     }
517 
518     /* Retrieve last read position */
519     c->last = whd_driver->internal_info.con_lastpos;
520 
521     index = dtoh32(c->log.idx);
522 
523     /* Protect against corrupt value */
524     if (index > c->bufsize)
525     {
526         WPRINT_WHD_ERROR( ("%s:%d index > c->bufsize \n", __FUNCTION__, __LINE__) );
527         result = WHD_WLAN_BUFTOOSHORT;
528         goto done;
529     }
530 
531     /* Skip reading the console buffer if the index pointer has not moved */
532     if (index == c->last)
533     {
534         result = WHD_SUCCESS;
535         goto done;
536     }
537 
538     /* Read the console buffer */
539     /* xxx this could optimize and read only the portion of the buffer needed, but
540      * it would also have to handle wrap-around.
541      */
542     address = dtoh32(c->log.buf);
543     result = whd_bus_transfer_backplane_bytes(whd_driver, BUS_READ, address, c->bufsize, (uint8_t *)c->buf);
544     if (result != WHD_SUCCESS)
545     {
546         WPRINT_WHD_ERROR( ("%s:%d whd_bus_transfer_backplane_bytes failed\n", __FUNCTION__, __LINE__) );
547         goto done;
548     }
549 
550     while (c->last != index)
551     {
552         for (n = 0; n < buffer_size - 2; n++)
553         {
554             if (c->last == index)
555             {
556                 /* This would output a partial line.  Instead, back up
557                  * the buffer pointer and output this line next time around.
558                  */
559                 if (c->last >= n)
560                 {
561                     c->last -= n;
562                 }
563                 else
564                 {
565                     c->last = c->bufsize - n;
566                 }
567                 /* Save last read position */
568                 whd_driver->internal_info.con_lastpos = c->last;
569 
570                 result = WHD_SUCCESS;
571                 goto done;
572             }
573             ch = c->buf[c->last];
574             c->last = (c->last + 1) % c->bufsize;
575             if (ch == '\n')
576             {
577                 break;
578             }
579             buffer[n] = ch;
580         }
581         if (n > 0)
582         {
583             if (buffer[n - 1] == '\r')
584                 n--;
585             buffer[n] = 0;
586             WPRINT_MACRO( ("CONSOLE: %s\n", buffer) );
587         }
588     }
589     /* Save last read position */
590     whd_driver->internal_info.con_lastpos = c->last;
591     result = WHD_SUCCESS;
592 
593 done: return result;
594 }
595 
whd_wifi_peek(whd_driver_t whd_driver,uint32_t address,uint8_t register_length,uint8_t * value)596 void whd_wifi_peek(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, uint8_t *value)
597 {
598     uint8_t status;
599 
600     WHD_WLAN_KEEP_AWAKE(whd_driver);
601 
602     status = whd_bus_read_backplane_value(whd_driver, address, register_length, value);
603 
604     if (status != WHD_SUCCESS)
605     {
606         WPRINT_WHD_ERROR( ("%s: Error reading interrupt status\n", __FUNCTION__) );
607     }
608 
609     WHD_WLAN_LET_SLEEP(whd_driver);
610 }
611 
whd_wifi_poke(whd_driver_t whd_driver,uint32_t address,uint8_t register_length,uint32_t value)612 void whd_wifi_poke(whd_driver_t whd_driver, uint32_t address, uint8_t register_length, uint32_t value)
613 {
614     uint8_t status;
615 
616     WHD_WLAN_KEEP_AWAKE(whd_driver);
617 
618     status = whd_bus_write_backplane_value(whd_driver, address, register_length, value);
619 
620     if (status != WHD_SUCCESS)
621     {
622         WPRINT_WHD_ERROR( ("%s: Error clearing the interrupt status\n", __FUNCTION__) );
623     }
624 
625     WHD_WLAN_LET_SLEEP(whd_driver);
626 }
627 
whd_ioctl_log_add(whd_driver_t whd_driver,uint32_t cmd,whd_buffer_t buffer)628 whd_result_t whd_ioctl_log_add(whd_driver_t whd_driver, uint32_t cmd, whd_buffer_t buffer)
629 {
630     uint8_t *data = NULL;
631     size_t data_size = whd_buffer_get_current_piece_size(whd_driver, buffer);
632 
633     data = whd_buffer_get_current_piece_data_pointer(whd_driver, buffer);
634     CHECK_IOCTL_BUFFER(data);
635     CHECK_RETURN(cy_rtos_get_semaphore(&whd_driver->whd_log_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE) );
636     data = data + IOCTL_OFFSET;
637     data_size = data_size - IOCTL_OFFSET;
638     whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].ioct_log = cmd;
639     whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].is_this_event = 0;
640     whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].data_size = MIN_OF(
641         WHD_MAX_DATA_SIZE, data_size);
642     memset(whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].data, 0,
643            WHD_MAX_DATA_SIZE);
644     memcpy(whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].data, data,
645            whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].data_size);
646 
647     whd_driver->whd_ioctl_log_index++;
648     CHECK_RETURN(cy_rtos_set_semaphore(&whd_driver->whd_log_mutex, WHD_FALSE) );
649     return WHD_SUCCESS;
650 }
651 
whd_ioctl_log_add_event(whd_driver_t whd_driver,uint32_t cmd,uint16_t flag,uint32_t reason)652 whd_result_t whd_ioctl_log_add_event(whd_driver_t whd_driver, uint32_t cmd, uint16_t flag, uint32_t reason)
653 {
654     CHECK_RETURN(cy_rtos_get_semaphore(&whd_driver->whd_log_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE) );
655     whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].is_this_event = 1;
656     whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].ioct_log = cmd;
657     whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].flag = flag;
658     whd_driver->whd_ioctl_log[whd_driver->whd_ioctl_log_index % WHD_IOCTL_LOG_SIZE].reason = reason;
659 
660     whd_driver->whd_ioctl_log_index++;
661     CHECK_RETURN(cy_rtos_set_semaphore(&whd_driver->whd_log_mutex, WHD_FALSE) );
662     return WHD_SUCCESS;
663 }
664 
whd_ioctl_print(whd_driver_t whd_driver)665 whd_result_t whd_ioctl_print(whd_driver_t whd_driver)
666 {
667     int i;
668     uint8_t *data = NULL;
669     size_t iovar_string_size = 0;
670 
671     CHECK_RETURN(cy_rtos_get_semaphore(&whd_driver->whd_log_mutex, CY_RTOS_NEVER_TIMEOUT, WHD_FALSE) );
672     for (i = 0; i < WHD_IOCTL_LOG_SIZE; i++)
673     {
674         char iovar[WHD_IOVAR_STRING_SIZE] = {0};
675         data = whd_driver->whd_ioctl_log[i].data;
676 
677         if ( (whd_driver->whd_ioctl_log[i].ioct_log == WLC_SET_VAR) ||
678              (whd_driver->whd_ioctl_log[i].ioct_log == WLC_GET_VAR) )
679         {
680             /* refer to whd_cdc_get_iovar_buffer() */
681             while (!*data)
682             {
683                 whd_driver->whd_ioctl_log[i].data_size--;
684                 data++;
685             }
686 
687             if (strlen( (char *)data ) <= WHD_IOVAR_STRING_SIZE)
688                 strncpy(iovar, (char *)data, strlen( (char *)data ) );
689 
690             iovar_string_size = strlen( (const char *)data );
691             iovar[iovar_string_size] = '\0';
692             data += (iovar_string_size + 1);
693             whd_driver->whd_ioctl_log[i].data_size -= (iovar_string_size + 1);
694         }
695         if (whd_driver->whd_ioctl_log[i].is_this_event == 1)
696         {
697             whd_event_info_to_string(whd_driver->whd_ioctl_log[i].ioct_log, whd_driver->whd_ioctl_log[i].flag,
698                                      whd_driver->whd_ioctl_log[i].reason, iovar, sizeof(iovar) - 1);
699             WPRINT_MACRO( ("\n<- E:%" PRIu32 "\t\t\tS:%d\t\t\t\tR:%" PRIu32 "\n%s\n",
700                            whd_driver->whd_ioctl_log[i].ioct_log,
701                            whd_driver->whd_ioctl_log[i].flag, whd_driver->whd_ioctl_log[i].reason, iovar) );
702         }
703         else if (whd_driver->whd_ioctl_log[i].ioct_log == WLC_SET_VAR)
704         {
705             WPRINT_MACRO( ("\n-> %s\n", iovar) );
706             whd_hexdump(data, whd_driver->whd_ioctl_log[i].data_size);
707         }
708         else if (whd_driver->whd_ioctl_log[i].ioct_log == WLC_GET_VAR)
709         {
710             WPRINT_MACRO( ("\n<- %s\n", iovar) );
711             whd_hexdump(data, whd_driver->whd_ioctl_log[i].data_size);
712         }
713         else if (whd_driver->whd_ioctl_log[i].ioct_log != 0)
714         {
715             whd_ioctl_info_to_string(whd_driver->whd_ioctl_log[i].ioct_log, iovar, sizeof(iovar) - 1);
716             WPRINT_MACRO( ("\n%s:%" PRIu32 "\n", iovar, whd_driver->whd_ioctl_log[i].ioct_log) );
717             whd_hexdump(data, whd_driver->whd_ioctl_log[i].data_size);
718         }
719     }
720 
721     memset(whd_driver->whd_ioctl_log, 0, sizeof(whd_driver->whd_ioctl_log) );
722     whd_driver->whd_ioctl_log_index = 0;
723     CHECK_RETURN(cy_rtos_set_semaphore(&whd_driver->whd_log_mutex, WHD_FALSE) );
724     return WHD_SUCCESS;
725 }
726 
whd_wifi_chip_info_init(whd_driver_t whd_driver)727 void whd_wifi_chip_info_init(whd_driver_t whd_driver)
728 {
729     whd_driver->chip_info.save_restore_enable = WHD_FALSE;
730 }
731 
whd_wifi_set_custom_country_code(whd_interface_t ifp,const whd_country_info_t * country_code)732 whd_result_t whd_wifi_set_custom_country_code(whd_interface_t ifp, const whd_country_info_t *country_code)
733 {
734     whd_driver_t whd_driver = ifp->whd_driver;
735 
736     /* Get chip number */
737     uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver);
738     if (wlan_chip_id == 43362)
739     {
740         whd_buffer_t buffer;
741         whd_result_t result;
742         whd_country_info_t *data;
743         data = (whd_country_info_t *)whd_cdc_get_ioctl_buffer(whd_driver, &buffer,
744                                                               (uint16_t)sizeof(whd_country_info_t) + 10);
745         if (data == NULL)
746         {
747             whd_assert("Could not get buffer for IOCTL", 0 != 0);
748             return WHD_BUFFER_ALLOC_FAIL;
749         }
750         memcpy(data, country_code, sizeof(whd_country_info_t) );
751         result = whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_CUSTOM_COUNTRY, buffer, NULL);
752         return result;
753     }
754     else
755     {
756         UNUSED_PARAMETER(country_code);
757         return WHD_UNSUPPORTED;
758     }
759 }
760 
whd_chip_specific_socsram_init(whd_driver_t whd_driver)761 whd_result_t whd_chip_specific_socsram_init(whd_driver_t whd_driver)
762 {
763     /* Get chip number */
764     uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver);
765     if ( (wlan_chip_id == 43430) || (wlan_chip_id == 43439) )
766     {
767         CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, SOCSRAM_BANKX_INDEX(whd_driver), 4, 0x3) );
768         CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, SOCSRAM_BANKX_PDA(whd_driver), 4, 0) );
769         return WHD_SUCCESS;
770     }
771     else
772     {
773         return WHD_SUCCESS;
774     }
775 }
776 
whd_chip_specific_init(whd_driver_t whd_driver)777 whd_result_t whd_chip_specific_init(whd_driver_t whd_driver)
778 {
779     /* Get chip number */
780     uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver);
781     if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43362) )
782     {
783         return WHD_SUCCESS;
784     }
785     else
786     {
787         return whd_enable_save_restore(whd_driver);
788     }
789 }
790 
whd_allow_wlan_bus_to_sleep(whd_driver_t whd_driver)791 whd_result_t whd_allow_wlan_bus_to_sleep(whd_driver_t whd_driver)
792 {
793     /* Get chip number */
794     uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver);
795     whd_bt_dev_t btdev = whd_driver->bt_dev;
796     if ( (wlan_chip_id == 4334) || (wlan_chip_id == 43362) )
797     {
798         /* Clear HT clock request */
799         if (whd_bus_is_up(whd_driver) == WHD_TRUE)
800         {
801             whd_bus_set_state(whd_driver, WHD_FALSE);
802             CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR,
803                                                       (uint8_t)1, 0) );
804             /* Bus specific sleep routine */
805             return whd_bus_sleep(whd_driver);
806         }
807         else
808         {
809             return WHD_SUCCESS;
810         }
811     }
812     else
813     {
814         /* Clear HT clock request */
815         if (whd_bus_is_up(whd_driver) == WHD_TRUE)
816         {
817             whd_bus_set_state(whd_driver, WHD_FALSE);
818             if (whd_driver->chip_info.save_restore_enable == WHD_FALSE)
819             {
820                 return whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR,
821                                                     (uint8_t)1, 0);
822             }
823             else
824             {
825                 if (btdev && btdev->bt_int_cb)
826                 {
827                     return WHD_SUCCESS;
828                 }
829                 return whd_kso_enable(whd_driver, WHD_FALSE);
830             }
831         }
832         else
833         {
834             return WHD_SUCCESS;
835         }
836     }
837 }
838 
whd_wifi_read_wlan_log(whd_driver_t whd_driver,char * buffer,uint32_t buffer_size)839 whd_result_t whd_wifi_read_wlan_log(whd_driver_t whd_driver, char *buffer, uint32_t buffer_size)
840 {
841     whd_result_t result;
842     uint32_t wlan_shared_address;
843     uint16_t wlan_chip_id = 0;
844 
845     CHECK_DRIVER_NULL(whd_driver);
846 
847     WHD_IOCTL_PRINT(whd_driver);
848 
849     wlan_chip_id = whd_chip_get_chip_id(whd_driver);
850     if (wlan_chip_id == 43362)
851     {
852         return whd_wifi_read_wlan_log_unsafe(whd_driver, ( (GET_C_VAR(whd_driver, CHIP_RAM_SIZE) +
853                                                             PLATFORM_WLAN_RAM_BASE) - 4 ), buffer, buffer_size);
854     }
855     else if ( (wlan_chip_id == 43909) || (wlan_chip_id == 43907) || (wlan_chip_id == 54907) )
856     {
857         result = whd_ensure_wlan_bus_is_up(whd_driver);
858         if (result != WHD_SUCCESS)
859         {
860             return result;
861         }
862         result = whd_wifi_read_wlan_log_unsafe(whd_driver, ( (GET_C_VAR(whd_driver, CHIP_RAM_SIZE) +
863                                                               GET_C_VAR(whd_driver,
864                                                                         ATCM_RAM_BASE_ADDRESS) ) - 4 ), buffer,
865                                                buffer_size);
866         whd_thread_notify(whd_driver);
867         return result;
868     }
869     else if ( (wlan_chip_id == 4334) || (wlan_chip_id == 4390) )
870     {
871         return WHD_UNSUPPORTED;
872     }
873     else
874     {
875         /* Backplane access needs HT clock. So, disabling bus sleep */
876         WHD_WLAN_KEEP_AWAKE(whd_driver);
877         /* FW populates the last word of RAM with wlan_shared_t struct address */
878         wlan_shared_address = PLATFORM_WLAN_RAM_BASE + GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS) +
879                               GET_C_VAR(whd_driver, CHIP_RAM_SIZE) - 4;
880         if (!GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS) && (whd_is_fw_sr_capable(whd_driver) == WHD_TRUE) )
881         {
882             wlan_shared_address -= GET_C_VAR(whd_driver, SOCRAM_SRMEM_SIZE);
883         }
884         result = whd_wifi_read_wlan_log_unsafe(whd_driver, wlan_shared_address, buffer, buffer_size);
885         WHD_WLAN_LET_SLEEP(whd_driver);
886         return result;
887     }
888 
889 }
890 
whd_wifi_print_whd_log(whd_driver_t whd_driver)891 uint32_t whd_wifi_print_whd_log(whd_driver_t whd_driver)
892 {
893     whd_result_t result;
894     char *buffer = NULL;
895 
896     CHECK_DRIVER_NULL(whd_driver);
897 
898     WHD_IOCTL_PRINT(whd_driver);
899 
900     if ( (buffer = whd_mem_malloc(WLAN_LOG_BUF_LEN) ) == NULL )
901     {
902         WPRINT_WHD_ERROR( ("Memory allocation failed for log buffer in %s \n", __FUNCTION__) );
903         return WHD_MALLOC_FAILURE;
904     }
905 
906     result = whd_wifi_read_wlan_log(whd_driver, buffer, WLAN_LOG_BUF_LEN);
907     if (result == WHD_SUCCESS)
908     {
909         whd_print_logbuffer();  // This is not supported yet.
910     }
911     whd_mem_free(buffer);
912     CHECK_RETURN(result);
913     return result;
914 }
915 
whd_wifi_read_fw_capabilities(whd_interface_t ifp)916 whd_result_t whd_wifi_read_fw_capabilities(whd_interface_t ifp)
917 {
918     whd_result_t result;
919     char caps[MAX_CAPS_BUFFER_SIZE];
920     whd_fwcap_id_t id;
921 
922     CHECK_IFP_NULL(ifp);
923     whd_driver_t whd_driver = ifp->whd_driver;
924 
925     result = whd_wifi_get_iovar_buffer(ifp, IOVAR_STR_CAP, (uint8_t *)caps, sizeof(caps) );
926     CHECK_RETURN(result);
927 
928     for (uint32_t i = 0; i < ARRAY_SIZE(whd_fwcap_map); i++)
929     {
930         if (strstr(caps, whd_fwcap_map[i].fwcap_name) )
931         {
932             id = whd_fwcap_map[i].feature;
933             WPRINT_WHD_DEBUG( ("Enabling FW Capabilities: %s\n", whd_fwcap_map[i].fwcap_name) );
934             whd_driver->chip_info.fwcap_flags |= (1 << id);
935         }
936     }
937     return WHD_SUCCESS;
938 }
939 
whd_ensure_wlan_bus_is_up(whd_driver_t whd_driver)940 whd_result_t whd_ensure_wlan_bus_is_up(whd_driver_t whd_driver)
941 {
942     uint8_t csr = 0;
943     uint32_t attempts = ( uint32_t )WLAN_BUS_UP_ATTEMPTS;
944     uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver);
945 
946     /* Ensure HT clock is up */
947     if (whd_bus_is_up(whd_driver) == WHD_TRUE)
948     {
949         return WHD_SUCCESS;
950     }
951 
952     if ( (wlan_chip_id == 43362) || (wlan_chip_id == 4334) )
953     {
954         /* Bus specific wakeup routine */
955         CHECK_RETURN(whd_bus_wakeup(whd_driver) );
956         CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR,
957                                                   (uint8_t)1, (uint32_t)SBSDIO_HT_AVAIL_REQ) );
958         do
959         {
960             CHECK_RETURN(whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR,
961                                                      (uint8_t)1, &csr) );
962             --attempts;
963         } while ( ( (csr & SBSDIO_HT_AVAIL) == 0 ) && (attempts != 0) &&
964                   (cy_rtos_delay_milliseconds( (uint32_t)1 ), 1 == 1) );
965 
966         if (attempts == 0)
967         {
968             WPRINT_WHD_ERROR( ("SDIO bus failed to come up , %s failed at %d \n", __func__, __LINE__) );
969             return WHD_SDIO_BUS_UP_FAIL;
970         }
971         else
972         {
973             whd_bus_set_state(whd_driver, WHD_TRUE);
974             return WHD_SUCCESS;
975         }
976     }
977     else if ( (wlan_chip_id == 43909) || (wlan_chip_id == 43907) || (wlan_chip_id == 54907) )
978     {
979         //To-Do
980         /* M2M power save mode */
981         //M2M_POWERSAVE_COMM_TX_BEGIN
982         return WHD_SUCCESS;
983     }
984     else
985     {
986         if (whd_driver->chip_info.save_restore_enable == WHD_FALSE)
987         {
988             CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR,
989                                                       (uint8_t)1, (uint32_t)SBSDIO_HT_AVAIL_REQ) );
990             do
991             {
992                 CHECK_RETURN(whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR,
993                                                          (uint8_t)sizeof(csr), &csr) );
994                 --attempts;
995             } while ( ( (csr & SBSDIO_HT_AVAIL) == 0 ) && (attempts != 0) &&
996                       (cy_rtos_delay_milliseconds( ( uint32_t )HT_AVAIL_WAIT_MS ), 1 == 1) );
997 
998             if (attempts == 0)
999             {
1000                 WPRINT_WHD_ERROR( ("SDIO bus failed to come up , %s failed at %d \n", __func__, __LINE__) );
1001                 return WHD_SDIO_BUS_UP_FAIL;
1002             }
1003             else
1004             {
1005                 whd_bus_set_state(whd_driver, WHD_TRUE);
1006                 return WHD_SUCCESS;
1007             }
1008         }
1009         else
1010         {
1011             if (whd_kso_enable(whd_driver, WHD_TRUE) == WHD_SUCCESS)
1012             {
1013                 whd_bus_set_state(whd_driver, WHD_TRUE);
1014                 return WHD_SUCCESS;
1015             }
1016             else
1017             {
1018                 WPRINT_WHD_ERROR( ("SDIO bus failed to come up , %s failed at %d \n", __func__, __LINE__) );
1019                 return WHD_SDIO_BUS_UP_FAIL;
1020             }
1021         }
1022     }
1023 }
1024 
whd_is_fw_sr_capable(whd_driver_t whd_driver)1025 static whd_bool_t whd_is_fw_sr_capable(whd_driver_t whd_driver)
1026 {
1027     uint32_t core_capext;
1028     uint32_t retention_ctl = 0;
1029     uint32_t srctrl = 0;
1030     whd_bool_t save_restore_capable = WHD_FALSE;
1031     whd_result_t result = WHD_SUCCESS;
1032 
1033     /* Get chip number */
1034     uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver);
1035 
1036     if ( (wlan_chip_id == 43430) || (wlan_chip_id == 43439) )
1037     {
1038         /* check if fw initialized sr engine */
1039         if (whd_bus_read_backplane_value(whd_driver, (uint32_t)CHIPCOMMON_SR_CONTROL1, (uint8_t)4,
1040                                          (uint8_t *)&srctrl) != WHD_SUCCESS)
1041         {
1042             return WHD_FALSE;
1043         }
1044         if (srctrl != 0)
1045         {
1046             return WHD_TRUE;
1047         }
1048         else
1049         {
1050             return WHD_FALSE;
1051         }
1052     }
1053     else if ( (wlan_chip_id == 43340) || (wlan_chip_id == 43342) )
1054     {
1055         /* check if fw initialized sr engine */
1056         result = whd_bus_read_backplane_value(whd_driver, (uint32_t)CHIPCOMMON_CORE_CAPEXT_ADDR, (uint8_t)4,
1057                                               (uint8_t *)&core_capext);
1058         if (result != WHD_SUCCESS)
1059         {
1060             return WHD_FALSE;
1061         }
1062 
1063         if ( (core_capext & CHIPCOMMON_CORE_CAPEXT_SR_SUPPORTED) != 0 )
1064         {
1065             result = whd_bus_read_backplane_value(whd_driver, (uint32_t)CHIPCOMMON_CORE_RETENTION_CTL, (uint8_t)4,
1066                                                   (uint8_t *)&retention_ctl);
1067             if (result != WHD_SUCCESS)
1068             {
1069                 return WHD_FALSE;
1070             }
1071             if ( (retention_ctl & (CHIPCOMMON_CORE_RCTL_MACPHY_DISABLE | CHIPCOMMON_CORE_RCTL_LOGIC_DISABLE) ) == 0 )
1072             {
1073                 save_restore_capable = WHD_TRUE;
1074             }
1075         }
1076         return save_restore_capable;
1077     }
1078     else
1079     {
1080         /* check if fw initialized sr engine */
1081         result =
1082             whd_bus_read_backplane_value(whd_driver, (uint32_t)RETENTION_CTL(
1083                                              whd_driver), (uint8_t)sizeof(retention_ctl),
1084                                          (uint8_t *)&retention_ctl);
1085         if (result != WHD_SUCCESS)
1086         {
1087             return WHD_FALSE;
1088         }
1089         if ( (retention_ctl & (RCTL_MACPHY_DISABLE | RCTL_LOGIC_DISABLE) ) == 0 )
1090         {
1091             save_restore_capable = WHD_TRUE;
1092         }
1093         return save_restore_capable;
1094     }
1095 }
1096 
whd_enable_save_restore(whd_driver_t whd_driver)1097 static whd_result_t whd_enable_save_restore(whd_driver_t whd_driver)
1098 {
1099     uint8_t data;
1100     /* Get chip number */
1101     uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver);
1102 
1103     if (whd_is_fw_sr_capable(whd_driver) == WHD_TRUE)
1104     {
1105         if ( (wlan_chip_id == 43012) || (wlan_chip_id == 0x4373) )
1106         {
1107             /* Configure WakeupCtrl register to set AlpAvail request bit in chipClockCSR register
1108              * after the sdiod core is powered on.
1109              */
1110             CHECK_RETURN(whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_WAKEUP_CTRL,
1111                                                      (uint8_t)sizeof(data), &data) );
1112             data |= SBSDIO_WCTRL_WAKE_TILL_ALP_AVAIL;
1113             CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_WAKEUP_CTRL,
1114                                                       (uint8_t)sizeof(data), data) );
1115         }
1116         else
1117         {
1118             /* Configure WakeupCtrl register to set HtAvail request bit in chipClockCSR register
1119              * after the sdiod core is powered on.
1120              */
1121             CHECK_RETURN(whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_WAKEUP_CTRL,
1122                                                      (uint8_t)1, &data) );
1123             data |= SBSDIO_WCTRL_WAKE_TILL_HT_AVAIL;
1124             CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_WAKEUP_CTRL,
1125                                                       (uint8_t)1, data) );
1126         }
1127 
1128         /* Set brcmCardCapability to noCmdDecode mode.
1129          * It makes sdiod_aos to wakeup host for any activity of cmd line, even though
1130          * module won't decode cmd or respond
1131          */
1132         CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, (uint32_t)SDIOD_CCCR_BRCM_CARDCAP,
1133                                                   (uint8_t)1, SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC) );
1134         if ( (wlan_chip_id == 43012) || (wlan_chip_id == 0x4373) )
1135         {
1136             CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR,
1137                                                       (uint8_t)1, SBSDIO_HT_AVAIL_REQ) );
1138         }
1139         else
1140         {
1141             CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_CHIP_CLOCK_CSR,
1142                                                       (uint8_t)1, (uint32_t)SBSDIO_FORCE_HT) );
1143         }
1144 
1145         /* Enable KeepSdioOn (KSO) bit for normal operation */
1146         if ( (wlan_chip_id == 43012) || (wlan_chip_id == 0x4373) )
1147         {
1148             CHECK_RETURN(whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR,
1149                                                      (uint8_t)sizeof(data), &data) );
1150         }
1151         else
1152         {
1153             CHECK_RETURN(whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR,
1154                                                      (uint8_t)1, &data) );
1155         }
1156         if ( (data & SBSDIO_SLPCSR_KEEP_SDIO_ON) == 0 )
1157         {
1158             data |= SBSDIO_SLPCSR_KEEP_SDIO_ON;
1159             if ( (wlan_chip_id == 43012) || (wlan_chip_id == 0x4373) )
1160             {
1161                 CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR,
1162                                                           (uint8_t)sizeof(data), data) );
1163             }
1164             else
1165             {
1166                 CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR,
1167                                                           (uint8_t)1, data) );
1168             }
1169         }
1170 
1171         /* SPI bus can be configured for sleep by default.
1172          * KSO bit solely controls the wlan chip sleep
1173          */
1174         CHECK_RETURN(whd_bus_sleep(whd_driver) );
1175 
1176         /* Put SPI interface block to sleep */
1177         CHECK_RETURN(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, SDIO_PULL_UP, (uint8_t)1, 0xf) );
1178 
1179         whd_driver->chip_info.save_restore_enable = WHD_TRUE;
1180     }
1181     else
1182     {
1183         whd_driver->chip_info.save_restore_enable = WHD_FALSE;
1184     }
1185 
1186     return WHD_SUCCESS;
1187 }
1188 
whd_kso_enable(whd_driver_t whd_driver,whd_bool_t enable)1189 static whd_result_t whd_kso_enable(whd_driver_t whd_driver, whd_bool_t enable)
1190 {
1191     uint8_t write_value = 0;
1192     uint8_t read_value = 0;
1193     uint8_t compare_value;
1194     uint8_t bmask;
1195     uint32_t attempts = ( uint32_t )MAX_KSO_ATTEMPTS;
1196     whd_result_t result;
1197     /* Get chip number */
1198 
1199     uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver);
1200     if (enable == WHD_TRUE)
1201     {
1202         write_value |= SBSDIO_SLPCSR_KEEP_SDIO_ON;
1203     }
1204 
1205     /* 1st KSO write goes to AOS wake up core if device is asleep  */
1206     /* Possibly device might not respond to this cmd. So, don't check return value here */
1207     if ( (wlan_chip_id == 43430) || (wlan_chip_id == 43439) || (wlan_chip_id == 43340) || (wlan_chip_id == 43342) )
1208     {
1209         /* 2 Sequential writes to KSO bit are required for SR module to wakeup, both write can fail */
1210         CHECK_RETURN_IGNORE(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR,
1211                                                          (uint8_t)1,
1212                                                          write_value) );
1213         CHECK_RETURN_IGNORE(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR,
1214                                                          (uint8_t)1,
1215                                                          write_value) );
1216         if (enable == WHD_TRUE)
1217         {
1218             /* device WAKEUP through KSO:
1219              * write bit 0 & read back until
1220              * both bits 0(kso bit) & 1 (dev on status) are set
1221              */
1222             compare_value = SBSDIO_SLPCSR_KEEP_SDIO_ON | SBSDIO_SLPCSR_DEVICE_ON;
1223             bmask = compare_value;
1224         }
1225         else
1226         {
1227             /* Put device to sleep, turn off  KSO  */
1228             compare_value = 0;
1229             /* Check for bit0 only, bit1(devon status) may not get cleared right away */
1230             bmask = SBSDIO_SLPCSR_KEEP_SDIO_ON;
1231         }
1232     }
1233     else
1234     {
1235         CHECK_RETURN_IGNORE(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR,
1236                                                          (uint8_t)1, write_value) );
1237 
1238         /* In case of 43012 chip, the chip could go down immediately after KSO bit is cleared.
1239          * So the further reads of KSO register could fail. Thereby just bailing out immediately
1240          * after clearing KSO bit, to avoid polling of KSO bit.
1241          */
1242         if (enable == WHD_FALSE)
1243         {
1244             return WHD_SUCCESS;
1245         }
1246 
1247         /* 2 Sequential writes to KSO bit are required for SR module to wakeup */
1248         CHECK_RETURN_IGNORE(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR,
1249                                                          (uint8_t)1, write_value) );
1250 
1251         /* device WAKEUP through KSO:
1252          * write bit 0 & read back until
1253          * both bits 0(kso bit) & 1 (dev on status) are set
1254          */
1255         compare_value = SBSDIO_SLPCSR_KEEP_SDIO_ON | SBSDIO_SLPCSR_DEVICE_ON;
1256         bmask = compare_value;
1257     }
1258 
1259     while (attempts != 0)
1260     {
1261         /* Reliable KSO bit set/clr:
1262          * Sdiod sleep write access appears to be in sync with PMU 32khz clk
1263          * just one write attempt may fail,(same is with read ?)
1264          * in any case, read it back until it matches written value
1265          */
1266         result = whd_bus_read_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR, (uint8_t)1,
1267                                              &read_value);
1268         if ( ( (read_value & bmask) == compare_value ) && (result == WHD_SUCCESS) && (read_value != 0xFF) )
1269         {
1270             break;
1271         }
1272 
1273         cy_rtos_delay_milliseconds( ( uint32_t )KSO_WAIT_MS );
1274 
1275         CHECK_RETURN_IGNORE(whd_bus_write_register_value(whd_driver, BACKPLANE_FUNCTION, (uint32_t)SDIO_SLEEP_CSR,
1276                                                          (uint8_t)1, write_value) );
1277         attempts--;
1278     }
1279 
1280     if (attempts == 0)
1281     {
1282         WPRINT_WHD_ERROR( ("SDIO bus failed to come up , %s failed at %d \n", __func__, __LINE__) );
1283         return WHD_SDIO_BUS_UP_FAIL;
1284     }
1285     else
1286     {
1287         return WHD_SUCCESS;
1288     }
1289 }
1290 
1291 void whd_wlan_wake_from_host(whd_driver_t whd_driver);
1292 
whd_wlan_wake_from_host(whd_driver_t whd_driver)1293 void whd_wlan_wake_from_host(whd_driver_t whd_driver)
1294 {
1295     uint32_t val32 = 0;
1296     whd_result_t result;
1297 
1298     result = whd_bus_read_backplane_value(whd_driver, D11_MACCONTROL_REG, D11_MACCONTROL_REG_SIZE, (uint8_t *)&val32);
1299     if (result != WHD_SUCCESS)
1300     {
1301         WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) );
1302     }
1303     WPRINT_WHD_DEBUG( ("%s: %d:before: maccontrol: 0x%08x\n", __FUNCTION__, __LINE__, (unsigned int)val32) );
1304 
1305     val32 = val32 | D11_MACCONTROL_REG_WAKE;
1306     result = whd_bus_write_backplane_value(whd_driver, D11_MACCONTROL_REG, D11_MACCONTROL_REG_SIZE, val32);
1307     if (result != WHD_SUCCESS)
1308     {
1309         WPRINT_WHD_ERROR( ("%s:%d whd_bus_write_backplane_value failed\n", __FUNCTION__, __LINE__) );
1310     }
1311     result = whd_bus_read_backplane_value(whd_driver, D11_MACCONTROL_REG, D11_MACCONTROL_REG_SIZE, (uint8_t *)&val32);
1312     if (result != WHD_SUCCESS)
1313     {
1314         WPRINT_WHD_ERROR( ("%s:%d whd_bus_read_backplane_value failed\n", __FUNCTION__, __LINE__) )
1315     }
1316     WPRINT_WHD_DEBUG( ("%s: %d:after: maccontrol: 0x%08x\n", __FUNCTION__, __LINE__, (unsigned int)val32) );
1317 }
1318 
whd_wlan_bus_complete_ds_wake(whd_driver_t whd_driver,whd_bool_t wake_from_firmware,uint32_t wake_event_indication_addr,uint32_t wake_indication_addr,uint32_t sdio_control_addr)1319 whd_result_t whd_wlan_bus_complete_ds_wake(whd_driver_t whd_driver, whd_bool_t wake_from_firmware,
1320                                            uint32_t wake_event_indication_addr, uint32_t wake_indication_addr,
1321                                            uint32_t sdio_control_addr)
1322 {
1323     uint32_t val = 0;
1324     uint32_t val1 = 0;
1325     uint32_t count = 0;
1326     int32_t timeout = 0;
1327     /* Get chip number */
1328 
1329     uint16_t wlan_chip_id = whd_chip_get_chip_id(whd_driver);
1330 
1331     if (wlan_chip_id == 43012)
1332     {
1333         WPRINT_WHD_DEBUG_DS( ("%s: enter: wake_fr_fw=%d\n", __func__, (int )wake_from_firmware) );
1334 
1335         /* Need to do for all wake causes */
1336         while (WHD_SUCCESS !=
1337                whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IOEN, (uint8_t)1, SDIO_FUNC_ENABLE_1) )
1338         {
1339             WPRINT_WHD_DEBUG( ("Retry IOEN write\n") );
1340             cy_rtos_delay_milliseconds(10);
1341         }
1342 
1343         CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(wake_event_indication_addr), 2,
1344                                                   (uint8_t *)&val) );
1345         CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(wake_indication_addr), 2, (uint8_t *)&val) );
1346 
1347         if (WHD_TRUE == wake_from_firmware)
1348         {
1349             WPRINT_WHD_DEBUG_DS( ("%s: CCCR written\n", __func__) );
1350 
1351             /* Read DS1 CTRL STATUS SHM to Check whether HOST MAIL BOX interrupt is triggered due to TX/RX
1352              * For RX Cases , Value will be DS1_SLEEP
1353              * For TX Cases, Value will be MAC ON or RADIO_PHY_ON
1354              */
1355             CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_STATUS), (uint8_t)2,
1356                                                       (uint8_t *)&val) );
1357             if (val == DS1_SLEEP)
1358             {
1359                 /* HUDI communication to inform D11 to Process and Exit DS1 not required for D11 Wake cases
1360                  * Simply update PMU Resource Mask and Re-download firmware for this case
1361                  */
1362                 WPRINT_WHD_DEBUG_DS( ("%s: D11 wake detected\n", __func__) );
1363 
1364                 CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, PMU_MINRESMASK, 1,
1365                                                            DEFAULT_43012_MIN_RES_MASK) );
1366 
1367                 return WHD_SUCCESS;
1368             }
1369 
1370             CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_SDIO), 2,
1371                                                        C_DS1_CTRL_SDIO_DS1_EXIT | C_DS1_CTRL_REQ_VALID) );
1372             WPRINT_WHD_DEBUG_DS( ("%s: SDIO ctl written\n", __func__) );
1373 
1374             CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_SDIO), (uint8_t)2,
1375                                                       (uint8_t *)&val) );
1376             WPRINT_WHD_DEBUG_DS( ("%s: M_DS1_CTRL_SDIO = [%x]\n", __func__, (int )val) );
1377 
1378             CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11_MACCONTROL_REG, (uint8_t)2, (uint8_t *)&val1) );
1379             WPRINT_WHD_DEBUG_DS( ("%s: before setting wake = [%x]\n", __func__, (int )val1) );
1380 
1381             CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, D11_MACCONTROL_REG, 2,
1382                                                        val1 | D11_MACCONTROL_REG_WAKE) );
1383             WPRINT_WHD_DEBUG_DS( ("%s: After setting wake= [%x]\n", __func__, (int )val1) );
1384 
1385             while (!(val & C_DS1_CTRL_PROC_DONE) )
1386             {
1387                 CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_SDIO), (uint8_t)2,
1388                                                           (uint8_t *)&val) );
1389                 count++;
1390                 if (count == 1000)
1391                 {
1392                     WPRINT_WHD_ERROR( ("%s: sdio timed out! Aborting\n", __func__) );
1393                     return WHD_TIMEOUT;
1394                 }
1395             }
1396 
1397             CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_SDIO), (uint8_t)2,
1398                                                       (uint8_t *)&val) );
1399             WPRINT_WHD_DEBUG_DS( ("%s: M_DS1_CTRL_SDIO after poll = [%x]\n", __func__, (int )val) );
1400 
1401             CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11_MACCONTROL_REG, (uint8_t)2, (uint8_t *)&val1) );
1402             WPRINT_WHD_DEBUG_DS( ("%s: D11_MACCONTROL_REG before Clear = [%x]\n", __func__, (int )val1) );
1403 
1404             CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, D11_MACCONTROL_REG, 2,
1405                                                        val1 & D11_MACCONTROL_CLEAR_WAKE) );
1406             WPRINT_WHD_DEBUG_DS( ("%s: D11_MACCONTROL_REG after Clear = [%x]\n", __func__, (int )val1) );
1407 
1408             CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, PMU_MINRESMASK, 1, DEFAULT_43012_MIN_RES_MASK) );
1409             CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, PMU_MINRESMASK, (uint8_t)1, (uint8_t *)&val1) );
1410 
1411             WPRINT_WHD_DEBUG_DS( ("%s: PMU_MINRESMASK = [%x]\n", __func__, (int )val1) );
1412         }
1413         else
1414         {
1415             while (WHD_SUCCESS != whd_ensure_wlan_bus_is_up(whd_driver) )
1416             {
1417                 WPRINT_WHD_DEBUG_DS( ("Retrying bus is up\n") );
1418             }
1419 
1420             WPRINT_WHD_DEBUG_DS( ("write backplane\n") );
1421 
1422             CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(sdio_control_addr), 2, (uint8_t *)&val) );
1423 
1424             while (WHD_SUCCESS !=
1425                    whd_bus_write_backplane_value(whd_driver, D11SHM_ADDR(sdio_control_addr), 2,
1426                                                  val | C_DS1_CTRL_SDIO_DS1_EXIT | C_DS1_CTRL_REQ_VALID) )
1427             {
1428                 WPRINT_WHD_DEBUG_DS( ("Retrying backplane write; addr=%x\n",
1429                                       (unsigned int )D11SHM_ADDR(sdio_control_addr) ) );
1430                 cy_rtos_delay_milliseconds(100);
1431             }
1432 
1433             WPRINT_WHD_DEBUG_DS( ("wake host\n") );
1434             whd_wlan_wake_from_host(whd_driver);
1435 
1436             WPRINT_WHD_DEBUG_DS( ("poll for timeout\n") );
1437             /* Poll for PROC_DONE to be set by ucode; timeout after a good amount of time */
1438             for (timeout = WHD_WLAN_WAKE_TIMEOUT * 10, val = 0; timeout >= 0;
1439                  timeout -= WHD_SHARED_MEMORY_POLLING_DELAY)
1440             {
1441                 whd_result_t read_result =
1442                     whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(sdio_control_addr), 2, (uint8_t *)&val);
1443 
1444                 if ( (WHD_SUCCESS != read_result) || !( (val) & C_DS1_CTRL_PROC_DONE ) )
1445                 {
1446                     cy_rtos_delay_milliseconds (WHD_SHARED_MEMORY_POLLING_DELAY);
1447                 }
1448                 else
1449                 {
1450                     /* success! */
1451                     WPRINT_WHD_DEBUG_DS( ("Ucode has posted DONE\n") );
1452                     break;
1453                 }
1454             }
1455 
1456             WPRINT_WHD_DEBUG_DS( ("%s: %d: 0x%08x\n", __func__, __LINE__, (unsigned int)val) );
1457 
1458             if ( (timeout < 0) && !(val & C_DS1_CTRL_PROC_DONE) )
1459             {
1460                 WPRINT_WHD_ERROR( ("%s: Failed to enter DS1 Exit state!\n", __func__) );
1461                 return WHD_TIMEOUT;
1462             }
1463         }
1464         WPRINT_WHD_DEBUG_DS( ("successfully completed DS wake sequence\n") );
1465         return WHD_SUCCESS;
1466     }
1467     else
1468     {
1469         UNUSED_PARAMETER(wake_from_firmware);
1470         UNUSED_PARAMETER(wake_event_indication_addr);
1471         UNUSED_PARAMETER(wake_indication_addr);
1472         UNUSED_PARAMETER(sdio_control_addr);
1473 
1474         WPRINT_WHD_DEBUG( ("%s: enter\n", __FUNCTION__) );
1475 
1476         CHECK_RETURN(whd_bus_write_register_value(whd_driver, BUS_FUNCTION, SDIOD_CCCR_IOEN, (uint8_t)1,
1477                                                   SDIO_FUNC_ENABLE_1) );
1478         WPRINT_WHD_DEBUG( ("%s: CCCR written\n", __FUNCTION__) );
1479 
1480         /* Read DS1 CTRL STATUS SHM to Check whether HOST MAIL BOX interrupt is triggered due to TX/RX
1481          * For RX Cases , Value will be DS1_SLEEP
1482          * For TX Cases, Value will be MAC ON or RADIO_PHY_ON
1483          */
1484         CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_STATUS), (uint8_t)2,
1485                                                   (uint8_t *)&val) );
1486         if (val == DS1_SLEEP)
1487         {
1488             /* HUDI communication to inform D11 to Process and Exit DS1 not required for D11 Wake cases
1489              * Simply update PMU Resource Mask and Re-download firmware for this case
1490              */
1491             CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, PMU_MINRESMASK, 1, DEFAULT_43012_MIN_RES_MASK) );
1492             return WHD_SUCCESS;
1493         }
1494         CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_SDIO), 2,
1495                                                    C_DS1_CTRL_SDIO_DS1_EXIT | C_DS1_CTRL_REQ_VALID) );
1496         WPRINT_WHD_DEBUG( ("%s: SDIO ctl written\n", __FUNCTION__) );
1497 
1498         CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(
1499                                                       M_DS1_CTRL_SDIO), (uint8_t)2, (uint8_t *)&val) );
1500         WPRINT_WHD_DEBUG( ("%s: M_DS1_CTRL_SDIO = [%x]\n", __FUNCTION__, (int)val) );
1501 
1502         CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11_MACCONTROL_REG, (uint8_t)2, (uint8_t *)&val1) );
1503         WPRINT_WHD_DEBUG( ("%s: before setting wake = [%x]\n", __FUNCTION__, (int)val1) );
1504         CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, D11_MACCONTROL_REG, 2,
1505                                                    val1 | D11_MACCONTROL_REG_WAKE) );
1506         WPRINT_WHD_DEBUG( ("%s: After setting wake= [%x]\n", __FUNCTION__, (int)val1) );
1507 
1508         while (!(val & C_DS1_CTRL_PROC_DONE) )
1509         {
1510             CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(M_DS1_CTRL_SDIO), (uint8_t)2,
1511                                                       (uint8_t *)&val) );
1512             count++;
1513             if (count == 1000)
1514             {
1515                 WPRINT_WHD_ERROR( ("%s: sdio timed out! Aborting\n", __FUNCTION__) );
1516                 return WHD_TIMEOUT;
1517             }
1518         }
1519 
1520         CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11SHM_ADDR(
1521                                                       M_DS1_CTRL_SDIO), (uint8_t)2, (uint8_t *)&val) );
1522         WPRINT_WHD_DEBUG( ("%s: M_DS1_CTRL_SDIO after poll = [%x]\n", __FUNCTION__, (int)val) );
1523 
1524         CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, D11_MACCONTROL_REG, (uint8_t)2, (uint8_t *)&val1) );
1525         WPRINT_WHD_DEBUG( ("%s: D11_MACCONTROL_REG before Clear = [%x]\n", __FUNCTION__, (int)val1) );
1526 
1527         CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, D11_MACCONTROL_REG, 2,
1528                                                    val1 & D11_MACCONTROL_CLEAR_WAKE) );
1529         WPRINT_WHD_DEBUG( ("%s: D11_MACCONTROL_REG after Clear = [%x]\n", __FUNCTION__, (int)val1) );
1530 
1531         CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, PMU_MINRESMASK, 1, DEFAULT_43012_MIN_RES_MASK) );
1532         CHECK_RETURN(whd_bus_read_backplane_value(whd_driver, PMU_MINRESMASK, (uint8_t)1, (uint8_t *)&val1) );
1533         WPRINT_WHD_DEBUG( ("%s: PMU_MINRESMASK = [%x]\n", __FUNCTION__, (int)val1) );
1534         return WHD_SUCCESS;
1535     }
1536 }
1537 
1538