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 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 | MHI_CH_EE_AMSS, 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 .num = 21, 362 .name = "QAIC_TIMESYNC", 363 .num_elements = 32, 364 .local_elements = 0, 365 .event_ring = 0, 366 .dir = DMA_FROM_DEVICE, 367 .ee_mask = MHI_CH_EE_SBL | MHI_CH_EE_AMSS, 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 378 static struct mhi_event_config aic100_events[] = { 379 { 380 .num_elements = 32, 381 .irq_moderation_ms = 0, 382 .irq = 0, 383 .channel = U32_MAX, 384 .priority = 1, 385 .mode = MHI_DB_BRST_DISABLE, 386 .data_type = MHI_ER_CTRL, 387 .hardware_event = false, 388 .client_managed = false, 389 .offload_channel = false, 390 }, 391 }; 392 393 static struct mhi_controller_config aic100_config = { 394 .max_channels = 128, 395 .timeout_ms = 0, /* controlled by mhi_timeout */ 396 .buf_len = 0, 397 .num_channels = ARRAY_SIZE(aic100_channels), 398 .ch_cfg = aic100_channels, 399 .num_events = ARRAY_SIZE(aic100_events), 400 .event_cfg = aic100_events, 401 .use_bounce_buf = false, 402 .m2_no_db = false, 403 }; 404 405 static int mhi_read_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 *out) 406 { 407 u32 tmp = readl_relaxed(addr); 408 409 if (tmp == U32_MAX) 410 return -EIO; 411 412 *out = tmp; 413 414 return 0; 415 } 416 417 static void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 val) 418 { 419 writel_relaxed(val, addr); 420 } 421 422 static int mhi_runtime_get(struct mhi_controller *mhi_cntrl) 423 { 424 return 0; 425 } 426 427 static void mhi_runtime_put(struct mhi_controller *mhi_cntrl) 428 { 429 } 430 431 static void mhi_status_cb(struct mhi_controller *mhi_cntrl, enum mhi_callback reason) 432 { 433 struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_cntrl->cntrl_dev)); 434 435 /* this event occurs in atomic context */ 436 if (reason == MHI_CB_FATAL_ERROR) 437 pci_err(qdev->pdev, "Fatal error received from device. Attempting to recover\n"); 438 /* this event occurs in non-atomic context */ 439 if (reason == MHI_CB_SYS_ERROR) 440 qaic_dev_reset_clean_local_state(qdev, true); 441 } 442 443 static int mhi_reset_and_async_power_up(struct mhi_controller *mhi_cntrl) 444 { 445 u8 time_sec = 1; 446 int current_ee; 447 int ret; 448 449 /* Reset the device to bring the device in PBL EE */ 450 mhi_soc_reset(mhi_cntrl); 451 452 /* 453 * Keep checking the execution environment(EE) after every 1 second 454 * interval. 455 */ 456 do { 457 msleep(1000); 458 current_ee = mhi_get_exec_env(mhi_cntrl); 459 } while (current_ee != MHI_EE_PBL && time_sec++ <= MAX_RESET_TIME_SEC); 460 461 /* If the device is in PBL EE retry power up */ 462 if (current_ee == MHI_EE_PBL) 463 ret = mhi_async_power_up(mhi_cntrl); 464 else 465 ret = -EIO; 466 467 return ret; 468 } 469 470 struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar, 471 int mhi_irq) 472 { 473 struct mhi_controller *mhi_cntrl; 474 int ret; 475 476 mhi_cntrl = devm_kzalloc(&pci_dev->dev, sizeof(*mhi_cntrl), GFP_KERNEL); 477 if (!mhi_cntrl) 478 return ERR_PTR(-ENOMEM); 479 480 mhi_cntrl->cntrl_dev = &pci_dev->dev; 481 482 /* 483 * Covers the entire possible physical ram region. Remote side is 484 * going to calculate a size of this range, so subtract 1 to prevent 485 * rollover. 486 */ 487 mhi_cntrl->iova_start = 0; 488 mhi_cntrl->iova_stop = PHYS_ADDR_MAX - 1; 489 mhi_cntrl->status_cb = mhi_status_cb; 490 mhi_cntrl->runtime_get = mhi_runtime_get; 491 mhi_cntrl->runtime_put = mhi_runtime_put; 492 mhi_cntrl->read_reg = mhi_read_reg; 493 mhi_cntrl->write_reg = mhi_write_reg; 494 mhi_cntrl->regs = mhi_bar; 495 mhi_cntrl->reg_len = SZ_4K; 496 mhi_cntrl->nr_irqs = 1; 497 mhi_cntrl->irq = devm_kmalloc(&pci_dev->dev, sizeof(*mhi_cntrl->irq), GFP_KERNEL); 498 499 if (!mhi_cntrl->irq) 500 return ERR_PTR(-ENOMEM); 501 502 mhi_cntrl->irq[0] = mhi_irq; 503 mhi_cntrl->fw_image = "qcom/aic100/sbl.bin"; 504 505 /* use latest configured timeout */ 506 aic100_config.timeout_ms = mhi_timeout_ms; 507 ret = mhi_register_controller(mhi_cntrl, &aic100_config); 508 if (ret) { 509 pci_err(pci_dev, "mhi_register_controller failed %d\n", ret); 510 return ERR_PTR(ret); 511 } 512 513 ret = mhi_prepare_for_power_up(mhi_cntrl); 514 if (ret) { 515 pci_err(pci_dev, "mhi_prepare_for_power_up failed %d\n", ret); 516 goto prepare_power_up_fail; 517 } 518 519 ret = mhi_async_power_up(mhi_cntrl); 520 /* 521 * If EIO is returned it is possible that device is in SBL EE, which is 522 * undesired. SOC reset the device and try to power up again. 523 */ 524 if (ret == -EIO && MHI_EE_SBL == mhi_get_exec_env(mhi_cntrl)) { 525 pci_err(pci_dev, "Found device in SBL at MHI init. Attempting a reset.\n"); 526 ret = mhi_reset_and_async_power_up(mhi_cntrl); 527 } 528 529 if (ret) { 530 pci_err(pci_dev, "mhi_async_power_up failed %d\n", ret); 531 goto power_up_fail; 532 } 533 534 return mhi_cntrl; 535 536 power_up_fail: 537 mhi_unprepare_after_power_down(mhi_cntrl); 538 prepare_power_up_fail: 539 mhi_unregister_controller(mhi_cntrl); 540 return ERR_PTR(ret); 541 } 542 543 void qaic_mhi_free_controller(struct mhi_controller *mhi_cntrl, bool link_up) 544 { 545 mhi_power_down(mhi_cntrl, link_up); 546 mhi_unprepare_after_power_down(mhi_cntrl); 547 mhi_unregister_controller(mhi_cntrl); 548 } 549 550 void qaic_mhi_start_reset(struct mhi_controller *mhi_cntrl) 551 { 552 mhi_power_down(mhi_cntrl, true); 553 } 554 555 void qaic_mhi_reset_done(struct mhi_controller *mhi_cntrl) 556 { 557 struct pci_dev *pci_dev = container_of(mhi_cntrl->cntrl_dev, struct pci_dev, dev); 558 int ret; 559 560 ret = mhi_async_power_up(mhi_cntrl); 561 if (ret) 562 pci_err(pci_dev, "mhi_async_power_up failed after reset %d\n", ret); 563 } 564