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