1 // SPDX-License-Identifier: BSD-3-Clause-Clear 2 /* 3 * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. 4 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. 5 */ 6 7 #include <linux/msi.h> 8 #include <linux/pci.h> 9 #include <linux/firmware.h> 10 11 #include "core.h" 12 #include "debug.h" 13 #include "mhi.h" 14 #include "pci.h" 15 16 #define MHI_TIMEOUT_DEFAULT_MS 90000 17 #define OTP_INVALID_BOARD_ID 0xFFFF 18 #define OTP_VALID_DUALMAC_BOARD_ID_MASK 0x1000 19 20 static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = { 21 { 22 .num = 20, 23 .name = "IPCR", 24 .num_elements = 32, 25 .event_ring = 1, 26 .dir = DMA_TO_DEVICE, 27 .ee_mask = 0x4, 28 .pollcfg = 0, 29 .doorbell = MHI_DB_BRST_DISABLE, 30 .lpm_notify = false, 31 .offload_channel = false, 32 .doorbell_mode_switch = false, 33 .auto_queue = false, 34 }, 35 { 36 .num = 21, 37 .name = "IPCR", 38 .num_elements = 32, 39 .event_ring = 1, 40 .dir = DMA_FROM_DEVICE, 41 .ee_mask = 0x4, 42 .pollcfg = 0, 43 .doorbell = MHI_DB_BRST_DISABLE, 44 .lpm_notify = false, 45 .offload_channel = false, 46 .doorbell_mode_switch = false, 47 .auto_queue = true, 48 }, 49 }; 50 51 static struct mhi_event_config ath12k_mhi_events_qcn9274[] = { 52 { 53 .num_elements = 32, 54 .irq_moderation_ms = 0, 55 .irq = 1, 56 .data_type = MHI_ER_CTRL, 57 .mode = MHI_DB_BRST_DISABLE, 58 .hardware_event = false, 59 .client_managed = false, 60 .offload_channel = false, 61 }, 62 { 63 .num_elements = 256, 64 .irq_moderation_ms = 1, 65 .irq = 2, 66 .mode = MHI_DB_BRST_DISABLE, 67 .priority = 1, 68 .hardware_event = false, 69 .client_managed = false, 70 .offload_channel = false, 71 }, 72 }; 73 74 const struct mhi_controller_config ath12k_mhi_config_qcn9274 = { 75 .max_channels = 30, 76 .timeout_ms = 10000, 77 .use_bounce_buf = false, 78 .buf_len = 0, 79 .num_channels = ARRAY_SIZE(ath12k_mhi_channels_qcn9274), 80 .ch_cfg = ath12k_mhi_channels_qcn9274, 81 .num_events = ARRAY_SIZE(ath12k_mhi_events_qcn9274), 82 .event_cfg = ath12k_mhi_events_qcn9274, 83 }; 84 85 static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = { 86 { 87 .num = 20, 88 .name = "IPCR", 89 .num_elements = 64, 90 .event_ring = 1, 91 .dir = DMA_TO_DEVICE, 92 .ee_mask = 0x4, 93 .pollcfg = 0, 94 .doorbell = MHI_DB_BRST_DISABLE, 95 .lpm_notify = false, 96 .offload_channel = false, 97 .doorbell_mode_switch = false, 98 .auto_queue = false, 99 }, 100 { 101 .num = 21, 102 .name = "IPCR", 103 .num_elements = 64, 104 .event_ring = 1, 105 .dir = DMA_FROM_DEVICE, 106 .ee_mask = 0x4, 107 .pollcfg = 0, 108 .doorbell = MHI_DB_BRST_DISABLE, 109 .lpm_notify = false, 110 .offload_channel = false, 111 .doorbell_mode_switch = false, 112 .auto_queue = true, 113 }, 114 }; 115 116 static struct mhi_event_config ath12k_mhi_events_wcn7850[] = { 117 { 118 .num_elements = 32, 119 .irq_moderation_ms = 0, 120 .irq = 1, 121 .mode = MHI_DB_BRST_DISABLE, 122 .data_type = MHI_ER_CTRL, 123 .hardware_event = false, 124 .client_managed = false, 125 .offload_channel = false, 126 }, 127 { 128 .num_elements = 256, 129 .irq_moderation_ms = 1, 130 .irq = 2, 131 .mode = MHI_DB_BRST_DISABLE, 132 .priority = 1, 133 .hardware_event = false, 134 .client_managed = false, 135 .offload_channel = false, 136 }, 137 }; 138 139 const struct mhi_controller_config ath12k_mhi_config_wcn7850 = { 140 .max_channels = 128, 141 .timeout_ms = 2000, 142 .use_bounce_buf = false, 143 .buf_len = 8192, 144 .num_channels = ARRAY_SIZE(ath12k_mhi_channels_wcn7850), 145 .ch_cfg = ath12k_mhi_channels_wcn7850, 146 .num_events = ARRAY_SIZE(ath12k_mhi_events_wcn7850), 147 .event_cfg = ath12k_mhi_events_wcn7850, 148 }; 149 150 void ath12k_mhi_set_mhictrl_reset(struct ath12k_base *ab) 151 { 152 u32 val; 153 154 val = ath12k_pci_read32(ab, MHISTATUS); 155 156 ath12k_dbg(ab, ATH12K_DBG_PCI, "MHISTATUS 0x%x\n", val); 157 158 /* Observed on some targets that after SOC_GLOBAL_RESET, MHISTATUS 159 * has SYSERR bit set and thus need to set MHICTRL_RESET 160 * to clear SYSERR. 161 */ 162 ath12k_pci_write32(ab, MHICTRL, MHICTRL_RESET_MASK); 163 164 mdelay(10); 165 } 166 167 static void ath12k_mhi_reset_txvecdb(struct ath12k_base *ab) 168 { 169 ath12k_pci_write32(ab, PCIE_TXVECDB, 0); 170 } 171 172 static void ath12k_mhi_reset_txvecstatus(struct ath12k_base *ab) 173 { 174 ath12k_pci_write32(ab, PCIE_TXVECSTATUS, 0); 175 } 176 177 static void ath12k_mhi_reset_rxvecdb(struct ath12k_base *ab) 178 { 179 ath12k_pci_write32(ab, PCIE_RXVECDB, 0); 180 } 181 182 static void ath12k_mhi_reset_rxvecstatus(struct ath12k_base *ab) 183 { 184 ath12k_pci_write32(ab, PCIE_RXVECSTATUS, 0); 185 } 186 187 void ath12k_mhi_clear_vector(struct ath12k_base *ab) 188 { 189 ath12k_mhi_reset_txvecdb(ab); 190 ath12k_mhi_reset_txvecstatus(ab); 191 ath12k_mhi_reset_rxvecdb(ab); 192 ath12k_mhi_reset_rxvecstatus(ab); 193 } 194 195 static int ath12k_mhi_get_msi(struct ath12k_pci *ab_pci) 196 { 197 struct ath12k_base *ab = ab_pci->ab; 198 u32 user_base_data, base_vector; 199 int ret, num_vectors, i; 200 int *irq; 201 unsigned int msi_data; 202 203 ret = ath12k_pci_get_user_msi_assignment(ab, 204 "MHI", &num_vectors, 205 &user_base_data, &base_vector); 206 if (ret) 207 return ret; 208 209 ath12k_dbg(ab, ATH12K_DBG_PCI, "Number of assigned MSI for MHI is %d, base vector is %d\n", 210 num_vectors, base_vector); 211 212 irq = kcalloc(num_vectors, sizeof(*irq), GFP_KERNEL); 213 if (!irq) 214 return -ENOMEM; 215 216 msi_data = base_vector; 217 for (i = 0; i < num_vectors; i++) { 218 if (test_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) 219 irq[i] = ath12k_pci_get_msi_irq(ab->dev, 220 msi_data++); 221 else 222 irq[i] = ath12k_pci_get_msi_irq(ab->dev, 223 msi_data); 224 } 225 226 ab_pci->mhi_ctrl->irq = irq; 227 ab_pci->mhi_ctrl->nr_irqs = num_vectors; 228 229 return 0; 230 } 231 232 static int ath12k_mhi_op_runtime_get(struct mhi_controller *mhi_cntrl) 233 { 234 return 0; 235 } 236 237 static void ath12k_mhi_op_runtime_put(struct mhi_controller *mhi_cntrl) 238 { 239 } 240 241 static char *ath12k_mhi_op_callback_to_str(enum mhi_callback reason) 242 { 243 switch (reason) { 244 case MHI_CB_IDLE: 245 return "MHI_CB_IDLE"; 246 case MHI_CB_PENDING_DATA: 247 return "MHI_CB_PENDING_DATA"; 248 case MHI_CB_LPM_ENTER: 249 return "MHI_CB_LPM_ENTER"; 250 case MHI_CB_LPM_EXIT: 251 return "MHI_CB_LPM_EXIT"; 252 case MHI_CB_EE_RDDM: 253 return "MHI_CB_EE_RDDM"; 254 case MHI_CB_EE_MISSION_MODE: 255 return "MHI_CB_EE_MISSION_MODE"; 256 case MHI_CB_SYS_ERROR: 257 return "MHI_CB_SYS_ERROR"; 258 case MHI_CB_FATAL_ERROR: 259 return "MHI_CB_FATAL_ERROR"; 260 case MHI_CB_BW_REQ: 261 return "MHI_CB_BW_REQ"; 262 default: 263 return "UNKNOWN"; 264 } 265 } 266 267 static void ath12k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl, 268 enum mhi_callback cb) 269 { 270 struct ath12k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev); 271 272 ath12k_dbg(ab, ATH12K_DBG_BOOT, "mhi notify status reason %s\n", 273 ath12k_mhi_op_callback_to_str(cb)); 274 275 switch (cb) { 276 case MHI_CB_SYS_ERROR: 277 ath12k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n"); 278 break; 279 case MHI_CB_EE_RDDM: 280 if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags))) 281 queue_work(ab->workqueue_aux, &ab->reset_work); 282 break; 283 default: 284 break; 285 } 286 } 287 288 static int ath12k_mhi_op_read_reg(struct mhi_controller *mhi_cntrl, 289 void __iomem *addr, 290 u32 *out) 291 { 292 *out = readl(addr); 293 294 return 0; 295 } 296 297 static void ath12k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl, 298 void __iomem *addr, 299 u32 val) 300 { 301 writel(val, addr); 302 } 303 304 int ath12k_mhi_register(struct ath12k_pci *ab_pci) 305 { 306 struct ath12k_base *ab = ab_pci->ab; 307 struct mhi_controller *mhi_ctrl; 308 unsigned int board_id; 309 int ret; 310 bool dualmac = false; 311 312 mhi_ctrl = mhi_alloc_controller(); 313 if (!mhi_ctrl) 314 return -ENOMEM; 315 316 ab_pci->mhi_ctrl = mhi_ctrl; 317 mhi_ctrl->cntrl_dev = ab->dev; 318 mhi_ctrl->regs = ab->mem; 319 mhi_ctrl->reg_len = ab->mem_len; 320 mhi_ctrl->rddm_size = ab->hw_params->rddm_size; 321 322 if (ab->hw_params->otp_board_id_register) { 323 board_id = 324 ath12k_pci_read32(ab, ab->hw_params->otp_board_id_register); 325 board_id = u32_get_bits(board_id, OTP_BOARD_ID_MASK); 326 327 if (!board_id || (board_id == OTP_INVALID_BOARD_ID)) { 328 ath12k_dbg(ab, ATH12K_DBG_BOOT, 329 "failed to read board id\n"); 330 } else if (board_id & OTP_VALID_DUALMAC_BOARD_ID_MASK) { 331 dualmac = true; 332 ath12k_dbg(ab, ATH12K_DBG_BOOT, 333 "dualmac fw selected for board id: %x\n", board_id); 334 } 335 } 336 337 if (dualmac) { 338 if (ab->fw.amss_dualmac_data && ab->fw.amss_dualmac_len > 0) { 339 /* use MHI firmware file from firmware-N.bin */ 340 mhi_ctrl->fw_data = ab->fw.amss_dualmac_data; 341 mhi_ctrl->fw_sz = ab->fw.amss_dualmac_len; 342 } else { 343 ath12k_warn(ab, "dualmac firmware IE not present in firmware-N.bin\n"); 344 ret = -ENOENT; 345 goto free_controller; 346 } 347 } else { 348 if (ab->fw.amss_data && ab->fw.amss_len > 0) { 349 /* use MHI firmware file from firmware-N.bin */ 350 mhi_ctrl->fw_data = ab->fw.amss_data; 351 mhi_ctrl->fw_sz = ab->fw.amss_len; 352 } else { 353 /* use the old separate mhi.bin MHI firmware file */ 354 ath12k_core_create_firmware_path(ab, ATH12K_AMSS_FILE, 355 ab_pci->amss_path, 356 sizeof(ab_pci->amss_path)); 357 mhi_ctrl->fw_image = ab_pci->amss_path; 358 } 359 } 360 361 ret = ath12k_mhi_get_msi(ab_pci); 362 if (ret) { 363 ath12k_err(ab, "failed to get msi for mhi\n"); 364 goto free_controller; 365 } 366 367 if (!test_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags)) 368 mhi_ctrl->irq_flags = IRQF_SHARED | IRQF_NOBALANCING; 369 370 mhi_ctrl->iova_start = 0; 371 mhi_ctrl->iova_stop = 0xffffffff; 372 mhi_ctrl->sbl_size = SZ_512K; 373 mhi_ctrl->seg_len = SZ_512K; 374 mhi_ctrl->fbc_download = true; 375 mhi_ctrl->runtime_get = ath12k_mhi_op_runtime_get; 376 mhi_ctrl->runtime_put = ath12k_mhi_op_runtime_put; 377 mhi_ctrl->status_cb = ath12k_mhi_op_status_cb; 378 mhi_ctrl->read_reg = ath12k_mhi_op_read_reg; 379 mhi_ctrl->write_reg = ath12k_mhi_op_write_reg; 380 381 ret = mhi_register_controller(mhi_ctrl, ab->hw_params->mhi_config); 382 if (ret) { 383 ath12k_err(ab, "failed to register to mhi bus, err = %d\n", ret); 384 goto free_controller; 385 } 386 387 return 0; 388 389 free_controller: 390 mhi_free_controller(mhi_ctrl); 391 ab_pci->mhi_ctrl = NULL; 392 return ret; 393 } 394 395 void ath12k_mhi_unregister(struct ath12k_pci *ab_pci) 396 { 397 struct mhi_controller *mhi_ctrl = ab_pci->mhi_ctrl; 398 399 mhi_unregister_controller(mhi_ctrl); 400 kfree(mhi_ctrl->irq); 401 mhi_free_controller(mhi_ctrl); 402 ab_pci->mhi_ctrl = NULL; 403 } 404 405 static char *ath12k_mhi_state_to_str(enum ath12k_mhi_state mhi_state) 406 { 407 switch (mhi_state) { 408 case ATH12K_MHI_INIT: 409 return "INIT"; 410 case ATH12K_MHI_DEINIT: 411 return "DEINIT"; 412 case ATH12K_MHI_POWER_ON: 413 return "POWER_ON"; 414 case ATH12K_MHI_POWER_OFF: 415 return "POWER_OFF"; 416 case ATH12K_MHI_POWER_OFF_KEEP_DEV: 417 return "POWER_OFF_KEEP_DEV"; 418 case ATH12K_MHI_FORCE_POWER_OFF: 419 return "FORCE_POWER_OFF"; 420 case ATH12K_MHI_SUSPEND: 421 return "SUSPEND"; 422 case ATH12K_MHI_RESUME: 423 return "RESUME"; 424 case ATH12K_MHI_TRIGGER_RDDM: 425 return "TRIGGER_RDDM"; 426 case ATH12K_MHI_RDDM_DONE: 427 return "RDDM_DONE"; 428 default: 429 return "UNKNOWN"; 430 } 431 }; 432 433 static void ath12k_mhi_set_state_bit(struct ath12k_pci *ab_pci, 434 enum ath12k_mhi_state mhi_state) 435 { 436 struct ath12k_base *ab = ab_pci->ab; 437 438 switch (mhi_state) { 439 case ATH12K_MHI_INIT: 440 set_bit(ATH12K_MHI_INIT, &ab_pci->mhi_state); 441 break; 442 case ATH12K_MHI_DEINIT: 443 clear_bit(ATH12K_MHI_INIT, &ab_pci->mhi_state); 444 break; 445 case ATH12K_MHI_POWER_ON: 446 set_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state); 447 break; 448 case ATH12K_MHI_POWER_OFF: 449 case ATH12K_MHI_POWER_OFF_KEEP_DEV: 450 case ATH12K_MHI_FORCE_POWER_OFF: 451 clear_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state); 452 clear_bit(ATH12K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state); 453 clear_bit(ATH12K_MHI_RDDM_DONE, &ab_pci->mhi_state); 454 break; 455 case ATH12K_MHI_SUSPEND: 456 set_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state); 457 break; 458 case ATH12K_MHI_RESUME: 459 clear_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state); 460 break; 461 case ATH12K_MHI_TRIGGER_RDDM: 462 set_bit(ATH12K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state); 463 break; 464 case ATH12K_MHI_RDDM_DONE: 465 set_bit(ATH12K_MHI_RDDM_DONE, &ab_pci->mhi_state); 466 break; 467 default: 468 ath12k_err(ab, "unhandled mhi state (%d)\n", mhi_state); 469 } 470 } 471 472 static int ath12k_mhi_check_state_bit(struct ath12k_pci *ab_pci, 473 enum ath12k_mhi_state mhi_state) 474 { 475 struct ath12k_base *ab = ab_pci->ab; 476 477 switch (mhi_state) { 478 case ATH12K_MHI_INIT: 479 if (!test_bit(ATH12K_MHI_INIT, &ab_pci->mhi_state)) 480 return 0; 481 break; 482 case ATH12K_MHI_DEINIT: 483 case ATH12K_MHI_POWER_ON: 484 if (test_bit(ATH12K_MHI_INIT, &ab_pci->mhi_state) && 485 !test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state)) 486 return 0; 487 break; 488 case ATH12K_MHI_FORCE_POWER_OFF: 489 if (test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state)) 490 return 0; 491 break; 492 case ATH12K_MHI_POWER_OFF: 493 case ATH12K_MHI_POWER_OFF_KEEP_DEV: 494 case ATH12K_MHI_SUSPEND: 495 if (test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state) && 496 !test_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state)) 497 return 0; 498 break; 499 case ATH12K_MHI_RESUME: 500 if (test_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state)) 501 return 0; 502 break; 503 case ATH12K_MHI_TRIGGER_RDDM: 504 if (test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state) && 505 !test_bit(ATH12K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state)) 506 return 0; 507 break; 508 case ATH12K_MHI_RDDM_DONE: 509 return 0; 510 default: 511 ath12k_err(ab, "unhandled mhi state: %s(%d)\n", 512 ath12k_mhi_state_to_str(mhi_state), mhi_state); 513 } 514 515 ath12k_err(ab, "failed to set mhi state %s(%d) in current mhi state (0x%lx)\n", 516 ath12k_mhi_state_to_str(mhi_state), mhi_state, 517 ab_pci->mhi_state); 518 519 return -EINVAL; 520 } 521 522 static int ath12k_mhi_set_state(struct ath12k_pci *ab_pci, 523 enum ath12k_mhi_state mhi_state) 524 { 525 struct ath12k_base *ab = ab_pci->ab; 526 int ret; 527 528 ret = ath12k_mhi_check_state_bit(ab_pci, mhi_state); 529 if (ret) 530 goto out; 531 532 ath12k_dbg(ab, ATH12K_DBG_PCI, "setting mhi state: %s(%d)\n", 533 ath12k_mhi_state_to_str(mhi_state), mhi_state); 534 535 switch (mhi_state) { 536 case ATH12K_MHI_INIT: 537 ret = mhi_prepare_for_power_up(ab_pci->mhi_ctrl); 538 break; 539 case ATH12K_MHI_DEINIT: 540 mhi_unprepare_after_power_down(ab_pci->mhi_ctrl); 541 ret = 0; 542 break; 543 case ATH12K_MHI_POWER_ON: 544 /* In case of resume, QRTR's resume_early() is called 545 * right after ath12k' resume_early(). Since QRTR requires 546 * MHI mission mode state when preparing IPCR channels 547 * (see ee_mask of that channel), we need to use the 'sync' 548 * version here to make sure MHI is in that state when we 549 * return. Or QRTR might resume before that state comes, 550 * and as a result it fails. 551 * 552 * The 'sync' version works for non-resume (normal power on) 553 * case as well. 554 */ 555 ret = mhi_sync_power_up(ab_pci->mhi_ctrl); 556 break; 557 case ATH12K_MHI_POWER_OFF: 558 mhi_power_down(ab_pci->mhi_ctrl, true); 559 ret = 0; 560 break; 561 case ATH12K_MHI_POWER_OFF_KEEP_DEV: 562 mhi_power_down_keep_dev(ab_pci->mhi_ctrl, true); 563 ret = 0; 564 break; 565 case ATH12K_MHI_FORCE_POWER_OFF: 566 mhi_power_down(ab_pci->mhi_ctrl, false); 567 ret = 0; 568 break; 569 case ATH12K_MHI_SUSPEND: 570 ret = mhi_pm_suspend(ab_pci->mhi_ctrl); 571 break; 572 case ATH12K_MHI_RESUME: 573 ret = mhi_pm_resume(ab_pci->mhi_ctrl); 574 break; 575 case ATH12K_MHI_TRIGGER_RDDM: 576 ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl); 577 break; 578 case ATH12K_MHI_RDDM_DONE: 579 break; 580 default: 581 ath12k_err(ab, "unhandled MHI state (%d)\n", mhi_state); 582 ret = -EINVAL; 583 } 584 585 if (ret) 586 goto out; 587 588 ath12k_mhi_set_state_bit(ab_pci, mhi_state); 589 590 return 0; 591 592 out: 593 ath12k_err(ab, "failed to set mhi state: %s(%d)\n", 594 ath12k_mhi_state_to_str(mhi_state), mhi_state); 595 return ret; 596 } 597 598 int ath12k_mhi_start(struct ath12k_pci *ab_pci) 599 { 600 int ret; 601 602 ab_pci->mhi_ctrl->timeout_ms = MHI_TIMEOUT_DEFAULT_MS; 603 604 ret = ath12k_mhi_set_state(ab_pci, ATH12K_MHI_INIT); 605 if (ret) 606 goto out; 607 608 ret = ath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_ON); 609 if (ret) 610 goto out; 611 612 return 0; 613 614 out: 615 return ret; 616 } 617 618 void ath12k_mhi_stop(struct ath12k_pci *ab_pci, bool is_suspend) 619 { 620 /* During suspend we need to use mhi_power_down_keep_dev() 621 * workaround, otherwise ath12k_core_resume() will timeout 622 * during resume. 623 */ 624 if (is_suspend) 625 ath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_OFF_KEEP_DEV); 626 else 627 ath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_OFF); 628 629 ath12k_mhi_set_state(ab_pci, ATH12K_MHI_DEINIT); 630 } 631 632 void ath12k_mhi_suspend(struct ath12k_pci *ab_pci) 633 { 634 ath12k_mhi_set_state(ab_pci, ATH12K_MHI_SUSPEND); 635 } 636 637 void ath12k_mhi_resume(struct ath12k_pci *ab_pci) 638 { 639 ath12k_mhi_set_state(ab_pci, ATH12K_MHI_RESUME); 640 } 641