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