162306a36Sopenharmony_ci// SPDX-License-Identifier: ISC 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2016-2017 Qualcomm Atheros, Inc. All rights reserved. 462306a36Sopenharmony_ci * Copyright (c) 2015 The Linux Foundation. All rights reserved. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#include <linux/module.h> 762306a36Sopenharmony_ci#include <linux/of.h> 862306a36Sopenharmony_ci#include <linux/platform_device.h> 962306a36Sopenharmony_ci#include <linux/clk.h> 1062306a36Sopenharmony_ci#include <linux/reset.h> 1162306a36Sopenharmony_ci#include "core.h" 1262306a36Sopenharmony_ci#include "debug.h" 1362306a36Sopenharmony_ci#include "pci.h" 1462306a36Sopenharmony_ci#include "ahb.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistatic const struct of_device_id ath10k_ahb_of_match[] = { 1762306a36Sopenharmony_ci { .compatible = "qcom,ipq4019-wifi", 1862306a36Sopenharmony_ci .data = (void *)ATH10K_HW_QCA4019 1962306a36Sopenharmony_ci }, 2062306a36Sopenharmony_ci { } 2162306a36Sopenharmony_ci}; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ath10k_ahb_of_match); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define QCA4019_SRAM_ADDR 0x000C0000 2662306a36Sopenharmony_ci#define QCA4019_SRAM_LEN 0x00040000 /* 256 kb */ 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci return &ath10k_pci_priv(ar)->ahb[0]; 3162306a36Sopenharmony_ci} 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic void ath10k_ahb_write32(struct ath10k *ar, u32 offset, u32 value) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci iowrite32(value, ar_ahb->mem + offset); 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic u32 ath10k_ahb_read32(struct ath10k *ar, u32 offset) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci return ioread32(ar_ahb->mem + offset); 4562306a36Sopenharmony_ci} 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic u32 ath10k_ahb_gcc_read32(struct ath10k *ar, u32 offset) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci return ioread32(ar_ahb->gcc_mem + offset); 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic void ath10k_ahb_tcsr_write32(struct ath10k *ar, u32 offset, u32 value) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci iowrite32(value, ar_ahb->tcsr_mem + offset); 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic u32 ath10k_ahb_tcsr_read32(struct ath10k *ar, u32 offset) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci return ioread32(ar_ahb->tcsr_mem + offset); 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic u32 ath10k_ahb_soc_read32(struct ath10k *ar, u32 addr) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci return ath10k_ahb_read32(ar, RTC_SOC_BASE_ADDRESS + addr); 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic int ath10k_ahb_get_num_banks(struct ath10k *ar) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci if (ar->hw_rev == ATH10K_HW_QCA4019) 7662306a36Sopenharmony_ci return 1; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci ath10k_warn(ar, "unknown number of banks, assuming 1\n"); 7962306a36Sopenharmony_ci return 1; 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic int ath10k_ahb_clock_init(struct ath10k *ar) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 8562306a36Sopenharmony_ci struct device *dev; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci dev = &ar_ahb->pdev->dev; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci ar_ahb->cmd_clk = devm_clk_get(dev, "wifi_wcss_cmd"); 9062306a36Sopenharmony_ci if (IS_ERR_OR_NULL(ar_ahb->cmd_clk)) { 9162306a36Sopenharmony_ci ath10k_err(ar, "failed to get cmd clk: %ld\n", 9262306a36Sopenharmony_ci PTR_ERR(ar_ahb->cmd_clk)); 9362306a36Sopenharmony_ci return ar_ahb->cmd_clk ? PTR_ERR(ar_ahb->cmd_clk) : -ENODEV; 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci ar_ahb->ref_clk = devm_clk_get(dev, "wifi_wcss_ref"); 9762306a36Sopenharmony_ci if (IS_ERR_OR_NULL(ar_ahb->ref_clk)) { 9862306a36Sopenharmony_ci ath10k_err(ar, "failed to get ref clk: %ld\n", 9962306a36Sopenharmony_ci PTR_ERR(ar_ahb->ref_clk)); 10062306a36Sopenharmony_ci return ar_ahb->ref_clk ? PTR_ERR(ar_ahb->ref_clk) : -ENODEV; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci ar_ahb->rtc_clk = devm_clk_get(dev, "wifi_wcss_rtc"); 10462306a36Sopenharmony_ci if (IS_ERR_OR_NULL(ar_ahb->rtc_clk)) { 10562306a36Sopenharmony_ci ath10k_err(ar, "failed to get rtc clk: %ld\n", 10662306a36Sopenharmony_ci PTR_ERR(ar_ahb->rtc_clk)); 10762306a36Sopenharmony_ci return ar_ahb->rtc_clk ? PTR_ERR(ar_ahb->rtc_clk) : -ENODEV; 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci return 0; 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic void ath10k_ahb_clock_deinit(struct ath10k *ar) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci ar_ahb->cmd_clk = NULL; 11862306a36Sopenharmony_ci ar_ahb->ref_clk = NULL; 11962306a36Sopenharmony_ci ar_ahb->rtc_clk = NULL; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic int ath10k_ahb_clock_enable(struct ath10k *ar) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 12562306a36Sopenharmony_ci int ret; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (IS_ERR_OR_NULL(ar_ahb->cmd_clk) || 12862306a36Sopenharmony_ci IS_ERR_OR_NULL(ar_ahb->ref_clk) || 12962306a36Sopenharmony_ci IS_ERR_OR_NULL(ar_ahb->rtc_clk)) { 13062306a36Sopenharmony_ci ath10k_err(ar, "clock(s) is/are not initialized\n"); 13162306a36Sopenharmony_ci ret = -EIO; 13262306a36Sopenharmony_ci goto out; 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci ret = clk_prepare_enable(ar_ahb->cmd_clk); 13662306a36Sopenharmony_ci if (ret) { 13762306a36Sopenharmony_ci ath10k_err(ar, "failed to enable cmd clk: %d\n", ret); 13862306a36Sopenharmony_ci goto out; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci ret = clk_prepare_enable(ar_ahb->ref_clk); 14262306a36Sopenharmony_ci if (ret) { 14362306a36Sopenharmony_ci ath10k_err(ar, "failed to enable ref clk: %d\n", ret); 14462306a36Sopenharmony_ci goto err_cmd_clk_disable; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci ret = clk_prepare_enable(ar_ahb->rtc_clk); 14862306a36Sopenharmony_ci if (ret) { 14962306a36Sopenharmony_ci ath10k_err(ar, "failed to enable rtc clk: %d\n", ret); 15062306a36Sopenharmony_ci goto err_ref_clk_disable; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci return 0; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cierr_ref_clk_disable: 15662306a36Sopenharmony_ci clk_disable_unprepare(ar_ahb->ref_clk); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cierr_cmd_clk_disable: 15962306a36Sopenharmony_ci clk_disable_unprepare(ar_ahb->cmd_clk); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ciout: 16262306a36Sopenharmony_ci return ret; 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic void ath10k_ahb_clock_disable(struct ath10k *ar) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci clk_disable_unprepare(ar_ahb->cmd_clk); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci clk_disable_unprepare(ar_ahb->ref_clk); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci clk_disable_unprepare(ar_ahb->rtc_clk); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic int ath10k_ahb_rst_ctrl_init(struct ath10k *ar) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 17962306a36Sopenharmony_ci struct device *dev; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci dev = &ar_ahb->pdev->dev; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci ar_ahb->core_cold_rst = devm_reset_control_get_exclusive(dev, 18462306a36Sopenharmony_ci "wifi_core_cold"); 18562306a36Sopenharmony_ci if (IS_ERR(ar_ahb->core_cold_rst)) { 18662306a36Sopenharmony_ci ath10k_err(ar, "failed to get core cold rst ctrl: %ld\n", 18762306a36Sopenharmony_ci PTR_ERR(ar_ahb->core_cold_rst)); 18862306a36Sopenharmony_ci return PTR_ERR(ar_ahb->core_cold_rst); 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci ar_ahb->radio_cold_rst = devm_reset_control_get_exclusive(dev, 19262306a36Sopenharmony_ci "wifi_radio_cold"); 19362306a36Sopenharmony_ci if (IS_ERR(ar_ahb->radio_cold_rst)) { 19462306a36Sopenharmony_ci ath10k_err(ar, "failed to get radio cold rst ctrl: %ld\n", 19562306a36Sopenharmony_ci PTR_ERR(ar_ahb->radio_cold_rst)); 19662306a36Sopenharmony_ci return PTR_ERR(ar_ahb->radio_cold_rst); 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci ar_ahb->radio_warm_rst = devm_reset_control_get_exclusive(dev, 20062306a36Sopenharmony_ci "wifi_radio_warm"); 20162306a36Sopenharmony_ci if (IS_ERR(ar_ahb->radio_warm_rst)) { 20262306a36Sopenharmony_ci ath10k_err(ar, "failed to get radio warm rst ctrl: %ld\n", 20362306a36Sopenharmony_ci PTR_ERR(ar_ahb->radio_warm_rst)); 20462306a36Sopenharmony_ci return PTR_ERR(ar_ahb->radio_warm_rst); 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci ar_ahb->radio_srif_rst = devm_reset_control_get_exclusive(dev, 20862306a36Sopenharmony_ci "wifi_radio_srif"); 20962306a36Sopenharmony_ci if (IS_ERR(ar_ahb->radio_srif_rst)) { 21062306a36Sopenharmony_ci ath10k_err(ar, "failed to get radio srif rst ctrl: %ld\n", 21162306a36Sopenharmony_ci PTR_ERR(ar_ahb->radio_srif_rst)); 21262306a36Sopenharmony_ci return PTR_ERR(ar_ahb->radio_srif_rst); 21362306a36Sopenharmony_ci } 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci ar_ahb->cpu_init_rst = devm_reset_control_get_exclusive(dev, 21662306a36Sopenharmony_ci "wifi_cpu_init"); 21762306a36Sopenharmony_ci if (IS_ERR(ar_ahb->cpu_init_rst)) { 21862306a36Sopenharmony_ci ath10k_err(ar, "failed to get cpu init rst ctrl: %ld\n", 21962306a36Sopenharmony_ci PTR_ERR(ar_ahb->cpu_init_rst)); 22062306a36Sopenharmony_ci return PTR_ERR(ar_ahb->cpu_init_rst); 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci return 0; 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic void ath10k_ahb_rst_ctrl_deinit(struct ath10k *ar) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci ar_ahb->core_cold_rst = NULL; 23162306a36Sopenharmony_ci ar_ahb->radio_cold_rst = NULL; 23262306a36Sopenharmony_ci ar_ahb->radio_warm_rst = NULL; 23362306a36Sopenharmony_ci ar_ahb->radio_srif_rst = NULL; 23462306a36Sopenharmony_ci ar_ahb->cpu_init_rst = NULL; 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic int ath10k_ahb_release_reset(struct ath10k *ar) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 24062306a36Sopenharmony_ci int ret; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) || 24362306a36Sopenharmony_ci IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) || 24462306a36Sopenharmony_ci IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) || 24562306a36Sopenharmony_ci IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { 24662306a36Sopenharmony_ci ath10k_err(ar, "rst ctrl(s) is/are not initialized\n"); 24762306a36Sopenharmony_ci return -EINVAL; 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci ret = reset_control_deassert(ar_ahb->radio_cold_rst); 25162306a36Sopenharmony_ci if (ret) { 25262306a36Sopenharmony_ci ath10k_err(ar, "failed to deassert radio cold rst: %d\n", ret); 25362306a36Sopenharmony_ci return ret; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci ret = reset_control_deassert(ar_ahb->radio_warm_rst); 25762306a36Sopenharmony_ci if (ret) { 25862306a36Sopenharmony_ci ath10k_err(ar, "failed to deassert radio warm rst: %d\n", ret); 25962306a36Sopenharmony_ci return ret; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci ret = reset_control_deassert(ar_ahb->radio_srif_rst); 26362306a36Sopenharmony_ci if (ret) { 26462306a36Sopenharmony_ci ath10k_err(ar, "failed to deassert radio srif rst: %d\n", ret); 26562306a36Sopenharmony_ci return ret; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci ret = reset_control_deassert(ar_ahb->cpu_init_rst); 26962306a36Sopenharmony_ci if (ret) { 27062306a36Sopenharmony_ci ath10k_err(ar, "failed to deassert cpu init rst: %d\n", ret); 27162306a36Sopenharmony_ci return ret; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci return 0; 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cistatic void ath10k_ahb_halt_axi_bus(struct ath10k *ar, u32 haltreq_reg, 27862306a36Sopenharmony_ci u32 haltack_reg) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci unsigned long timeout; 28162306a36Sopenharmony_ci u32 val; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci /* Issue halt axi bus request */ 28462306a36Sopenharmony_ci val = ath10k_ahb_tcsr_read32(ar, haltreq_reg); 28562306a36Sopenharmony_ci val |= AHB_AXI_BUS_HALT_REQ; 28662306a36Sopenharmony_ci ath10k_ahb_tcsr_write32(ar, haltreq_reg, val); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* Wait for axi bus halted ack */ 28962306a36Sopenharmony_ci timeout = jiffies + msecs_to_jiffies(ATH10K_AHB_AXI_BUS_HALT_TIMEOUT); 29062306a36Sopenharmony_ci do { 29162306a36Sopenharmony_ci val = ath10k_ahb_tcsr_read32(ar, haltack_reg); 29262306a36Sopenharmony_ci if (val & AHB_AXI_BUS_HALT_ACK) 29362306a36Sopenharmony_ci break; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci mdelay(1); 29662306a36Sopenharmony_ci } while (time_before(jiffies, timeout)); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci if (!(val & AHB_AXI_BUS_HALT_ACK)) { 29962306a36Sopenharmony_ci ath10k_err(ar, "failed to halt axi bus: %d\n", val); 30062306a36Sopenharmony_ci return; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci ath10k_dbg(ar, ATH10K_DBG_AHB, "axi bus halted\n"); 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistatic void ath10k_ahb_halt_chip(struct ath10k *ar) 30762306a36Sopenharmony_ci{ 30862306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 30962306a36Sopenharmony_ci u32 core_id, glb_cfg_reg, haltreq_reg, haltack_reg; 31062306a36Sopenharmony_ci u32 val; 31162306a36Sopenharmony_ci int ret; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst) || 31462306a36Sopenharmony_ci IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) || 31562306a36Sopenharmony_ci IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) || 31662306a36Sopenharmony_ci IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) || 31762306a36Sopenharmony_ci IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { 31862306a36Sopenharmony_ci ath10k_err(ar, "rst ctrl(s) is/are not initialized\n"); 31962306a36Sopenharmony_ci return; 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci core_id = ath10k_ahb_read32(ar, ATH10K_AHB_WLAN_CORE_ID_REG); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci switch (core_id) { 32562306a36Sopenharmony_ci case 0: 32662306a36Sopenharmony_ci glb_cfg_reg = ATH10K_AHB_TCSR_WIFI0_GLB_CFG; 32762306a36Sopenharmony_ci haltreq_reg = ATH10K_AHB_TCSR_WCSS0_HALTREQ; 32862306a36Sopenharmony_ci haltack_reg = ATH10K_AHB_TCSR_WCSS0_HALTACK; 32962306a36Sopenharmony_ci break; 33062306a36Sopenharmony_ci case 1: 33162306a36Sopenharmony_ci glb_cfg_reg = ATH10K_AHB_TCSR_WIFI1_GLB_CFG; 33262306a36Sopenharmony_ci haltreq_reg = ATH10K_AHB_TCSR_WCSS1_HALTREQ; 33362306a36Sopenharmony_ci haltack_reg = ATH10K_AHB_TCSR_WCSS1_HALTACK; 33462306a36Sopenharmony_ci break; 33562306a36Sopenharmony_ci default: 33662306a36Sopenharmony_ci ath10k_err(ar, "invalid core id %d found, skipping reset sequence\n", 33762306a36Sopenharmony_ci core_id); 33862306a36Sopenharmony_ci return; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci ath10k_ahb_halt_axi_bus(ar, haltreq_reg, haltack_reg); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg); 34462306a36Sopenharmony_ci val |= TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK; 34562306a36Sopenharmony_ci ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci ret = reset_control_assert(ar_ahb->core_cold_rst); 34862306a36Sopenharmony_ci if (ret) 34962306a36Sopenharmony_ci ath10k_err(ar, "failed to assert core cold rst: %d\n", ret); 35062306a36Sopenharmony_ci msleep(1); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci ret = reset_control_assert(ar_ahb->radio_cold_rst); 35362306a36Sopenharmony_ci if (ret) 35462306a36Sopenharmony_ci ath10k_err(ar, "failed to assert radio cold rst: %d\n", ret); 35562306a36Sopenharmony_ci msleep(1); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci ret = reset_control_assert(ar_ahb->radio_warm_rst); 35862306a36Sopenharmony_ci if (ret) 35962306a36Sopenharmony_ci ath10k_err(ar, "failed to assert radio warm rst: %d\n", ret); 36062306a36Sopenharmony_ci msleep(1); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci ret = reset_control_assert(ar_ahb->radio_srif_rst); 36362306a36Sopenharmony_ci if (ret) 36462306a36Sopenharmony_ci ath10k_err(ar, "failed to assert radio srif rst: %d\n", ret); 36562306a36Sopenharmony_ci msleep(1); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci ret = reset_control_assert(ar_ahb->cpu_init_rst); 36862306a36Sopenharmony_ci if (ret) 36962306a36Sopenharmony_ci ath10k_err(ar, "failed to assert cpu init rst: %d\n", ret); 37062306a36Sopenharmony_ci msleep(10); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci /* Clear halt req and core clock disable req before 37362306a36Sopenharmony_ci * deasserting wifi core reset. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_ci val = ath10k_ahb_tcsr_read32(ar, haltreq_reg); 37662306a36Sopenharmony_ci val &= ~AHB_AXI_BUS_HALT_REQ; 37762306a36Sopenharmony_ci ath10k_ahb_tcsr_write32(ar, haltreq_reg, val); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg); 38062306a36Sopenharmony_ci val &= ~TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK; 38162306a36Sopenharmony_ci ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci ret = reset_control_deassert(ar_ahb->core_cold_rst); 38462306a36Sopenharmony_ci if (ret) 38562306a36Sopenharmony_ci ath10k_err(ar, "failed to deassert core cold rst: %d\n", ret); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci ath10k_dbg(ar, ATH10K_DBG_AHB, "core %d reset done\n", core_id); 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic irqreturn_t ath10k_ahb_interrupt_handler(int irq, void *arg) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci struct ath10k *ar = arg; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci if (!ath10k_pci_irq_pending(ar)) 39562306a36Sopenharmony_ci return IRQ_NONE; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci ath10k_pci_disable_and_clear_legacy_irq(ar); 39862306a36Sopenharmony_ci ath10k_pci_irq_msi_fw_mask(ar); 39962306a36Sopenharmony_ci napi_schedule(&ar->napi); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci return IRQ_HANDLED; 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_cistatic int ath10k_ahb_request_irq_legacy(struct ath10k *ar) 40562306a36Sopenharmony_ci{ 40662306a36Sopenharmony_ci struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); 40762306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 40862306a36Sopenharmony_ci int ret; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci ret = request_irq(ar_ahb->irq, 41162306a36Sopenharmony_ci ath10k_ahb_interrupt_handler, 41262306a36Sopenharmony_ci IRQF_SHARED, "ath10k_ahb", ar); 41362306a36Sopenharmony_ci if (ret) { 41462306a36Sopenharmony_ci ath10k_warn(ar, "failed to request legacy irq %d: %d\n", 41562306a36Sopenharmony_ci ar_ahb->irq, ret); 41662306a36Sopenharmony_ci return ret; 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci ar_pci->oper_irq_mode = ATH10K_PCI_IRQ_LEGACY; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci return 0; 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic void ath10k_ahb_release_irq_legacy(struct ath10k *ar) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci free_irq(ar_ahb->irq, ar); 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic void ath10k_ahb_irq_disable(struct ath10k *ar) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci ath10k_ce_disable_interrupts(ar); 43362306a36Sopenharmony_ci ath10k_pci_disable_and_clear_legacy_irq(ar); 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistatic int ath10k_ahb_resource_init(struct ath10k *ar) 43762306a36Sopenharmony_ci{ 43862306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 43962306a36Sopenharmony_ci struct platform_device *pdev; 44062306a36Sopenharmony_ci struct resource *res; 44162306a36Sopenharmony_ci int ret; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci pdev = ar_ahb->pdev; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci ar_ahb->mem = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 44662306a36Sopenharmony_ci if (IS_ERR(ar_ahb->mem)) { 44762306a36Sopenharmony_ci ath10k_err(ar, "mem ioremap error\n"); 44862306a36Sopenharmony_ci ret = PTR_ERR(ar_ahb->mem); 44962306a36Sopenharmony_ci goto out; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci ar_ahb->mem_len = resource_size(res); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci ar_ahb->gcc_mem = ioremap(ATH10K_GCC_REG_BASE, 45562306a36Sopenharmony_ci ATH10K_GCC_REG_SIZE); 45662306a36Sopenharmony_ci if (!ar_ahb->gcc_mem) { 45762306a36Sopenharmony_ci ath10k_err(ar, "gcc mem ioremap error\n"); 45862306a36Sopenharmony_ci ret = -ENOMEM; 45962306a36Sopenharmony_ci goto err_mem_unmap; 46062306a36Sopenharmony_ci } 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci ar_ahb->tcsr_mem = ioremap(ATH10K_TCSR_REG_BASE, 46362306a36Sopenharmony_ci ATH10K_TCSR_REG_SIZE); 46462306a36Sopenharmony_ci if (!ar_ahb->tcsr_mem) { 46562306a36Sopenharmony_ci ath10k_err(ar, "tcsr mem ioremap error\n"); 46662306a36Sopenharmony_ci ret = -ENOMEM; 46762306a36Sopenharmony_ci goto err_gcc_mem_unmap; 46862306a36Sopenharmony_ci } 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 47162306a36Sopenharmony_ci if (ret) { 47262306a36Sopenharmony_ci ath10k_err(ar, "failed to set 32-bit dma mask: %d\n", ret); 47362306a36Sopenharmony_ci goto err_tcsr_mem_unmap; 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 47762306a36Sopenharmony_ci if (ret) { 47862306a36Sopenharmony_ci ath10k_err(ar, "failed to set 32-bit consistent dma: %d\n", 47962306a36Sopenharmony_ci ret); 48062306a36Sopenharmony_ci goto err_tcsr_mem_unmap; 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci ret = ath10k_ahb_clock_init(ar); 48462306a36Sopenharmony_ci if (ret) 48562306a36Sopenharmony_ci goto err_tcsr_mem_unmap; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci ret = ath10k_ahb_rst_ctrl_init(ar); 48862306a36Sopenharmony_ci if (ret) 48962306a36Sopenharmony_ci goto err_clock_deinit; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci ar_ahb->irq = platform_get_irq_byname(pdev, "legacy"); 49262306a36Sopenharmony_ci if (ar_ahb->irq < 0) { 49362306a36Sopenharmony_ci ath10k_err(ar, "failed to get irq number: %d\n", ar_ahb->irq); 49462306a36Sopenharmony_ci ret = ar_ahb->irq; 49562306a36Sopenharmony_ci goto err_clock_deinit; 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci ath10k_dbg(ar, ATH10K_DBG_BOOT, "irq: %d\n", ar_ahb->irq); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci ath10k_dbg(ar, ATH10K_DBG_BOOT, "mem: 0x%pK mem_len: %lu gcc mem: 0x%pK tcsr_mem: 0x%pK\n", 50162306a36Sopenharmony_ci ar_ahb->mem, ar_ahb->mem_len, 50262306a36Sopenharmony_ci ar_ahb->gcc_mem, ar_ahb->tcsr_mem); 50362306a36Sopenharmony_ci return 0; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_cierr_clock_deinit: 50662306a36Sopenharmony_ci ath10k_ahb_clock_deinit(ar); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_cierr_tcsr_mem_unmap: 50962306a36Sopenharmony_ci iounmap(ar_ahb->tcsr_mem); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cierr_gcc_mem_unmap: 51262306a36Sopenharmony_ci ar_ahb->tcsr_mem = NULL; 51362306a36Sopenharmony_ci iounmap(ar_ahb->gcc_mem); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_cierr_mem_unmap: 51662306a36Sopenharmony_ci ar_ahb->gcc_mem = NULL; 51762306a36Sopenharmony_ci devm_iounmap(&pdev->dev, ar_ahb->mem); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ciout: 52062306a36Sopenharmony_ci ar_ahb->mem = NULL; 52162306a36Sopenharmony_ci return ret; 52262306a36Sopenharmony_ci} 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_cistatic void ath10k_ahb_resource_deinit(struct ath10k *ar) 52562306a36Sopenharmony_ci{ 52662306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 52762306a36Sopenharmony_ci struct device *dev; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci dev = &ar_ahb->pdev->dev; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci if (ar_ahb->mem) 53262306a36Sopenharmony_ci devm_iounmap(dev, ar_ahb->mem); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci if (ar_ahb->gcc_mem) 53562306a36Sopenharmony_ci iounmap(ar_ahb->gcc_mem); 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci if (ar_ahb->tcsr_mem) 53862306a36Sopenharmony_ci iounmap(ar_ahb->tcsr_mem); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci ar_ahb->mem = NULL; 54162306a36Sopenharmony_ci ar_ahb->gcc_mem = NULL; 54262306a36Sopenharmony_ci ar_ahb->tcsr_mem = NULL; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci ath10k_ahb_clock_deinit(ar); 54562306a36Sopenharmony_ci ath10k_ahb_rst_ctrl_deinit(ar); 54662306a36Sopenharmony_ci} 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_cistatic int ath10k_ahb_prepare_device(struct ath10k *ar) 54962306a36Sopenharmony_ci{ 55062306a36Sopenharmony_ci u32 val; 55162306a36Sopenharmony_ci int ret; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci ret = ath10k_ahb_clock_enable(ar); 55462306a36Sopenharmony_ci if (ret) { 55562306a36Sopenharmony_ci ath10k_err(ar, "failed to enable clocks\n"); 55662306a36Sopenharmony_ci return ret; 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci /* Clock for the target is supplied from outside of target (ie, 56062306a36Sopenharmony_ci * external clock module controlled by the host). Target needs 56162306a36Sopenharmony_ci * to know what frequency target cpu is configured which is needed 56262306a36Sopenharmony_ci * for target internal use. Read target cpu frequency info from 56362306a36Sopenharmony_ci * gcc register and write into target's scratch register where 56462306a36Sopenharmony_ci * target expects this information. 56562306a36Sopenharmony_ci */ 56662306a36Sopenharmony_ci val = ath10k_ahb_gcc_read32(ar, ATH10K_AHB_GCC_FEPLL_PLL_DIV); 56762306a36Sopenharmony_ci ath10k_ahb_write32(ar, ATH10K_AHB_WIFI_SCRATCH_5_REG, val); 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci ret = ath10k_ahb_release_reset(ar); 57062306a36Sopenharmony_ci if (ret) 57162306a36Sopenharmony_ci goto err_clk_disable; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci ath10k_ahb_irq_disable(ar); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci ath10k_ahb_write32(ar, FW_INDICATOR_ADDRESS, FW_IND_HOST_READY); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci ret = ath10k_pci_wait_for_target_init(ar); 57862306a36Sopenharmony_ci if (ret) 57962306a36Sopenharmony_ci goto err_halt_chip; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci return 0; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cierr_halt_chip: 58462306a36Sopenharmony_ci ath10k_ahb_halt_chip(ar); 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_cierr_clk_disable: 58762306a36Sopenharmony_ci ath10k_ahb_clock_disable(ar); 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci return ret; 59062306a36Sopenharmony_ci} 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_cistatic int ath10k_ahb_chip_reset(struct ath10k *ar) 59362306a36Sopenharmony_ci{ 59462306a36Sopenharmony_ci int ret; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci ath10k_ahb_halt_chip(ar); 59762306a36Sopenharmony_ci ath10k_ahb_clock_disable(ar); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci ret = ath10k_ahb_prepare_device(ar); 60062306a36Sopenharmony_ci if (ret) 60162306a36Sopenharmony_ci return ret; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci return 0; 60462306a36Sopenharmony_ci} 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_cistatic int ath10k_ahb_wake_target_cpu(struct ath10k *ar) 60762306a36Sopenharmony_ci{ 60862306a36Sopenharmony_ci u32 addr, val; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci addr = SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS; 61162306a36Sopenharmony_ci val = ath10k_ahb_read32(ar, addr); 61262306a36Sopenharmony_ci val |= ATH10K_AHB_CORE_CTRL_CPU_INTR_MASK; 61362306a36Sopenharmony_ci ath10k_ahb_write32(ar, addr, val); 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci return 0; 61662306a36Sopenharmony_ci} 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_cistatic int ath10k_ahb_hif_start(struct ath10k *ar) 61962306a36Sopenharmony_ci{ 62062306a36Sopenharmony_ci ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif start\n"); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci ath10k_core_napi_enable(ar); 62362306a36Sopenharmony_ci ath10k_ce_enable_interrupts(ar); 62462306a36Sopenharmony_ci ath10k_pci_enable_legacy_irq(ar); 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci ath10k_pci_rx_post(ar); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci return 0; 62962306a36Sopenharmony_ci} 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_cistatic void ath10k_ahb_hif_stop(struct ath10k *ar) 63262306a36Sopenharmony_ci{ 63362306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif stop\n"); 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci ath10k_ahb_irq_disable(ar); 63862306a36Sopenharmony_ci synchronize_irq(ar_ahb->irq); 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci ath10k_core_napi_sync_disable(ar); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci ath10k_pci_flush(ar); 64362306a36Sopenharmony_ci} 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic int ath10k_ahb_hif_power_up(struct ath10k *ar, 64662306a36Sopenharmony_ci enum ath10k_firmware_mode fw_mode) 64762306a36Sopenharmony_ci{ 64862306a36Sopenharmony_ci int ret; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif power up\n"); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci ret = ath10k_ahb_chip_reset(ar); 65362306a36Sopenharmony_ci if (ret) { 65462306a36Sopenharmony_ci ath10k_err(ar, "failed to reset chip: %d\n", ret); 65562306a36Sopenharmony_ci goto out; 65662306a36Sopenharmony_ci } 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci ret = ath10k_pci_init_pipes(ar); 65962306a36Sopenharmony_ci if (ret) { 66062306a36Sopenharmony_ci ath10k_err(ar, "failed to initialize CE: %d\n", ret); 66162306a36Sopenharmony_ci goto out; 66262306a36Sopenharmony_ci } 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci ret = ath10k_pci_init_config(ar); 66562306a36Sopenharmony_ci if (ret) { 66662306a36Sopenharmony_ci ath10k_err(ar, "failed to setup init config: %d\n", ret); 66762306a36Sopenharmony_ci goto err_ce_deinit; 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci ret = ath10k_ahb_wake_target_cpu(ar); 67162306a36Sopenharmony_ci if (ret) { 67262306a36Sopenharmony_ci ath10k_err(ar, "could not wake up target CPU: %d\n", ret); 67362306a36Sopenharmony_ci goto err_ce_deinit; 67462306a36Sopenharmony_ci } 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci return 0; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_cierr_ce_deinit: 67962306a36Sopenharmony_ci ath10k_pci_ce_deinit(ar); 68062306a36Sopenharmony_ciout: 68162306a36Sopenharmony_ci return ret; 68262306a36Sopenharmony_ci} 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_cistatic u32 ath10k_ahb_qca4019_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci u32 val = 0, region = addr & 0xfffff; 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci if (region >= QCA4019_SRAM_ADDR && region <= 69162306a36Sopenharmony_ci (QCA4019_SRAM_ADDR + QCA4019_SRAM_LEN)) { 69262306a36Sopenharmony_ci /* SRAM contents for QCA4019 can be directly accessed and 69362306a36Sopenharmony_ci * no conversions are required 69462306a36Sopenharmony_ci */ 69562306a36Sopenharmony_ci val |= region; 69662306a36Sopenharmony_ci } else { 69762306a36Sopenharmony_ci val |= 0x100000 | region; 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci return val; 70162306a36Sopenharmony_ci} 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_cistatic const struct ath10k_hif_ops ath10k_ahb_hif_ops = { 70462306a36Sopenharmony_ci .tx_sg = ath10k_pci_hif_tx_sg, 70562306a36Sopenharmony_ci .diag_read = ath10k_pci_hif_diag_read, 70662306a36Sopenharmony_ci .diag_write = ath10k_pci_diag_write_mem, 70762306a36Sopenharmony_ci .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, 70862306a36Sopenharmony_ci .start = ath10k_ahb_hif_start, 70962306a36Sopenharmony_ci .stop = ath10k_ahb_hif_stop, 71062306a36Sopenharmony_ci .map_service_to_pipe = ath10k_pci_hif_map_service_to_pipe, 71162306a36Sopenharmony_ci .get_default_pipe = ath10k_pci_hif_get_default_pipe, 71262306a36Sopenharmony_ci .send_complete_check = ath10k_pci_hif_send_complete_check, 71362306a36Sopenharmony_ci .get_free_queue_number = ath10k_pci_hif_get_free_queue_number, 71462306a36Sopenharmony_ci .power_up = ath10k_ahb_hif_power_up, 71562306a36Sopenharmony_ci .power_down = ath10k_pci_hif_power_down, 71662306a36Sopenharmony_ci .read32 = ath10k_ahb_read32, 71762306a36Sopenharmony_ci .write32 = ath10k_ahb_write32, 71862306a36Sopenharmony_ci}; 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_cistatic const struct ath10k_bus_ops ath10k_ahb_bus_ops = { 72162306a36Sopenharmony_ci .read32 = ath10k_ahb_read32, 72262306a36Sopenharmony_ci .write32 = ath10k_ahb_write32, 72362306a36Sopenharmony_ci .get_num_banks = ath10k_ahb_get_num_banks, 72462306a36Sopenharmony_ci}; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_cistatic int ath10k_ahb_probe(struct platform_device *pdev) 72762306a36Sopenharmony_ci{ 72862306a36Sopenharmony_ci struct ath10k *ar; 72962306a36Sopenharmony_ci struct ath10k_ahb *ar_ahb; 73062306a36Sopenharmony_ci struct ath10k_pci *ar_pci; 73162306a36Sopenharmony_ci enum ath10k_hw_rev hw_rev; 73262306a36Sopenharmony_ci size_t size; 73362306a36Sopenharmony_ci int ret; 73462306a36Sopenharmony_ci struct ath10k_bus_params bus_params = {}; 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci hw_rev = (uintptr_t)of_device_get_match_data(&pdev->dev); 73762306a36Sopenharmony_ci if (!hw_rev) { 73862306a36Sopenharmony_ci dev_err(&pdev->dev, "OF data missing\n"); 73962306a36Sopenharmony_ci return -EINVAL; 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci size = sizeof(*ar_pci) + sizeof(*ar_ahb); 74362306a36Sopenharmony_ci ar = ath10k_core_create(size, &pdev->dev, ATH10K_BUS_AHB, 74462306a36Sopenharmony_ci hw_rev, &ath10k_ahb_hif_ops); 74562306a36Sopenharmony_ci if (!ar) { 74662306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to allocate core\n"); 74762306a36Sopenharmony_ci return -ENOMEM; 74862306a36Sopenharmony_ci } 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci ath10k_dbg(ar, ATH10K_DBG_BOOT, "ahb probe\n"); 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci ar_pci = ath10k_pci_priv(ar); 75362306a36Sopenharmony_ci ar_ahb = ath10k_ahb_priv(ar); 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci ar_ahb->pdev = pdev; 75662306a36Sopenharmony_ci platform_set_drvdata(pdev, ar); 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci ret = ath10k_ahb_resource_init(ar); 75962306a36Sopenharmony_ci if (ret) 76062306a36Sopenharmony_ci goto err_core_destroy; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci ar->dev_id = 0; 76362306a36Sopenharmony_ci ar_pci->mem = ar_ahb->mem; 76462306a36Sopenharmony_ci ar_pci->mem_len = ar_ahb->mem_len; 76562306a36Sopenharmony_ci ar_pci->ar = ar; 76662306a36Sopenharmony_ci ar_pci->ce.bus_ops = &ath10k_ahb_bus_ops; 76762306a36Sopenharmony_ci ar_pci->targ_cpu_to_ce_addr = ath10k_ahb_qca4019_targ_cpu_to_ce_addr; 76862306a36Sopenharmony_ci ar->ce_priv = &ar_pci->ce; 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci ret = ath10k_pci_setup_resource(ar); 77162306a36Sopenharmony_ci if (ret) { 77262306a36Sopenharmony_ci ath10k_err(ar, "failed to setup resource: %d\n", ret); 77362306a36Sopenharmony_ci goto err_resource_deinit; 77462306a36Sopenharmony_ci } 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci ath10k_pci_init_napi(ar); 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci ret = ath10k_ahb_request_irq_legacy(ar); 77962306a36Sopenharmony_ci if (ret) 78062306a36Sopenharmony_ci goto err_free_pipes; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci ret = ath10k_ahb_prepare_device(ar); 78362306a36Sopenharmony_ci if (ret) 78462306a36Sopenharmony_ci goto err_free_irq; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci ath10k_pci_ce_deinit(ar); 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci bus_params.dev_type = ATH10K_DEV_TYPE_LL; 78962306a36Sopenharmony_ci bus_params.chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS); 79062306a36Sopenharmony_ci if (bus_params.chip_id == 0xffffffff) { 79162306a36Sopenharmony_ci ath10k_err(ar, "failed to get chip id\n"); 79262306a36Sopenharmony_ci ret = -ENODEV; 79362306a36Sopenharmony_ci goto err_halt_device; 79462306a36Sopenharmony_ci } 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci ret = ath10k_core_register(ar, &bus_params); 79762306a36Sopenharmony_ci if (ret) { 79862306a36Sopenharmony_ci ath10k_err(ar, "failed to register driver core: %d\n", ret); 79962306a36Sopenharmony_ci goto err_halt_device; 80062306a36Sopenharmony_ci } 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci return 0; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_cierr_halt_device: 80562306a36Sopenharmony_ci ath10k_ahb_halt_chip(ar); 80662306a36Sopenharmony_ci ath10k_ahb_clock_disable(ar); 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_cierr_free_irq: 80962306a36Sopenharmony_ci ath10k_ahb_release_irq_legacy(ar); 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_cierr_free_pipes: 81262306a36Sopenharmony_ci ath10k_pci_release_resource(ar); 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_cierr_resource_deinit: 81562306a36Sopenharmony_ci ath10k_ahb_resource_deinit(ar); 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_cierr_core_destroy: 81862306a36Sopenharmony_ci ath10k_core_destroy(ar); 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci return ret; 82162306a36Sopenharmony_ci} 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_cistatic void ath10k_ahb_remove(struct platform_device *pdev) 82462306a36Sopenharmony_ci{ 82562306a36Sopenharmony_ci struct ath10k *ar = platform_get_drvdata(pdev); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci ath10k_dbg(ar, ATH10K_DBG_AHB, "ahb remove\n"); 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci ath10k_core_unregister(ar); 83062306a36Sopenharmony_ci ath10k_ahb_irq_disable(ar); 83162306a36Sopenharmony_ci ath10k_ahb_release_irq_legacy(ar); 83262306a36Sopenharmony_ci ath10k_pci_release_resource(ar); 83362306a36Sopenharmony_ci ath10k_ahb_halt_chip(ar); 83462306a36Sopenharmony_ci ath10k_ahb_clock_disable(ar); 83562306a36Sopenharmony_ci ath10k_ahb_resource_deinit(ar); 83662306a36Sopenharmony_ci ath10k_core_destroy(ar); 83762306a36Sopenharmony_ci} 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_cistatic struct platform_driver ath10k_ahb_driver = { 84062306a36Sopenharmony_ci .driver = { 84162306a36Sopenharmony_ci .name = "ath10k_ahb", 84262306a36Sopenharmony_ci .of_match_table = ath10k_ahb_of_match, 84362306a36Sopenharmony_ci }, 84462306a36Sopenharmony_ci .probe = ath10k_ahb_probe, 84562306a36Sopenharmony_ci .remove_new = ath10k_ahb_remove, 84662306a36Sopenharmony_ci}; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ciint ath10k_ahb_init(void) 84962306a36Sopenharmony_ci{ 85062306a36Sopenharmony_ci int ret; 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci ret = platform_driver_register(&ath10k_ahb_driver); 85362306a36Sopenharmony_ci if (ret) 85462306a36Sopenharmony_ci printk(KERN_ERR "failed to register ath10k ahb driver: %d\n", 85562306a36Sopenharmony_ci ret); 85662306a36Sopenharmony_ci return ret; 85762306a36Sopenharmony_ci} 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_civoid ath10k_ahb_exit(void) 86062306a36Sopenharmony_ci{ 86162306a36Sopenharmony_ci platform_driver_unregister(&ath10k_ahb_driver); 86262306a36Sopenharmony_ci} 863