Path: blob/main/sys/contrib/dev/athk/ath10k/ahb.c
105957 views
// SPDX-License-Identifier: ISC1/*2* Copyright (c) 2016-2017 Qualcomm Atheros, Inc. All rights reserved.3* Copyright (c) 2015 The Linux Foundation. All rights reserved.4*/5#include <linux/module.h>6#include <linux/of.h>7#include <linux/platform_device.h>8#include <linux/clk.h>9#include <linux/reset.h>10#include "core.h"11#include "debug.h"12#include "pci.h"13#include "ahb.h"1415static const struct of_device_id ath10k_ahb_of_match[] = {16{ .compatible = "qcom,ipq4019-wifi",17.data = (void *)ATH10K_HW_QCA401918},19{ }20};2122MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match);2324#define QCA4019_SRAM_ADDR 0x000C000025#define QCA4019_SRAM_LEN 0x00040000 /* 256 kb */2627static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar)28{29return &ath10k_pci_priv(ar)->ahb[0];30}3132static void ath10k_ahb_write32(struct ath10k *ar, u32 offset, u32 value)33{34struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);3536iowrite32(value, ar_ahb->mem + offset);37}3839static u32 ath10k_ahb_read32(struct ath10k *ar, u32 offset)40{41struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);4243return ioread32(ar_ahb->mem + offset);44}4546static u32 ath10k_ahb_gcc_read32(struct ath10k *ar, u32 offset)47{48struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);4950return ioread32(ar_ahb->gcc_mem + offset);51}5253static void ath10k_ahb_tcsr_write32(struct ath10k *ar, u32 offset, u32 value)54{55struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);5657iowrite32(value, ar_ahb->tcsr_mem + offset);58}5960static u32 ath10k_ahb_tcsr_read32(struct ath10k *ar, u32 offset)61{62struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);6364return ioread32(ar_ahb->tcsr_mem + offset);65}6667static u32 ath10k_ahb_soc_read32(struct ath10k *ar, u32 addr)68{69return ath10k_ahb_read32(ar, RTC_SOC_BASE_ADDRESS + addr);70}7172static int ath10k_ahb_get_num_banks(struct ath10k *ar)73{74if (ar->hw_rev == ATH10K_HW_QCA4019)75return 1;7677ath10k_warn(ar, "unknown number of banks, assuming 1\n");78return 1;79}8081static int ath10k_ahb_clock_init(struct ath10k *ar)82{83struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);84struct device *dev;8586dev = &ar_ahb->pdev->dev;8788ar_ahb->cmd_clk = devm_clk_get(dev, "wifi_wcss_cmd");89if (IS_ERR_OR_NULL(ar_ahb->cmd_clk)) {90ath10k_err(ar, "failed to get cmd clk: %ld\n",91PTR_ERR(ar_ahb->cmd_clk));92return ar_ahb->cmd_clk ? PTR_ERR(ar_ahb->cmd_clk) : -ENODEV;93}9495ar_ahb->ref_clk = devm_clk_get(dev, "wifi_wcss_ref");96if (IS_ERR_OR_NULL(ar_ahb->ref_clk)) {97ath10k_err(ar, "failed to get ref clk: %ld\n",98PTR_ERR(ar_ahb->ref_clk));99return ar_ahb->ref_clk ? PTR_ERR(ar_ahb->ref_clk) : -ENODEV;100}101102ar_ahb->rtc_clk = devm_clk_get(dev, "wifi_wcss_rtc");103if (IS_ERR_OR_NULL(ar_ahb->rtc_clk)) {104ath10k_err(ar, "failed to get rtc clk: %ld\n",105PTR_ERR(ar_ahb->rtc_clk));106return ar_ahb->rtc_clk ? PTR_ERR(ar_ahb->rtc_clk) : -ENODEV;107}108109return 0;110}111112static void ath10k_ahb_clock_deinit(struct ath10k *ar)113{114struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);115116ar_ahb->cmd_clk = NULL;117ar_ahb->ref_clk = NULL;118ar_ahb->rtc_clk = NULL;119}120121static int ath10k_ahb_clock_enable(struct ath10k *ar)122{123struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);124int ret;125126if (IS_ERR_OR_NULL(ar_ahb->cmd_clk) ||127IS_ERR_OR_NULL(ar_ahb->ref_clk) ||128IS_ERR_OR_NULL(ar_ahb->rtc_clk)) {129ath10k_err(ar, "clock(s) is/are not initialized\n");130ret = -EIO;131goto out;132}133134ret = clk_prepare_enable(ar_ahb->cmd_clk);135if (ret) {136ath10k_err(ar, "failed to enable cmd clk: %d\n", ret);137goto out;138}139140ret = clk_prepare_enable(ar_ahb->ref_clk);141if (ret) {142ath10k_err(ar, "failed to enable ref clk: %d\n", ret);143goto err_cmd_clk_disable;144}145146ret = clk_prepare_enable(ar_ahb->rtc_clk);147if (ret) {148ath10k_err(ar, "failed to enable rtc clk: %d\n", ret);149goto err_ref_clk_disable;150}151152return 0;153154err_ref_clk_disable:155clk_disable_unprepare(ar_ahb->ref_clk);156157err_cmd_clk_disable:158clk_disable_unprepare(ar_ahb->cmd_clk);159160out:161return ret;162}163164static void ath10k_ahb_clock_disable(struct ath10k *ar)165{166struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);167168clk_disable_unprepare(ar_ahb->cmd_clk);169170clk_disable_unprepare(ar_ahb->ref_clk);171172clk_disable_unprepare(ar_ahb->rtc_clk);173}174175static int ath10k_ahb_rst_ctrl_init(struct ath10k *ar)176{177struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);178struct device *dev;179180dev = &ar_ahb->pdev->dev;181182ar_ahb->core_cold_rst = devm_reset_control_get_exclusive(dev,183"wifi_core_cold");184if (IS_ERR(ar_ahb->core_cold_rst)) {185ath10k_err(ar, "failed to get core cold rst ctrl: %ld\n",186PTR_ERR(ar_ahb->core_cold_rst));187return PTR_ERR(ar_ahb->core_cold_rst);188}189190ar_ahb->radio_cold_rst = devm_reset_control_get_exclusive(dev,191"wifi_radio_cold");192if (IS_ERR(ar_ahb->radio_cold_rst)) {193ath10k_err(ar, "failed to get radio cold rst ctrl: %ld\n",194PTR_ERR(ar_ahb->radio_cold_rst));195return PTR_ERR(ar_ahb->radio_cold_rst);196}197198ar_ahb->radio_warm_rst = devm_reset_control_get_exclusive(dev,199"wifi_radio_warm");200if (IS_ERR(ar_ahb->radio_warm_rst)) {201ath10k_err(ar, "failed to get radio warm rst ctrl: %ld\n",202PTR_ERR(ar_ahb->radio_warm_rst));203return PTR_ERR(ar_ahb->radio_warm_rst);204}205206ar_ahb->radio_srif_rst = devm_reset_control_get_exclusive(dev,207"wifi_radio_srif");208if (IS_ERR(ar_ahb->radio_srif_rst)) {209ath10k_err(ar, "failed to get radio srif rst ctrl: %ld\n",210PTR_ERR(ar_ahb->radio_srif_rst));211return PTR_ERR(ar_ahb->radio_srif_rst);212}213214ar_ahb->cpu_init_rst = devm_reset_control_get_exclusive(dev,215"wifi_cpu_init");216if (IS_ERR(ar_ahb->cpu_init_rst)) {217ath10k_err(ar, "failed to get cpu init rst ctrl: %ld\n",218PTR_ERR(ar_ahb->cpu_init_rst));219return PTR_ERR(ar_ahb->cpu_init_rst);220}221222return 0;223}224225static void ath10k_ahb_rst_ctrl_deinit(struct ath10k *ar)226{227struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);228229ar_ahb->core_cold_rst = NULL;230ar_ahb->radio_cold_rst = NULL;231ar_ahb->radio_warm_rst = NULL;232ar_ahb->radio_srif_rst = NULL;233ar_ahb->cpu_init_rst = NULL;234}235236static int ath10k_ahb_release_reset(struct ath10k *ar)237{238struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);239int ret;240241if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) ||242IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) ||243IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) ||244IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) {245ath10k_err(ar, "rst ctrl(s) is/are not initialized\n");246return -EINVAL;247}248249ret = reset_control_deassert(ar_ahb->radio_cold_rst);250if (ret) {251ath10k_err(ar, "failed to deassert radio cold rst: %d\n", ret);252return ret;253}254255ret = reset_control_deassert(ar_ahb->radio_warm_rst);256if (ret) {257ath10k_err(ar, "failed to deassert radio warm rst: %d\n", ret);258return ret;259}260261ret = reset_control_deassert(ar_ahb->radio_srif_rst);262if (ret) {263ath10k_err(ar, "failed to deassert radio srif rst: %d\n", ret);264return ret;265}266267ret = reset_control_deassert(ar_ahb->cpu_init_rst);268if (ret) {269ath10k_err(ar, "failed to deassert cpu init rst: %d\n", ret);270return ret;271}272273return 0;274}275276static void ath10k_ahb_halt_axi_bus(struct ath10k *ar, u32 haltreq_reg,277u32 haltack_reg)278{279unsigned long timeout;280u32 val;281282/* Issue halt axi bus request */283val = ath10k_ahb_tcsr_read32(ar, haltreq_reg);284val |= AHB_AXI_BUS_HALT_REQ;285ath10k_ahb_tcsr_write32(ar, haltreq_reg, val);286287/* Wait for axi bus halted ack */288timeout = jiffies + msecs_to_jiffies(ATH10K_AHB_AXI_BUS_HALT_TIMEOUT);289do {290val = ath10k_ahb_tcsr_read32(ar, haltack_reg);291if (val & AHB_AXI_BUS_HALT_ACK)292break;293294mdelay(1);295} while (time_before(jiffies, timeout));296297if (!(val & AHB_AXI_BUS_HALT_ACK)) {298ath10k_err(ar, "failed to halt axi bus: %d\n", val);299return;300}301302ath10k_dbg(ar, ATH10K_DBG_AHB, "axi bus halted\n");303}304305static void ath10k_ahb_halt_chip(struct ath10k *ar)306{307struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);308u32 core_id, glb_cfg_reg, haltreq_reg, haltack_reg;309u32 val;310int ret;311312if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst) ||313IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) ||314IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) ||315IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) ||316IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) {317ath10k_err(ar, "rst ctrl(s) is/are not initialized\n");318return;319}320321core_id = ath10k_ahb_read32(ar, ATH10K_AHB_WLAN_CORE_ID_REG);322323switch (core_id) {324case 0:325glb_cfg_reg = ATH10K_AHB_TCSR_WIFI0_GLB_CFG;326haltreq_reg = ATH10K_AHB_TCSR_WCSS0_HALTREQ;327haltack_reg = ATH10K_AHB_TCSR_WCSS0_HALTACK;328break;329case 1:330glb_cfg_reg = ATH10K_AHB_TCSR_WIFI1_GLB_CFG;331haltreq_reg = ATH10K_AHB_TCSR_WCSS1_HALTREQ;332haltack_reg = ATH10K_AHB_TCSR_WCSS1_HALTACK;333break;334default:335ath10k_err(ar, "invalid core id %d found, skipping reset sequence\n",336core_id);337return;338}339340ath10k_ahb_halt_axi_bus(ar, haltreq_reg, haltack_reg);341342val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg);343val |= TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK;344ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val);345346ret = reset_control_assert(ar_ahb->core_cold_rst);347if (ret)348ath10k_err(ar, "failed to assert core cold rst: %d\n", ret);349msleep(1);350351ret = reset_control_assert(ar_ahb->radio_cold_rst);352if (ret)353ath10k_err(ar, "failed to assert radio cold rst: %d\n", ret);354msleep(1);355356ret = reset_control_assert(ar_ahb->radio_warm_rst);357if (ret)358ath10k_err(ar, "failed to assert radio warm rst: %d\n", ret);359msleep(1);360361ret = reset_control_assert(ar_ahb->radio_srif_rst);362if (ret)363ath10k_err(ar, "failed to assert radio srif rst: %d\n", ret);364msleep(1);365366ret = reset_control_assert(ar_ahb->cpu_init_rst);367if (ret)368ath10k_err(ar, "failed to assert cpu init rst: %d\n", ret);369msleep(10);370371/* Clear halt req and core clock disable req before372* deasserting wifi core reset.373*/374val = ath10k_ahb_tcsr_read32(ar, haltreq_reg);375val &= ~AHB_AXI_BUS_HALT_REQ;376ath10k_ahb_tcsr_write32(ar, haltreq_reg, val);377378val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg);379val &= ~TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK;380ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val);381382ret = reset_control_deassert(ar_ahb->core_cold_rst);383if (ret)384ath10k_err(ar, "failed to deassert core cold rst: %d\n", ret);385386ath10k_dbg(ar, ATH10K_DBG_AHB, "core %d reset done\n", core_id);387}388389static irqreturn_t ath10k_ahb_interrupt_handler(int irq, void *arg)390{391struct ath10k *ar = arg;392393if (!ath10k_pci_irq_pending(ar))394return IRQ_NONE;395396ath10k_pci_disable_and_clear_intx_irq(ar);397ath10k_pci_irq_msi_fw_mask(ar);398napi_schedule(&ar->napi);399400return IRQ_HANDLED;401}402403static int ath10k_ahb_request_irq_intx(struct ath10k *ar)404{405struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);406struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);407int ret;408409ret = request_irq(ar_ahb->irq,410ath10k_ahb_interrupt_handler,411IRQF_SHARED, "ath10k_ahb", ar);412if (ret) {413ath10k_warn(ar, "failed to request legacy irq %d: %d\n",414ar_ahb->irq, ret);415return ret;416}417ar_pci->oper_irq_mode = ATH10K_PCI_IRQ_INTX;418419return 0;420}421422static void ath10k_ahb_release_irq_intx(struct ath10k *ar)423{424struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);425426free_irq(ar_ahb->irq, ar);427}428429static void ath10k_ahb_irq_disable(struct ath10k *ar)430{431ath10k_ce_disable_interrupts(ar);432ath10k_pci_disable_and_clear_intx_irq(ar);433}434435static int ath10k_ahb_resource_init(struct ath10k *ar)436{437struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);438struct platform_device *pdev;439struct resource *res;440int ret;441442pdev = ar_ahb->pdev;443444ar_ahb->mem = devm_platform_get_and_ioremap_resource(pdev, 0, &res);445if (IS_ERR(ar_ahb->mem)) {446ath10k_err(ar, "mem ioremap error\n");447ret = PTR_ERR(ar_ahb->mem);448goto out;449}450451ar_ahb->mem_len = resource_size(res);452453ar_ahb->gcc_mem = ioremap(ATH10K_GCC_REG_BASE,454ATH10K_GCC_REG_SIZE);455if (!ar_ahb->gcc_mem) {456ath10k_err(ar, "gcc mem ioremap error\n");457ret = -ENOMEM;458goto err_mem_unmap;459}460461ar_ahb->tcsr_mem = ioremap(ATH10K_TCSR_REG_BASE,462ATH10K_TCSR_REG_SIZE);463if (!ar_ahb->tcsr_mem) {464ath10k_err(ar, "tcsr mem ioremap error\n");465ret = -ENOMEM;466goto err_gcc_mem_unmap;467}468469ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));470if (ret) {471ath10k_err(ar, "failed to set 32-bit dma mask: %d\n", ret);472goto err_tcsr_mem_unmap;473}474475ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));476if (ret) {477ath10k_err(ar, "failed to set 32-bit consistent dma: %d\n",478ret);479goto err_tcsr_mem_unmap;480}481482ret = ath10k_ahb_clock_init(ar);483if (ret)484goto err_tcsr_mem_unmap;485486ret = ath10k_ahb_rst_ctrl_init(ar);487if (ret)488goto err_clock_deinit;489490ar_ahb->irq = platform_get_irq_byname(pdev, "legacy");491if (ar_ahb->irq < 0) {492ath10k_err(ar, "failed to get irq number: %d\n", ar_ahb->irq);493ret = ar_ahb->irq;494goto err_clock_deinit;495}496497ath10k_dbg(ar, ATH10K_DBG_BOOT, "irq: %d\n", ar_ahb->irq);498499ath10k_dbg(ar, ATH10K_DBG_BOOT, "mem: 0x%p mem_len: %lu gcc mem: 0x%p tcsr_mem: 0x%p\n",500ar_ahb->mem, ar_ahb->mem_len,501ar_ahb->gcc_mem, ar_ahb->tcsr_mem);502return 0;503504err_clock_deinit:505ath10k_ahb_clock_deinit(ar);506507err_tcsr_mem_unmap:508iounmap(ar_ahb->tcsr_mem);509510err_gcc_mem_unmap:511ar_ahb->tcsr_mem = NULL;512iounmap(ar_ahb->gcc_mem);513514err_mem_unmap:515ar_ahb->gcc_mem = NULL;516devm_iounmap(&pdev->dev, ar_ahb->mem);517518out:519ar_ahb->mem = NULL;520return ret;521}522523static void ath10k_ahb_resource_deinit(struct ath10k *ar)524{525struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);526struct device *dev;527528dev = &ar_ahb->pdev->dev;529530if (ar_ahb->mem)531devm_iounmap(dev, ar_ahb->mem);532533if (ar_ahb->gcc_mem)534iounmap(ar_ahb->gcc_mem);535536if (ar_ahb->tcsr_mem)537iounmap(ar_ahb->tcsr_mem);538539ar_ahb->mem = NULL;540ar_ahb->gcc_mem = NULL;541ar_ahb->tcsr_mem = NULL;542543ath10k_ahb_clock_deinit(ar);544ath10k_ahb_rst_ctrl_deinit(ar);545}546547static int ath10k_ahb_prepare_device(struct ath10k *ar)548{549u32 val;550int ret;551552ret = ath10k_ahb_clock_enable(ar);553if (ret) {554ath10k_err(ar, "failed to enable clocks\n");555return ret;556}557558/* Clock for the target is supplied from outside of target (ie,559* external clock module controlled by the host). Target needs560* to know what frequency target cpu is configured which is needed561* for target internal use. Read target cpu frequency info from562* gcc register and write into target's scratch register where563* target expects this information.564*/565val = ath10k_ahb_gcc_read32(ar, ATH10K_AHB_GCC_FEPLL_PLL_DIV);566ath10k_ahb_write32(ar, ATH10K_AHB_WIFI_SCRATCH_5_REG, val);567568ret = ath10k_ahb_release_reset(ar);569if (ret)570goto err_clk_disable;571572ath10k_ahb_irq_disable(ar);573574ath10k_ahb_write32(ar, FW_INDICATOR_ADDRESS, FW_IND_HOST_READY);575576ret = ath10k_pci_wait_for_target_init(ar);577if (ret)578goto err_halt_chip;579580return 0;581582err_halt_chip:583ath10k_ahb_halt_chip(ar);584585err_clk_disable:586ath10k_ahb_clock_disable(ar);587588return ret;589}590591static int ath10k_ahb_chip_reset(struct ath10k *ar)592{593int ret;594595ath10k_ahb_halt_chip(ar);596ath10k_ahb_clock_disable(ar);597598ret = ath10k_ahb_prepare_device(ar);599if (ret)600return ret;601602return 0;603}604605static int ath10k_ahb_wake_target_cpu(struct ath10k *ar)606{607u32 addr, val;608609addr = SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS;610val = ath10k_ahb_read32(ar, addr);611val |= ATH10K_AHB_CORE_CTRL_CPU_INTR_MASK;612ath10k_ahb_write32(ar, addr, val);613614return 0;615}616617static int ath10k_ahb_hif_start(struct ath10k *ar)618{619ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif start\n");620621ath10k_core_napi_enable(ar);622ath10k_ce_enable_interrupts(ar);623ath10k_pci_enable_intx_irq(ar);624625ath10k_pci_rx_post(ar);626627return 0;628}629630static void ath10k_ahb_hif_stop(struct ath10k *ar)631{632struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);633634ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif stop\n");635636ath10k_ahb_irq_disable(ar);637synchronize_irq(ar_ahb->irq);638639ath10k_core_napi_sync_disable(ar);640641ath10k_pci_flush(ar);642}643644static int ath10k_ahb_hif_power_up(struct ath10k *ar,645enum ath10k_firmware_mode fw_mode)646{647int ret;648649ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif power up\n");650651ret = ath10k_ahb_chip_reset(ar);652if (ret) {653ath10k_err(ar, "failed to reset chip: %d\n", ret);654goto out;655}656657ret = ath10k_pci_init_pipes(ar);658if (ret) {659ath10k_err(ar, "failed to initialize CE: %d\n", ret);660goto out;661}662663ret = ath10k_pci_init_config(ar);664if (ret) {665ath10k_err(ar, "failed to setup init config: %d\n", ret);666goto err_ce_deinit;667}668669ret = ath10k_ahb_wake_target_cpu(ar);670if (ret) {671ath10k_err(ar, "could not wake up target CPU: %d\n", ret);672goto err_ce_deinit;673}674675return 0;676677err_ce_deinit:678ath10k_pci_ce_deinit(ar);679out:680return ret;681}682683static u32 ath10k_ahb_qca4019_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)684{685u32 val = 0, region = addr & 0xfffff;686687val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS);688689if (region >= QCA4019_SRAM_ADDR && region <=690(QCA4019_SRAM_ADDR + QCA4019_SRAM_LEN)) {691/* SRAM contents for QCA4019 can be directly accessed and692* no conversions are required693*/694val |= region;695} else {696val |= 0x100000 | region;697}698699return val;700}701702static const struct ath10k_hif_ops ath10k_ahb_hif_ops = {703.tx_sg = ath10k_pci_hif_tx_sg,704.diag_read = ath10k_pci_hif_diag_read,705.diag_write = ath10k_pci_diag_write_mem,706.exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg,707.start = ath10k_ahb_hif_start,708.stop = ath10k_ahb_hif_stop,709.map_service_to_pipe = ath10k_pci_hif_map_service_to_pipe,710.get_default_pipe = ath10k_pci_hif_get_default_pipe,711.send_complete_check = ath10k_pci_hif_send_complete_check,712.get_free_queue_number = ath10k_pci_hif_get_free_queue_number,713.power_up = ath10k_ahb_hif_power_up,714.power_down = ath10k_pci_hif_power_down,715.read32 = ath10k_ahb_read32,716.write32 = ath10k_ahb_write32,717};718719static const struct ath10k_bus_ops ath10k_ahb_bus_ops = {720.read32 = ath10k_ahb_read32,721.write32 = ath10k_ahb_write32,722.get_num_banks = ath10k_ahb_get_num_banks,723};724725static int ath10k_ahb_probe(struct platform_device *pdev)726{727struct ath10k *ar;728struct ath10k_ahb *ar_ahb;729struct ath10k_pci *ar_pci;730enum ath10k_hw_rev hw_rev;731size_t size;732int ret;733struct ath10k_bus_params bus_params = {};734735hw_rev = (uintptr_t)of_device_get_match_data(&pdev->dev);736if (!hw_rev) {737dev_err(&pdev->dev, "OF data missing\n");738return -EINVAL;739}740741size = sizeof(*ar_pci) + sizeof(*ar_ahb);742ar = ath10k_core_create(size, &pdev->dev, ATH10K_BUS_AHB,743hw_rev, &ath10k_ahb_hif_ops);744if (!ar) {745dev_err(&pdev->dev, "failed to allocate core\n");746return -ENOMEM;747}748749ath10k_dbg(ar, ATH10K_DBG_BOOT, "ahb probe\n");750751ar_pci = ath10k_pci_priv(ar);752ar_ahb = ath10k_ahb_priv(ar);753754ar_ahb->pdev = pdev;755platform_set_drvdata(pdev, ar);756757ret = ath10k_ahb_resource_init(ar);758if (ret)759goto err_core_destroy;760761ar->dev_id = 0;762ar_pci->mem = ar_ahb->mem;763ar_pci->mem_len = ar_ahb->mem_len;764ar_pci->ar = ar;765ar_pci->ce.bus_ops = &ath10k_ahb_bus_ops;766ar_pci->targ_cpu_to_ce_addr = ath10k_ahb_qca4019_targ_cpu_to_ce_addr;767ar->ce_priv = &ar_pci->ce;768769ret = ath10k_pci_setup_resource(ar);770if (ret) {771ath10k_err(ar, "failed to setup resource: %d\n", ret);772goto err_resource_deinit;773}774775ath10k_pci_init_napi(ar);776777ret = ath10k_ahb_request_irq_intx(ar);778if (ret)779goto err_free_pipes;780781ret = ath10k_ahb_prepare_device(ar);782if (ret)783goto err_free_irq;784785ath10k_pci_ce_deinit(ar);786787bus_params.dev_type = ATH10K_DEV_TYPE_LL;788bus_params.chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS);789if (bus_params.chip_id == 0xffffffff) {790ath10k_err(ar, "failed to get chip id\n");791ret = -ENODEV;792goto err_halt_device;793}794795ret = ath10k_core_register(ar, &bus_params);796if (ret) {797ath10k_err(ar, "failed to register driver core: %d\n", ret);798goto err_halt_device;799}800801return 0;802803err_halt_device:804ath10k_ahb_halt_chip(ar);805ath10k_ahb_clock_disable(ar);806807err_free_irq:808ath10k_ahb_release_irq_intx(ar);809810err_free_pipes:811ath10k_pci_release_resource(ar);812813err_resource_deinit:814ath10k_ahb_resource_deinit(ar);815816err_core_destroy:817ath10k_core_destroy(ar);818819return ret;820}821822static void ath10k_ahb_remove(struct platform_device *pdev)823{824struct ath10k *ar = platform_get_drvdata(pdev);825826ath10k_dbg(ar, ATH10K_DBG_AHB, "ahb remove\n");827828ath10k_core_unregister(ar);829ath10k_ahb_irq_disable(ar);830ath10k_ahb_release_irq_intx(ar);831ath10k_pci_release_resource(ar);832ath10k_ahb_halt_chip(ar);833ath10k_ahb_clock_disable(ar);834ath10k_ahb_resource_deinit(ar);835ath10k_core_destroy(ar);836}837838static struct platform_driver ath10k_ahb_driver = {839.driver = {840.name = "ath10k_ahb",841.of_match_table = ath10k_ahb_of_match,842},843.probe = ath10k_ahb_probe,844.remove = ath10k_ahb_remove,845};846847int ath10k_ahb_init(void)848{849int ret;850851ret = platform_driver_register(&ath10k_ahb_driver);852if (ret)853printk(KERN_ERR "failed to register ath10k ahb driver: %d\n",854ret);855return ret;856}857858void ath10k_ahb_exit(void)859{860platform_driver_unregister(&ath10k_ahb_driver);861}862863864