blob: a79de6cd8df755308cb091ceed304bc5ad92a341 [file] [log] [blame]
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001/*
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +05302 * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08003 *
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080019#include <linux/platform_device.h>
20#include <linux/err.h>
21#include <linux/pci.h>
22#include <linux/list.h>
23#include <linux/slab.h>
24
Yuanyuan Liu11f526a2016-05-18 10:22:07 -070025#ifdef CONFIG_PLD_PCIE_CNSS
Yue Mae6a7a322016-08-31 11:09:23 -070026#include <net/cnss2.h>
27#endif
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080028
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080029#include "pld_internal.h"
Jeff Johnsonbbaf4e42016-10-07 12:33:22 -070030#include "pld_pcie.h"
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080031
32#ifdef CONFIG_PCI
33
34#ifdef QCA_WIFI_3_0_ADRASTEA
35#define CE_COUNT_MAX 12
36#else
37#define CE_COUNT_MAX 8
38#endif
39
40/**
41 * pld_pcie_probe() - Probe function for PCIE platform driver
42 * @pdev: PCIE device
43 * @id: PCIE device ID table
44 *
45 * The probe function will be called when PCIE device provided
46 * in the ID table is detected.
47 *
48 * Return: int
49 */
50static int pld_pcie_probe(struct pci_dev *pdev,
51 const struct pci_device_id *id)
52{
53 struct pld_context *pld_context;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080054 int ret = 0;
55
56 pld_context = pld_get_global_context();
57 if (!pld_context) {
58 ret = -ENODEV;
59 goto out;
60 }
61
Ajit Pal Singh5e618aa2018-12-20 17:47:36 +053062 ret = pld_add_dev(pld_context, &pdev->dev, NULL, PLD_BUS_TYPE_PCIE);
Yuanyuan Liu5e25f532016-05-25 16:26:40 -070063 if (ret)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080064 goto out;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080065
66 return pld_context->ops->probe(&pdev->dev,
67 PLD_BUS_TYPE_PCIE, pdev, (void *)id);
68
69out:
70 return ret;
71}
72
73
74/**
75 * pld_pcie_remove() - Remove function for PCIE device
76 * @pdev: PCIE device
77 *
78 * The remove function will be called when PCIE device is disconnected
79 *
80 * Return: void
81 */
82static void pld_pcie_remove(struct pci_dev *pdev)
83{
84 struct pld_context *pld_context;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080085
86 pld_context = pld_get_global_context();
87
88 if (!pld_context)
89 return;
90
Yuanyuan Liu960fa212016-05-24 17:15:43 -070091 pld_context->ops->remove(&pdev->dev, PLD_BUS_TYPE_PCIE);
92
Yuanyuan Liu5e25f532016-05-25 16:26:40 -070093 pld_del_dev(pld_context, &pdev->dev);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080094}
95
Yuanyuan Liu11f526a2016-05-18 10:22:07 -070096#ifdef CONFIG_PLD_PCIE_CNSS
Yuanyuan Liud9f7a362016-01-22 14:27:12 -080097/**
98 * pld_pcie_reinit() - SSR re-initialize function for PCIE device
99 * @pdev: PCIE device
100 * @id: PCIE device ID
101 *
102 * During subsystem restart(SSR), this function will be called to
103 * re-initialize PCIE device.
104 *
105 * Return: int
106 */
107static int pld_pcie_reinit(struct pci_dev *pdev,
108 const struct pci_device_id *id)
109{
110 struct pld_context *pld_context;
111
112 pld_context = pld_get_global_context();
113 if (pld_context->ops->reinit)
114 return pld_context->ops->reinit(&pdev->dev,
115 PLD_BUS_TYPE_PCIE, pdev, (void *)id);
116
117 return -ENODEV;
118}
119
120/**
121 * pld_pcie_shutdown() - SSR shutdown function for PCIE device
122 * @pdev: PCIE device
123 *
124 * During SSR, this function will be called to shutdown PCIE device.
125 *
126 * Return: void
127 */
128static void pld_pcie_shutdown(struct pci_dev *pdev)
129{
130 struct pld_context *pld_context;
131
132 pld_context = pld_get_global_context();
133 if (pld_context->ops->shutdown)
134 pld_context->ops->shutdown(&pdev->dev, PLD_BUS_TYPE_PCIE);
135}
136
137/**
138 * pld_pcie_crash_shutdown() - Crash shutdown function for PCIE device
139 * @pdev: PCIE device
140 *
141 * This function will be called when a crash is detected, it will shutdown
142 * the PCIE device.
143 *
144 * Return: void
145 */
146static void pld_pcie_crash_shutdown(struct pci_dev *pdev)
147{
148 struct pld_context *pld_context;
149
150 pld_context = pld_get_global_context();
151 if (pld_context->ops->crash_shutdown)
152 pld_context->ops->crash_shutdown(&pdev->dev, PLD_BUS_TYPE_PCIE);
153}
154
155/**
156 * pld_pcie_notify_handler() - Modem state notification callback function
157 * @pdev: PCIE device
158 * @state: modem power state
159 *
160 * This function will be called when there's a modem power state change.
161 *
162 * Return: void
163 */
164static void pld_pcie_notify_handler(struct pci_dev *pdev, int state)
165{
166 struct pld_context *pld_context;
167
168 pld_context = pld_get_global_context();
169 if (pld_context->ops->modem_status)
170 pld_context->ops->modem_status(&pdev->dev,
171 PLD_BUS_TYPE_PCIE, state);
172}
Yuanyuan Liud698eb62016-04-11 11:43:30 -0700173
Yuanyuan Liu06a342f2017-01-12 16:48:19 -0800174/**
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530175 * pld_pcie_uevent() - update wlan driver status callback function
Yuanyuan Liu06a342f2017-01-12 16:48:19 -0800176 * @pdev: PCIE device
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530177 * @status driver uevent status
Yuanyuan Liu06a342f2017-01-12 16:48:19 -0800178 *
179 * This function will be called when platform driver wants to update wlan
180 * driver's status.
181 *
182 * Return: void
183 */
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530184static void pld_pcie_uevent(struct pci_dev *pdev, uint32_t status)
Yuanyuan Liu06a342f2017-01-12 16:48:19 -0800185{
186 struct pld_context *pld_context;
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530187 struct pld_uevent_data data;
Yuanyuan Liu06a342f2017-01-12 16:48:19 -0800188
189 pld_context = pld_get_global_context();
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530190 if (!pld_context)
191 return;
192
Yue Ma096189d2017-09-13 11:14:59 -0700193 switch (status) {
194 case CNSS_RECOVERY:
Dustin Brown8f05f652018-10-25 15:17:30 -0700195 data.uevent = PLD_FW_RECOVERY_START;
Yue Ma096189d2017-09-13 11:14:59 -0700196 break;
Arunk Khandavallif9957c02018-10-24 16:51:14 +0530197 case CNSS_FW_DOWN:
198 data.uevent = PLD_FW_DOWN;
199 break;
Yue Ma096189d2017-09-13 11:14:59 -0700200 default:
201 goto out;
202 }
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530203
Will Huangbdd28712017-06-21 11:02:39 +0800204 if (pld_context->ops->uevent)
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530205 pld_context->ops->uevent(&pdev->dev, &data);
206
Yue Ma096189d2017-09-13 11:14:59 -0700207out:
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530208 return;
Yuanyuan Liu06a342f2017-01-12 16:48:19 -0800209}
210
Yuanyuan Liud698eb62016-04-11 11:43:30 -0700211#ifdef FEATURE_RUNTIME_PM
212/**
213 * pld_pcie_runtime_suspend() - PM runtime suspend
214 * @pdev: PCIE device
215 *
216 * PM runtime suspend callback function.
217 *
218 * Return: int
219 */
220static int pld_pcie_runtime_suspend(struct pci_dev *pdev)
221{
222 struct pld_context *pld_context;
223
224 pld_context = pld_get_global_context();
225 if (pld_context->ops->runtime_suspend)
226 return pld_context->ops->runtime_suspend(&pdev->dev,
227 PLD_BUS_TYPE_PCIE);
228
229 return -ENODEV;
230}
231
232/**
233 * pld_pcie_runtime_resume() - PM runtime resume
234 * @pdev: PCIE device
235 *
236 * PM runtime resume callback function.
237 *
238 * Return: int
239 */
240static int pld_pcie_runtime_resume(struct pci_dev *pdev)
241{
242 struct pld_context *pld_context;
243
244 pld_context = pld_get_global_context();
245 if (pld_context->ops->runtime_resume)
246 return pld_context->ops->runtime_resume(&pdev->dev,
247 PLD_BUS_TYPE_PCIE);
248
249 return -ENODEV;
250}
251#endif
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800252#endif
253
Yuanyuan Liu25c66e12016-05-13 10:17:46 -0700254#ifdef CONFIG_PM
Yue Ma52d355c2017-01-25 14:49:23 -0800255#ifdef CONFIG_PLD_PCIE_CNSS
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800256/**
257 * pld_pcie_suspend() - Suspend callback function for power management
258 * @pdev: PCIE device
259 * @state: power state
260 *
261 * This function is to suspend the PCIE device when power management is
262 * enabled.
263 *
264 * Return: void
265 */
266static int pld_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
267{
268 struct pld_context *pld_context;
269
270 pld_context = pld_get_global_context();
271 return pld_context->ops->suspend(&pdev->dev,
272 PLD_BUS_TYPE_PCIE, state);
273}
274
275/**
276 * pld_pcie_resume() - Resume callback function for power management
277 * @pdev: PCIE device
278 *
279 * This function is to resume the PCIE device when power management is
280 * enabled.
281 *
282 * Return: void
283 */
284static int pld_pcie_resume(struct pci_dev *pdev)
285{
286 struct pld_context *pld_context;
287
288 pld_context = pld_get_global_context();
289 return pld_context->ops->resume(&pdev->dev, PLD_BUS_TYPE_PCIE);
290}
Yue Mae42c8452017-01-06 17:28:28 -0800291
292/**
293 * pld_pcie_suspend_noirq() - Complete the actions started by suspend()
294 * @pdev: PCI device
295 *
296 * Complete the actions started by suspend(). Carry out any additional
297 * operations required for suspending the device that might be racing
298 * with its driver's interrupt handler, which is guaranteed not to run
299 * while suspend_noirq() is being executed.
300 *
301 * Return: 0 for success
302 * Non zero failure code for errors
303 */
304static int pld_pcie_suspend_noirq(struct pci_dev *pdev)
305{
306 struct pld_context *pld_context;
307
308 pld_context = pld_get_global_context();
309 if (!pld_context)
310 return -EINVAL;
311
312 if (pld_context->ops->suspend_noirq)
313 return pld_context->ops->
314 suspend_noirq(&pdev->dev, PLD_BUS_TYPE_PCIE);
315 return 0;
316}
317
318/**
319 * pld_pcie_resume_noirq() - Prepare for the execution of resume()
320 * @pdev: PCI device
321 *
322 * Prepare for the execution of resume() by carrying out any additional
323 * operations required for resuming the device that might be racing with
324 * its driver's interrupt handler, which is guaranteed not to run while
325 * resume_noirq() is being executed.
326 *
327 * Return: 0 for success
328 * Non zero failure code for errors
329 */
330static int pld_pcie_resume_noirq(struct pci_dev *pdev)
331{
332 struct pld_context *pld_context;
333
334 pld_context = pld_get_global_context();
335 if (!pld_context)
336 return -EINVAL;
337
338 if (pld_context->ops->resume_noirq)
339 return pld_context->ops->
340 resume_noirq(&pdev->dev, PLD_BUS_TYPE_PCIE);
341 return 0;
342}
Yue Ma52d355c2017-01-25 14:49:23 -0800343#else
344/**
345 * pld_pcie_pm_suspend() - Suspend callback function for power management
346 * @dev: device
347 *
348 * This function is to suspend the PCIE device when power management is
349 * enabled.
350 *
351 * Return: 0 for success
352 * Non zero failure code for errors
353 */
354static int pld_pcie_pm_suspend(struct device *dev)
355{
356 struct pld_context *pld_context;
357
358 pm_message_t state = { .event = PM_EVENT_SUSPEND };
359
360 pld_context = pld_get_global_context();
361 return pld_context->ops->suspend(dev, PLD_BUS_TYPE_PCIE, state);
362}
363
364/**
365 * pld_pcie_pm_resume() - Resume callback function for power management
366 * @dev: device
367 *
368 * This function is to resume the PCIE device when power management is
369 * enabled.
370 *
371 * Return: 0 for success
372 * Non zero failure code for errors
373 */
374static int pld_pcie_pm_resume(struct device *dev)
375{
376 struct pld_context *pld_context;
377
378 pld_context = pld_get_global_context();
379 return pld_context->ops->resume(dev, PLD_BUS_TYPE_PCIE);
380}
381
382/**
383 * pld_pcie_pm_suspend_noirq() - Complete the actions started by suspend()
384 * @dev: device
385 *
386 * Complete the actions started by suspend(). Carry out any additional
387 * operations required for suspending the device that might be racing
388 * with its driver's interrupt handler, which is guaranteed not to run
389 * while suspend_noirq() is being executed.
390 *
391 * Return: 0 for success
392 * Non zero failure code for errors
393 */
394static int pld_pcie_pm_suspend_noirq(struct device *dev)
395{
396 struct pld_context *pld_context;
397
398 pld_context = pld_get_global_context();
399 if (!pld_context)
400 return -EINVAL;
401
402 if (pld_context->ops->suspend_noirq)
403 return pld_context->ops->suspend_noirq(dev, PLD_BUS_TYPE_PCIE);
404 return 0;
405}
406
407/**
408 * pld_pcie_pm_resume_noirq() - Prepare for the execution of resume()
409 * @dev: device
410 *
411 * Prepare for the execution of resume() by carrying out any additional
412 * operations required for resuming the device that might be racing with
413 * its driver's interrupt handler, which is guaranteed not to run while
414 * resume_noirq() is being executed.
415 *
416 * Return: 0 for success
417 * Non zero failure code for errors
418 */
419static int pld_pcie_pm_resume_noirq(struct device *dev)
420{
421 struct pld_context *pld_context;
422
423 pld_context = pld_get_global_context();
424 if (!pld_context)
425 return -EINVAL;
426
427 if (pld_context->ops->resume_noirq)
428 return pld_context->ops->
429 resume_noirq(dev, PLD_BUS_TYPE_PCIE);
430 return 0;
431}
432#endif
Yuanyuan Liu25c66e12016-05-13 10:17:46 -0700433#endif
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800434
435static struct pci_device_id pld_pcie_id_table[] = {
436 { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID },
437 { 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID },
438 { 0x168c, 0x0041, PCI_ANY_ID, PCI_ANY_ID },
439 { 0x168c, 0xabcd, PCI_ANY_ID, PCI_ANY_ID },
440 { 0x168c, 0x7021, PCI_ANY_ID, PCI_ANY_ID },
441 { 0 }
442};
443
Manikandan Mohan04459b92018-02-23 16:32:48 -0800444#ifdef MULTI_IF_NAME
445#define PLD_PCIE_OPS_NAME "pld_pcie_" MULTI_IF_NAME
446#else
447#define PLD_PCIE_OPS_NAME "pld_pcie"
448#endif
449
Yuanyuan Liu11f526a2016-05-18 10:22:07 -0700450#ifdef CONFIG_PLD_PCIE_CNSS
Yuanyuan Liud698eb62016-04-11 11:43:30 -0700451#ifdef FEATURE_RUNTIME_PM
452struct cnss_wlan_runtime_ops runtime_pm_ops = {
453 .runtime_suspend = pld_pcie_runtime_suspend,
454 .runtime_resume = pld_pcie_runtime_resume,
455};
456#endif
457
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800458struct cnss_wlan_driver pld_pcie_ops = {
Manikandan Mohan04459b92018-02-23 16:32:48 -0800459 .name = PLD_PCIE_OPS_NAME,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800460 .id_table = pld_pcie_id_table,
461 .probe = pld_pcie_probe,
462 .remove = pld_pcie_remove,
463 .reinit = pld_pcie_reinit,
464 .shutdown = pld_pcie_shutdown,
465 .crash_shutdown = pld_pcie_crash_shutdown,
466 .modem_status = pld_pcie_notify_handler,
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530467 .update_status = pld_pcie_uevent,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800468#ifdef CONFIG_PM
469 .suspend = pld_pcie_suspend,
470 .resume = pld_pcie_resume,
Yue Mae42c8452017-01-06 17:28:28 -0800471 .suspend_noirq = pld_pcie_suspend_noirq,
472 .resume_noirq = pld_pcie_resume_noirq,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800473#endif
Yuanyuan Liud698eb62016-04-11 11:43:30 -0700474#ifdef FEATURE_RUNTIME_PM
475 .runtime_ops = &runtime_pm_ops,
476#endif
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800477};
478
479/**
480 * pld_pcie_register_driver() - Register PCIE device callback functions
481 *
482 * Return: int
483 */
484int pld_pcie_register_driver(void)
485{
486 return cnss_wlan_register_driver(&pld_pcie_ops);
487}
488
489/**
490 * pld_pcie_unregister_driver() - Unregister PCIE device callback functions
491 *
492 * Return: void
493 */
494void pld_pcie_unregister_driver(void)
495{
496 cnss_wlan_unregister_driver(&pld_pcie_ops);
497}
498#else
Yue Ma52d355c2017-01-25 14:49:23 -0800499#ifdef CONFIG_PM
500static const struct dev_pm_ops pld_pm_ops = {
501 SET_SYSTEM_SLEEP_PM_OPS(pld_pcie_pm_suspend, pld_pcie_pm_resume)
502 .suspend_noirq = pld_pcie_pm_suspend_noirq,
503 .resume_noirq = pld_pcie_pm_resume_noirq,
504};
505#endif
506
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800507struct pci_driver pld_pcie_ops = {
Manikandan Mohan04459b92018-02-23 16:32:48 -0800508 .name = PLD_PCIE_OPS_NAME,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800509 .id_table = pld_pcie_id_table,
510 .probe = pld_pcie_probe,
511 .remove = pld_pcie_remove,
Yue Ma52d355c2017-01-25 14:49:23 -0800512 .driver = {
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800513#ifdef CONFIG_PM
Yue Ma52d355c2017-01-25 14:49:23 -0800514 .pm = &pld_pm_ops,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800515#endif
Yue Ma52d355c2017-01-25 14:49:23 -0800516 },
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800517};
518
519int pld_pcie_register_driver(void)
520{
521 return pci_register_driver(&pld_pcie_ops);
522}
523
524void pld_pcie_unregister_driver(void)
525{
526 pci_unregister_driver(&pld_pcie_ops);
527}
528#endif
529
530/**
531 * pld_pcie_get_ce_id() - Get CE number for the provided IRQ
Yue Ma85761e62017-10-30 11:13:45 -0700532 * @dev: device
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800533 * @irq: IRQ number
534 *
535 * Return: CE number
536 */
Yue Ma85761e62017-10-30 11:13:45 -0700537int pld_pcie_get_ce_id(struct device *dev, int irq)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800538{
539 int ce_id = irq - 100;
Manikandan Mohan8cf50612017-04-10 13:23:32 -0700540
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800541 if (ce_id < CE_COUNT_MAX && ce_id >= 0)
542 return ce_id;
543
544 return -EINVAL;
545}
546
Yuanyuan Liu11f526a2016-05-18 10:22:07 -0700547#ifdef CONFIG_PLD_PCIE_CNSS
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800548/**
549 * pld_pcie_wlan_enable() - Enable WLAN
Yue Ma85761e62017-10-30 11:13:45 -0700550 * @dev: device
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800551 * @config: WLAN configuration data
552 * @mode: WLAN mode
553 * @host_version: host software version
554 *
555 * This function enables WLAN FW. It passed WLAN configuration data,
556 * WLAN mode and host software version to FW.
557 *
558 * Return: 0 for success
559 * Non zero failure code for errors
560 */
Yue Ma08047522016-11-08 18:53:26 -0800561int pld_pcie_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800562 enum pld_driver_mode mode, const char *host_version)
563{
564 struct cnss_wlan_enable_cfg cfg;
565 enum cnss_driver_mode cnss_mode;
566
567 cfg.num_ce_tgt_cfg = config->num_ce_tgt_cfg;
568 cfg.ce_tgt_cfg = (struct cnss_ce_tgt_pipe_cfg *)
569 config->ce_tgt_cfg;
570 cfg.num_ce_svc_pipe_cfg = config->num_ce_svc_pipe_cfg;
571 cfg.ce_svc_cfg = (struct cnss_ce_svc_pipe_cfg *)
572 config->ce_svc_cfg;
573 cfg.num_shadow_reg_cfg = config->num_shadow_reg_cfg;
574 cfg.shadow_reg_cfg = (struct cnss_shadow_reg_cfg *)
575 config->shadow_reg_cfg;
Yue Ma502a28f2017-01-03 16:38:44 -0800576 cfg.num_shadow_reg_v2_cfg = config->num_shadow_reg_v2_cfg;
577 cfg.shadow_reg_v2_cfg = (struct cnss_shadow_reg_v2_cfg *)
578 config->shadow_reg_v2_cfg;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800579
580 switch (mode) {
581 case PLD_FTM:
582 cnss_mode = CNSS_FTM;
583 break;
584 case PLD_EPPING:
585 cnss_mode = CNSS_EPPING;
586 break;
587 default:
588 cnss_mode = CNSS_MISSION;
589 break;
590 }
Yue Ma08047522016-11-08 18:53:26 -0800591 return cnss_wlan_enable(dev, &cfg, cnss_mode, host_version);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800592}
593
594/**
595 * pld_pcie_wlan_disable() - Disable WLAN
Yue Ma85761e62017-10-30 11:13:45 -0700596 * @dev: device
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800597 * @mode: WLAN mode
598 *
599 * This function disables WLAN FW. It passes WLAN mode to FW.
600 *
601 * Return: 0 for success
602 * Non zero failure code for errors
603 */
Yue Ma08047522016-11-08 18:53:26 -0800604int pld_pcie_wlan_disable(struct device *dev, enum pld_driver_mode mode)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800605{
Yue Ma08047522016-11-08 18:53:26 -0800606 return cnss_wlan_disable(dev, CNSS_OFF);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800607}
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800608
609/**
610 * pld_pcie_get_fw_files_for_target() - Get FW file names
Yue Ma85761e62017-10-30 11:13:45 -0700611 * @dev: device
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800612 * @pfw_files: buffer for FW file names
613 * @target_type: target type
614 * @target_version: target version
615 *
616 * Return target specific FW file names to the buffer.
617 *
618 * Return: 0 for success
619 * Non zero failure code for errors
620 */
Yue Ma85761e62017-10-30 11:13:45 -0700621int pld_pcie_get_fw_files_for_target(struct device *dev,
622 struct pld_fw_files *pfw_files,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800623 u32 target_type, u32 target_version)
624{
625 int ret = 0;
626 struct cnss_fw_files cnss_fw_files;
627
628 if (pfw_files == NULL)
629 return -ENODEV;
630
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700631 memset(pfw_files, 0, sizeof(*pfw_files));
632
Yue Ma85761e62017-10-30 11:13:45 -0700633 ret = cnss_get_fw_files_for_target(dev, &cnss_fw_files,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800634 target_type, target_version);
Yue Ma85761e62017-10-30 11:13:45 -0700635 if (ret)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800636 return ret;
637
Qun Zhang4a83a462018-09-11 16:28:51 +0800638 scnprintf(pfw_files->image_file, PLD_MAX_FILE_NAME, PREFIX "%s",
639 cnss_fw_files.image_file);
640 scnprintf(pfw_files->board_data, PLD_MAX_FILE_NAME, PREFIX "%s",
641 cnss_fw_files.board_data);
642 scnprintf(pfw_files->otp_data, PLD_MAX_FILE_NAME, PREFIX "%s",
643 cnss_fw_files.otp_data);
644 scnprintf(pfw_files->utf_file, PLD_MAX_FILE_NAME, PREFIX "%s",
645 cnss_fw_files.utf_file);
646 scnprintf(pfw_files->utf_board_data, PLD_MAX_FILE_NAME, PREFIX "%s",
647 cnss_fw_files.utf_board_data);
648 scnprintf(pfw_files->epping_file, PLD_MAX_FILE_NAME, PREFIX "%s",
649 cnss_fw_files.epping_file);
650 scnprintf(pfw_files->evicted_data, PLD_MAX_FILE_NAME, PREFIX "%s",
651 cnss_fw_files.evicted_data);
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700652
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800653 return 0;
654}
655
656/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800657 * pld_pcie_get_platform_cap() - Get platform capabilities
Yue Ma85761e62017-10-30 11:13:45 -0700658 * @dev: device
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800659 * @cap: buffer to the capabilities
660 *
661 * Return capabilities to the buffer.
662 *
663 * Return: 0 for success
664 * Non zero failure code for errors
665 */
Yue Ma85761e62017-10-30 11:13:45 -0700666int pld_pcie_get_platform_cap(struct device *dev, struct pld_platform_cap *cap)
667{
668 int ret = 0;
669 struct cnss_platform_cap cnss_cap;
670
671 if (cap == NULL)
672 return -ENODEV;
673
674 ret = cnss_get_platform_cap(dev, &cnss_cap);
675 if (ret)
676 return ret;
677
678 memcpy(cap, &cnss_cap, sizeof(*cap));
679 return 0;
680}
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800681
682/**
Yue Macd243862016-11-04 19:21:16 -0700683 * pld_pcie_get_soc_info() - Get SOC information
Yue Ma85761e62017-10-30 11:13:45 -0700684 * @dev: device
Yue Macd243862016-11-04 19:21:16 -0700685 * @info: buffer to SOC information
686 *
687 * Return SOC info to the buffer.
688 *
689 * Return: 0 for success
690 * Non zero failure code for errors
691 */
692int pld_pcie_get_soc_info(struct device *dev, struct pld_soc_info *info)
693{
694 int ret = 0;
lihual8b9daf22018-04-02 15:18:54 +0800695 struct cnss_soc_info cnss_info = {0};
Yue Macd243862016-11-04 19:21:16 -0700696
697 if (info == NULL)
698 return -ENODEV;
699
700 ret = cnss_get_soc_info(dev, &cnss_info);
701 if (ret)
702 return ret;
703
Frank Liu0e7ac562018-06-15 15:29:49 +0800704 info->v_addr = cnss_info.va;
705 info->p_addr = cnss_info.pa;
706 info->chip_id = cnss_info.chip_id;
707 info->chip_family = cnss_info.chip_family;
708 info->board_id = cnss_info.board_id;
709 info->soc_id = cnss_info.soc_id;
710 info->fw_version = cnss_info.fw_version;
711 strlcpy(info->fw_build_timestamp, cnss_info.fw_build_timestamp,
712 sizeof(info->fw_build_timestamp));
Yue Macd243862016-11-04 19:21:16 -0700713
714 return 0;
715}
716
717/**
Yuanyuan Liu10fc3d32017-01-12 15:32:06 -0800718 * pld_pcie_schedule_recovery_work() - schedule recovery work
719 * @dev: device
720 * @reason: recovery reason
721 *
722 * Return: void
723 */
724void pld_pcie_schedule_recovery_work(struct device *dev,
725 enum pld_recovery_reason reason)
726{
727 enum cnss_recovery_reason cnss_reason;
728
729 switch (reason) {
730 case PLD_REASON_LINK_DOWN:
731 cnss_reason = CNSS_REASON_LINK_DOWN;
732 break;
733 default:
734 cnss_reason = CNSS_REASON_DEFAULT;
735 break;
736 }
737 cnss_schedule_recovery(dev, cnss_reason);
738}
739
740/**
741 * pld_pcie_device_self_recovery() - device self recovery
742 * @dev: device
743 * @reason: recovery reason
744 *
745 * Return: void
746 */
747void pld_pcie_device_self_recovery(struct device *dev,
748 enum pld_recovery_reason reason)
749{
750 enum cnss_recovery_reason cnss_reason;
751
752 switch (reason) {
753 case PLD_REASON_LINK_DOWN:
754 cnss_reason = CNSS_REASON_LINK_DOWN;
755 break;
756 default:
757 cnss_reason = CNSS_REASON_DEFAULT;
758 break;
759 }
760 cnss_self_recovery(dev, cnss_reason);
761}
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800762#endif
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800763#endif