xref: /freebsd/sys/contrib/dev/athk/ath10k/ahb.c (revision 07724ba62b4c432ea04dce9465a5ab6e2c3f5a0d)
1da8fa4e3SBjoern A. Zeeb // SPDX-License-Identifier: ISC
2da8fa4e3SBjoern A. Zeeb /*
3da8fa4e3SBjoern A. Zeeb  * Copyright (c) 2016-2017 Qualcomm Atheros, Inc. All rights reserved.
4da8fa4e3SBjoern A. Zeeb  * Copyright (c) 2015 The Linux Foundation. All rights reserved.
5da8fa4e3SBjoern A. Zeeb  */
6da8fa4e3SBjoern A. Zeeb #include <linux/module.h>
7da8fa4e3SBjoern A. Zeeb #include <linux/of.h>
8*07724ba6SBjoern A. Zeeb #include <linux/platform_device.h>
9da8fa4e3SBjoern A. Zeeb #include <linux/clk.h>
10da8fa4e3SBjoern A. Zeeb #include <linux/reset.h>
11da8fa4e3SBjoern A. Zeeb #include "core.h"
12da8fa4e3SBjoern A. Zeeb #include "debug.h"
13da8fa4e3SBjoern A. Zeeb #include "pci.h"
14da8fa4e3SBjoern A. Zeeb #include "ahb.h"
15da8fa4e3SBjoern A. Zeeb 
16da8fa4e3SBjoern A. Zeeb static const struct of_device_id ath10k_ahb_of_match[] = {
17da8fa4e3SBjoern A. Zeeb 	{ .compatible = "qcom,ipq4019-wifi",
18da8fa4e3SBjoern A. Zeeb 	  .data = (void *)ATH10K_HW_QCA4019
19da8fa4e3SBjoern A. Zeeb 	},
20da8fa4e3SBjoern A. Zeeb 	{ }
21da8fa4e3SBjoern A. Zeeb };
22da8fa4e3SBjoern A. Zeeb 
23da8fa4e3SBjoern A. Zeeb MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match);
24da8fa4e3SBjoern A. Zeeb 
25da8fa4e3SBjoern A. Zeeb #define QCA4019_SRAM_ADDR      0x000C0000
26da8fa4e3SBjoern A. Zeeb #define QCA4019_SRAM_LEN       0x00040000 /* 256 kb */
27da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_priv(struct ath10k * ar)28da8fa4e3SBjoern A. Zeeb static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar)
29da8fa4e3SBjoern A. Zeeb {
30*07724ba6SBjoern A. Zeeb 	return &ath10k_pci_priv(ar)->ahb[0];
31da8fa4e3SBjoern A. Zeeb }
32da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_write32(struct ath10k * ar,u32 offset,u32 value)33da8fa4e3SBjoern A. Zeeb static void ath10k_ahb_write32(struct ath10k *ar, u32 offset, u32 value)
34da8fa4e3SBjoern A. Zeeb {
35da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
36da8fa4e3SBjoern A. Zeeb 
37da8fa4e3SBjoern A. Zeeb 	iowrite32(value, ar_ahb->mem + offset);
38da8fa4e3SBjoern A. Zeeb }
39da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_read32(struct ath10k * ar,u32 offset)40da8fa4e3SBjoern A. Zeeb static u32 ath10k_ahb_read32(struct ath10k *ar, u32 offset)
41da8fa4e3SBjoern A. Zeeb {
42da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
43da8fa4e3SBjoern A. Zeeb 
44da8fa4e3SBjoern A. Zeeb 	return ioread32(ar_ahb->mem + offset);
45da8fa4e3SBjoern A. Zeeb }
46da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_gcc_read32(struct ath10k * ar,u32 offset)47da8fa4e3SBjoern A. Zeeb static u32 ath10k_ahb_gcc_read32(struct ath10k *ar, u32 offset)
48da8fa4e3SBjoern A. Zeeb {
49da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
50da8fa4e3SBjoern A. Zeeb 
51da8fa4e3SBjoern A. Zeeb 	return ioread32(ar_ahb->gcc_mem + offset);
52da8fa4e3SBjoern A. Zeeb }
53da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_tcsr_write32(struct ath10k * ar,u32 offset,u32 value)54da8fa4e3SBjoern A. Zeeb static void ath10k_ahb_tcsr_write32(struct ath10k *ar, u32 offset, u32 value)
55da8fa4e3SBjoern A. Zeeb {
56da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
57da8fa4e3SBjoern A. Zeeb 
58da8fa4e3SBjoern A. Zeeb 	iowrite32(value, ar_ahb->tcsr_mem + offset);
59da8fa4e3SBjoern A. Zeeb }
60da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_tcsr_read32(struct ath10k * ar,u32 offset)61da8fa4e3SBjoern A. Zeeb static u32 ath10k_ahb_tcsr_read32(struct ath10k *ar, u32 offset)
62da8fa4e3SBjoern A. Zeeb {
63da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
64da8fa4e3SBjoern A. Zeeb 
65da8fa4e3SBjoern A. Zeeb 	return ioread32(ar_ahb->tcsr_mem + offset);
66da8fa4e3SBjoern A. Zeeb }
67da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_soc_read32(struct ath10k * ar,u32 addr)68da8fa4e3SBjoern A. Zeeb static u32 ath10k_ahb_soc_read32(struct ath10k *ar, u32 addr)
69da8fa4e3SBjoern A. Zeeb {
70da8fa4e3SBjoern A. Zeeb 	return ath10k_ahb_read32(ar, RTC_SOC_BASE_ADDRESS + addr);
71da8fa4e3SBjoern A. Zeeb }
72da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_get_num_banks(struct ath10k * ar)73da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_get_num_banks(struct ath10k *ar)
74da8fa4e3SBjoern A. Zeeb {
75da8fa4e3SBjoern A. Zeeb 	if (ar->hw_rev == ATH10K_HW_QCA4019)
76da8fa4e3SBjoern A. Zeeb 		return 1;
77da8fa4e3SBjoern A. Zeeb 
78da8fa4e3SBjoern A. Zeeb 	ath10k_warn(ar, "unknown number of banks, assuming 1\n");
79da8fa4e3SBjoern A. Zeeb 	return 1;
80da8fa4e3SBjoern A. Zeeb }
81da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_clock_init(struct ath10k * ar)82da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_clock_init(struct ath10k *ar)
83da8fa4e3SBjoern A. Zeeb {
84da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
85da8fa4e3SBjoern A. Zeeb 	struct device *dev;
86da8fa4e3SBjoern A. Zeeb 
87da8fa4e3SBjoern A. Zeeb 	dev = &ar_ahb->pdev->dev;
88da8fa4e3SBjoern A. Zeeb 
89da8fa4e3SBjoern A. Zeeb 	ar_ahb->cmd_clk = devm_clk_get(dev, "wifi_wcss_cmd");
90da8fa4e3SBjoern A. Zeeb 	if (IS_ERR_OR_NULL(ar_ahb->cmd_clk)) {
91da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to get cmd clk: %ld\n",
92da8fa4e3SBjoern A. Zeeb 			   PTR_ERR(ar_ahb->cmd_clk));
93da8fa4e3SBjoern A. Zeeb 		return ar_ahb->cmd_clk ? PTR_ERR(ar_ahb->cmd_clk) : -ENODEV;
94da8fa4e3SBjoern A. Zeeb 	}
95da8fa4e3SBjoern A. Zeeb 
96da8fa4e3SBjoern A. Zeeb 	ar_ahb->ref_clk = devm_clk_get(dev, "wifi_wcss_ref");
97da8fa4e3SBjoern A. Zeeb 	if (IS_ERR_OR_NULL(ar_ahb->ref_clk)) {
98da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to get ref clk: %ld\n",
99da8fa4e3SBjoern A. Zeeb 			   PTR_ERR(ar_ahb->ref_clk));
100da8fa4e3SBjoern A. Zeeb 		return ar_ahb->ref_clk ? PTR_ERR(ar_ahb->ref_clk) : -ENODEV;
101da8fa4e3SBjoern A. Zeeb 	}
102da8fa4e3SBjoern A. Zeeb 
103da8fa4e3SBjoern A. Zeeb 	ar_ahb->rtc_clk = devm_clk_get(dev, "wifi_wcss_rtc");
104da8fa4e3SBjoern A. Zeeb 	if (IS_ERR_OR_NULL(ar_ahb->rtc_clk)) {
105da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to get rtc clk: %ld\n",
106da8fa4e3SBjoern A. Zeeb 			   PTR_ERR(ar_ahb->rtc_clk));
107da8fa4e3SBjoern A. Zeeb 		return ar_ahb->rtc_clk ? PTR_ERR(ar_ahb->rtc_clk) : -ENODEV;
108da8fa4e3SBjoern A. Zeeb 	}
109da8fa4e3SBjoern A. Zeeb 
110da8fa4e3SBjoern A. Zeeb 	return 0;
111da8fa4e3SBjoern A. Zeeb }
112da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_clock_deinit(struct ath10k * ar)113da8fa4e3SBjoern A. Zeeb static void ath10k_ahb_clock_deinit(struct ath10k *ar)
114da8fa4e3SBjoern A. Zeeb {
115da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
116da8fa4e3SBjoern A. Zeeb 
117da8fa4e3SBjoern A. Zeeb 	ar_ahb->cmd_clk = NULL;
118da8fa4e3SBjoern A. Zeeb 	ar_ahb->ref_clk = NULL;
119da8fa4e3SBjoern A. Zeeb 	ar_ahb->rtc_clk = NULL;
120da8fa4e3SBjoern A. Zeeb }
121da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_clock_enable(struct ath10k * ar)122da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_clock_enable(struct ath10k *ar)
123da8fa4e3SBjoern A. Zeeb {
124da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
125da8fa4e3SBjoern A. Zeeb 	int ret;
126da8fa4e3SBjoern A. Zeeb 
127da8fa4e3SBjoern A. Zeeb 	if (IS_ERR_OR_NULL(ar_ahb->cmd_clk) ||
128da8fa4e3SBjoern A. Zeeb 	    IS_ERR_OR_NULL(ar_ahb->ref_clk) ||
129da8fa4e3SBjoern A. Zeeb 	    IS_ERR_OR_NULL(ar_ahb->rtc_clk)) {
130da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "clock(s) is/are not initialized\n");
131da8fa4e3SBjoern A. Zeeb 		ret = -EIO;
132da8fa4e3SBjoern A. Zeeb 		goto out;
133da8fa4e3SBjoern A. Zeeb 	}
134da8fa4e3SBjoern A. Zeeb 
135da8fa4e3SBjoern A. Zeeb 	ret = clk_prepare_enable(ar_ahb->cmd_clk);
136da8fa4e3SBjoern A. Zeeb 	if (ret) {
137da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to enable cmd clk: %d\n", ret);
138da8fa4e3SBjoern A. Zeeb 		goto out;
139da8fa4e3SBjoern A. Zeeb 	}
140da8fa4e3SBjoern A. Zeeb 
141da8fa4e3SBjoern A. Zeeb 	ret = clk_prepare_enable(ar_ahb->ref_clk);
142da8fa4e3SBjoern A. Zeeb 	if (ret) {
143da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to enable ref clk: %d\n", ret);
144da8fa4e3SBjoern A. Zeeb 		goto err_cmd_clk_disable;
145da8fa4e3SBjoern A. Zeeb 	}
146da8fa4e3SBjoern A. Zeeb 
147da8fa4e3SBjoern A. Zeeb 	ret = clk_prepare_enable(ar_ahb->rtc_clk);
148da8fa4e3SBjoern A. Zeeb 	if (ret) {
149da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to enable rtc clk: %d\n", ret);
150da8fa4e3SBjoern A. Zeeb 		goto err_ref_clk_disable;
151da8fa4e3SBjoern A. Zeeb 	}
152da8fa4e3SBjoern A. Zeeb 
153da8fa4e3SBjoern A. Zeeb 	return 0;
154da8fa4e3SBjoern A. Zeeb 
155da8fa4e3SBjoern A. Zeeb err_ref_clk_disable:
156da8fa4e3SBjoern A. Zeeb 	clk_disable_unprepare(ar_ahb->ref_clk);
157da8fa4e3SBjoern A. Zeeb 
158da8fa4e3SBjoern A. Zeeb err_cmd_clk_disable:
159da8fa4e3SBjoern A. Zeeb 	clk_disable_unprepare(ar_ahb->cmd_clk);
160da8fa4e3SBjoern A. Zeeb 
161da8fa4e3SBjoern A. Zeeb out:
162da8fa4e3SBjoern A. Zeeb 	return ret;
163da8fa4e3SBjoern A. Zeeb }
164da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_clock_disable(struct ath10k * ar)165da8fa4e3SBjoern A. Zeeb static void ath10k_ahb_clock_disable(struct ath10k *ar)
166da8fa4e3SBjoern A. Zeeb {
167da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
168da8fa4e3SBjoern A. Zeeb 
169da8fa4e3SBjoern A. Zeeb 	clk_disable_unprepare(ar_ahb->cmd_clk);
170da8fa4e3SBjoern A. Zeeb 
171da8fa4e3SBjoern A. Zeeb 	clk_disable_unprepare(ar_ahb->ref_clk);
172da8fa4e3SBjoern A. Zeeb 
173da8fa4e3SBjoern A. Zeeb 	clk_disable_unprepare(ar_ahb->rtc_clk);
174da8fa4e3SBjoern A. Zeeb }
175da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_rst_ctrl_init(struct ath10k * ar)176da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_rst_ctrl_init(struct ath10k *ar)
177da8fa4e3SBjoern A. Zeeb {
178da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
179da8fa4e3SBjoern A. Zeeb 	struct device *dev;
180da8fa4e3SBjoern A. Zeeb 
181da8fa4e3SBjoern A. Zeeb 	dev = &ar_ahb->pdev->dev;
182da8fa4e3SBjoern A. Zeeb 
183da8fa4e3SBjoern A. Zeeb 	ar_ahb->core_cold_rst = devm_reset_control_get_exclusive(dev,
184da8fa4e3SBjoern A. Zeeb 								 "wifi_core_cold");
185da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(ar_ahb->core_cold_rst)) {
186da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to get core cold rst ctrl: %ld\n",
187da8fa4e3SBjoern A. Zeeb 			   PTR_ERR(ar_ahb->core_cold_rst));
188da8fa4e3SBjoern A. Zeeb 		return PTR_ERR(ar_ahb->core_cold_rst);
189da8fa4e3SBjoern A. Zeeb 	}
190da8fa4e3SBjoern A. Zeeb 
191da8fa4e3SBjoern A. Zeeb 	ar_ahb->radio_cold_rst = devm_reset_control_get_exclusive(dev,
192da8fa4e3SBjoern A. Zeeb 								  "wifi_radio_cold");
193da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(ar_ahb->radio_cold_rst)) {
194da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to get radio cold rst ctrl: %ld\n",
195da8fa4e3SBjoern A. Zeeb 			   PTR_ERR(ar_ahb->radio_cold_rst));
196da8fa4e3SBjoern A. Zeeb 		return PTR_ERR(ar_ahb->radio_cold_rst);
197da8fa4e3SBjoern A. Zeeb 	}
198da8fa4e3SBjoern A. Zeeb 
199da8fa4e3SBjoern A. Zeeb 	ar_ahb->radio_warm_rst = devm_reset_control_get_exclusive(dev,
200da8fa4e3SBjoern A. Zeeb 								  "wifi_radio_warm");
201da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(ar_ahb->radio_warm_rst)) {
202da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to get radio warm rst ctrl: %ld\n",
203da8fa4e3SBjoern A. Zeeb 			   PTR_ERR(ar_ahb->radio_warm_rst));
204da8fa4e3SBjoern A. Zeeb 		return PTR_ERR(ar_ahb->radio_warm_rst);
205da8fa4e3SBjoern A. Zeeb 	}
206da8fa4e3SBjoern A. Zeeb 
207da8fa4e3SBjoern A. Zeeb 	ar_ahb->radio_srif_rst = devm_reset_control_get_exclusive(dev,
208da8fa4e3SBjoern A. Zeeb 								  "wifi_radio_srif");
209da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(ar_ahb->radio_srif_rst)) {
210da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to get radio srif rst ctrl: %ld\n",
211da8fa4e3SBjoern A. Zeeb 			   PTR_ERR(ar_ahb->radio_srif_rst));
212da8fa4e3SBjoern A. Zeeb 		return PTR_ERR(ar_ahb->radio_srif_rst);
213da8fa4e3SBjoern A. Zeeb 	}
214da8fa4e3SBjoern A. Zeeb 
215da8fa4e3SBjoern A. Zeeb 	ar_ahb->cpu_init_rst = devm_reset_control_get_exclusive(dev,
216da8fa4e3SBjoern A. Zeeb 								"wifi_cpu_init");
217da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(ar_ahb->cpu_init_rst)) {
218da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to get cpu init rst ctrl: %ld\n",
219da8fa4e3SBjoern A. Zeeb 			   PTR_ERR(ar_ahb->cpu_init_rst));
220da8fa4e3SBjoern A. Zeeb 		return PTR_ERR(ar_ahb->cpu_init_rst);
221da8fa4e3SBjoern A. Zeeb 	}
222da8fa4e3SBjoern A. Zeeb 
223da8fa4e3SBjoern A. Zeeb 	return 0;
224da8fa4e3SBjoern A. Zeeb }
225da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_rst_ctrl_deinit(struct ath10k * ar)226da8fa4e3SBjoern A. Zeeb static void ath10k_ahb_rst_ctrl_deinit(struct ath10k *ar)
227da8fa4e3SBjoern A. Zeeb {
228da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
229da8fa4e3SBjoern A. Zeeb 
230da8fa4e3SBjoern A. Zeeb 	ar_ahb->core_cold_rst = NULL;
231da8fa4e3SBjoern A. Zeeb 	ar_ahb->radio_cold_rst = NULL;
232da8fa4e3SBjoern A. Zeeb 	ar_ahb->radio_warm_rst = NULL;
233da8fa4e3SBjoern A. Zeeb 	ar_ahb->radio_srif_rst = NULL;
234da8fa4e3SBjoern A. Zeeb 	ar_ahb->cpu_init_rst = NULL;
235da8fa4e3SBjoern A. Zeeb }
236da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_release_reset(struct ath10k * ar)237da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_release_reset(struct ath10k *ar)
238da8fa4e3SBjoern A. Zeeb {
239da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
240da8fa4e3SBjoern A. Zeeb 	int ret;
241da8fa4e3SBjoern A. Zeeb 
242da8fa4e3SBjoern A. Zeeb 	if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) ||
243da8fa4e3SBjoern A. Zeeb 	    IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) ||
244da8fa4e3SBjoern A. Zeeb 	    IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) ||
245da8fa4e3SBjoern A. Zeeb 	    IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) {
246da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "rst ctrl(s) is/are not initialized\n");
247da8fa4e3SBjoern A. Zeeb 		return -EINVAL;
248da8fa4e3SBjoern A. Zeeb 	}
249da8fa4e3SBjoern A. Zeeb 
250da8fa4e3SBjoern A. Zeeb 	ret = reset_control_deassert(ar_ahb->radio_cold_rst);
251da8fa4e3SBjoern A. Zeeb 	if (ret) {
252da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to deassert radio cold rst: %d\n", ret);
253da8fa4e3SBjoern A. Zeeb 		return ret;
254da8fa4e3SBjoern A. Zeeb 	}
255da8fa4e3SBjoern A. Zeeb 
256da8fa4e3SBjoern A. Zeeb 	ret = reset_control_deassert(ar_ahb->radio_warm_rst);
257da8fa4e3SBjoern A. Zeeb 	if (ret) {
258da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to deassert radio warm rst: %d\n", ret);
259da8fa4e3SBjoern A. Zeeb 		return ret;
260da8fa4e3SBjoern A. Zeeb 	}
261da8fa4e3SBjoern A. Zeeb 
262da8fa4e3SBjoern A. Zeeb 	ret = reset_control_deassert(ar_ahb->radio_srif_rst);
263da8fa4e3SBjoern A. Zeeb 	if (ret) {
264da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to deassert radio srif rst: %d\n", ret);
265da8fa4e3SBjoern A. Zeeb 		return ret;
266da8fa4e3SBjoern A. Zeeb 	}
267da8fa4e3SBjoern A. Zeeb 
268da8fa4e3SBjoern A. Zeeb 	ret = reset_control_deassert(ar_ahb->cpu_init_rst);
269da8fa4e3SBjoern A. Zeeb 	if (ret) {
270da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to deassert cpu init rst: %d\n", ret);
271da8fa4e3SBjoern A. Zeeb 		return ret;
272da8fa4e3SBjoern A. Zeeb 	}
273da8fa4e3SBjoern A. Zeeb 
274da8fa4e3SBjoern A. Zeeb 	return 0;
275da8fa4e3SBjoern A. Zeeb }
276da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_halt_axi_bus(struct ath10k * ar,u32 haltreq_reg,u32 haltack_reg)277da8fa4e3SBjoern A. Zeeb static void ath10k_ahb_halt_axi_bus(struct ath10k *ar, u32 haltreq_reg,
278da8fa4e3SBjoern A. Zeeb 				    u32 haltack_reg)
279da8fa4e3SBjoern A. Zeeb {
280da8fa4e3SBjoern A. Zeeb 	unsigned long timeout;
281da8fa4e3SBjoern A. Zeeb 	u32 val;
282da8fa4e3SBjoern A. Zeeb 
283da8fa4e3SBjoern A. Zeeb 	/* Issue halt axi bus request */
284da8fa4e3SBjoern A. Zeeb 	val = ath10k_ahb_tcsr_read32(ar, haltreq_reg);
285da8fa4e3SBjoern A. Zeeb 	val |= AHB_AXI_BUS_HALT_REQ;
286da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_tcsr_write32(ar, haltreq_reg, val);
287da8fa4e3SBjoern A. Zeeb 
288da8fa4e3SBjoern A. Zeeb 	/* Wait for axi bus halted ack */
289da8fa4e3SBjoern A. Zeeb 	timeout = jiffies + msecs_to_jiffies(ATH10K_AHB_AXI_BUS_HALT_TIMEOUT);
290da8fa4e3SBjoern A. Zeeb 	do {
291da8fa4e3SBjoern A. Zeeb 		val = ath10k_ahb_tcsr_read32(ar, haltack_reg);
292da8fa4e3SBjoern A. Zeeb 		if (val & AHB_AXI_BUS_HALT_ACK)
293da8fa4e3SBjoern A. Zeeb 			break;
294da8fa4e3SBjoern A. Zeeb 
295da8fa4e3SBjoern A. Zeeb 		mdelay(1);
296da8fa4e3SBjoern A. Zeeb 	} while (time_before(jiffies, timeout));
297da8fa4e3SBjoern A. Zeeb 
298da8fa4e3SBjoern A. Zeeb 	if (!(val & AHB_AXI_BUS_HALT_ACK)) {
299da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to halt axi bus: %d\n", val);
300da8fa4e3SBjoern A. Zeeb 		return;
301da8fa4e3SBjoern A. Zeeb 	}
302da8fa4e3SBjoern A. Zeeb 
303da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_AHB, "axi bus halted\n");
304da8fa4e3SBjoern A. Zeeb }
305da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_halt_chip(struct ath10k * ar)306da8fa4e3SBjoern A. Zeeb static void ath10k_ahb_halt_chip(struct ath10k *ar)
307da8fa4e3SBjoern A. Zeeb {
308da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
309da8fa4e3SBjoern A. Zeeb 	u32 core_id, glb_cfg_reg, haltreq_reg, haltack_reg;
310da8fa4e3SBjoern A. Zeeb 	u32 val;
311da8fa4e3SBjoern A. Zeeb 	int ret;
312da8fa4e3SBjoern A. Zeeb 
313da8fa4e3SBjoern A. Zeeb 	if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst) ||
314da8fa4e3SBjoern A. Zeeb 	    IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) ||
315da8fa4e3SBjoern A. Zeeb 	    IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) ||
316da8fa4e3SBjoern A. Zeeb 	    IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) ||
317da8fa4e3SBjoern A. Zeeb 	    IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) {
318da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "rst ctrl(s) is/are not initialized\n");
319da8fa4e3SBjoern A. Zeeb 		return;
320da8fa4e3SBjoern A. Zeeb 	}
321da8fa4e3SBjoern A. Zeeb 
322da8fa4e3SBjoern A. Zeeb 	core_id = ath10k_ahb_read32(ar, ATH10K_AHB_WLAN_CORE_ID_REG);
323da8fa4e3SBjoern A. Zeeb 
324da8fa4e3SBjoern A. Zeeb 	switch (core_id) {
325da8fa4e3SBjoern A. Zeeb 	case 0:
326da8fa4e3SBjoern A. Zeeb 		glb_cfg_reg = ATH10K_AHB_TCSR_WIFI0_GLB_CFG;
327da8fa4e3SBjoern A. Zeeb 		haltreq_reg = ATH10K_AHB_TCSR_WCSS0_HALTREQ;
328da8fa4e3SBjoern A. Zeeb 		haltack_reg = ATH10K_AHB_TCSR_WCSS0_HALTACK;
329da8fa4e3SBjoern A. Zeeb 		break;
330da8fa4e3SBjoern A. Zeeb 	case 1:
331da8fa4e3SBjoern A. Zeeb 		glb_cfg_reg = ATH10K_AHB_TCSR_WIFI1_GLB_CFG;
332da8fa4e3SBjoern A. Zeeb 		haltreq_reg = ATH10K_AHB_TCSR_WCSS1_HALTREQ;
333da8fa4e3SBjoern A. Zeeb 		haltack_reg = ATH10K_AHB_TCSR_WCSS1_HALTACK;
334da8fa4e3SBjoern A. Zeeb 		break;
335da8fa4e3SBjoern A. Zeeb 	default:
336da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "invalid core id %d found, skipping reset sequence\n",
337da8fa4e3SBjoern A. Zeeb 			   core_id);
338da8fa4e3SBjoern A. Zeeb 		return;
339da8fa4e3SBjoern A. Zeeb 	}
340da8fa4e3SBjoern A. Zeeb 
341da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_halt_axi_bus(ar, haltreq_reg, haltack_reg);
342da8fa4e3SBjoern A. Zeeb 
343da8fa4e3SBjoern A. Zeeb 	val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg);
344da8fa4e3SBjoern A. Zeeb 	val |= TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK;
345da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val);
346da8fa4e3SBjoern A. Zeeb 
347da8fa4e3SBjoern A. Zeeb 	ret = reset_control_assert(ar_ahb->core_cold_rst);
348da8fa4e3SBjoern A. Zeeb 	if (ret)
349da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to assert core cold rst: %d\n", ret);
350da8fa4e3SBjoern A. Zeeb 	msleep(1);
351da8fa4e3SBjoern A. Zeeb 
352da8fa4e3SBjoern A. Zeeb 	ret = reset_control_assert(ar_ahb->radio_cold_rst);
353da8fa4e3SBjoern A. Zeeb 	if (ret)
354da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to assert radio cold rst: %d\n", ret);
355da8fa4e3SBjoern A. Zeeb 	msleep(1);
356da8fa4e3SBjoern A. Zeeb 
357da8fa4e3SBjoern A. Zeeb 	ret = reset_control_assert(ar_ahb->radio_warm_rst);
358da8fa4e3SBjoern A. Zeeb 	if (ret)
359da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to assert radio warm rst: %d\n", ret);
360da8fa4e3SBjoern A. Zeeb 	msleep(1);
361da8fa4e3SBjoern A. Zeeb 
362da8fa4e3SBjoern A. Zeeb 	ret = reset_control_assert(ar_ahb->radio_srif_rst);
363da8fa4e3SBjoern A. Zeeb 	if (ret)
364da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to assert radio srif rst: %d\n", ret);
365da8fa4e3SBjoern A. Zeeb 	msleep(1);
366da8fa4e3SBjoern A. Zeeb 
367da8fa4e3SBjoern A. Zeeb 	ret = reset_control_assert(ar_ahb->cpu_init_rst);
368da8fa4e3SBjoern A. Zeeb 	if (ret)
369da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to assert cpu init rst: %d\n", ret);
370da8fa4e3SBjoern A. Zeeb 	msleep(10);
371da8fa4e3SBjoern A. Zeeb 
372da8fa4e3SBjoern A. Zeeb 	/* Clear halt req and core clock disable req before
373da8fa4e3SBjoern A. Zeeb 	 * deasserting wifi core reset.
374da8fa4e3SBjoern A. Zeeb 	 */
375da8fa4e3SBjoern A. Zeeb 	val = ath10k_ahb_tcsr_read32(ar, haltreq_reg);
376da8fa4e3SBjoern A. Zeeb 	val &= ~AHB_AXI_BUS_HALT_REQ;
377da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_tcsr_write32(ar, haltreq_reg, val);
378da8fa4e3SBjoern A. Zeeb 
379da8fa4e3SBjoern A. Zeeb 	val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg);
380da8fa4e3SBjoern A. Zeeb 	val &= ~TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK;
381da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val);
382da8fa4e3SBjoern A. Zeeb 
383da8fa4e3SBjoern A. Zeeb 	ret = reset_control_deassert(ar_ahb->core_cold_rst);
384da8fa4e3SBjoern A. Zeeb 	if (ret)
385da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to deassert core cold rst: %d\n", ret);
386da8fa4e3SBjoern A. Zeeb 
387da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_AHB, "core %d reset done\n", core_id);
388da8fa4e3SBjoern A. Zeeb }
389da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_interrupt_handler(int irq,void * arg)390da8fa4e3SBjoern A. Zeeb static irqreturn_t ath10k_ahb_interrupt_handler(int irq, void *arg)
391da8fa4e3SBjoern A. Zeeb {
392da8fa4e3SBjoern A. Zeeb 	struct ath10k *ar = arg;
393da8fa4e3SBjoern A. Zeeb 
394da8fa4e3SBjoern A. Zeeb 	if (!ath10k_pci_irq_pending(ar))
395da8fa4e3SBjoern A. Zeeb 		return IRQ_NONE;
396da8fa4e3SBjoern A. Zeeb 
397da8fa4e3SBjoern A. Zeeb 	ath10k_pci_disable_and_clear_legacy_irq(ar);
398da8fa4e3SBjoern A. Zeeb 	ath10k_pci_irq_msi_fw_mask(ar);
399da8fa4e3SBjoern A. Zeeb 	napi_schedule(&ar->napi);
400da8fa4e3SBjoern A. Zeeb 
401da8fa4e3SBjoern A. Zeeb 	return IRQ_HANDLED;
402da8fa4e3SBjoern A. Zeeb }
403da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_request_irq_legacy(struct ath10k * ar)404da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_request_irq_legacy(struct ath10k *ar)
405da8fa4e3SBjoern A. Zeeb {
406da8fa4e3SBjoern A. Zeeb 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
407da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
408da8fa4e3SBjoern A. Zeeb 	int ret;
409da8fa4e3SBjoern A. Zeeb 
410da8fa4e3SBjoern A. Zeeb 	ret = request_irq(ar_ahb->irq,
411da8fa4e3SBjoern A. Zeeb 			  ath10k_ahb_interrupt_handler,
412da8fa4e3SBjoern A. Zeeb 			  IRQF_SHARED, "ath10k_ahb", ar);
413da8fa4e3SBjoern A. Zeeb 	if (ret) {
414da8fa4e3SBjoern A. Zeeb 		ath10k_warn(ar, "failed to request legacy irq %d: %d\n",
415da8fa4e3SBjoern A. Zeeb 			    ar_ahb->irq, ret);
416da8fa4e3SBjoern A. Zeeb 		return ret;
417da8fa4e3SBjoern A. Zeeb 	}
418da8fa4e3SBjoern A. Zeeb 	ar_pci->oper_irq_mode = ATH10K_PCI_IRQ_LEGACY;
419da8fa4e3SBjoern A. Zeeb 
420da8fa4e3SBjoern A. Zeeb 	return 0;
421da8fa4e3SBjoern A. Zeeb }
422da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_release_irq_legacy(struct ath10k * ar)423da8fa4e3SBjoern A. Zeeb static void ath10k_ahb_release_irq_legacy(struct ath10k *ar)
424da8fa4e3SBjoern A. Zeeb {
425da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
426da8fa4e3SBjoern A. Zeeb 
427da8fa4e3SBjoern A. Zeeb 	free_irq(ar_ahb->irq, ar);
428da8fa4e3SBjoern A. Zeeb }
429da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_irq_disable(struct ath10k * ar)430da8fa4e3SBjoern A. Zeeb static void ath10k_ahb_irq_disable(struct ath10k *ar)
431da8fa4e3SBjoern A. Zeeb {
432da8fa4e3SBjoern A. Zeeb 	ath10k_ce_disable_interrupts(ar);
433da8fa4e3SBjoern A. Zeeb 	ath10k_pci_disable_and_clear_legacy_irq(ar);
434da8fa4e3SBjoern A. Zeeb }
435da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_resource_init(struct ath10k * ar)436da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_resource_init(struct ath10k *ar)
437da8fa4e3SBjoern A. Zeeb {
438da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
439da8fa4e3SBjoern A. Zeeb 	struct platform_device *pdev;
440da8fa4e3SBjoern A. Zeeb 	struct resource *res;
441da8fa4e3SBjoern A. Zeeb 	int ret;
442da8fa4e3SBjoern A. Zeeb 
443da8fa4e3SBjoern A. Zeeb 	pdev = ar_ahb->pdev;
444da8fa4e3SBjoern A. Zeeb 
445da8fa4e3SBjoern A. Zeeb 	ar_ahb->mem = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
446da8fa4e3SBjoern A. Zeeb 	if (IS_ERR(ar_ahb->mem)) {
447da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "mem ioremap error\n");
448da8fa4e3SBjoern A. Zeeb 		ret = PTR_ERR(ar_ahb->mem);
449da8fa4e3SBjoern A. Zeeb 		goto out;
450da8fa4e3SBjoern A. Zeeb 	}
451da8fa4e3SBjoern A. Zeeb 
452da8fa4e3SBjoern A. Zeeb 	ar_ahb->mem_len = resource_size(res);
453da8fa4e3SBjoern A. Zeeb 
454da8fa4e3SBjoern A. Zeeb 	ar_ahb->gcc_mem = ioremap(ATH10K_GCC_REG_BASE,
455da8fa4e3SBjoern A. Zeeb 				  ATH10K_GCC_REG_SIZE);
456da8fa4e3SBjoern A. Zeeb 	if (!ar_ahb->gcc_mem) {
457da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "gcc mem ioremap error\n");
458da8fa4e3SBjoern A. Zeeb 		ret = -ENOMEM;
459da8fa4e3SBjoern A. Zeeb 		goto err_mem_unmap;
460da8fa4e3SBjoern A. Zeeb 	}
461da8fa4e3SBjoern A. Zeeb 
462da8fa4e3SBjoern A. Zeeb 	ar_ahb->tcsr_mem = ioremap(ATH10K_TCSR_REG_BASE,
463da8fa4e3SBjoern A. Zeeb 				   ATH10K_TCSR_REG_SIZE);
464da8fa4e3SBjoern A. Zeeb 	if (!ar_ahb->tcsr_mem) {
465da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "tcsr mem ioremap error\n");
466da8fa4e3SBjoern A. Zeeb 		ret = -ENOMEM;
467da8fa4e3SBjoern A. Zeeb 		goto err_gcc_mem_unmap;
468da8fa4e3SBjoern A. Zeeb 	}
469da8fa4e3SBjoern A. Zeeb 
470da8fa4e3SBjoern A. Zeeb 	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
471da8fa4e3SBjoern A. Zeeb 	if (ret) {
472da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to set 32-bit dma mask: %d\n", ret);
473da8fa4e3SBjoern A. Zeeb 		goto err_tcsr_mem_unmap;
474da8fa4e3SBjoern A. Zeeb 	}
475da8fa4e3SBjoern A. Zeeb 
476da8fa4e3SBjoern A. Zeeb 	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
477da8fa4e3SBjoern A. Zeeb 	if (ret) {
478da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to set 32-bit consistent dma: %d\n",
479da8fa4e3SBjoern A. Zeeb 			   ret);
480da8fa4e3SBjoern A. Zeeb 		goto err_tcsr_mem_unmap;
481da8fa4e3SBjoern A. Zeeb 	}
482da8fa4e3SBjoern A. Zeeb 
483da8fa4e3SBjoern A. Zeeb 	ret = ath10k_ahb_clock_init(ar);
484da8fa4e3SBjoern A. Zeeb 	if (ret)
485da8fa4e3SBjoern A. Zeeb 		goto err_tcsr_mem_unmap;
486da8fa4e3SBjoern A. Zeeb 
487da8fa4e3SBjoern A. Zeeb 	ret = ath10k_ahb_rst_ctrl_init(ar);
488da8fa4e3SBjoern A. Zeeb 	if (ret)
489da8fa4e3SBjoern A. Zeeb 		goto err_clock_deinit;
490da8fa4e3SBjoern A. Zeeb 
491da8fa4e3SBjoern A. Zeeb 	ar_ahb->irq = platform_get_irq_byname(pdev, "legacy");
492da8fa4e3SBjoern A. Zeeb 	if (ar_ahb->irq < 0) {
493da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to get irq number: %d\n", ar_ahb->irq);
494da8fa4e3SBjoern A. Zeeb 		ret = ar_ahb->irq;
495da8fa4e3SBjoern A. Zeeb 		goto err_clock_deinit;
496da8fa4e3SBjoern A. Zeeb 	}
497da8fa4e3SBjoern A. Zeeb 
498da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "irq: %d\n", ar_ahb->irq);
499da8fa4e3SBjoern A. Zeeb 
500da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "mem: 0x%pK mem_len: %lu gcc mem: 0x%pK tcsr_mem: 0x%pK\n",
501da8fa4e3SBjoern A. Zeeb 		   ar_ahb->mem, ar_ahb->mem_len,
502da8fa4e3SBjoern A. Zeeb 		   ar_ahb->gcc_mem, ar_ahb->tcsr_mem);
503da8fa4e3SBjoern A. Zeeb 	return 0;
504da8fa4e3SBjoern A. Zeeb 
505da8fa4e3SBjoern A. Zeeb err_clock_deinit:
506da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_clock_deinit(ar);
507da8fa4e3SBjoern A. Zeeb 
508da8fa4e3SBjoern A. Zeeb err_tcsr_mem_unmap:
509da8fa4e3SBjoern A. Zeeb 	iounmap(ar_ahb->tcsr_mem);
510da8fa4e3SBjoern A. Zeeb 
511da8fa4e3SBjoern A. Zeeb err_gcc_mem_unmap:
512da8fa4e3SBjoern A. Zeeb 	ar_ahb->tcsr_mem = NULL;
513da8fa4e3SBjoern A. Zeeb 	iounmap(ar_ahb->gcc_mem);
514da8fa4e3SBjoern A. Zeeb 
515da8fa4e3SBjoern A. Zeeb err_mem_unmap:
516da8fa4e3SBjoern A. Zeeb 	ar_ahb->gcc_mem = NULL;
517da8fa4e3SBjoern A. Zeeb 	devm_iounmap(&pdev->dev, ar_ahb->mem);
518da8fa4e3SBjoern A. Zeeb 
519da8fa4e3SBjoern A. Zeeb out:
520da8fa4e3SBjoern A. Zeeb 	ar_ahb->mem = NULL;
521da8fa4e3SBjoern A. Zeeb 	return ret;
522da8fa4e3SBjoern A. Zeeb }
523da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_resource_deinit(struct ath10k * ar)524da8fa4e3SBjoern A. Zeeb static void ath10k_ahb_resource_deinit(struct ath10k *ar)
525da8fa4e3SBjoern A. Zeeb {
526da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
527da8fa4e3SBjoern A. Zeeb 	struct device *dev;
528da8fa4e3SBjoern A. Zeeb 
529da8fa4e3SBjoern A. Zeeb 	dev = &ar_ahb->pdev->dev;
530da8fa4e3SBjoern A. Zeeb 
531da8fa4e3SBjoern A. Zeeb 	if (ar_ahb->mem)
532da8fa4e3SBjoern A. Zeeb 		devm_iounmap(dev, ar_ahb->mem);
533da8fa4e3SBjoern A. Zeeb 
534da8fa4e3SBjoern A. Zeeb 	if (ar_ahb->gcc_mem)
535da8fa4e3SBjoern A. Zeeb 		iounmap(ar_ahb->gcc_mem);
536da8fa4e3SBjoern A. Zeeb 
537da8fa4e3SBjoern A. Zeeb 	if (ar_ahb->tcsr_mem)
538da8fa4e3SBjoern A. Zeeb 		iounmap(ar_ahb->tcsr_mem);
539da8fa4e3SBjoern A. Zeeb 
540da8fa4e3SBjoern A. Zeeb 	ar_ahb->mem = NULL;
541da8fa4e3SBjoern A. Zeeb 	ar_ahb->gcc_mem = NULL;
542da8fa4e3SBjoern A. Zeeb 	ar_ahb->tcsr_mem = NULL;
543da8fa4e3SBjoern A. Zeeb 
544da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_clock_deinit(ar);
545da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_rst_ctrl_deinit(ar);
546da8fa4e3SBjoern A. Zeeb }
547da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_prepare_device(struct ath10k * ar)548da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_prepare_device(struct ath10k *ar)
549da8fa4e3SBjoern A. Zeeb {
550da8fa4e3SBjoern A. Zeeb 	u32 val;
551da8fa4e3SBjoern A. Zeeb 	int ret;
552da8fa4e3SBjoern A. Zeeb 
553da8fa4e3SBjoern A. Zeeb 	ret = ath10k_ahb_clock_enable(ar);
554da8fa4e3SBjoern A. Zeeb 	if (ret) {
555da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to enable clocks\n");
556da8fa4e3SBjoern A. Zeeb 		return ret;
557da8fa4e3SBjoern A. Zeeb 	}
558da8fa4e3SBjoern A. Zeeb 
559da8fa4e3SBjoern A. Zeeb 	/* Clock for the target is supplied from outside of target (ie,
560da8fa4e3SBjoern A. Zeeb 	 * external clock module controlled by the host). Target needs
561da8fa4e3SBjoern A. Zeeb 	 * to know what frequency target cpu is configured which is needed
562da8fa4e3SBjoern A. Zeeb 	 * for target internal use. Read target cpu frequency info from
563da8fa4e3SBjoern A. Zeeb 	 * gcc register and write into target's scratch register where
564da8fa4e3SBjoern A. Zeeb 	 * target expects this information.
565da8fa4e3SBjoern A. Zeeb 	 */
566da8fa4e3SBjoern A. Zeeb 	val = ath10k_ahb_gcc_read32(ar, ATH10K_AHB_GCC_FEPLL_PLL_DIV);
567da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_write32(ar, ATH10K_AHB_WIFI_SCRATCH_5_REG, val);
568da8fa4e3SBjoern A. Zeeb 
569da8fa4e3SBjoern A. Zeeb 	ret = ath10k_ahb_release_reset(ar);
570da8fa4e3SBjoern A. Zeeb 	if (ret)
571da8fa4e3SBjoern A. Zeeb 		goto err_clk_disable;
572da8fa4e3SBjoern A. Zeeb 
573da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_irq_disable(ar);
574da8fa4e3SBjoern A. Zeeb 
575da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_write32(ar, FW_INDICATOR_ADDRESS, FW_IND_HOST_READY);
576da8fa4e3SBjoern A. Zeeb 
577da8fa4e3SBjoern A. Zeeb 	ret = ath10k_pci_wait_for_target_init(ar);
578da8fa4e3SBjoern A. Zeeb 	if (ret)
579da8fa4e3SBjoern A. Zeeb 		goto err_halt_chip;
580da8fa4e3SBjoern A. Zeeb 
581da8fa4e3SBjoern A. Zeeb 	return 0;
582da8fa4e3SBjoern A. Zeeb 
583da8fa4e3SBjoern A. Zeeb err_halt_chip:
584da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_halt_chip(ar);
585da8fa4e3SBjoern A. Zeeb 
586da8fa4e3SBjoern A. Zeeb err_clk_disable:
587da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_clock_disable(ar);
588da8fa4e3SBjoern A. Zeeb 
589da8fa4e3SBjoern A. Zeeb 	return ret;
590da8fa4e3SBjoern A. Zeeb }
591da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_chip_reset(struct ath10k * ar)592da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_chip_reset(struct ath10k *ar)
593da8fa4e3SBjoern A. Zeeb {
594da8fa4e3SBjoern A. Zeeb 	int ret;
595da8fa4e3SBjoern A. Zeeb 
596da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_halt_chip(ar);
597da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_clock_disable(ar);
598da8fa4e3SBjoern A. Zeeb 
599da8fa4e3SBjoern A. Zeeb 	ret = ath10k_ahb_prepare_device(ar);
600da8fa4e3SBjoern A. Zeeb 	if (ret)
601da8fa4e3SBjoern A. Zeeb 		return ret;
602da8fa4e3SBjoern A. Zeeb 
603da8fa4e3SBjoern A. Zeeb 	return 0;
604da8fa4e3SBjoern A. Zeeb }
605da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_wake_target_cpu(struct ath10k * ar)606da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_wake_target_cpu(struct ath10k *ar)
607da8fa4e3SBjoern A. Zeeb {
608da8fa4e3SBjoern A. Zeeb 	u32 addr, val;
609da8fa4e3SBjoern A. Zeeb 
610da8fa4e3SBjoern A. Zeeb 	addr = SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS;
611da8fa4e3SBjoern A. Zeeb 	val = ath10k_ahb_read32(ar, addr);
612da8fa4e3SBjoern A. Zeeb 	val |= ATH10K_AHB_CORE_CTRL_CPU_INTR_MASK;
613da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_write32(ar, addr, val);
614da8fa4e3SBjoern A. Zeeb 
615da8fa4e3SBjoern A. Zeeb 	return 0;
616da8fa4e3SBjoern A. Zeeb }
617da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_hif_start(struct ath10k * ar)618da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_hif_start(struct ath10k *ar)
619da8fa4e3SBjoern A. Zeeb {
620da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif start\n");
621da8fa4e3SBjoern A. Zeeb 
622da8fa4e3SBjoern A. Zeeb 	ath10k_core_napi_enable(ar);
623da8fa4e3SBjoern A. Zeeb 	ath10k_ce_enable_interrupts(ar);
624da8fa4e3SBjoern A. Zeeb 	ath10k_pci_enable_legacy_irq(ar);
625da8fa4e3SBjoern A. Zeeb 
626da8fa4e3SBjoern A. Zeeb 	ath10k_pci_rx_post(ar);
627da8fa4e3SBjoern A. Zeeb 
628da8fa4e3SBjoern A. Zeeb 	return 0;
629da8fa4e3SBjoern A. Zeeb }
630da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_hif_stop(struct ath10k * ar)631da8fa4e3SBjoern A. Zeeb static void ath10k_ahb_hif_stop(struct ath10k *ar)
632da8fa4e3SBjoern A. Zeeb {
633da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
634da8fa4e3SBjoern A. Zeeb 
635da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif stop\n");
636da8fa4e3SBjoern A. Zeeb 
637da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_irq_disable(ar);
638da8fa4e3SBjoern A. Zeeb 	synchronize_irq(ar_ahb->irq);
639da8fa4e3SBjoern A. Zeeb 
640da8fa4e3SBjoern A. Zeeb 	ath10k_core_napi_sync_disable(ar);
641da8fa4e3SBjoern A. Zeeb 
642da8fa4e3SBjoern A. Zeeb 	ath10k_pci_flush(ar);
643da8fa4e3SBjoern A. Zeeb }
644da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_hif_power_up(struct ath10k * ar,enum ath10k_firmware_mode fw_mode)645da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_hif_power_up(struct ath10k *ar,
646da8fa4e3SBjoern A. Zeeb 				   enum ath10k_firmware_mode fw_mode)
647da8fa4e3SBjoern A. Zeeb {
648da8fa4e3SBjoern A. Zeeb 	int ret;
649da8fa4e3SBjoern A. Zeeb 
650da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif power up\n");
651da8fa4e3SBjoern A. Zeeb 
652da8fa4e3SBjoern A. Zeeb 	ret = ath10k_ahb_chip_reset(ar);
653da8fa4e3SBjoern A. Zeeb 	if (ret) {
654da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to reset chip: %d\n", ret);
655da8fa4e3SBjoern A. Zeeb 		goto out;
656da8fa4e3SBjoern A. Zeeb 	}
657da8fa4e3SBjoern A. Zeeb 
658da8fa4e3SBjoern A. Zeeb 	ret = ath10k_pci_init_pipes(ar);
659da8fa4e3SBjoern A. Zeeb 	if (ret) {
660da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to initialize CE: %d\n", ret);
661da8fa4e3SBjoern A. Zeeb 		goto out;
662da8fa4e3SBjoern A. Zeeb 	}
663da8fa4e3SBjoern A. Zeeb 
664da8fa4e3SBjoern A. Zeeb 	ret = ath10k_pci_init_config(ar);
665da8fa4e3SBjoern A. Zeeb 	if (ret) {
666da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to setup init config: %d\n", ret);
667da8fa4e3SBjoern A. Zeeb 		goto err_ce_deinit;
668da8fa4e3SBjoern A. Zeeb 	}
669da8fa4e3SBjoern A. Zeeb 
670da8fa4e3SBjoern A. Zeeb 	ret = ath10k_ahb_wake_target_cpu(ar);
671da8fa4e3SBjoern A. Zeeb 	if (ret) {
672da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "could not wake up target CPU: %d\n", ret);
673da8fa4e3SBjoern A. Zeeb 		goto err_ce_deinit;
674da8fa4e3SBjoern A. Zeeb 	}
675da8fa4e3SBjoern A. Zeeb 
676da8fa4e3SBjoern A. Zeeb 	return 0;
677da8fa4e3SBjoern A. Zeeb 
678da8fa4e3SBjoern A. Zeeb err_ce_deinit:
679da8fa4e3SBjoern A. Zeeb 	ath10k_pci_ce_deinit(ar);
680da8fa4e3SBjoern A. Zeeb out:
681da8fa4e3SBjoern A. Zeeb 	return ret;
682da8fa4e3SBjoern A. Zeeb }
683da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_qca4019_targ_cpu_to_ce_addr(struct ath10k * ar,u32 addr)684da8fa4e3SBjoern A. Zeeb static u32 ath10k_ahb_qca4019_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
685da8fa4e3SBjoern A. Zeeb {
686da8fa4e3SBjoern A. Zeeb 	u32 val = 0, region = addr & 0xfffff;
687da8fa4e3SBjoern A. Zeeb 
688da8fa4e3SBjoern A. Zeeb 	val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS);
689da8fa4e3SBjoern A. Zeeb 
690da8fa4e3SBjoern A. Zeeb 	if (region >= QCA4019_SRAM_ADDR && region <=
691da8fa4e3SBjoern A. Zeeb 	    (QCA4019_SRAM_ADDR + QCA4019_SRAM_LEN)) {
692da8fa4e3SBjoern A. Zeeb 		/* SRAM contents for QCA4019 can be directly accessed and
693da8fa4e3SBjoern A. Zeeb 		 * no conversions are required
694da8fa4e3SBjoern A. Zeeb 		 */
695da8fa4e3SBjoern A. Zeeb 		val |= region;
696da8fa4e3SBjoern A. Zeeb 	} else {
697da8fa4e3SBjoern A. Zeeb 		val |= 0x100000 | region;
698da8fa4e3SBjoern A. Zeeb 	}
699da8fa4e3SBjoern A. Zeeb 
700da8fa4e3SBjoern A. Zeeb 	return val;
701da8fa4e3SBjoern A. Zeeb }
702da8fa4e3SBjoern A. Zeeb 
703da8fa4e3SBjoern A. Zeeb static const struct ath10k_hif_ops ath10k_ahb_hif_ops = {
704da8fa4e3SBjoern A. Zeeb 	.tx_sg                  = ath10k_pci_hif_tx_sg,
705da8fa4e3SBjoern A. Zeeb 	.diag_read              = ath10k_pci_hif_diag_read,
706da8fa4e3SBjoern A. Zeeb 	.diag_write             = ath10k_pci_diag_write_mem,
707da8fa4e3SBjoern A. Zeeb 	.exchange_bmi_msg       = ath10k_pci_hif_exchange_bmi_msg,
708da8fa4e3SBjoern A. Zeeb 	.start                  = ath10k_ahb_hif_start,
709da8fa4e3SBjoern A. Zeeb 	.stop                   = ath10k_ahb_hif_stop,
710da8fa4e3SBjoern A. Zeeb 	.map_service_to_pipe    = ath10k_pci_hif_map_service_to_pipe,
711da8fa4e3SBjoern A. Zeeb 	.get_default_pipe       = ath10k_pci_hif_get_default_pipe,
712da8fa4e3SBjoern A. Zeeb 	.send_complete_check    = ath10k_pci_hif_send_complete_check,
713da8fa4e3SBjoern A. Zeeb 	.get_free_queue_number  = ath10k_pci_hif_get_free_queue_number,
714da8fa4e3SBjoern A. Zeeb 	.power_up               = ath10k_ahb_hif_power_up,
715da8fa4e3SBjoern A. Zeeb 	.power_down             = ath10k_pci_hif_power_down,
716da8fa4e3SBjoern A. Zeeb 	.read32                 = ath10k_ahb_read32,
717da8fa4e3SBjoern A. Zeeb 	.write32                = ath10k_ahb_write32,
718da8fa4e3SBjoern A. Zeeb };
719da8fa4e3SBjoern A. Zeeb 
720da8fa4e3SBjoern A. Zeeb static const struct ath10k_bus_ops ath10k_ahb_bus_ops = {
721da8fa4e3SBjoern A. Zeeb 	.read32		= ath10k_ahb_read32,
722da8fa4e3SBjoern A. Zeeb 	.write32	= ath10k_ahb_write32,
723da8fa4e3SBjoern A. Zeeb 	.get_num_banks	= ath10k_ahb_get_num_banks,
724da8fa4e3SBjoern A. Zeeb };
725da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_probe(struct platform_device * pdev)726da8fa4e3SBjoern A. Zeeb static int ath10k_ahb_probe(struct platform_device *pdev)
727da8fa4e3SBjoern A. Zeeb {
728da8fa4e3SBjoern A. Zeeb 	struct ath10k *ar;
729da8fa4e3SBjoern A. Zeeb 	struct ath10k_ahb *ar_ahb;
730da8fa4e3SBjoern A. Zeeb 	struct ath10k_pci *ar_pci;
731da8fa4e3SBjoern A. Zeeb 	enum ath10k_hw_rev hw_rev;
732da8fa4e3SBjoern A. Zeeb 	size_t size;
733da8fa4e3SBjoern A. Zeeb 	int ret;
734da8fa4e3SBjoern A. Zeeb 	struct ath10k_bus_params bus_params = {};
735da8fa4e3SBjoern A. Zeeb 
736*07724ba6SBjoern A. Zeeb 	hw_rev = (enum ath10k_hw_rev)of_device_get_match_data(&pdev->dev);
737*07724ba6SBjoern A. Zeeb 	if (!hw_rev) {
738*07724ba6SBjoern A. Zeeb 		dev_err(&pdev->dev, "OF data missing\n");
739da8fa4e3SBjoern A. Zeeb 		return -EINVAL;
740da8fa4e3SBjoern A. Zeeb 	}
741da8fa4e3SBjoern A. Zeeb 
742da8fa4e3SBjoern A. Zeeb 	size = sizeof(*ar_pci) + sizeof(*ar_ahb);
743da8fa4e3SBjoern A. Zeeb 	ar = ath10k_core_create(size, &pdev->dev, ATH10K_BUS_AHB,
744da8fa4e3SBjoern A. Zeeb 				hw_rev, &ath10k_ahb_hif_ops);
745da8fa4e3SBjoern A. Zeeb 	if (!ar) {
746da8fa4e3SBjoern A. Zeeb 		dev_err(&pdev->dev, "failed to allocate core\n");
747da8fa4e3SBjoern A. Zeeb 		return -ENOMEM;
748da8fa4e3SBjoern A. Zeeb 	}
749da8fa4e3SBjoern A. Zeeb 
750da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_BOOT, "ahb probe\n");
751da8fa4e3SBjoern A. Zeeb 
752da8fa4e3SBjoern A. Zeeb 	ar_pci = ath10k_pci_priv(ar);
753da8fa4e3SBjoern A. Zeeb 	ar_ahb = ath10k_ahb_priv(ar);
754da8fa4e3SBjoern A. Zeeb 
755da8fa4e3SBjoern A. Zeeb 	ar_ahb->pdev = pdev;
756da8fa4e3SBjoern A. Zeeb 	platform_set_drvdata(pdev, ar);
757da8fa4e3SBjoern A. Zeeb 
758da8fa4e3SBjoern A. Zeeb 	ret = ath10k_ahb_resource_init(ar);
759da8fa4e3SBjoern A. Zeeb 	if (ret)
760da8fa4e3SBjoern A. Zeeb 		goto err_core_destroy;
761da8fa4e3SBjoern A. Zeeb 
762da8fa4e3SBjoern A. Zeeb 	ar->dev_id = 0;
763da8fa4e3SBjoern A. Zeeb 	ar_pci->mem = ar_ahb->mem;
764da8fa4e3SBjoern A. Zeeb 	ar_pci->mem_len = ar_ahb->mem_len;
765da8fa4e3SBjoern A. Zeeb 	ar_pci->ar = ar;
766da8fa4e3SBjoern A. Zeeb 	ar_pci->ce.bus_ops = &ath10k_ahb_bus_ops;
767da8fa4e3SBjoern A. Zeeb 	ar_pci->targ_cpu_to_ce_addr = ath10k_ahb_qca4019_targ_cpu_to_ce_addr;
768da8fa4e3SBjoern A. Zeeb 	ar->ce_priv = &ar_pci->ce;
769da8fa4e3SBjoern A. Zeeb 
770da8fa4e3SBjoern A. Zeeb 	ret = ath10k_pci_setup_resource(ar);
771da8fa4e3SBjoern A. Zeeb 	if (ret) {
772da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to setup resource: %d\n", ret);
773da8fa4e3SBjoern A. Zeeb 		goto err_resource_deinit;
774da8fa4e3SBjoern A. Zeeb 	}
775da8fa4e3SBjoern A. Zeeb 
776da8fa4e3SBjoern A. Zeeb 	ath10k_pci_init_napi(ar);
777da8fa4e3SBjoern A. Zeeb 
778da8fa4e3SBjoern A. Zeeb 	ret = ath10k_ahb_request_irq_legacy(ar);
779da8fa4e3SBjoern A. Zeeb 	if (ret)
780da8fa4e3SBjoern A. Zeeb 		goto err_free_pipes;
781da8fa4e3SBjoern A. Zeeb 
782da8fa4e3SBjoern A. Zeeb 	ret = ath10k_ahb_prepare_device(ar);
783da8fa4e3SBjoern A. Zeeb 	if (ret)
784da8fa4e3SBjoern A. Zeeb 		goto err_free_irq;
785da8fa4e3SBjoern A. Zeeb 
786da8fa4e3SBjoern A. Zeeb 	ath10k_pci_ce_deinit(ar);
787da8fa4e3SBjoern A. Zeeb 
788da8fa4e3SBjoern A. Zeeb 	bus_params.dev_type = ATH10K_DEV_TYPE_LL;
789da8fa4e3SBjoern A. Zeeb 	bus_params.chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
790da8fa4e3SBjoern A. Zeeb 	if (bus_params.chip_id == 0xffffffff) {
791da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to get chip id\n");
792da8fa4e3SBjoern A. Zeeb 		ret = -ENODEV;
793da8fa4e3SBjoern A. Zeeb 		goto err_halt_device;
794da8fa4e3SBjoern A. Zeeb 	}
795da8fa4e3SBjoern A. Zeeb 
796da8fa4e3SBjoern A. Zeeb 	ret = ath10k_core_register(ar, &bus_params);
797da8fa4e3SBjoern A. Zeeb 	if (ret) {
798da8fa4e3SBjoern A. Zeeb 		ath10k_err(ar, "failed to register driver core: %d\n", ret);
799da8fa4e3SBjoern A. Zeeb 		goto err_halt_device;
800da8fa4e3SBjoern A. Zeeb 	}
801da8fa4e3SBjoern A. Zeeb 
802da8fa4e3SBjoern A. Zeeb 	return 0;
803da8fa4e3SBjoern A. Zeeb 
804da8fa4e3SBjoern A. Zeeb err_halt_device:
805da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_halt_chip(ar);
806da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_clock_disable(ar);
807da8fa4e3SBjoern A. Zeeb 
808da8fa4e3SBjoern A. Zeeb err_free_irq:
809da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_release_irq_legacy(ar);
810da8fa4e3SBjoern A. Zeeb 
811da8fa4e3SBjoern A. Zeeb err_free_pipes:
812da8fa4e3SBjoern A. Zeeb 	ath10k_pci_release_resource(ar);
813da8fa4e3SBjoern A. Zeeb 
814da8fa4e3SBjoern A. Zeeb err_resource_deinit:
815da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_resource_deinit(ar);
816da8fa4e3SBjoern A. Zeeb 
817da8fa4e3SBjoern A. Zeeb err_core_destroy:
818da8fa4e3SBjoern A. Zeeb 	ath10k_core_destroy(ar);
819da8fa4e3SBjoern A. Zeeb 
820da8fa4e3SBjoern A. Zeeb 	return ret;
821da8fa4e3SBjoern A. Zeeb }
822da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_remove(struct platform_device * pdev)823*07724ba6SBjoern A. Zeeb static void ath10k_ahb_remove(struct platform_device *pdev)
824da8fa4e3SBjoern A. Zeeb {
825da8fa4e3SBjoern A. Zeeb 	struct ath10k *ar = platform_get_drvdata(pdev);
826da8fa4e3SBjoern A. Zeeb 
827da8fa4e3SBjoern A. Zeeb 	ath10k_dbg(ar, ATH10K_DBG_AHB, "ahb remove\n");
828da8fa4e3SBjoern A. Zeeb 
829da8fa4e3SBjoern A. Zeeb 	ath10k_core_unregister(ar);
830da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_irq_disable(ar);
831da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_release_irq_legacy(ar);
832da8fa4e3SBjoern A. Zeeb 	ath10k_pci_release_resource(ar);
833da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_halt_chip(ar);
834da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_clock_disable(ar);
835da8fa4e3SBjoern A. Zeeb 	ath10k_ahb_resource_deinit(ar);
836da8fa4e3SBjoern A. Zeeb 	ath10k_core_destroy(ar);
837da8fa4e3SBjoern A. Zeeb }
838da8fa4e3SBjoern A. Zeeb 
839da8fa4e3SBjoern A. Zeeb static struct platform_driver ath10k_ahb_driver = {
840da8fa4e3SBjoern A. Zeeb 	.driver         = {
841da8fa4e3SBjoern A. Zeeb 		.name   = "ath10k_ahb",
842da8fa4e3SBjoern A. Zeeb 		.of_match_table = ath10k_ahb_of_match,
843da8fa4e3SBjoern A. Zeeb 	},
844da8fa4e3SBjoern A. Zeeb 	.probe  = ath10k_ahb_probe,
845*07724ba6SBjoern A. Zeeb 	.remove_new = ath10k_ahb_remove,
846da8fa4e3SBjoern A. Zeeb };
847da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_init(void)848da8fa4e3SBjoern A. Zeeb int ath10k_ahb_init(void)
849da8fa4e3SBjoern A. Zeeb {
850da8fa4e3SBjoern A. Zeeb 	int ret;
851da8fa4e3SBjoern A. Zeeb 
852da8fa4e3SBjoern A. Zeeb 	ret = platform_driver_register(&ath10k_ahb_driver);
853da8fa4e3SBjoern A. Zeeb 	if (ret)
854da8fa4e3SBjoern A. Zeeb 		printk(KERN_ERR "failed to register ath10k ahb driver: %d\n",
855da8fa4e3SBjoern A. Zeeb 		       ret);
856da8fa4e3SBjoern A. Zeeb 	return ret;
857da8fa4e3SBjoern A. Zeeb }
858da8fa4e3SBjoern A. Zeeb 
ath10k_ahb_exit(void)859da8fa4e3SBjoern A. Zeeb void ath10k_ahb_exit(void)
860da8fa4e3SBjoern A. Zeeb {
861da8fa4e3SBjoern A. Zeeb 	platform_driver_unregister(&ath10k_ahb_driver);
862da8fa4e3SBjoern A. Zeeb }
863