xref: /wlan-dirver/qcacld-3.0/core/pld/src/pld_pcie.c (revision a24510696edc222f9e9b89d388912a346710831d)
1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 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/pci.h>
23 #include <linux/list.h>
24 #include <linux/slab.h>
25 
26 #ifdef CONFIG_PLD_PCIE_CNSS
27 #ifdef CONFIG_CNSS_OUT_OF_TREE
28 #include "cnss2.h"
29 #else
30 #include <net/cnss2.h>
31 #endif
32 #endif
33 
34 #include "pld_internal.h"
35 #include "pld_pcie.h"
36 #include "osif_psoc_sync.h"
37 
38 #ifdef CONFIG_PCI
39 
40 #ifdef QCA_WIFI_3_0_ADRASTEA
41 #define CE_COUNT_MAX 12
42 #else
43 #define CE_COUNT_MAX 8
44 #endif
45 
46 #if defined(CONFIG_PLD_PCIE_CNSS) && \
47 	(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
48 #ifndef CHIP_VERSION
49 #define CHIP_VERSION CNSS_CHIP_VER_ANY
50 #endif
51 #endif
52 
53 /**
54  * pld_pcie_probe() - Probe function for PCIE platform driver
55  * @pdev: PCIE device
56  * @id: PCIE device ID table
57  *
58  * The probe function will be called when PCIE device provided
59  * in the ID table is detected.
60  *
61  * Return: int
62  */
63 static int pld_pcie_probe(struct pci_dev *pdev,
64 			  const struct pci_device_id *id)
65 {
66 	struct pld_context *pld_context;
67 	int ret = 0;
68 
69 	pld_context = pld_get_global_context();
70 	if (!pld_context) {
71 		ret = -ENODEV;
72 		goto out;
73 	}
74 
75 	ret = pld_add_dev(pld_context, &pdev->dev, NULL, PLD_BUS_TYPE_PCIE);
76 	if (ret)
77 		goto out;
78 
79 	return pld_context->ops->probe(&pdev->dev,
80 		       PLD_BUS_TYPE_PCIE, pdev, (void *)id);
81 
82 out:
83 	return ret;
84 }
85 
86 
87 /**
88  * pld_pcie_remove() - Remove function for PCIE device
89  * @pdev: PCIE device
90  *
91  * The remove function will be called when PCIE device is disconnected
92  *
93  * Return: void
94  */
95 static void pld_pcie_remove(struct pci_dev *pdev)
96 {
97 	struct pld_context *pld_context;
98 	int errno;
99 	struct osif_psoc_sync *psoc_sync;
100 
101 	errno = osif_psoc_sync_trans_start_wait(&pdev->dev, &psoc_sync);
102 	if (errno)
103 		return;
104 
105 	osif_psoc_sync_unregister(&pdev->dev);
106 
107 	osif_psoc_sync_wait_for_ops(psoc_sync);
108 
109 	pld_context = pld_get_global_context();
110 
111 	if (!pld_context)
112 		goto out;
113 
114 	pld_context->ops->remove(&pdev->dev, PLD_BUS_TYPE_PCIE);
115 
116 	pld_del_dev(pld_context, &pdev->dev);
117 
118 out:
119 	osif_psoc_sync_trans_stop(psoc_sync);
120 	osif_psoc_sync_destroy(psoc_sync);
121 }
122 
123 #ifdef CONFIG_PLD_PCIE_CNSS
124 /**
125  * pld_pcie_idle_restart_cb() - Perform idle restart
126  * @pdev: PCIE device
127  * @id: PCIE device ID
128  *
129  * This function will be called if there is an idle restart request
130  *
131  * Return: int
132  */
133 static int pld_pcie_idle_restart_cb(struct pci_dev *pdev,
134 				    const struct pci_device_id *id)
135 {
136 	struct pld_context *pld_context;
137 
138 	pld_context = pld_get_global_context();
139 	if (pld_context->ops->idle_restart)
140 		return pld_context->ops->idle_restart(&pdev->dev,
141 						      PLD_BUS_TYPE_PCIE);
142 
143 	return -ENODEV;
144 }
145 
146 /**
147  * pld_pcie_idle_shutdown_cb() - Perform idle shutdown
148  * @pdev: PCIE device
149  * @id: PCIE device ID
150  *
151  * This function will be called if there is an idle shutdown request
152  *
153  * Return: int
154  */
155 static int pld_pcie_idle_shutdown_cb(struct pci_dev *pdev)
156 {
157 	struct pld_context *pld_context;
158 
159 	pld_context = pld_get_global_context();
160 	if (pld_context->ops->shutdown)
161 		return pld_context->ops->idle_shutdown(&pdev->dev,
162 						       PLD_BUS_TYPE_PCIE);
163 
164 	return -ENODEV;
165 }
166 
167 /**
168  * pld_pcie_reinit() - SSR re-initialize function for PCIE device
169  * @pdev: PCIE device
170  * @id: PCIE device ID
171  *
172  * During subsystem restart(SSR), this function will be called to
173  * re-initialize PCIE device.
174  *
175  * Return: int
176  */
177 static int pld_pcie_reinit(struct pci_dev *pdev,
178 			    const struct pci_device_id *id)
179 {
180 	struct pld_context *pld_context;
181 
182 	pld_context = pld_get_global_context();
183 	if (pld_context->ops->reinit)
184 		return pld_context->ops->reinit(&pdev->dev,
185 				PLD_BUS_TYPE_PCIE, pdev, (void *)id);
186 
187 	return -ENODEV;
188 }
189 
190 /**
191  * pld_pcie_shutdown() - SSR shutdown function for PCIE device
192  * @pdev: PCIE device
193  *
194  * During SSR, this function will be called to shutdown PCIE device.
195  *
196  * Return: void
197  */
198 static void pld_pcie_shutdown(struct pci_dev *pdev)
199 {
200 	struct pld_context *pld_context;
201 
202 	pld_context = pld_get_global_context();
203 	if (pld_context->ops->shutdown)
204 		pld_context->ops->shutdown(&pdev->dev, PLD_BUS_TYPE_PCIE);
205 }
206 
207 /**
208  * pld_pcie_crash_shutdown() - Crash shutdown function for PCIE device
209  * @pdev: PCIE device
210  *
211  * This function will be called when a crash is detected, it will shutdown
212  * the PCIE device.
213  *
214  * Return: void
215  */
216 static void pld_pcie_crash_shutdown(struct pci_dev *pdev)
217 {
218 	struct pld_context *pld_context;
219 
220 	pld_context = pld_get_global_context();
221 	if (pld_context->ops->crash_shutdown)
222 		pld_context->ops->crash_shutdown(&pdev->dev, PLD_BUS_TYPE_PCIE);
223 }
224 
225 /**
226  * pld_pcie_notify_handler() - Modem state notification callback function
227  * @pdev: PCIE device
228  * @state: modem power state
229  *
230  * This function will be called when there's a modem power state change.
231  *
232  * Return: void
233  */
234 static void pld_pcie_notify_handler(struct pci_dev *pdev, int state)
235 {
236 	struct pld_context *pld_context;
237 
238 	pld_context = pld_get_global_context();
239 	if (pld_context->ops->modem_status)
240 		pld_context->ops->modem_status(&pdev->dev,
241 					       PLD_BUS_TYPE_PCIE, state);
242 }
243 
244 /**
245  * pld_pcie_uevent() - update wlan driver status callback function
246  * @pdev: PCIE device
247  * @status driver uevent status
248  *
249  * This function will be called when platform driver wants to update wlan
250  * driver's status.
251  *
252  * Return: void
253  */
254 static void pld_pcie_uevent(struct pci_dev *pdev, uint32_t status)
255 {
256 	struct pld_context *pld_context;
257 	struct pld_uevent_data data = {0};
258 
259 	pld_context = pld_get_global_context();
260 	if (!pld_context)
261 		return;
262 
263 	switch (status) {
264 	case CNSS_RECOVERY:
265 		data.uevent = PLD_FW_RECOVERY_START;
266 		break;
267 	case CNSS_FW_DOWN:
268 		data.uevent = PLD_FW_DOWN;
269 		break;
270 	default:
271 		goto out;
272 	}
273 
274 	if (pld_context->ops->uevent)
275 		pld_context->ops->uevent(&pdev->dev, &data);
276 
277 out:
278 	return;
279 }
280 
281 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
282 /**
283  * pld_bus_event_type_convert() - Convert enum cnss_bus_event_type
284  *		to enum pld_bus_event
285  * @etype: enum cnss_bus_event_type value
286  *
287  * This function will convert enum cnss_bus_event_type to
288  * enum pld_bus_event.
289  *
290  * Return: enum pld_bus_event
291  */
292 static inline
293 enum pld_bus_event pld_bus_event_type_convert(enum cnss_bus_event_type etype)
294 {
295 	enum pld_bus_event pld_etype = PLD_BUS_EVENT_INVALID;
296 
297 	switch (etype) {
298 	case BUS_EVENT_PCI_LINK_DOWN:
299 		pld_etype = PLD_BUS_EVENT_PCIE_LINK_DOWN;
300 		break;
301 	default:
302 		break;
303 	}
304 
305 	return pld_etype;
306 }
307 
308 /**
309  * pld_pcie_update_event() - update wlan driver status callback function
310  * @pdev: PCIE device
311  * @cnss_uevent_data: driver uevent data
312  *
313  * This function will be called when platform driver wants to update wlan
314  * driver's status.
315  *
316  * Return: 0 for success, non zero for error code
317  */
318 static int pld_pcie_update_event(struct pci_dev *pdev,
319 				 struct cnss_uevent_data *uevent_data)
320 {
321 	struct pld_context *pld_context;
322 	struct pld_uevent_data data = {0};
323 	struct cnss_hang_event *hang_event;
324 
325 	pld_context = pld_get_global_context();
326 
327 	if (!pld_context || !uevent_data)
328 		return -EINVAL;
329 
330 	switch (uevent_data->status) {
331 	case CNSS_HANG_EVENT:
332 		if (!uevent_data->data)
333 			return -EINVAL;
334 		hang_event = (struct cnss_hang_event *)uevent_data->data;
335 		data.uevent = PLD_FW_HANG_EVENT;
336 		data.hang_data.hang_event_data = hang_event->hang_event_data;
337 		data.hang_data.hang_event_data_len =
338 					hang_event->hang_event_data_len;
339 		break;
340 	case CNSS_BUS_EVENT:
341 	{
342 		struct cnss_bus_event *bus_evt = uevent_data->data;
343 
344 		if (!bus_evt)
345 			return -EINVAL;
346 
347 		data.uevent = PLD_BUS_EVENT;
348 
349 		/* Process uevent_data->data if any */
350 		data.bus_data.etype =
351 			pld_bus_event_type_convert(bus_evt->etype);
352 		data.bus_data.event_data = bus_evt->event_data;
353 		break;
354 	}
355 	default:
356 		return 0;
357 	}
358 
359 	if (pld_context->ops->uevent)
360 		pld_context->ops->uevent(&pdev->dev, &data);
361 
362 	return 0;
363 }
364 #endif
365 
366 #ifdef FEATURE_RUNTIME_PM
367 /**
368  * pld_pcie_runtime_suspend() - PM runtime suspend
369  * @pdev: PCIE device
370  *
371  * PM runtime suspend callback function.
372  *
373  * Return: int
374  */
375 static int pld_pcie_runtime_suspend(struct pci_dev *pdev)
376 {
377 	struct pld_context *pld_context;
378 
379 	pld_context = pld_get_global_context();
380 	if (pld_context->ops->runtime_suspend)
381 		return pld_context->ops->runtime_suspend(&pdev->dev,
382 							 PLD_BUS_TYPE_PCIE);
383 
384 	return -ENODEV;
385 }
386 
387 /**
388  * pld_pcie_runtime_resume() - PM runtime resume
389  * @pdev: PCIE device
390  *
391  * PM runtime resume callback function.
392  *
393  * Return: int
394  */
395 static int pld_pcie_runtime_resume(struct pci_dev *pdev)
396 {
397 	struct pld_context *pld_context;
398 
399 	pld_context = pld_get_global_context();
400 	if (pld_context->ops->runtime_resume)
401 		return pld_context->ops->runtime_resume(&pdev->dev,
402 							PLD_BUS_TYPE_PCIE);
403 
404 	return -ENODEV;
405 }
406 #endif
407 
408 #ifdef FEATURE_GET_DRIVER_MODE
409 /**
410  * pld_pcie_get_mode() - Get current WLAN driver mode
411  *
412  * This function is to get current driver mode
413  *
414  * Return: mission mode or ftm mode
415  */
416 static
417 enum cnss_driver_mode pld_pcie_get_mode(void)
418 {
419 	struct pld_context *pld_ctx =  pld_get_global_context();
420 	enum cnss_driver_mode cnss_mode = CNSS_MISSION;
421 
422 	if (!pld_ctx)
423 		return cnss_mode;
424 
425 	switch (pld_ctx->mode) {
426 	case QDF_GLOBAL_MISSION_MODE:
427 		cnss_mode = CNSS_MISSION;
428 		break;
429 	case QDF_GLOBAL_WALTEST_MODE:
430 		cnss_mode = CNSS_WALTEST;
431 		break;
432 	case QDF_GLOBAL_FTM_MODE:
433 		cnss_mode = CNSS_FTM;
434 		break;
435 	case QDF_GLOBAL_COLDBOOT_CALIB_MODE:
436 		cnss_mode = CNSS_CALIBRATION;
437 		break;
438 	case QDF_GLOBAL_EPPING_MODE:
439 		cnss_mode = CNSS_EPPING;
440 		break;
441 	case QDF_GLOBAL_QVIT_MODE:
442 		cnss_mode = CNSS_QVIT;
443 		break;
444 	default:
445 		cnss_mode = CNSS_MISSION;
446 		break;
447 	}
448 	return cnss_mode;
449 }
450 #endif
451 #endif
452 
453 #ifdef CONFIG_PM
454 #ifdef CONFIG_PLD_PCIE_CNSS
455 /**
456  * pld_pcie_suspend() - Suspend callback function for power management
457  * @pdev: PCIE device
458  * @state: power state
459  *
460  * This function is to suspend the PCIE device when power management is
461  * enabled.
462  *
463  * Return: void
464  */
465 static int pld_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
466 {
467 	struct pld_context *pld_context;
468 
469 	pld_context = pld_get_global_context();
470 	return pld_context->ops->suspend(&pdev->dev,
471 					 PLD_BUS_TYPE_PCIE, state);
472 }
473 
474 /**
475  * pld_pcie_resume() - Resume callback function for power management
476  * @pdev: PCIE device
477  *
478  * This function is to resume the PCIE device when power management is
479  * enabled.
480  *
481  * Return: void
482  */
483 static int pld_pcie_resume(struct pci_dev *pdev)
484 {
485 	struct pld_context *pld_context;
486 
487 	pld_context = pld_get_global_context();
488 	return pld_context->ops->resume(&pdev->dev, PLD_BUS_TYPE_PCIE);
489 }
490 
491 /**
492  * pld_pcie_suspend_noirq() - Complete the actions started by suspend()
493  * @pdev: PCI device
494  *
495  * Complete the actions started by suspend().  Carry out any additional
496  * operations required for suspending the device that might be racing
497  * with its driver's interrupt handler, which is guaranteed not to run
498  * while suspend_noirq() is being executed.
499  *
500  * Return: 0 for success
501  *         Non zero failure code for errors
502  */
503 static int pld_pcie_suspend_noirq(struct pci_dev *pdev)
504 {
505 	struct pld_context *pld_context;
506 
507 	pld_context = pld_get_global_context();
508 	if (!pld_context)
509 		return -EINVAL;
510 
511 	if (pld_context->ops->suspend_noirq)
512 		return pld_context->ops->
513 			suspend_noirq(&pdev->dev, PLD_BUS_TYPE_PCIE);
514 	return 0;
515 }
516 
517 /**
518  * pld_pcie_resume_noirq() - Prepare for the execution of resume()
519  * @pdev: PCI device
520  *
521  * Prepare for the execution of resume() by carrying out any additional
522  * operations required for resuming the device that might be racing with
523  * its driver's interrupt handler, which is guaranteed not to run while
524  * resume_noirq() is being executed.
525  *
526  * Return: 0 for success
527  *         Non zero failure code for errors
528  */
529 static int pld_pcie_resume_noirq(struct pci_dev *pdev)
530 {
531 	struct pld_context *pld_context;
532 
533 	pld_context = pld_get_global_context();
534 	if (!pld_context)
535 		return -EINVAL;
536 
537 	if (pld_context->ops->resume_noirq)
538 		return pld_context->ops->
539 			resume_noirq(&pdev->dev, PLD_BUS_TYPE_PCIE);
540 	return 0;
541 }
542 #else
543 /**
544  * pld_pcie_pm_suspend() - Suspend callback function for power management
545  * @dev: device
546  *
547  * This function is to suspend the PCIE device when power management is
548  * enabled.
549  *
550  * Return: 0 for success
551  *         Non zero failure code for errors
552  */
553 static int pld_pcie_pm_suspend(struct device *dev)
554 {
555 	struct pld_context *pld_context;
556 
557 	pm_message_t state = { .event = PM_EVENT_SUSPEND };
558 
559 	pld_context = pld_get_global_context();
560 	return pld_context->ops->suspend(dev, PLD_BUS_TYPE_PCIE, state);
561 }
562 
563 /**
564  * pld_pcie_pm_resume() - Resume callback function for power management
565  * @dev: device
566  *
567  * This function is to resume the PCIE device when power management is
568  * enabled.
569  *
570  * Return: 0 for success
571  *         Non zero failure code for errors
572  */
573 static int pld_pcie_pm_resume(struct device *dev)
574 {
575 	struct pld_context *pld_context;
576 
577 	pld_context = pld_get_global_context();
578 	return pld_context->ops->resume(dev, PLD_BUS_TYPE_PCIE);
579 }
580 
581 /**
582  * pld_pcie_pm_suspend_noirq() - Complete the actions started by suspend()
583  * @dev: device
584  *
585  * Complete the actions started by suspend().  Carry out any additional
586  * operations required for suspending the device that might be racing
587  * with its driver's interrupt handler, which is guaranteed not to run
588  * while suspend_noirq() is being executed.
589  *
590  * Return: 0 for success
591  *         Non zero failure code for errors
592  */
593 static int pld_pcie_pm_suspend_noirq(struct device *dev)
594 {
595 	struct pld_context *pld_context;
596 
597 	pld_context = pld_get_global_context();
598 	if (!pld_context)
599 		return -EINVAL;
600 
601 	if (pld_context->ops->suspend_noirq)
602 		return pld_context->ops->suspend_noirq(dev, PLD_BUS_TYPE_PCIE);
603 	return 0;
604 }
605 
606 /**
607  * pld_pcie_pm_resume_noirq() - Prepare for the execution of resume()
608  * @dev: device
609  *
610  * Prepare for the execution of resume() by carrying out any additional
611  * operations required for resuming the device that might be racing with
612  * its driver's interrupt handler, which is guaranteed not to run while
613  * resume_noirq() is being executed.
614  *
615  * Return: 0 for success
616  *         Non zero failure code for errors
617  */
618 static int pld_pcie_pm_resume_noirq(struct device *dev)
619 {
620 	struct pld_context *pld_context;
621 
622 	pld_context = pld_get_global_context();
623 	if (!pld_context)
624 		return -EINVAL;
625 
626 	if (pld_context->ops->resume_noirq)
627 		return pld_context->ops->
628 			resume_noirq(dev, PLD_BUS_TYPE_PCIE);
629 	return 0;
630 }
631 #endif
632 #endif
633 
634 static struct pci_device_id pld_pcie_id_table[] = {
635 #ifdef CONFIG_AR6320_SUPPORT
636 	{ 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID },
637 #elif defined(QCA_WIFI_QCA6290)
638 	{ 0x17cb, 0x1100, PCI_ANY_ID, PCI_ANY_ID },
639 #elif defined(QCA_WIFI_QCA6390)
640 	{ 0x17cb, 0x1101, PCI_ANY_ID, PCI_ANY_ID },
641 #elif defined(QCA_WIFI_QCA6490)
642 	{ 0x17cb, 0x1103, PCI_ANY_ID, PCI_ANY_ID },
643 #elif defined(QCA_WIFI_KIWI)
644 #if defined(QCA_WIFI_MANGO)
645 	{ 0x17cb, 0x110A, PCI_ANY_ID, PCI_ANY_ID },
646 #else
647 	{ 0x17cb, 0x1107, PCI_ANY_ID, PCI_ANY_ID },
648 #endif
649 #elif defined(QCN7605_SUPPORT)
650 	{ 0x17cb, 0x1102, PCI_ANY_ID, PCI_ANY_ID },
651 #else
652 	{ 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID },
653 	{ 0x168c, 0x0041, PCI_ANY_ID, PCI_ANY_ID },
654 	{ 0x168c, 0xabcd, PCI_ANY_ID, PCI_ANY_ID },
655 	{ 0x168c, 0x7021, PCI_ANY_ID, PCI_ANY_ID },
656 #endif
657 	{ 0 }
658 };
659 
660 #ifdef MULTI_IF_NAME
661 #define PLD_PCIE_OPS_NAME "pld_pcie_" MULTI_IF_NAME
662 #else
663 #define PLD_PCIE_OPS_NAME "pld_pcie"
664 #endif
665 
666 #ifdef CONFIG_PLD_PCIE_CNSS
667 #ifdef FEATURE_RUNTIME_PM
668 struct cnss_wlan_runtime_ops runtime_pm_ops = {
669 	.runtime_suspend = pld_pcie_runtime_suspend,
670 	.runtime_resume = pld_pcie_runtime_resume,
671 };
672 #endif
673 
674 struct cnss_wlan_driver pld_pcie_ops = {
675 	.name       = PLD_PCIE_OPS_NAME,
676 	.id_table   = pld_pcie_id_table,
677 	.probe      = pld_pcie_probe,
678 	.remove     = pld_pcie_remove,
679 	.idle_restart  = pld_pcie_idle_restart_cb,
680 	.idle_shutdown = pld_pcie_idle_shutdown_cb,
681 	.reinit     = pld_pcie_reinit,
682 	.shutdown   = pld_pcie_shutdown,
683 	.crash_shutdown = pld_pcie_crash_shutdown,
684 	.modem_status   = pld_pcie_notify_handler,
685 	.update_status  = pld_pcie_uevent,
686 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
687 	.update_event = pld_pcie_update_event,
688 #endif
689 #ifdef CONFIG_PM
690 	.suspend    = pld_pcie_suspend,
691 	.resume     = pld_pcie_resume,
692 	.suspend_noirq = pld_pcie_suspend_noirq,
693 	.resume_noirq  = pld_pcie_resume_noirq,
694 #endif
695 #ifdef FEATURE_RUNTIME_PM
696 	.runtime_ops = &runtime_pm_ops,
697 #endif
698 #ifdef FEATURE_GET_DRIVER_MODE
699 	.get_driver_mode  = pld_pcie_get_mode,
700 #endif
701 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
702 	.chip_version = CHIP_VERSION,
703 #endif
704 };
705 
706 /**
707  * pld_pcie_register_driver() - Register PCIE device callback functions
708  *
709  * Return: int
710  */
711 int pld_pcie_register_driver(void)
712 {
713 	return cnss_wlan_register_driver(&pld_pcie_ops);
714 }
715 
716 /**
717  * pld_pcie_unregister_driver() - Unregister PCIE device callback functions
718  *
719  * Return: void
720  */
721 void pld_pcie_unregister_driver(void)
722 {
723 	cnss_wlan_unregister_driver(&pld_pcie_ops);
724 }
725 #else
726 #ifdef CONFIG_PM
727 static const struct dev_pm_ops pld_pm_ops = {
728 	SET_SYSTEM_SLEEP_PM_OPS(pld_pcie_pm_suspend, pld_pcie_pm_resume)
729 	.suspend_noirq = pld_pcie_pm_suspend_noirq,
730 	.resume_noirq = pld_pcie_pm_resume_noirq,
731 };
732 #endif
733 
734 struct pci_driver pld_pcie_ops = {
735 	.name       = PLD_PCIE_OPS_NAME,
736 	.id_table   = pld_pcie_id_table,
737 	.probe      = pld_pcie_probe,
738 	.remove     = pld_pcie_remove,
739 	.driver     = {
740 #ifdef CONFIG_PM
741 		.pm = &pld_pm_ops,
742 #endif
743 	},
744 };
745 
746 int pld_pcie_register_driver(void)
747 {
748 	return pci_register_driver(&pld_pcie_ops);
749 }
750 
751 void pld_pcie_unregister_driver(void)
752 {
753 	pci_unregister_driver(&pld_pcie_ops);
754 }
755 #endif
756 
757 /**
758  * pld_pcie_get_ce_id() - Get CE number for the provided IRQ
759  * @dev: device
760  * @irq: IRQ number
761  *
762  * Return: CE number
763  */
764 int pld_pcie_get_ce_id(struct device *dev, int irq)
765 {
766 	int ce_id = irq - 100;
767 
768 	if (ce_id < CE_COUNT_MAX && ce_id >= 0)
769 		return ce_id;
770 
771 	return -EINVAL;
772 }
773 
774 #ifdef CONFIG_PLD_PCIE_CNSS
775 #ifdef CONFIG_SHADOW_V3
776 static inline void
777 pld_pcie_populate_shadow_v3_cfg(struct cnss_wlan_enable_cfg *cfg,
778 				struct pld_wlan_enable_cfg *config)
779 {
780 	cfg->num_shadow_reg_v3_cfg = config->num_shadow_reg_v3_cfg;
781 	cfg->shadow_reg_v3_cfg = (struct cnss_shadow_reg_v3_cfg *)
782 				 config->shadow_reg_v3_cfg;
783 }
784 #else
785 static inline void
786 pld_pcie_populate_shadow_v3_cfg(struct cnss_wlan_enable_cfg *cfg,
787 				struct pld_wlan_enable_cfg *config)
788 {
789 }
790 #endif
791 /**
792  * pld_pcie_wlan_enable() - Enable WLAN
793  * @dev: device
794  * @config: WLAN configuration data
795  * @mode: WLAN mode
796  * @host_version: host software version
797  *
798  * This function enables WLAN FW. It passed WLAN configuration data,
799  * WLAN mode and host software version to FW.
800  *
801  * Return: 0 for success
802  *         Non zero failure code for errors
803  */
804 int pld_pcie_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
805 			 enum pld_driver_mode mode, const char *host_version)
806 {
807 	struct cnss_wlan_enable_cfg cfg;
808 	enum cnss_driver_mode cnss_mode;
809 
810 	cfg.num_ce_tgt_cfg = config->num_ce_tgt_cfg;
811 	cfg.ce_tgt_cfg = (struct cnss_ce_tgt_pipe_cfg *)
812 		config->ce_tgt_cfg;
813 	cfg.num_ce_svc_pipe_cfg = config->num_ce_svc_pipe_cfg;
814 	cfg.ce_svc_cfg = (struct cnss_ce_svc_pipe_cfg *)
815 		config->ce_svc_cfg;
816 	cfg.num_shadow_reg_cfg = config->num_shadow_reg_cfg;
817 	cfg.shadow_reg_cfg = (struct cnss_shadow_reg_cfg *)
818 		config->shadow_reg_cfg;
819 	cfg.num_shadow_reg_v2_cfg = config->num_shadow_reg_v2_cfg;
820 	cfg.shadow_reg_v2_cfg = (struct cnss_shadow_reg_v2_cfg *)
821 		config->shadow_reg_v2_cfg;
822 	cfg.rri_over_ddr_cfg_valid = config->rri_over_ddr_cfg_valid;
823 	if (config->rri_over_ddr_cfg_valid) {
824 		cfg.rri_over_ddr_cfg.base_addr_low =
825 			 config->rri_over_ddr_cfg.base_addr_low;
826 		cfg.rri_over_ddr_cfg.base_addr_high =
827 			 config->rri_over_ddr_cfg.base_addr_high;
828 	}
829 
830 	pld_pcie_populate_shadow_v3_cfg(&cfg, config);
831 
832 	switch (mode) {
833 	case PLD_FTM:
834 		cnss_mode = CNSS_FTM;
835 		break;
836 	case PLD_EPPING:
837 		cnss_mode = CNSS_EPPING;
838 		break;
839 	default:
840 		cnss_mode = CNSS_MISSION;
841 		break;
842 	}
843 	return cnss_wlan_enable(dev, &cfg, cnss_mode, host_version);
844 }
845 
846 /**
847  * pld_pcie_wlan_disable() - Disable WLAN
848  * @dev: device
849  * @mode: WLAN mode
850  *
851  * This function disables WLAN FW. It passes WLAN mode to FW.
852  *
853  * Return: 0 for success
854  *         Non zero failure code for errors
855  */
856 int pld_pcie_wlan_disable(struct device *dev, enum pld_driver_mode mode)
857 {
858 	return cnss_wlan_disable(dev, CNSS_OFF);
859 }
860 
861 /**
862  * pld_pcie_get_fw_files_for_target() - Get FW file names
863  * @dev: device
864  * @pfw_files: buffer for FW file names
865  * @target_type: target type
866  * @target_version: target version
867  *
868  * Return target specific FW file names to the buffer.
869  *
870  * Return: 0 for success
871  *         Non zero failure code for errors
872  */
873 int pld_pcie_get_fw_files_for_target(struct device *dev,
874 				     struct pld_fw_files *pfw_files,
875 				     u32 target_type, u32 target_version)
876 {
877 	int ret = 0;
878 	struct cnss_fw_files cnss_fw_files;
879 
880 	if (!pfw_files)
881 		return -ENODEV;
882 
883 	memset(pfw_files, 0, sizeof(*pfw_files));
884 
885 	ret = cnss_get_fw_files_for_target(dev, &cnss_fw_files,
886 					   target_type, target_version);
887 	if (ret)
888 		return ret;
889 
890 	scnprintf(pfw_files->image_file, PLD_MAX_FILE_NAME, PREFIX "%s",
891 		  cnss_fw_files.image_file);
892 	scnprintf(pfw_files->board_data, PLD_MAX_FILE_NAME, PREFIX "%s",
893 		  cnss_fw_files.board_data);
894 	scnprintf(pfw_files->otp_data, PLD_MAX_FILE_NAME, PREFIX "%s",
895 		  cnss_fw_files.otp_data);
896 	scnprintf(pfw_files->utf_file, PLD_MAX_FILE_NAME, PREFIX "%s",
897 		  cnss_fw_files.utf_file);
898 	scnprintf(pfw_files->utf_board_data, PLD_MAX_FILE_NAME, PREFIX "%s",
899 		  cnss_fw_files.utf_board_data);
900 	scnprintf(pfw_files->epping_file, PLD_MAX_FILE_NAME, PREFIX "%s",
901 		  cnss_fw_files.epping_file);
902 	scnprintf(pfw_files->evicted_data, PLD_MAX_FILE_NAME, PREFIX "%s",
903 		  cnss_fw_files.evicted_data);
904 
905 	return 0;
906 }
907 
908 /**
909  * pld_pcie_get_platform_cap() - Get platform capabilities
910  * @dev: device
911  * @cap: buffer to the capabilities
912  *
913  * Return capabilities to the buffer.
914  *
915  * Return: 0 for success
916  *         Non zero failure code for errors
917  */
918 int pld_pcie_get_platform_cap(struct device *dev, struct pld_platform_cap *cap)
919 {
920 	int ret = 0;
921 	struct cnss_platform_cap cnss_cap;
922 
923 	if (!cap)
924 		return -ENODEV;
925 
926 	ret = cnss_get_platform_cap(dev, &cnss_cap);
927 	if (ret)
928 		return ret;
929 
930 	memcpy(cap, &cnss_cap, sizeof(*cap));
931 	return 0;
932 }
933 
934 /**
935  * pld_pcie_get_soc_info() - Get SOC information
936  * @dev: device
937  * @info: buffer to SOC information
938  *
939  * Return SOC info to the buffer.
940  *
941  * Return: 0 for success
942  *         Non zero failure code for errors
943  */
944 int pld_pcie_get_soc_info(struct device *dev, struct pld_soc_info *info)
945 {
946 	int ret = 0, i;
947 	struct cnss_soc_info cnss_info = {0};
948 
949 	if (!info)
950 		return -ENODEV;
951 
952 	ret = cnss_get_soc_info(dev, &cnss_info);
953 	if (ret)
954 		return ret;
955 
956 	info->v_addr = cnss_info.va;
957 	info->p_addr = cnss_info.pa;
958 	info->chip_id = cnss_info.chip_id;
959 	info->chip_family = cnss_info.chip_family;
960 	info->board_id = cnss_info.board_id;
961 	info->soc_id = cnss_info.soc_id;
962 	info->fw_version = cnss_info.fw_version;
963 	strlcpy(info->fw_build_timestamp, cnss_info.fw_build_timestamp,
964 		sizeof(info->fw_build_timestamp));
965 	info->device_version.family_number =
966 		cnss_info.device_version.family_number;
967 	info->device_version.device_number =
968 		cnss_info.device_version.device_number;
969 	info->device_version.major_version =
970 		cnss_info.device_version.major_version;
971 	info->device_version.minor_version =
972 		cnss_info.device_version.minor_version;
973 	for (i = 0; i < PLD_MAX_DEV_MEM_NUM; i++) {
974 		info->dev_mem_info[i].start = cnss_info.dev_mem_info[i].start;
975 		info->dev_mem_info[i].size = cnss_info.dev_mem_info[i].size;
976 	}
977 
978 	return 0;
979 }
980 
981 /**
982  * pld_pcie_schedule_recovery_work() - schedule recovery work
983  * @dev: device
984  * @reason: recovery reason
985  *
986  * Return: void
987  */
988 void pld_pcie_schedule_recovery_work(struct device *dev,
989 				     enum pld_recovery_reason reason)
990 {
991 	enum cnss_recovery_reason cnss_reason;
992 
993 	switch (reason) {
994 	case PLD_REASON_LINK_DOWN:
995 		cnss_reason = CNSS_REASON_LINK_DOWN;
996 		break;
997 	default:
998 		cnss_reason = CNSS_REASON_DEFAULT;
999 		break;
1000 	}
1001 	cnss_schedule_recovery(dev, cnss_reason);
1002 }
1003 
1004 /**
1005  * pld_pcie_device_self_recovery() - device self recovery
1006  * @dev: device
1007  * @reason: recovery reason
1008  *
1009  * Return: void
1010  */
1011 void pld_pcie_device_self_recovery(struct device *dev,
1012 				   enum pld_recovery_reason reason)
1013 {
1014 	enum cnss_recovery_reason cnss_reason;
1015 
1016 	switch (reason) {
1017 	case PLD_REASON_LINK_DOWN:
1018 		cnss_reason = CNSS_REASON_LINK_DOWN;
1019 		break;
1020 	default:
1021 		cnss_reason = CNSS_REASON_DEFAULT;
1022 		break;
1023 	}
1024 	cnss_self_recovery(dev, cnss_reason);
1025 }
1026 #endif
1027 #endif
1028