xref: /openbmc/linux/drivers/net/wireless/ath/ath11k/ahb.c (revision c08279a9)
1d5c65159SKalle Valo // SPDX-License-Identifier: BSD-3-Clause-Clear
2d5c65159SKalle Valo /*
3d5c65159SKalle Valo  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4d5c65159SKalle Valo  */
5d5c65159SKalle Valo 
6d5c65159SKalle Valo #include <linux/module.h>
7d5c65159SKalle Valo #include <linux/platform_device.h>
8d5c65159SKalle Valo #include <linux/of_device.h>
9d5c65159SKalle Valo #include <linux/of.h>
10d5c65159SKalle Valo #include <linux/dma-mapping.h>
11d5c65159SKalle Valo #include "ahb.h"
12d5c65159SKalle Valo #include "debug.h"
1331858805SGovind Singh #include "hif.h"
14d5c65159SKalle Valo #include <linux/remoteproc.h>
15d5c65159SKalle Valo 
16d5c65159SKalle Valo static const struct of_device_id ath11k_ahb_of_match[] = {
17d5c65159SKalle Valo 	/* TODO: Should we change the compatible string to something similar
18d5c65159SKalle Valo 	 * to one that ath10k uses?
19d5c65159SKalle Valo 	 */
20d5c65159SKalle Valo 	{ .compatible = "qcom,ipq8074-wifi",
21d5c65159SKalle Valo 	  .data = (void *)ATH11K_HW_IPQ8074,
22d5c65159SKalle Valo 	},
23d5c65159SKalle Valo 	{ }
24d5c65159SKalle Valo };
25d5c65159SKalle Valo 
26d5c65159SKalle Valo MODULE_DEVICE_TABLE(of, ath11k_ahb_of_match);
27d5c65159SKalle Valo 
281ff8ed78SGovind Singh static const struct ath11k_bus_params ath11k_ahb_bus_params = {
291ff8ed78SGovind Singh 	.mhi_support = false,
3056970454SGovind Singh 	.m3_fw_support = false,
316eb6ea51SGovind Singh 	.fixed_bdf_addr = true,
326eb6ea51SGovind Singh 	.fixed_mem_region = true,
331ff8ed78SGovind Singh };
341ff8ed78SGovind Singh 
35d5c65159SKalle Valo /* Target firmware's Copy Engine configuration. */
36d5c65159SKalle Valo static const struct ce_pipe_config target_ce_config_wlan[] = {
37d5c65159SKalle Valo 	/* CE0: host->target HTC control and raw streams */
38d5c65159SKalle Valo 	{
39d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(0),
40d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
41d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
42d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
43d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
44d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
45d5c65159SKalle Valo 	},
46d5c65159SKalle Valo 
47d5c65159SKalle Valo 	/* CE1: target->host HTT + HTC control */
48d5c65159SKalle Valo 	{
49d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(1),
50d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),
51d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
52d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
53d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
54d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
55d5c65159SKalle Valo 	},
56d5c65159SKalle Valo 
57d5c65159SKalle Valo 	/* CE2: target->host WMI */
58d5c65159SKalle Valo 	{
59d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
60d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),
61d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
62d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
63d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
64d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
65d5c65159SKalle Valo 	},
66d5c65159SKalle Valo 
67d5c65159SKalle Valo 	/* CE3: host->target WMI */
68d5c65159SKalle Valo 	{
69d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(3),
70d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
71d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
72d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
73d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
74d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
75d5c65159SKalle Valo 	},
76d5c65159SKalle Valo 
77d5c65159SKalle Valo 	/* CE4: host->target HTT */
78d5c65159SKalle Valo 	{
79d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(4),
80d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
81d5c65159SKalle Valo 		.nentries = __cpu_to_le32(256),
82d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(256),
83d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
84d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
85d5c65159SKalle Valo 	},
86d5c65159SKalle Valo 
87d5c65159SKalle Valo 	/* CE5: target->host Pktlog */
88d5c65159SKalle Valo 	{
89d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(5),
90d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),
91d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
92d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
93d5c65159SKalle Valo 		.flags = __cpu_to_le32(0),
94d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
95d5c65159SKalle Valo 	},
96d5c65159SKalle Valo 
97d5c65159SKalle Valo 	/* CE6: Reserved for target autonomous hif_memcpy */
98d5c65159SKalle Valo 	{
99d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(6),
100d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
101d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
102d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(65535),
103d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
104d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
105d5c65159SKalle Valo 	},
106d5c65159SKalle Valo 
107d5c65159SKalle Valo 	/* CE7 used only by Host */
108d5c65159SKalle Valo 	{
109d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(7),
110d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
111d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
112d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
113d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
114d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
115d5c65159SKalle Valo 	},
116d5c65159SKalle Valo 
117d5c65159SKalle Valo 	/* CE8 target->host used only by IPA */
118d5c65159SKalle Valo 	{
119d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(8),
120d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
121d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
122d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(65535),
123d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
124d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
125d5c65159SKalle Valo 	},
126d5c65159SKalle Valo 
127d5c65159SKalle Valo 	/* CE9 host->target HTT */
128d5c65159SKalle Valo 	{
129d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(9),
130d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
131d5c65159SKalle Valo 		.nentries = __cpu_to_le32(32),
132d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(2048),
133d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
134d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
135d5c65159SKalle Valo 	},
136d5c65159SKalle Valo 
137d5c65159SKalle Valo 	/* CE10 target->host HTT */
138d5c65159SKalle Valo 	{
139d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(10),
140d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
141d5c65159SKalle Valo 		.nentries = __cpu_to_le32(0),
142d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(0),
143d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
144d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
145d5c65159SKalle Valo 	},
146d5c65159SKalle Valo 
147d5c65159SKalle Valo 	/* CE11 Not used */
148d5c65159SKalle Valo 	{
149d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(0),
150d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(0),
151d5c65159SKalle Valo 		.nentries = __cpu_to_le32(0),
152d5c65159SKalle Valo 		.nbytes_max = __cpu_to_le32(0),
153d5c65159SKalle Valo 		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
154d5c65159SKalle Valo 		.reserved = __cpu_to_le32(0),
155d5c65159SKalle Valo 	},
156d5c65159SKalle Valo };
157d5c65159SKalle Valo 
158d5c65159SKalle Valo /* Map from service/endpoint to Copy Engine.
159d5c65159SKalle Valo  * This table is derived from the CE_PCI TABLE, above.
160d5c65159SKalle Valo  * It is passed to the Target at startup for use by firmware.
161d5c65159SKalle Valo  */
162d5c65159SKalle Valo static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
163d5c65159SKalle Valo 	{
164d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
165d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
166d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(3),
167d5c65159SKalle Valo 	},
168d5c65159SKalle Valo 	{
169d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
170d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
171d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
172d5c65159SKalle Valo 	},
173d5c65159SKalle Valo 	{
174d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
175d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
176d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(3),
177d5c65159SKalle Valo 	},
178d5c65159SKalle Valo 	{
179d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
180d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
181d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
182d5c65159SKalle Valo 	},
183d5c65159SKalle Valo 	{
184d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
185d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
186d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(3),
187d5c65159SKalle Valo 	},
188d5c65159SKalle Valo 	{
189d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
190d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
191d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
192d5c65159SKalle Valo 	},
193d5c65159SKalle Valo 	{
194d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
195d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
196d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(3),
197d5c65159SKalle Valo 	},
198d5c65159SKalle Valo 	{
199d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
200d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
201d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
202d5c65159SKalle Valo 	},
203d5c65159SKalle Valo 	{
204d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
205d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
206d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(3),
207d5c65159SKalle Valo 	},
208d5c65159SKalle Valo 	{
209d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
210d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
211d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
212d5c65159SKalle Valo 	},
213d5c65159SKalle Valo 	{
214d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
215d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
216d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(7),
217d5c65159SKalle Valo 	},
218d5c65159SKalle Valo 	{
219d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
220d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
221d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
222d5c65159SKalle Valo 	},
223d5c65159SKalle Valo 	{
224d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
225d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
226d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(9),
227d5c65159SKalle Valo 	},
228d5c65159SKalle Valo 	{
229d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
230d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
231d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(2),
232d5c65159SKalle Valo 	},
233d5c65159SKalle Valo 	{
234d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
235d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
236d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(0),
237d5c65159SKalle Valo 	},
238d5c65159SKalle Valo 	{
239d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
240d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
241d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(1),
242d5c65159SKalle Valo 	},
243d5c65159SKalle Valo 	{ /* not used */
244d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
245d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
246d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(0),
247d5c65159SKalle Valo 	},
248d5c65159SKalle Valo 	{ /* not used */
249d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
250d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
251d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(1),
252d5c65159SKalle Valo 	},
253d5c65159SKalle Valo 	{
254d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
255d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
256d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(4),
257d5c65159SKalle Valo 	},
258d5c65159SKalle Valo 	{
259d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
260d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
261d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(1),
262d5c65159SKalle Valo 	},
263d5c65159SKalle Valo 	{
264d5c65159SKalle Valo 		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG),
265d5c65159SKalle Valo 		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
266d5c65159SKalle Valo 		.pipenum = __cpu_to_le32(5),
267d5c65159SKalle Valo 	},
268d5c65159SKalle Valo 
269d5c65159SKalle Valo 	/* (Additions here) */
270d5c65159SKalle Valo 
271d5c65159SKalle Valo 	{ /* terminator entry */ }
272d5c65159SKalle Valo };
273d5c65159SKalle Valo 
274d5c65159SKalle Valo #define ATH11K_IRQ_CE0_OFFSET 4
275d5c65159SKalle Valo 
276d5c65159SKalle Valo static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
277d5c65159SKalle Valo 	"misc-pulse1",
278d5c65159SKalle Valo 	"misc-latch",
279d5c65159SKalle Valo 	"sw-exception",
280d5c65159SKalle Valo 	"watchdog",
281d5c65159SKalle Valo 	"ce0",
282d5c65159SKalle Valo 	"ce1",
283d5c65159SKalle Valo 	"ce2",
284d5c65159SKalle Valo 	"ce3",
285d5c65159SKalle Valo 	"ce4",
286d5c65159SKalle Valo 	"ce5",
287d5c65159SKalle Valo 	"ce6",
288d5c65159SKalle Valo 	"ce7",
289d5c65159SKalle Valo 	"ce8",
290d5c65159SKalle Valo 	"ce9",
291d5c65159SKalle Valo 	"ce10",
292d5c65159SKalle Valo 	"ce11",
293d5c65159SKalle Valo 	"host2wbm-desc-feed",
294d5c65159SKalle Valo 	"host2reo-re-injection",
295d5c65159SKalle Valo 	"host2reo-command",
296d5c65159SKalle Valo 	"host2rxdma-monitor-ring3",
297d5c65159SKalle Valo 	"host2rxdma-monitor-ring2",
298d5c65159SKalle Valo 	"host2rxdma-monitor-ring1",
299d5c65159SKalle Valo 	"reo2ost-exception",
300d5c65159SKalle Valo 	"wbm2host-rx-release",
301d5c65159SKalle Valo 	"reo2host-status",
302d5c65159SKalle Valo 	"reo2host-destination-ring4",
303d5c65159SKalle Valo 	"reo2host-destination-ring3",
304d5c65159SKalle Valo 	"reo2host-destination-ring2",
305d5c65159SKalle Valo 	"reo2host-destination-ring1",
306d5c65159SKalle Valo 	"rxdma2host-monitor-destination-mac3",
307d5c65159SKalle Valo 	"rxdma2host-monitor-destination-mac2",
308d5c65159SKalle Valo 	"rxdma2host-monitor-destination-mac1",
309d5c65159SKalle Valo 	"ppdu-end-interrupts-mac3",
310d5c65159SKalle Valo 	"ppdu-end-interrupts-mac2",
311d5c65159SKalle Valo 	"ppdu-end-interrupts-mac1",
312d5c65159SKalle Valo 	"rxdma2host-monitor-status-ring-mac3",
313d5c65159SKalle Valo 	"rxdma2host-monitor-status-ring-mac2",
314d5c65159SKalle Valo 	"rxdma2host-monitor-status-ring-mac1",
315d5c65159SKalle Valo 	"host2rxdma-host-buf-ring-mac3",
316d5c65159SKalle Valo 	"host2rxdma-host-buf-ring-mac2",
317d5c65159SKalle Valo 	"host2rxdma-host-buf-ring-mac1",
318d5c65159SKalle Valo 	"rxdma2host-destination-ring-mac3",
319d5c65159SKalle Valo 	"rxdma2host-destination-ring-mac2",
320d5c65159SKalle Valo 	"rxdma2host-destination-ring-mac1",
321d5c65159SKalle Valo 	"host2tcl-input-ring4",
322d5c65159SKalle Valo 	"host2tcl-input-ring3",
323d5c65159SKalle Valo 	"host2tcl-input-ring2",
324d5c65159SKalle Valo 	"host2tcl-input-ring1",
325d5c65159SKalle Valo 	"wbm2host-tx-completions-ring3",
326d5c65159SKalle Valo 	"wbm2host-tx-completions-ring2",
327d5c65159SKalle Valo 	"wbm2host-tx-completions-ring1",
328d5c65159SKalle Valo 	"tcl2host-status-ring",
329d5c65159SKalle Valo };
330d5c65159SKalle Valo 
331d5c65159SKalle Valo /* enum ext_irq_num - irq numbers that can be used by external modules
332d5c65159SKalle Valo  * like datapath
333d5c65159SKalle Valo  */
334d5c65159SKalle Valo enum ext_irq_num {
335d5c65159SKalle Valo 	host2wbm_desc_feed = 16,
336d5c65159SKalle Valo 	host2reo_re_injection,
337d5c65159SKalle Valo 	host2reo_command,
338d5c65159SKalle Valo 	host2rxdma_monitor_ring3,
339d5c65159SKalle Valo 	host2rxdma_monitor_ring2,
340d5c65159SKalle Valo 	host2rxdma_monitor_ring1,
341d5c65159SKalle Valo 	reo2host_exception,
342d5c65159SKalle Valo 	wbm2host_rx_release,
343d5c65159SKalle Valo 	reo2host_status,
344d5c65159SKalle Valo 	reo2host_destination_ring4,
345d5c65159SKalle Valo 	reo2host_destination_ring3,
346d5c65159SKalle Valo 	reo2host_destination_ring2,
347d5c65159SKalle Valo 	reo2host_destination_ring1,
348d5c65159SKalle Valo 	rxdma2host_monitor_destination_mac3,
349d5c65159SKalle Valo 	rxdma2host_monitor_destination_mac2,
350d5c65159SKalle Valo 	rxdma2host_monitor_destination_mac1,
351d5c65159SKalle Valo 	ppdu_end_interrupts_mac3,
352d5c65159SKalle Valo 	ppdu_end_interrupts_mac2,
353d5c65159SKalle Valo 	ppdu_end_interrupts_mac1,
354d5c65159SKalle Valo 	rxdma2host_monitor_status_ring_mac3,
355d5c65159SKalle Valo 	rxdma2host_monitor_status_ring_mac2,
356d5c65159SKalle Valo 	rxdma2host_monitor_status_ring_mac1,
357d5c65159SKalle Valo 	host2rxdma_host_buf_ring_mac3,
358d5c65159SKalle Valo 	host2rxdma_host_buf_ring_mac2,
359d5c65159SKalle Valo 	host2rxdma_host_buf_ring_mac1,
360d5c65159SKalle Valo 	rxdma2host_destination_ring_mac3,
361d5c65159SKalle Valo 	rxdma2host_destination_ring_mac2,
362d5c65159SKalle Valo 	rxdma2host_destination_ring_mac1,
363d5c65159SKalle Valo 	host2tcl_input_ring4,
364d5c65159SKalle Valo 	host2tcl_input_ring3,
365d5c65159SKalle Valo 	host2tcl_input_ring2,
366d5c65159SKalle Valo 	host2tcl_input_ring1,
367d5c65159SKalle Valo 	wbm2host_tx_completions_ring3,
368d5c65159SKalle Valo 	wbm2host_tx_completions_ring2,
369d5c65159SKalle Valo 	wbm2host_tx_completions_ring1,
370d5c65159SKalle Valo 	tcl2host_status_ring,
371d5c65159SKalle Valo };
372d5c65159SKalle Valo 
37331858805SGovind Singh static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset)
37431858805SGovind Singh {
37531858805SGovind Singh 	return ioread32(ab->mem + offset);
37631858805SGovind Singh }
37731858805SGovind Singh 
37831858805SGovind Singh static inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value)
37931858805SGovind Singh {
38031858805SGovind Singh 	iowrite32(value, ab->mem + offset);
38131858805SGovind Singh }
38231858805SGovind Singh 
383d5c65159SKalle Valo static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab)
384d5c65159SKalle Valo {
385d5c65159SKalle Valo 	int i;
386d5c65159SKalle Valo 
387d9d4b5f3SKalle Valo 	for (i = 0; i < ab->hw_params.ce_count; i++) {
388d5c65159SKalle Valo 		struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
389d5c65159SKalle Valo 
390e3396b8bSCarl Huang 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
391d5c65159SKalle Valo 			continue;
392d5c65159SKalle Valo 
393d5c65159SKalle Valo 		tasklet_kill(&ce_pipe->intr_tq);
394d5c65159SKalle Valo 	}
395d5c65159SKalle Valo }
396d5c65159SKalle Valo 
397d5c65159SKalle Valo static void ath11k_ahb_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
398d5c65159SKalle Valo {
399d5c65159SKalle Valo 	int i;
400d5c65159SKalle Valo 
401d5c65159SKalle Valo 	for (i = 0; i < irq_grp->num_irq; i++)
402d5c65159SKalle Valo 		disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
403d5c65159SKalle Valo }
404d5c65159SKalle Valo 
405d5c65159SKalle Valo static void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
406d5c65159SKalle Valo {
407d5c65159SKalle Valo 	int i;
408d5c65159SKalle Valo 
409d5c65159SKalle Valo 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
410d5c65159SKalle Valo 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
411d5c65159SKalle Valo 
412d5c65159SKalle Valo 		ath11k_ahb_ext_grp_disable(irq_grp);
413d5c65159SKalle Valo 
414d5c65159SKalle Valo 		napi_synchronize(&irq_grp->napi);
415d5c65159SKalle Valo 		napi_disable(&irq_grp->napi);
416d5c65159SKalle Valo 	}
417d5c65159SKalle Valo }
418d5c65159SKalle Valo 
419d5c65159SKalle Valo static void ath11k_ahb_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
420d5c65159SKalle Valo {
421d5c65159SKalle Valo 	int i;
422d5c65159SKalle Valo 
423d5c65159SKalle Valo 	for (i = 0; i < irq_grp->num_irq; i++)
424d5c65159SKalle Valo 		enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
425d5c65159SKalle Valo }
426d5c65159SKalle Valo 
427d5c65159SKalle Valo static void ath11k_ahb_setbit32(struct ath11k_base *ab, u8 bit, u32 offset)
428d5c65159SKalle Valo {
429d5c65159SKalle Valo 	u32 val;
430d5c65159SKalle Valo 
431d5c65159SKalle Valo 	val = ath11k_ahb_read32(ab, offset);
432d5c65159SKalle Valo 	ath11k_ahb_write32(ab, offset, val | BIT(bit));
433d5c65159SKalle Valo }
434d5c65159SKalle Valo 
435d5c65159SKalle Valo static void ath11k_ahb_clearbit32(struct ath11k_base *ab, u8 bit, u32 offset)
436d5c65159SKalle Valo {
437d5c65159SKalle Valo 	u32 val;
438d5c65159SKalle Valo 
439d5c65159SKalle Valo 	val = ath11k_ahb_read32(ab, offset);
440d5c65159SKalle Valo 	ath11k_ahb_write32(ab, offset, val & ~BIT(bit));
441d5c65159SKalle Valo }
442d5c65159SKalle Valo 
443d5c65159SKalle Valo static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
444d5c65159SKalle Valo {
445d5c65159SKalle Valo 	const struct ce_pipe_config *ce_config;
446d5c65159SKalle Valo 
447d5c65159SKalle Valo 	ce_config = &target_ce_config_wlan[ce_id];
448d5c65159SKalle Valo 	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
449d5c65159SKalle Valo 		ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
450d5c65159SKalle Valo 
451d5c65159SKalle Valo 	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) {
452d5c65159SKalle Valo 		ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
453d5c65159SKalle Valo 		ath11k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
454d5c65159SKalle Valo 				    CE_HOST_IE_3_ADDRESS);
455d5c65159SKalle Valo 	}
456d5c65159SKalle Valo }
457d5c65159SKalle Valo 
458d5c65159SKalle Valo static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
459d5c65159SKalle Valo {
460d5c65159SKalle Valo 	const struct ce_pipe_config *ce_config;
461d5c65159SKalle Valo 
462d5c65159SKalle Valo 	ce_config = &target_ce_config_wlan[ce_id];
463d5c65159SKalle Valo 	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
464d5c65159SKalle Valo 		ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
465d5c65159SKalle Valo 
466d5c65159SKalle Valo 	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) {
467d5c65159SKalle Valo 		ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
468d5c65159SKalle Valo 		ath11k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
469d5c65159SKalle Valo 				      CE_HOST_IE_3_ADDRESS);
470d5c65159SKalle Valo 	}
471d5c65159SKalle Valo }
472d5c65159SKalle Valo 
473d5c65159SKalle Valo static void ath11k_ahb_sync_ce_irqs(struct ath11k_base *ab)
474d5c65159SKalle Valo {
475d5c65159SKalle Valo 	int i;
476d5c65159SKalle Valo 	int irq_idx;
477d5c65159SKalle Valo 
478d9d4b5f3SKalle Valo 	for (i = 0; i < ab->hw_params.ce_count; i++) {
479e3396b8bSCarl Huang 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
480d5c65159SKalle Valo 			continue;
481d5c65159SKalle Valo 
482d5c65159SKalle Valo 		irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
483d5c65159SKalle Valo 		synchronize_irq(ab->irq_num[irq_idx]);
484d5c65159SKalle Valo 	}
485d5c65159SKalle Valo }
486d5c65159SKalle Valo 
487d5c65159SKalle Valo static void ath11k_ahb_sync_ext_irqs(struct ath11k_base *ab)
488d5c65159SKalle Valo {
489d5c65159SKalle Valo 	int i, j;
490d5c65159SKalle Valo 	int irq_idx;
491d5c65159SKalle Valo 
492d5c65159SKalle Valo 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
493d5c65159SKalle Valo 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
494d5c65159SKalle Valo 
495d5c65159SKalle Valo 		for (j = 0; j < irq_grp->num_irq; j++) {
496d5c65159SKalle Valo 			irq_idx = irq_grp->irqs[j];
497d5c65159SKalle Valo 			synchronize_irq(ab->irq_num[irq_idx]);
498d5c65159SKalle Valo 		}
499d5c65159SKalle Valo 	}
500d5c65159SKalle Valo }
501d5c65159SKalle Valo 
502d5c65159SKalle Valo static void ath11k_ahb_ce_irqs_enable(struct ath11k_base *ab)
503d5c65159SKalle Valo {
504d5c65159SKalle Valo 	int i;
505d5c65159SKalle Valo 
506d9d4b5f3SKalle Valo 	for (i = 0; i < ab->hw_params.ce_count; i++) {
507e3396b8bSCarl Huang 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
508d5c65159SKalle Valo 			continue;
509d5c65159SKalle Valo 		ath11k_ahb_ce_irq_enable(ab, i);
510d5c65159SKalle Valo 	}
511d5c65159SKalle Valo }
512d5c65159SKalle Valo 
513d5c65159SKalle Valo static void ath11k_ahb_ce_irqs_disable(struct ath11k_base *ab)
514d5c65159SKalle Valo {
515d5c65159SKalle Valo 	int i;
516d5c65159SKalle Valo 
517d9d4b5f3SKalle Valo 	for (i = 0; i < ab->hw_params.ce_count; i++) {
518e3396b8bSCarl Huang 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
519d5c65159SKalle Valo 			continue;
520d5c65159SKalle Valo 		ath11k_ahb_ce_irq_disable(ab, i);
521d5c65159SKalle Valo 	}
522d5c65159SKalle Valo }
523d5c65159SKalle Valo 
52431858805SGovind Singh static int ath11k_ahb_start(struct ath11k_base *ab)
525d5c65159SKalle Valo {
526d5c65159SKalle Valo 	ath11k_ahb_ce_irqs_enable(ab);
527d5c65159SKalle Valo 	ath11k_ce_rx_post_buf(ab);
528d5c65159SKalle Valo 
529d5c65159SKalle Valo 	return 0;
530d5c65159SKalle Valo }
531d5c65159SKalle Valo 
53231858805SGovind Singh static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab)
533d5c65159SKalle Valo {
534d5c65159SKalle Valo 	int i;
535d5c65159SKalle Valo 
536d5c65159SKalle Valo 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
537d5c65159SKalle Valo 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
538d5c65159SKalle Valo 
539d5c65159SKalle Valo 		napi_enable(&irq_grp->napi);
540d5c65159SKalle Valo 		ath11k_ahb_ext_grp_enable(irq_grp);
541d5c65159SKalle Valo 	}
542d5c65159SKalle Valo }
543d5c65159SKalle Valo 
54431858805SGovind Singh static void ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
545d5c65159SKalle Valo {
546d5c65159SKalle Valo 	__ath11k_ahb_ext_irq_disable(ab);
547d5c65159SKalle Valo 	ath11k_ahb_sync_ext_irqs(ab);
548d5c65159SKalle Valo }
549d5c65159SKalle Valo 
55031858805SGovind Singh static void ath11k_ahb_stop(struct ath11k_base *ab)
551d5c65159SKalle Valo {
552d5c65159SKalle Valo 	if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))
553d5c65159SKalle Valo 		ath11k_ahb_ce_irqs_disable(ab);
554d5c65159SKalle Valo 	ath11k_ahb_sync_ce_irqs(ab);
555d5c65159SKalle Valo 	ath11k_ahb_kill_tasklets(ab);
556d5c65159SKalle Valo 	del_timer_sync(&ab->rx_replenish_retry);
557d5c65159SKalle Valo 	ath11k_ce_cleanup_pipes(ab);
558d5c65159SKalle Valo }
559d5c65159SKalle Valo 
56031858805SGovind Singh static int ath11k_ahb_power_up(struct ath11k_base *ab)
561d5c65159SKalle Valo {
562d5c65159SKalle Valo 	int ret;
563d5c65159SKalle Valo 
564d5c65159SKalle Valo 	ret = rproc_boot(ab->tgt_rproc);
565d5c65159SKalle Valo 	if (ret)
566d5c65159SKalle Valo 		ath11k_err(ab, "failed to boot the remote processor Q6\n");
567d5c65159SKalle Valo 
568d5c65159SKalle Valo 	return ret;
569d5c65159SKalle Valo }
570d5c65159SKalle Valo 
57131858805SGovind Singh static void ath11k_ahb_power_down(struct ath11k_base *ab)
572d5c65159SKalle Valo {
573d5c65159SKalle Valo 	rproc_shutdown(ab->tgt_rproc);
574d5c65159SKalle Valo }
575d5c65159SKalle Valo 
576d5c65159SKalle Valo static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
577d5c65159SKalle Valo {
578d5c65159SKalle Valo 	struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
579d5c65159SKalle Valo 
580d6af906dSAnilkumar Kolli 	cfg->tgt_ce_len = ARRAY_SIZE(target_ce_config_wlan) - 1;
581d6af906dSAnilkumar Kolli 	cfg->tgt_ce = target_ce_config_wlan;
582d6af906dSAnilkumar Kolli 	cfg->svc_to_ce_map_len = ARRAY_SIZE(target_service_to_ce_map_wlan);
583d6af906dSAnilkumar Kolli 	cfg->svc_to_ce_map = target_service_to_ce_map_wlan;
584eb8de049SGovind Singh 	ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074;
585d5c65159SKalle Valo }
586d5c65159SKalle Valo 
587d5c65159SKalle Valo static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab)
588d5c65159SKalle Valo {
589d5c65159SKalle Valo 	int i, j;
590d5c65159SKalle Valo 
591d5c65159SKalle Valo 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
592d5c65159SKalle Valo 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
593d5c65159SKalle Valo 
594d5c65159SKalle Valo 		for (j = 0; j < irq_grp->num_irq; j++)
595d5c65159SKalle Valo 			free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);
596d5c65159SKalle Valo 	}
597d5c65159SKalle Valo }
598d5c65159SKalle Valo 
599d5c65159SKalle Valo static void ath11k_ahb_free_irq(struct ath11k_base *ab)
600d5c65159SKalle Valo {
601d5c65159SKalle Valo 	int irq_idx;
602d5c65159SKalle Valo 	int i;
603d5c65159SKalle Valo 
604d9d4b5f3SKalle Valo 	for (i = 0; i < ab->hw_params.ce_count; i++) {
605e3396b8bSCarl Huang 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
606d5c65159SKalle Valo 			continue;
607d5c65159SKalle Valo 		irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
608d5c65159SKalle Valo 		free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
609d5c65159SKalle Valo 	}
610d5c65159SKalle Valo 
611d5c65159SKalle Valo 	ath11k_ahb_free_ext_irq(ab);
612d5c65159SKalle Valo }
613d5c65159SKalle Valo 
614c08279a9SAllen Pais static void ath11k_ahb_ce_tasklet(struct tasklet_struct *t)
615d5c65159SKalle Valo {
616c08279a9SAllen Pais 	struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
617d5c65159SKalle Valo 
618d5c65159SKalle Valo 	ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
619d5c65159SKalle Valo 
620d5c65159SKalle Valo 	ath11k_ahb_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
621d5c65159SKalle Valo }
622d5c65159SKalle Valo 
623d5c65159SKalle Valo static irqreturn_t ath11k_ahb_ce_interrupt_handler(int irq, void *arg)
624d5c65159SKalle Valo {
625d5c65159SKalle Valo 	struct ath11k_ce_pipe *ce_pipe = arg;
626d5c65159SKalle Valo 
6275118935bSManikanta Pubbisetty 	/* last interrupt received for this CE */
6285118935bSManikanta Pubbisetty 	ce_pipe->timestamp = jiffies;
6295118935bSManikanta Pubbisetty 
630d5c65159SKalle Valo 	ath11k_ahb_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
631d5c65159SKalle Valo 
632d5c65159SKalle Valo 	tasklet_schedule(&ce_pipe->intr_tq);
633d5c65159SKalle Valo 
634d5c65159SKalle Valo 	return IRQ_HANDLED;
635d5c65159SKalle Valo }
636d5c65159SKalle Valo 
637d5c65159SKalle Valo static int ath11k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget)
638d5c65159SKalle Valo {
639d5c65159SKalle Valo 	struct ath11k_ext_irq_grp *irq_grp = container_of(napi,
640d5c65159SKalle Valo 						struct ath11k_ext_irq_grp,
641d5c65159SKalle Valo 						napi);
642d5c65159SKalle Valo 	struct ath11k_base *ab = irq_grp->ab;
643d5c65159SKalle Valo 	int work_done;
644d5c65159SKalle Valo 
645d5c65159SKalle Valo 	work_done = ath11k_dp_service_srng(ab, irq_grp, budget);
646d5c65159SKalle Valo 	if (work_done < budget) {
647d5c65159SKalle Valo 		napi_complete_done(napi, work_done);
648d5c65159SKalle Valo 		ath11k_ahb_ext_grp_enable(irq_grp);
649d5c65159SKalle Valo 	}
650d5c65159SKalle Valo 
651d5c65159SKalle Valo 	if (work_done > budget)
652d5c65159SKalle Valo 		work_done = budget;
653d5c65159SKalle Valo 
654d5c65159SKalle Valo 	return work_done;
655d5c65159SKalle Valo }
656d5c65159SKalle Valo 
657d5c65159SKalle Valo static irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg)
658d5c65159SKalle Valo {
659d5c65159SKalle Valo 	struct ath11k_ext_irq_grp *irq_grp = arg;
660d5c65159SKalle Valo 
6615118935bSManikanta Pubbisetty 	/* last interrupt received for this group */
6625118935bSManikanta Pubbisetty 	irq_grp->timestamp = jiffies;
6635118935bSManikanta Pubbisetty 
664d5c65159SKalle Valo 	ath11k_ahb_ext_grp_disable(irq_grp);
665d5c65159SKalle Valo 
666d5c65159SKalle Valo 	napi_schedule(&irq_grp->napi);
667d5c65159SKalle Valo 
668d5c65159SKalle Valo 	return IRQ_HANDLED;
669d5c65159SKalle Valo }
670d5c65159SKalle Valo 
671d5c65159SKalle Valo static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab)
672d5c65159SKalle Valo {
673d547ca4cSAnilkumar Kolli 	struct ath11k_hw_params *hw = &ab->hw_params;
674d5c65159SKalle Valo 	int i, j;
675d5c65159SKalle Valo 	int irq;
676d5c65159SKalle Valo 	int ret;
677d5c65159SKalle Valo 
678d5c65159SKalle Valo 	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
679d5c65159SKalle Valo 		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
680d5c65159SKalle Valo 		u32 num_irq = 0;
681d5c65159SKalle Valo 
682d5c65159SKalle Valo 		irq_grp->ab = ab;
683d5c65159SKalle Valo 		irq_grp->grp_id = i;
684d5c65159SKalle Valo 		init_dummy_netdev(&irq_grp->napi_ndev);
685d5c65159SKalle Valo 		netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
686d5c65159SKalle Valo 			       ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT);
687d5c65159SKalle Valo 
688d5c65159SKalle Valo 		for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) {
68934d5a3a8SKalle Valo 			if (ab->hw_params.ring_mask->tx[i] & BIT(j)) {
690d5c65159SKalle Valo 				irq_grp->irqs[num_irq++] =
691d5c65159SKalle Valo 					wbm2host_tx_completions_ring1 - j;
692d5c65159SKalle Valo 			}
693d5c65159SKalle Valo 
69434d5a3a8SKalle Valo 			if (ab->hw_params.ring_mask->rx[i] & BIT(j)) {
695d5c65159SKalle Valo 				irq_grp->irqs[num_irq++] =
696d5c65159SKalle Valo 					reo2host_destination_ring1 - j;
697d5c65159SKalle Valo 			}
698d5c65159SKalle Valo 
69934d5a3a8SKalle Valo 			if (ab->hw_params.ring_mask->rx_err[i] & BIT(j))
700d5c65159SKalle Valo 				irq_grp->irqs[num_irq++] = reo2host_exception;
701d5c65159SKalle Valo 
70234d5a3a8SKalle Valo 			if (ab->hw_params.ring_mask->rx_wbm_rel[i] & BIT(j))
703d5c65159SKalle Valo 				irq_grp->irqs[num_irq++] = wbm2host_rx_release;
704d5c65159SKalle Valo 
70534d5a3a8SKalle Valo 			if (ab->hw_params.ring_mask->reo_status[i] & BIT(j))
706d5c65159SKalle Valo 				irq_grp->irqs[num_irq++] = reo2host_status;
707d5c65159SKalle Valo 
708d547ca4cSAnilkumar Kolli 			if (j < ab->hw_params.max_radios) {
70934d5a3a8SKalle Valo 				if (ab->hw_params.ring_mask->rxdma2host[i] & BIT(j)) {
710d5c65159SKalle Valo 					irq_grp->irqs[num_irq++] =
711d547ca4cSAnilkumar Kolli 						rxdma2host_destination_ring_mac1 -
712d547ca4cSAnilkumar Kolli 						ath11k_hw_get_mac_from_pdev_id(hw, j);
713d5c65159SKalle Valo 				}
714d5c65159SKalle Valo 
71534d5a3a8SKalle Valo 				if (ab->hw_params.ring_mask->host2rxdma[i] & BIT(j)) {
716d5c65159SKalle Valo 					irq_grp->irqs[num_irq++] =
717d547ca4cSAnilkumar Kolli 						host2rxdma_host_buf_ring_mac1 -
718d547ca4cSAnilkumar Kolli 						ath11k_hw_get_mac_from_pdev_id(hw, j);
719d5c65159SKalle Valo 				}
720d5c65159SKalle Valo 
72134d5a3a8SKalle Valo 				if (ab->hw_params.ring_mask->rx_mon_status[i] & BIT(j)) {
722d5c65159SKalle Valo 					irq_grp->irqs[num_irq++] =
723d5c65159SKalle Valo 						ppdu_end_interrupts_mac1 -
724d547ca4cSAnilkumar Kolli 						ath11k_hw_get_mac_from_pdev_id(hw, j);
725d5c65159SKalle Valo 					irq_grp->irqs[num_irq++] =
726d5c65159SKalle Valo 						rxdma2host_monitor_status_ring_mac1 -
727d547ca4cSAnilkumar Kolli 						ath11k_hw_get_mac_from_pdev_id(hw, j);
728d5c65159SKalle Valo 				}
729d5c65159SKalle Valo 			}
730d5c65159SKalle Valo 		}
731d5c65159SKalle Valo 		irq_grp->num_irq = num_irq;
732d5c65159SKalle Valo 
733d5c65159SKalle Valo 		for (j = 0; j < irq_grp->num_irq; j++) {
734d5c65159SKalle Valo 			int irq_idx = irq_grp->irqs[j];
735d5c65159SKalle Valo 
736d5c65159SKalle Valo 			irq = platform_get_irq_byname(ab->pdev,
737d5c65159SKalle Valo 						      irq_name[irq_idx]);
738d5c65159SKalle Valo 			ab->irq_num[irq_idx] = irq;
73905090864SManikanta Pubbisetty 			irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
740d5c65159SKalle Valo 			ret = request_irq(irq, ath11k_ahb_ext_interrupt_handler,
741d5c65159SKalle Valo 					  IRQF_TRIGGER_RISING,
742d5c65159SKalle Valo 					  irq_name[irq_idx], irq_grp);
743d5c65159SKalle Valo 			if (ret) {
744d5c65159SKalle Valo 				ath11k_err(ab, "failed request_irq for %d\n",
745d5c65159SKalle Valo 					   irq);
746d5c65159SKalle Valo 			}
747d5c65159SKalle Valo 		}
748d5c65159SKalle Valo 	}
749d5c65159SKalle Valo 
750d5c65159SKalle Valo 	return 0;
751d5c65159SKalle Valo }
752d5c65159SKalle Valo 
753d5c65159SKalle Valo static int ath11k_ahb_config_irq(struct ath11k_base *ab)
754d5c65159SKalle Valo {
755d5c65159SKalle Valo 	int irq, irq_idx, i;
756d5c65159SKalle Valo 	int ret;
757d5c65159SKalle Valo 
758d5c65159SKalle Valo 	/* Configure CE irqs */
759d9d4b5f3SKalle Valo 	for (i = 0; i < ab->hw_params.ce_count; i++) {
760d5c65159SKalle Valo 		struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
761d5c65159SKalle Valo 
762e3396b8bSCarl Huang 		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
763d5c65159SKalle Valo 			continue;
764d5c65159SKalle Valo 
765d5c65159SKalle Valo 		irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
766d5c65159SKalle Valo 
767c08279a9SAllen Pais 		tasklet_setup(&ce_pipe->intr_tq, ath11k_ahb_ce_tasklet);
768d5c65159SKalle Valo 		irq = platform_get_irq_byname(ab->pdev, irq_name[irq_idx]);
769d5c65159SKalle Valo 		ret = request_irq(irq, ath11k_ahb_ce_interrupt_handler,
770d5c65159SKalle Valo 				  IRQF_TRIGGER_RISING, irq_name[irq_idx],
771d5c65159SKalle Valo 				  ce_pipe);
772d5c65159SKalle Valo 		if (ret)
773d5c65159SKalle Valo 			return ret;
774d5c65159SKalle Valo 
775d5c65159SKalle Valo 		ab->irq_num[irq_idx] = irq;
776d5c65159SKalle Valo 	}
777d5c65159SKalle Valo 
778d5c65159SKalle Valo 	/* Configure external interrupts */
779d5c65159SKalle Valo 	ret = ath11k_ahb_ext_irq_config(ab);
780d5c65159SKalle Valo 
781d5c65159SKalle Valo 	return ret;
782d5c65159SKalle Valo }
783d5c65159SKalle Valo 
78431858805SGovind Singh static int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
785d5c65159SKalle Valo 					  u8 *ul_pipe, u8 *dl_pipe)
786d5c65159SKalle Valo {
787d5c65159SKalle Valo 	const struct service_to_pipe *entry;
788d5c65159SKalle Valo 	bool ul_set = false, dl_set = false;
789d5c65159SKalle Valo 	int i;
790d5c65159SKalle Valo 
791d5c65159SKalle Valo 	for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) {
792d5c65159SKalle Valo 		entry = &target_service_to_ce_map_wlan[i];
793d5c65159SKalle Valo 
794d5c65159SKalle Valo 		if (__le32_to_cpu(entry->service_id) != service_id)
795d5c65159SKalle Valo 			continue;
796d5c65159SKalle Valo 
797d5c65159SKalle Valo 		switch (__le32_to_cpu(entry->pipedir)) {
798d5c65159SKalle Valo 		case PIPEDIR_NONE:
799d5c65159SKalle Valo 			break;
800d5c65159SKalle Valo 		case PIPEDIR_IN:
801d5c65159SKalle Valo 			WARN_ON(dl_set);
802d5c65159SKalle Valo 			*dl_pipe = __le32_to_cpu(entry->pipenum);
803d5c65159SKalle Valo 			dl_set = true;
804d5c65159SKalle Valo 			break;
805d5c65159SKalle Valo 		case PIPEDIR_OUT:
806d5c65159SKalle Valo 			WARN_ON(ul_set);
807d5c65159SKalle Valo 			*ul_pipe = __le32_to_cpu(entry->pipenum);
808d5c65159SKalle Valo 			ul_set = true;
809d5c65159SKalle Valo 			break;
810d5c65159SKalle Valo 		case PIPEDIR_INOUT:
811d5c65159SKalle Valo 			WARN_ON(dl_set);
812d5c65159SKalle Valo 			WARN_ON(ul_set);
813d5c65159SKalle Valo 			*dl_pipe = __le32_to_cpu(entry->pipenum);
814d5c65159SKalle Valo 			*ul_pipe = __le32_to_cpu(entry->pipenum);
815d5c65159SKalle Valo 			dl_set = true;
816d5c65159SKalle Valo 			ul_set = true;
817d5c65159SKalle Valo 			break;
818d5c65159SKalle Valo 		}
819d5c65159SKalle Valo 	}
820d5c65159SKalle Valo 
821d5c65159SKalle Valo 	if (WARN_ON(!ul_set || !dl_set))
822d5c65159SKalle Valo 		return -ENOENT;
823d5c65159SKalle Valo 
824d5c65159SKalle Valo 	return 0;
825d5c65159SKalle Valo }
826d5c65159SKalle Valo 
82731858805SGovind Singh static const struct ath11k_hif_ops ath11k_ahb_hif_ops = {
82831858805SGovind Singh 	.start = ath11k_ahb_start,
82931858805SGovind Singh 	.stop = ath11k_ahb_stop,
83031858805SGovind Singh 	.read32 = ath11k_ahb_read32,
83131858805SGovind Singh 	.write32 = ath11k_ahb_write32,
83231858805SGovind Singh 	.irq_enable = ath11k_ahb_ext_irq_enable,
83331858805SGovind Singh 	.irq_disable = ath11k_ahb_ext_irq_disable,
83431858805SGovind Singh 	.map_service_to_pipe = ath11k_ahb_map_service_to_pipe,
83531858805SGovind Singh 	.power_down = ath11k_ahb_power_down,
83631858805SGovind Singh 	.power_up = ath11k_ahb_power_up,
83731858805SGovind Singh };
83831858805SGovind Singh 
839d5c65159SKalle Valo static int ath11k_ahb_probe(struct platform_device *pdev)
840d5c65159SKalle Valo {
841d5c65159SKalle Valo 	struct ath11k_base *ab;
842d5c65159SKalle Valo 	const struct of_device_id *of_id;
843d5c65159SKalle Valo 	struct resource *mem_res;
844d5c65159SKalle Valo 	void __iomem *mem;
845d5c65159SKalle Valo 	int ret;
846d5c65159SKalle Valo 
847d5c65159SKalle Valo 	of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev);
848d5c65159SKalle Valo 	if (!of_id) {
849d5c65159SKalle Valo 		dev_err(&pdev->dev, "failed to find matching device tree id\n");
850d5c65159SKalle Valo 		return -EINVAL;
851d5c65159SKalle Valo 	}
852d5c65159SKalle Valo 
853c8ffcd12SWei Yongjun 	mem = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res);
854d5c65159SKalle Valo 	if (IS_ERR(mem)) {
855d5c65159SKalle Valo 		dev_err(&pdev->dev, "ioremap error\n");
856d5c65159SKalle Valo 		return PTR_ERR(mem);
857d5c65159SKalle Valo 	}
858d5c65159SKalle Valo 
859d5c65159SKalle Valo 	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
860d5c65159SKalle Valo 	if (ret) {
861d5c65159SKalle Valo 		dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n");
862d5c65159SKalle Valo 		return ret;
863d5c65159SKalle Valo 	}
864d5c65159SKalle Valo 
8651ff8ed78SGovind Singh 	ab = ath11k_core_alloc(&pdev->dev, 0, ATH11K_BUS_AHB, &ath11k_ahb_bus_params);
866d5c65159SKalle Valo 	if (!ab) {
867d5c65159SKalle Valo 		dev_err(&pdev->dev, "failed to allocate ath11k base\n");
868d5c65159SKalle Valo 		return -ENOMEM;
869d5c65159SKalle Valo 	}
870d5c65159SKalle Valo 
87131858805SGovind Singh 	ab->hif.ops = &ath11k_ahb_hif_ops;
872d5c65159SKalle Valo 	ab->pdev = pdev;
873d5c65159SKalle Valo 	ab->hw_rev = (enum ath11k_hw_rev)of_id->data;
874d5c65159SKalle Valo 	ab->mem = mem;
875d5c65159SKalle Valo 	ab->mem_len = resource_size(mem_res);
876d5c65159SKalle Valo 	platform_set_drvdata(pdev, ab);
877d5c65159SKalle Valo 
878b8246f88SKalle Valo 	ret = ath11k_core_pre_init(ab);
879b8246f88SKalle Valo 	if (ret)
880b8246f88SKalle Valo 		goto err_core_free;
881b8246f88SKalle Valo 
882d5c65159SKalle Valo 	ret = ath11k_hal_srng_init(ab);
883d5c65159SKalle Valo 	if (ret)
884d5c65159SKalle Valo 		goto err_core_free;
885d5c65159SKalle Valo 
886d5c65159SKalle Valo 	ret = ath11k_ce_alloc_pipes(ab);
887d5c65159SKalle Valo 	if (ret) {
888d5c65159SKalle Valo 		ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
889d5c65159SKalle Valo 		goto err_hal_srng_deinit;
890d5c65159SKalle Valo 	}
891d5c65159SKalle Valo 
892d5c65159SKalle Valo 	ath11k_ahb_init_qmi_ce_config(ab);
893d5c65159SKalle Valo 
894d5c65159SKalle Valo 	ret = ath11k_core_init(ab);
895d5c65159SKalle Valo 	if (ret) {
896d5c65159SKalle Valo 		ath11k_err(ab, "failed to init core: %d\n", ret);
897d5c65159SKalle Valo 		goto err_ce_free;
898d5c65159SKalle Valo 	}
899d5c65159SKalle Valo 
900166e22b3SAnilkumar Kolli 	ret = ath11k_ahb_config_irq(ab);
901166e22b3SAnilkumar Kolli 	if (ret) {
902166e22b3SAnilkumar Kolli 		ath11k_err(ab, "failed to configure irq: %d\n", ret);
903166e22b3SAnilkumar Kolli 		goto err_ce_free;
904166e22b3SAnilkumar Kolli 	}
905166e22b3SAnilkumar Kolli 
906d5c65159SKalle Valo 	return 0;
907d5c65159SKalle Valo 
908d5c65159SKalle Valo err_ce_free:
909d5c65159SKalle Valo 	ath11k_ce_free_pipes(ab);
910d5c65159SKalle Valo 
911d5c65159SKalle Valo err_hal_srng_deinit:
912d5c65159SKalle Valo 	ath11k_hal_srng_deinit(ab);
913d5c65159SKalle Valo 
914d5c65159SKalle Valo err_core_free:
915d5c65159SKalle Valo 	ath11k_core_free(ab);
916d5c65159SKalle Valo 	platform_set_drvdata(pdev, NULL);
917d5c65159SKalle Valo 
918d5c65159SKalle Valo 	return ret;
919d5c65159SKalle Valo }
920d5c65159SKalle Valo 
921d5c65159SKalle Valo static int ath11k_ahb_remove(struct platform_device *pdev)
922d5c65159SKalle Valo {
923d5c65159SKalle Valo 	struct ath11k_base *ab = platform_get_drvdata(pdev);
924d5c65159SKalle Valo 
925d5c65159SKalle Valo 	reinit_completion(&ab->driver_recovery);
926d5c65159SKalle Valo 
927d5c65159SKalle Valo 	if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags))
928d5c65159SKalle Valo 		wait_for_completion_timeout(&ab->driver_recovery,
929d5c65159SKalle Valo 					    ATH11K_AHB_RECOVERY_TIMEOUT);
930d5c65159SKalle Valo 
931d5c65159SKalle Valo 	set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
932d5c65159SKalle Valo 	cancel_work_sync(&ab->restart_work);
933d5c65159SKalle Valo 
934d5c65159SKalle Valo 	ath11k_core_deinit(ab);
935d5c65159SKalle Valo 	ath11k_ahb_free_irq(ab);
936d5c65159SKalle Valo 
937d5c65159SKalle Valo 	ath11k_hal_srng_deinit(ab);
938d5c65159SKalle Valo 	ath11k_ce_free_pipes(ab);
939d5c65159SKalle Valo 	ath11k_core_free(ab);
940d5c65159SKalle Valo 	platform_set_drvdata(pdev, NULL);
941d5c65159SKalle Valo 
942d5c65159SKalle Valo 	return 0;
943d5c65159SKalle Valo }
944d5c65159SKalle Valo 
945d5c65159SKalle Valo static struct platform_driver ath11k_ahb_driver = {
946d5c65159SKalle Valo 	.driver         = {
947d5c65159SKalle Valo 		.name   = "ath11k",
948d5c65159SKalle Valo 		.of_match_table = ath11k_ahb_of_match,
949d5c65159SKalle Valo 	},
950d5c65159SKalle Valo 	.probe  = ath11k_ahb_probe,
951d5c65159SKalle Valo 	.remove = ath11k_ahb_remove,
952d5c65159SKalle Valo };
953d5c65159SKalle Valo 
95431858805SGovind Singh static int ath11k_ahb_init(void)
955d5c65159SKalle Valo {
956d5c65159SKalle Valo 	return platform_driver_register(&ath11k_ahb_driver);
957d5c65159SKalle Valo }
95831858805SGovind Singh module_init(ath11k_ahb_init);
959d5c65159SKalle Valo 
96031858805SGovind Singh static void ath11k_ahb_exit(void)
961d5c65159SKalle Valo {
962d5c65159SKalle Valo 	platform_driver_unregister(&ath11k_ahb_driver);
963d5c65159SKalle Valo }
96431858805SGovind Singh module_exit(ath11k_ahb_exit);
96531858805SGovind Singh 
9666e0355afSGovind Singh MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN AHB devices");
96731858805SGovind Singh MODULE_LICENSE("Dual BSD/GPL");
968