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