1081 lines · c
1// SPDX-License-Identifier: BSD-3-Clause-Clear2/*3 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.4 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.5 */6 7#include <linux/module.h>8#include <linux/msi.h>9#include <linux/pci.h>10#include <linux/of.h>11 12#include "pci.h"13#include "core.h"14#include "hif.h"15#include "mhi.h"16#include "debug.h"17#include "pcic.h"18#include "qmi.h"19 20#define ATH11K_PCI_BAR_NUM 021#define ATH11K_PCI_DMA_MASK 3622#define ATH11K_PCI_COHERENT_DMA_MASK 3223 24#define TCSR_SOC_HW_VERSION 0x022425#define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8)26#define TCSR_SOC_HW_VERSION_MINOR_MASK GENMASK(7, 0)27 28#define QCA6390_DEVICE_ID 0x110129#define QCN9074_DEVICE_ID 0x110430#define WCN6855_DEVICE_ID 0x110331 32#define TCSR_SOC_HW_SUB_VER 0x191001033 34static const struct pci_device_id ath11k_pci_id_table[] = {35 { PCI_VDEVICE(QCOM, QCA6390_DEVICE_ID) },36 { PCI_VDEVICE(QCOM, WCN6855_DEVICE_ID) },37 { PCI_VDEVICE(QCOM, QCN9074_DEVICE_ID) },38 {0}39};40 41MODULE_DEVICE_TABLE(pci, ath11k_pci_id_table);42 43static int ath11k_pci_bus_wake_up(struct ath11k_base *ab)44{45 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);46 47 return mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);48}49 50static void ath11k_pci_bus_release(struct ath11k_base *ab)51{52 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);53 54 mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);55}56 57static u32 ath11k_pci_get_window_start(struct ath11k_base *ab, u32 offset)58{59 if (!ab->hw_params.static_window_map)60 return ATH11K_PCI_WINDOW_START;61 62 if ((offset ^ HAL_SEQ_WCSS_UMAC_OFFSET) < ATH11K_PCI_WINDOW_RANGE_MASK)63 /* if offset lies within DP register range, use 3rd window */64 return 3 * ATH11K_PCI_WINDOW_START;65 else if ((offset ^ HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab)) <66 ATH11K_PCI_WINDOW_RANGE_MASK)67 /* if offset lies within CE register range, use 2nd window */68 return 2 * ATH11K_PCI_WINDOW_START;69 else70 return ATH11K_PCI_WINDOW_START;71}72 73static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offset)74{75 struct ath11k_base *ab = ab_pci->ab;76 77 u32 window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, offset);78 79 lockdep_assert_held(&ab_pci->window_lock);80 81 if (window != ab_pci->register_window) {82 iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window,83 ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);84 ioread32(ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);85 ab_pci->register_window = window;86 }87}88 89static void90ath11k_pci_window_write32(struct ath11k_base *ab, u32 offset, u32 value)91{92 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);93 u32 window_start;94 95 window_start = ath11k_pci_get_window_start(ab, offset);96 97 if (window_start == ATH11K_PCI_WINDOW_START) {98 spin_lock_bh(&ab_pci->window_lock);99 ath11k_pci_select_window(ab_pci, offset);100 iowrite32(value, ab->mem + window_start +101 (offset & ATH11K_PCI_WINDOW_RANGE_MASK));102 spin_unlock_bh(&ab_pci->window_lock);103 } else {104 iowrite32(value, ab->mem + window_start +105 (offset & ATH11K_PCI_WINDOW_RANGE_MASK));106 }107}108 109static u32 ath11k_pci_window_read32(struct ath11k_base *ab, u32 offset)110{111 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);112 u32 window_start, val;113 114 window_start = ath11k_pci_get_window_start(ab, offset);115 116 if (window_start == ATH11K_PCI_WINDOW_START) {117 spin_lock_bh(&ab_pci->window_lock);118 ath11k_pci_select_window(ab_pci, offset);119 val = ioread32(ab->mem + window_start +120 (offset & ATH11K_PCI_WINDOW_RANGE_MASK));121 spin_unlock_bh(&ab_pci->window_lock);122 } else {123 val = ioread32(ab->mem + window_start +124 (offset & ATH11K_PCI_WINDOW_RANGE_MASK));125 }126 127 return val;128}129 130int ath11k_pci_get_msi_irq(struct ath11k_base *ab, unsigned int vector)131{132 struct pci_dev *pci_dev = to_pci_dev(ab->dev);133 134 return pci_irq_vector(pci_dev, vector);135}136 137static const struct ath11k_pci_ops ath11k_pci_ops_qca6390 = {138 .wakeup = ath11k_pci_bus_wake_up,139 .release = ath11k_pci_bus_release,140 .get_msi_irq = ath11k_pci_get_msi_irq,141 .window_write32 = ath11k_pci_window_write32,142 .window_read32 = ath11k_pci_window_read32,143};144 145static const struct ath11k_pci_ops ath11k_pci_ops_qcn9074 = {146 .wakeup = NULL,147 .release = NULL,148 .get_msi_irq = ath11k_pci_get_msi_irq,149 .window_write32 = ath11k_pci_window_write32,150 .window_read32 = ath11k_pci_window_read32,151};152 153static const struct ath11k_msi_config msi_config_one_msi = {154 .total_vectors = 1,155 .total_users = 4,156 .users = (struct ath11k_msi_user[]) {157 { .name = "MHI", .num_vectors = 3, .base_vector = 0 },158 { .name = "CE", .num_vectors = 1, .base_vector = 0 },159 { .name = "WAKE", .num_vectors = 1, .base_vector = 0 },160 { .name = "DP", .num_vectors = 1, .base_vector = 0 },161 },162};163 164static inline void ath11k_pci_select_static_window(struct ath11k_pci *ab_pci)165{166 u32 umac_window;167 u32 ce_window;168 u32 window;169 170 umac_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_SEQ_WCSS_UMAC_OFFSET);171 ce_window = FIELD_GET(ATH11K_PCI_WINDOW_VALUE_MASK, HAL_CE_WFSS_CE_REG_BASE);172 window = (umac_window << 12) | (ce_window << 6);173 174 iowrite32(ATH11K_PCI_WINDOW_ENABLE_BIT | window,175 ab_pci->ab->mem + ATH11K_PCI_WINDOW_REG_ADDRESS);176}177 178static void ath11k_pci_soc_global_reset(struct ath11k_base *ab)179{180 u32 val, delay;181 182 val = ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET);183 184 val |= PCIE_SOC_GLOBAL_RESET_V;185 186 ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val);187 188 /* TODO: exact time to sleep is uncertain */189 delay = 10;190 mdelay(delay);191 192 /* Need to toggle V bit back otherwise stuck in reset status */193 val &= ~PCIE_SOC_GLOBAL_RESET_V;194 195 ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val);196 197 mdelay(delay);198 199 val = ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET);200 if (val == 0xffffffff)201 ath11k_warn(ab, "link down error during global reset\n");202}203 204static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)205{206 u32 val;207 208 /* read cookie */209 val = ath11k_pcic_read32(ab, PCIE_Q6_COOKIE_ADDR);210 ath11k_dbg(ab, ATH11K_DBG_PCI, "pcie_q6_cookie_addr 0x%x\n", val);211 212 val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY);213 ath11k_dbg(ab, ATH11K_DBG_PCI, "wlaon_warm_sw_entry 0x%x\n", val);214 215 /* TODO: exact time to sleep is uncertain */216 mdelay(10);217 218 /* write 0 to WLAON_WARM_SW_ENTRY to prevent Q6 from219 * continuing warm path and entering dead loop.220 */221 ath11k_pcic_write32(ab, WLAON_WARM_SW_ENTRY, 0);222 mdelay(10);223 224 val = ath11k_pcic_read32(ab, WLAON_WARM_SW_ENTRY);225 ath11k_dbg(ab, ATH11K_DBG_PCI, "wlaon_warm_sw_entry 0x%x\n", val);226 227 /* A read clear register. clear the register to prevent228 * Q6 from entering wrong code path.229 */230 val = ath11k_pcic_read32(ab, WLAON_SOC_RESET_CAUSE_REG);231 ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause %d\n", val);232}233 234static int ath11k_pci_set_link_reg(struct ath11k_base *ab,235 u32 offset, u32 value, u32 mask)236{237 u32 v;238 int i;239 240 v = ath11k_pcic_read32(ab, offset);241 if ((v & mask) == value)242 return 0;243 244 for (i = 0; i < 10; i++) {245 ath11k_pcic_write32(ab, offset, (v & ~mask) | value);246 247 v = ath11k_pcic_read32(ab, offset);248 if ((v & mask) == value)249 return 0;250 251 mdelay(2);252 }253 254 ath11k_warn(ab, "failed to set pcie link register 0x%08x: 0x%08x != 0x%08x\n",255 offset, v & mask, value);256 257 return -ETIMEDOUT;258}259 260static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)261{262 int ret;263 264 ret = ath11k_pci_set_link_reg(ab,265 PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG(ab),266 PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL,267 PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK);268 if (ret) {269 ath11k_warn(ab, "failed to set sysclk: %d\n", ret);270 return ret;271 }272 273 ret = ath11k_pci_set_link_reg(ab,274 PCIE_PCS_OSC_DTCT_CONFIG1_REG(ab),275 PCIE_PCS_OSC_DTCT_CONFIG1_VAL,276 PCIE_PCS_OSC_DTCT_CONFIG_MSK);277 if (ret) {278 ath11k_warn(ab, "failed to set dtct config1 error: %d\n", ret);279 return ret;280 }281 282 ret = ath11k_pci_set_link_reg(ab,283 PCIE_PCS_OSC_DTCT_CONFIG2_REG(ab),284 PCIE_PCS_OSC_DTCT_CONFIG2_VAL,285 PCIE_PCS_OSC_DTCT_CONFIG_MSK);286 if (ret) {287 ath11k_warn(ab, "failed to set dtct config2: %d\n", ret);288 return ret;289 }290 291 ret = ath11k_pci_set_link_reg(ab,292 PCIE_PCS_OSC_DTCT_CONFIG4_REG(ab),293 PCIE_PCS_OSC_DTCT_CONFIG4_VAL,294 PCIE_PCS_OSC_DTCT_CONFIG_MSK);295 if (ret) {296 ath11k_warn(ab, "failed to set dtct config4: %d\n", ret);297 return ret;298 }299 300 return 0;301}302 303static void ath11k_pci_enable_ltssm(struct ath11k_base *ab)304{305 u32 val;306 int i;307 308 val = ath11k_pcic_read32(ab, PCIE_PCIE_PARF_LTSSM);309 310 /* PCIE link seems very unstable after the Hot Reset*/311 for (i = 0; val != PARM_LTSSM_VALUE && i < 5; i++) {312 if (val == 0xffffffff)313 mdelay(5);314 315 ath11k_pcic_write32(ab, PCIE_PCIE_PARF_LTSSM, PARM_LTSSM_VALUE);316 val = ath11k_pcic_read32(ab, PCIE_PCIE_PARF_LTSSM);317 }318 319 ath11k_dbg(ab, ATH11K_DBG_PCI, "ltssm 0x%x\n", val);320 321 val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST);322 val |= GCC_GCC_PCIE_HOT_RST_VAL;323 ath11k_pcic_write32(ab, GCC_GCC_PCIE_HOT_RST, val);324 val = ath11k_pcic_read32(ab, GCC_GCC_PCIE_HOT_RST);325 326 ath11k_dbg(ab, ATH11K_DBG_PCI, "pcie_hot_rst 0x%x\n", val);327 328 mdelay(5);329}330 331static void ath11k_pci_clear_all_intrs(struct ath11k_base *ab)332{333 /* This is a WAR for PCIE Hotreset.334 * When target receive Hotreset, but will set the interrupt.335 * So when download SBL again, SBL will open Interrupt and336 * receive it, and crash immediately.337 */338 ath11k_pcic_write32(ab, PCIE_PCIE_INT_ALL_CLEAR, PCIE_INT_CLEAR_ALL);339}340 341static void ath11k_pci_set_wlaon_pwr_ctrl(struct ath11k_base *ab)342{343 u32 val;344 345 val = ath11k_pcic_read32(ab, WLAON_QFPROM_PWR_CTRL_REG);346 val &= ~QFPROM_PWR_CTRL_VDD4BLOW_MASK;347 ath11k_pcic_write32(ab, WLAON_QFPROM_PWR_CTRL_REG, val);348}349 350static void ath11k_pci_force_wake(struct ath11k_base *ab)351{352 ath11k_pcic_write32(ab, PCIE_SOC_WAKE_PCIE_LOCAL_REG, 1);353 mdelay(5);354}355 356static void ath11k_pci_sw_reset(struct ath11k_base *ab, bool power_on)357{358 mdelay(100);359 360 if (power_on) {361 ath11k_pci_enable_ltssm(ab);362 ath11k_pci_clear_all_intrs(ab);363 ath11k_pci_set_wlaon_pwr_ctrl(ab);364 if (ab->hw_params.fix_l1ss)365 ath11k_pci_fix_l1ss(ab);366 }367 368 ath11k_mhi_clear_vector(ab);369 ath11k_pci_clear_dbg_registers(ab);370 ath11k_pci_soc_global_reset(ab);371 ath11k_mhi_set_mhictrl_reset(ab);372}373 374static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab)375{376 struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;377 378 cfg->tgt_ce = ab->hw_params.target_ce_config;379 cfg->tgt_ce_len = ab->hw_params.target_ce_count;380 381 cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map;382 cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len;383 ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id;384 385 ath11k_ce_get_shadow_config(ab, &cfg->shadow_reg_v2,386 &cfg->shadow_reg_v2_len);387}388 389static void ath11k_pci_msi_config(struct ath11k_pci *ab_pci, bool enable)390{391 struct pci_dev *dev = ab_pci->pdev;392 u16 control;393 394 pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);395 396 if (enable)397 control |= PCI_MSI_FLAGS_ENABLE;398 else399 control &= ~PCI_MSI_FLAGS_ENABLE;400 401 pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);402}403 404static void ath11k_pci_msi_enable(struct ath11k_pci *ab_pci)405{406 ath11k_pci_msi_config(ab_pci, true);407}408 409static void ath11k_pci_msi_disable(struct ath11k_pci *ab_pci)410{411 ath11k_pci_msi_config(ab_pci, false);412}413 414static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci)415{416 struct ath11k_base *ab = ab_pci->ab;417 const struct ath11k_msi_config *msi_config = ab->pci.msi.config;418 struct pci_dev *pci_dev = ab_pci->pdev;419 struct msi_desc *msi_desc;420 int num_vectors;421 int ret;422 423 num_vectors = pci_alloc_irq_vectors(pci_dev,424 msi_config->total_vectors,425 msi_config->total_vectors,426 PCI_IRQ_MSI);427 if (num_vectors == msi_config->total_vectors) {428 set_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags);429 } else {430 num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,431 1,432 1,433 PCI_IRQ_MSI);434 if (num_vectors < 0) {435 ret = -EINVAL;436 goto reset_msi_config;437 }438 clear_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags);439 ab->pci.msi.config = &msi_config_one_msi;440 ath11k_dbg(ab, ATH11K_DBG_PCI, "request one msi vector\n");441 }442 ath11k_info(ab, "MSI vectors: %d\n", num_vectors);443 444 ath11k_pci_msi_disable(ab_pci);445 446 msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);447 if (!msi_desc) {448 ath11k_err(ab, "msi_desc is NULL!\n");449 ret = -EINVAL;450 goto free_msi_vector;451 }452 453 ab->pci.msi.ep_base_data = msi_desc->msg.data;454 455 pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO,456 &ab->pci.msi.addr_lo);457 458 if (msi_desc->pci.msi_attrib.is_64) {459 pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,460 &ab->pci.msi.addr_hi);461 } else {462 ab->pci.msi.addr_hi = 0;463 }464 465 ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab->pci.msi.ep_base_data);466 467 return 0;468 469free_msi_vector:470 pci_free_irq_vectors(ab_pci->pdev);471 472reset_msi_config:473 return ret;474}475 476static void ath11k_pci_free_msi(struct ath11k_pci *ab_pci)477{478 pci_free_irq_vectors(ab_pci->pdev);479}480 481static int ath11k_pci_config_msi_data(struct ath11k_pci *ab_pci)482{483 struct msi_desc *msi_desc;484 485 msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);486 if (!msi_desc) {487 ath11k_err(ab_pci->ab, "msi_desc is NULL!\n");488 pci_free_irq_vectors(ab_pci->pdev);489 return -EINVAL;490 }491 492 ab_pci->ab->pci.msi.ep_base_data = msi_desc->msg.data;493 494 ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "after request_irq msi_ep_base_data %d\n",495 ab_pci->ab->pci.msi.ep_base_data);496 497 return 0;498}499 500static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)501{502 struct ath11k_base *ab = ab_pci->ab;503 u16 device_id;504 int ret = 0;505 506 pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);507 if (device_id != ab_pci->dev_id) {508 ath11k_err(ab, "pci device id mismatch: 0x%x 0x%x\n",509 device_id, ab_pci->dev_id);510 ret = -EIO;511 goto out;512 }513 514 ret = pci_assign_resource(pdev, ATH11K_PCI_BAR_NUM);515 if (ret) {516 ath11k_err(ab, "failed to assign pci resource: %d\n", ret);517 goto out;518 }519 520 ret = pci_enable_device(pdev);521 if (ret) {522 ath11k_err(ab, "failed to enable pci device: %d\n", ret);523 goto out;524 }525 526 ret = pci_request_region(pdev, ATH11K_PCI_BAR_NUM, "ath11k_pci");527 if (ret) {528 ath11k_err(ab, "failed to request pci region: %d\n", ret);529 goto disable_device;530 }531 532 ret = dma_set_mask(&pdev->dev,533 DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));534 if (ret) {535 ath11k_err(ab, "failed to set pci dma mask to %d: %d\n",536 ATH11K_PCI_DMA_MASK, ret);537 goto release_region;538 }539 540 ab_pci->dma_mask = DMA_BIT_MASK(ATH11K_PCI_DMA_MASK);541 542 ret = dma_set_coherent_mask(&pdev->dev,543 DMA_BIT_MASK(ATH11K_PCI_COHERENT_DMA_MASK));544 if (ret) {545 ath11k_err(ab, "failed to set pci coherent dma mask to %d: %d\n",546 ATH11K_PCI_COHERENT_DMA_MASK, ret);547 goto release_region;548 }549 550 pci_set_master(pdev);551 552 ab->mem_len = pci_resource_len(pdev, ATH11K_PCI_BAR_NUM);553 ab->mem = pci_iomap(pdev, ATH11K_PCI_BAR_NUM, 0);554 if (!ab->mem) {555 ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM);556 ret = -EIO;557 goto release_region;558 }559 560 ab->mem_ce = ab->mem;561 562 ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci_mem 0x%p\n", ab->mem);563 return 0;564 565release_region:566 pci_release_region(pdev, ATH11K_PCI_BAR_NUM);567disable_device:568 pci_disable_device(pdev);569out:570 return ret;571}572 573static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)574{575 struct ath11k_base *ab = ab_pci->ab;576 struct pci_dev *pci_dev = ab_pci->pdev;577 578 pci_iounmap(pci_dev, ab->mem);579 ab->mem = NULL;580 pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM);581 if (pci_is_enabled(pci_dev))582 pci_disable_device(pci_dev);583}584 585static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci)586{587 struct ath11k_base *ab = ab_pci->ab;588 589 pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL,590 &ab_pci->link_ctl);591 592 ath11k_dbg(ab, ATH11K_DBG_PCI, "link_ctl 0x%04x L0s %d L1 %d\n",593 ab_pci->link_ctl,594 u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S),595 u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1));596 597 /* disable L0s and L1 */598 pcie_capability_clear_word(ab_pci->pdev, PCI_EXP_LNKCTL,599 PCI_EXP_LNKCTL_ASPMC);600 601 set_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags);602}603 604static void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci)605{606 if (test_and_clear_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags))607 pcie_capability_clear_and_set_word(ab_pci->pdev, PCI_EXP_LNKCTL,608 PCI_EXP_LNKCTL_ASPMC,609 ab_pci->link_ctl &610 PCI_EXP_LNKCTL_ASPMC);611}612 613static int ath11k_pci_power_up(struct ath11k_base *ab)614{615 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);616 int ret;617 618 ab_pci->register_window = 0;619 clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags);620 ath11k_pci_sw_reset(ab_pci->ab, true);621 622 /* Disable ASPM during firmware download due to problems switching623 * to AMSS state.624 */625 ath11k_pci_aspm_disable(ab_pci);626 627 ath11k_pci_msi_enable(ab_pci);628 629 ret = ath11k_mhi_start(ab_pci);630 if (ret) {631 ath11k_err(ab, "failed to start mhi: %d\n", ret);632 return ret;633 }634 635 if (ab->hw_params.static_window_map)636 ath11k_pci_select_static_window(ab_pci);637 638 return 0;639}640 641static void ath11k_pci_power_down(struct ath11k_base *ab)642{643 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);644 645 /* restore aspm in case firmware bootup fails */646 ath11k_pci_aspm_restore(ab_pci);647 648 ath11k_pci_force_wake(ab_pci->ab);649 650 ath11k_pci_msi_disable(ab_pci);651 652 ath11k_mhi_stop(ab_pci);653 clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags);654 ath11k_pci_sw_reset(ab_pci->ab, false);655}656 657static int ath11k_pci_hif_suspend(struct ath11k_base *ab)658{659 struct ath11k_pci *ar_pci = ath11k_pci_priv(ab);660 661 return ath11k_mhi_suspend(ar_pci);662}663 664static int ath11k_pci_hif_resume(struct ath11k_base *ab)665{666 struct ath11k_pci *ar_pci = ath11k_pci_priv(ab);667 668 return ath11k_mhi_resume(ar_pci);669}670 671static void ath11k_pci_hif_ce_irq_enable(struct ath11k_base *ab)672{673 ath11k_pcic_ce_irqs_enable(ab);674}675 676static void ath11k_pci_hif_ce_irq_disable(struct ath11k_base *ab)677{678 ath11k_pcic_ce_irq_disable_sync(ab);679}680 681static int ath11k_pci_start(struct ath11k_base *ab)682{683 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);684 685 /* TODO: for now don't restore ASPM in case of single MSI686 * vector as MHI register reading in M2 causes system hang.687 */688 if (test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags))689 ath11k_pci_aspm_restore(ab_pci);690 else691 ath11k_info(ab, "leaving PCI ASPM disabled to avoid MHI M2 problems\n");692 693 ath11k_pcic_start(ab);694 695 return 0;696}697 698static const struct ath11k_hif_ops ath11k_pci_hif_ops = {699 .start = ath11k_pci_start,700 .stop = ath11k_pcic_stop,701 .read32 = ath11k_pcic_read32,702 .write32 = ath11k_pcic_write32,703 .read = ath11k_pcic_read,704 .power_down = ath11k_pci_power_down,705 .power_up = ath11k_pci_power_up,706 .suspend = ath11k_pci_hif_suspend,707 .resume = ath11k_pci_hif_resume,708 .irq_enable = ath11k_pcic_ext_irq_enable,709 .irq_disable = ath11k_pcic_ext_irq_disable,710 .get_msi_address = ath11k_pcic_get_msi_address,711 .get_user_msi_vector = ath11k_pcic_get_user_msi_assignment,712 .map_service_to_pipe = ath11k_pcic_map_service_to_pipe,713 .ce_irq_enable = ath11k_pci_hif_ce_irq_enable,714 .ce_irq_disable = ath11k_pci_hif_ce_irq_disable,715 .get_ce_msi_idx = ath11k_pcic_get_ce_msi_idx,716};717 718static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 *major, u32 *minor)719{720 u32 soc_hw_version;721 722 soc_hw_version = ath11k_pcic_read32(ab, TCSR_SOC_HW_VERSION);723 *major = FIELD_GET(TCSR_SOC_HW_VERSION_MAJOR_MASK,724 soc_hw_version);725 *minor = FIELD_GET(TCSR_SOC_HW_VERSION_MINOR_MASK,726 soc_hw_version);727 728 ath11k_dbg(ab, ATH11K_DBG_PCI, "tcsr_soc_hw_version major %d minor %d\n",729 *major, *minor);730}731 732static int ath11k_pci_set_irq_affinity_hint(struct ath11k_pci *ab_pci,733 const struct cpumask *m)734{735 if (test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab_pci->ab->dev_flags))736 return 0;737 738 return irq_set_affinity_hint(ab_pci->pdev->irq, m);739}740 741static int ath11k_pci_probe(struct pci_dev *pdev,742 const struct pci_device_id *pci_dev)743{744 struct ath11k_base *ab;745 struct ath11k_pci *ab_pci;746 u32 soc_hw_version_major, soc_hw_version_minor, addr;747 int ret;748 u32 sub_version;749 750 ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI);751 752 if (!ab) {753 dev_err(&pdev->dev, "failed to allocate ath11k base\n");754 return -ENOMEM;755 }756 757 ab->dev = &pdev->dev;758 pci_set_drvdata(pdev, ab);759 ab_pci = ath11k_pci_priv(ab);760 ab_pci->dev_id = pci_dev->device;761 ab_pci->ab = ab;762 ab_pci->pdev = pdev;763 ab->hif.ops = &ath11k_pci_hif_ops;764 ab->fw_mode = ATH11K_FIRMWARE_MODE_NORMAL;765 pci_set_drvdata(pdev, ab);766 spin_lock_init(&ab_pci->window_lock);767 768 /* Set fixed_mem_region to true for platforms support reserved memory769 * from DT. If memory is reserved from DT for FW, ath11k driver need not770 * allocate memory.771 */772 ret = of_property_read_u32(ab->dev->of_node, "memory-region", &addr);773 if (!ret)774 set_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags);775 776 ret = ath11k_pci_claim(ab_pci, pdev);777 if (ret) {778 ath11k_err(ab, "failed to claim device: %d\n", ret);779 goto err_free_core;780 }781 782 ath11k_dbg(ab, ATH11K_DBG_BOOT, "pci probe %04x:%04x %04x:%04x\n",783 pdev->vendor, pdev->device,784 pdev->subsystem_vendor, pdev->subsystem_device);785 786 ab->id.vendor = pdev->vendor;787 ab->id.device = pdev->device;788 ab->id.subsystem_vendor = pdev->subsystem_vendor;789 ab->id.subsystem_device = pdev->subsystem_device;790 791 switch (pci_dev->device) {792 case QCA6390_DEVICE_ID:793 ret = ath11k_pcic_register_pci_ops(ab, &ath11k_pci_ops_qca6390);794 if (ret) {795 ath11k_err(ab, "failed to register PCI ops: %d\n", ret);796 goto err_pci_free_region;797 }798 799 ath11k_pci_read_hw_version(ab, &soc_hw_version_major,800 &soc_hw_version_minor);801 switch (soc_hw_version_major) {802 case 2:803 ab->hw_rev = ATH11K_HW_QCA6390_HW20;804 break;805 default:806 dev_err(&pdev->dev, "Unsupported QCA6390 SOC hardware version: %d %d\n",807 soc_hw_version_major, soc_hw_version_minor);808 ret = -EOPNOTSUPP;809 goto err_pci_free_region;810 }811 812 break;813 case QCN9074_DEVICE_ID:814 ret = ath11k_pcic_register_pci_ops(ab, &ath11k_pci_ops_qcn9074);815 if (ret) {816 ath11k_err(ab, "failed to register PCI ops: %d\n", ret);817 goto err_pci_free_region;818 }819 ab->hw_rev = ATH11K_HW_QCN9074_HW10;820 break;821 case WCN6855_DEVICE_ID:822 ret = ath11k_pcic_register_pci_ops(ab, &ath11k_pci_ops_qca6390);823 if (ret) {824 ath11k_err(ab, "failed to register PCI ops: %d\n", ret);825 goto err_pci_free_region;826 }827 ab->id.bdf_search = ATH11K_BDF_SEARCH_BUS_AND_BOARD;828 ath11k_pci_read_hw_version(ab, &soc_hw_version_major,829 &soc_hw_version_minor);830 switch (soc_hw_version_major) {831 case 2:832 switch (soc_hw_version_minor) {833 case 0x00:834 case 0x01:835 ab->hw_rev = ATH11K_HW_WCN6855_HW20;836 break;837 case 0x10:838 case 0x11:839 sub_version = ath11k_pcic_read32(ab, TCSR_SOC_HW_SUB_VER);840 ath11k_dbg(ab, ATH11K_DBG_PCI, "sub_version 0x%x\n",841 sub_version);842 switch (sub_version) {843 case 0x1019A0E1:844 case 0x1019B0E1:845 case 0x1019C0E1:846 case 0x1019D0E1:847 ab->hw_rev = ATH11K_HW_QCA2066_HW21;848 break;849 default:850 ab->hw_rev = ATH11K_HW_WCN6855_HW21;851 }852 break;853 default:854 goto unsupported_wcn6855_soc;855 }856 break;857 default:858unsupported_wcn6855_soc:859 dev_err(&pdev->dev, "Unsupported WCN6855 SOC hardware version: %d %d\n",860 soc_hw_version_major, soc_hw_version_minor);861 ret = -EOPNOTSUPP;862 goto err_pci_free_region;863 }864 865 break;866 default:867 dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n",868 pci_dev->device);869 ret = -EOPNOTSUPP;870 goto err_pci_free_region;871 }872 873 ret = ath11k_pcic_init_msi_config(ab);874 if (ret) {875 ath11k_err(ab, "failed to init msi config: %d\n", ret);876 goto err_pci_free_region;877 }878 879 ret = ath11k_pci_alloc_msi(ab_pci);880 if (ret) {881 ath11k_err(ab, "failed to enable msi: %d\n", ret);882 goto err_pci_free_region;883 }884 885 ret = ath11k_core_pre_init(ab);886 if (ret)887 goto err_pci_disable_msi;888 889 ret = ath11k_pci_set_irq_affinity_hint(ab_pci, cpumask_of(0));890 if (ret) {891 ath11k_err(ab, "failed to set irq affinity %d\n", ret);892 goto err_pci_disable_msi;893 }894 895 ret = ath11k_mhi_register(ab_pci);896 if (ret) {897 ath11k_err(ab, "failed to register mhi: %d\n", ret);898 goto err_irq_affinity_cleanup;899 }900 901 ret = ath11k_hal_srng_init(ab);902 if (ret)903 goto err_mhi_unregister;904 905 ret = ath11k_ce_alloc_pipes(ab);906 if (ret) {907 ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);908 goto err_hal_srng_deinit;909 }910 911 ath11k_pci_init_qmi_ce_config(ab);912 913 ret = ath11k_pcic_config_irq(ab);914 if (ret) {915 ath11k_err(ab, "failed to config irq: %d\n", ret);916 goto err_ce_free;917 }918 919 /* kernel may allocate a dummy vector before request_irq and920 * then allocate a real vector when request_irq is called.921 * So get msi_data here again to avoid spurious interrupt922 * as msi_data will configured to srngs.923 */924 ret = ath11k_pci_config_msi_data(ab_pci);925 if (ret) {926 ath11k_err(ab, "failed to config msi_data: %d\n", ret);927 goto err_free_irq;928 }929 930 ret = ath11k_core_init(ab);931 if (ret) {932 ath11k_err(ab, "failed to init core: %d\n", ret);933 goto err_free_irq;934 }935 ath11k_qmi_fwreset_from_cold_boot(ab);936 return 0;937 938err_free_irq:939 ath11k_pcic_free_irq(ab);940 941err_ce_free:942 ath11k_ce_free_pipes(ab);943 944err_hal_srng_deinit:945 ath11k_hal_srng_deinit(ab);946 947err_mhi_unregister:948 ath11k_mhi_unregister(ab_pci);949 950err_irq_affinity_cleanup:951 ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);952 953err_pci_disable_msi:954 ath11k_pci_free_msi(ab_pci);955 956err_pci_free_region:957 ath11k_pci_free_region(ab_pci);958 959err_free_core:960 ath11k_core_free(ab);961 962 return ret;963}964 965static void ath11k_pci_remove(struct pci_dev *pdev)966{967 struct ath11k_base *ab = pci_get_drvdata(pdev);968 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);969 970 ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);971 972 if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {973 ath11k_pci_power_down(ab);974 ath11k_debugfs_soc_destroy(ab);975 ath11k_qmi_deinit_service(ab);976 goto qmi_fail;977 }978 979 set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);980 981 ath11k_core_deinit(ab);982 983qmi_fail:984 ath11k_mhi_unregister(ab_pci);985 986 ath11k_pcic_free_irq(ab);987 ath11k_pci_free_msi(ab_pci);988 ath11k_pci_free_region(ab_pci);989 990 ath11k_hal_srng_deinit(ab);991 ath11k_ce_free_pipes(ab);992 ath11k_core_free(ab);993}994 995static void ath11k_pci_shutdown(struct pci_dev *pdev)996{997 struct ath11k_base *ab = pci_get_drvdata(pdev);998 struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);999 1000 ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);1001 ath11k_pci_power_down(ab);1002}1003 1004static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev)1005{1006 struct ath11k_base *ab = dev_get_drvdata(dev);1007 int ret;1008 1009 if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {1010 ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot skipping pci suspend as qmi is not initialised\n");1011 return 0;1012 }1013 1014 ret = ath11k_core_suspend(ab);1015 if (ret)1016 ath11k_warn(ab, "failed to suspend core: %d\n", ret);1017 1018 return 0;1019}1020 1021static __maybe_unused int ath11k_pci_pm_resume(struct device *dev)1022{1023 struct ath11k_base *ab = dev_get_drvdata(dev);1024 int ret;1025 1026 if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {1027 ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot skipping pci resume as qmi is not initialised\n");1028 return 0;1029 }1030 1031 ret = ath11k_core_resume(ab);1032 if (ret)1033 ath11k_warn(ab, "failed to resume core: %d\n", ret);1034 1035 return ret;1036}1037 1038static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops,1039 ath11k_pci_pm_suspend,1040 ath11k_pci_pm_resume);1041 1042static struct pci_driver ath11k_pci_driver = {1043 .name = "ath11k_pci",1044 .id_table = ath11k_pci_id_table,1045 .probe = ath11k_pci_probe,1046 .remove = ath11k_pci_remove,1047 .shutdown = ath11k_pci_shutdown,1048#ifdef CONFIG_PM1049 .driver.pm = &ath11k_pci_pm_ops,1050#endif1051};1052 1053static int ath11k_pci_init(void)1054{1055 int ret;1056 1057 ret = pci_register_driver(&ath11k_pci_driver);1058 if (ret)1059 pr_err("failed to register ath11k pci driver: %d\n",1060 ret);1061 1062 return ret;1063}1064module_init(ath11k_pci_init);1065 1066static void ath11k_pci_exit(void)1067{1068 pci_unregister_driver(&ath11k_pci_driver);1069}1070 1071module_exit(ath11k_pci_exit);1072 1073MODULE_DESCRIPTION("Driver support for Qualcomm Technologies PCIe 802.11ax WLAN devices");1074MODULE_LICENSE("Dual BSD/GPL");1075 1076/* firmware files */1077MODULE_FIRMWARE(ATH11K_FW_DIR "/QCA6390/hw2.0/*");1078MODULE_FIRMWARE(ATH11K_FW_DIR "/QCN9074/hw1.0/*");1079MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.0/*");1080MODULE_FIRMWARE(ATH11K_FW_DIR "/WCN6855/hw2.1/*");1081