1 /*
2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include <linux/platform_device.h>
21 #include <linux/err.h>
22 #include <linux/list.h>
23 #include <linux/slab.h>
24 #include "osif_psoc_sync.h"
25
26 #include "pld_pcie_fw_sim.h"
27
28 #if defined(CONFIG_PLD_PCIE_FW_SIM) || defined(CONFIG_PLD_IPCIE_FW_SIM)
29
30 #ifdef QCA_WIFI_3_0_ADRASTEA
31 #define CE_COUNT_MAX 12
32 #else
33 #define CE_COUNT_MAX 8
34 #endif
35
36 #endif
37
38 #ifdef CONFIG_PLD_IPCIE_FW_SIM
39 /**
40 * pld_pcie_fw_sim_probe() - Probe function for PCIE platform driver
41 * @pdev: PCIE device
42 * @id: PCIE device ID table
43 *
44 * The probe function will be called when PCIE device provided
45 * in the ID table is detected.
46 *
47 * Return: int
48 */
pld_pcie_fw_sim_probe(struct pci_dev * pdev,const struct pci_device_id * id)49 static int pld_pcie_fw_sim_probe(struct pci_dev *pdev,
50 const struct pci_device_id *id)
51 {
52 struct pld_context *pld_context;
53 int ret = 0;
54
55 pld_context = pld_get_global_context();
56 if (!pld_context) {
57 ret = -ENODEV;
58 goto out;
59 }
60
61 ret = pld_add_dev(pld_context, &pdev->dev, NULL,
62 PLD_BUS_TYPE_IPCI_FW_SIM);
63 if (ret)
64 goto out;
65
66 return pld_context->ops->probe(&pdev->dev,
67 PLD_BUS_TYPE_IPCI_FW_SIM, NULL, NULL);
68
69 out:
70 return ret;
71 }
72
73 /**
74 * pld_pcie_fw_sim_remove() - Remove function for PCIE device
75 * @pdev: PCIE device
76 *
77 * The remove function will be called when PCIE device is disconnected
78 *
79 * Return: void
80 */
pld_pcie_fw_sim_remove(struct pci_dev * pdev)81 static void pld_pcie_fw_sim_remove(struct pci_dev *pdev)
82 {
83 struct pld_context *pld_context;
84 int errno;
85 struct osif_psoc_sync *psoc_sync;
86
87 errno = osif_psoc_sync_trans_start_wait(&pdev->dev, &psoc_sync);
88 if (errno)
89 return;
90
91 osif_psoc_sync_unregister(&pdev->dev);
92 osif_psoc_sync_wait_for_ops(psoc_sync);
93
94 pld_context = pld_get_global_context();
95
96 if (!pld_context)
97 goto out;
98
99 pld_context->ops->remove(&pdev->dev, PLD_BUS_TYPE_IPCI_FW_SIM);
100
101 pld_del_dev(pld_context, &pdev->dev);
102
103 out:
104 osif_psoc_sync_trans_stop(psoc_sync);
105 osif_psoc_sync_destroy(psoc_sync);
106 }
107
108 /**
109 * pld_pcie_fw_sim_idle_restart_cb() - Perform idle restart
110 * @pdev: PCIE device
111 * @id: PCIE device ID
112 *
113 * This function will be called if there is an idle restart request
114 *
115 * Return: int
116 */
pld_pcie_fw_sim_idle_restart_cb(struct pci_dev * pdev,const struct pci_device_id * id)117 static int pld_pcie_fw_sim_idle_restart_cb(struct pci_dev *pdev,
118 const struct pci_device_id *id)
119 {
120 struct pld_context *pld_context;
121
122 pld_context = pld_get_global_context();
123 if (pld_context->ops->idle_restart)
124 return pld_context->ops->idle_restart(&pdev->dev,
125 PLD_BUS_TYPE_IPCI_FW_SIM);
126
127 return -ENODEV;
128 }
129
130 /**
131 * pld_pcie_fw_sim_idle_shutdown_cb() - Perform idle shutdown
132 * @pdev: PCIE device
133 *
134 * This function will be called if there is an idle shutdown request
135 *
136 * Return: int
137 */
pld_pcie_fw_sim_idle_shutdown_cb(struct pci_dev * pdev)138 static int pld_pcie_fw_sim_idle_shutdown_cb(struct pci_dev *pdev)
139 {
140 struct pld_context *pld_context;
141
142 pld_context = pld_get_global_context();
143 if (pld_context->ops->shutdown)
144 return pld_context->ops->idle_shutdown(&pdev->dev,
145 PLD_BUS_TYPE_IPCI_FW_SIM);
146
147 return -ENODEV;
148 }
149
150 /**
151 * pld_pcie_fw_sim_reinit() - SSR re-initialize function for PCIE device
152 * @pdev: PCIE device
153 * @id: PCIE device ID
154 *
155 * During subsystem restart(SSR), this function will be called to
156 * re-initialize pcie device.
157 *
158 * Return: int
159 */
pld_pcie_fw_sim_reinit(struct pci_dev * pdev,const struct pci_device_id * id)160 static int pld_pcie_fw_sim_reinit(struct pci_dev *pdev,
161 const struct pci_device_id *id)
162 {
163 struct pld_context *pld_context;
164
165 pld_context = pld_get_global_context();
166 if (pld_context->ops->reinit)
167 return pld_context->ops->reinit(&pdev->dev,
168 PLD_BUS_TYPE_IPCI_FW_SIM, NULL, NULL);
169
170 return -ENODEV;
171 }
172
173 /**
174 * pld_pcie_fw_sim_shutdown() - SSR shutdown function for PCIE device
175 * @pdev: PCIE device
176 *
177 * During SSR, this function will be called to shutdown PCIE device.
178 *
179 * Return: void
180 */
pld_pcie_fw_sim_shutdown(struct pci_dev * pdev)181 static void pld_pcie_fw_sim_shutdown(struct pci_dev *pdev)
182 {
183 struct pld_context *pld_context;
184
185 pld_context = pld_get_global_context();
186 if (pld_context->ops->shutdown)
187 pld_context->ops->shutdown(&pdev->dev,
188 PLD_BUS_TYPE_IPCI_FW_SIM);
189 }
190
191 /**
192 * pld_pcie_fw_sim_crash_shutdown() - Crash shutdown function for PCIE device
193 * @pdev: PCIE device
194 *
195 * This function will be called when a crash is detected, it will shutdown
196 * the PCIE device.
197 *
198 * Return: void
199 */
pld_pcie_fw_sim_crash_shutdown(struct pci_dev * pdev)200 static void pld_pcie_fw_sim_crash_shutdown(struct pci_dev *pdev)
201 {
202 struct pld_context *pld_context;
203
204 pld_context = pld_get_global_context();
205 if (pld_context->ops->crash_shutdown)
206 pld_context->ops->crash_shutdown(&pdev->dev,
207 PLD_BUS_TYPE_IPCI_FW_SIM);
208 }
209
210 /**
211 * pld_pcie_fw_sim_notify_handler() - Modem state notification callback function
212 * @pdev: PCIE device
213 * @state: modem power state
214 *
215 * This function will be called when there's a modem power state change.
216 *
217 * Return: void
218 */
pld_pcie_fw_sim_notify_handler(struct pci_dev * pdev,int state)219 static void pld_pcie_fw_sim_notify_handler(struct pci_dev *pdev, int state)
220 {
221 struct pld_context *pld_context;
222
223 pld_context = pld_get_global_context();
224 if (pld_context->ops->modem_status)
225 pld_context->ops->modem_status(&pdev->dev,
226 PLD_BUS_TYPE_IPCI_FW_SIM, state);
227 }
228
229 /**
230 * pld_pcie_fw_sim_uevent() - update wlan driver status callback function
231 * @pdev: PCIE device
232 * @status: driver uevent status
233 *
234 * This function will be called when platform driver wants to update wlan
235 * driver's status.
236 *
237 * Return: void
238 */
pld_pcie_fw_sim_uevent(struct pci_dev * pdev,uint32_t status)239 static void pld_pcie_fw_sim_uevent(struct pci_dev *pdev, uint32_t status)
240 {
241 struct pld_context *pld_context;
242 struct pld_uevent_data data = {0};
243
244 pld_context = pld_get_global_context();
245 if (!pld_context)
246 return;
247
248 switch (status) {
249 case CNSS_RECOVERY:
250 data.uevent = PLD_FW_RECOVERY_START;
251 break;
252 case CNSS_FW_DOWN:
253 data.uevent = PLD_FW_DOWN;
254 break;
255 default:
256 goto out;
257 }
258
259 if (pld_context->ops->uevent)
260 pld_context->ops->uevent(&pdev->dev, &data);
261
262 out:
263 return;
264 }
265
266 /**
267 * pld_pcie_fw_sim_set_thermal_state: Set thermal state for thermal mitigation
268 * @dev: device
269 * @thermal_state: Thermal state set by thermal subsystem
270 * @mon_id: Thermal cooling device ID
271 *
272 * This function will be called when thermal subsystem notifies platform
273 * driver about change in thermal state.
274 *
275 * Return: 0 for success
276 * Non zero failure code for errors
277 */
pld_pcie_fw_sim_set_thermal_state(struct device * dev,unsigned long thermal_state,int mon_id)278 static int pld_pcie_fw_sim_set_thermal_state(struct device *dev,
279 unsigned long thermal_state,
280 int mon_id)
281 {
282 struct pld_context *pld_context;
283
284 pld_context = pld_get_global_context();
285 if (!pld_context)
286 return -EINVAL;
287
288 if (pld_context->ops->set_curr_therm_cdev_state)
289 return pld_context->ops->set_curr_therm_cdev_state(dev,
290 thermal_state,
291 mon_id);
292
293 return -ENOTSUPP;
294 }
295
296 static struct pci_device_id pld_pcie_fw_sim_id_table[] = {
297 { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID },
298 { 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID },
299 { 0x168c, 0x0041, PCI_ANY_ID, PCI_ANY_ID },
300 { 0x168c, 0xabcd, PCI_ANY_ID, PCI_ANY_ID },
301 { 0x168c, 0x7021, PCI_ANY_ID, PCI_ANY_ID },
302 { 0 }
303 };
304
305 #ifdef MULTI_IF_NAME
306 #define PLD_PCIE_FW_SIM_OPS_NAME "pld_ipcie_fw_sim_" MULTI_IF_NAME
307 #else
308 #define PLD_PCIE_FW_SIM_OPS_NAME "pld_ipcie_fw_sim"
309 #endif
310
311 #endif
312
313 #ifdef CONFIG_PLD_PCIE_FW_SIM
314 /**
315 * pld_pcie_fw_sim_probe() - Probe function for PCIE platform driver
316 * @pdev: PCIE device
317 * @id: PCIE device ID table
318 *
319 * The probe function will be called when PCIE device provided
320 * in the ID table is detected.
321 *
322 * Return: int
323 */
pld_pcie_fw_sim_probe(struct pci_dev * pdev,const struct pci_device_id * id)324 static int pld_pcie_fw_sim_probe(struct pci_dev *pdev,
325 const struct pci_device_id *id)
326 {
327 struct pld_context *pld_context;
328 int ret = 0;
329
330 pld_context = pld_get_global_context();
331 if (!pld_context) {
332 ret = -ENODEV;
333 goto out;
334 }
335
336 ret = pld_add_dev(pld_context, &pdev->dev, NULL,
337 PLD_BUS_TYPE_PCIE_FW_SIM);
338 if (ret)
339 goto out;
340
341 return pld_context->ops->probe(&pdev->dev,
342 PLD_BUS_TYPE_PCIE_FW_SIM, pdev, (void *)id);
343
344 out:
345 return ret;
346 }
347
348 /**
349 * pld_pcie_fw_sim_remove() - Remove function for PCIE device
350 * @pdev: PCIE device
351 *
352 * The remove function will be called when PCIE device is disconnected
353 *
354 * Return: void
355 */
pld_pcie_fw_sim_remove(struct pci_dev * pdev)356 static void pld_pcie_fw_sim_remove(struct pci_dev *pdev)
357 {
358 struct pld_context *pld_context;
359 int errno;
360 struct osif_psoc_sync *psoc_sync;
361
362 errno = osif_psoc_sync_trans_start_wait(&pdev->dev, &psoc_sync);
363 if (errno)
364 return;
365
366 osif_psoc_sync_unregister(&pdev->dev);
367 osif_psoc_sync_wait_for_ops(psoc_sync);
368
369 pld_context = pld_get_global_context();
370
371 if (!pld_context)
372 goto out;
373
374 pld_context->ops->remove(&pdev->dev, PLD_BUS_TYPE_PCIE_FW_SIM);
375
376 pld_del_dev(pld_context, &pdev->dev);
377
378 out:
379 osif_psoc_sync_trans_stop(psoc_sync);
380 osif_psoc_sync_destroy(psoc_sync);
381 }
382
383 /**
384 * pld_pcie_fw_sim_idle_restart_cb() - Perform idle restart
385 * @pdev: PCIE device
386 * @id: PCIE device ID
387 *
388 * This function will be called if there is an idle restart request
389 *
390 * Return: int
391 */
pld_pcie_fw_sim_idle_restart_cb(struct pci_dev * pdev,const struct pci_device_id * id)392 static int pld_pcie_fw_sim_idle_restart_cb(struct pci_dev *pdev,
393 const struct pci_device_id *id)
394 {
395 struct pld_context *pld_context;
396
397 pld_context = pld_get_global_context();
398 if (pld_context->ops->idle_restart)
399 return pld_context->ops->idle_restart(&pdev->dev,
400 PLD_BUS_TYPE_PCIE_FW_SIM);
401
402 return -ENODEV;
403 }
404
405 /**
406 * pld_pcie_fw_sim_idle_shutdown_cb() - Perform idle shutdown
407 * @pdev: PCIE device
408 *
409 * This function will be called if there is an idle shutdown request
410 *
411 * Return: int
412 */
pld_pcie_fw_sim_idle_shutdown_cb(struct pci_dev * pdev)413 static int pld_pcie_fw_sim_idle_shutdown_cb(struct pci_dev *pdev)
414 {
415 struct pld_context *pld_context;
416
417 pld_context = pld_get_global_context();
418 if (pld_context->ops->shutdown)
419 return pld_context->ops->idle_shutdown(&pdev->dev,
420 PLD_BUS_TYPE_PCIE_FW_SIM);
421
422 return -ENODEV;
423 }
424
425 /**
426 * pld_pcie_fw_sim_reinit() - SSR re-initialize function for PCIE device
427 * @pdev: PCIE device
428 * @id: PCIE device ID
429 *
430 * During subsystem restart(SSR), this function will be called to
431 * re-initialize pcie device.
432 *
433 * Return: int
434 */
pld_pcie_fw_sim_reinit(struct pci_dev * pdev,const struct pci_device_id * id)435 static int pld_pcie_fw_sim_reinit(struct pci_dev *pdev,
436 const struct pci_device_id *id)
437 {
438 struct pld_context *pld_context;
439
440 pld_context = pld_get_global_context();
441 if (pld_context->ops->reinit)
442 return pld_context->ops->reinit(&pdev->dev,
443 PLD_BUS_TYPE_PCIE_FW_SIM, pdev, (void *)id);
444
445 return -ENODEV;
446 }
447
448 /**
449 * pld_pcie_fw_sim_shutdown() - SSR shutdown function for PCIE device
450 * @pdev: PCIE device
451 *
452 * During SSR, this function will be called to shutdown PCIE device.
453 *
454 * Return: void
455 */
pld_pcie_fw_sim_shutdown(struct pci_dev * pdev)456 static void pld_pcie_fw_sim_shutdown(struct pci_dev *pdev)
457 {
458 struct pld_context *pld_context;
459
460 pld_context = pld_get_global_context();
461 if (pld_context->ops->shutdown)
462 pld_context->ops->shutdown(&pdev->dev,
463 PLD_BUS_TYPE_PCIE_FW_SIM);
464 }
465
466 /**
467 * pld_pcie_fw_sim_crash_shutdown() - Crash shutdown function for PCIE device
468 * @pdev: PCIE device
469 *
470 * This function will be called when a crash is detected, it will shutdown
471 * the PCIE device.
472 *
473 * Return: void
474 */
pld_pcie_fw_sim_crash_shutdown(struct pci_dev * pdev)475 static void pld_pcie_fw_sim_crash_shutdown(struct pci_dev *pdev)
476 {
477 struct pld_context *pld_context;
478
479 pld_context = pld_get_global_context();
480 if (pld_context->ops->crash_shutdown)
481 pld_context->ops->crash_shutdown(&pdev->dev,
482 PLD_BUS_TYPE_PCIE_FW_SIM);
483 }
484
485 /**
486 * pld_pcie_fw_sim_notify_handler() - Modem state notification callback function
487 * @pdev: PCIE device
488 * @state: modem power state
489 *
490 * This function will be called when there's a modem power state change.
491 *
492 * Return: void
493 */
pld_pcie_fw_sim_notify_handler(struct pci_dev * pdev,int state)494 static void pld_pcie_fw_sim_notify_handler(struct pci_dev *pdev, int state)
495 {
496 struct pld_context *pld_context;
497
498 pld_context = pld_get_global_context();
499 if (pld_context->ops->modem_status)
500 pld_context->ops->modem_status(&pdev->dev,
501 PLD_BUS_TYPE_PCIE_FW_SIM, state);
502 }
503
504 /**
505 * pld_pcie_fw_sim_uevent() - update wlan driver status callback function
506 * @pdev: PCIE device
507 * @status: driver uevent status
508 *
509 * This function will be called when platform driver wants to update wlan
510 * driver's status.
511 *
512 * Return: void
513 */
pld_pcie_fw_sim_uevent(struct pci_dev * pdev,uint32_t status)514 static void pld_pcie_fw_sim_uevent(struct pci_dev *pdev, uint32_t status)
515 {
516 struct pld_context *pld_context;
517 struct pld_uevent_data data = {0};
518
519 pld_context = pld_get_global_context();
520 if (!pld_context)
521 return;
522
523 switch (status) {
524 case CNSS_RECOVERY:
525 data.uevent = PLD_FW_RECOVERY_START;
526 break;
527 case CNSS_FW_DOWN:
528 data.uevent = PLD_FW_DOWN;
529 break;
530 default:
531 goto out;
532 }
533
534 if (pld_context->ops->uevent)
535 pld_context->ops->uevent(&pdev->dev, &data);
536
537 out:
538 return;
539 }
540
541 /**
542 * pld_pcie_fw_sim_set_thermal_state: Set thermal state for thermal mitigation
543 * @dev: device
544 * @thermal_state: Thermal state set by thermal subsystem
545 * @mon_id: Thermal cooling device ID
546 *
547 * This function will be called when thermal subsystem notifies platform
548 * driver about change in thermal state.
549 *
550 * Return: 0 for success
551 * Non zero failure code for errors
552 */
pld_pcie_fw_sim_set_thermal_state(struct device * dev,unsigned long thermal_state,int mon_id)553 static int pld_pcie_fw_sim_set_thermal_state(struct device *dev,
554 unsigned long thermal_state,
555 int mon_id)
556 {
557 struct pld_context *pld_context;
558
559 pld_context = pld_get_global_context();
560 if (!pld_context)
561 return -EINVAL;
562
563 if (pld_context->ops->set_curr_therm_cdev_state)
564 return pld_context->ops->set_curr_therm_cdev_state(dev,
565 thermal_state,
566 mon_id);
567
568 return -ENOTSUPP;
569 }
570
571 static struct pci_device_id pld_pcie_fw_sim_id_table[] = {
572 { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID },
573 { 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID },
574 { 0x168c, 0x0041, PCI_ANY_ID, PCI_ANY_ID },
575 { 0x168c, 0xabcd, PCI_ANY_ID, PCI_ANY_ID },
576 { 0x168c, 0x7021, PCI_ANY_ID, PCI_ANY_ID },
577 { 0 }
578 };
579
580 #ifdef MULTI_IF_NAME
581 #define PLD_PCIE_FW_SIM_OPS_NAME "pld_pcie_fw_sim_" MULTI_IF_NAME
582 #else
583 #define PLD_PCIE_FW_SIM_OPS_NAME "pld_pcie_fw_sim"
584 #endif
585
586 #endif
587
588 #if defined(CONFIG_PLD_PCIE_FW_SIM) || defined(CONFIG_PLD_IPCIE_FW_SIM)
589 struct cnss_wlan_driver pld_pcie_fw_sim_ops = {
590 .name = PLD_PCIE_FW_SIM_OPS_NAME,
591 .id_table = pld_pcie_fw_sim_id_table,
592 .probe = pld_pcie_fw_sim_probe,
593 .remove = pld_pcie_fw_sim_remove,
594 .idle_restart = pld_pcie_fw_sim_idle_restart_cb,
595 .idle_shutdown = pld_pcie_fw_sim_idle_shutdown_cb,
596 .reinit = pld_pcie_fw_sim_reinit,
597 .shutdown = pld_pcie_fw_sim_shutdown,
598 .crash_shutdown = pld_pcie_fw_sim_crash_shutdown,
599 .modem_status = pld_pcie_fw_sim_notify_handler,
600 .update_status = pld_pcie_fw_sim_uevent,
601 .set_therm_cdev_state = pld_pcie_fw_sim_set_thermal_state,
602 };
603
604 /**
605 * pld_pcie_fw_sim_register_driver() - Register PCIE device callback functions
606 *
607 * Return: int
608 */
pld_pcie_fw_sim_register_driver(void)609 int pld_pcie_fw_sim_register_driver(void)
610 {
611 return cnss_fw_sim_wlan_register_driver(&pld_pcie_fw_sim_ops);
612 }
613
614 /**
615 * pld_pcie_fw_sim_unregister_driver() - Unregister PCIE device callback
616 * functions
617 *
618 * Return: void
619 */
pld_pcie_fw_sim_unregister_driver(void)620 void pld_pcie_fw_sim_unregister_driver(void)
621 {
622 cnss_fw_sim_wlan_unregister_driver(&pld_pcie_fw_sim_ops);
623 }
624
625 #ifdef CONFIG_SHADOW_V3
626 static inline void
pld_pcie_fw_sim_populate_shadow_v3_cfg(struct cnss_wlan_enable_cfg * cfg,struct pld_wlan_enable_cfg * config)627 pld_pcie_fw_sim_populate_shadow_v3_cfg(struct cnss_wlan_enable_cfg *cfg,
628 struct pld_wlan_enable_cfg *config)
629 {
630 cfg->num_shadow_reg_v3_cfg = config->num_shadow_reg_v3_cfg;
631 cfg->shadow_reg_v3_cfg = (struct cnss_shadow_reg_v3_cfg *)
632 config->shadow_reg_v3_cfg;
633 }
634 #else
635 static inline void
pld_pcie_fw_sim_populate_shadow_v3_cfg(struct cnss_wlan_enable_cfg * cfg,struct pld_wlan_enable_cfg * config)636 pld_pcie_fw_sim_populate_shadow_v3_cfg(struct cnss_wlan_enable_cfg *cfg,
637 struct pld_wlan_enable_cfg *config)
638 {
639 }
640 #endif
641
642 /**
643 * pld_pcie_fw_sim_wlan_enable() - Enable WLAN
644 * @dev: device
645 * @config: WLAN configuration data
646 * @mode: WLAN mode
647 * @host_version: host software version
648 *
649 * This function enables WLAN FW. It passed WLAN configuration data,
650 * WLAN mode and host software version to FW.
651 *
652 * Return: 0 for success
653 * Non zero failure code for errors
654 */
pld_pcie_fw_sim_wlan_enable(struct device * dev,struct pld_wlan_enable_cfg * config,enum pld_driver_mode mode,const char * host_version)655 int pld_pcie_fw_sim_wlan_enable(struct device *dev,
656 struct pld_wlan_enable_cfg *config,
657 enum pld_driver_mode mode,
658 const char *host_version)
659 {
660 struct cnss_wlan_enable_cfg cfg;
661 enum cnss_driver_mode cnss_mode;
662
663 cfg.num_ce_tgt_cfg = config->num_ce_tgt_cfg;
664 cfg.ce_tgt_cfg = (struct cnss_ce_tgt_pipe_cfg *)
665 config->ce_tgt_cfg;
666 cfg.num_ce_svc_pipe_cfg = config->num_ce_svc_pipe_cfg;
667 cfg.ce_svc_cfg = (struct cnss_ce_svc_pipe_cfg *)
668 config->ce_svc_cfg;
669 cfg.num_shadow_reg_cfg = config->num_shadow_reg_cfg;
670 cfg.shadow_reg_cfg = (struct cnss_shadow_reg_cfg *)
671 config->shadow_reg_cfg;
672 cfg.num_shadow_reg_v2_cfg = config->num_shadow_reg_v2_cfg;
673 cfg.shadow_reg_v2_cfg = (struct cnss_shadow_reg_v2_cfg *)
674 config->shadow_reg_v2_cfg;
675 cfg.rri_over_ddr_cfg_valid = config->rri_over_ddr_cfg_valid;
676 if (config->rri_over_ddr_cfg_valid) {
677 cfg.rri_over_ddr_cfg.base_addr_low =
678 config->rri_over_ddr_cfg.base_addr_low;
679 cfg.rri_over_ddr_cfg.base_addr_high =
680 config->rri_over_ddr_cfg.base_addr_high;
681 }
682
683 pld_pcie_fw_sim_populate_shadow_v3_cfg(&cfg, config);
684
685 switch (mode) {
686 case PLD_FTM:
687 cnss_mode = CNSS_FTM;
688 break;
689 case PLD_EPPING:
690 cnss_mode = CNSS_EPPING;
691 break;
692 default:
693 cnss_mode = CNSS_MISSION;
694 break;
695 }
696 return cnss_fw_sim_wlan_enable(dev, &cfg, cnss_mode, host_version);
697 }
698
699 /**
700 * pld_pcie_fw_sim_wlan_disable() - Disable WLAN
701 * @dev: device
702 * @mode: WLAN mode
703 *
704 * This function disables WLAN FW. It passes WLAN mode to FW.
705 *
706 * Return: 0 for success
707 * Non zero failure code for errors
708 */
pld_pcie_fw_sim_wlan_disable(struct device * dev,enum pld_driver_mode mode)709 int pld_pcie_fw_sim_wlan_disable(struct device *dev, enum pld_driver_mode mode)
710 {
711 return cnss_fw_sim_wlan_disable(dev, CNSS_OFF);
712 }
713
714 /**
715 * pld_pcie_fw_sim_get_soc_info() - Get SOC information
716 * @dev: device
717 * @info: buffer to SOC information
718 *
719 * Return SOC info to the buffer.
720 *
721 * Return: 0 for success
722 * Non zero failure code for errors
723 */
pld_pcie_fw_sim_get_soc_info(struct device * dev,struct pld_soc_info * info)724 int pld_pcie_fw_sim_get_soc_info(struct device *dev, struct pld_soc_info *info)
725 {
726 int ret = 0, i;
727 struct cnss_soc_info cnss_info = {0};
728
729 if (!info)
730 return -ENODEV;
731
732 ret = cnss_fw_sim_get_soc_info(dev, &cnss_info);
733 if (ret)
734 return ret;
735
736 info->v_addr = cnss_info.va;
737 info->p_addr = cnss_info.pa;
738 info->chip_id = cnss_info.chip_id;
739 info->chip_family = cnss_info.chip_family;
740 info->board_id = cnss_info.board_id;
741 info->soc_id = cnss_info.soc_id;
742 info->fw_version = cnss_info.fw_version;
743 strlcpy(info->fw_build_timestamp, cnss_info.fw_build_timestamp,
744 sizeof(info->fw_build_timestamp));
745 info->device_version.family_number =
746 cnss_info.device_version.family_number;
747 info->device_version.device_number =
748 cnss_info.device_version.device_number;
749 info->device_version.major_version =
750 cnss_info.device_version.major_version;
751 info->device_version.minor_version =
752 cnss_info.device_version.minor_version;
753 for (i = 0; i < PLD_MAX_DEV_MEM_NUM; i++) {
754 info->dev_mem_info[i].start = cnss_info.dev_mem_info[i].start;
755 info->dev_mem_info[i].size = cnss_info.dev_mem_info[i].size;
756 }
757
758 return 0;
759 }
760
761 /**
762 * pld_pcie_fw_sim_get_platform_cap() - Get platform capabilities
763 * @dev: device
764 * @cap: buffer to the capabilities
765 *
766 * Return capabilities to the buffer.
767 *
768 * Return: 0 for success
769 * Non zero failure code for errors
770 */
pld_pcie_fw_sim_get_platform_cap(struct device * dev,struct pld_platform_cap * cap)771 int pld_pcie_fw_sim_get_platform_cap(struct device *dev,
772 struct pld_platform_cap *cap)
773 {
774 int ret = 0;
775 struct cnss_platform_cap cnss_cap;
776
777 if (!cap)
778 return -ENODEV;
779
780 ret = cnss_fw_sim_get_platform_cap(dev, &cnss_cap);
781 if (ret)
782 return ret;
783
784 memcpy(cap, &cnss_cap, sizeof(*cap));
785 return 0;
786 }
787
788 /*
789 * pld_pcie_get_irq() - Get irq by ce_id
790 * @dev: device
791 * @ce_id: CE id for which irq is requested
792 *
793 * Return irq number.
794 *
795 * Return: irq number for success
796 * Non zero failure code for errors
797 */
pld_pcie_fw_sim_get_irq(struct device * dev,int ce_id)798 int pld_pcie_fw_sim_get_irq(struct device *dev, int ce_id)
799 {
800 uint32_t msi_data_start;
801 uint32_t msi_data_count;
802 uint32_t msi_irq_start;
803 uint32_t msi_data;
804 int ret;
805
806 ret = cnss_fw_sim_get_user_msi_assignment(dev, "CE",
807 &msi_data_count,
808 &msi_data_start,
809 &msi_irq_start);
810 if (ret)
811 return ret;
812
813 msi_data = (ce_id % msi_data_count) + msi_irq_start;
814 ret = cnss_fw_sim_get_msi_irq(dev, msi_data);
815
816 return ret;
817 }
818 #endif
819