xref: /wlan-driver/qca-wifi-host-cmn/hif/src/snoc/if_ahb.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC: if_ahb.c
22*5113495bSYour Name  *
23*5113495bSYour Name  * c file for ahb specific implementations.
24*5113495bSYour Name  */
25*5113495bSYour Name 
26*5113495bSYour Name #include "hif.h"
27*5113495bSYour Name #include "target_type.h"
28*5113495bSYour Name #include "hif_main.h"
29*5113495bSYour Name #include "hif_debug.h"
30*5113495bSYour Name #include "hif_io32.h"
31*5113495bSYour Name #include "ce_main.h"
32*5113495bSYour Name #include "ce_api.h"
33*5113495bSYour Name #include "ce_tasklet.h"
34*5113495bSYour Name #include "if_ahb.h"
35*5113495bSYour Name #include "if_pci.h"
36*5113495bSYour Name #include "ahb_api.h"
37*5113495bSYour Name #include "pci_api.h"
38*5113495bSYour Name #include "hif_napi.h"
39*5113495bSYour Name #include "qal_vbus_dev.h"
40*5113495bSYour Name #include "qdf_irq.h"
41*5113495bSYour Name 
42*5113495bSYour Name #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
43*5113495bSYour Name #define IRQF_DISABLED 0x00000020
44*5113495bSYour Name #endif
45*5113495bSYour Name 
46*5113495bSYour Name #define HIF_IC_CE0_IRQ_OFFSET 4
47*5113495bSYour Name #define HIF_IC_MAX_IRQ 58
48*5113495bSYour Name 
49*5113495bSYour Name static uint16_t ic_irqnum[HIF_IC_MAX_IRQ];
50*5113495bSYour Name /* integrated chip irq names */
51*5113495bSYour Name const char *ic_irqname[HIF_IC_MAX_IRQ] = {
52*5113495bSYour Name "misc-pulse1",
53*5113495bSYour Name "misc-latch",
54*5113495bSYour Name "sw-exception",
55*5113495bSYour Name "watchdog",
56*5113495bSYour Name "ce0",
57*5113495bSYour Name "ce1",
58*5113495bSYour Name "ce2",
59*5113495bSYour Name "ce3",
60*5113495bSYour Name "ce4",
61*5113495bSYour Name "ce5",
62*5113495bSYour Name "ce6",
63*5113495bSYour Name "ce7",
64*5113495bSYour Name "ce8",
65*5113495bSYour Name "ce9",
66*5113495bSYour Name "ce10",
67*5113495bSYour Name "ce11",
68*5113495bSYour Name "host2wbm-desc-feed",
69*5113495bSYour Name "host2reo-re-injection",
70*5113495bSYour Name "host2reo-command",
71*5113495bSYour Name "host2rxdma-monitor-ring3",
72*5113495bSYour Name "host2rxdma-monitor-ring2",
73*5113495bSYour Name "host2rxdma-monitor-ring1",
74*5113495bSYour Name "reo2ost-exception",
75*5113495bSYour Name "wbm2host-rx-release",
76*5113495bSYour Name "reo2host-status",
77*5113495bSYour Name "reo2host-destination-ring4",
78*5113495bSYour Name "reo2host-destination-ring3",
79*5113495bSYour Name "reo2host-destination-ring2",
80*5113495bSYour Name "reo2host-destination-ring1",
81*5113495bSYour Name "rxdma2host-monitor-destination-mac3",
82*5113495bSYour Name "rxdma2host-monitor-destination-mac2",
83*5113495bSYour Name "rxdma2host-monitor-destination-mac1",
84*5113495bSYour Name "ppdu-end-interrupts-mac3",
85*5113495bSYour Name "ppdu-end-interrupts-mac2",
86*5113495bSYour Name "ppdu-end-interrupts-mac1",
87*5113495bSYour Name "rxdma2host-monitor-status-ring-mac3",
88*5113495bSYour Name "rxdma2host-monitor-status-ring-mac2",
89*5113495bSYour Name "rxdma2host-monitor-status-ring-mac1",
90*5113495bSYour Name "host2rxdma-host-buf-ring-mac3",
91*5113495bSYour Name "host2rxdma-host-buf-ring-mac2",
92*5113495bSYour Name "host2rxdma-host-buf-ring-mac1",
93*5113495bSYour Name "rxdma2host-destination-ring-mac3",
94*5113495bSYour Name "rxdma2host-destination-ring-mac2",
95*5113495bSYour Name "rxdma2host-destination-ring-mac1",
96*5113495bSYour Name "host2tcl-input-ring4",
97*5113495bSYour Name "host2tcl-input-ring3",
98*5113495bSYour Name "host2tcl-input-ring2",
99*5113495bSYour Name "host2tcl-input-ring1",
100*5113495bSYour Name "wbm2host-tx-completions-ring4",
101*5113495bSYour Name "wbm2host-tx-completions-ring3",
102*5113495bSYour Name "wbm2host-tx-completions-ring2",
103*5113495bSYour Name "wbm2host-tx-completions-ring1",
104*5113495bSYour Name "tcl2host-status-ring",
105*5113495bSYour Name "txmon2host-monitor-destination-mac3",
106*5113495bSYour Name "txmon2host-monitor-destination-mac2",
107*5113495bSYour Name "txmon2host-monitor-destination-mac1",
108*5113495bSYour Name "host2tx-monitor-ring1",
109*5113495bSYour Name };
110*5113495bSYour Name 
111*5113495bSYour Name /**
112*5113495bSYour Name  * hif_ahb_get_irq_name() - get irqname
113*5113495bSYour Name  * @irq_no: irq number
114*5113495bSYour Name  *
115*5113495bSYour Name  * This function gives irqnumber to irqname
116*5113495bSYour Name  * mapping.
117*5113495bSYour Name  *
118*5113495bSYour Name  * Return: irq name
119*5113495bSYour Name  */
hif_ahb_get_irq_name(int irq_no)120*5113495bSYour Name const char *hif_ahb_get_irq_name(int irq_no)
121*5113495bSYour Name {
122*5113495bSYour Name 	return ic_irqname[irq_no];
123*5113495bSYour Name }
124*5113495bSYour Name 
125*5113495bSYour Name /**
126*5113495bSYour Name  * hif_ahb_disable_isr() - disable isr
127*5113495bSYour Name  * @scn: struct hif_softc
128*5113495bSYour Name  *
129*5113495bSYour Name  * This function disables isr and kills tasklets
130*5113495bSYour Name  *
131*5113495bSYour Name  * Return: void
132*5113495bSYour Name  */
hif_ahb_disable_isr(struct hif_softc * scn)133*5113495bSYour Name void hif_ahb_disable_isr(struct hif_softc *scn)
134*5113495bSYour Name {
135*5113495bSYour Name 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
136*5113495bSYour Name 	hif_exec_kill(&scn->osc);
137*5113495bSYour Name 	hif_nointrs(scn);
138*5113495bSYour Name 	ce_tasklet_kill(scn);
139*5113495bSYour Name 	tasklet_kill(&sc->intr_tq);
140*5113495bSYour Name 	qdf_atomic_set(&scn->active_tasklet_cnt, 0);
141*5113495bSYour Name 	qdf_atomic_set(&scn->active_grp_tasklet_cnt, 0);
142*5113495bSYour Name }
143*5113495bSYour Name 
144*5113495bSYour Name /**
145*5113495bSYour Name  * hif_ahb_dump_registers() - dump bus debug registers
146*5113495bSYour Name  * @hif_ctx: struct hif_opaque_softc
147*5113495bSYour Name  *
148*5113495bSYour Name  * This function dumps hif bus debug registers
149*5113495bSYour Name  *
150*5113495bSYour Name  * Return: 0 for success or error code
151*5113495bSYour Name  */
hif_ahb_dump_registers(struct hif_softc * hif_ctx)152*5113495bSYour Name int hif_ahb_dump_registers(struct hif_softc *hif_ctx)
153*5113495bSYour Name {
154*5113495bSYour Name 	int status;
155*5113495bSYour Name 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
156*5113495bSYour Name 
157*5113495bSYour Name 	status = hif_dump_ce_registers(scn);
158*5113495bSYour Name 	if (status)
159*5113495bSYour Name 		hif_err("Dump CE Registers Failed status %d", status);
160*5113495bSYour Name 
161*5113495bSYour Name 	return 0;
162*5113495bSYour Name }
163*5113495bSYour Name 
164*5113495bSYour Name /**
165*5113495bSYour Name  * hif_ahb_close() - hif_bus_close
166*5113495bSYour Name  * @scn: pointer to the hif context.
167*5113495bSYour Name  *
168*5113495bSYour Name  * This is a callback function for hif_bus_close.
169*5113495bSYour Name  *
170*5113495bSYour Name  *
171*5113495bSYour Name  * Return: n/a
172*5113495bSYour Name  */
hif_ahb_close(struct hif_softc * scn)173*5113495bSYour Name void hif_ahb_close(struct hif_softc *scn)
174*5113495bSYour Name {
175*5113495bSYour Name 	hif_ce_close(scn);
176*5113495bSYour Name }
177*5113495bSYour Name 
178*5113495bSYour Name /**
179*5113495bSYour Name  * hif_ahb_open() - hif_ahb open
180*5113495bSYour Name  * @hif_ctx: hif context
181*5113495bSYour Name  * @bus_type: bus type
182*5113495bSYour Name  *
183*5113495bSYour Name  * This is a callback function for hif_bus_open.
184*5113495bSYour Name  *
185*5113495bSYour Name  * Return: QDF_STATUS
186*5113495bSYour Name  */
hif_ahb_open(struct hif_softc * hif_ctx,enum qdf_bus_type bus_type)187*5113495bSYour Name QDF_STATUS hif_ahb_open(struct hif_softc *hif_ctx, enum qdf_bus_type bus_type)
188*5113495bSYour Name {
189*5113495bSYour Name 
190*5113495bSYour Name 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(hif_ctx);
191*5113495bSYour Name 
192*5113495bSYour Name 	qdf_spinlock_create(&sc->irq_lock);
193*5113495bSYour Name 	return hif_ce_open(hif_ctx);
194*5113495bSYour Name }
195*5113495bSYour Name 
196*5113495bSYour Name /**
197*5113495bSYour Name  * hif_ahb_bus_configure() - Configure the bus
198*5113495bSYour Name  * @scn: pointer to the hif context.
199*5113495bSYour Name  *
200*5113495bSYour Name  * This function configure the ahb bus
201*5113495bSYour Name  *
202*5113495bSYour Name  * Return: 0 for success. nonzero for failure.
203*5113495bSYour Name  */
hif_ahb_bus_configure(struct hif_softc * scn)204*5113495bSYour Name int hif_ahb_bus_configure(struct hif_softc *scn)
205*5113495bSYour Name {
206*5113495bSYour Name 	return hif_pci_bus_configure(scn);
207*5113495bSYour Name }
208*5113495bSYour Name 
hif_ahb_get_bar_addr_pld(struct hif_pci_softc * sc,struct device * dev)209*5113495bSYour Name static void hif_ahb_get_bar_addr_pld(struct hif_pci_softc *sc,
210*5113495bSYour Name 				     struct device *dev)
211*5113495bSYour Name {
212*5113495bSYour Name 	struct pld_soc_info info;
213*5113495bSYour Name 	int ret = 0;
214*5113495bSYour Name 
215*5113495bSYour Name 	ret = pld_get_soc_info(dev, &info);
216*5113495bSYour Name 	sc->mem = info.v_addr;
217*5113495bSYour Name 	pld_set_bar_addr(dev, info.v_addr);
218*5113495bSYour Name 	sc->ce_sc.ol_sc.mem    = info.v_addr;
219*5113495bSYour Name 	sc->ce_sc.ol_sc.mem_pa = info.p_addr;
220*5113495bSYour Name }
221*5113495bSYour Name 
hif_ahb_get_soc_cmem_info_pld(struct hif_pci_softc * sc,struct device * dev)222*5113495bSYour Name static void hif_ahb_get_soc_cmem_info_pld(struct hif_pci_softc *sc,
223*5113495bSYour Name 					  struct device *dev)
224*5113495bSYour Name {
225*5113495bSYour Name 	struct pld_soc_info info;
226*5113495bSYour Name 	int ret = 0;
227*5113495bSYour Name 	struct hif_softc *scn = HIF_GET_SOFTC(sc);
228*5113495bSYour Name 
229*5113495bSYour Name 	ret = pld_get_soc_info(dev, &info);
230*5113495bSYour Name 	/* dev_mem_info[0] is for CMEM */
231*5113495bSYour Name 	scn->cmem_start = info.dev_mem_info[0].start;
232*5113495bSYour Name 	scn->cmem_size = info.dev_mem_info[0].size;
233*5113495bSYour Name }
234*5113495bSYour Name 
hif_ahb_configure_irq_by_ceid(struct hif_softc * scn,int ce_id)235*5113495bSYour Name int hif_ahb_configure_irq_by_ceid(struct hif_softc *scn, int ce_id)
236*5113495bSYour Name {
237*5113495bSYour Name 	int ret = 0;
238*5113495bSYour Name 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
239*5113495bSYour Name 	struct platform_device *pdev = (struct platform_device *)sc->pdev;
240*5113495bSYour Name 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
241*5113495bSYour Name 	int irq = 0;
242*5113495bSYour Name 
243*5113495bSYour Name 	if (ce_id >= CE_COUNT_MAX)
244*5113495bSYour Name 		return -EINVAL;
245*5113495bSYour Name 
246*5113495bSYour Name 	ret = pfrm_get_irq(&pdev->dev, (struct qdf_pfm_hndl *)pdev,
247*5113495bSYour Name 			   ic_irqname[HIF_IC_CE0_IRQ_OFFSET + ce_id],
248*5113495bSYour Name 			   HIF_IC_CE0_IRQ_OFFSET + ce_id, &irq);
249*5113495bSYour Name 	if (ret) {
250*5113495bSYour Name 		dev_err(&pdev->dev, "get irq failed\n");
251*5113495bSYour Name 		ret = -EFAULT;
252*5113495bSYour Name 		goto end;
253*5113495bSYour Name 	}
254*5113495bSYour Name 
255*5113495bSYour Name 	ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + ce_id] = irq;
256*5113495bSYour Name 	ret = pfrm_request_irq(&pdev->dev, irq,
257*5113495bSYour Name 			       hif_ahb_interrupt_handler,
258*5113495bSYour Name 			       IRQF_TRIGGER_RISING,
259*5113495bSYour Name 			       ic_irqname[HIF_IC_CE0_IRQ_OFFSET + ce_id],
260*5113495bSYour Name 			       &hif_state->tasklets[ce_id]);
261*5113495bSYour Name 	if (ret) {
262*5113495bSYour Name 		dev_err(&pdev->dev, "ath_request_irq failed\n");
263*5113495bSYour Name 		ret = -EFAULT;
264*5113495bSYour Name 		goto end;
265*5113495bSYour Name 	}
266*5113495bSYour Name 	hif_ahb_irq_enable(scn, ce_id);
267*5113495bSYour Name 
268*5113495bSYour Name end:
269*5113495bSYour Name 	return ret;
270*5113495bSYour Name }
271*5113495bSYour Name 
hif_ahb_configure_irq(struct hif_pci_softc * sc)272*5113495bSYour Name int hif_ahb_configure_irq(struct hif_pci_softc *sc)
273*5113495bSYour Name {
274*5113495bSYour Name 	int ret = 0;
275*5113495bSYour Name 	struct hif_softc *scn = HIF_GET_SOFTC(sc);
276*5113495bSYour Name 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
277*5113495bSYour Name 	struct CE_attr *host_ce_conf = hif_state->host_ce_config;
278*5113495bSYour Name 	int i;
279*5113495bSYour Name 
280*5113495bSYour Name 	/* configure per CE interrupts */
281*5113495bSYour Name 	for (i = 0; i < scn->ce_count; i++) {
282*5113495bSYour Name 		if (host_ce_conf[i].flags & CE_ATTR_DISABLE_INTR)
283*5113495bSYour Name 			continue;
284*5113495bSYour Name 
285*5113495bSYour Name 		if (host_ce_conf[i].flags & CE_ATTR_INIT_ON_DEMAND)
286*5113495bSYour Name 			continue;
287*5113495bSYour Name 
288*5113495bSYour Name 		ret = hif_ahb_configure_irq_by_ceid(scn, i);
289*5113495bSYour Name 		if (ret)
290*5113495bSYour Name 			goto end;
291*5113495bSYour Name 	}
292*5113495bSYour Name 
293*5113495bSYour Name end:
294*5113495bSYour Name 	return ret;
295*5113495bSYour Name }
296*5113495bSYour Name 
hif_ahb_configure_grp_irq(struct hif_softc * scn,struct hif_exec_context * hif_ext_group)297*5113495bSYour Name int hif_ahb_configure_grp_irq(struct hif_softc *scn,
298*5113495bSYour Name 			      struct hif_exec_context *hif_ext_group)
299*5113495bSYour Name {
300*5113495bSYour Name 	int ret = 0;
301*5113495bSYour Name 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
302*5113495bSYour Name 	struct platform_device *pdev = (struct platform_device *)sc->pdev;
303*5113495bSYour Name 	int irq = 0;
304*5113495bSYour Name 	int j;
305*5113495bSYour Name 
306*5113495bSYour Name 	/* configure external interrupts */
307*5113495bSYour Name 	hif_ext_group->irq_enable = &hif_ahb_exec_grp_irq_enable;
308*5113495bSYour Name 	hif_ext_group->irq_disable = &hif_ahb_exec_grp_irq_disable;
309*5113495bSYour Name 	hif_ext_group->irq_name = &hif_ahb_get_irq_name;
310*5113495bSYour Name 	hif_ext_group->work_complete = &hif_dummy_grp_done;
311*5113495bSYour Name 
312*5113495bSYour Name 	for (j = 0; j < hif_ext_group->numirq; j++) {
313*5113495bSYour Name 		ret = pfrm_get_irq(&pdev->dev, (struct qdf_pfm_hndl *)pdev,
314*5113495bSYour Name 				   ic_irqname[hif_ext_group->irq[j]],
315*5113495bSYour Name 				   hif_ext_group->irq[j], &irq);
316*5113495bSYour Name 		if (ret) {
317*5113495bSYour Name 			dev_err(&pdev->dev, "get irq failed\n");
318*5113495bSYour Name 			ret = -EFAULT;
319*5113495bSYour Name 			goto end;
320*5113495bSYour Name 		}
321*5113495bSYour Name 		ic_irqnum[hif_ext_group->irq[j]] = irq;
322*5113495bSYour Name 		hif_ext_group->os_irq[j] = irq;
323*5113495bSYour Name 	}
324*5113495bSYour Name 
325*5113495bSYour Name 	for (j = 0; j < hif_ext_group->numirq; j++) {
326*5113495bSYour Name 		irq = hif_ext_group->os_irq[j];
327*5113495bSYour Name 
328*5113495bSYour Name 		qdf_spin_lock_irqsave(&hif_ext_group->irq_lock);
329*5113495bSYour Name 		qdf_dev_set_irq_status_flags(irq, QDF_IRQ_DISABLE_UNLAZY);
330*5113495bSYour Name 		qdf_spin_unlock_irqrestore(&hif_ext_group->irq_lock);
331*5113495bSYour Name 
332*5113495bSYour Name 		ret = pfrm_request_irq(scn->qdf_dev->dev,
333*5113495bSYour Name 				       irq, hif_ext_group_interrupt_handler,
334*5113495bSYour Name 				       IRQF_TRIGGER_RISING | IRQF_SHARED,
335*5113495bSYour Name 				       ic_irqname[hif_ext_group->irq[j]],
336*5113495bSYour Name 				       hif_ext_group);
337*5113495bSYour Name 		if (ret) {
338*5113495bSYour Name 			dev_err(&pdev->dev, "ath_request_irq failed\n");
339*5113495bSYour Name 			ret = -EFAULT;
340*5113495bSYour Name 			goto end;
341*5113495bSYour Name 		}
342*5113495bSYour Name 	}
343*5113495bSYour Name 
344*5113495bSYour Name 	qdf_spin_lock_irqsave(&hif_ext_group->irq_lock);
345*5113495bSYour Name 	hif_ext_group->irq_requested = true;
346*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&hif_ext_group->irq_lock);
347*5113495bSYour Name end:
348*5113495bSYour Name 	return ret;
349*5113495bSYour Name }
350*5113495bSYour Name 
hif_ahb_deconfigure_grp_irq(struct hif_softc * scn)351*5113495bSYour Name void hif_ahb_deconfigure_grp_irq(struct hif_softc *scn)
352*5113495bSYour Name {
353*5113495bSYour Name 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
354*5113495bSYour Name 	struct hif_exec_context *hif_ext_group;
355*5113495bSYour Name 	int i, j;
356*5113495bSYour Name 	int irq = 0;
357*5113495bSYour Name 
358*5113495bSYour Name 	/* configure external interrupts */
359*5113495bSYour Name 	for (i = 0; i < hif_state->hif_num_extgroup; i++) {
360*5113495bSYour Name 		hif_ext_group = hif_state->hif_ext_group[i];
361*5113495bSYour Name 		if (hif_ext_group->irq_requested == true) {
362*5113495bSYour Name 			qdf_spin_lock_irqsave(&hif_ext_group->irq_lock);
363*5113495bSYour Name 			hif_ext_group->irq_requested = false;
364*5113495bSYour Name 			for (j = 0; j < hif_ext_group->numirq; j++) {
365*5113495bSYour Name 				irq = hif_ext_group->os_irq[j];
366*5113495bSYour Name 				hif_ext_group->irq_enabled = false;
367*5113495bSYour Name 				qdf_dev_clear_irq_status_flags(
368*5113495bSYour Name 							irq,
369*5113495bSYour Name 							QDF_IRQ_DISABLE_UNLAZY);
370*5113495bSYour Name 			}
371*5113495bSYour Name 			qdf_spin_unlock_irqrestore(&hif_ext_group->irq_lock);
372*5113495bSYour Name 
373*5113495bSYour Name 			/* Avoid holding the irq_lock while freeing the irq
374*5113495bSYour Name 			 * as the same lock is being held by the irq handler
375*5113495bSYour Name 			 * while disabling the irq. This causes a deadlock
376*5113495bSYour Name 			 * between free_irq and irq_handler.
377*5113495bSYour Name 			 */
378*5113495bSYour Name 			for (j = 0; j < hif_ext_group->numirq; j++) {
379*5113495bSYour Name 				irq = hif_ext_group->os_irq[j];
380*5113495bSYour Name 				pfrm_free_irq(scn->qdf_dev->dev,
381*5113495bSYour Name 					      irq, hif_ext_group);
382*5113495bSYour Name 			}
383*5113495bSYour Name 		}
384*5113495bSYour Name 	}
385*5113495bSYour Name }
386*5113495bSYour Name 
hif_ahb_interrupt_handler(int irq,void * context)387*5113495bSYour Name irqreturn_t hif_ahb_interrupt_handler(int irq, void *context)
388*5113495bSYour Name {
389*5113495bSYour Name 	struct ce_tasklet_entry *tasklet_entry = context;
390*5113495bSYour Name 	return ce_dispatch_interrupt(tasklet_entry->ce_id, tasklet_entry);
391*5113495bSYour Name }
392*5113495bSYour Name 
393*5113495bSYour Name /**
394*5113495bSYour Name  * hif_ahb_disable_bus() - Disable the bus
395*5113495bSYour Name  * @scn : pointer to the hif context
396*5113495bSYour Name  *
397*5113495bSYour Name  * This function disables the bus and helds the target in reset state
398*5113495bSYour Name  *
399*5113495bSYour Name  * Return: none
400*5113495bSYour Name  */
hif_ahb_disable_bus(struct hif_softc * scn)401*5113495bSYour Name void hif_ahb_disable_bus(struct hif_softc *scn)
402*5113495bSYour Name {
403*5113495bSYour Name 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
404*5113495bSYour Name 	void __iomem *mem;
405*5113495bSYour Name 	struct platform_device *pdev = (struct platform_device *)sc->pdev;
406*5113495bSYour Name 	struct resource *memres = NULL;
407*5113495bSYour Name 	int mem_pa_size = 0;
408*5113495bSYour Name 	struct hif_target_info *tgt_info = NULL;
409*5113495bSYour Name 	struct qdf_vbus_resource *vmres = NULL;
410*5113495bSYour Name 	QDF_STATUS status;
411*5113495bSYour Name 
412*5113495bSYour Name 	tgt_info = &scn->target_info;
413*5113495bSYour Name 	/*Disable WIFI clock input*/
414*5113495bSYour Name 	if (sc->mem) {
415*5113495bSYour Name 		status = pfrm_platform_get_resource(
416*5113495bSYour Name 				scn->qdf_dev->dev,
417*5113495bSYour Name 				(struct qdf_pfm_hndl *)pdev, &vmres,
418*5113495bSYour Name 				IORESOURCE_MEM, 0);
419*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
420*5113495bSYour Name 			hif_info("Failed to get IORESOURCE_MEM");
421*5113495bSYour Name 			return;
422*5113495bSYour Name 		}
423*5113495bSYour Name 		memres = (struct resource *)vmres;
424*5113495bSYour Name 		if (memres)
425*5113495bSYour Name 			mem_pa_size = memres->end - memres->start + 1;
426*5113495bSYour Name 
427*5113495bSYour Name 		if (tgt_info->target_type == TARGET_TYPE_QCA5018 ||
428*5113495bSYour Name 		    tgt_info->target_type == TARGET_TYPE_QCA5332) {
429*5113495bSYour Name 			iounmap(sc->mem_ce);
430*5113495bSYour Name 			sc->mem_ce = NULL;
431*5113495bSYour Name 			scn->mem_ce = NULL;
432*5113495bSYour Name 		}
433*5113495bSYour Name 		if (sc->mem_pmm_base) {
434*5113495bSYour Name 			iounmap(sc->mem_pmm_base);
435*5113495bSYour Name 			sc->mem_pmm_base = NULL;
436*5113495bSYour Name 			scn->mem_pmm_base = NULL;
437*5113495bSYour Name 		}
438*5113495bSYour Name 		if (sc->mem_cmem) {
439*5113495bSYour Name 			iounmap(sc->mem_cmem);
440*5113495bSYour Name 			sc->mem_cmem = NULL;
441*5113495bSYour Name 			scn->mem_cmem = NULL;
442*5113495bSYour Name 		}
443*5113495bSYour Name 		mem = (void __iomem *)sc->mem;
444*5113495bSYour Name 		if (mem) {
445*5113495bSYour Name 			pfrm_devm_iounmap(&pdev->dev, mem);
446*5113495bSYour Name 			pfrm_devm_release_mem_region(&pdev->dev, scn->mem_pa,
447*5113495bSYour Name 						     mem_pa_size);
448*5113495bSYour Name 			sc->mem = NULL;
449*5113495bSYour Name 			pld_set_bar_addr(&pdev->dev, NULL);
450*5113495bSYour Name 		}
451*5113495bSYour Name 	}
452*5113495bSYour Name 	scn->mem = NULL;
453*5113495bSYour Name }
454*5113495bSYour Name 
455*5113495bSYour Name /**
456*5113495bSYour Name  * hif_ahb_enable_bus() - Enable the bus
457*5113495bSYour Name  * @ol_sc: HIF context
458*5113495bSYour Name  * @dev: dev
459*5113495bSYour Name  * @bdev: bus dev
460*5113495bSYour Name  * @bid: bus id
461*5113495bSYour Name  * @type: bus type
462*5113495bSYour Name  *
463*5113495bSYour Name  * This function enables the radio bus by enabling necessary
464*5113495bSYour Name  * clocks and waits for the target to get ready to proceed further
465*5113495bSYour Name  *
466*5113495bSYour Name  * Return: QDF_STATUS
467*5113495bSYour Name  */
hif_ahb_enable_bus(struct hif_softc * ol_sc,struct device * dev,void * bdev,const struct hif_bus_id * bid,enum hif_enable_type type)468*5113495bSYour Name QDF_STATUS hif_ahb_enable_bus(struct hif_softc *ol_sc,
469*5113495bSYour Name 		struct device *dev, void *bdev,
470*5113495bSYour Name 		const struct hif_bus_id *bid,
471*5113495bSYour Name 		enum hif_enable_type type)
472*5113495bSYour Name {
473*5113495bSYour Name 	int ret = 0;
474*5113495bSYour Name 	int hif_type;
475*5113495bSYour Name 	int target_type;
476*5113495bSYour Name 	const struct platform_device_id *id = (struct platform_device_id *)bid;
477*5113495bSYour Name 	struct platform_device *pdev = bdev;
478*5113495bSYour Name 	struct hif_target_info *tgt_info = NULL;
479*5113495bSYour Name 	struct resource *memres = NULL;
480*5113495bSYour Name 	void __iomem *mem = NULL;
481*5113495bSYour Name 	uint32_t revision_id = 0;
482*5113495bSYour Name 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(ol_sc);
483*5113495bSYour Name 	QDF_STATUS status;
484*5113495bSYour Name 	struct qdf_vbus_resource *vmres = NULL;
485*5113495bSYour Name 
486*5113495bSYour Name 	sc->pdev = (struct pci_dev *)pdev;
487*5113495bSYour Name 	sc->dev = &pdev->dev;
488*5113495bSYour Name 	sc->devid = id->driver_data;
489*5113495bSYour Name 
490*5113495bSYour Name 	ret = hif_get_device_type(id->driver_data, revision_id,
491*5113495bSYour Name 			&hif_type, &target_type);
492*5113495bSYour Name 	if (ret < 0) {
493*5113495bSYour Name 		hif_err("Invalid device ret %d id %d revision_id %d",
494*5113495bSYour Name 			ret, (int)id->driver_data, revision_id);
495*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
496*5113495bSYour Name 	}
497*5113495bSYour Name 
498*5113495bSYour Name 	if (target_type == TARGET_TYPE_QCN6122 ||
499*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9160 ||
500*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6432) {
501*5113495bSYour Name 		hif_ahb_get_bar_addr_pld(sc, dev);
502*5113495bSYour Name 	}
503*5113495bSYour Name 
504*5113495bSYour Name 	/* 11BE SoC chipsets Need to call this function to get cmem addr */
505*5113495bSYour Name 	if (target_type == TARGET_TYPE_QCA5332 ||
506*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6432)
507*5113495bSYour Name 		hif_ahb_get_soc_cmem_info_pld(sc, dev);
508*5113495bSYour Name 
509*5113495bSYour Name 	if (target_type == TARGET_TYPE_QCN6122 ||
510*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN9160 ||
511*5113495bSYour Name 	    target_type == TARGET_TYPE_QCN6432) {
512*5113495bSYour Name 		hif_update_irq_ops_with_pci(ol_sc);
513*5113495bSYour Name 	} else {
514*5113495bSYour Name 		status = pfrm_platform_get_resource(&pdev->dev,
515*5113495bSYour Name 						    (struct qdf_pfm_hndl *)pdev,
516*5113495bSYour Name 						    &vmres,
517*5113495bSYour Name 						    IORESOURCE_MEM, 0);
518*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
519*5113495bSYour Name 			hif_err("Failed to get IORESOURCE_MEM");
520*5113495bSYour Name 			return status;
521*5113495bSYour Name 		}
522*5113495bSYour Name 		memres = (struct resource *)vmres;
523*5113495bSYour Name 		if (!memres) {
524*5113495bSYour Name 			hif_err("Failed to get IORESOURCE_MEM");
525*5113495bSYour Name 			return QDF_STATUS_E_IO;
526*5113495bSYour Name 		}
527*5113495bSYour Name 
528*5113495bSYour Name 		/* Arrange for access to Target SoC registers. */
529*5113495bSYour Name #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
530*5113495bSYour Name 		status = pfrm_devm_ioremap_resource(
531*5113495bSYour Name 					dev,
532*5113495bSYour Name 					(struct qdf_vbus_resource *)memres,
533*5113495bSYour Name 					&mem);
534*5113495bSYour Name #else
535*5113495bSYour Name 		status = pfrm_devm_request_and_ioremap(
536*5113495bSYour Name 					dev,
537*5113495bSYour Name 					(struct qdf_vbus_resource *)memres,
538*5113495bSYour Name 					&mem);
539*5113495bSYour Name #endif
540*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
541*5113495bSYour Name 			hif_err("ath: ioremap error");
542*5113495bSYour Name 			ret = PTR_ERR(mem);
543*5113495bSYour Name 			goto err_cleanup1;
544*5113495bSYour Name 		}
545*5113495bSYour Name 
546*5113495bSYour Name 		sc->mem = mem;
547*5113495bSYour Name 		pld_set_bar_addr(dev, mem);
548*5113495bSYour Name 		ol_sc->mem = mem;
549*5113495bSYour Name 		ol_sc->mem_pa = memres->start;
550*5113495bSYour Name 	}
551*5113495bSYour Name 
552*5113495bSYour Name 	ret = pfrm_dma_set_mask(dev, 32);
553*5113495bSYour Name 	if (ret) {
554*5113495bSYour Name 		hif_err("ath: 32-bit DMA not available");
555*5113495bSYour Name 		status = QDF_STATUS_E_IO;
556*5113495bSYour Name 		goto err_cleanup1;
557*5113495bSYour Name 	}
558*5113495bSYour Name 
559*5113495bSYour Name #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
560*5113495bSYour Name 	ret = pfrm_dma_set_mask_and_coherent(dev, 32);
561*5113495bSYour Name #else
562*5113495bSYour Name 	ret = pfrm_dma_set_coherent_mask(dev, 32);
563*5113495bSYour Name #endif
564*5113495bSYour Name 	if (ret) {
565*5113495bSYour Name 		hif_err("Failed to set dma mask error = %d", ret);
566*5113495bSYour Name 		return QDF_STATUS_E_IO;
567*5113495bSYour Name 	}
568*5113495bSYour Name 
569*5113495bSYour Name 	tgt_info = hif_get_target_info_handle((struct hif_opaque_softc *)ol_sc);
570*5113495bSYour Name 
571*5113495bSYour Name 	tgt_info->target_type = target_type;
572*5113495bSYour Name 	hif_register_tbl_attach(ol_sc, hif_type);
573*5113495bSYour Name 	hif_target_register_tbl_attach(ol_sc, target_type);
574*5113495bSYour Name 	/*
575*5113495bSYour Name 	 * In QCA5018 CE region moved to SOC outside WCSS block.
576*5113495bSYour Name 	 * Allocate separate I/O remap to access CE registers.
577*5113495bSYour Name 	 */
578*5113495bSYour Name 	if (tgt_info->target_type == TARGET_TYPE_QCA5018 ||
579*5113495bSYour Name 	    tgt_info->target_type == TARGET_TYPE_QCA5332) {
580*5113495bSYour Name 		struct hif_softc *scn = HIF_GET_SOFTC(sc);
581*5113495bSYour Name 
582*5113495bSYour Name 		sc->mem_ce = qdf_ioremap(HOST_CE_ADDRESS, HOST_CE_SIZE);
583*5113495bSYour Name 		if (IS_ERR(sc->mem_ce)) {
584*5113495bSYour Name 			hif_err("CE: ioremap failed");
585*5113495bSYour Name 			return QDF_STATUS_E_IO;
586*5113495bSYour Name 		}
587*5113495bSYour Name 		ol_sc->mem_ce = sc->mem_ce;
588*5113495bSYour Name 		pld_set_bar_addr(dev, sc->mem_ce);
589*5113495bSYour Name 	}
590*5113495bSYour Name 
591*5113495bSYour Name 	if (tgt_info->target_type == TARGET_TYPE_QCA5332) {
592*5113495bSYour Name 		struct hif_softc *scn = HIF_GET_SOFTC(sc);
593*5113495bSYour Name 
594*5113495bSYour Name 		/*
595*5113495bSYour Name 		 * In QCA5332 CMEM region is outside WCSS block.
596*5113495bSYour Name 		 * Allocate separate I/O remap to access CMEM address.
597*5113495bSYour Name 		 */
598*5113495bSYour Name 		sc->mem_cmem = qdf_ioremap(HOST_CMEM_ADDRESS, HOST_CMEM_SIZE);
599*5113495bSYour Name 		if (IS_ERR(sc->mem_cmem)) {
600*5113495bSYour Name 			hif_err("CE: ioremap failed");
601*5113495bSYour Name 			return QDF_STATUS_E_IO;
602*5113495bSYour Name 		}
603*5113495bSYour Name 		ol_sc->mem_cmem = sc->mem_cmem;
604*5113495bSYour Name 
605*5113495bSYour Name 		/*
606*5113495bSYour Name 		 * PMM SCRATCH Register for QCA5332
607*5113495bSYour Name 		 */
608*5113495bSYour Name 		sc->mem_pmm_base = qdf_ioremap(PMM_SCRATCH_BASE,
609*5113495bSYour Name 						   PMM_SCRATCH_SIZE);
610*5113495bSYour Name 		if (IS_ERR(sc->mem_pmm_base)) {
611*5113495bSYour Name 			hif_err("CE: ioremap failed");
612*5113495bSYour Name 			return QDF_STATUS_E_IO;
613*5113495bSYour Name 		}
614*5113495bSYour Name 		ol_sc->mem_pmm_base = sc->mem_pmm_base;
615*5113495bSYour Name 	}
616*5113495bSYour Name 
617*5113495bSYour Name 	hif_info("X - hif_type = 0x%x, target_type = 0x%x",
618*5113495bSYour Name 		hif_type, target_type);
619*5113495bSYour Name 
620*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
621*5113495bSYour Name err_cleanup1:
622*5113495bSYour Name 	return status;
623*5113495bSYour Name }
624*5113495bSYour Name 
625*5113495bSYour Name /**
626*5113495bSYour Name  * hif_ahb_nointrs() - disable IRQ
627*5113495bSYour Name  *
628*5113495bSYour Name  * @scn: struct hif_softc
629*5113495bSYour Name  *
630*5113495bSYour Name  * This function stops interrupt(s)
631*5113495bSYour Name  *
632*5113495bSYour Name  * Return: none
633*5113495bSYour Name  */
hif_ahb_nointrs(struct hif_softc * scn)634*5113495bSYour Name void hif_ahb_nointrs(struct hif_softc *scn)
635*5113495bSYour Name {
636*5113495bSYour Name 	int i;
637*5113495bSYour Name 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
638*5113495bSYour Name 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
639*5113495bSYour Name 	struct CE_attr *host_ce_conf = hif_state->host_ce_config;
640*5113495bSYour Name 
641*5113495bSYour Name 	scn->free_irq_done = true;
642*5113495bSYour Name 	ce_unregister_irq(hif_state, CE_ALL_BITMAP);
643*5113495bSYour Name 
644*5113495bSYour Name 	if (scn->request_irq_done == false)
645*5113495bSYour Name 		return;
646*5113495bSYour Name 
647*5113495bSYour Name 	if (sc->num_msi_intrs > 0) {
648*5113495bSYour Name 		/* MSI interrupt(s) */
649*5113495bSYour Name 		for (i = 0; i < sc->num_msi_intrs; i++) {
650*5113495bSYour Name 			pfrm_free_irq(scn->qdf_dev->dev, sc->irq + i, sc);
651*5113495bSYour Name 		}
652*5113495bSYour Name 		sc->num_msi_intrs = 0;
653*5113495bSYour Name 	} else {
654*5113495bSYour Name 		if (!scn->per_ce_irq) {
655*5113495bSYour Name 			pfrm_free_irq(scn->qdf_dev->dev, sc->irq, sc);
656*5113495bSYour Name 		} else {
657*5113495bSYour Name 			for (i = 0; i < scn->ce_count; i++) {
658*5113495bSYour Name 				if (host_ce_conf[i].flags
659*5113495bSYour Name 						& CE_ATTR_DISABLE_INTR)
660*5113495bSYour Name 					continue;
661*5113495bSYour Name 				if (!hif_state->tasklets[i].inited)
662*5113495bSYour Name 					continue;
663*5113495bSYour Name 				pfrm_free_irq(
664*5113495bSYour Name 					scn->qdf_dev->dev,
665*5113495bSYour Name 					ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + i],
666*5113495bSYour Name 					&hif_state->tasklets[i]);
667*5113495bSYour Name 			}
668*5113495bSYour Name 			hif_ahb_deconfigure_grp_irq(scn);
669*5113495bSYour Name 		}
670*5113495bSYour Name 	}
671*5113495bSYour Name 	scn->request_irq_done = false;
672*5113495bSYour Name 
673*5113495bSYour Name }
674*5113495bSYour Name 
675*5113495bSYour Name /**
676*5113495bSYour Name  * hif_ahb_irq_enable() - enable copy engine IRQ
677*5113495bSYour Name  * @scn: struct hif_softc
678*5113495bSYour Name  * @ce_id: ce_id
679*5113495bSYour Name  *
680*5113495bSYour Name  * This function enables the interrupt for the radio.
681*5113495bSYour Name  *
682*5113495bSYour Name  * Return: N/A
683*5113495bSYour Name  */
hif_ahb_irq_enable(struct hif_softc * scn,int ce_id)684*5113495bSYour Name void hif_ahb_irq_enable(struct hif_softc *scn, int ce_id)
685*5113495bSYour Name {
686*5113495bSYour Name 	uint32_t regval;
687*5113495bSYour Name 	uint32_t reg_offset = 0;
688*5113495bSYour Name 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
689*5113495bSYour Name 	struct CE_pipe_config *target_ce_conf = &hif_state->target_ce_config[ce_id];
690*5113495bSYour Name 	struct hif_target_info *tgt_info = &scn->target_info;
691*5113495bSYour Name 	void *mem = scn->mem_ce ? scn->mem_ce : scn->mem;
692*5113495bSYour Name 
693*5113495bSYour Name 	if (scn->per_ce_irq) {
694*5113495bSYour Name 		if (target_ce_conf->pipedir & PIPEDIR_OUT) {
695*5113495bSYour Name 			reg_offset = HOST_IE_ADDRESS;
696*5113495bSYour Name 			qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
697*5113495bSYour Name 			regval = hif_read32_mb(scn, mem + reg_offset);
698*5113495bSYour Name 			regval |= HOST_IE_REG1_CE_BIT(ce_id);
699*5113495bSYour Name 			hif_write32_mb(scn, mem + reg_offset, regval);
700*5113495bSYour Name 			qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
701*5113495bSYour Name 		}
702*5113495bSYour Name 		if (target_ce_conf->pipedir & PIPEDIR_IN) {
703*5113495bSYour Name 			reg_offset = HOST_IE_ADDRESS_2;
704*5113495bSYour Name 			qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
705*5113495bSYour Name 			regval = hif_read32_mb(scn, mem + reg_offset);
706*5113495bSYour Name 			regval |= HOST_IE_REG2_CE_BIT(ce_id);
707*5113495bSYour Name 			hif_write32_mb(scn, mem + reg_offset, regval);
708*5113495bSYour Name 			if (tgt_info->target_type == TARGET_TYPE_QCA8074 ||
709*5113495bSYour Name 			    tgt_info->target_type == TARGET_TYPE_QCA8074V2 ||
710*5113495bSYour Name 			    tgt_info->target_type == TARGET_TYPE_QCA9574 ||
711*5113495bSYour Name 			    tgt_info->target_type == TARGET_TYPE_QCA5332 ||
712*5113495bSYour Name 			    tgt_info->target_type == TARGET_TYPE_QCA5018 ||
713*5113495bSYour Name 			    tgt_info->target_type == TARGET_TYPE_QCA6018) {
714*5113495bSYour Name 				/* Enable destination ring interrupts for
715*5113495bSYour Name 				 * 8074, 8074V2, 6018 and 50xx
716*5113495bSYour Name 				 */
717*5113495bSYour Name 				regval = hif_read32_mb(scn, mem +
718*5113495bSYour Name 					HOST_IE_ADDRESS_3);
719*5113495bSYour Name 				regval |= HOST_IE_REG3_CE_BIT(ce_id);
720*5113495bSYour Name 
721*5113495bSYour Name 				hif_write32_mb(scn, mem +
722*5113495bSYour Name 					       HOST_IE_ADDRESS_3, regval);
723*5113495bSYour Name 			}
724*5113495bSYour Name 			qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
725*5113495bSYour Name 		}
726*5113495bSYour Name 	} else {
727*5113495bSYour Name 		hif_pci_irq_enable(scn, ce_id);
728*5113495bSYour Name 	}
729*5113495bSYour Name }
730*5113495bSYour Name 
731*5113495bSYour Name /**
732*5113495bSYour Name  * hif_ahb_irq_disable() - disable copy engine IRQ
733*5113495bSYour Name  * @scn: struct hif_softc
734*5113495bSYour Name  * @ce_id: ce_id
735*5113495bSYour Name  *
736*5113495bSYour Name  * Return: N/A
737*5113495bSYour Name  */
hif_ahb_irq_disable(struct hif_softc * scn,int ce_id)738*5113495bSYour Name void hif_ahb_irq_disable(struct hif_softc *scn, int ce_id)
739*5113495bSYour Name {
740*5113495bSYour Name 	uint32_t regval;
741*5113495bSYour Name 	uint32_t reg_offset = 0;
742*5113495bSYour Name 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
743*5113495bSYour Name 	struct CE_pipe_config *target_ce_conf = &hif_state->target_ce_config[ce_id];
744*5113495bSYour Name 	struct hif_target_info *tgt_info = &scn->target_info;
745*5113495bSYour Name 	void *mem = scn->mem_ce ? scn->mem_ce : scn->mem;
746*5113495bSYour Name 
747*5113495bSYour Name 	if (scn->per_ce_irq) {
748*5113495bSYour Name 		if (target_ce_conf->pipedir & PIPEDIR_OUT) {
749*5113495bSYour Name 			reg_offset = HOST_IE_ADDRESS;
750*5113495bSYour Name 			qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
751*5113495bSYour Name 			regval = hif_read32_mb(scn, mem + reg_offset);
752*5113495bSYour Name 			regval &= ~HOST_IE_REG1_CE_BIT(ce_id);
753*5113495bSYour Name 			hif_write32_mb(scn, mem + reg_offset, regval);
754*5113495bSYour Name 			qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
755*5113495bSYour Name 		}
756*5113495bSYour Name 		if (target_ce_conf->pipedir & PIPEDIR_IN) {
757*5113495bSYour Name 			reg_offset = HOST_IE_ADDRESS_2;
758*5113495bSYour Name 			qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
759*5113495bSYour Name 			regval = hif_read32_mb(scn, mem + reg_offset);
760*5113495bSYour Name 			regval &= ~HOST_IE_REG2_CE_BIT(ce_id);
761*5113495bSYour Name 			hif_write32_mb(scn, mem + reg_offset, regval);
762*5113495bSYour Name 			if (tgt_info->target_type == TARGET_TYPE_QCA8074 ||
763*5113495bSYour Name 			    tgt_info->target_type == TARGET_TYPE_QCA8074V2 ||
764*5113495bSYour Name 			    tgt_info->target_type == TARGET_TYPE_QCA9574 ||
765*5113495bSYour Name 			    tgt_info->target_type == TARGET_TYPE_QCA5332 ||
766*5113495bSYour Name 			    tgt_info->target_type == TARGET_TYPE_QCA5018 ||
767*5113495bSYour Name 			    tgt_info->target_type == TARGET_TYPE_QCA6018) {
768*5113495bSYour Name 				/* Disable destination ring interrupts for
769*5113495bSYour Name 				 * 8074, 8074V2, 6018 and 50xx
770*5113495bSYour Name 				 */
771*5113495bSYour Name 				regval = hif_read32_mb(scn, mem +
772*5113495bSYour Name 					HOST_IE_ADDRESS_3);
773*5113495bSYour Name 				regval &= ~HOST_IE_REG3_CE_BIT(ce_id);
774*5113495bSYour Name 
775*5113495bSYour Name 				hif_write32_mb(scn, mem +
776*5113495bSYour Name 					       HOST_IE_ADDRESS_3, regval);
777*5113495bSYour Name 			}
778*5113495bSYour Name 			qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
779*5113495bSYour Name 		}
780*5113495bSYour Name 	}
781*5113495bSYour Name }
782*5113495bSYour Name 
hif_ahb_exec_grp_irq_disable(struct hif_exec_context * hif_ext_group)783*5113495bSYour Name void hif_ahb_exec_grp_irq_disable(struct hif_exec_context *hif_ext_group)
784*5113495bSYour Name {
785*5113495bSYour Name 	int i;
786*5113495bSYour Name 
787*5113495bSYour Name 	qdf_spin_lock_irqsave(&hif_ext_group->irq_lock);
788*5113495bSYour Name 	if (hif_ext_group->irq_enabled) {
789*5113495bSYour Name 		for (i = 0; i < hif_ext_group->numirq; i++) {
790*5113495bSYour Name 			disable_irq_nosync(hif_ext_group->os_irq[i]);
791*5113495bSYour Name 		}
792*5113495bSYour Name 		hif_ext_group->irq_enabled = false;
793*5113495bSYour Name 	}
794*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&hif_ext_group->irq_lock);
795*5113495bSYour Name }
796*5113495bSYour Name 
hif_ahb_exec_grp_irq_enable(struct hif_exec_context * hif_ext_group)797*5113495bSYour Name void hif_ahb_exec_grp_irq_enable(struct hif_exec_context *hif_ext_group)
798*5113495bSYour Name {
799*5113495bSYour Name 	int i;
800*5113495bSYour Name 
801*5113495bSYour Name 	qdf_spin_lock_irqsave(&hif_ext_group->irq_lock);
802*5113495bSYour Name 	if (hif_ext_group->irq_requested && !hif_ext_group->irq_enabled) {
803*5113495bSYour Name 		for (i = 0; i < hif_ext_group->numirq; i++) {
804*5113495bSYour Name 			enable_irq(hif_ext_group->os_irq[i]);
805*5113495bSYour Name 		}
806*5113495bSYour Name 		hif_ext_group->irq_enabled = true;
807*5113495bSYour Name 	}
808*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&hif_ext_group->irq_lock);
809*5113495bSYour Name }
810*5113495bSYour Name 
811*5113495bSYour Name /**
812*5113495bSYour Name  * hif_ahb_needs_bmi() - return true if the soc needs bmi through the driver
813*5113495bSYour Name  * @scn: hif context
814*5113495bSYour Name  *
815*5113495bSYour Name  * Return: true if soc needs driver bmi otherwise false
816*5113495bSYour Name  */
hif_ahb_needs_bmi(struct hif_softc * scn)817*5113495bSYour Name bool hif_ahb_needs_bmi(struct hif_softc *scn)
818*5113495bSYour Name {
819*5113495bSYour Name 	return !ce_srng_based(scn);
820*5113495bSYour Name }
821*5113495bSYour Name 
822*5113495bSYour Name /**
823*5113495bSYour Name  * hif_display_ahb_irq_regs() - prints the host interrupt enable (IE) regs
824*5113495bSYour Name  * @scn: hif context
825*5113495bSYour Name  *
826*5113495bSYour Name  * Return: None
827*5113495bSYour Name  */
828*5113495bSYour Name 
hif_display_ahb_irq_regs(struct hif_softc * scn)829*5113495bSYour Name void hif_display_ahb_irq_regs(struct hif_softc *scn)
830*5113495bSYour Name {
831*5113495bSYour Name 	uint32_t regval;
832*5113495bSYour Name 	void *mem = scn->mem_ce ? scn->mem_ce : scn->mem;
833*5113495bSYour Name 	struct hif_target_info *tgt_info = &scn->target_info;
834*5113495bSYour Name 
835*5113495bSYour Name 	if (tgt_info->target_type == TARGET_TYPE_QCN6122 ||
836*5113495bSYour Name 	    tgt_info->target_type == TARGET_TYPE_QCN9160 ||
837*5113495bSYour Name 	    tgt_info->target_type == TARGET_TYPE_QCN6432) {
838*5113495bSYour Name 		return;
839*5113495bSYour Name 	}
840*5113495bSYour Name 	if (scn->per_ce_irq) {
841*5113495bSYour Name 		regval = hif_read32_mb(scn, mem + HOST_IE_ADDRESS);
842*5113495bSYour Name 		hif_nofl_err("IRQ enable register value 0x%08x", regval);
843*5113495bSYour Name 
844*5113495bSYour Name 		regval = hif_read32_mb(scn, mem + HOST_IE_ADDRESS_2);
845*5113495bSYour Name 		hif_nofl_err("IRQ enable register 2 value 0x%08x", regval);
846*5113495bSYour Name 
847*5113495bSYour Name 		if (tgt_info->target_type == TARGET_TYPE_QCA8074 ||
848*5113495bSYour Name 		    tgt_info->target_type == TARGET_TYPE_QCA8074V2 ||
849*5113495bSYour Name 		    tgt_info->target_type == TARGET_TYPE_QCA9574 ||
850*5113495bSYour Name 		    tgt_info->target_type == TARGET_TYPE_QCA5332 ||
851*5113495bSYour Name 		    tgt_info->target_type == TARGET_TYPE_QCA5018 ||
852*5113495bSYour Name 		    tgt_info->target_type == TARGET_TYPE_QCA6018) {
853*5113495bSYour Name 			regval = hif_read32_mb(scn, mem +
854*5113495bSYour Name 					       HOST_IE_ADDRESS_3);
855*5113495bSYour Name 			hif_nofl_err("IRQ enable register 3 value 0x%08x",
856*5113495bSYour Name 				     regval);
857*5113495bSYour Name 		}
858*5113495bSYour Name 	}
859*5113495bSYour Name }
860*5113495bSYour Name 
hif_ahb_display_stats(struct hif_softc * scn)861*5113495bSYour Name void hif_ahb_display_stats(struct hif_softc *scn)
862*5113495bSYour Name {
863*5113495bSYour Name 	if (!scn) {
864*5113495bSYour Name 		hif_err("hif_scn null");
865*5113495bSYour Name 		return;
866*5113495bSYour Name 	}
867*5113495bSYour Name 	hif_display_ahb_irq_regs(scn);
868*5113495bSYour Name 	hif_display_ce_stats(scn);
869*5113495bSYour Name }
870*5113495bSYour Name 
hif_ahb_clear_stats(struct hif_softc * scn)871*5113495bSYour Name void hif_ahb_clear_stats(struct hif_softc *scn)
872*5113495bSYour Name {
873*5113495bSYour Name 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
874*5113495bSYour Name 
875*5113495bSYour Name 	if (!hif_state) {
876*5113495bSYour Name 		hif_err("hif_state null");
877*5113495bSYour Name 		return;
878*5113495bSYour Name 	}
879*5113495bSYour Name 	hif_clear_ce_stats(hif_state);
880*5113495bSYour Name }
881