blob: 161e68eefa6530606404e0d88c91bd6e31974380 [file] [log] [blame]
Yue Ma4dac45d2018-02-23 11:49:25 -08001/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
Yue Ma0317e4a2018-01-10 11:48:32 -08002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/firmware.h>
14#include <linux/irq.h>
15#include <linux/module.h>
16#include <linux/msi.h>
17#include <linux/of.h>
18#include <linux/pm_runtime.h>
Yue Ma3eb55622018-02-22 12:14:00 -080019#include <linux/memblock.h>
Yue Mae83a0eff2018-05-04 14:15:54 -070020#include <soc/qcom/ramdump.h>
Yue Ma0317e4a2018-01-10 11:48:32 -080021
22#include "main.h"
Yue Mafcf60422018-05-01 16:59:56 -070023#include "bus.h"
Yue Ma0317e4a2018-01-10 11:48:32 -080024#include "debug.h"
25#include "pci.h"
26
27#define PCI_LINK_UP 1
28#define PCI_LINK_DOWN 0
29
30#define SAVE_PCI_CONFIG_SPACE 1
31#define RESTORE_PCI_CONFIG_SPACE 0
32
33#define PM_OPTIONS_DEFAULT 0
34#define PM_OPTIONS_LINK_DOWN \
35 (MSM_PCIE_CONFIG_NO_CFG_RESTORE | MSM_PCIE_CONFIG_LINKDOWN)
36
37#define PCI_BAR_NUM 0
38
Yue Ma3eb55622018-02-22 12:14:00 -080039#define PCI_DMA_MASK_32_BIT 32
40#define PCI_DMA_MASK_64_BIT 64
Yue Ma0317e4a2018-01-10 11:48:32 -080041
42#define MHI_NODE_NAME "qcom,mhi"
Yue Ma3eb55622018-02-22 12:14:00 -080043#define MHI_MSI_NAME "MHI"
Yue Ma0317e4a2018-01-10 11:48:32 -080044
45#define MAX_M3_FILE_NAME_LENGTH 13
46#define DEFAULT_M3_FILE_NAME "m3.bin"
Yue Mab74e6f32018-06-13 18:39:58 -070047#define DEFAULT_FW_FILE_NAME "amss.bin"
Yue Ma0317e4a2018-01-10 11:48:32 -080048
Yue Mafcf60422018-05-01 16:59:56 -070049#define WAKE_MSI_NAME "WAKE"
50
51#define FW_ASSERT_TIMEOUT 5000
52
Yue Ma0317e4a2018-01-10 11:48:32 -080053static DEFINE_SPINLOCK(pci_link_down_lock);
54
55static unsigned int pci_link_down_panic;
56module_param(pci_link_down_panic, uint, 0600);
57MODULE_PARM_DESC(pci_link_down_panic,
58 "Trigger kernel panic when PCI link down is detected");
59
60static bool fbc_bypass;
61#ifdef CONFIG_CNSS2_DEBUG
62module_param(fbc_bypass, bool, 0600);
63MODULE_PARM_DESC(fbc_bypass,
64 "Bypass firmware download when loading WLAN driver");
65#endif
66
67static int cnss_set_pci_config_space(struct cnss_pci_data *pci_priv, bool save)
68{
69 struct pci_dev *pci_dev = pci_priv->pci_dev;
70 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
71 bool link_down_or_recovery;
72
73 if (!plat_priv)
74 return -ENODEV;
75
76 link_down_or_recovery = pci_priv->pci_link_down_ind ||
77 (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state));
78
79 if (save) {
80 if (link_down_or_recovery) {
81 pci_priv->saved_state = NULL;
82 } else {
83 pci_save_state(pci_dev);
84 pci_priv->saved_state = pci_store_saved_state(pci_dev);
85 }
86 } else {
87 if (link_down_or_recovery) {
88 pci_load_saved_state(pci_dev, pci_priv->default_state);
89 pci_restore_state(pci_dev);
90 } else if (pci_priv->saved_state) {
91 pci_load_and_free_saved_state(pci_dev,
92 &pci_priv->saved_state);
93 pci_restore_state(pci_dev);
94 }
95 }
96
97 return 0;
98}
99
100static int cnss_set_pci_link(struct cnss_pci_data *pci_priv, bool link_up)
101{
102 int ret = 0;
103 struct pci_dev *pci_dev = pci_priv->pci_dev;
104
105 ret = msm_pcie_pm_control(link_up ? MSM_PCIE_RESUME :
106 MSM_PCIE_SUSPEND,
107 pci_dev->bus->number,
108 pci_dev, NULL,
109 PM_OPTIONS_DEFAULT);
110 if (ret) {
111 cnss_pr_err("Failed to %s PCI link with default option, err = %d\n",
112 link_up ? "resume" : "suspend", ret);
113 return ret;
114 }
115
116 return 0;
117}
118
119int cnss_suspend_pci_link(struct cnss_pci_data *pci_priv)
120{
121 int ret = 0;
122
123 if (!pci_priv)
124 return -ENODEV;
125
126 cnss_pr_dbg("Suspending PCI link\n");
127 if (!pci_priv->pci_link_state) {
128 cnss_pr_info("PCI link is already suspended!\n");
129 goto out;
130 }
131
132 ret = cnss_set_pci_config_space(pci_priv, SAVE_PCI_CONFIG_SPACE);
133 if (ret)
134 goto out;
135
136 pci_disable_device(pci_priv->pci_dev);
137
138 if (pci_priv->pci_dev->device != QCA6174_DEVICE_ID) {
139 if (pci_set_power_state(pci_priv->pci_dev, PCI_D3hot))
140 cnss_pr_err("Failed to set D3Hot, err = %d\n", ret);
141 }
142
143 ret = cnss_set_pci_link(pci_priv, PCI_LINK_DOWN);
144 if (ret)
145 goto out;
146
147 pci_priv->pci_link_state = PCI_LINK_DOWN;
148
149 return 0;
150out:
151 return ret;
152}
153
154int cnss_resume_pci_link(struct cnss_pci_data *pci_priv)
155{
156 int ret = 0;
157
158 if (!pci_priv)
159 return -ENODEV;
160
161 cnss_pr_dbg("Resuming PCI link\n");
162 if (pci_priv->pci_link_state) {
163 cnss_pr_info("PCI link is already resumed!\n");
164 goto out;
165 }
166
167 ret = cnss_set_pci_link(pci_priv, PCI_LINK_UP);
168 if (ret)
169 goto out;
170
171 pci_priv->pci_link_state = PCI_LINK_UP;
172
Yue Ma3eb55622018-02-22 12:14:00 -0800173 if (pci_priv->pci_dev->device != QCA6174_DEVICE_ID) {
174 ret = pci_set_power_state(pci_priv->pci_dev, PCI_D0);
175 if (ret) {
176 cnss_pr_err("Failed to set D0, err = %d\n", ret);
177 goto out;
178 }
179 }
180
Yue Ma0317e4a2018-01-10 11:48:32 -0800181 ret = cnss_set_pci_config_space(pci_priv, RESTORE_PCI_CONFIG_SPACE);
182 if (ret)
183 goto out;
184
185 ret = pci_enable_device(pci_priv->pci_dev);
186 if (ret) {
187 cnss_pr_err("Failed to enable PCI device, err = %d\n", ret);
188 goto out;
189 }
190
191 pci_set_master(pci_priv->pci_dev);
192
193 if (pci_priv->pci_link_down_ind)
194 pci_priv->pci_link_down_ind = false;
195
196 return 0;
197out:
198 return ret;
199}
200
201int cnss_pci_link_down(struct device *dev)
202{
203 unsigned long flags;
204 struct pci_dev *pci_dev = to_pci_dev(dev);
205 struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
206
207 if (!pci_priv) {
208 cnss_pr_err("pci_priv is NULL!\n");
209 return -EINVAL;
210 }
211
212 if (pci_link_down_panic)
213 panic("cnss: PCI link is down!\n");
214
215 spin_lock_irqsave(&pci_link_down_lock, flags);
216 if (pci_priv->pci_link_down_ind) {
217 cnss_pr_dbg("PCI link down recovery is in progress, ignore!\n");
218 spin_unlock_irqrestore(&pci_link_down_lock, flags);
219 return -EINVAL;
220 }
221 pci_priv->pci_link_down_ind = true;
222 spin_unlock_irqrestore(&pci_link_down_lock, flags);
223
224 cnss_pr_err("PCI link down is detected by host driver, schedule recovery!\n");
225
Yue Ma0317e4a2018-01-10 11:48:32 -0800226 cnss_schedule_recovery(dev, CNSS_REASON_LINK_DOWN);
227
228 return 0;
229}
230EXPORT_SYMBOL(cnss_pci_link_down);
231
Yue Mae83a0eff2018-05-04 14:15:54 -0700232int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv)
233{
234 int ret = 0;
235 struct cnss_plat_data *plat_priv;
236
237 if (!pci_priv)
238 return -ENODEV;
239
240 plat_priv = pci_priv->plat_priv;
241
242 if (test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
243 clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
244 cnss_pr_dbg("Skip driver probe\n");
245 goto out;
246 }
247
248 if (!pci_priv->driver_ops) {
249 cnss_pr_err("driver_ops is NULL\n");
250 ret = -EINVAL;
251 goto out;
252 }
253
254 if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
255 test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
256 ret = pci_priv->driver_ops->reinit(pci_priv->pci_dev,
257 pci_priv->pci_device_id);
258 if (ret) {
259 cnss_pr_err("Failed to reinit host driver, err = %d\n",
260 ret);
261 goto out;
262 }
263 clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
264 } else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state)) {
265 ret = pci_priv->driver_ops->probe(pci_priv->pci_dev,
266 pci_priv->pci_device_id);
267 if (ret) {
268 cnss_pr_err("Failed to probe host driver, err = %d\n",
269 ret);
270 goto out;
271 }
272 clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
273 clear_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
274 set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
275 }
276
277 return 0;
278
279out:
280 return ret;
281}
282
283int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv)
284{
285 struct cnss_plat_data *plat_priv;
286
287 if (!pci_priv)
288 return -ENODEV;
289
290 plat_priv = pci_priv->plat_priv;
291
292 if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state) ||
293 test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state) ||
294 test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
295 cnss_pr_dbg("Skip driver remove\n");
296 return 0;
297 }
298
299 if (!pci_priv->driver_ops) {
300 cnss_pr_err("driver_ops is NULL\n");
301 return -EINVAL;
302 }
303
304 if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
305 test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
306 pci_priv->driver_ops->shutdown(pci_priv->pci_dev);
307 } else if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) {
308 pci_priv->driver_ops->remove(pci_priv->pci_dev);
309 clear_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
310 }
311
312 return 0;
313}
314
315int cnss_pci_call_driver_modem_status(struct cnss_pci_data *pci_priv,
316 int modem_current_status)
317{
318 struct cnss_wlan_driver *driver_ops;
319
320 if (!pci_priv)
321 return -ENODEV;
322
323 driver_ops = pci_priv->driver_ops;
324 if (!driver_ops || !driver_ops->modem_status)
325 return -EINVAL;
326
327 driver_ops->modem_status(pci_priv->pci_dev, modem_current_status);
328
329 return 0;
330}
331
332static int cnss_qca6174_powerup(struct cnss_pci_data *pci_priv)
333{
334 int ret = 0;
335 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
336
337 ret = cnss_power_on_device(plat_priv);
338 if (ret) {
339 cnss_pr_err("Failed to power on device, err = %d\n", ret);
340 goto out;
341 }
342
343 ret = cnss_resume_pci_link(pci_priv);
344 if (ret) {
345 cnss_pr_err("Failed to resume PCI link, err = %d\n", ret);
346 goto power_off;
347 }
348
349 ret = cnss_pci_call_driver_probe(pci_priv);
350 if (ret)
351 goto suspend_link;
352
353 return 0;
354suspend_link:
355 cnss_suspend_pci_link(pci_priv);
356power_off:
357 cnss_power_off_device(plat_priv);
358out:
359 return ret;
360}
361
362static int cnss_qca6174_shutdown(struct cnss_pci_data *pci_priv)
363{
364 int ret = 0;
365 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
366
367 cnss_pm_request_resume(pci_priv);
368
369 cnss_pci_call_driver_remove(pci_priv);
370
371 cnss_request_bus_bandwidth(&plat_priv->plat_dev->dev,
372 CNSS_BUS_WIDTH_NONE);
373 cnss_pci_set_monitor_wake_intr(pci_priv, false);
374 cnss_pci_set_auto_suspended(pci_priv, 0);
375
376 ret = cnss_suspend_pci_link(pci_priv);
377 if (ret)
378 cnss_pr_err("Failed to suspend PCI link, err = %d\n", ret);
379
380 cnss_power_off_device(plat_priv);
381
382 clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
383
384 return ret;
385}
386
387static void cnss_qca6174_crash_shutdown(struct cnss_pci_data *pci_priv)
388{
389 if (pci_priv->driver_ops && pci_priv->driver_ops->crash_shutdown)
390 pci_priv->driver_ops->crash_shutdown(pci_priv->pci_dev);
391}
392
393static int cnss_qca6174_ramdump(struct cnss_pci_data *pci_priv)
394{
395 int ret = 0;
396 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
397 struct cnss_ramdump_info *ramdump_info;
398 struct ramdump_segment segment;
399
400 ramdump_info = &plat_priv->ramdump_info;
401 if (!ramdump_info->ramdump_size)
402 return -EINVAL;
403
404 memset(&segment, 0, sizeof(segment));
405 segment.v_address = ramdump_info->ramdump_va;
406 segment.size = ramdump_info->ramdump_size;
407 ret = do_ramdump(ramdump_info->ramdump_dev, &segment, 1);
408
409 return ret;
410}
411
412static int cnss_qca6290_powerup(struct cnss_pci_data *pci_priv)
413{
414 int ret = 0;
415 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
416 unsigned int timeout;
417
418 if (plat_priv->ramdump_info_v2.dump_data_valid ||
419 test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
420 cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_DEINIT);
421 cnss_pci_clear_dump_info(pci_priv);
422 }
423
424 ret = cnss_power_on_device(plat_priv);
425 if (ret) {
426 cnss_pr_err("Failed to power on device, err = %d\n", ret);
427 goto out;
428 }
429
430 ret = cnss_resume_pci_link(pci_priv);
431 if (ret) {
432 cnss_pr_err("Failed to resume PCI link, err = %d\n", ret);
433 goto power_off;
434 }
435
Yue Mab79d4862018-07-11 12:32:12 -0700436 timeout = cnss_get_boot_timeout(&pci_priv->pci_dev->dev);
Yue Mae83a0eff2018-05-04 14:15:54 -0700437
438 ret = cnss_pci_start_mhi(pci_priv);
439 if (ret) {
440 cnss_pr_err("Failed to start MHI, err = %d\n", ret);
441 if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state) &&
442 !pci_priv->pci_link_down_ind && timeout)
443 mod_timer(&plat_priv->fw_boot_timer,
444 jiffies + msecs_to_jiffies(timeout >> 1));
445 return 0;
446 }
447
448 if (test_bit(USE_CORE_ONLY_FW, cnss_get_debug_quirks())) {
449 clear_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state);
450 clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
451 return 0;
452 }
453
454 cnss_set_pin_connect_status(plat_priv);
455
456 if (*cnss_get_qmi_bypass()) {
457 ret = cnss_pci_call_driver_probe(pci_priv);
458 if (ret)
459 goto stop_mhi;
460 } else if (timeout) {
461 mod_timer(&plat_priv->fw_boot_timer,
462 jiffies + msecs_to_jiffies(timeout << 1));
463 }
464
465 return 0;
466
467stop_mhi:
468 cnss_pci_stop_mhi(pci_priv);
469 cnss_suspend_pci_link(pci_priv);
470power_off:
471 cnss_power_off_device(plat_priv);
472out:
473 return ret;
474}
475
476static int cnss_qca6290_shutdown(struct cnss_pci_data *pci_priv)
477{
478 int ret = 0;
479 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
480
481 cnss_pm_request_resume(pci_priv);
482
483 cnss_pci_call_driver_remove(pci_priv);
484
485 cnss_request_bus_bandwidth(&plat_priv->plat_dev->dev,
486 CNSS_BUS_WIDTH_NONE);
487 cnss_pci_set_monitor_wake_intr(pci_priv, false);
488 cnss_pci_set_auto_suspended(pci_priv, 0);
489
490 cnss_pci_stop_mhi(pci_priv);
491
492 ret = cnss_suspend_pci_link(pci_priv);
493 if (ret)
494 cnss_pr_err("Failed to suspend PCI link, err = %d\n", ret);
495
496 cnss_power_off_device(plat_priv);
497
498 clear_bit(CNSS_FW_READY, &plat_priv->driver_state);
499 clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
500 clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
501
502 return ret;
503}
504
505static void cnss_qca6290_crash_shutdown(struct cnss_pci_data *pci_priv)
506{
507 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
508
509 cnss_pr_dbg("Crash shutdown with driver_state 0x%lx\n",
510 plat_priv->driver_state);
511
512 if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
513 cnss_pr_dbg("Ignore crash shutdown\n");
514 return;
515 }
516
517 cnss_pci_collect_dump_info(pci_priv, true);
518}
519
520static int cnss_qca6290_ramdump(struct cnss_pci_data *pci_priv)
521{
522 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
523 struct cnss_ramdump_info_v2 *info_v2 = &plat_priv->ramdump_info_v2;
524 struct cnss_dump_data *dump_data = &info_v2->dump_data;
525 struct cnss_dump_seg *dump_seg = info_v2->dump_data_vaddr;
526 struct ramdump_segment *ramdump_segs, *s;
527 int i, ret = 0;
528
529 if (!info_v2->dump_data_valid ||
530 dump_data->nentries == 0)
531 return 0;
532
533 ramdump_segs = kcalloc(dump_data->nentries,
534 sizeof(*ramdump_segs),
535 GFP_KERNEL);
536 if (!ramdump_segs)
537 return -ENOMEM;
538
539 s = ramdump_segs;
540 for (i = 0; i < dump_data->nentries; i++) {
541 s->address = dump_seg->address;
542 s->v_address = dump_seg->v_address;
543 s->size = dump_seg->size;
544 s++;
545 dump_seg++;
546 }
547
548 ret = do_elf_ramdump(info_v2->ramdump_dev, ramdump_segs,
549 dump_data->nentries);
550 kfree(ramdump_segs);
551
552 cnss_pci_set_mhi_state(plat_priv->bus_priv, CNSS_MHI_DEINIT);
553 cnss_pci_clear_dump_info(plat_priv->bus_priv);
554
555 return ret;
556}
557
558int cnss_pci_dev_powerup(struct cnss_pci_data *pci_priv)
559{
560 int ret = 0;
561
562 if (!pci_priv) {
563 cnss_pr_err("pci_priv is NULL\n");
564 return -ENODEV;
565 }
566
567 switch (pci_priv->device_id) {
568 case QCA6174_DEVICE_ID:
569 ret = cnss_qca6174_powerup(pci_priv);
570 break;
571 case QCA6290_EMULATION_DEVICE_ID:
572 case QCA6290_DEVICE_ID:
Yue Mab74e6f32018-06-13 18:39:58 -0700573 case QCA6390_EMULATION_DEVICE_ID:
574 case QCA6390_DEVICE_ID:
Yue Mae83a0eff2018-05-04 14:15:54 -0700575 ret = cnss_qca6290_powerup(pci_priv);
576 break;
577 default:
578 cnss_pr_err("Unknown device_id found: 0x%x\n",
579 pci_priv->device_id);
580 ret = -ENODEV;
581 }
582
583 return ret;
584}
585
586int cnss_pci_dev_shutdown(struct cnss_pci_data *pci_priv)
587{
588 int ret = 0;
589
590 if (!pci_priv) {
591 cnss_pr_err("pci_priv is NULL\n");
592 return -ENODEV;
593 }
594
595 switch (pci_priv->device_id) {
596 case QCA6174_DEVICE_ID:
597 ret = cnss_qca6174_shutdown(pci_priv);
598 break;
599 case QCA6290_EMULATION_DEVICE_ID:
600 case QCA6290_DEVICE_ID:
Yue Mab74e6f32018-06-13 18:39:58 -0700601 case QCA6390_EMULATION_DEVICE_ID:
602 case QCA6390_DEVICE_ID:
Yue Mae83a0eff2018-05-04 14:15:54 -0700603 ret = cnss_qca6290_shutdown(pci_priv);
604 break;
605 default:
606 cnss_pr_err("Unknown device_id found: 0x%x\n",
607 pci_priv->device_id);
608 ret = -ENODEV;
609 }
610
611 return ret;
612}
613
614int cnss_pci_dev_crash_shutdown(struct cnss_pci_data *pci_priv)
615{
616 int ret = 0;
617
618 if (!pci_priv) {
619 cnss_pr_err("pci_priv is NULL\n");
620 return -ENODEV;
621 }
622
623 switch (pci_priv->device_id) {
624 case QCA6174_DEVICE_ID:
625 cnss_qca6174_crash_shutdown(pci_priv);
626 break;
627 case QCA6290_EMULATION_DEVICE_ID:
628 case QCA6290_DEVICE_ID:
Yue Mab74e6f32018-06-13 18:39:58 -0700629 case QCA6390_EMULATION_DEVICE_ID:
630 case QCA6390_DEVICE_ID:
Yue Mae83a0eff2018-05-04 14:15:54 -0700631 cnss_qca6290_crash_shutdown(pci_priv);
632 break;
633 default:
634 cnss_pr_err("Unknown device_id found: 0x%x\n",
635 pci_priv->device_id);
636 ret = -ENODEV;
637 }
638
639 return ret;
640}
641
642int cnss_pci_dev_ramdump(struct cnss_pci_data *pci_priv)
643{
644 int ret = 0;
645
646 if (!pci_priv) {
647 cnss_pr_err("pci_priv is NULL\n");
648 return -ENODEV;
649 }
650
651 switch (pci_priv->device_id) {
652 case QCA6174_DEVICE_ID:
653 ret = cnss_qca6174_ramdump(pci_priv);
654 break;
655 case QCA6290_EMULATION_DEVICE_ID:
656 case QCA6290_DEVICE_ID:
Yue Mab74e6f32018-06-13 18:39:58 -0700657 case QCA6390_EMULATION_DEVICE_ID:
658 case QCA6390_DEVICE_ID:
Yue Mae83a0eff2018-05-04 14:15:54 -0700659 ret = cnss_qca6290_ramdump(pci_priv);
660 break;
661 default:
662 cnss_pr_err("Unknown device_id found: 0x%x\n",
663 pci_priv->device_id);
664 ret = -ENODEV;
665 }
666
667 return ret;
668}
669
670int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops)
671{
672 int ret = 0;
673 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
674 struct cnss_pci_data *pci_priv;
675
676 if (!plat_priv) {
677 cnss_pr_err("plat_priv is NULL\n");
678 return -ENODEV;
679 }
680
681 pci_priv = plat_priv->bus_priv;
682 if (!pci_priv) {
683 cnss_pr_err("pci_priv is NULL\n");
684 return -ENODEV;
685 }
686
687 if (pci_priv->driver_ops) {
688 cnss_pr_err("Driver has already registered\n");
689 return -EEXIST;
690 }
691
692 ret = cnss_driver_event_post(plat_priv,
693 CNSS_DRIVER_EVENT_REGISTER_DRIVER,
694 CNSS_EVENT_SYNC_UNINTERRUPTIBLE,
695 driver_ops);
696 return ret;
697}
698EXPORT_SYMBOL(cnss_wlan_register_driver);
699
700void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver_ops)
701{
702 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
703
704 if (!plat_priv) {
705 cnss_pr_err("plat_priv is NULL\n");
706 return;
707 }
708
709 cnss_driver_event_post(plat_priv,
710 CNSS_DRIVER_EVENT_UNREGISTER_DRIVER,
711 CNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL);
712}
713EXPORT_SYMBOL(cnss_wlan_unregister_driver);
714
715int cnss_pci_register_driver_hdlr(struct cnss_pci_data *pci_priv,
716 void *data)
717{
718 int ret = 0;
719 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
720
721 set_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
722 pci_priv->driver_ops = data;
723
724 ret = cnss_pci_dev_powerup(pci_priv);
725 if (ret) {
726 clear_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
727 pci_priv->driver_ops = NULL;
728 }
729
730 return ret;
731}
732
733int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv)
734{
735 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
736
737 set_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
738 cnss_pci_dev_shutdown(pci_priv);
739 pci_priv->driver_ops = NULL;
740
741 return 0;
742}
743
Yue Ma0317e4a2018-01-10 11:48:32 -0800744static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv)
745{
746 int ret = 0;
747 struct device *dev;
748 struct dma_iommu_mapping *mapping;
749 int atomic_ctx = 1;
750 int s1_bypass = 1;
Yue Ma4dac45d2018-02-23 11:49:25 -0800751 int fast = 1;
752
753 cnss_pr_dbg("Initializing SMMU\n");
Yue Ma0317e4a2018-01-10 11:48:32 -0800754
755 dev = &pci_priv->pci_dev->dev;
756
Yue Ma4dac45d2018-02-23 11:49:25 -0800757 mapping = arm_iommu_create_mapping(dev->bus,
Yue Ma0317e4a2018-01-10 11:48:32 -0800758 pci_priv->smmu_iova_start,
759 pci_priv->smmu_iova_len);
760 if (IS_ERR(mapping)) {
761 ret = PTR_ERR(mapping);
762 cnss_pr_err("Failed to create SMMU mapping, err = %d\n", ret);
763 goto out;
764 }
765
Yue Ma4dac45d2018-02-23 11:49:25 -0800766 if (pci_priv->smmu_s1_enable) {
767 cnss_pr_dbg("Enabling SMMU S1 stage\n");
Yue Ma0317e4a2018-01-10 11:48:32 -0800768
Yue Ma4dac45d2018-02-23 11:49:25 -0800769 ret = iommu_domain_set_attr(mapping->domain,
770 DOMAIN_ATTR_ATOMIC,
771 &atomic_ctx);
772 if (ret) {
773 pr_err("Failed to set SMMU atomic_ctx attribute, err = %d\n",
774 ret);
775 goto release_mapping;
776 }
777
778 ret = iommu_domain_set_attr(mapping->domain,
779 DOMAIN_ATTR_FAST,
780 &fast);
781 if (ret) {
782 pr_err("Failed to set SMMU fast attribute, err = %d\n",
783 ret);
784 goto release_mapping;
785 }
786 } else {
787 ret = iommu_domain_set_attr(mapping->domain,
788 DOMAIN_ATTR_S1_BYPASS,
789 &s1_bypass);
790 if (ret) {
791 pr_err("Failed to set SMMU s1_bypass attribute, err = %d\n",
792 ret);
793 goto release_mapping;
794 }
Yue Ma0317e4a2018-01-10 11:48:32 -0800795 }
796
797 ret = arm_iommu_attach_device(dev, mapping);
798 if (ret) {
799 pr_err("Failed to attach SMMU device, err = %d\n", ret);
800 goto release_mapping;
801 }
802
803 pci_priv->smmu_mapping = mapping;
804
805 return ret;
806release_mapping:
807 arm_iommu_release_mapping(mapping);
808out:
809 return ret;
810}
811
812static void cnss_pci_deinit_smmu(struct cnss_pci_data *pci_priv)
813{
814 arm_iommu_detach_device(&pci_priv->pci_dev->dev);
815 arm_iommu_release_mapping(pci_priv->smmu_mapping);
816
817 pci_priv->smmu_mapping = NULL;
818}
819
820static void cnss_pci_event_cb(struct msm_pcie_notify *notify)
821{
822 unsigned long flags;
823 struct pci_dev *pci_dev;
824 struct cnss_pci_data *pci_priv;
825
826 if (!notify)
827 return;
828
829 pci_dev = notify->user;
830 if (!pci_dev)
831 return;
832
833 pci_priv = cnss_get_pci_priv(pci_dev);
834 if (!pci_priv)
835 return;
836
837 switch (notify->event) {
838 case MSM_PCIE_EVENT_LINKDOWN:
839 if (pci_link_down_panic)
840 panic("cnss: PCI link is down!\n");
841
842 spin_lock_irqsave(&pci_link_down_lock, flags);
843 if (pci_priv->pci_link_down_ind) {
844 cnss_pr_dbg("PCI link down recovery is in progress, ignore!\n");
845 spin_unlock_irqrestore(&pci_link_down_lock, flags);
846 return;
847 }
848 pci_priv->pci_link_down_ind = true;
849 spin_unlock_irqrestore(&pci_link_down_lock, flags);
850
851 cnss_pr_err("PCI link down, schedule recovery!\n");
Yue Ma0317e4a2018-01-10 11:48:32 -0800852 if (pci_dev->device == QCA6174_DEVICE_ID)
853 disable_irq(pci_dev->irq);
854 cnss_schedule_recovery(&pci_dev->dev, CNSS_REASON_LINK_DOWN);
855 break;
856 case MSM_PCIE_EVENT_WAKEUP:
857 if (cnss_pci_get_monitor_wake_intr(pci_priv) &&
858 cnss_pci_get_auto_suspended(pci_priv)) {
859 cnss_pci_set_monitor_wake_intr(pci_priv, false);
860 pm_request_resume(&pci_dev->dev);
861 }
862 break;
863 default:
864 cnss_pr_err("Received invalid PCI event: %d\n", notify->event);
865 }
866}
867
868static int cnss_reg_pci_event(struct cnss_pci_data *pci_priv)
869{
870 int ret = 0;
871 struct msm_pcie_register_event *pci_event;
872
873 pci_event = &pci_priv->msm_pci_event;
874 pci_event->events = MSM_PCIE_EVENT_LINKDOWN |
875 MSM_PCIE_EVENT_WAKEUP;
876 pci_event->user = pci_priv->pci_dev;
877 pci_event->mode = MSM_PCIE_TRIGGER_CALLBACK;
878 pci_event->callback = cnss_pci_event_cb;
879 pci_event->options = MSM_PCIE_CONFIG_NO_RECOVERY;
880
881 ret = msm_pcie_register_event(pci_event);
882 if (ret)
883 cnss_pr_err("Failed to register MSM PCI event, err = %d\n",
884 ret);
885
886 return ret;
887}
888
889static void cnss_dereg_pci_event(struct cnss_pci_data *pci_priv)
890{
891 msm_pcie_deregister_event(&pci_priv->msm_pci_event);
892}
893
894static int cnss_pci_suspend(struct device *dev)
895{
896 int ret = 0;
897 struct pci_dev *pci_dev = to_pci_dev(dev);
898 struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
Yue Ma0317e4a2018-01-10 11:48:32 -0800899 struct cnss_wlan_driver *driver_ops;
900
901 pm_message_t state = { .event = PM_EVENT_SUSPEND };
902
903 if (!pci_priv)
904 goto out;
905
Yue Mae83a0eff2018-05-04 14:15:54 -0700906 driver_ops = pci_priv->driver_ops;
Yue Ma0317e4a2018-01-10 11:48:32 -0800907 if (driver_ops && driver_ops->suspend) {
908 ret = driver_ops->suspend(pci_dev, state);
909 if (ret) {
910 cnss_pr_err("Failed to suspend host driver, err = %d\n",
911 ret);
912 ret = -EAGAIN;
913 goto out;
914 }
915 }
916
Yue Mafad13942018-05-14 17:38:00 -0700917 if (pci_priv->pci_link_state == PCI_LINK_UP) {
Yue Ma0317e4a2018-01-10 11:48:32 -0800918 ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_SUSPEND);
919 if (ret) {
920 if (driver_ops && driver_ops->resume)
921 driver_ops->resume(pci_dev);
922 ret = -EAGAIN;
923 goto out;
924 }
925
926 cnss_set_pci_config_space(pci_priv,
927 SAVE_PCI_CONFIG_SPACE);
928 pci_disable_device(pci_dev);
929
930 ret = pci_set_power_state(pci_dev, PCI_D3hot);
931 if (ret)
932 cnss_pr_err("Failed to set D3Hot, err = %d\n",
933 ret);
934 }
935
936 cnss_pci_set_monitor_wake_intr(pci_priv, false);
937
938 return 0;
939
940out:
941 return ret;
942}
943
944static int cnss_pci_resume(struct device *dev)
945{
946 int ret = 0;
947 struct pci_dev *pci_dev = to_pci_dev(dev);
948 struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
Yue Ma0317e4a2018-01-10 11:48:32 -0800949 struct cnss_wlan_driver *driver_ops;
950
951 if (!pci_priv)
952 goto out;
953
Yue Ma0317e4a2018-01-10 11:48:32 -0800954 if (pci_priv->pci_link_down_ind)
955 goto out;
956
Yue Mafad13942018-05-14 17:38:00 -0700957 if (pci_priv->pci_link_state == PCI_LINK_UP) {
958 ret = pci_enable_device(pci_dev);
959 if (ret)
960 cnss_pr_err("Failed to enable PCI device, err = %d\n",
961 ret);
Yue Ma0317e4a2018-01-10 11:48:32 -0800962
Yue Mafad13942018-05-14 17:38:00 -0700963 if (pci_priv->saved_state)
964 cnss_set_pci_config_space(pci_priv,
965 RESTORE_PCI_CONFIG_SPACE);
Yue Ma0317e4a2018-01-10 11:48:32 -0800966
Yue Mafad13942018-05-14 17:38:00 -0700967 pci_set_master(pci_dev);
968 cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RESUME);
969 }
Yue Ma0317e4a2018-01-10 11:48:32 -0800970
Yue Mae83a0eff2018-05-04 14:15:54 -0700971 driver_ops = pci_priv->driver_ops;
Yue Ma0317e4a2018-01-10 11:48:32 -0800972 if (driver_ops && driver_ops->resume) {
973 ret = driver_ops->resume(pci_dev);
974 if (ret)
975 cnss_pr_err("Failed to resume host driver, err = %d\n",
976 ret);
977 }
978
979 return 0;
980
981out:
982 return ret;
983}
984
985static int cnss_pci_suspend_noirq(struct device *dev)
986{
987 int ret = 0;
988 struct pci_dev *pci_dev = to_pci_dev(dev);
989 struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
Yue Ma0317e4a2018-01-10 11:48:32 -0800990 struct cnss_wlan_driver *driver_ops;
991
992 if (!pci_priv)
993 goto out;
994
Yue Mae83a0eff2018-05-04 14:15:54 -0700995 driver_ops = pci_priv->driver_ops;
Yue Ma0317e4a2018-01-10 11:48:32 -0800996 if (driver_ops && driver_ops->suspend_noirq)
997 ret = driver_ops->suspend_noirq(pci_dev);
998
Yue Mafad13942018-05-14 17:38:00 -0700999 ret = cnss_set_pci_link(pci_priv, PCI_LINK_DOWN);
1000 if (ret)
1001 goto out;
1002 pci_priv->pci_link_state = PCI_LINK_DOWN;
1003
Yue Ma0317e4a2018-01-10 11:48:32 -08001004out:
1005 return ret;
1006}
1007
1008static int cnss_pci_resume_noirq(struct device *dev)
1009{
1010 int ret = 0;
1011 struct pci_dev *pci_dev = to_pci_dev(dev);
1012 struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
Yue Ma0317e4a2018-01-10 11:48:32 -08001013 struct cnss_wlan_driver *driver_ops;
1014
1015 if (!pci_priv)
1016 goto out;
1017
Yue Mafad13942018-05-14 17:38:00 -07001018 ret = cnss_set_pci_link(pci_priv, PCI_LINK_UP);
1019 if (ret)
Yue Ma0317e4a2018-01-10 11:48:32 -08001020 goto out;
Yue Mafad13942018-05-14 17:38:00 -07001021 pci_priv->pci_link_state = PCI_LINK_UP;
Yue Ma0317e4a2018-01-10 11:48:32 -08001022
Yue Mae83a0eff2018-05-04 14:15:54 -07001023 driver_ops = pci_priv->driver_ops;
Yue Ma0317e4a2018-01-10 11:48:32 -08001024 if (driver_ops && driver_ops->resume_noirq &&
1025 !pci_priv->pci_link_down_ind)
1026 ret = driver_ops->resume_noirq(pci_dev);
1027
1028out:
1029 return ret;
1030}
1031
1032static int cnss_pci_runtime_suspend(struct device *dev)
1033{
1034 int ret = 0;
1035 struct pci_dev *pci_dev = to_pci_dev(dev);
1036 struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
Yue Ma0317e4a2018-01-10 11:48:32 -08001037 struct cnss_wlan_driver *driver_ops;
1038
1039 if (!pci_priv)
1040 return -EAGAIN;
1041
Yue Ma0317e4a2018-01-10 11:48:32 -08001042 if (pci_priv->pci_link_down_ind) {
1043 cnss_pr_dbg("PCI link down recovery is in progress!\n");
1044 return -EAGAIN;
1045 }
1046
1047 cnss_pr_dbg("Runtime suspend start\n");
1048
Yue Mae83a0eff2018-05-04 14:15:54 -07001049 driver_ops = pci_priv->driver_ops;
Yue Ma0317e4a2018-01-10 11:48:32 -08001050 if (driver_ops && driver_ops->runtime_ops &&
1051 driver_ops->runtime_ops->runtime_suspend)
1052 ret = driver_ops->runtime_ops->runtime_suspend(pci_dev);
1053
1054 cnss_pr_info("Runtime suspend status: %d\n", ret);
1055
1056 return ret;
1057}
1058
1059static int cnss_pci_runtime_resume(struct device *dev)
1060{
1061 int ret = 0;
1062 struct pci_dev *pci_dev = to_pci_dev(dev);
1063 struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
Yue Ma0317e4a2018-01-10 11:48:32 -08001064 struct cnss_wlan_driver *driver_ops;
1065
1066 if (!pci_priv)
1067 return -EAGAIN;
1068
Yue Ma0317e4a2018-01-10 11:48:32 -08001069 if (pci_priv->pci_link_down_ind) {
1070 cnss_pr_dbg("PCI link down recovery is in progress!\n");
1071 return -EAGAIN;
1072 }
1073
1074 cnss_pr_dbg("Runtime resume start\n");
1075
Yue Mae83a0eff2018-05-04 14:15:54 -07001076 driver_ops = pci_priv->driver_ops;
Yue Ma0317e4a2018-01-10 11:48:32 -08001077 if (driver_ops && driver_ops->runtime_ops &&
1078 driver_ops->runtime_ops->runtime_resume)
1079 ret = driver_ops->runtime_ops->runtime_resume(pci_dev);
1080
1081 cnss_pr_info("Runtime resume status: %d\n", ret);
1082
1083 return ret;
1084}
1085
1086static int cnss_pci_runtime_idle(struct device *dev)
1087{
1088 cnss_pr_dbg("Runtime idle\n");
1089
1090 pm_request_autosuspend(dev);
1091
1092 return -EBUSY;
1093}
1094
1095int cnss_wlan_pm_control(struct device *dev, bool vote)
1096{
Yue Mafcf60422018-05-01 16:59:56 -07001097 struct pci_dev *pci_dev = to_pci_dev(dev);
Yue Ma0317e4a2018-01-10 11:48:32 -08001098
1099 return msm_pcie_pm_control(vote ? MSM_PCIE_DISABLE_PC :
1100 MSM_PCIE_ENABLE_PC,
1101 pci_dev->bus->number, pci_dev,
1102 NULL, PM_OPTIONS_DEFAULT);
1103}
1104EXPORT_SYMBOL(cnss_wlan_pm_control);
1105
1106int cnss_auto_suspend(struct device *dev)
1107{
1108 int ret = 0;
Yue Mafcf60422018-05-01 16:59:56 -07001109 struct pci_dev *pci_dev = to_pci_dev(dev);
1110 struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
1111 struct cnss_plat_data *plat_priv;
Yue Ma0317e4a2018-01-10 11:48:32 -08001112 struct cnss_bus_bw_info *bus_bw_info;
1113
Yue Ma0317e4a2018-01-10 11:48:32 -08001114 if (!pci_priv)
1115 return -ENODEV;
1116
Yue Mafcf60422018-05-01 16:59:56 -07001117 plat_priv = pci_priv->plat_priv;
1118 if (!plat_priv)
1119 return -ENODEV;
Yue Ma0317e4a2018-01-10 11:48:32 -08001120
1121 if (pci_priv->pci_link_state) {
1122 if (cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_SUSPEND)) {
1123 ret = -EAGAIN;
1124 goto out;
1125 }
1126
1127 cnss_set_pci_config_space(pci_priv, SAVE_PCI_CONFIG_SPACE);
1128 pci_disable_device(pci_dev);
1129
1130 ret = pci_set_power_state(pci_dev, PCI_D3hot);
1131 if (ret)
1132 cnss_pr_err("Failed to set D3Hot, err = %d\n", ret);
1133
1134 cnss_pr_dbg("Suspending PCI link\n");
1135 if (cnss_set_pci_link(pci_priv, PCI_LINK_DOWN)) {
1136 cnss_pr_err("Failed to suspend PCI link!\n");
1137 ret = -EAGAIN;
1138 goto resume_mhi;
1139 }
1140
1141 pci_priv->pci_link_state = PCI_LINK_DOWN;
1142 }
1143
1144 cnss_pci_set_auto_suspended(pci_priv, 1);
1145 cnss_pci_set_monitor_wake_intr(pci_priv, true);
1146
1147 bus_bw_info = &plat_priv->bus_bw_info;
1148 msm_bus_scale_client_update_request(bus_bw_info->bus_client,
1149 CNSS_BUS_WIDTH_NONE);
1150
1151 return 0;
1152
1153resume_mhi:
1154 if (pci_enable_device(pci_dev))
1155 cnss_pr_err("Failed to enable PCI device!\n");
1156 cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RESUME);
1157out:
1158 return ret;
1159}
1160EXPORT_SYMBOL(cnss_auto_suspend);
1161
1162int cnss_auto_resume(struct device *dev)
1163{
1164 int ret = 0;
Yue Mafcf60422018-05-01 16:59:56 -07001165 struct pci_dev *pci_dev = to_pci_dev(dev);
1166 struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
1167 struct cnss_plat_data *plat_priv;
Yue Ma0317e4a2018-01-10 11:48:32 -08001168 struct cnss_bus_bw_info *bus_bw_info;
1169
Yue Ma0317e4a2018-01-10 11:48:32 -08001170 if (!pci_priv)
1171 return -ENODEV;
1172
Yue Mafcf60422018-05-01 16:59:56 -07001173 plat_priv = pci_priv->plat_priv;
1174 if (!plat_priv)
1175 return -ENODEV;
1176
Yue Ma0317e4a2018-01-10 11:48:32 -08001177 if (!pci_priv->pci_link_state) {
1178 cnss_pr_dbg("Resuming PCI link\n");
1179 if (cnss_set_pci_link(pci_priv, PCI_LINK_UP)) {
1180 cnss_pr_err("Failed to resume PCI link!\n");
1181 ret = -EAGAIN;
1182 goto out;
1183 }
1184 pci_priv->pci_link_state = PCI_LINK_UP;
1185
1186 ret = pci_enable_device(pci_dev);
1187 if (ret)
1188 cnss_pr_err("Failed to enable PCI device, err = %d\n",
1189 ret);
1190
1191 cnss_set_pci_config_space(pci_priv, RESTORE_PCI_CONFIG_SPACE);
1192 pci_set_master(pci_dev);
1193 cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RESUME);
1194 }
1195
1196 cnss_pci_set_auto_suspended(pci_priv, 0);
1197
1198 bus_bw_info = &plat_priv->bus_bw_info;
1199 msm_bus_scale_client_update_request(bus_bw_info->bus_client,
1200 bus_bw_info->current_bw_vote);
1201out:
1202 return ret;
1203}
1204EXPORT_SYMBOL(cnss_auto_resume);
1205
1206int cnss_pm_request_resume(struct cnss_pci_data *pci_priv)
1207{
1208 struct pci_dev *pci_dev;
1209
1210 if (!pci_priv)
1211 return -ENODEV;
1212
1213 pci_dev = pci_priv->pci_dev;
1214 if (!pci_dev)
1215 return -ENODEV;
1216
1217 return pm_request_resume(&pci_dev->dev);
1218}
1219
1220int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv)
1221{
1222 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
Yue Maa3e15032018-02-15 15:56:12 -08001223 struct cnss_fw_mem *fw_mem = plat_priv->fw_mem;
1224 int i;
Yue Ma0317e4a2018-01-10 11:48:32 -08001225
Yue Maa3e15032018-02-15 15:56:12 -08001226 for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
1227 if (!fw_mem[i].va && fw_mem[i].size) {
1228 fw_mem[i].va =
1229 dma_alloc_coherent(&pci_priv->pci_dev->dev,
1230 fw_mem[i].size,
1231 &fw_mem[i].pa, GFP_KERNEL);
1232 if (!fw_mem[i].va) {
1233 cnss_pr_err("Failed to allocate memory for FW, size: 0x%zx, type: %u\n",
1234 fw_mem[i].size, fw_mem[i].type);
Yue Ma0317e4a2018-01-10 11:48:32 -08001235
Yue Maa3e15032018-02-15 15:56:12 -08001236 return -ENOMEM;
1237 }
Yue Ma0317e4a2018-01-10 11:48:32 -08001238 }
1239 }
1240
1241 return 0;
1242}
1243
1244static void cnss_pci_free_fw_mem(struct cnss_pci_data *pci_priv)
1245{
1246 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
Yue Maa3e15032018-02-15 15:56:12 -08001247 struct cnss_fw_mem *fw_mem = plat_priv->fw_mem;
1248 int i;
Yue Ma0317e4a2018-01-10 11:48:32 -08001249
Yue Maa3e15032018-02-15 15:56:12 -08001250 for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
1251 if (fw_mem[i].va && fw_mem[i].size) {
1252 cnss_pr_dbg("Freeing memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx, type: %u\n",
1253 fw_mem[i].va, &fw_mem[i].pa,
1254 fw_mem[i].size, fw_mem[i].type);
1255 dma_free_coherent(&pci_priv->pci_dev->dev,
1256 fw_mem[i].size, fw_mem[i].va,
1257 fw_mem[i].pa);
1258 fw_mem[i].va = NULL;
1259 fw_mem[i].pa = 0;
1260 fw_mem[i].size = 0;
1261 fw_mem[i].type = 0;
1262 }
Yue Ma0317e4a2018-01-10 11:48:32 -08001263 }
Yue Maa3e15032018-02-15 15:56:12 -08001264
1265 plat_priv->fw_mem_seg_len = 0;
Yue Ma0317e4a2018-01-10 11:48:32 -08001266}
1267
1268int cnss_pci_load_m3(struct cnss_pci_data *pci_priv)
1269{
1270 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
1271 struct cnss_fw_mem *m3_mem = &plat_priv->m3_mem;
1272 char filename[MAX_M3_FILE_NAME_LENGTH];
1273 const struct firmware *fw_entry;
1274 int ret = 0;
1275
1276 if (!m3_mem->va && !m3_mem->size) {
1277 snprintf(filename, sizeof(filename), DEFAULT_M3_FILE_NAME);
1278
1279 ret = request_firmware(&fw_entry, filename,
1280 &pci_priv->pci_dev->dev);
1281 if (ret) {
1282 cnss_pr_err("Failed to load M3 image: %s\n", filename);
1283 return ret;
1284 }
1285
1286 m3_mem->va = dma_alloc_coherent(&pci_priv->pci_dev->dev,
1287 fw_entry->size, &m3_mem->pa,
1288 GFP_KERNEL);
1289 if (!m3_mem->va) {
1290 cnss_pr_err("Failed to allocate memory for M3, size: 0x%zx\n",
1291 fw_entry->size);
1292 release_firmware(fw_entry);
1293 return -ENOMEM;
1294 }
1295
1296 memcpy(m3_mem->va, fw_entry->data, fw_entry->size);
1297 m3_mem->size = fw_entry->size;
1298 release_firmware(fw_entry);
1299 }
1300
1301 return 0;
1302}
1303
1304static void cnss_pci_free_m3_mem(struct cnss_pci_data *pci_priv)
1305{
1306 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
1307 struct cnss_fw_mem *m3_mem = &plat_priv->m3_mem;
1308
1309 if (m3_mem->va && m3_mem->size) {
1310 cnss_pr_dbg("Freeing memory for M3, va: 0x%pK, pa: %pa, size: 0x%zx\n",
1311 m3_mem->va, &m3_mem->pa, m3_mem->size);
1312 dma_free_coherent(&pci_priv->pci_dev->dev, m3_mem->size,
1313 m3_mem->va, m3_mem->pa);
1314 }
1315
1316 m3_mem->va = NULL;
1317 m3_mem->pa = 0;
1318 m3_mem->size = 0;
1319}
1320
Yue Mafcf60422018-05-01 16:59:56 -07001321int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv)
Yue Ma0317e4a2018-01-10 11:48:32 -08001322{
Yue Mafcf60422018-05-01 16:59:56 -07001323 int ret;
1324 struct cnss_plat_data *plat_priv;
1325
Yue Ma0317e4a2018-01-10 11:48:32 -08001326 if (!pci_priv)
1327 return -ENODEV;
1328
Yue Mafcf60422018-05-01 16:59:56 -07001329 plat_priv = pci_priv->plat_priv;
1330 if (!plat_priv)
1331 return -ENODEV;
1332
1333 ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_TRIGGER_RDDM);
1334 if (ret) {
1335 cnss_pr_err("Failed to trigger RDDM, err = %d\n", ret);
1336 cnss_schedule_recovery(&pci_priv->pci_dev->dev,
1337 CNSS_REASON_DEFAULT);
1338 return 0;
1339 }
1340
1341 if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state)) {
1342 mod_timer(&plat_priv->fw_boot_timer,
1343 jiffies + msecs_to_jiffies(FW_ASSERT_TIMEOUT));
1344 }
Yue Ma0317e4a2018-01-10 11:48:32 -08001345
1346 return 0;
1347}
1348
Yue Mafcf60422018-05-01 16:59:56 -07001349void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv)
1350{
1351 if (!pci_priv)
1352 return;
1353
1354 cnss_pr_err("Timeout waiting for FW ready indication\n");
1355
1356 cnss_schedule_recovery(&pci_priv->pci_dev->dev,
1357 CNSS_REASON_TIMEOUT);
1358}
1359
1360int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info)
1361{
1362 struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev));
1363
1364 if (!pci_priv)
1365 return -ENODEV;
1366
1367 info->va = pci_priv->bar;
1368 info->pa = pci_resource_start(pci_priv->pci_dev, PCI_BAR_NUM);
1369
1370 return 0;
1371}
1372EXPORT_SYMBOL(cnss_get_soc_info);
1373
Yue Ma0317e4a2018-01-10 11:48:32 -08001374static struct cnss_msi_config msi_config = {
1375 .total_vectors = 32,
1376 .total_users = 4,
1377 .users = (struct cnss_msi_user[]) {
Yue Ma3eb55622018-02-22 12:14:00 -08001378 { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
1379 { .name = "CE", .num_vectors = 10, .base_vector = 3 },
Yue Ma0317e4a2018-01-10 11:48:32 -08001380 { .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
1381 { .name = "DP", .num_vectors = 18, .base_vector = 14 },
1382 },
1383};
1384
1385static int cnss_pci_get_msi_assignment(struct cnss_pci_data *pci_priv)
1386{
1387 pci_priv->msi_config = &msi_config;
1388
1389 return 0;
1390}
1391
1392static int cnss_pci_enable_msi(struct cnss_pci_data *pci_priv)
1393{
1394 int ret = 0;
1395 struct pci_dev *pci_dev = pci_priv->pci_dev;
1396 int num_vectors;
1397 struct cnss_msi_config *msi_config;
1398 struct msi_desc *msi_desc;
1399
1400 ret = cnss_pci_get_msi_assignment(pci_priv);
1401 if (ret) {
1402 cnss_pr_err("Failed to get MSI assignment, err = %d\n", ret);
1403 goto out;
1404 }
1405
1406 msi_config = pci_priv->msi_config;
1407 if (!msi_config) {
1408 cnss_pr_err("msi_config is NULL!\n");
1409 ret = -EINVAL;
1410 goto out;
1411 }
1412
Yue Ma46c7d762018-03-21 16:11:49 -07001413 num_vectors = pci_alloc_irq_vectors(pci_dev,
1414 msi_config->total_vectors,
1415 msi_config->total_vectors,
1416 PCI_IRQ_MSI);
Yue Ma0317e4a2018-01-10 11:48:32 -08001417 if (num_vectors != msi_config->total_vectors) {
1418 cnss_pr_err("Failed to get enough MSI vectors (%d), available vectors = %d",
1419 msi_config->total_vectors, num_vectors);
Yue Ma46c7d762018-03-21 16:11:49 -07001420 if (num_vectors >= 0)
1421 ret = -EINVAL;
Yue Ma0317e4a2018-01-10 11:48:32 -08001422 goto reset_msi_config;
1423 }
1424
1425 msi_desc = irq_get_msi_desc(pci_dev->irq);
1426 if (!msi_desc) {
1427 cnss_pr_err("msi_desc is NULL!\n");
1428 ret = -EINVAL;
Yue Ma46c7d762018-03-21 16:11:49 -07001429 goto free_msi_vector;
Yue Ma0317e4a2018-01-10 11:48:32 -08001430 }
1431
1432 pci_priv->msi_ep_base_data = msi_desc->msg.data;
1433 if (!pci_priv->msi_ep_base_data) {
1434 cnss_pr_err("Got 0 MSI base data!\n");
1435 CNSS_ASSERT(0);
1436 }
1437
1438 cnss_pr_dbg("MSI base data is %d\n", pci_priv->msi_ep_base_data);
1439
1440 return 0;
1441
Yue Ma46c7d762018-03-21 16:11:49 -07001442free_msi_vector:
1443 pci_free_irq_vectors(pci_priv->pci_dev);
Yue Ma0317e4a2018-01-10 11:48:32 -08001444reset_msi_config:
1445 pci_priv->msi_config = NULL;
1446out:
1447 return ret;
1448}
1449
1450static void cnss_pci_disable_msi(struct cnss_pci_data *pci_priv)
1451{
Yue Ma46c7d762018-03-21 16:11:49 -07001452 pci_free_irq_vectors(pci_priv->pci_dev);
Yue Ma0317e4a2018-01-10 11:48:32 -08001453}
1454
1455int cnss_get_user_msi_assignment(struct device *dev, char *user_name,
1456 int *num_vectors, u32 *user_base_data,
1457 u32 *base_vector)
1458{
Yue Mafcf60422018-05-01 16:59:56 -07001459 struct cnss_pci_data *pci_priv = cnss_get_pci_priv(to_pci_dev(dev));
Yue Ma0317e4a2018-01-10 11:48:32 -08001460 struct cnss_msi_config *msi_config;
1461 int idx;
1462
1463 if (!pci_priv)
1464 return -ENODEV;
1465
1466 msi_config = pci_priv->msi_config;
1467 if (!msi_config) {
1468 cnss_pr_err("MSI is not supported.\n");
1469 return -EINVAL;
1470 }
1471
1472 for (idx = 0; idx < msi_config->total_users; idx++) {
1473 if (strcmp(user_name, msi_config->users[idx].name) == 0) {
1474 *num_vectors = msi_config->users[idx].num_vectors;
1475 *user_base_data = msi_config->users[idx].base_vector
1476 + pci_priv->msi_ep_base_data;
1477 *base_vector = msi_config->users[idx].base_vector;
1478
1479 cnss_pr_dbg("Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
1480 user_name, *num_vectors, *user_base_data,
1481 *base_vector);
1482
1483 return 0;
1484 }
1485 }
1486
1487 cnss_pr_err("Failed to find MSI assignment for %s!\n", user_name);
1488
1489 return -EINVAL;
1490}
1491EXPORT_SYMBOL(cnss_get_user_msi_assignment);
1492
1493int cnss_get_msi_irq(struct device *dev, unsigned int vector)
1494{
1495 struct pci_dev *pci_dev = to_pci_dev(dev);
Yue Ma46c7d762018-03-21 16:11:49 -07001496 int irq_num;
Yue Ma0317e4a2018-01-10 11:48:32 -08001497
Yue Ma46c7d762018-03-21 16:11:49 -07001498 irq_num = pci_irq_vector(pci_dev, vector);
1499 cnss_pr_dbg("Get IRQ number %d for vector index %d\n", irq_num, vector);
1500
1501 return irq_num;
Yue Ma0317e4a2018-01-10 11:48:32 -08001502}
1503EXPORT_SYMBOL(cnss_get_msi_irq);
1504
1505void cnss_get_msi_address(struct device *dev, u32 *msi_addr_low,
1506 u32 *msi_addr_high)
1507{
1508 struct pci_dev *pci_dev = to_pci_dev(dev);
1509
1510 pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO,
1511 msi_addr_low);
1512
1513 pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
1514 msi_addr_high);
1515}
1516EXPORT_SYMBOL(cnss_get_msi_address);
1517
Yue Mafcf60422018-05-01 16:59:56 -07001518u32 cnss_pci_get_wake_msi(struct cnss_pci_data *pci_priv)
1519{
1520 int ret, num_vectors;
1521 u32 user_base_data, base_vector;
1522
1523 if (!pci_priv)
1524 return -ENODEV;
1525
1526 ret = cnss_get_user_msi_assignment(&pci_priv->pci_dev->dev,
1527 WAKE_MSI_NAME, &num_vectors,
1528 &user_base_data, &base_vector);
1529 if (ret) {
1530 cnss_pr_err("WAKE MSI is not valid\n");
1531 return 0;
1532 }
1533
1534 return user_base_data;
1535}
1536
Yue Ma0317e4a2018-01-10 11:48:32 -08001537static int cnss_pci_enable_bus(struct cnss_pci_data *pci_priv)
1538{
1539 int ret = 0;
1540 struct pci_dev *pci_dev = pci_priv->pci_dev;
1541 u16 device_id;
Yue Ma3eb55622018-02-22 12:14:00 -08001542 u32 pci_dma_mask = PCI_DMA_MASK_64_BIT;
Yue Ma0317e4a2018-01-10 11:48:32 -08001543
1544 pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id);
1545 if (device_id != pci_priv->pci_device_id->device) {
1546 cnss_pr_err("PCI device ID mismatch, config ID: 0x%x, probe ID: 0x%x\n",
1547 device_id, pci_priv->pci_device_id->device);
1548 ret = -EIO;
1549 goto out;
1550 }
1551
1552 ret = pci_assign_resource(pci_dev, PCI_BAR_NUM);
1553 if (ret) {
1554 pr_err("Failed to assign PCI resource, err = %d\n", ret);
1555 goto out;
1556 }
1557
1558 ret = pci_enable_device(pci_dev);
1559 if (ret) {
1560 cnss_pr_err("Failed to enable PCI device, err = %d\n", ret);
1561 goto out;
1562 }
1563
1564 ret = pci_request_region(pci_dev, PCI_BAR_NUM, "cnss");
1565 if (ret) {
1566 cnss_pr_err("Failed to request PCI region, err = %d\n", ret);
1567 goto disable_device;
1568 }
1569
Yue Ma3eb55622018-02-22 12:14:00 -08001570 if (device_id == QCA6174_DEVICE_ID)
1571 pci_dma_mask = PCI_DMA_MASK_32_BIT;
1572
1573 ret = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(pci_dma_mask));
Yue Ma0317e4a2018-01-10 11:48:32 -08001574 if (ret) {
1575 cnss_pr_err("Failed to set PCI DMA mask (%d), err = %d\n",
Yue Ma3eb55622018-02-22 12:14:00 -08001576 ret, pci_dma_mask);
Yue Ma0317e4a2018-01-10 11:48:32 -08001577 goto release_region;
1578 }
1579
Yue Ma3eb55622018-02-22 12:14:00 -08001580 ret = pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(pci_dma_mask));
Yue Ma0317e4a2018-01-10 11:48:32 -08001581 if (ret) {
1582 cnss_pr_err("Failed to set PCI consistent DMA mask (%d), err = %d\n",
Yue Ma3eb55622018-02-22 12:14:00 -08001583 ret, pci_dma_mask);
Yue Ma0317e4a2018-01-10 11:48:32 -08001584 goto release_region;
1585 }
1586
1587 pci_set_master(pci_dev);
1588
1589 pci_priv->bar = pci_iomap(pci_dev, PCI_BAR_NUM, 0);
1590 if (!pci_priv->bar) {
1591 cnss_pr_err("Failed to do PCI IO map!\n");
1592 ret = -EIO;
1593 goto clear_master;
1594 }
1595 return 0;
1596
1597clear_master:
1598 pci_clear_master(pci_dev);
1599release_region:
1600 pci_release_region(pci_dev, PCI_BAR_NUM);
1601disable_device:
1602 pci_disable_device(pci_dev);
1603out:
1604 return ret;
1605}
1606
1607static void cnss_pci_disable_bus(struct cnss_pci_data *pci_priv)
1608{
1609 struct pci_dev *pci_dev = pci_priv->pci_dev;
1610
1611 if (pci_priv->bar) {
1612 pci_iounmap(pci_dev, pci_priv->bar);
1613 pci_priv->bar = NULL;
1614 }
1615
1616 pci_clear_master(pci_dev);
1617 pci_release_region(pci_dev, PCI_BAR_NUM);
Yue Ma3eb55622018-02-22 12:14:00 -08001618 if (pci_is_enabled(pci_dev))
1619 pci_disable_device(pci_dev);
Yue Ma0317e4a2018-01-10 11:48:32 -08001620}
1621
Yue Ma3eb55622018-02-22 12:14:00 -08001622static int cnss_mhi_pm_runtime_get(struct mhi_controller *mhi_ctrl, void *priv)
Yue Ma0317e4a2018-01-10 11:48:32 -08001623{
Yue Ma3eb55622018-02-22 12:14:00 -08001624 struct cnss_pci_data *pci_priv = priv;
1625
1626 return pm_runtime_get(&pci_priv->pci_dev->dev);
Yue Ma0317e4a2018-01-10 11:48:32 -08001627}
1628
Yue Ma3eb55622018-02-22 12:14:00 -08001629static void cnss_mhi_pm_runtime_put_noidle(struct mhi_controller *mhi_ctrl,
1630 void *priv)
Yue Ma0317e4a2018-01-10 11:48:32 -08001631{
Yue Ma3eb55622018-02-22 12:14:00 -08001632 struct cnss_pci_data *pci_priv = priv;
1633
1634 pm_runtime_put_noidle(&pci_priv->pci_dev->dev);
Yue Ma0317e4a2018-01-10 11:48:32 -08001635}
1636
1637static char *cnss_mhi_state_to_str(enum cnss_mhi_state mhi_state)
1638{
1639 switch (mhi_state) {
1640 case CNSS_MHI_INIT:
1641 return "INIT";
1642 case CNSS_MHI_DEINIT:
1643 return "DEINIT";
1644 case CNSS_MHI_POWER_ON:
1645 return "POWER_ON";
1646 case CNSS_MHI_POWER_OFF:
1647 return "POWER_OFF";
Yue Ma3eb55622018-02-22 12:14:00 -08001648 case CNSS_MHI_FORCE_POWER_OFF:
1649 return "FORCE_POWER_OFF";
Yue Ma0317e4a2018-01-10 11:48:32 -08001650 case CNSS_MHI_SUSPEND:
1651 return "SUSPEND";
1652 case CNSS_MHI_RESUME:
1653 return "RESUME";
1654 case CNSS_MHI_TRIGGER_RDDM:
1655 return "TRIGGER_RDDM";
Yue Ma0317e4a2018-01-10 11:48:32 -08001656 default:
1657 return "UNKNOWN";
1658 }
1659};
1660
Yue Ma3eb55622018-02-22 12:14:00 -08001661void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic)
Yue Ma0317e4a2018-01-10 11:48:32 -08001662{
Yue Ma0317e4a2018-01-10 11:48:32 -08001663 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
1664 struct cnss_dump_data *dump_data =
1665 &plat_priv->ramdump_info_v2.dump_data;
Yue Ma3eb55622018-02-22 12:14:00 -08001666 struct cnss_dump_seg *dump_seg =
1667 plat_priv->ramdump_info_v2.dump_data_vaddr;
1668 struct image_info *fw_image, *rddm_image;
Yue Maa3e15032018-02-15 15:56:12 -08001669 struct cnss_fw_mem *fw_mem = plat_priv->fw_mem;
Yue Ma3eb55622018-02-22 12:14:00 -08001670 int ret, i;
Yue Ma0317e4a2018-01-10 11:48:32 -08001671
Yue Ma3eb55622018-02-22 12:14:00 -08001672 ret = mhi_download_rddm_img(pci_priv->mhi_ctrl, in_panic);
1673 if (ret) {
1674 cnss_pr_err("Failed to download RDDM image, err = %d\n", ret);
1675 return;
Yue Ma0317e4a2018-01-10 11:48:32 -08001676 }
1677
Yue Ma3eb55622018-02-22 12:14:00 -08001678 fw_image = pci_priv->mhi_ctrl->fbc_image;
1679 rddm_image = pci_priv->mhi_ctrl->rddm_image;
1680 dump_data->nentries = 0;
Yue Ma0317e4a2018-01-10 11:48:32 -08001681
Yue Ma3eb55622018-02-22 12:14:00 -08001682 cnss_pr_dbg("Collect FW image dump segment, nentries %d\n",
1683 fw_image->entries);
1684
1685 for (i = 0; i < fw_image->entries; i++) {
1686 dump_seg->address = fw_image->mhi_buf[i].dma_addr;
1687 dump_seg->v_address = fw_image->mhi_buf[i].buf;
1688 dump_seg->size = fw_image->mhi_buf[i].len;
1689 dump_seg->type = CNSS_FW_IMAGE;
Yue Ma0317e4a2018-01-10 11:48:32 -08001690 cnss_pr_dbg("seg-%d: address 0x%lx, v_address %pK, size 0x%lx\n",
1691 i, dump_seg->address,
1692 dump_seg->v_address, dump_seg->size);
1693 dump_seg++;
1694 }
1695
Yue Ma3eb55622018-02-22 12:14:00 -08001696 dump_data->nentries += fw_image->entries;
Yue Ma0317e4a2018-01-10 11:48:32 -08001697
Yue Ma3eb55622018-02-22 12:14:00 -08001698 cnss_pr_dbg("Collect RDDM image dump segment, nentries %d\n",
1699 rddm_image->entries);
Yue Ma0317e4a2018-01-10 11:48:32 -08001700
Yue Ma3eb55622018-02-22 12:14:00 -08001701 for (i = 0; i < rddm_image->entries; i++) {
1702 dump_seg->address = rddm_image->mhi_buf[i].dma_addr;
1703 dump_seg->v_address = rddm_image->mhi_buf[i].buf;
1704 dump_seg->size = rddm_image->mhi_buf[i].len;
1705 dump_seg->type = CNSS_FW_RDDM;
1706 cnss_pr_dbg("seg-%d: address 0x%lx, v_address %pK, size 0x%lx\n",
1707 i, dump_seg->address,
1708 dump_seg->v_address, dump_seg->size);
1709 dump_seg++;
1710 }
Yue Ma0317e4a2018-01-10 11:48:32 -08001711
Yue Ma3eb55622018-02-22 12:14:00 -08001712 dump_data->nentries += rddm_image->entries;
Yue Ma0317e4a2018-01-10 11:48:32 -08001713
Yue Maa3e15032018-02-15 15:56:12 -08001714 cnss_pr_dbg("Collect remote heap dump segment\n");
Yue Ma0317e4a2018-01-10 11:48:32 -08001715
Yue Maa3e15032018-02-15 15:56:12 -08001716 for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
Yue Mab79d4862018-07-11 12:32:12 -07001717 if (fw_mem[i].type == CNSS_MEM_TYPE_DDR) {
Yue Maa3e15032018-02-15 15:56:12 -08001718 dump_seg->address = fw_mem[i].pa;
1719 dump_seg->v_address = fw_mem[i].va;
1720 dump_seg->size = fw_mem[i].size;
1721 dump_seg->type = CNSS_FW_REMOTE_HEAP;
1722 cnss_pr_dbg("seg-%d: address 0x%lx, v_address %pK, size 0x%lx\n",
1723 i, dump_seg->address, dump_seg->v_address,
1724 dump_seg->size);
1725 dump_seg++;
1726 dump_data->nentries++;
1727 }
Yue Ma3eb55622018-02-22 12:14:00 -08001728 }
Yue Ma0317e4a2018-01-10 11:48:32 -08001729
1730 if (dump_data->nentries > 0)
1731 plat_priv->ramdump_info_v2.dump_data_valid = true;
1732}
1733
1734void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv)
1735{
1736 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
1737
1738 plat_priv->ramdump_info_v2.dump_data.nentries = 0;
1739 plat_priv->ramdump_info_v2.dump_data_valid = false;
1740}
1741
Yue Ma3eb55622018-02-22 12:14:00 -08001742static int cnss_mhi_link_status(struct mhi_controller *mhi_ctrl, void *priv)
Yue Ma0317e4a2018-01-10 11:48:32 -08001743{
1744 struct cnss_pci_data *pci_priv = priv;
Yue Ma3eb55622018-02-22 12:14:00 -08001745 u16 device_id;
Yue Ma0317e4a2018-01-10 11:48:32 -08001746
Yue Ma3eb55622018-02-22 12:14:00 -08001747 if (!pci_priv) {
1748 cnss_pr_err("pci_priv is NULL\n");
1749 return -EINVAL;
1750 }
1751
1752 pci_read_config_word(pci_priv->pci_dev, PCI_DEVICE_ID, &device_id);
1753 if (device_id != pci_priv->device_id) {
1754 cnss_pr_err("PCI device ID mismatch, link possibly down, current read ID: 0x%x, record ID: 0x%x\n",
1755 device_id, pci_priv->device_id);
1756 return -EIO;
1757 }
1758
1759 return 0;
1760}
1761
1762static void cnss_mhi_notify_status(struct mhi_controller *mhi_ctrl, void *priv,
1763 enum MHI_CB reason)
1764{
1765 struct cnss_pci_data *pci_priv = priv;
1766 struct cnss_plat_data *plat_priv;
1767 enum cnss_recovery_reason cnss_reason;
1768
1769 if (!pci_priv) {
1770 cnss_pr_err("pci_priv is NULL");
Yue Ma0317e4a2018-01-10 11:48:32 -08001771 return;
Yue Ma3eb55622018-02-22 12:14:00 -08001772 }
1773
1774 plat_priv = pci_priv->plat_priv;
Yue Ma0317e4a2018-01-10 11:48:32 -08001775
1776 cnss_pr_dbg("MHI status cb is called with reason %d\n", reason);
1777
Yue Mae83a0eff2018-05-04 14:15:54 -07001778 if (pci_priv->driver_ops && pci_priv->driver_ops->update_status)
1779 pci_priv->driver_ops->update_status(pci_priv->pci_dev,
1780 CNSS_FW_DOWN);
Yue Ma8bead6d2018-02-01 12:25:47 -08001781
Yue Ma3eb55622018-02-22 12:14:00 -08001782 switch (reason) {
1783 case MHI_CB_EE_RDDM:
1784 cnss_reason = CNSS_REASON_RDDM;
1785 break;
1786 default:
1787 cnss_pr_err("Unsupported MHI status cb reason: %d\n", reason);
1788 return;
1789 }
1790
Yue Ma0317e4a2018-01-10 11:48:32 -08001791 set_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
1792 del_timer(&plat_priv->fw_boot_timer);
1793
Yue Ma0317e4a2018-01-10 11:48:32 -08001794 cnss_schedule_recovery(&pci_priv->pci_dev->dev,
1795 cnss_reason);
1796}
1797
Yue Ma3eb55622018-02-22 12:14:00 -08001798static int cnss_pci_get_mhi_msi(struct cnss_pci_data *pci_priv)
1799{
1800 int ret, num_vectors, i;
1801 u32 user_base_data, base_vector;
1802 int *irq;
1803
1804 ret = cnss_get_user_msi_assignment(&pci_priv->pci_dev->dev,
1805 MHI_MSI_NAME, &num_vectors,
1806 &user_base_data, &base_vector);
1807 if (ret)
1808 return ret;
1809
1810 cnss_pr_dbg("Number of assigned MSI for MHI is %d, base vector is %d\n",
1811 num_vectors, base_vector);
1812
1813 irq = kcalloc(num_vectors, sizeof(int), GFP_KERNEL);
1814 if (!irq)
1815 return -ENOMEM;
1816
1817 for (i = 0; i < num_vectors; i++)
1818 irq[i] = cnss_get_msi_irq(&pci_priv->pci_dev->dev,
1819 base_vector + i);
1820
1821 pci_priv->mhi_ctrl->irq = irq;
1822 pci_priv->mhi_ctrl->msi_allocated = num_vectors;
1823
1824 return 0;
1825}
1826
Yue Ma0317e4a2018-01-10 11:48:32 -08001827static int cnss_pci_register_mhi(struct cnss_pci_data *pci_priv)
1828{
1829 int ret = 0;
Yue Ma3eb55622018-02-22 12:14:00 -08001830 struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
Yue Ma0317e4a2018-01-10 11:48:32 -08001831 struct pci_dev *pci_dev = pci_priv->pci_dev;
Yue Ma3eb55622018-02-22 12:14:00 -08001832 struct mhi_controller *mhi_ctrl;
Yue Ma0317e4a2018-01-10 11:48:32 -08001833
Yue Ma3eb55622018-02-22 12:14:00 -08001834 mhi_ctrl = mhi_alloc_controller(0);
1835 if (!mhi_ctrl) {
1836 cnss_pr_err("Invalid MHI controller context\n");
1837 return -EINVAL;
Yue Ma0317e4a2018-01-10 11:48:32 -08001838 }
Yue Ma0317e4a2018-01-10 11:48:32 -08001839
Yue Ma3eb55622018-02-22 12:14:00 -08001840 pci_priv->mhi_ctrl = mhi_ctrl;
Yue Ma0317e4a2018-01-10 11:48:32 -08001841
Yue Ma3eb55622018-02-22 12:14:00 -08001842 mhi_ctrl->priv_data = pci_priv;
1843 mhi_ctrl->dev = &pci_dev->dev;
1844 mhi_ctrl->of_node = (&plat_priv->plat_dev->dev)->of_node;
1845 mhi_ctrl->dev_id = pci_priv->device_id;
1846 mhi_ctrl->domain = pci_domain_nr(pci_dev->bus);
1847 mhi_ctrl->bus = pci_dev->bus->number;
1848 mhi_ctrl->slot = PCI_SLOT(pci_dev->devfn);
Yue Ma0317e4a2018-01-10 11:48:32 -08001849
Yue Mab74e6f32018-06-13 18:39:58 -07001850 mhi_ctrl->fw_image = plat_priv->firmware_name;
1851
Yue Ma3eb55622018-02-22 12:14:00 -08001852 mhi_ctrl->regs = pci_priv->bar;
1853 cnss_pr_dbg("BAR starts at %pa\n",
1854 &pci_resource_start(pci_priv->pci_dev, PCI_BAR_NUM));
1855
1856 ret = cnss_pci_get_mhi_msi(pci_priv);
Yue Ma0317e4a2018-01-10 11:48:32 -08001857 if (ret) {
Yue Ma3eb55622018-02-22 12:14:00 -08001858 cnss_pr_err("Failed to get MSI for MHI\n");
1859 return ret;
1860 }
1861
1862 if (pci_priv->smmu_s1_enable) {
1863 mhi_ctrl->iova_start = pci_priv->smmu_iova_start;
1864 mhi_ctrl->iova_stop = pci_priv->smmu_iova_start +
1865 pci_priv->smmu_iova_len;
1866 } else {
1867 mhi_ctrl->iova_start = memblock_start_of_DRAM();
1868 mhi_ctrl->iova_stop = memblock_end_of_DRAM();
1869 }
1870
1871 mhi_ctrl->link_status = cnss_mhi_link_status;
1872 mhi_ctrl->status_cb = cnss_mhi_notify_status;
1873 mhi_ctrl->runtime_get = cnss_mhi_pm_runtime_get;
1874 mhi_ctrl->runtime_put = cnss_mhi_pm_runtime_put_noidle;
1875
1876 mhi_ctrl->rddm_size = pci_priv->plat_priv->ramdump_info_v2.ramdump_size;
Yue Ma36e40302018-07-12 10:50:56 -07001877 mhi_ctrl->sbl_size = SZ_512K;
1878 mhi_ctrl->seg_len = SZ_512K;
1879 mhi_ctrl->fbc_download = true;
Yue Ma3eb55622018-02-22 12:14:00 -08001880
1881 mhi_ctrl->log_buf = ipc_log_context_create(CNSS_IPC_LOG_PAGES,
1882 "cnss-mhi", 0);
1883 if (!mhi_ctrl->log_buf)
1884 cnss_pr_err("Unable to create CNSS MHI IPC log context\n");
1885
1886 ret = of_register_mhi_controller(mhi_ctrl);
1887 if (ret) {
1888 cnss_pr_err("Failed to register to MHI bus, err = %d\n", ret);
Yue Ma0317e4a2018-01-10 11:48:32 -08001889 return ret;
1890 }
1891
1892 return 0;
1893}
1894
1895static void cnss_pci_unregister_mhi(struct cnss_pci_data *pci_priv)
1896{
Yue Ma3eb55622018-02-22 12:14:00 -08001897 struct mhi_controller *mhi_ctrl = pci_priv->mhi_ctrl;
Yue Ma0317e4a2018-01-10 11:48:32 -08001898
Yue Ma3eb55622018-02-22 12:14:00 -08001899 mhi_unregister_mhi_controller(mhi_ctrl);
1900 ipc_log_context_destroy(mhi_ctrl->log_buf);
1901 kfree(mhi_ctrl->irq);
Yue Ma0317e4a2018-01-10 11:48:32 -08001902}
1903
1904static int cnss_pci_check_mhi_state_bit(struct cnss_pci_data *pci_priv,
1905 enum cnss_mhi_state mhi_state)
1906{
1907 switch (mhi_state) {
1908 case CNSS_MHI_INIT:
1909 if (!test_bit(CNSS_MHI_INIT, &pci_priv->mhi_state))
1910 return 0;
1911 break;
1912 case CNSS_MHI_DEINIT:
1913 case CNSS_MHI_POWER_ON:
1914 if (test_bit(CNSS_MHI_INIT, &pci_priv->mhi_state) &&
1915 !test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state))
1916 return 0;
1917 break;
Yue Ma3eb55622018-02-22 12:14:00 -08001918 case CNSS_MHI_FORCE_POWER_OFF:
1919 if (test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state))
1920 return 0;
1921 break;
Yue Ma0317e4a2018-01-10 11:48:32 -08001922 case CNSS_MHI_POWER_OFF:
1923 case CNSS_MHI_SUSPEND:
1924 if (test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state) &&
1925 !test_bit(CNSS_MHI_SUSPEND, &pci_priv->mhi_state))
1926 return 0;
1927 break;
1928 case CNSS_MHI_RESUME:
1929 if (test_bit(CNSS_MHI_SUSPEND, &pci_priv->mhi_state))
1930 return 0;
1931 break;
1932 case CNSS_MHI_TRIGGER_RDDM:
Yue Ma2eb731a2018-06-27 18:27:34 -07001933 if (test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state) &&
1934 !test_bit(CNSS_MHI_TRIGGER_RDDM, &pci_priv->mhi_state))
1935 return 0;
1936 break;
Yue Ma0317e4a2018-01-10 11:48:32 -08001937 default:
1938 cnss_pr_err("Unhandled MHI state: %s(%d)\n",
1939 cnss_mhi_state_to_str(mhi_state), mhi_state);
1940 }
1941
1942 cnss_pr_err("Cannot set MHI state %s(%d) in current MHI state (0x%lx)\n",
1943 cnss_mhi_state_to_str(mhi_state), mhi_state,
1944 pci_priv->mhi_state);
1945
1946 return -EINVAL;
1947}
1948
1949static void cnss_pci_set_mhi_state_bit(struct cnss_pci_data *pci_priv,
1950 enum cnss_mhi_state mhi_state)
1951{
1952 switch (mhi_state) {
1953 case CNSS_MHI_INIT:
1954 set_bit(CNSS_MHI_INIT, &pci_priv->mhi_state);
1955 break;
1956 case CNSS_MHI_DEINIT:
1957 clear_bit(CNSS_MHI_INIT, &pci_priv->mhi_state);
1958 break;
1959 case CNSS_MHI_POWER_ON:
1960 set_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state);
1961 break;
1962 case CNSS_MHI_POWER_OFF:
Yue Ma3eb55622018-02-22 12:14:00 -08001963 case CNSS_MHI_FORCE_POWER_OFF:
Yue Ma0317e4a2018-01-10 11:48:32 -08001964 clear_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state);
1965 break;
1966 case CNSS_MHI_SUSPEND:
1967 set_bit(CNSS_MHI_SUSPEND, &pci_priv->mhi_state);
1968 break;
1969 case CNSS_MHI_RESUME:
1970 clear_bit(CNSS_MHI_SUSPEND, &pci_priv->mhi_state);
1971 break;
1972 case CNSS_MHI_TRIGGER_RDDM:
Yue Ma0317e4a2018-01-10 11:48:32 -08001973 break;
1974 default:
1975 cnss_pr_err("Unhandled MHI state (%d)\n", mhi_state);
1976 }
1977}
1978
1979int cnss_pci_set_mhi_state(struct cnss_pci_data *pci_priv,
1980 enum cnss_mhi_state mhi_state)
1981{
1982 int ret = 0;
Yue Ma0317e4a2018-01-10 11:48:32 -08001983
1984 if (!pci_priv) {
1985 cnss_pr_err("pci_priv is NULL!\n");
1986 return -ENODEV;
1987 }
1988
1989 if (pci_priv->device_id == QCA6174_DEVICE_ID)
1990 return 0;
1991
Yue Ma3eb55622018-02-22 12:14:00 -08001992 if (mhi_state < 0) {
1993 cnss_pr_err("Invalid MHI state (%d)\n", mhi_state);
Yue Ma0317e4a2018-01-10 11:48:32 -08001994 return -EINVAL;
1995 }
1996
1997 ret = cnss_pci_check_mhi_state_bit(pci_priv, mhi_state);
1998 if (ret)
1999 goto out;
2000
2001 cnss_pr_dbg("Setting MHI state: %s(%d)\n",
2002 cnss_mhi_state_to_str(mhi_state), mhi_state);
Yue Ma3eb55622018-02-22 12:14:00 -08002003
2004 switch (mhi_state) {
2005 case CNSS_MHI_INIT:
2006 ret = mhi_prepare_for_power_up(pci_priv->mhi_ctrl);
2007 break;
2008 case CNSS_MHI_DEINIT:
2009 mhi_unprepare_after_power_down(pci_priv->mhi_ctrl);
2010 ret = 0;
2011 break;
2012 case CNSS_MHI_POWER_ON:
2013 ret = mhi_sync_power_up(pci_priv->mhi_ctrl);
2014 break;
2015 case CNSS_MHI_POWER_OFF:
2016 mhi_power_down(pci_priv->mhi_ctrl, true);
2017 ret = 0;
2018 break;
2019 case CNSS_MHI_FORCE_POWER_OFF:
2020 mhi_power_down(pci_priv->mhi_ctrl, false);
2021 ret = 0;
2022 break;
2023 case CNSS_MHI_SUSPEND:
2024 ret = mhi_pm_suspend(pci_priv->mhi_ctrl);
2025 break;
2026 case CNSS_MHI_RESUME:
2027 ret = mhi_pm_resume(pci_priv->mhi_ctrl);
2028 break;
2029 case CNSS_MHI_TRIGGER_RDDM:
Yue Ma03c22ee2018-04-05 17:40:33 -07002030 ret = mhi_force_rddm_mode(pci_priv->mhi_ctrl);
Yue Ma3eb55622018-02-22 12:14:00 -08002031 break;
2032 default:
2033 cnss_pr_err("Unhandled MHI state (%d)\n", mhi_state);
2034 ret = -EINVAL;
Yue Ma0317e4a2018-01-10 11:48:32 -08002035 }
2036
Yue Ma3eb55622018-02-22 12:14:00 -08002037 if (ret)
2038 goto out;
2039
Yue Ma0317e4a2018-01-10 11:48:32 -08002040 cnss_pci_set_mhi_state_bit(pci_priv, mhi_state);
2041
Yue Ma3eb55622018-02-22 12:14:00 -08002042 return 0;
2043
Yue Ma0317e4a2018-01-10 11:48:32 -08002044out:
Yue Ma3eb55622018-02-22 12:14:00 -08002045 cnss_pr_err("Failed to set MHI state: %s(%d)\n",
2046 cnss_mhi_state_to_str(mhi_state), mhi_state);
Yue Ma0317e4a2018-01-10 11:48:32 -08002047 return ret;
2048}
2049
2050int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv)
2051{
2052 int ret = 0;
2053
2054 if (!pci_priv) {
2055 cnss_pr_err("pci_priv is NULL!\n");
2056 return -ENODEV;
2057 }
2058
2059 if (fbc_bypass)
2060 return 0;
2061
2062 ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_INIT);
2063 if (ret)
2064 goto out;
2065
2066 ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_POWER_ON);
2067 if (ret)
2068 goto out;
2069
2070 return 0;
2071
2072out:
2073 return ret;
2074}
2075
2076void cnss_pci_stop_mhi(struct cnss_pci_data *pci_priv)
2077{
2078 struct cnss_plat_data *plat_priv;
2079
2080 if (!pci_priv) {
2081 cnss_pr_err("pci_priv is NULL!\n");
2082 return;
2083 }
2084
2085 if (fbc_bypass)
2086 return;
2087
2088 plat_priv = pci_priv->plat_priv;
2089
2090 cnss_pci_set_mhi_state_bit(pci_priv, CNSS_MHI_RESUME);
Yue Ma3eb55622018-02-22 12:14:00 -08002091 if (!pci_priv->pci_link_down_ind)
2092 cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_POWER_OFF);
2093 else
2094 cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_FORCE_POWER_OFF);
Yue Ma0317e4a2018-01-10 11:48:32 -08002095
2096 if (plat_priv->ramdump_info_v2.dump_data_valid ||
2097 test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state))
2098 return;
2099
2100 cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_DEINIT);
2101}
2102
2103static int cnss_pci_probe(struct pci_dev *pci_dev,
2104 const struct pci_device_id *id)
2105{
2106 int ret = 0;
2107 struct cnss_pci_data *pci_priv;
2108 struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
2109 struct resource *res;
2110
2111 cnss_pr_dbg("PCI is probing, vendor ID: 0x%x, device ID: 0x%x\n",
2112 id->vendor, pci_dev->device);
2113
Yue Ma0317e4a2018-01-10 11:48:32 -08002114 pci_priv = devm_kzalloc(&pci_dev->dev, sizeof(*pci_priv),
2115 GFP_KERNEL);
2116 if (!pci_priv) {
2117 ret = -ENOMEM;
2118 goto out;
2119 }
2120
2121 pci_priv->pci_link_state = PCI_LINK_UP;
2122 pci_priv->plat_priv = plat_priv;
2123 pci_priv->pci_dev = pci_dev;
2124 pci_priv->pci_device_id = id;
2125 pci_priv->device_id = pci_dev->device;
2126 cnss_set_pci_priv(pci_dev, pci_priv);
2127 plat_priv->device_id = pci_dev->device;
2128 plat_priv->bus_priv = pci_priv;
Yue Mab74e6f32018-06-13 18:39:58 -07002129 snprintf(plat_priv->firmware_name, sizeof(plat_priv->firmware_name),
2130 DEFAULT_FW_FILE_NAME);
Yue Ma0317e4a2018-01-10 11:48:32 -08002131
2132 ret = cnss_register_subsys(plat_priv);
2133 if (ret)
2134 goto reset_ctx;
2135
2136 ret = cnss_register_ramdump(plat_priv);
2137 if (ret)
2138 goto unregister_subsys;
2139
2140 res = platform_get_resource_byname(plat_priv->plat_dev, IORESOURCE_MEM,
2141 "smmu_iova_base");
2142 if (res) {
Yue Ma4dac45d2018-02-23 11:49:25 -08002143 if (of_property_read_bool(plat_priv->plat_dev->dev.of_node,
2144 "qcom,smmu-s1-enable"))
2145 pci_priv->smmu_s1_enable = true;
2146
Yue Ma0317e4a2018-01-10 11:48:32 -08002147 pci_priv->smmu_iova_start = res->start;
2148 pci_priv->smmu_iova_len = resource_size(res);
2149 cnss_pr_dbg("smmu_iova_start: %pa, smmu_iova_len: %zu\n",
2150 &pci_priv->smmu_iova_start,
2151 pci_priv->smmu_iova_len);
2152
2153 ret = cnss_pci_init_smmu(pci_priv);
2154 if (ret) {
2155 cnss_pr_err("Failed to init SMMU, err = %d\n", ret);
2156 goto unregister_ramdump;
2157 }
2158 }
2159
2160 ret = cnss_reg_pci_event(pci_priv);
2161 if (ret) {
2162 cnss_pr_err("Failed to register PCI event, err = %d\n", ret);
2163 goto deinit_smmu;
2164 }
2165
2166 ret = cnss_pci_enable_bus(pci_priv);
2167 if (ret)
2168 goto dereg_pci_event;
2169
2170 pci_save_state(pci_dev);
2171 pci_priv->default_state = pci_store_saved_state(pci_dev);
2172
2173 switch (pci_dev->device) {
2174 case QCA6174_DEVICE_ID:
2175 pci_read_config_word(pci_dev, QCA6174_REV_ID_OFFSET,
2176 &pci_priv->revision_id);
2177 ret = cnss_suspend_pci_link(pci_priv);
2178 if (ret)
2179 cnss_pr_err("Failed to suspend PCI link, err = %d\n",
2180 ret);
2181 cnss_power_off_device(plat_priv);
2182 break;
2183 case QCA6290_EMULATION_DEVICE_ID:
2184 case QCA6290_DEVICE_ID:
Yue Mab74e6f32018-06-13 18:39:58 -07002185 case QCA6390_EMULATION_DEVICE_ID:
2186 case QCA6390_DEVICE_ID:
Yue Ma0317e4a2018-01-10 11:48:32 -08002187 ret = cnss_pci_enable_msi(pci_priv);
2188 if (ret)
2189 goto disable_bus;
2190 ret = cnss_pci_register_mhi(pci_priv);
2191 if (ret) {
2192 cnss_pci_disable_msi(pci_priv);
2193 goto disable_bus;
2194 }
2195 ret = cnss_suspend_pci_link(pci_priv);
2196 if (ret)
2197 cnss_pr_err("Failed to suspend PCI link, err = %d\n",
2198 ret);
2199 cnss_power_off_device(plat_priv);
2200 break;
2201 default:
2202 cnss_pr_err("Unknown PCI device found: 0x%x\n",
2203 pci_dev->device);
2204 ret = -ENODEV;
2205 goto disable_bus;
2206 }
2207
2208 return 0;
2209
2210disable_bus:
2211 cnss_pci_disable_bus(pci_priv);
2212dereg_pci_event:
2213 cnss_dereg_pci_event(pci_priv);
2214deinit_smmu:
2215 if (pci_priv->smmu_mapping)
2216 cnss_pci_deinit_smmu(pci_priv);
2217unregister_ramdump:
2218 cnss_unregister_ramdump(plat_priv);
2219unregister_subsys:
2220 cnss_unregister_subsys(plat_priv);
2221reset_ctx:
2222 plat_priv->bus_priv = NULL;
2223out:
2224 return ret;
2225}
2226
2227static void cnss_pci_remove(struct pci_dev *pci_dev)
2228{
2229 struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
2230 struct cnss_plat_data *plat_priv =
2231 cnss_bus_dev_to_plat_priv(&pci_dev->dev);
2232
2233 cnss_pci_free_m3_mem(pci_priv);
2234 cnss_pci_free_fw_mem(pci_priv);
2235
2236 switch (pci_dev->device) {
2237 case QCA6290_EMULATION_DEVICE_ID:
2238 case QCA6290_DEVICE_ID:
Yue Mab74e6f32018-06-13 18:39:58 -07002239 case QCA6390_EMULATION_DEVICE_ID:
2240 case QCA6390_DEVICE_ID:
Yue Ma0317e4a2018-01-10 11:48:32 -08002241 cnss_pci_unregister_mhi(pci_priv);
2242 cnss_pci_disable_msi(pci_priv);
2243 break;
2244 default:
2245 break;
2246 }
2247
2248 pci_load_and_free_saved_state(pci_dev, &pci_priv->saved_state);
2249
2250 cnss_pci_disable_bus(pci_priv);
2251 cnss_dereg_pci_event(pci_priv);
2252 if (pci_priv->smmu_mapping)
2253 cnss_pci_deinit_smmu(pci_priv);
2254 cnss_unregister_ramdump(plat_priv);
2255 cnss_unregister_subsys(plat_priv);
2256 plat_priv->bus_priv = NULL;
2257}
2258
2259static const struct pci_device_id cnss_pci_id_table[] = {
2260 { QCA6174_VENDOR_ID, QCA6174_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
2261 { QCA6290_EMULATION_VENDOR_ID, QCA6290_EMULATION_DEVICE_ID,
2262 PCI_ANY_ID, PCI_ANY_ID },
2263 { QCA6290_VENDOR_ID, QCA6290_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
Yue Mab74e6f32018-06-13 18:39:58 -07002264 { QCA6390_VENDOR_ID, QCA6390_EMULATION_DEVICE_ID, PCI_ANY_ID,
2265 PCI_ANY_ID },
2266 { QCA6390_VENDOR_ID, QCA6390_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
Yue Ma0317e4a2018-01-10 11:48:32 -08002267 { 0 }
2268};
2269MODULE_DEVICE_TABLE(pci, cnss_pci_id_table);
2270
2271static const struct dev_pm_ops cnss_pm_ops = {
2272 SET_SYSTEM_SLEEP_PM_OPS(cnss_pci_suspend, cnss_pci_resume)
2273 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(cnss_pci_suspend_noirq,
2274 cnss_pci_resume_noirq)
2275 SET_RUNTIME_PM_OPS(cnss_pci_runtime_suspend, cnss_pci_runtime_resume,
2276 cnss_pci_runtime_idle)
2277};
2278
2279struct pci_driver cnss_pci_driver = {
2280 .name = "cnss_pci",
2281 .id_table = cnss_pci_id_table,
2282 .probe = cnss_pci_probe,
2283 .remove = cnss_pci_remove,
2284 .driver = {
2285 .pm = &cnss_pm_ops,
2286 },
2287};
2288
2289int cnss_pci_init(struct cnss_plat_data *plat_priv)
2290{
2291 int ret = 0;
2292 struct device *dev = &plat_priv->plat_dev->dev;
2293 u32 rc_num;
2294
2295 ret = of_property_read_u32(dev->of_node, "qcom,wlan-rc-num", &rc_num);
2296 if (ret) {
2297 cnss_pr_err("Failed to find PCIe RC number, err = %d\n", ret);
2298 goto out;
2299 }
2300
2301 ret = msm_pcie_enumerate(rc_num);
2302 if (ret) {
2303 cnss_pr_err("Failed to enable PCIe RC%x, err = %d\n",
2304 rc_num, ret);
2305 goto out;
2306 }
2307
2308 ret = pci_register_driver(&cnss_pci_driver);
2309 if (ret) {
2310 cnss_pr_err("Failed to register to PCI framework, err = %d\n",
2311 ret);
2312 goto out;
2313 }
2314
2315 return 0;
2316out:
2317 return ret;
2318}
2319
2320void cnss_pci_deinit(struct cnss_plat_data *plat_priv)
2321{
2322 pci_unregister_driver(&cnss_pci_driver);
2323}