blob: 5442b1009ae8a68bab1713035394f1e7f453bc07 [file] [log] [blame]
Yuanyuan Liud9f7a362016-01-22 14:27:12 -08001/*
Manikandan Mohan04459b92018-02-23 16:32:48 -08002 * Copyright (c) 2016-2018 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
Yuanyuan Liu5e25f532016-05-25 16:26:40 -070062 ret = pld_add_dev(pld_context, &pdev->dev, PLD_BUS_TYPE_PCIE);
63 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:
195 data.uevent = PLD_RECOVERY;
196 break;
197 default:
198 goto out;
199 }
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530200
Will Huangbdd28712017-06-21 11:02:39 +0800201 if (pld_context->ops->uevent)
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530202 pld_context->ops->uevent(&pdev->dev, &data);
203
Yue Ma096189d2017-09-13 11:14:59 -0700204out:
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530205 return;
Yuanyuan Liu06a342f2017-01-12 16:48:19 -0800206}
207
Yuanyuan Liud698eb62016-04-11 11:43:30 -0700208#ifdef FEATURE_RUNTIME_PM
209/**
210 * pld_pcie_runtime_suspend() - PM runtime suspend
211 * @pdev: PCIE device
212 *
213 * PM runtime suspend callback function.
214 *
215 * Return: int
216 */
217static int pld_pcie_runtime_suspend(struct pci_dev *pdev)
218{
219 struct pld_context *pld_context;
220
221 pld_context = pld_get_global_context();
222 if (pld_context->ops->runtime_suspend)
223 return pld_context->ops->runtime_suspend(&pdev->dev,
224 PLD_BUS_TYPE_PCIE);
225
226 return -ENODEV;
227}
228
229/**
230 * pld_pcie_runtime_resume() - PM runtime resume
231 * @pdev: PCIE device
232 *
233 * PM runtime resume callback function.
234 *
235 * Return: int
236 */
237static int pld_pcie_runtime_resume(struct pci_dev *pdev)
238{
239 struct pld_context *pld_context;
240
241 pld_context = pld_get_global_context();
242 if (pld_context->ops->runtime_resume)
243 return pld_context->ops->runtime_resume(&pdev->dev,
244 PLD_BUS_TYPE_PCIE);
245
246 return -ENODEV;
247}
248#endif
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800249#endif
250
Yuanyuan Liu25c66e12016-05-13 10:17:46 -0700251#ifdef CONFIG_PM
Yue Ma52d355c2017-01-25 14:49:23 -0800252#ifdef CONFIG_PLD_PCIE_CNSS
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800253/**
254 * pld_pcie_suspend() - Suspend callback function for power management
255 * @pdev: PCIE device
256 * @state: power state
257 *
258 * This function is to suspend the PCIE device when power management is
259 * enabled.
260 *
261 * Return: void
262 */
263static int pld_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
264{
265 struct pld_context *pld_context;
266
267 pld_context = pld_get_global_context();
268 return pld_context->ops->suspend(&pdev->dev,
269 PLD_BUS_TYPE_PCIE, state);
270}
271
272/**
273 * pld_pcie_resume() - Resume callback function for power management
274 * @pdev: PCIE device
275 *
276 * This function is to resume the PCIE device when power management is
277 * enabled.
278 *
279 * Return: void
280 */
281static int pld_pcie_resume(struct pci_dev *pdev)
282{
283 struct pld_context *pld_context;
284
285 pld_context = pld_get_global_context();
286 return pld_context->ops->resume(&pdev->dev, PLD_BUS_TYPE_PCIE);
287}
Yue Mae42c8452017-01-06 17:28:28 -0800288
289/**
290 * pld_pcie_suspend_noirq() - Complete the actions started by suspend()
291 * @pdev: PCI device
292 *
293 * Complete the actions started by suspend(). Carry out any additional
294 * operations required for suspending the device that might be racing
295 * with its driver's interrupt handler, which is guaranteed not to run
296 * while suspend_noirq() is being executed.
297 *
298 * Return: 0 for success
299 * Non zero failure code for errors
300 */
301static int pld_pcie_suspend_noirq(struct pci_dev *pdev)
302{
303 struct pld_context *pld_context;
304
305 pld_context = pld_get_global_context();
306 if (!pld_context)
307 return -EINVAL;
308
309 if (pld_context->ops->suspend_noirq)
310 return pld_context->ops->
311 suspend_noirq(&pdev->dev, PLD_BUS_TYPE_PCIE);
312 return 0;
313}
314
315/**
316 * pld_pcie_resume_noirq() - Prepare for the execution of resume()
317 * @pdev: PCI device
318 *
319 * Prepare for the execution of resume() by carrying out any additional
320 * operations required for resuming the device that might be racing with
321 * its driver's interrupt handler, which is guaranteed not to run while
322 * resume_noirq() is being executed.
323 *
324 * Return: 0 for success
325 * Non zero failure code for errors
326 */
327static int pld_pcie_resume_noirq(struct pci_dev *pdev)
328{
329 struct pld_context *pld_context;
330
331 pld_context = pld_get_global_context();
332 if (!pld_context)
333 return -EINVAL;
334
335 if (pld_context->ops->resume_noirq)
336 return pld_context->ops->
337 resume_noirq(&pdev->dev, PLD_BUS_TYPE_PCIE);
338 return 0;
339}
Yue Ma52d355c2017-01-25 14:49:23 -0800340#else
341/**
342 * pld_pcie_pm_suspend() - Suspend callback function for power management
343 * @dev: device
344 *
345 * This function is to suspend the PCIE device when power management is
346 * enabled.
347 *
348 * Return: 0 for success
349 * Non zero failure code for errors
350 */
351static int pld_pcie_pm_suspend(struct device *dev)
352{
353 struct pld_context *pld_context;
354
355 pm_message_t state = { .event = PM_EVENT_SUSPEND };
356
357 pld_context = pld_get_global_context();
358 return pld_context->ops->suspend(dev, PLD_BUS_TYPE_PCIE, state);
359}
360
361/**
362 * pld_pcie_pm_resume() - Resume callback function for power management
363 * @dev: device
364 *
365 * This function is to resume the PCIE device when power management is
366 * enabled.
367 *
368 * Return: 0 for success
369 * Non zero failure code for errors
370 */
371static int pld_pcie_pm_resume(struct device *dev)
372{
373 struct pld_context *pld_context;
374
375 pld_context = pld_get_global_context();
376 return pld_context->ops->resume(dev, PLD_BUS_TYPE_PCIE);
377}
378
379/**
380 * pld_pcie_pm_suspend_noirq() - Complete the actions started by suspend()
381 * @dev: device
382 *
383 * Complete the actions started by suspend(). Carry out any additional
384 * operations required for suspending the device that might be racing
385 * with its driver's interrupt handler, which is guaranteed not to run
386 * while suspend_noirq() is being executed.
387 *
388 * Return: 0 for success
389 * Non zero failure code for errors
390 */
391static int pld_pcie_pm_suspend_noirq(struct device *dev)
392{
393 struct pld_context *pld_context;
394
395 pld_context = pld_get_global_context();
396 if (!pld_context)
397 return -EINVAL;
398
399 if (pld_context->ops->suspend_noirq)
400 return pld_context->ops->suspend_noirq(dev, PLD_BUS_TYPE_PCIE);
401 return 0;
402}
403
404/**
405 * pld_pcie_pm_resume_noirq() - Prepare for the execution of resume()
406 * @dev: device
407 *
408 * Prepare for the execution of resume() by carrying out any additional
409 * operations required for resuming the device that might be racing with
410 * its driver's interrupt handler, which is guaranteed not to run while
411 * resume_noirq() is being executed.
412 *
413 * Return: 0 for success
414 * Non zero failure code for errors
415 */
416static int pld_pcie_pm_resume_noirq(struct device *dev)
417{
418 struct pld_context *pld_context;
419
420 pld_context = pld_get_global_context();
421 if (!pld_context)
422 return -EINVAL;
423
424 if (pld_context->ops->resume_noirq)
425 return pld_context->ops->
426 resume_noirq(dev, PLD_BUS_TYPE_PCIE);
427 return 0;
428}
429#endif
Yuanyuan Liu25c66e12016-05-13 10:17:46 -0700430#endif
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800431
432static struct pci_device_id pld_pcie_id_table[] = {
433 { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID },
434 { 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID },
435 { 0x168c, 0x0041, PCI_ANY_ID, PCI_ANY_ID },
436 { 0x168c, 0xabcd, PCI_ANY_ID, PCI_ANY_ID },
437 { 0x168c, 0x7021, PCI_ANY_ID, PCI_ANY_ID },
438 { 0 }
439};
440
Manikandan Mohan04459b92018-02-23 16:32:48 -0800441#ifdef MULTI_IF_NAME
442#define PLD_PCIE_OPS_NAME "pld_pcie_" MULTI_IF_NAME
443#else
444#define PLD_PCIE_OPS_NAME "pld_pcie"
445#endif
446
Yuanyuan Liu11f526a2016-05-18 10:22:07 -0700447#ifdef CONFIG_PLD_PCIE_CNSS
Yuanyuan Liud698eb62016-04-11 11:43:30 -0700448#ifdef FEATURE_RUNTIME_PM
449struct cnss_wlan_runtime_ops runtime_pm_ops = {
450 .runtime_suspend = pld_pcie_runtime_suspend,
451 .runtime_resume = pld_pcie_runtime_resume,
452};
453#endif
454
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800455struct cnss_wlan_driver pld_pcie_ops = {
Manikandan Mohan04459b92018-02-23 16:32:48 -0800456 .name = PLD_PCIE_OPS_NAME,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800457 .id_table = pld_pcie_id_table,
458 .probe = pld_pcie_probe,
459 .remove = pld_pcie_remove,
460 .reinit = pld_pcie_reinit,
461 .shutdown = pld_pcie_shutdown,
462 .crash_shutdown = pld_pcie_crash_shutdown,
463 .modem_status = pld_pcie_notify_handler,
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +0530464 .update_status = pld_pcie_uevent,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800465#ifdef CONFIG_PM
466 .suspend = pld_pcie_suspend,
467 .resume = pld_pcie_resume,
Yue Mae42c8452017-01-06 17:28:28 -0800468 .suspend_noirq = pld_pcie_suspend_noirq,
469 .resume_noirq = pld_pcie_resume_noirq,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800470#endif
Yuanyuan Liud698eb62016-04-11 11:43:30 -0700471#ifdef FEATURE_RUNTIME_PM
472 .runtime_ops = &runtime_pm_ops,
473#endif
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800474};
475
476/**
477 * pld_pcie_register_driver() - Register PCIE device callback functions
478 *
479 * Return: int
480 */
481int pld_pcie_register_driver(void)
482{
483 return cnss_wlan_register_driver(&pld_pcie_ops);
484}
485
486/**
487 * pld_pcie_unregister_driver() - Unregister PCIE device callback functions
488 *
489 * Return: void
490 */
491void pld_pcie_unregister_driver(void)
492{
493 cnss_wlan_unregister_driver(&pld_pcie_ops);
494}
495#else
Yue Ma52d355c2017-01-25 14:49:23 -0800496#ifdef CONFIG_PM
497static const struct dev_pm_ops pld_pm_ops = {
498 SET_SYSTEM_SLEEP_PM_OPS(pld_pcie_pm_suspend, pld_pcie_pm_resume)
499 .suspend_noirq = pld_pcie_pm_suspend_noirq,
500 .resume_noirq = pld_pcie_pm_resume_noirq,
501};
502#endif
503
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800504struct pci_driver pld_pcie_ops = {
Manikandan Mohan04459b92018-02-23 16:32:48 -0800505 .name = PLD_PCIE_OPS_NAME,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800506 .id_table = pld_pcie_id_table,
507 .probe = pld_pcie_probe,
508 .remove = pld_pcie_remove,
Yue Ma52d355c2017-01-25 14:49:23 -0800509 .driver = {
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800510#ifdef CONFIG_PM
Yue Ma52d355c2017-01-25 14:49:23 -0800511 .pm = &pld_pm_ops,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800512#endif
Yue Ma52d355c2017-01-25 14:49:23 -0800513 },
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800514};
515
516int pld_pcie_register_driver(void)
517{
518 return pci_register_driver(&pld_pcie_ops);
519}
520
521void pld_pcie_unregister_driver(void)
522{
523 pci_unregister_driver(&pld_pcie_ops);
524}
525#endif
526
527/**
528 * pld_pcie_get_ce_id() - Get CE number for the provided IRQ
Yue Ma85761e62017-10-30 11:13:45 -0700529 * @dev: device
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800530 * @irq: IRQ number
531 *
532 * Return: CE number
533 */
Yue Ma85761e62017-10-30 11:13:45 -0700534int pld_pcie_get_ce_id(struct device *dev, int irq)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800535{
536 int ce_id = irq - 100;
Manikandan Mohan8cf50612017-04-10 13:23:32 -0700537
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800538 if (ce_id < CE_COUNT_MAX && ce_id >= 0)
539 return ce_id;
540
541 return -EINVAL;
542}
543
Yuanyuan Liu11f526a2016-05-18 10:22:07 -0700544#ifdef CONFIG_PLD_PCIE_CNSS
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800545/**
546 * pld_pcie_wlan_enable() - Enable WLAN
Yue Ma85761e62017-10-30 11:13:45 -0700547 * @dev: device
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800548 * @config: WLAN configuration data
549 * @mode: WLAN mode
550 * @host_version: host software version
551 *
552 * This function enables WLAN FW. It passed WLAN configuration data,
553 * WLAN mode and host software version to FW.
554 *
555 * Return: 0 for success
556 * Non zero failure code for errors
557 */
Yue Ma08047522016-11-08 18:53:26 -0800558int pld_pcie_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800559 enum pld_driver_mode mode, const char *host_version)
560{
561 struct cnss_wlan_enable_cfg cfg;
562 enum cnss_driver_mode cnss_mode;
563
564 cfg.num_ce_tgt_cfg = config->num_ce_tgt_cfg;
565 cfg.ce_tgt_cfg = (struct cnss_ce_tgt_pipe_cfg *)
566 config->ce_tgt_cfg;
567 cfg.num_ce_svc_pipe_cfg = config->num_ce_svc_pipe_cfg;
568 cfg.ce_svc_cfg = (struct cnss_ce_svc_pipe_cfg *)
569 config->ce_svc_cfg;
570 cfg.num_shadow_reg_cfg = config->num_shadow_reg_cfg;
571 cfg.shadow_reg_cfg = (struct cnss_shadow_reg_cfg *)
572 config->shadow_reg_cfg;
Yue Ma502a28f2017-01-03 16:38:44 -0800573 cfg.num_shadow_reg_v2_cfg = config->num_shadow_reg_v2_cfg;
574 cfg.shadow_reg_v2_cfg = (struct cnss_shadow_reg_v2_cfg *)
575 config->shadow_reg_v2_cfg;
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800576
577 switch (mode) {
578 case PLD_FTM:
579 cnss_mode = CNSS_FTM;
580 break;
581 case PLD_EPPING:
582 cnss_mode = CNSS_EPPING;
583 break;
584 default:
585 cnss_mode = CNSS_MISSION;
586 break;
587 }
Yue Ma08047522016-11-08 18:53:26 -0800588 return cnss_wlan_enable(dev, &cfg, cnss_mode, host_version);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800589}
590
591/**
592 * pld_pcie_wlan_disable() - Disable WLAN
Yue Ma85761e62017-10-30 11:13:45 -0700593 * @dev: device
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800594 * @mode: WLAN mode
595 *
596 * This function disables WLAN FW. It passes WLAN mode to FW.
597 *
598 * Return: 0 for success
599 * Non zero failure code for errors
600 */
Yue Ma08047522016-11-08 18:53:26 -0800601int pld_pcie_wlan_disable(struct device *dev, enum pld_driver_mode mode)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800602{
Yue Ma08047522016-11-08 18:53:26 -0800603 return cnss_wlan_disable(dev, CNSS_OFF);
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800604}
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800605
606/**
607 * pld_pcie_get_fw_files_for_target() - Get FW file names
Yue Ma85761e62017-10-30 11:13:45 -0700608 * @dev: device
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800609 * @pfw_files: buffer for FW file names
610 * @target_type: target type
611 * @target_version: target version
612 *
613 * Return target specific FW file names to the buffer.
614 *
615 * Return: 0 for success
616 * Non zero failure code for errors
617 */
Yue Ma85761e62017-10-30 11:13:45 -0700618int pld_pcie_get_fw_files_for_target(struct device *dev,
619 struct pld_fw_files *pfw_files,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800620 u32 target_type, u32 target_version)
621{
622 int ret = 0;
623 struct cnss_fw_files cnss_fw_files;
624
625 if (pfw_files == NULL)
626 return -ENODEV;
627
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700628 memset(pfw_files, 0, sizeof(*pfw_files));
629
Yue Ma85761e62017-10-30 11:13:45 -0700630 ret = cnss_get_fw_files_for_target(dev, &cnss_fw_files,
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800631 target_type, target_version);
Yue Ma85761e62017-10-30 11:13:45 -0700632 if (ret)
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800633 return ret;
634
Yuanyuan Liu6a313dc2016-05-10 14:19:10 -0700635 strlcpy(pfw_files->image_file, cnss_fw_files.image_file,
636 PLD_MAX_FILE_NAME);
637 strlcpy(pfw_files->board_data, cnss_fw_files.board_data,
638 PLD_MAX_FILE_NAME);
639 strlcpy(pfw_files->otp_data, cnss_fw_files.otp_data,
640 PLD_MAX_FILE_NAME);
641 strlcpy(pfw_files->utf_file, cnss_fw_files.utf_file,
642 PLD_MAX_FILE_NAME);
643 strlcpy(pfw_files->utf_board_data, cnss_fw_files.utf_board_data,
644 PLD_MAX_FILE_NAME);
645 strlcpy(pfw_files->epping_file, cnss_fw_files.epping_file,
646 PLD_MAX_FILE_NAME);
647 strlcpy(pfw_files->evicted_data, cnss_fw_files.evicted_data,
648 PLD_MAX_FILE_NAME);
649
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800650 return 0;
651}
652
653/**
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800654 * pld_pcie_get_platform_cap() - Get platform capabilities
Yue Ma85761e62017-10-30 11:13:45 -0700655 * @dev: device
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800656 * @cap: buffer to the capabilities
657 *
658 * Return capabilities to the buffer.
659 *
660 * Return: 0 for success
661 * Non zero failure code for errors
662 */
Yue Ma85761e62017-10-30 11:13:45 -0700663int pld_pcie_get_platform_cap(struct device *dev, struct pld_platform_cap *cap)
664{
665 int ret = 0;
666 struct cnss_platform_cap cnss_cap;
667
668 if (cap == NULL)
669 return -ENODEV;
670
671 ret = cnss_get_platform_cap(dev, &cnss_cap);
672 if (ret)
673 return ret;
674
675 memcpy(cap, &cnss_cap, sizeof(*cap));
676 return 0;
677}
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800678
679/**
Yue Macd243862016-11-04 19:21:16 -0700680 * pld_pcie_get_soc_info() - Get SOC information
Yue Ma85761e62017-10-30 11:13:45 -0700681 * @dev: device
Yue Macd243862016-11-04 19:21:16 -0700682 * @info: buffer to SOC information
683 *
684 * Return SOC info to the buffer.
685 *
686 * Return: 0 for success
687 * Non zero failure code for errors
688 */
689int pld_pcie_get_soc_info(struct device *dev, struct pld_soc_info *info)
690{
691 int ret = 0;
lihual8b9daf22018-04-02 15:18:54 +0800692 struct cnss_soc_info cnss_info = {0};
Yue Macd243862016-11-04 19:21:16 -0700693
694 if (info == NULL)
695 return -ENODEV;
696
697 ret = cnss_get_soc_info(dev, &cnss_info);
698 if (ret)
699 return ret;
700
Frank Liu0e7ac562018-06-15 15:29:49 +0800701 info->v_addr = cnss_info.va;
702 info->p_addr = cnss_info.pa;
703 info->chip_id = cnss_info.chip_id;
704 info->chip_family = cnss_info.chip_family;
705 info->board_id = cnss_info.board_id;
706 info->soc_id = cnss_info.soc_id;
707 info->fw_version = cnss_info.fw_version;
708 strlcpy(info->fw_build_timestamp, cnss_info.fw_build_timestamp,
709 sizeof(info->fw_build_timestamp));
Yue Macd243862016-11-04 19:21:16 -0700710
711 return 0;
712}
713
714/**
Yuanyuan Liu10fc3d32017-01-12 15:32:06 -0800715 * pld_pcie_schedule_recovery_work() - schedule recovery work
716 * @dev: device
717 * @reason: recovery reason
718 *
719 * Return: void
720 */
721void pld_pcie_schedule_recovery_work(struct device *dev,
722 enum pld_recovery_reason reason)
723{
724 enum cnss_recovery_reason cnss_reason;
725
726 switch (reason) {
727 case PLD_REASON_LINK_DOWN:
728 cnss_reason = CNSS_REASON_LINK_DOWN;
729 break;
730 default:
731 cnss_reason = CNSS_REASON_DEFAULT;
732 break;
733 }
734 cnss_schedule_recovery(dev, cnss_reason);
735}
736
737/**
738 * pld_pcie_device_self_recovery() - device self recovery
739 * @dev: device
740 * @reason: recovery reason
741 *
742 * Return: void
743 */
744void pld_pcie_device_self_recovery(struct device *dev,
745 enum pld_recovery_reason reason)
746{
747 enum cnss_recovery_reason cnss_reason;
748
749 switch (reason) {
750 case PLD_REASON_LINK_DOWN:
751 cnss_reason = CNSS_REASON_LINK_DOWN;
752 break;
753 default:
754 cnss_reason = CNSS_REASON_DEFAULT;
755 break;
756 }
757 cnss_self_recovery(dev, cnss_reason);
758}
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800759#endif
Yuanyuan Liud9f7a362016-01-22 14:27:12 -0800760#endif