1*5113495bSYour Name /*
2*5113495bSYour Name * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
3*5113495bSYour Name * Copyright (c) 2022 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 #include "targcfg.h"
21*5113495bSYour Name #include "target_type.h"
22*5113495bSYour Name #include "qdf_lock.h"
23*5113495bSYour Name #include "qdf_status.h"
24*5113495bSYour Name #include "qdf_status.h"
25*5113495bSYour Name #include <qdf_atomic.h> /* qdf_atomic_read */
26*5113495bSYour Name #include <targaddrs.h>
27*5113495bSYour Name #include "hif_io32.h"
28*5113495bSYour Name #include <hif.h>
29*5113495bSYour Name #include "regtable.h"
30*5113495bSYour Name #include <a_debug.h>
31*5113495bSYour Name #include "hif_main.h"
32*5113495bSYour Name #include "ce_api.h"
33*5113495bSYour Name #include "qdf_trace.h"
34*5113495bSYour Name #include "hif_debug.h"
35*5113495bSYour Name #include "qdf_module.h"
36*5113495bSYour Name
37*5113495bSYour Name void
hif_ce_dump_target_memory(struct hif_softc * scn,void * ramdump_base,uint32_t address,uint32_t size)38*5113495bSYour Name hif_ce_dump_target_memory(struct hif_softc *scn, void *ramdump_base,
39*5113495bSYour Name uint32_t address, uint32_t size)
40*5113495bSYour Name {
41*5113495bSYour Name uint32_t loc = address;
42*5113495bSYour Name uint32_t val = 0;
43*5113495bSYour Name uint32_t j = 0;
44*5113495bSYour Name u8 *temp = ramdump_base;
45*5113495bSYour Name
46*5113495bSYour Name if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
47*5113495bSYour Name return;
48*5113495bSYour Name
49*5113495bSYour Name while (j < size) {
50*5113495bSYour Name val = hif_read32_mb(scn, scn->mem + loc + j);
51*5113495bSYour Name qdf_mem_copy(temp, &val, 4);
52*5113495bSYour Name j += 4;
53*5113495bSYour Name temp += 4;
54*5113495bSYour Name }
55*5113495bSYour Name
56*5113495bSYour Name Q_TARGET_ACCESS_END(scn);
57*5113495bSYour Name }
58*5113495bSYour Name /*
59*5113495bSYour Name * TBDXXX: Should be a function call specific to each Target-type.
60*5113495bSYour Name * This convoluted macro converts from Target CPU Virtual Address
61*5113495bSYour Name * Space to CE Address Space. As part of this process, we
62*5113495bSYour Name * conservatively fetch the current PCIE_BAR. MOST of the time,
63*5113495bSYour Name * this should match the upper bits of PCI space for this device;
64*5113495bSYour Name * but that's not guaranteed.
65*5113495bSYour Name */
66*5113495bSYour Name #ifdef QCA_WIFI_3_0
67*5113495bSYour Name #define TARG_CPU_SPACE_TO_CE_SPACE(sc, pci_addr, addr) \
68*5113495bSYour Name (scn->mem_pa + addr)
69*5113495bSYour Name #else
70*5113495bSYour Name #define TARG_CPU_SPACE_TO_CE_SPACE(sc, pci_addr, addr) \
71*5113495bSYour Name (((hif_read32_mb(sc, (pci_addr) + \
72*5113495bSYour Name (SOC_CORE_BASE_ADDRESS|CORE_CTRL_ADDRESS)) & 0x7ff) << 21) \
73*5113495bSYour Name | 0x100000 | ((addr) & 0xfffff))
74*5113495bSYour Name #endif
75*5113495bSYour Name
76*5113495bSYour Name #define TARG_CPU_SPACE_TO_CE_SPACE_AR900B(scn, pci_addr, addr) \
77*5113495bSYour Name (hif_read32_mb(scn, (pci_addr) + (WIFICMN_PCIE_BAR_REG_ADDRESS)) \
78*5113495bSYour Name | 0x100000 | ((addr) & 0xfffff))
79*5113495bSYour Name
80*5113495bSYour Name #define SRAM_BASE_ADDRESS 0xc0000
81*5113495bSYour Name #define SRAM_END_ADDRESS 0x100000
82*5113495bSYour Name
83*5113495bSYour Name /* Wait up to this many Ms for a Diagnostic Access CE operation to complete */
84*5113495bSYour Name #define DIAG_ACCESS_CE_TIMEOUT_MS 10
85*5113495bSYour Name
86*5113495bSYour Name /**
87*5113495bSYour Name * get_ce_phy_addr() - get the physical address of an soc virtual address
88*5113495bSYour Name * @sc: hif context
89*5113495bSYour Name * @address: soc virtual address
90*5113495bSYour Name * @target_type: target type being used.
91*5113495bSYour Name *
92*5113495bSYour Name * Return: soc physical address
93*5113495bSYour Name */
get_ce_phy_addr(struct hif_softc * sc,uint32_t address,unsigned int target_type)94*5113495bSYour Name static qdf_dma_addr_t get_ce_phy_addr(struct hif_softc *sc, uint32_t address,
95*5113495bSYour Name unsigned int target_type)
96*5113495bSYour Name {
97*5113495bSYour Name qdf_dma_addr_t ce_phy_addr;
98*5113495bSYour Name struct hif_softc *scn = sc;
99*5113495bSYour Name
100*5113495bSYour Name if ((target_type == TARGET_TYPE_AR900B) ||
101*5113495bSYour Name (target_type == TARGET_TYPE_QCA9984) ||
102*5113495bSYour Name (target_type == TARGET_TYPE_QCA9888)) {
103*5113495bSYour Name ce_phy_addr =
104*5113495bSYour Name TARG_CPU_SPACE_TO_CE_SPACE_AR900B(sc, sc->mem, address);
105*5113495bSYour Name } else {
106*5113495bSYour Name ce_phy_addr =
107*5113495bSYour Name TARG_CPU_SPACE_TO_CE_SPACE(sc, sc->mem, address);
108*5113495bSYour Name }
109*5113495bSYour Name
110*5113495bSYour Name return ce_phy_addr;
111*5113495bSYour Name }
112*5113495bSYour Name
113*5113495bSYour Name /*
114*5113495bSYour Name * Diagnostic read/write access is provided for startup/config/debug usage.
115*5113495bSYour Name * Caller must guarantee proper alignment, when applicable, and single user
116*5113495bSYour Name * at any moment.
117*5113495bSYour Name */
118*5113495bSYour Name
119*5113495bSYour Name #define FW_SRAM_ADDRESS 0x000C0000
120*5113495bSYour Name
hif_diag_read_mem(struct hif_opaque_softc * hif_ctx,uint32_t address,uint8_t * data,int nbytes)121*5113495bSYour Name QDF_STATUS hif_diag_read_mem(struct hif_opaque_softc *hif_ctx,
122*5113495bSYour Name uint32_t address, uint8_t *data, int nbytes)
123*5113495bSYour Name {
124*5113495bSYour Name struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
125*5113495bSYour Name
126*5113495bSYour Name struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
127*5113495bSYour Name QDF_STATUS status = QDF_STATUS_SUCCESS;
128*5113495bSYour Name qdf_dma_addr_t buf;
129*5113495bSYour Name unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
130*5113495bSYour Name unsigned int id;
131*5113495bSYour Name unsigned int flags;
132*5113495bSYour Name struct CE_handle *ce_diag;
133*5113495bSYour Name qdf_dma_addr_t CE_data; /* Host buffer address in CE space */
134*5113495bSYour Name qdf_dma_addr_t CE_data_base = 0;
135*5113495bSYour Name void *data_buf = NULL;
136*5113495bSYour Name int i;
137*5113495bSYour Name unsigned int mux_id = 0;
138*5113495bSYour Name unsigned int transaction_id = 0xffff;
139*5113495bSYour Name qdf_dma_addr_t ce_phy_addr = address;
140*5113495bSYour Name unsigned int toeplitz_hash_result;
141*5113495bSYour Name unsigned int user_flags = 0;
142*5113495bSYour Name unsigned int target_type = 0;
143*5113495bSYour Name unsigned int boundary_addr = 0;
144*5113495bSYour Name
145*5113495bSYour Name ce_diag = hif_state->ce_diag;
146*5113495bSYour Name if (!ce_diag) {
147*5113495bSYour Name hif_err("DIAG CE not present");
148*5113495bSYour Name return QDF_STATUS_E_INVAL;
149*5113495bSYour Name }
150*5113495bSYour Name /* not supporting diag ce on srng based systems, therefore we know this
151*5113495bSYour Name * isn't an srng based system */
152*5113495bSYour Name
153*5113495bSYour Name transaction_id = (mux_id & MUX_ID_MASK) |
154*5113495bSYour Name (transaction_id & TRANSACTION_ID_MASK);
155*5113495bSYour Name #ifdef QCA_WIFI_3_0
156*5113495bSYour Name user_flags &= DESC_DATA_FLAG_MASK;
157*5113495bSYour Name #endif
158*5113495bSYour Name target_type = (hif_get_target_info_handle(hif_ctx))->target_type;
159*5113495bSYour Name
160*5113495bSYour Name /* This code cannot handle reads to non-memory space. Redirect to the
161*5113495bSYour Name * register read fn but preserve the multi word read capability of
162*5113495bSYour Name * this fn
163*5113495bSYour Name */
164*5113495bSYour Name if ((target_type == TARGET_TYPE_AR900B) ||
165*5113495bSYour Name (target_type == TARGET_TYPE_QCA9984) ||
166*5113495bSYour Name (target_type == TARGET_TYPE_AR9888) ||
167*5113495bSYour Name (target_type == TARGET_TYPE_QCA9888))
168*5113495bSYour Name boundary_addr = FW_SRAM_ADDRESS;
169*5113495bSYour Name else
170*5113495bSYour Name boundary_addr = DRAM_BASE_ADDRESS;
171*5113495bSYour Name
172*5113495bSYour Name if (address < boundary_addr) {
173*5113495bSYour Name
174*5113495bSYour Name if ((address & 0x3) || ((uintptr_t) data & 0x3))
175*5113495bSYour Name return QDF_STATUS_E_INVAL;
176*5113495bSYour Name
177*5113495bSYour Name while ((nbytes >= 4) &&
178*5113495bSYour Name (QDF_STATUS_SUCCESS == (status =
179*5113495bSYour Name hif_diag_read_access(hif_ctx, address,
180*5113495bSYour Name (uint32_t *)data)))) {
181*5113495bSYour Name
182*5113495bSYour Name nbytes -= sizeof(uint32_t);
183*5113495bSYour Name address += sizeof(uint32_t);
184*5113495bSYour Name data += sizeof(uint32_t);
185*5113495bSYour Name
186*5113495bSYour Name }
187*5113495bSYour Name
188*5113495bSYour Name return status;
189*5113495bSYour Name }
190*5113495bSYour Name
191*5113495bSYour Name A_TARGET_ACCESS_LIKELY(scn);
192*5113495bSYour Name
193*5113495bSYour Name /*
194*5113495bSYour Name * Allocate a temporary bounce buffer to hold caller's data
195*5113495bSYour Name * to be DMA'ed from Target. This guarantees
196*5113495bSYour Name * 1) 4-byte alignment
197*5113495bSYour Name * 2) Buffer in DMA-able space
198*5113495bSYour Name */
199*5113495bSYour Name orig_nbytes = nbytes;
200*5113495bSYour Name data_buf = qdf_mem_alloc_consistent(scn->qdf_dev, scn->qdf_dev->dev,
201*5113495bSYour Name orig_nbytes, &CE_data_base);
202*5113495bSYour Name if (!data_buf) {
203*5113495bSYour Name status = QDF_STATUS_E_NOMEM;
204*5113495bSYour Name goto done;
205*5113495bSYour Name }
206*5113495bSYour Name qdf_mem_zero(data_buf, orig_nbytes);
207*5113495bSYour Name
208*5113495bSYour Name remaining_bytes = orig_nbytes;
209*5113495bSYour Name CE_data = CE_data_base;
210*5113495bSYour Name while (remaining_bytes) {
211*5113495bSYour Name nbytes = min(remaining_bytes, DIAG_TRANSFER_LIMIT);
212*5113495bSYour Name {
213*5113495bSYour Name status = ce_recv_buf_enqueue(ce_diag, NULL, CE_data);
214*5113495bSYour Name if (status != QDF_STATUS_SUCCESS)
215*5113495bSYour Name goto done;
216*5113495bSYour Name }
217*5113495bSYour Name
218*5113495bSYour Name if (Q_TARGET_ACCESS_BEGIN(scn) < 0) {
219*5113495bSYour Name status = QDF_STATUS_E_FAILURE;
220*5113495bSYour Name goto done;
221*5113495bSYour Name }
222*5113495bSYour Name
223*5113495bSYour Name /* convert soc virtual address to physical address */
224*5113495bSYour Name ce_phy_addr = get_ce_phy_addr(scn, address, target_type);
225*5113495bSYour Name
226*5113495bSYour Name if (Q_TARGET_ACCESS_END(scn) < 0) {
227*5113495bSYour Name status = QDF_STATUS_E_FAILURE;
228*5113495bSYour Name goto done;
229*5113495bSYour Name }
230*5113495bSYour Name
231*5113495bSYour Name /* Request CE to send from Target(!)
232*5113495bSYour Name * address to Host buffer
233*5113495bSYour Name */
234*5113495bSYour Name status = ce_send(ce_diag, NULL, ce_phy_addr, nbytes,
235*5113495bSYour Name transaction_id, 0, user_flags);
236*5113495bSYour Name if (status != QDF_STATUS_SUCCESS)
237*5113495bSYour Name goto done;
238*5113495bSYour Name
239*5113495bSYour Name i = 0;
240*5113495bSYour Name while (ce_completed_send_next(ce_diag, NULL, NULL, &buf,
241*5113495bSYour Name &completed_nbytes, &id, NULL, NULL,
242*5113495bSYour Name &toeplitz_hash_result) != QDF_STATUS_SUCCESS) {
243*5113495bSYour Name qdf_mdelay(1);
244*5113495bSYour Name if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
245*5113495bSYour Name status = QDF_STATUS_E_BUSY;
246*5113495bSYour Name goto done;
247*5113495bSYour Name }
248*5113495bSYour Name }
249*5113495bSYour Name if (nbytes != completed_nbytes) {
250*5113495bSYour Name status = QDF_STATUS_E_FAILURE;
251*5113495bSYour Name goto done;
252*5113495bSYour Name }
253*5113495bSYour Name if (buf != ce_phy_addr) {
254*5113495bSYour Name status = QDF_STATUS_E_FAILURE;
255*5113495bSYour Name goto done;
256*5113495bSYour Name }
257*5113495bSYour Name
258*5113495bSYour Name i = 0;
259*5113495bSYour Name while (ce_completed_recv_next
260*5113495bSYour Name (ce_diag, NULL, NULL, &buf,
261*5113495bSYour Name &completed_nbytes, &id,
262*5113495bSYour Name &flags) != QDF_STATUS_SUCCESS) {
263*5113495bSYour Name qdf_mdelay(1);
264*5113495bSYour Name if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
265*5113495bSYour Name status = QDF_STATUS_E_BUSY;
266*5113495bSYour Name goto done;
267*5113495bSYour Name }
268*5113495bSYour Name }
269*5113495bSYour Name if (nbytes != completed_nbytes) {
270*5113495bSYour Name status = QDF_STATUS_E_FAILURE;
271*5113495bSYour Name goto done;
272*5113495bSYour Name }
273*5113495bSYour Name if (buf != CE_data) {
274*5113495bSYour Name status = QDF_STATUS_E_FAILURE;
275*5113495bSYour Name goto done;
276*5113495bSYour Name }
277*5113495bSYour Name
278*5113495bSYour Name remaining_bytes -= nbytes;
279*5113495bSYour Name address += nbytes;
280*5113495bSYour Name CE_data += nbytes;
281*5113495bSYour Name }
282*5113495bSYour Name
283*5113495bSYour Name done:
284*5113495bSYour Name A_TARGET_ACCESS_UNLIKELY(scn);
285*5113495bSYour Name
286*5113495bSYour Name if (status == QDF_STATUS_SUCCESS)
287*5113495bSYour Name qdf_mem_copy(data, data_buf, orig_nbytes);
288*5113495bSYour Name else
289*5113495bSYour Name hif_err("Failure (0x%x)", address);
290*5113495bSYour Name
291*5113495bSYour Name if (data_buf)
292*5113495bSYour Name qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev,
293*5113495bSYour Name orig_nbytes, data_buf, CE_data_base, 0);
294*5113495bSYour Name
295*5113495bSYour Name return status;
296*5113495bSYour Name }
297*5113495bSYour Name qdf_export_symbol(hif_diag_read_mem);
298*5113495bSYour Name
299*5113495bSYour Name /* Read 4-byte aligned data from Target memory or register */
hif_diag_read_access(struct hif_opaque_softc * hif_ctx,uint32_t address,uint32_t * data)300*5113495bSYour Name QDF_STATUS hif_diag_read_access(struct hif_opaque_softc *hif_ctx,
301*5113495bSYour Name uint32_t address, uint32_t *data)
302*5113495bSYour Name {
303*5113495bSYour Name struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
304*5113495bSYour Name
305*5113495bSYour Name if (address >= DRAM_BASE_ADDRESS) {
306*5113495bSYour Name /* Assume range doesn't cross this boundary */
307*5113495bSYour Name return hif_diag_read_mem(hif_ctx, address, (uint8_t *) data,
308*5113495bSYour Name sizeof(uint32_t));
309*5113495bSYour Name } else {
310*5113495bSYour Name if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
311*5113495bSYour Name return QDF_STATUS_E_FAILURE;
312*5113495bSYour Name *data = A_TARGET_READ(scn, address);
313*5113495bSYour Name if (Q_TARGET_ACCESS_END(scn) < 0)
314*5113495bSYour Name return QDF_STATUS_E_FAILURE;
315*5113495bSYour Name
316*5113495bSYour Name return QDF_STATUS_SUCCESS;
317*5113495bSYour Name }
318*5113495bSYour Name }
319*5113495bSYour Name
320*5113495bSYour Name /**
321*5113495bSYour Name * hif_diag_write_mem() - write data into the soc memory
322*5113495bSYour Name * @hif_ctx: hif context
323*5113495bSYour Name * @address: soc virtual address
324*5113495bSYour Name * @data: data to copy into the soc address
325*5113495bSYour Name * @nbytes: number of bytes to copy
326*5113495bSYour Name */
hif_diag_write_mem(struct hif_opaque_softc * hif_ctx,uint32_t address,uint8_t * data,int nbytes)327*5113495bSYour Name QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *hif_ctx,
328*5113495bSYour Name uint32_t address, uint8_t *data, int nbytes)
329*5113495bSYour Name {
330*5113495bSYour Name struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
331*5113495bSYour Name struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx);
332*5113495bSYour Name QDF_STATUS status = QDF_STATUS_SUCCESS;
333*5113495bSYour Name qdf_dma_addr_t buf;
334*5113495bSYour Name unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
335*5113495bSYour Name unsigned int id;
336*5113495bSYour Name unsigned int flags;
337*5113495bSYour Name struct CE_handle *ce_diag;
338*5113495bSYour Name void *data_buf = NULL;
339*5113495bSYour Name qdf_dma_addr_t CE_data; /* Host buffer address in CE space */
340*5113495bSYour Name qdf_dma_addr_t CE_data_base = 0;
341*5113495bSYour Name int i;
342*5113495bSYour Name unsigned int mux_id = 0;
343*5113495bSYour Name unsigned int transaction_id = 0xffff;
344*5113495bSYour Name qdf_dma_addr_t ce_phy_addr = address;
345*5113495bSYour Name unsigned int toeplitz_hash_result;
346*5113495bSYour Name unsigned int user_flags = 0;
347*5113495bSYour Name unsigned int target_type = 0;
348*5113495bSYour Name
349*5113495bSYour Name ce_diag = hif_state->ce_diag;
350*5113495bSYour Name if (!ce_diag) {
351*5113495bSYour Name hif_err("DIAG CE not present");
352*5113495bSYour Name return QDF_STATUS_E_INVAL;
353*5113495bSYour Name }
354*5113495bSYour Name /* not supporting diag ce on srng based systems, therefore we know this
355*5113495bSYour Name * isn't an srng based system */
356*5113495bSYour Name
357*5113495bSYour Name transaction_id = (mux_id & MUX_ID_MASK) |
358*5113495bSYour Name (transaction_id & TRANSACTION_ID_MASK);
359*5113495bSYour Name #ifdef QCA_WIFI_3_0
360*5113495bSYour Name user_flags &= DESC_DATA_FLAG_MASK;
361*5113495bSYour Name #endif
362*5113495bSYour Name
363*5113495bSYour Name A_TARGET_ACCESS_LIKELY(scn);
364*5113495bSYour Name
365*5113495bSYour Name /*
366*5113495bSYour Name * Allocate a temporary bounce buffer to hold caller's data
367*5113495bSYour Name * to be DMA'ed to Target. This guarantees
368*5113495bSYour Name * 1) 4-byte alignment
369*5113495bSYour Name * 2) Buffer in DMA-able space
370*5113495bSYour Name */
371*5113495bSYour Name orig_nbytes = nbytes;
372*5113495bSYour Name data_buf = qdf_mem_alloc_consistent(scn->qdf_dev, scn->qdf_dev->dev,
373*5113495bSYour Name orig_nbytes, &CE_data_base);
374*5113495bSYour Name if (!data_buf) {
375*5113495bSYour Name status = QDF_STATUS_E_NOMEM;
376*5113495bSYour Name goto done;
377*5113495bSYour Name }
378*5113495bSYour Name
379*5113495bSYour Name /* Copy caller's data to allocated DMA buf */
380*5113495bSYour Name qdf_mem_copy(data_buf, data, orig_nbytes);
381*5113495bSYour Name qdf_mem_dma_sync_single_for_device(scn->qdf_dev, CE_data_base,
382*5113495bSYour Name orig_nbytes, DMA_TO_DEVICE);
383*5113495bSYour Name
384*5113495bSYour Name target_type = (hif_get_target_info_handle(hif_ctx))->target_type;
385*5113495bSYour Name
386*5113495bSYour Name if (Q_TARGET_ACCESS_BEGIN(scn) < 0) {
387*5113495bSYour Name status = QDF_STATUS_E_FAILURE;
388*5113495bSYour Name goto done;
389*5113495bSYour Name }
390*5113495bSYour Name
391*5113495bSYour Name /* convert soc virtual address to physical address */
392*5113495bSYour Name ce_phy_addr = get_ce_phy_addr(scn, address, target_type);
393*5113495bSYour Name
394*5113495bSYour Name if (Q_TARGET_ACCESS_END(scn) < 0) {
395*5113495bSYour Name status = QDF_STATUS_E_FAILURE;
396*5113495bSYour Name goto done;
397*5113495bSYour Name }
398*5113495bSYour Name
399*5113495bSYour Name remaining_bytes = orig_nbytes;
400*5113495bSYour Name CE_data = CE_data_base;
401*5113495bSYour Name while (remaining_bytes) {
402*5113495bSYour Name nbytes = min(remaining_bytes, DIAG_TRANSFER_LIMIT);
403*5113495bSYour Name
404*5113495bSYour Name /* Set up to receive directly into Target(!) address */
405*5113495bSYour Name status = ce_recv_buf_enqueue(ce_diag, NULL, ce_phy_addr);
406*5113495bSYour Name if (status != QDF_STATUS_SUCCESS)
407*5113495bSYour Name goto done;
408*5113495bSYour Name
409*5113495bSYour Name /*
410*5113495bSYour Name * Request CE to send caller-supplied data that
411*5113495bSYour Name * was copied to bounce buffer to Target(!) address.
412*5113495bSYour Name */
413*5113495bSYour Name status = ce_send(ce_diag, NULL, (qdf_dma_addr_t) CE_data,
414*5113495bSYour Name nbytes, transaction_id, 0, user_flags);
415*5113495bSYour Name
416*5113495bSYour Name if (status != QDF_STATUS_SUCCESS)
417*5113495bSYour Name goto done;
418*5113495bSYour Name
419*5113495bSYour Name /* poll for transfer complete */
420*5113495bSYour Name i = 0;
421*5113495bSYour Name while (ce_completed_send_next(ce_diag, NULL, NULL, &buf,
422*5113495bSYour Name &completed_nbytes, &id,
423*5113495bSYour Name NULL, NULL, &toeplitz_hash_result) !=
424*5113495bSYour Name QDF_STATUS_SUCCESS) {
425*5113495bSYour Name qdf_mdelay(1);
426*5113495bSYour Name if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
427*5113495bSYour Name status = QDF_STATUS_E_BUSY;
428*5113495bSYour Name goto done;
429*5113495bSYour Name }
430*5113495bSYour Name }
431*5113495bSYour Name
432*5113495bSYour Name if (nbytes != completed_nbytes) {
433*5113495bSYour Name status = QDF_STATUS_E_FAILURE;
434*5113495bSYour Name goto done;
435*5113495bSYour Name }
436*5113495bSYour Name
437*5113495bSYour Name if (buf != CE_data) {
438*5113495bSYour Name status = QDF_STATUS_E_FAILURE;
439*5113495bSYour Name goto done;
440*5113495bSYour Name }
441*5113495bSYour Name
442*5113495bSYour Name i = 0;
443*5113495bSYour Name while (ce_completed_recv_next
444*5113495bSYour Name (ce_diag, NULL, NULL, &buf,
445*5113495bSYour Name &completed_nbytes, &id,
446*5113495bSYour Name &flags) != QDF_STATUS_SUCCESS) {
447*5113495bSYour Name qdf_mdelay(1);
448*5113495bSYour Name if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
449*5113495bSYour Name status = QDF_STATUS_E_BUSY;
450*5113495bSYour Name goto done;
451*5113495bSYour Name }
452*5113495bSYour Name }
453*5113495bSYour Name
454*5113495bSYour Name if (nbytes != completed_nbytes) {
455*5113495bSYour Name status = QDF_STATUS_E_FAILURE;
456*5113495bSYour Name goto done;
457*5113495bSYour Name }
458*5113495bSYour Name
459*5113495bSYour Name if (buf != ce_phy_addr) {
460*5113495bSYour Name status = QDF_STATUS_E_FAILURE;
461*5113495bSYour Name goto done;
462*5113495bSYour Name }
463*5113495bSYour Name
464*5113495bSYour Name remaining_bytes -= nbytes;
465*5113495bSYour Name address += nbytes;
466*5113495bSYour Name CE_data += nbytes;
467*5113495bSYour Name }
468*5113495bSYour Name
469*5113495bSYour Name done:
470*5113495bSYour Name A_TARGET_ACCESS_UNLIKELY(scn);
471*5113495bSYour Name
472*5113495bSYour Name if (data_buf) {
473*5113495bSYour Name qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev,
474*5113495bSYour Name orig_nbytes, data_buf, CE_data_base, 0);
475*5113495bSYour Name }
476*5113495bSYour Name
477*5113495bSYour Name if (status != QDF_STATUS_SUCCESS) {
478*5113495bSYour Name hif_err("Failure (0x%llx)", (uint64_t)ce_phy_addr);
479*5113495bSYour Name }
480*5113495bSYour Name
481*5113495bSYour Name return status;
482*5113495bSYour Name }
483*5113495bSYour Name
484*5113495bSYour Name /* Write 4B data to Target memory or register */
hif_diag_write_access(struct hif_opaque_softc * hif_ctx,uint32_t address,uint32_t data)485*5113495bSYour Name QDF_STATUS hif_diag_write_access(struct hif_opaque_softc *hif_ctx,
486*5113495bSYour Name uint32_t address, uint32_t data)
487*5113495bSYour Name {
488*5113495bSYour Name struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
489*5113495bSYour Name
490*5113495bSYour Name if (address >= DRAM_BASE_ADDRESS) {
491*5113495bSYour Name /* Assume range doesn't cross this boundary */
492*5113495bSYour Name uint32_t data_buf = data;
493*5113495bSYour Name
494*5113495bSYour Name return hif_diag_write_mem(hif_ctx, address,
495*5113495bSYour Name (uint8_t *) &data_buf,
496*5113495bSYour Name sizeof(uint32_t));
497*5113495bSYour Name } else {
498*5113495bSYour Name if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
499*5113495bSYour Name return QDF_STATUS_E_FAILURE;
500*5113495bSYour Name A_TARGET_WRITE(scn, address, data);
501*5113495bSYour Name if (Q_TARGET_ACCESS_END(scn) < 0)
502*5113495bSYour Name return QDF_STATUS_E_FAILURE;
503*5113495bSYour Name
504*5113495bSYour Name return QDF_STATUS_SUCCESS;
505*5113495bSYour Name }
506*5113495bSYour Name }
507