2 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <linux/module.h>
19 #include <linux/pci.h>
20 #include <linux/moduleparam.h>
21 #include <linux/interrupt.h>
22 #include <linux/suspend.h>
24 #include <linux/rtnetlink.h>
25 #include <linux/pm_runtime.h>
27 static bool use_msi
= true;
28 module_param(use_msi
, bool, 0444);
29 MODULE_PARM_DESC(use_msi
, " Use MSI interrupt, default - true");
32 module_param(ftm_mode
, bool, 0444);
33 MODULE_PARM_DESC(ftm_mode
, " Set factory test mode, default - false");
35 static int wil6210_pm_notify(struct notifier_block
*notify_block
,
36 unsigned long mode
, void *unused
);
39 int wil_set_capabilities(struct wil6210_priv
*wil
)
41 const char *wil_fw_name
;
42 u32 jtag_id
= wil_r(wil
, RGF_USER_JTAG_DEV_ID
);
43 u8 chip_revision
= (wil_r(wil
, RGF_USER_REVISION_ID
) &
44 RGF_USER_REVISION_ID_MASK
);
46 struct fw_map
*iccm_section
, *sct
;
48 bitmap_zero(wil
->hw_capa
, hw_capa_last
);
49 bitmap_zero(wil
->fw_capabilities
, WMI_FW_CAPABILITY_MAX
);
50 bitmap_zero(wil
->platform_capa
, WIL_PLATFORM_CAPA_MAX
);
51 wil
->wil_fw_name
= ftm_mode
? WIL_FW_NAME_FTM_DEFAULT
:
53 wil
->chip_revision
= chip_revision
;
56 case JTAG_DEV_ID_SPARROW
:
57 memcpy(fw_mapping
, sparrow_fw_mapping
,
58 sizeof(sparrow_fw_mapping
));
59 switch (chip_revision
) {
60 case REVISION_ID_SPARROW_D0
:
61 wil
->hw_name
= "Sparrow D0";
62 wil
->hw_version
= HW_VER_SPARROW_D0
;
63 wil_fw_name
= ftm_mode
? WIL_FW_NAME_FTM_SPARROW_PLUS
:
64 WIL_FW_NAME_SPARROW_PLUS
;
66 if (wil_fw_verify_file_exists(wil
, wil_fw_name
))
67 wil
->wil_fw_name
= wil_fw_name
;
68 sct
= wil_find_fw_mapping("mac_rgf_ext");
70 wil_err(wil
, "mac_rgf_ext section not found in fw_mapping\n");
73 memcpy(sct
, &sparrow_d0_mac_rgf_ext
, sizeof(*sct
));
75 case REVISION_ID_SPARROW_B0
:
76 wil
->hw_name
= "Sparrow B0";
77 wil
->hw_version
= HW_VER_SPARROW_B0
;
80 wil
->hw_name
= "Unknown";
81 wil
->hw_version
= HW_VER_UNKNOWN
;
84 wil
->rgf_fw_assert_code_addr
= SPARROW_RGF_FW_ASSERT_CODE
;
85 wil
->rgf_ucode_assert_code_addr
= SPARROW_RGF_UCODE_ASSERT_CODE
;
87 case JTAG_DEV_ID_TALYN
:
88 wil
->hw_name
= "Talyn";
89 wil
->hw_version
= HW_VER_TALYN
;
90 memcpy(fw_mapping
, talyn_fw_mapping
, sizeof(talyn_fw_mapping
));
91 wil
->rgf_fw_assert_code_addr
= TALYN_RGF_FW_ASSERT_CODE
;
92 wil
->rgf_ucode_assert_code_addr
= TALYN_RGF_UCODE_ASSERT_CODE
;
93 if (wil_r(wil
, RGF_USER_OTP_HW_RD_MACHINE_1
) &
94 BIT_NO_FLASH_INDICATION
)
95 set_bit(hw_capa_no_flash
, wil
->hw_capa
);
98 wil_err(wil
, "Unknown board hardware, chip_id 0x%08x, chip_revision 0x%08x\n",
99 jtag_id
, chip_revision
);
100 wil
->hw_name
= "Unknown";
101 wil
->hw_version
= HW_VER_UNKNOWN
;
105 iccm_section
= wil_find_fw_mapping("fw_code");
107 wil_err(wil
, "fw_code section not found in fw_mapping\n");
110 wil
->iccm_base
= iccm_section
->host
;
112 wil_info(wil
, "Board hardware is %s, flash %sexist\n", wil
->hw_name
,
113 test_bit(hw_capa_no_flash
, wil
->hw_capa
) ? "doesn't " : "");
115 /* Get platform capabilities */
116 if (wil
->platform_ops
.get_capa
) {
118 wil
->platform_ops
.get_capa(wil
->platform_handle
);
119 memcpy(wil
->platform_capa
, &platform_capa
,
120 min(sizeof(wil
->platform_capa
), sizeof(platform_capa
)));
123 /* extract FW capabilities from file without loading the FW */
124 wil_request_firmware(wil
, wil
->wil_fw_name
, false);
125 wil_refresh_fw_capabilities(wil
);
130 void wil_disable_irq(struct wil6210_priv
*wil
)
132 disable_irq(wil
->pdev
->irq
);
135 void wil_enable_irq(struct wil6210_priv
*wil
)
137 enable_irq(wil
->pdev
->irq
);
141 static int wil_if_pcie_enable(struct wil6210_priv
*wil
)
143 struct pci_dev
*pdev
= wil
->pdev
;
145 /* on platforms with buggy ACPI, pdev->msi_enabled may be set to
146 * allow pci_enable_device to work. This indicates INTx was not routed
147 * and only MSI should be used
149 int msi_only
= pdev
->msi_enabled
;
150 bool _use_msi
= use_msi
;
151 bool wmi_only
= test_bit(WMI_FW_CAPABILITY_WMI_ONLY
,
152 wil
->fw_capabilities
);
154 wil_dbg_misc(wil
, "if_pcie_enable, wmi_only %d\n", wmi_only
);
156 pci_set_master(pdev
);
158 wil_dbg_misc(wil
, "Setup %s interrupt\n", use_msi
? "MSI" : "INTx");
160 if (use_msi
&& pci_enable_msi(pdev
)) {
161 wil_err(wil
, "pci_enable_msi failed, use INTx\n");
165 if (!_use_msi
&& msi_only
) {
166 wil_err(wil
, "Interrupt pin not routed, unable to use INTx\n");
171 rc
= wil6210_init_irq(wil
, pdev
->irq
, _use_msi
);
175 /* need reset here to obtain MAC or in case of WMI-only FW, full reset
176 * and fw loading takes place
178 mutex_lock(&wil
->mutex
);
179 rc
= wil_reset(wil
, wmi_only
);
180 mutex_unlock(&wil
->mutex
);
187 wil6210_fini_irq(wil
, pdev
->irq
);
188 /* safe to call if no MSI */
189 pci_disable_msi(pdev
);
191 pci_clear_master(pdev
);
195 static int wil_if_pcie_disable(struct wil6210_priv
*wil
)
197 struct pci_dev
*pdev
= wil
->pdev
;
199 wil_dbg_misc(wil
, "if_pcie_disable\n");
201 pci_clear_master(pdev
);
202 /* disable and release IRQ */
203 wil6210_fini_irq(wil
, pdev
->irq
);
204 /* safe to call if no MSI */
205 pci_disable_msi(pdev
);
206 /* TODO: disable HW */
211 static int wil_platform_rop_ramdump(void *wil_handle
, void *buf
, uint32_t size
)
213 struct wil6210_priv
*wil
= wil_handle
;
218 return wil_fw_copy_crash_dump(wil
, buf
, size
);
221 static int wil_platform_rop_fw_recovery(void *wil_handle
)
223 struct wil6210_priv
*wil
= wil_handle
;
228 wil_fw_error_recovery(wil
);
233 static void wil_platform_ops_uninit(struct wil6210_priv
*wil
)
235 if (wil
->platform_ops
.uninit
)
236 wil
->platform_ops
.uninit(wil
->platform_handle
);
237 memset(&wil
->platform_ops
, 0, sizeof(wil
->platform_ops
));
240 static int wil_pcie_probe(struct pci_dev
*pdev
, const struct pci_device_id
*id
)
242 struct wil6210_priv
*wil
;
243 struct device
*dev
= &pdev
->dev
;
245 const struct wil_platform_rops rops
= {
246 .ramdump
= wil_platform_rop_ramdump
,
247 .fw_recovery
= wil_platform_rop_fw_recovery
,
249 u32 bar_size
= pci_resource_len(pdev
, 0);
250 int dma_addr_size
[] = {48, 40, 32}; /* keep descending order */
254 dev_info(&pdev
->dev
, WIL_NAME
255 " device found [%04x:%04x] (rev %x) bar size 0x%x\n",
256 (int)pdev
->vendor
, (int)pdev
->device
, (int)pdev
->revision
,
259 if ((bar_size
< WIL6210_MIN_MEM_SIZE
) ||
260 (bar_size
> WIL6210_MAX_MEM_SIZE
)) {
261 dev_err(&pdev
->dev
, "Unexpected BAR0 size 0x%x\n",
266 wil
= wil_if_alloc(dev
);
268 rc
= (int)PTR_ERR(wil
);
269 dev_err(dev
, "wil_if_alloc failed: %d\n", rc
);
274 pci_set_drvdata(pdev
, wil
);
275 wil
->bar_size
= bar_size
;
276 /* rollback to if_free */
278 wil
->platform_handle
=
279 wil_platform_init(&pdev
->dev
, &wil
->platform_ops
, &rops
, wil
);
280 if (!wil
->platform_handle
) {
282 wil_err(wil
, "wil_platform_init failed\n");
285 /* rollback to err_plat */
287 /* device supports >32bit addresses */
288 for (i
= 0; i
< ARRAY_SIZE(dma_addr_size
); i
++) {
289 rc
= dma_set_mask_and_coherent(dev
,
290 DMA_BIT_MASK(dma_addr_size
[i
]));
292 dev_err(dev
, "dma_set_mask_and_coherent(%d) failed: %d\n",
293 dma_addr_size
[i
], rc
);
296 dev_info(dev
, "using dma mask %d", dma_addr_size
[i
]);
297 wil
->dma_addr_size
= dma_addr_size
[i
];
301 if (wil
->dma_addr_size
== 0)
304 rc
= pci_enable_device(pdev
);
305 if (rc
&& pdev
->msi_enabled
== 0) {
307 "pci_enable_device failed, retry with MSI only\n");
308 /* Work around for platforms that can't allocate IRQ:
309 * retry with MSI only
311 pdev
->msi_enabled
= 1;
312 rc
= pci_enable_device(pdev
);
316 "pci_enable_device failed, even with MSI only\n");
319 /* rollback to err_disable_pdev */
320 pci_set_power_state(pdev
, PCI_D0
);
322 rc
= pci_request_region(pdev
, 0, WIL_NAME
);
324 wil_err(wil
, "pci_request_region failed\n");
325 goto err_disable_pdev
;
327 /* rollback to err_release_reg */
329 wil
->csr
= pci_ioremap_bar(pdev
, 0);
331 wil_err(wil
, "pci_ioremap_bar failed\n");
333 goto err_release_reg
;
335 /* rollback to err_iounmap */
336 wil_info(wil
, "CSR at %pR -> 0x%p\n", &pdev
->resource
[0], wil
->csr
);
338 rc
= wil_set_capabilities(wil
);
340 wil_err(wil
, "wil_set_capabilities failed, rc %d\n", rc
);
343 wil6210_clear_irq(wil
);
345 /* FW should raise IRQ when ready */
346 rc
= wil_if_pcie_enable(wil
);
348 wil_err(wil
, "Enable device failed\n");
351 /* rollback to bus_disable */
353 rc
= wil_if_add(wil
);
355 wil_err(wil
, "wil_if_add failed: %d\n", rc
);
359 if (IS_ENABLED(CONFIG_PM
))
360 wil
->pm_notify
.notifier_call
= wil6210_pm_notify
;
362 rc
= register_pm_notifier(&wil
->pm_notify
);
364 /* Do not fail the driver initialization, as suspend can
365 * be prevented in a later phase if needed
367 wil_err(wil
, "register_pm_notifier failed: %d\n", rc
);
369 wil6210_debugfs_init(wil
);
371 wil_pm_runtime_allow(wil
);
376 wil_if_pcie_disable(wil
);
378 pci_iounmap(pdev
, wil
->csr
);
380 pci_release_region(pdev
, 0);
382 pci_disable_device(pdev
);
384 wil_platform_ops_uninit(wil
);
391 static void wil_pcie_remove(struct pci_dev
*pdev
)
393 struct wil6210_priv
*wil
= pci_get_drvdata(pdev
);
394 void __iomem
*csr
= wil
->csr
;
396 wil_dbg_misc(wil
, "pcie_remove\n");
398 unregister_pm_notifier(&wil
->pm_notify
);
400 wil_pm_runtime_forbid(wil
);
402 wil6210_debugfs_remove(wil
);
404 wil_p2p_wdev_free(wil
);
407 wil_if_pcie_disable(wil
);
408 pci_iounmap(pdev
, csr
);
409 pci_release_region(pdev
, 0);
410 pci_disable_device(pdev
);
411 wil_platform_ops_uninit(wil
);
415 static const struct pci_device_id wil6210_pcie_ids
[] = {
416 { PCI_DEVICE(0x1ae9, 0x0310) },
417 { PCI_DEVICE(0x1ae9, 0x0302) }, /* same as above, firmware broken */
418 { PCI_DEVICE(0x17cb, 0x1201) }, /* Talyn */
419 { /* end: all zeroes */ },
421 MODULE_DEVICE_TABLE(pci
, wil6210_pcie_ids
);
423 static int wil6210_suspend(struct device
*dev
, bool is_runtime
)
426 struct pci_dev
*pdev
= to_pci_dev(dev
);
427 struct wil6210_priv
*wil
= pci_get_drvdata(pdev
);
428 struct net_device
*ndev
= wil_to_ndev(wil
);
429 bool keep_radio_on
= ndev
->flags
& IFF_UP
&&
430 wil
->keep_radio_on_during_sleep
;
432 wil_dbg_pm(wil
, "suspend: %s\n", is_runtime
? "runtime" : "system");
434 rc
= wil_can_suspend(wil
, is_runtime
);
438 rc
= wil_suspend(wil
, is_runtime
, keep_radio_on
);
440 /* In case radio stays on, platform device will control
443 if (!keep_radio_on
) {
444 /* disable bus mastering */
445 pci_clear_master(pdev
);
446 wil
->suspend_stats
.r_off
.successful_suspends
++;
448 wil
->suspend_stats
.r_on
.successful_suspends
++;
455 static int wil6210_resume(struct device
*dev
, bool is_runtime
)
458 struct pci_dev
*pdev
= to_pci_dev(dev
);
459 struct wil6210_priv
*wil
= pci_get_drvdata(pdev
);
460 struct net_device
*ndev
= wil_to_ndev(wil
);
461 bool keep_radio_on
= ndev
->flags
& IFF_UP
&&
462 wil
->keep_radio_on_during_sleep
;
464 wil_dbg_pm(wil
, "resume: %s\n", is_runtime
? "runtime" : "system");
466 /* In case radio stays on, platform device will control
471 pci_set_master(pdev
);
472 rc
= wil_resume(wil
, is_runtime
, keep_radio_on
);
474 wil_err(wil
, "device failed to resume (%d)\n", rc
);
475 if (!keep_radio_on
) {
476 pci_clear_master(pdev
);
477 wil
->suspend_stats
.r_off
.failed_resumes
++;
479 wil
->suspend_stats
.r_on
.failed_resumes
++;
483 wil
->suspend_stats
.r_on
.successful_resumes
++;
485 wil
->suspend_stats
.r_off
.successful_resumes
++;
491 static int wil6210_pm_notify(struct notifier_block
*notify_block
,
492 unsigned long mode
, void *unused
)
494 struct wil6210_priv
*wil
= container_of(
495 notify_block
, struct wil6210_priv
, pm_notify
);
497 enum wil_platform_event evt
;
499 wil_dbg_pm(wil
, "pm_notify: mode (%ld)\n", mode
);
502 case PM_HIBERNATION_PREPARE
:
503 case PM_SUSPEND_PREPARE
:
504 case PM_RESTORE_PREPARE
:
505 rc
= wil_can_suspend(wil
, false);
508 evt
= WIL_PLATFORM_EVT_PRE_SUSPEND
;
509 if (wil
->platform_ops
.notify
)
510 rc
= wil
->platform_ops
.notify(wil
->platform_handle
,
513 case PM_POST_SUSPEND
:
514 case PM_POST_HIBERNATION
:
515 case PM_POST_RESTORE
:
516 evt
= WIL_PLATFORM_EVT_POST_SUSPEND
;
517 if (wil
->platform_ops
.notify
)
518 rc
= wil
->platform_ops
.notify(wil
->platform_handle
,
522 wil_dbg_pm(wil
, "unhandled notify mode %ld\n", mode
);
526 wil_dbg_pm(wil
, "notification mode %ld: rc (%d)\n", mode
, rc
);
530 static int __maybe_unused
wil6210_pm_suspend(struct device
*dev
)
532 return wil6210_suspend(dev
, false);
535 static int __maybe_unused
wil6210_pm_resume(struct device
*dev
)
537 return wil6210_resume(dev
, false);
540 static int __maybe_unused
wil6210_pm_runtime_idle(struct device
*dev
)
542 struct pci_dev
*pdev
= to_pci_dev(dev
);
543 struct wil6210_priv
*wil
= pci_get_drvdata(pdev
);
545 wil_dbg_pm(wil
, "Runtime idle\n");
547 return wil_can_suspend(wil
, true);
550 static int __maybe_unused
wil6210_pm_runtime_resume(struct device
*dev
)
552 return wil6210_resume(dev
, true);
555 static int __maybe_unused
wil6210_pm_runtime_suspend(struct device
*dev
)
557 struct pci_dev
*pdev
= to_pci_dev(dev
);
558 struct wil6210_priv
*wil
= pci_get_drvdata(pdev
);
560 if (test_bit(wil_status_suspended
, wil
->status
)) {
561 wil_dbg_pm(wil
, "trying to suspend while suspended\n");
565 return wil6210_suspend(dev
, true);
568 static const struct dev_pm_ops wil6210_pm_ops
= {
569 SET_SYSTEM_SLEEP_PM_OPS(wil6210_pm_suspend
, wil6210_pm_resume
)
570 SET_RUNTIME_PM_OPS(wil6210_pm_runtime_suspend
,
571 wil6210_pm_runtime_resume
,
572 wil6210_pm_runtime_idle
)
575 static struct pci_driver wil6210_driver
= {
576 .probe
= wil_pcie_probe
,
577 .remove
= wil_pcie_remove
,
578 .id_table
= wil6210_pcie_ids
,
581 .pm
= &wil6210_pm_ops
,
585 static int __init
wil6210_driver_init(void)
589 rc
= wil_platform_modinit();
593 rc
= pci_register_driver(&wil6210_driver
);
595 wil_platform_modexit();
598 module_init(wil6210_driver_init
);
600 static void __exit
wil6210_driver_exit(void)
602 pci_unregister_driver(&wil6210_driver
);
603 wil_platform_modexit();
605 module_exit(wil6210_driver_exit
);
607 MODULE_LICENSE("Dual BSD/GPL");
608 MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>");
609 MODULE_DESCRIPTION("Driver for 60g WiFi WIL6210 card");