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 /** @file
19 * Broadcom WLAN M2M Protocol interface
20 *
21 * Implements the WHD Bus Protocol Interface for M2M
22 * Provides functions for initialising, de-intitialising 802.11 device,
23 * sending/receiving raw packets etc
24 */
25
26 #include "cybsp.h"
27 #if (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_M2M_INTERFACE)
28
29 #include "cyhal_dma.h"
30 #include "cyhal_hw_types.h"
31 #include "whd_bus_m2m_protocol.h"
32
33 #include "whd_bus.h"
34 #include "whd_bus_common.h"
35 #include "whd_chip_reg.h"
36 #include "whd_chip_constants.h"
37 #include "whd_buffer_api.h"
38 #include "whd_types_int.h"
39 #include "whd_types.h"
40 #include "whd_thread_internal.h"
41 #include "whd_resource_if.h"
42 #include "whd_wlioctl.h"
43
44 /******************************************************
45 * Constants
46 ******************************************************/
47
48 #define WHD_BUS_M2M_BACKPLANE_READ_PADD_SIZE (0)
49 #define WHD_BUS_M2M_MAX_BACKPLANE_TRANSFER_SIZE (WHD_PAYLOAD_MTU)
50 #define BOOT_WLAN_WAIT_TIME (5) /* 5ms wait time */
51 #define M2M_DMA_RX_BUFFER_SIZE (WHD_PHYSICAL_HEADER + WLC_IOCTL_MEDLEN)
52
53 #define ARMCR4_SW_INT0 (0x1 << 0)
54
55 #if !defined (__IAR_SYSTEMS_ICC__)
56 /* assume registers are Device memory, so have implicit CPU memory barriers */
57 #define MEMORY_BARRIER_AGAINST_COMPILER_REORDERING() __asm__ __volatile__ ("" : : : "memory")
58 #define REGISTER_WRITE_WITH_BARRIER(type, address, value) \
59 do {*(volatile type *)(address) = (type)(value); \
60 MEMORY_BARRIER_AGAINST_COMPILER_REORDERING();} while (0)
61 #define REGISTER_READ(type, address) \
62 (*(volatile type *)(address) )
63 #endif
64
65 /******************************************************
66 * Structures
67 ******************************************************/
68 struct whd_bus_priv
69 {
70 whd_m2m_config_t m2m_config;
71 cyhal_m2m_t *m2m_obj;
72 };
73
74 /******************************************************
75 * Variables
76 ******************************************************/
77 static whd_bus_info_t whd_bus_m2m_info;
78 static struct whd_bus_priv whd_bus_priv;
79
80 /******************************************************
81 * Function declarations
82 ******************************************************/
83 static whd_result_t whd_bus_m2m_init(whd_driver_t whd_driver);
84 static whd_result_t whd_bus_m2m_deinit(whd_driver_t whd_driver);
85 static whd_result_t whd_bus_m2m_ack_interrupt(whd_driver_t whd_driver, uint32_t intstatus);
86 static whd_result_t whd_bus_m2m_send_buffer(whd_driver_t whd_driver, whd_buffer_t buffer);
87
88 static whd_bool_t whd_bus_m2m_wake_interrupt_present(whd_driver_t whd_driver);
89 static uint32_t whd_bus_m2m_packet_available_to_read(whd_driver_t whd_driver);
90 static whd_result_t whd_bus_m2m_read_frame(whd_driver_t whd_driver, whd_buffer_t *buffer);
91
92 static whd_result_t whd_bus_m2m_write_backplane_value(whd_driver_t whd_driver, uint32_t address,
93 uint8_t register_length, uint32_t value);
94 static whd_result_t whd_bus_m2m_read_backplane_value(whd_driver_t whd_driver, uint32_t address, uint8_t register_length,
95 uint8_t *value);
96 static whd_result_t whd_bus_m2m_write_register_value(whd_driver_t whd_driver, whd_bus_function_t function,
97 uint32_t address, uint8_t value_length, uint32_t value);
98 static whd_result_t whd_bus_m2m_read_register_value(whd_driver_t whd_driver, whd_bus_function_t function,
99 uint32_t address, uint8_t value_length, uint8_t *value);
100 static whd_result_t whd_bus_m2m_transfer_bytes(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction,
101 whd_bus_function_t function, uint32_t address, uint16_t size,
102 whd_transfer_bytes_packet_t *data);
103
104 static whd_result_t whd_bus_m2m_poke_wlan(whd_driver_t whd_driver);
105 static whd_result_t whd_bus_m2m_wakeup(whd_driver_t whd_driver);
106 static whd_result_t whd_bus_m2m_sleep(whd_driver_t whd_driver);
107 static uint8_t whd_bus_m2m_backplane_read_padd_size(whd_driver_t whd_driver);
108 static whd_result_t whd_bus_m2m_wait_for_wlan_event(whd_driver_t whd_driver, cy_semaphore_t *transceive_semaphore);
109 static whd_bool_t whd_bus_m2m_use_status_report_scheme(whd_driver_t whd_driver);
110 static uint32_t whd_bus_m2m_get_max_transfer_size(whd_driver_t whd_driver);
111 static void whd_bus_m2m_init_stats(whd_driver_t whd_driver);
112 static whd_result_t whd_bus_m2m_print_stats(whd_driver_t whd_driver, whd_bool_t reset_after_print);
113 static whd_result_t whd_bus_m2m_reinit_stats(whd_driver_t whd_driver, whd_bool_t wake_from_firmware);
114 static whd_result_t whd_bus_m2m_irq_register(whd_driver_t whd_driver);
115 static whd_result_t whd_bus_m2m_irq_enable(whd_driver_t whd_driver, whd_bool_t enable);
116 static whd_result_t whd_bus_m2m_download_resource(whd_driver_t whd_driver, whd_resource_type_t resource,
117 whd_bool_t direct_resource, uint32_t address, uint32_t image_size);
118 static whd_result_t whd_bus_m2m_write_wifi_nvram_image(whd_driver_t whd_driver);
119 static whd_result_t whd_bus_m2m_set_backplane_window(whd_driver_t whd_driver, uint32_t addr, uint32_t *curaddr);
120
121 static whd_result_t boot_wlan(whd_driver_t whd_driver);
122 whd_bool_t whd_ensure_wlan_is_up(whd_driver_t whd_driver);
123 whd_result_t m2m_bus_write_wifi_firmware_image(whd_driver_t whd_driver);
124 void whd_bus_m2m_irq_handler(void *callback_arg, cyhal_m2m_event_t events);
125
126
127 /******************************************************
128 * Function definitions
129 ******************************************************/
130
131 // Functions for whd_driver->bus_if function list
whd_bus_m2m_attach(whd_driver_t whd_driver,whd_m2m_config_t * whd_m2m_config,cyhal_m2m_t * m2m_obj)132 uint32_t whd_bus_m2m_attach(whd_driver_t whd_driver, whd_m2m_config_t *whd_m2m_config, cyhal_m2m_t *m2m_obj)
133 {
134 WPRINT_WHD_INFO( ("m2m_attach\n") );
135
136 whd_driver->bus_if = &whd_bus_m2m_info;
137 whd_driver->bus_priv = &whd_bus_priv;
138
139 memset(whd_driver->bus_if, 0, sizeof(whd_bus_info_t) );
140 memset(whd_driver->bus_priv, 0, sizeof(struct whd_bus_priv) );
141
142 whd_driver->bus_priv->m2m_obj = m2m_obj;
143 whd_driver->bus_priv->m2m_config = *whd_m2m_config;
144
145 whd_driver->bus_if->whd_bus_init_fptr = whd_bus_m2m_init;
146 whd_driver->bus_if->whd_bus_deinit_fptr = whd_bus_m2m_deinit;
147
148 whd_driver->bus_if->whd_bus_ack_interrupt_fptr = whd_bus_m2m_ack_interrupt;
149 whd_driver->bus_if->whd_bus_send_buffer_fptr = whd_bus_m2m_send_buffer;
150
151 whd_driver->bus_if->whd_bus_wake_interrupt_present_fptr = whd_bus_m2m_wake_interrupt_present;
152 whd_driver->bus_if->whd_bus_packet_available_to_read_fptr = whd_bus_m2m_packet_available_to_read;
153 whd_driver->bus_if->whd_bus_read_frame_fptr = whd_bus_m2m_read_frame;
154
155
156 whd_driver->bus_if->whd_bus_write_backplane_value_fptr = whd_bus_m2m_write_backplane_value;
157 whd_driver->bus_if->whd_bus_read_backplane_value_fptr = whd_bus_m2m_read_backplane_value;
158
159 whd_driver->bus_if->whd_bus_write_register_value_fptr = whd_bus_m2m_write_register_value;
160 whd_driver->bus_if->whd_bus_read_register_value_fptr = whd_bus_m2m_read_register_value;
161
162 whd_driver->bus_if->whd_bus_transfer_bytes_fptr = whd_bus_m2m_transfer_bytes;
163
164 whd_driver->bus_if->whd_bus_poke_wlan_fptr = whd_bus_m2m_poke_wlan;
165
166 whd_driver->bus_if->whd_bus_wakeup_fptr = whd_bus_m2m_wakeup;
167 whd_driver->bus_if->whd_bus_sleep_fptr = whd_bus_m2m_sleep;
168
169 whd_driver->bus_if->whd_bus_backplane_read_padd_size_fptr = whd_bus_m2m_backplane_read_padd_size;
170
171 whd_driver->bus_if->whd_bus_wait_for_wlan_event_fptr = whd_bus_m2m_wait_for_wlan_event;
172 whd_driver->bus_if->whd_bus_use_status_report_scheme_fptr = whd_bus_m2m_use_status_report_scheme;
173
174 whd_driver->bus_if->whd_bus_get_max_transfer_size_fptr = whd_bus_m2m_get_max_transfer_size;
175
176 whd_driver->bus_if->whd_bus_init_stats_fptr = whd_bus_m2m_init_stats;
177 whd_driver->bus_if->whd_bus_print_stats_fptr = whd_bus_m2m_print_stats;
178 whd_driver->bus_if->whd_bus_reinit_stats_fptr = whd_bus_m2m_reinit_stats;
179 whd_driver->bus_if->whd_bus_irq_register_fptr = whd_bus_m2m_irq_register;
180 whd_driver->bus_if->whd_bus_irq_enable_fptr = whd_bus_m2m_irq_enable;
181 whd_driver->bus_if->whd_bus_download_resource_fptr = whd_bus_m2m_download_resource;
182 whd_driver->bus_if->whd_bus_set_backplane_window_fptr = whd_bus_m2m_set_backplane_window;
183
184 return WHD_SUCCESS;
185 }
186
whd_bus_m2m_detach(whd_driver_t whd_driver)187 void whd_bus_m2m_detach(whd_driver_t whd_driver)
188 {
189 whd_driver->bus_if = NULL;
190 whd_driver->bus_priv = NULL;
191 }
192
whd_bus_m2m_irq_handler(void * callback_arg,cyhal_m2m_event_t events)193 void whd_bus_m2m_irq_handler(void *callback_arg, cyhal_m2m_event_t events)
194 {
195 whd_driver_t whd_driver = (whd_driver_t)callback_arg;
196
197 whd_bus_m2m_irq_enable(whd_driver, WHD_FALSE);
198 whd_thread_notify_irq(whd_driver);
199 }
200
whd_bus_m2m_init(whd_driver_t whd_driver)201 static whd_result_t whd_bus_m2m_init(whd_driver_t whd_driver)
202 {
203 whd_result_t result = WHD_SUCCESS;
204
205 #if !defined (__IAR_SYSTEMS_ICC__)
206 /* Get chip id */
207 whd_chip_set_chip_id(whd_driver, (uint16_t)REGISTER_READ(uint32_t, CHIPCOMMON_BASE_ADDRESS) );
208 #endif
209
210 result = boot_wlan(whd_driver);
211
212 if (result == WHD_SUCCESS)
213 {
214 cyhal_m2m_init(whd_driver->bus_priv->m2m_obj, M2M_DMA_RX_BUFFER_SIZE);
215 cyhal_m2m_register_callback(whd_driver->bus_priv->m2m_obj, whd_bus_m2m_irq_handler, whd_driver);
216 }
217 return result;
218 }
219
whd_bus_m2m_deinit(whd_driver_t whd_driver)220 static whd_result_t whd_bus_m2m_deinit(whd_driver_t whd_driver)
221 {
222 //PLATFORM_WLAN_POWERSAVE_RES_UP();
223
224 /* Down M2M and WLAN */
225 CHECK_RETURN(whd_disable_device_core(whd_driver, WLAN_ARM_CORE, WLAN_CORE_FLAG_CPU_HALT) );
226 cyhal_m2m_free(whd_driver->bus_priv->m2m_obj);
227
228 /* Put WLAN to reset. */
229 //host_platform_reset_wifi( WICED_TRUE );
230
231 //PLATFORM_WLAN_POWERSAVE_RES_DOWN( NULL, WICED_FALSE );
232
233 /* Force resource down even if resource up/down is unbalanced */
234 //PLATFORM_WLAN_POWERSAVE_RES_DOWN( NULL, WICED_TRUE );
235
236 CHECK_RETURN(whd_allow_wlan_bus_to_sleep(whd_driver) );
237
238 whd_bus_set_resource_download_halt(whd_driver, WHD_FALSE);
239
240 DELAYED_BUS_RELEASE_SCHEDULE(whd_driver, WHD_FALSE);
241
242 return WHD_SUCCESS;
243 }
244
whd_bus_m2m_ack_interrupt(whd_driver_t whd_driver,uint32_t intstatus)245 static whd_result_t whd_bus_m2m_ack_interrupt(whd_driver_t whd_driver, uint32_t intstatus)
246 {
247 return WHD_SUCCESS;
248 }
249
whd_bus_m2m_send_buffer(whd_driver_t whd_driver,whd_buffer_t buffer)250 static whd_result_t whd_bus_m2m_send_buffer(whd_driver_t whd_driver, whd_buffer_t buffer)
251 {
252 whd_result_t result = WHD_SUCCESS;
253
254 if (cyhal_m2m_tx_send(whd_driver->bus_priv->m2m_obj, buffer) != CY_RSLT_SUCCESS)
255 {
256 result = WHD_WLAN_ERROR;
257 }
258
259 return result;
260 }
261
whd_bus_m2m_wake_interrupt_present(whd_driver_t whd_driver)262 static whd_bool_t whd_bus_m2m_wake_interrupt_present(whd_driver_t whd_driver)
263 {
264 /* functionality is only currently needed and present on SDIO */
265 return WHD_FALSE;
266 }
267
whd_bus_m2m_packet_available_to_read(whd_driver_t whd_driver)268 static uint32_t whd_bus_m2m_packet_available_to_read(whd_driver_t whd_driver)
269 {
270 return 1;
271 }
272
whd_bus_m2m_read_frame(whd_driver_t whd_driver,whd_buffer_t * buffer)273 static whd_result_t whd_bus_m2m_read_frame(whd_driver_t whd_driver, whd_buffer_t *buffer)
274 {
275 whd_result_t result = WHD_SUCCESS;
276 cyhal_m2m_event_t m2m_event;
277 uint16_t *hwtag;
278 void *packet = NULL;
279 bool signal_txdone;
280
281 cyhal_m2m_rx_prepare(whd_driver->bus_priv->m2m_obj);
282
283 m2m_event = cyhal_m2m_intr_status(whd_driver->bus_priv->m2m_obj, &signal_txdone);
284 if (signal_txdone)
285 {
286 /* Signal WLAN core there is a TX done by setting wlancr4 SW interrupt 0 */
287 CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, GET_C_VAR(whd_driver, PMU_BASE_ADDRESS) + 0x1c,
288 (uint8_t)4, ARMCR4_SW_INT0) );
289 }
290
291 /* Handle DMA interrupts */
292 if ( (m2m_event & CYHAL_M2M_TX_CHANNEL_INTERRUPT) != 0 )
293 {
294 cyhal_m2m_tx_release(whd_driver->bus_priv->m2m_obj);
295 }
296
297 /* Handle DMA receive interrupt */
298 cyhal_m2m_rx_receive(whd_driver->bus_priv->m2m_obj, &packet, &hwtag);
299 if (packet == NULL)
300 {
301 result = WHD_NO_PACKET_TO_RECEIVE;
302 }
303 else
304 {
305 *buffer = packet;
306
307 /* move the data pointer 12 bytes(sizeof(wwd_buffer_header_t))
308 * back to the start of the pakcet
309 */
310 whd_buffer_add_remove_at_front(whd_driver, buffer, -(int)sizeof(whd_buffer_header_t) );
311 whd_sdpcm_update_credit(whd_driver, (uint8_t *)hwtag);
312 }
313
314 cyhal_m2m_rx_prepare(whd_driver->bus_priv->m2m_obj);
315
316 return result;
317 }
318
whd_bus_m2m_write_backplane_value(whd_driver_t whd_driver,uint32_t address,uint8_t register_length,uint32_t value)319 static whd_result_t whd_bus_m2m_write_backplane_value(whd_driver_t whd_driver, uint32_t address,
320 uint8_t register_length, uint32_t value)
321 {
322 #if !defined (__IAR_SYSTEMS_ICC__)
323 MEMORY_BARRIER_AGAINST_COMPILER_REORDERING();
324
325 if (register_length == 4)
326 {
327 REGISTER_WRITE_WITH_BARRIER(uint32_t, address, value);
328 }
329 else if (register_length == 2)
330 {
331 REGISTER_WRITE_WITH_BARRIER(uint16_t, address, value);
332 }
333 else if (register_length == 1)
334 {
335 REGISTER_WRITE_WITH_BARRIER(uint8_t, address, value);
336 }
337 else
338 {
339 return WHD_WLAN_ERROR;
340 }
341 #endif
342 return WHD_SUCCESS;
343 }
344
whd_bus_m2m_read_backplane_value(whd_driver_t whd_driver,uint32_t address,uint8_t register_length,uint8_t * value)345 static whd_result_t whd_bus_m2m_read_backplane_value(whd_driver_t whd_driver, uint32_t address,
346 uint8_t register_length, /*@out@*/ uint8_t *value)
347 {
348 #if !defined (__IAR_SYSTEMS_ICC__)
349 MEMORY_BARRIER_AGAINST_COMPILER_REORDERING();
350
351 if (register_length == 4)
352 {
353 *( (uint32_t *)value ) = REGISTER_READ(uint32_t, address);
354 }
355 else if (register_length == 2)
356 {
357 *( (uint16_t *)value ) = REGISTER_READ(uint16_t, address);
358 }
359 else if (register_length == 1)
360 {
361 *value = REGISTER_READ(uint8_t, address);
362 }
363 else
364 {
365 return WHD_WLAN_ERROR;
366 }
367 #endif
368 return WHD_SUCCESS;
369 }
370
whd_bus_m2m_write_register_value(whd_driver_t whd_driver,whd_bus_function_t function,uint32_t address,uint8_t value_length,uint32_t value)371 static whd_result_t whd_bus_m2m_write_register_value(whd_driver_t whd_driver, whd_bus_function_t function,
372 uint32_t address, uint8_t value_length, uint32_t value)
373 {
374 // Not used by M2M bus
375 return WHD_SUCCESS;
376 }
377
whd_bus_m2m_read_register_value(whd_driver_t whd_driver,whd_bus_function_t function,uint32_t address,uint8_t value_length,uint8_t * value)378 static whd_result_t whd_bus_m2m_read_register_value(whd_driver_t whd_driver, whd_bus_function_t function,
379 uint32_t address, uint8_t value_length, uint8_t *value)
380 {
381 // Not used by M2M bus
382 return WHD_SUCCESS;
383 }
384
whd_bus_m2m_transfer_bytes(whd_driver_t whd_driver,whd_bus_transfer_direction_t direction,whd_bus_function_t function,uint32_t address,uint16_t size,whd_transfer_bytes_packet_t * data)385 static whd_result_t whd_bus_m2m_transfer_bytes(whd_driver_t whd_driver, whd_bus_transfer_direction_t direction,
386 whd_bus_function_t function, uint32_t address, uint16_t size,
387 whd_transfer_bytes_packet_t *data)
388 {
389 if (function != BACKPLANE_FUNCTION)
390 {
391 return WHD_DOES_NOT_EXIST;
392 }
393
394 if (direction == BUS_WRITE)
395 {
396 DISABLE_COMPILER_WARNING(diag_suppress = Pa039)
397 memcpy( (uint8_t *)address, data->data, size );
398 ENABLE_COMPILER_WARNING(diag_suppress = Pa039)
399 if (address == 0)
400 {
401 uint32_t resetinst = *( (uint32_t *)data->data );
402
403 /* CR4_FF_ROM_SHADOW_INDEX_REGISTER */
404 CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, GET_C_VAR(whd_driver, PMU_BASE_ADDRESS) + 0x080,
405 (uint8_t)1, 0) );
406
407 /* CR4_FF_ROM_SHADOW_DATA_REGISTER */
408 CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, GET_C_VAR(whd_driver, PMU_BASE_ADDRESS) + 0x084,
409 (uint8_t)4, resetinst) );
410 }
411 }
412 else
413 {
414 DISABLE_COMPILER_WARNING(diag_suppress = Pa039)
415 memcpy(data->data, (uint8_t *)address, size);
416 ENABLE_COMPILER_WARNING(diag_suppress = Pa039)
417 }
418
419 return WHD_SUCCESS;
420 }
421
whd_bus_m2m_poke_wlan(whd_driver_t whd_driver)422 static whd_result_t whd_bus_m2m_poke_wlan(whd_driver_t whd_driver)
423 {
424 // Not used by M2M bus
425 return WHD_SUCCESS;
426 }
427
whd_bus_m2m_wakeup(whd_driver_t whd_driver)428 static whd_result_t whd_bus_m2m_wakeup(whd_driver_t whd_driver)
429 {
430 WPRINT_WHD_INFO( ("bus_m2m_wakeup\n") );
431 return WHD_SUCCESS;
432 }
433
whd_bus_m2m_sleep(whd_driver_t whd_driver)434 static whd_result_t whd_bus_m2m_sleep(whd_driver_t whd_driver)
435 {
436 WPRINT_WHD_INFO( ("bus_m2m_sleep\n") );
437 return WHD_SUCCESS;
438 }
439
whd_bus_m2m_backplane_read_padd_size(whd_driver_t whd_driver)440 static uint8_t whd_bus_m2m_backplane_read_padd_size(whd_driver_t whd_driver)
441 {
442 return WHD_BUS_M2M_BACKPLANE_READ_PADD_SIZE;
443 }
444
whd_bus_m2m_wait_for_wlan_event(whd_driver_t whd_driver,cy_semaphore_t * transceive_semaphore)445 static whd_result_t whd_bus_m2m_wait_for_wlan_event(whd_driver_t whd_driver, cy_semaphore_t *transceive_semaphore)
446 {
447 whd_result_t result = WHD_SUCCESS;
448 uint32_t timeout_ms;
449
450 timeout_ms = CY_RTOS_NEVER_TIMEOUT;
451
452 whd_bus_m2m_irq_enable(whd_driver, WHD_TRUE);
453 result = cy_rtos_get_semaphore(transceive_semaphore, timeout_ms, WHD_FALSE);
454
455 return result;
456 }
457
whd_bus_m2m_use_status_report_scheme(whd_driver_t whd_driver)458 static whd_bool_t whd_bus_m2m_use_status_report_scheme(whd_driver_t whd_driver)
459 {
460 /* !M2M_RX_POLL_MODE */
461 return WHD_FALSE;
462 }
463
whd_bus_m2m_get_max_transfer_size(whd_driver_t whd_driver)464 static uint32_t whd_bus_m2m_get_max_transfer_size(whd_driver_t whd_driver)
465 {
466 return WHD_BUS_M2M_MAX_BACKPLANE_TRANSFER_SIZE;
467 }
468
whd_bus_m2m_init_stats(whd_driver_t whd_driver)469 static void whd_bus_m2m_init_stats(whd_driver_t whd_driver)
470 {
471 /* To be implemented */
472 }
473
whd_bus_m2m_print_stats(whd_driver_t whd_driver,whd_bool_t reset_after_print)474 static whd_result_t whd_bus_m2m_print_stats(whd_driver_t whd_driver, whd_bool_t reset_after_print)
475 {
476 /* To be implemented */
477 UNUSED_VARIABLE(reset_after_print);
478 WPRINT_MACRO( ("Bus stats not available\n") );
479 return WHD_SUCCESS;
480 }
481
whd_bus_m2m_reinit_stats(whd_driver_t whd_driver,whd_bool_t wake_from_firmware)482 static whd_result_t whd_bus_m2m_reinit_stats(whd_driver_t whd_driver, whd_bool_t wake_from_firmware)
483 {
484 UNUSED_PARAMETER(wake_from_firmware);
485 /* functionality is only currently needed and present on SDIO */
486 return WHD_UNSUPPORTED;
487 }
488
whd_bus_m2m_irq_register(whd_driver_t whd_driver)489 static whd_result_t whd_bus_m2m_irq_register(whd_driver_t whd_driver)
490 {
491 return WHD_TRUE;
492 }
493
whd_bus_m2m_irq_enable(whd_driver_t whd_driver,whd_bool_t enable)494 static whd_result_t whd_bus_m2m_irq_enable(whd_driver_t whd_driver, whd_bool_t enable)
495 {
496 if (enable)
497 {
498 WPRINT_WHD_INFO( ("M2M interrupt enable\n") );
499 _cyhal_system_m2m_enable_irq();
500 _cyhal_system_sw0_enable_irq();
501 }
502 else
503 {
504 WPRINT_WHD_INFO( ("M2M interrupt disable\n") );
505 _cyhal_system_m2m_disable_irq();
506 _cyhal_system_sw0_disable_irq();
507 }
508 return WHD_TRUE;
509 }
510
m2m_bus_write_wifi_firmware_image(whd_driver_t whd_driver)511 whd_result_t m2m_bus_write_wifi_firmware_image(whd_driver_t whd_driver)
512 {
513 /* Halt ARM and remove from reset */
514 WPRINT_WHD_INFO( ("Reset wlan core..\n") );
515 VERIFY_RESULT(whd_reset_device_core(whd_driver, WLAN_ARM_CORE, WLAN_CORE_FLAG_CPU_HALT) );
516
517 return whd_bus_write_wifi_firmware_image(whd_driver);
518 }
519
boot_wlan(whd_driver_t whd_driver)520 static whd_result_t boot_wlan(whd_driver_t whd_driver)
521 {
522 whd_result_t result = WHD_SUCCESS;
523
524 /* Load wlan firmware from sflash */
525 result = m2m_bus_write_wifi_firmware_image(whd_driver);
526 if ( (result == WHD_UNFINISHED) || (result != WHD_SUCCESS) )
527 {
528 /* for user abort, then put wifi module into known good state */
529 return result;
530 }
531
532 VERIFY_RESULT(whd_bus_m2m_write_wifi_nvram_image(whd_driver) );
533
534 /* Release ARM core */
535 WPRINT_WHD_INFO( ("Release WLAN core..\n") );
536 VERIFY_RESULT(whd_wlan_armcore_run(whd_driver, WLAN_ARM_CORE, WLAN_CORE_FLAG_NONE) );
537
538 #if (PLATFORM_BACKPLANE_ON_CPU_CLOCK_ENABLE == 0)
539 /*
540 * Wifi firmware initialization will change some BBPLL settings. When backplane clock
541 * source is not on CPU clock, accessing backplane during that period might wedge the
542 * ACPU. Running a delay loop in cache can avoid the wedge. At least 3ms is required
543 * to avoid the problem.
544 */
545 cy_rtos_delay_milliseconds(10);
546 #endif /* PLATFORM_BACKPLANE_ON_CPU_CLOCK_ENABLE == 0 */
547
548 return result;
549 }
550
whd_bus_m2m_download_resource(whd_driver_t whd_driver,whd_resource_type_t resource,whd_bool_t direct_resource,uint32_t address,uint32_t image_size)551 static whd_result_t whd_bus_m2m_download_resource(whd_driver_t whd_driver, whd_resource_type_t resource,
552 whd_bool_t direct_resource, uint32_t address,
553 uint32_t image_size)
554 {
555 whd_result_t result = WHD_SUCCESS;
556 uint32_t size_out;
557 uint32_t reset_instr = 0;
558
559 CHECK_RETURN(whd_resource_read(whd_driver, resource, 0,
560 GET_C_VAR(whd_driver, CHIP_RAM_SIZE), &size_out,
561 (uint8_t *)(address) ) );
562
563 CHECK_RETURN(whd_resource_read(whd_driver, resource, 0, 4, &size_out, &reset_instr) );
564
565 /* CR4_FF_ROM_SHADOW_INDEX_REGISTER */
566 CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, GET_C_VAR(whd_driver, PMU_BASE_ADDRESS) + 0x080,
567 (uint8_t)1, 0) );
568
569 /* CR4_FF_ROM_SHADOW_DATA_REGISTER */
570 CHECK_RETURN(whd_bus_write_backplane_value(whd_driver, GET_C_VAR(whd_driver, PMU_BASE_ADDRESS) + 0x084,
571 (uint8_t)4, reset_instr) );
572
573 return result;
574 }
575
whd_bus_m2m_write_wifi_nvram_image(whd_driver_t whd_driver)576 static whd_result_t whd_bus_m2m_write_wifi_nvram_image(whd_driver_t whd_driver)
577 {
578 uint32_t nvram_size;
579 uint32_t nvram_destination_address;
580 uint32_t nvram_size_in_words;
581 uint32_t size_out;
582 uint32_t image_size;
583
584 /* Get the size of the variable image */
585 CHECK_RETURN(whd_resource_size(whd_driver, WHD_RESOURCE_WLAN_NVRAM, &image_size) );
586
587 /* Round up the size of the image */
588 nvram_size = ROUND_UP(image_size, 4);
589
590 /* Put the NVRAM image at the end of RAM leaving the last 4 bytes for the size */
591 nvram_destination_address = (GET_C_VAR(whd_driver, CHIP_RAM_SIZE) - 4) - nvram_size;
592 nvram_destination_address += GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS);
593
594 /* Write NVRAM image into WLAN RAM */
595 CHECK_RETURN(whd_resource_read(whd_driver, WHD_RESOURCE_WLAN_NVRAM, 0,
596 image_size, &size_out, (uint8_t *)nvram_destination_address) );
597
598
599 /* Calculate the NVRAM image size in words (multiples of 4 bytes) and its bitwise inverse */
600 nvram_size_in_words = nvram_size / 4;
601 nvram_size_in_words = (~nvram_size_in_words << 16) | (nvram_size_in_words & 0x0000FFFF);
602
603 memcpy( (uint8_t *)(GET_C_VAR(whd_driver, ATCM_RAM_BASE_ADDRESS) + GET_C_VAR(whd_driver, CHIP_RAM_SIZE) - 4),
604 (uint8_t *)&nvram_size_in_words, 4 );
605
606 return WHD_SUCCESS;
607 }
608
whd_bus_m2m_set_backplane_window(whd_driver_t whd_driver,uint32_t addr,uint32_t * cur_addr)609 whd_result_t whd_bus_m2m_set_backplane_window(whd_driver_t whd_driver, uint32_t addr, uint32_t *cur_addr)
610 {
611 return WHD_UNSUPPORTED;
612 }
613
whd_ensure_wlan_is_up(whd_driver_t whd_driver)614 whd_bool_t whd_ensure_wlan_is_up(whd_driver_t whd_driver)
615 {
616 if ( (whd_driver != NULL) && (whd_driver->internal_info.whd_wlan_status.state == WLAN_UP) )
617 return WHD_TRUE;
618 else
619 return WHD_FALSE;
620 }
621
622 #endif /* (CYBSP_WIFI_INTERFACE_TYPE == CYBSP_M2M_INTERFACE) */
623
624