1 // SPDX-License-Identifier: GPL-2.0-only 2 3 /* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ 4 /* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ 5 6 #include <linux/delay.h> 7 #include <linux/err.h> 8 #include <linux/memblock.h> 9 #include <linux/mhi.h> 10 #include <linux/moduleparam.h> 11 #include <linux/pci.h> 12 #include <linux/sizes.h> 13 14 #include "mhi_controller.h" 15 #include "qaic.h" 16 17 #define MAX_RESET_TIME_SEC 25 18 19 static unsigned int mhi_timeout_ms = 2000; /* 2 sec default */ 20 module_param(mhi_timeout_ms, uint, 0600); 21 MODULE_PARM_DESC(mhi_timeout_ms, "MHI controller timeout value"); 22 23 static const struct mhi_channel_config aic100_channels[] = { 24 { 25 .name = "QAIC_LOOPBACK", 26 .num = 0, 27 .num_elements = 32, 28 .local_elements = 0, 29 .event_ring = 0, 30 .dir = DMA_TO_DEVICE, 31 .ee_mask = MHI_CH_EE_AMSS, 32 .pollcfg = 0, 33 .doorbell = MHI_DB_BRST_DISABLE, 34 .lpm_notify = false, 35 .offload_channel = false, 36 .doorbell_mode_switch = false, 37 .auto_queue = false, 38 .wake_capable = false, 39 }, 40 { 41 .name = "QAIC_LOOPBACK", 42 .num = 1, 43 .num_elements = 32, 44 .local_elements = 0, 45 .event_ring = 0, 46 .dir = DMA_FROM_DEVICE, 47 .ee_mask = MHI_CH_EE_AMSS, 48 .pollcfg = 0, 49 .doorbell = MHI_DB_BRST_DISABLE, 50 .lpm_notify = false, 51 .offload_channel = false, 52 .doorbell_mode_switch = false, 53 .auto_queue = false, 54 .wake_capable = false, 55 }, 56 { 57 .name = "QAIC_SAHARA", 58 .num = 2, 59 .num_elements = 32, 60 .local_elements = 0, 61 .event_ring = 0, 62 .dir = DMA_TO_DEVICE, 63 .ee_mask = MHI_CH_EE_SBL, 64 .pollcfg = 0, 65 .doorbell = MHI_DB_BRST_DISABLE, 66 .lpm_notify = false, 67 .offload_channel = false, 68 .doorbell_mode_switch = false, 69 .auto_queue = false, 70 .wake_capable = false, 71 }, 72 { 73 .name = "QAIC_SAHARA", 74 .num = 3, 75 .num_elements = 32, 76 .local_elements = 0, 77 .event_ring = 0, 78 .dir = DMA_FROM_DEVICE, 79 .ee_mask = MHI_CH_EE_SBL, 80 .pollcfg = 0, 81 .doorbell = MHI_DB_BRST_DISABLE, 82 .lpm_notify = false, 83 .offload_channel = false, 84 .doorbell_mode_switch = false, 85 .auto_queue = false, 86 .wake_capable = false, 87 }, 88 { 89 .name = "QAIC_DIAG", 90 .num = 4, 91 .num_elements = 32, 92 .local_elements = 0, 93 .event_ring = 0, 94 .dir = DMA_TO_DEVICE, 95 .ee_mask = MHI_CH_EE_AMSS, 96 .pollcfg = 0, 97 .doorbell = MHI_DB_BRST_DISABLE, 98 .lpm_notify = false, 99 .offload_channel = false, 100 .doorbell_mode_switch = false, 101 .auto_queue = false, 102 .wake_capable = false, 103 }, 104 { 105 .name = "QAIC_DIAG", 106 .num = 5, 107 .num_elements = 32, 108 .local_elements = 0, 109 .event_ring = 0, 110 .dir = DMA_FROM_DEVICE, 111 .ee_mask = MHI_CH_EE_AMSS, 112 .pollcfg = 0, 113 .doorbell = MHI_DB_BRST_DISABLE, 114 .lpm_notify = false, 115 .offload_channel = false, 116 .doorbell_mode_switch = false, 117 .auto_queue = false, 118 .wake_capable = false, 119 }, 120 { 121 .name = "QAIC_SSR", 122 .num = 6, 123 .num_elements = 32, 124 .local_elements = 0, 125 .event_ring = 0, 126 .dir = DMA_TO_DEVICE, 127 .ee_mask = MHI_CH_EE_AMSS, 128 .pollcfg = 0, 129 .doorbell = MHI_DB_BRST_DISABLE, 130 .lpm_notify = false, 131 .offload_channel = false, 132 .doorbell_mode_switch = false, 133 .auto_queue = false, 134 .wake_capable = false, 135 }, 136 { 137 .name = "QAIC_SSR", 138 .num = 7, 139 .num_elements = 32, 140 .local_elements = 0, 141 .event_ring = 0, 142 .dir = DMA_FROM_DEVICE, 143 .ee_mask = MHI_CH_EE_AMSS, 144 .pollcfg = 0, 145 .doorbell = MHI_DB_BRST_DISABLE, 146 .lpm_notify = false, 147 .offload_channel = false, 148 .doorbell_mode_switch = false, 149 .auto_queue = false, 150 .wake_capable = false, 151 }, 152 { 153 .name = "QAIC_QDSS", 154 .num = 8, 155 .num_elements = 32, 156 .local_elements = 0, 157 .event_ring = 0, 158 .dir = DMA_TO_DEVICE, 159 .ee_mask = MHI_CH_EE_AMSS, 160 .pollcfg = 0, 161 .doorbell = MHI_DB_BRST_DISABLE, 162 .lpm_notify = false, 163 .offload_channel = false, 164 .doorbell_mode_switch = false, 165 .auto_queue = false, 166 .wake_capable = false, 167 }, 168 { 169 .name = "QAIC_QDSS", 170 .num = 9, 171 .num_elements = 32, 172 .local_elements = 0, 173 .event_ring = 0, 174 .dir = DMA_FROM_DEVICE, 175 .ee_mask = MHI_CH_EE_AMSS, 176 .pollcfg = 0, 177 .doorbell = MHI_DB_BRST_DISABLE, 178 .lpm_notify = false, 179 .offload_channel = false, 180 .doorbell_mode_switch = false, 181 .auto_queue = false, 182 .wake_capable = false, 183 }, 184 { 185 .name = "QAIC_CONTROL", 186 .num = 10, 187 .num_elements = 128, 188 .local_elements = 0, 189 .event_ring = 0, 190 .dir = DMA_TO_DEVICE, 191 .ee_mask = MHI_CH_EE_AMSS, 192 .pollcfg = 0, 193 .doorbell = MHI_DB_BRST_DISABLE, 194 .lpm_notify = false, 195 .offload_channel = false, 196 .doorbell_mode_switch = false, 197 .auto_queue = false, 198 .wake_capable = false, 199 }, 200 { 201 .name = "QAIC_CONTROL", 202 .num = 11, 203 .num_elements = 128, 204 .local_elements = 0, 205 .event_ring = 0, 206 .dir = DMA_FROM_DEVICE, 207 .ee_mask = MHI_CH_EE_AMSS, 208 .pollcfg = 0, 209 .doorbell = MHI_DB_BRST_DISABLE, 210 .lpm_notify = false, 211 .offload_channel = false, 212 .doorbell_mode_switch = false, 213 .auto_queue = false, 214 .wake_capable = false, 215 }, 216 { 217 .name = "QAIC_LOGGING", 218 .num = 12, 219 .num_elements = 32, 220 .local_elements = 0, 221 .event_ring = 0, 222 .dir = DMA_TO_DEVICE, 223 .ee_mask = MHI_CH_EE_SBL, 224 .pollcfg = 0, 225 .doorbell = MHI_DB_BRST_DISABLE, 226 .lpm_notify = false, 227 .offload_channel = false, 228 .doorbell_mode_switch = false, 229 .auto_queue = false, 230 .wake_capable = false, 231 }, 232 { 233 .name = "QAIC_LOGGING", 234 .num = 13, 235 .num_elements = 32, 236 .local_elements = 0, 237 .event_ring = 0, 238 .dir = DMA_FROM_DEVICE, 239 .ee_mask = MHI_CH_EE_SBL, 240 .pollcfg = 0, 241 .doorbell = MHI_DB_BRST_DISABLE, 242 .lpm_notify = false, 243 .offload_channel = false, 244 .doorbell_mode_switch = false, 245 .auto_queue = false, 246 .wake_capable = false, 247 }, 248 { 249 .name = "QAIC_STATUS", 250 .num = 14, 251 .num_elements = 32, 252 .local_elements = 0, 253 .event_ring = 0, 254 .dir = DMA_TO_DEVICE, 255 .ee_mask = MHI_CH_EE_AMSS, 256 .pollcfg = 0, 257 .doorbell = MHI_DB_BRST_DISABLE, 258 .lpm_notify = false, 259 .offload_channel = false, 260 .doorbell_mode_switch = false, 261 .auto_queue = false, 262 .wake_capable = false, 263 }, 264 { 265 .name = "QAIC_STATUS", 266 .num = 15, 267 .num_elements = 32, 268 .local_elements = 0, 269 .event_ring = 0, 270 .dir = DMA_FROM_DEVICE, 271 .ee_mask = MHI_CH_EE_AMSS, 272 .pollcfg = 0, 273 .doorbell = MHI_DB_BRST_DISABLE, 274 .lpm_notify = false, 275 .offload_channel = false, 276 .doorbell_mode_switch = false, 277 .auto_queue = false, 278 .wake_capable = false, 279 }, 280 { 281 .name = "QAIC_TELEMETRY", 282 .num = 16, 283 .num_elements = 32, 284 .local_elements = 0, 285 .event_ring = 0, 286 .dir = DMA_TO_DEVICE, 287 .ee_mask = MHI_CH_EE_AMSS, 288 .pollcfg = 0, 289 .doorbell = MHI_DB_BRST_DISABLE, 290 .lpm_notify = false, 291 .offload_channel = false, 292 .doorbell_mode_switch = false, 293 .auto_queue = false, 294 .wake_capable = false, 295 }, 296 { 297 .name = "QAIC_TELEMETRY", 298 .num = 17, 299 .num_elements = 32, 300 .local_elements = 0, 301 .event_ring = 0, 302 .dir = DMA_FROM_DEVICE, 303 .ee_mask = MHI_CH_EE_AMSS, 304 .pollcfg = 0, 305 .doorbell = MHI_DB_BRST_DISABLE, 306 .lpm_notify = false, 307 .offload_channel = false, 308 .doorbell_mode_switch = false, 309 .auto_queue = false, 310 .wake_capable = false, 311 }, 312 { 313 .name = "QAIC_DEBUG", 314 .num = 18, 315 .num_elements = 32, 316 .local_elements = 0, 317 .event_ring = 0, 318 .dir = DMA_TO_DEVICE, 319 .ee_mask = MHI_CH_EE_AMSS, 320 .pollcfg = 0, 321 .doorbell = MHI_DB_BRST_DISABLE, 322 .lpm_notify = false, 323 .offload_channel = false, 324 .doorbell_mode_switch = false, 325 .auto_queue = false, 326 .wake_capable = false, 327 }, 328 { 329 .name = "QAIC_DEBUG", 330 .num = 19, 331 .num_elements = 32, 332 .local_elements = 0, 333 .event_ring = 0, 334 .dir = DMA_FROM_DEVICE, 335 .ee_mask = MHI_CH_EE_AMSS, 336 .pollcfg = 0, 337 .doorbell = MHI_DB_BRST_DISABLE, 338 .lpm_notify = false, 339 .offload_channel = false, 340 .doorbell_mode_switch = false, 341 .auto_queue = false, 342 .wake_capable = false, 343 }, 344 { 345 .name = "QAIC_TIMESYNC", 346 .num = 20, 347 .num_elements = 32, 348 .local_elements = 0, 349 .event_ring = 0, 350 .dir = DMA_TO_DEVICE, 351 .ee_mask = MHI_CH_EE_SBL, 352 .pollcfg = 0, 353 .doorbell = MHI_DB_BRST_DISABLE, 354 .lpm_notify = false, 355 .offload_channel = false, 356 .doorbell_mode_switch = false, 357 .auto_queue = false, 358 .wake_capable = false, 359 }, 360 { 361 .name = "QAIC_TIMESYNC", 362 .num = 21, 363 .num_elements = 32, 364 .local_elements = 0, 365 .event_ring = 0, 366 .dir = DMA_FROM_DEVICE, 367 .ee_mask = MHI_CH_EE_SBL, 368 .pollcfg = 0, 369 .doorbell = MHI_DB_BRST_DISABLE, 370 .lpm_notify = false, 371 .offload_channel = false, 372 .doorbell_mode_switch = false, 373 .auto_queue = false, 374 .wake_capable = false, 375 }, 376 { 377 .name = "QAIC_TIMESYNC_PERIODIC", 378 .num = 22, 379 .num_elements = 32, 380 .local_elements = 0, 381 .event_ring = 0, 382 .dir = DMA_TO_DEVICE, 383 .ee_mask = MHI_CH_EE_AMSS, 384 .pollcfg = 0, 385 .doorbell = MHI_DB_BRST_DISABLE, 386 .lpm_notify = false, 387 .offload_channel = false, 388 .doorbell_mode_switch = false, 389 .auto_queue = false, 390 .wake_capable = false, 391 }, 392 { 393 .name = "QAIC_TIMESYNC_PERIODIC", 394 .num = 23, 395 .num_elements = 32, 396 .local_elements = 0, 397 .event_ring = 0, 398 .dir = DMA_FROM_DEVICE, 399 .ee_mask = MHI_CH_EE_AMSS, 400 .pollcfg = 0, 401 .doorbell = MHI_DB_BRST_DISABLE, 402 .lpm_notify = false, 403 .offload_channel = false, 404 .doorbell_mode_switch = false, 405 .auto_queue = false, 406 .wake_capable = false, 407 }, 408 { 409 .name = "IPCR", 410 .num = 24, 411 .num_elements = 32, 412 .local_elements = 0, 413 .event_ring = 0, 414 .dir = DMA_TO_DEVICE, 415 .ee_mask = MHI_CH_EE_AMSS, 416 .pollcfg = 0, 417 .doorbell = MHI_DB_BRST_DISABLE, 418 .lpm_notify = false, 419 .offload_channel = false, 420 .doorbell_mode_switch = false, 421 .auto_queue = false, 422 .wake_capable = false, 423 }, 424 { 425 .name = "IPCR", 426 .num = 25, 427 .num_elements = 32, 428 .local_elements = 0, 429 .event_ring = 0, 430 .dir = DMA_FROM_DEVICE, 431 .ee_mask = MHI_CH_EE_AMSS, 432 .pollcfg = 0, 433 .doorbell = MHI_DB_BRST_DISABLE, 434 .lpm_notify = false, 435 .offload_channel = false, 436 .doorbell_mode_switch = false, 437 .auto_queue = true, 438 .wake_capable = false, 439 }, 440 }; 441 442 static struct mhi_event_config aic100_events[] = { 443 { 444 .num_elements = 32, 445 .irq_moderation_ms = 0, 446 .irq = 0, 447 .channel = U32_MAX, 448 .priority = 1, 449 .mode = MHI_DB_BRST_DISABLE, 450 .data_type = MHI_ER_CTRL, 451 .hardware_event = false, 452 .client_managed = false, 453 .offload_channel = false, 454 }, 455 }; 456 457 static struct mhi_controller_config aic100_config = { 458 .max_channels = 128, 459 .timeout_ms = 0, /* controlled by mhi_timeout */ 460 .buf_len = 0, 461 .num_channels = ARRAY_SIZE(aic100_channels), 462 .ch_cfg = aic100_channels, 463 .num_events = ARRAY_SIZE(aic100_events), 464 .event_cfg = aic100_events, 465 .use_bounce_buf = false, 466 .m2_no_db = false, 467 }; 468 469 static int mhi_read_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 *out) 470 { 471 u32 tmp; 472 473 /* 474 * SOC_HW_VERSION quirk 475 * The SOC_HW_VERSION register (offset 0x224) is not reliable and 476 * may contain uninitialized values, including 0xFFFFFFFF. This could 477 * cause a false positive link down error. Instead, intercept any 478 * reads and provide the correct value of the register. 479 */ 480 if (addr - mhi_cntrl->regs == 0x224) { 481 *out = 0x60110200; 482 return 0; 483 } 484 485 tmp = readl_relaxed(addr); 486 if (tmp == U32_MAX) 487 return -EIO; 488 489 *out = tmp; 490 491 return 0; 492 } 493 494 static void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 val) 495 { 496 writel_relaxed(val, addr); 497 } 498 499 static int mhi_runtime_get(struct mhi_controller *mhi_cntrl) 500 { 501 return 0; 502 } 503 504 static void mhi_runtime_put(struct mhi_controller *mhi_cntrl) 505 { 506 } 507 508 static void mhi_status_cb(struct mhi_controller *mhi_cntrl, enum mhi_callback reason) 509 { 510 struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_cntrl->cntrl_dev)); 511 512 /* this event occurs in atomic context */ 513 if (reason == MHI_CB_FATAL_ERROR) 514 pci_err(qdev->pdev, "Fatal error received from device. Attempting to recover\n"); 515 /* this event occurs in non-atomic context */ 516 if (reason == MHI_CB_SYS_ERROR) 517 qaic_dev_reset_clean_local_state(qdev); 518 } 519 520 static int mhi_reset_and_async_power_up(struct mhi_controller *mhi_cntrl) 521 { 522 u8 time_sec = 1; 523 int current_ee; 524 int ret; 525 526 /* Reset the device to bring the device in PBL EE */ 527 mhi_soc_reset(mhi_cntrl); 528 529 /* 530 * Keep checking the execution environment(EE) after every 1 second 531 * interval. 532 */ 533 do { 534 msleep(1000); 535 current_ee = mhi_get_exec_env(mhi_cntrl); 536 } while (current_ee != MHI_EE_PBL && time_sec++ <= MAX_RESET_TIME_SEC); 537 538 /* If the device is in PBL EE retry power up */ 539 if (current_ee == MHI_EE_PBL) 540 ret = mhi_async_power_up(mhi_cntrl); 541 else 542 ret = -EIO; 543 544 return ret; 545 } 546 547 struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar, 548 int mhi_irq, bool shared_msi) 549 { 550 struct mhi_controller *mhi_cntrl; 551 int ret; 552 553 mhi_cntrl = devm_kzalloc(&pci_dev->dev, sizeof(*mhi_cntrl), GFP_KERNEL); 554 if (!mhi_cntrl) 555 return ERR_PTR(-ENOMEM); 556 557 mhi_cntrl->cntrl_dev = &pci_dev->dev; 558 559 /* 560 * Covers the entire possible physical ram region. Remote side is 561 * going to calculate a size of this range, so subtract 1 to prevent 562 * rollover. 563 */ 564 mhi_cntrl->iova_start = 0; 565 mhi_cntrl->iova_stop = PHYS_ADDR_MAX - 1; 566 mhi_cntrl->status_cb = mhi_status_cb; 567 mhi_cntrl->runtime_get = mhi_runtime_get; 568 mhi_cntrl->runtime_put = mhi_runtime_put; 569 mhi_cntrl->read_reg = mhi_read_reg; 570 mhi_cntrl->write_reg = mhi_write_reg; 571 mhi_cntrl->regs = mhi_bar; 572 mhi_cntrl->reg_len = SZ_4K; 573 mhi_cntrl->nr_irqs = 1; 574 mhi_cntrl->irq = devm_kmalloc(&pci_dev->dev, sizeof(*mhi_cntrl->irq), GFP_KERNEL); 575 576 if (!mhi_cntrl->irq) 577 return ERR_PTR(-ENOMEM); 578 579 mhi_cntrl->irq[0] = mhi_irq; 580 581 if (shared_msi) /* MSI shared with data path, no IRQF_NO_SUSPEND */ 582 mhi_cntrl->irq_flags = IRQF_SHARED; 583 584 mhi_cntrl->fw_image = "qcom/aic100/sbl.bin"; 585 586 /* use latest configured timeout */ 587 aic100_config.timeout_ms = mhi_timeout_ms; 588 ret = mhi_register_controller(mhi_cntrl, &aic100_config); 589 if (ret) { 590 pci_err(pci_dev, "mhi_register_controller failed %d\n", ret); 591 return ERR_PTR(ret); 592 } 593 594 ret = mhi_prepare_for_power_up(mhi_cntrl); 595 if (ret) { 596 pci_err(pci_dev, "mhi_prepare_for_power_up failed %d\n", ret); 597 goto prepare_power_up_fail; 598 } 599 600 ret = mhi_async_power_up(mhi_cntrl); 601 /* 602 * If EIO is returned it is possible that device is in SBL EE, which is 603 * undesired. SOC reset the device and try to power up again. 604 */ 605 if (ret == -EIO && MHI_EE_SBL == mhi_get_exec_env(mhi_cntrl)) { 606 pci_err(pci_dev, "Found device in SBL at MHI init. Attempting a reset.\n"); 607 ret = mhi_reset_and_async_power_up(mhi_cntrl); 608 } 609 610 if (ret) { 611 pci_err(pci_dev, "mhi_async_power_up failed %d\n", ret); 612 goto power_up_fail; 613 } 614 615 return mhi_cntrl; 616 617 power_up_fail: 618 mhi_unprepare_after_power_down(mhi_cntrl); 619 prepare_power_up_fail: 620 mhi_unregister_controller(mhi_cntrl); 621 return ERR_PTR(ret); 622 } 623 624 void qaic_mhi_free_controller(struct mhi_controller *mhi_cntrl, bool link_up) 625 { 626 mhi_power_down(mhi_cntrl, link_up); 627 mhi_unprepare_after_power_down(mhi_cntrl); 628 mhi_unregister_controller(mhi_cntrl); 629 } 630 631 void qaic_mhi_start_reset(struct mhi_controller *mhi_cntrl) 632 { 633 mhi_power_down(mhi_cntrl, true); 634 } 635 636 void qaic_mhi_reset_done(struct mhi_controller *mhi_cntrl) 637 { 638 struct pci_dev *pci_dev = container_of(mhi_cntrl->cntrl_dev, struct pci_dev, dev); 639 int ret; 640 641 ret = mhi_async_power_up(mhi_cntrl); 642 if (ret) 643 pci_err(pci_dev, "mhi_async_power_up failed after reset %d\n", ret); 644 } 645