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