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