blob: 6fee451e05aa10451475419a1e7bbfd5ff82dfdc [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Komal Seelam02cf2f82016-02-22 20:44:25 +05302 * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080028#include "targcfg.h"
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053029#include "qdf_lock.h"
30#include "qdf_status.h"
31#include "qdf_status.h"
32#include <qdf_atomic.h> /* qdf_atomic_read */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080033#include <targaddrs.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080034#include "hif_io32.h"
35#include <hif.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080036#include "regtable.h"
37#include <a_debug.h>
38#include "hif_main.h"
39#include "ce_api.h"
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053040#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080041#ifdef CONFIG_CNSS
42#include <net/cnss.h>
43#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080044#include "hif_debug.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045
Komal Seelam5584a7c2016-02-24 19:22:48 +053046void
47hif_dump_target_memory(struct hif_opaque_softc *hif_ctx, void *ramdump_base,
48 uint32_t address, uint32_t size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080049{
Komal Seelam644263d2016-02-22 20:45:49 +053050 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080051 uint32_t loc = address;
52 uint32_t val = 0;
53 uint32_t j = 0;
54 u8 *temp = ramdump_base;
55
Houston Hoffmanbac94542016-03-14 21:11:59 -070056 if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
57 return;
58
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080059 while (j < size) {
60 val = hif_read32_mb(scn->mem + loc + j);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053061 qdf_mem_copy(temp, &val, 4);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062 j += 4;
63 temp += 4;
64 }
Houston Hoffmanbac94542016-03-14 21:11:59 -070065
66 Q_TARGET_ACCESS_END(scn);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080067}
68/*
69 * TBDXXX: Should be a function call specific to each Target-type.
70 * This convoluted macro converts from Target CPU Virtual Address
71 * Space to CE Address Space. As part of this process, we
72 * conservatively fetch the current PCIE_BAR. MOST of the time,
73 * this should match the upper bits of PCI space for this device;
74 * but that's not guaranteed.
75 */
76#ifdef QCA_WIFI_3_0
77#define TARG_CPU_SPACE_TO_CE_SPACE(pci_addr, addr) \
78 (scn->mem_pa + addr)
79#else
80#define TARG_CPU_SPACE_TO_CE_SPACE(pci_addr, addr) \
81 (((hif_read32_mb((pci_addr) + \
82 (SOC_CORE_BASE_ADDRESS|CORE_CTRL_ADDRESS)) & 0x7ff) << 21) \
83 | 0x100000 | ((addr) & 0xfffff))
84#endif
Houston Hoffmanfb698ef2016-05-05 19:50:44 -070085
86#define TARG_CPU_SPACE_TO_CE_SPACE_IPQ4019(pci_addr, addr) \
87 (hif_read32_mb((pci_addr)+(WIFICMN_PCIE_BAR_REG_ADDRESS)) \
88 | ((addr) & 0xfffff))
89
90#define TARG_CPU_SPACE_TO_CE_SPACE_AR900B(pci_addr, addr) \
91 (hif_read32_mb((pci_addr)+(WIFICMN_PCIE_BAR_REG_ADDRESS)) \
92 | 0x100000 | ((addr) & 0xfffff))
93
94#define SRAM_BASE_ADDRESS 0xc0000
95#define SRAM_END_ADDRESS 0x100000
96#define WIFI0_IPQ4019_BAR 0xa000000
97#define WIFI1_IPQ4019_BAR 0xa800000
98
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080099/* Wait up to this many Ms for a Diagnostic Access CE operation to complete */
100#define DIAG_ACCESS_CE_TIMEOUT_MS 10
101
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700102/**
103 * get_ce_phy_addr() - get the physical address of an soc virtual address
104 * @sc: hif context
105 * @address: soc virtual address
106 * @target_type: target type being used.
107 *
108 * Return: soc physical address
109 */
110qdf_dma_addr_t get_ce_phy_addr(struct hif_softc *sc, uint32_t address,
111 unsigned int target_type)
112{
113 qdf_dma_addr_t ce_phy_addr;
114 struct hif_softc *scn = sc;
115 unsigned int region = address & 0xfffff;
116 unsigned int bar = address & 0xfff00000;
117 unsigned int sramregion = 0;
118
119 if ((target_type == TARGET_TYPE_IPQ4019) &&
120 (region >= SRAM_BASE_ADDRESS && region <= SRAM_END_ADDRESS)
121 && (bar == WIFI0_IPQ4019_BAR ||
122 bar == WIFI1_IPQ4019_BAR || bar == 0)) {
123 sramregion = 1;
124 }
125
126 if ((target_type == TARGET_TYPE_IPQ4019) && sramregion == 1) {
127 ce_phy_addr =
128 TARG_CPU_SPACE_TO_CE_SPACE_IPQ4019(sc->mem, address);
129 } else if ((target_type == TARGET_TYPE_AR900B) ||
130 (target_type == TARGET_TYPE_QCA9984) ||
131 (target_type == TARGET_TYPE_IPQ4019) ||
132 (target_type == TARGET_TYPE_QCA9888)) {
133 ce_phy_addr =
134 TARG_CPU_SPACE_TO_CE_SPACE_AR900B(sc->mem, address);
135 } else {
136 ce_phy_addr =
137 TARG_CPU_SPACE_TO_CE_SPACE(sc->mem, address);
138 }
139
140 return ce_phy_addr;
141}
142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143/*
144 * Diagnostic read/write access is provided for startup/config/debug usage.
145 * Caller must guarantee proper alignment, when applicable, and single user
146 * at any moment.
147 */
148
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700149#define FW_SRAM_ADDRESS 0x000C0000
150
151QDF_STATUS hif_diag_read_mem(struct hif_opaque_softc *hif_ctx,
152 uint32_t address, uint8_t *data, int nbytes)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800153{
Komal Seelam644263d2016-02-22 20:45:49 +0530154 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700155
Komal Seelam02cf2f82016-02-22 20:44:25 +0530156 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530157 QDF_STATUS status = QDF_STATUS_SUCCESS;
158 qdf_dma_addr_t buf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159 unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
160 unsigned int id;
161 unsigned int flags;
162 struct CE_handle *ce_diag;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530163 qdf_dma_addr_t CE_data; /* Host buffer address in CE space */
164 qdf_dma_addr_t CE_data_base = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800165 void *data_buf = NULL;
166 int i;
167 unsigned int mux_id = 0;
168 unsigned int transaction_id = 0xffff;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530169 qdf_dma_addr_t ce_phy_addr = address;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170 unsigned int toeplitz_hash_result;
171 unsigned int user_flags = 0;
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700172 unsigned int target_type = 0;
173 unsigned int boundary_addr = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800174
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800175 transaction_id = (mux_id & MUX_ID_MASK) |
176 (transaction_id & TRANSACTION_ID_MASK);
177#ifdef QCA_WIFI_3_0
178 user_flags &= DESC_DATA_FLAG_MASK;
179#endif
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700180 target_type = (hif_get_target_info_handle(hif_ctx))->target_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800181
182 /* This code cannot handle reads to non-memory space. Redirect to the
183 * register read fn but preserve the multi word read capability of
184 * this fn
185 */
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700186 if ((target_type == TARGET_TYPE_IPQ4019) ||
187 (target_type == TARGET_TYPE_AR900B) ||
188 (target_type == TARGET_TYPE_QCA9984) ||
189 (target_type == TARGET_TYPE_IPQ4019) ||
190 (target_type == TARGET_TYPE_QCA9888))
191 boundary_addr = FW_SRAM_ADDRESS;
192 else
193 boundary_addr = DRAM_BASE_ADDRESS;
194
195 if (address < boundary_addr) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800196
197 if ((address & 0x3) || ((uintptr_t) data & 0x3))
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530198 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199
200 while ((nbytes >= 4) &&
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530201 (QDF_STATUS_SUCCESS == (status =
Komal Seelam644263d2016-02-22 20:45:49 +0530202 hif_diag_read_access(hif_ctx, address,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800203 (uint32_t *)data)))) {
204
205 nbytes -= sizeof(uint32_t);
206 address += sizeof(uint32_t);
207 data += sizeof(uint32_t);
208
209 }
210
211 return status;
212 }
213 ce_diag = hif_state->ce_diag;
214
215 A_TARGET_ACCESS_LIKELY(scn);
216
217 /*
218 * Allocate a temporary bounce buffer to hold caller's data
219 * to be DMA'ed from Target. This guarantees
220 * 1) 4-byte alignment
221 * 2) Buffer in DMA-able space
222 */
223 orig_nbytes = nbytes;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530224 data_buf = qdf_mem_alloc_consistent(scn->qdf_dev, scn->qdf_dev->dev,
225 orig_nbytes, &CE_data_base);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800226 if (!data_buf) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530227 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228 goto done;
229 }
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530230 qdf_mem_set(data_buf, orig_nbytes, 0);
231 qdf_mem_dma_sync_single_for_device(scn->qdf_dev, CE_data_base,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800232 orig_nbytes, DMA_FROM_DEVICE);
233
234 remaining_bytes = orig_nbytes;
235 CE_data = CE_data_base;
236 while (remaining_bytes) {
237 nbytes = min(remaining_bytes, DIAG_TRANSFER_LIMIT);
238 {
239 status = ce_recv_buf_enqueue(ce_diag, NULL, CE_data);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530240 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800241 goto done;
242 }
243
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700244 if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
245 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800246
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700247 /* convert soc virtual address to physical address */
248 ce_phy_addr = get_ce_phy_addr(scn, address, target_type);
249
250 if (Q_TARGET_ACCESS_END(scn) < 0)
251 return QDF_STATUS_E_FAILURE;
252
253 /* Request CE to send from Target(!)
254 * address to Host buffer */
255 status = ce_send(ce_diag, NULL, ce_phy_addr, nbytes,
256 transaction_id, 0, user_flags);
257 if (status != QDF_STATUS_SUCCESS)
258 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800259
260 i = 0;
261 while (ce_completed_send_next(ce_diag, NULL, NULL, &buf,
262 &completed_nbytes, &id, NULL, NULL,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530263 &toeplitz_hash_result) != QDF_STATUS_SUCCESS) {
264 qdf_mdelay(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800265 if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530266 status = QDF_STATUS_E_BUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800267 goto done;
268 }
269 }
270 if (nbytes != completed_nbytes) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530271 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800272 goto done;
273 }
274 if (buf != ce_phy_addr) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530275 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800276 goto done;
277 }
278
279 i = 0;
280 while (ce_completed_recv_next
281 (ce_diag, NULL, NULL, &buf,
282 &completed_nbytes, &id,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530283 &flags) != QDF_STATUS_SUCCESS) {
284 qdf_mdelay(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800285 if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530286 status = QDF_STATUS_E_BUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800287 goto done;
288 }
289 }
290 if (nbytes != completed_nbytes) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530291 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292 goto done;
293 }
294 if (buf != CE_data) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530295 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296 goto done;
297 }
298
299 remaining_bytes -= nbytes;
300 address += nbytes;
301 CE_data += nbytes;
302 }
303
304done:
305 A_TARGET_ACCESS_UNLIKELY(scn);
306
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530307 if (status == QDF_STATUS_SUCCESS)
308 qdf_mem_copy(data, data_buf, orig_nbytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800309 else
310 HIF_ERROR("%s failure (0x%x)", __func__, address);
311
312 if (data_buf)
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530313 qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev,
314 orig_nbytes, data_buf, CE_data_base, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800315
316 return status;
317}
318
319/* Read 4-byte aligned data from Target memory or register */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530320QDF_STATUS hif_diag_read_access(struct hif_opaque_softc *hif_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800321 uint32_t address, uint32_t *data)
322{
Komal Seelam644263d2016-02-22 20:45:49 +0530323 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800324
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800325 if (address >= DRAM_BASE_ADDRESS) {
326 /* Assume range doesn't cross this boundary */
Komal Seelam644263d2016-02-22 20:45:49 +0530327 return hif_diag_read_mem(hif_ctx, address, (uint8_t *) data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800328 sizeof(uint32_t));
329 } else {
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700330 if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
Houston Hoffman987ab442016-03-14 21:12:02 -0700331 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800332 *data = A_TARGET_READ(scn, address);
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700333 if (Q_TARGET_ACCESS_END(scn) < 0)
Houston Hoffman987ab442016-03-14 21:12:02 -0700334 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800335
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530336 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800337 }
338}
339
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700340/**
341 * hif_diag_write_mem() - write data into the soc memory
342 * @hif_ctx: hif context
343 * @address: soc virtual address
344 * @data: data to copy into the soc address
345 * @nbytes: number of bytes to coppy
346 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530347QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *hif_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800348 uint32_t address, uint8_t *data, int nbytes)
349{
Komal Seelam644263d2016-02-22 20:45:49 +0530350 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Komal Seelam02cf2f82016-02-22 20:44:25 +0530351 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530352 QDF_STATUS status = QDF_STATUS_SUCCESS;
353 qdf_dma_addr_t buf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800354 unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
355 unsigned int id;
356 unsigned int flags;
357 struct CE_handle *ce_diag;
358 void *data_buf = NULL;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530359 qdf_dma_addr_t CE_data; /* Host buffer address in CE space */
360 qdf_dma_addr_t CE_data_base = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800361 int i;
362 unsigned int mux_id = 0;
363 unsigned int transaction_id = 0xffff;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530364 qdf_dma_addr_t ce_phy_addr = address;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365 unsigned int toeplitz_hash_result;
366 unsigned int user_flags = 0;
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700367 unsigned int target_type = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800368 ce_diag = hif_state->ce_diag;
369 transaction_id = (mux_id & MUX_ID_MASK) |
370 (transaction_id & TRANSACTION_ID_MASK);
371#ifdef QCA_WIFI_3_0
372 user_flags &= DESC_DATA_FLAG_MASK;
373#endif
374
375 A_TARGET_ACCESS_LIKELY(scn);
376
377 /*
378 * Allocate a temporary bounce buffer to hold caller's data
379 * to be DMA'ed to Target. This guarantees
380 * 1) 4-byte alignment
381 * 2) Buffer in DMA-able space
382 */
383 orig_nbytes = nbytes;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530384 data_buf = qdf_mem_alloc_consistent(scn->qdf_dev, scn->qdf_dev->dev,
385 orig_nbytes, &CE_data_base);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800386 if (!data_buf) {
387 status = A_NO_MEMORY;
388 goto done;
389 }
390
391 /* Copy caller's data to allocated DMA buf */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530392 qdf_mem_copy(data_buf, data, orig_nbytes);
393 qdf_mem_dma_sync_single_for_device(scn->qdf_dev, CE_data_base,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800394 orig_nbytes, DMA_TO_DEVICE);
395
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700396 target_type = (hif_get_target_info_handle(hif_ctx))->target_type;
397
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700398 if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
Houston Hoffman987ab442016-03-14 21:12:02 -0700399 return QDF_STATUS_E_FAILURE;
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700400
401 /* convert soc virtual address to physical address */
402 ce_phy_addr = get_ce_phy_addr(scn, address, target_type);
403
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700404 if (Q_TARGET_ACCESS_END(scn) < 0)
Houston Hoffman987ab442016-03-14 21:12:02 -0700405 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800406
407 remaining_bytes = orig_nbytes;
408 CE_data = CE_data_base;
409 while (remaining_bytes) {
410 nbytes = min(remaining_bytes, DIAG_TRANSFER_LIMIT);
411
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700412 /* Set up to receive directly into Target(!) address */
413 status = ce_recv_buf_enqueue(ce_diag, NULL, ce_phy_addr);
414 if (status != QDF_STATUS_SUCCESS)
415 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800416
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700417 /*
418 * Request CE to send caller-supplied data that
419 * was copied to bounce buffer to Target(!) address.
420 */
421 status = ce_send(ce_diag, NULL, (qdf_dma_addr_t) CE_data,
422 nbytes, transaction_id, 0, user_flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800423
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700424 if (status != QDF_STATUS_SUCCESS)
425 goto done;
426
427 /* poll for transfer complete */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800428 i = 0;
429 while (ce_completed_send_next(ce_diag, NULL, NULL, &buf,
430 &completed_nbytes, &id,
431 NULL, NULL, &toeplitz_hash_result) !=
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530432 QDF_STATUS_SUCCESS) {
433 qdf_mdelay(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800434 if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530435 status = QDF_STATUS_E_BUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800436 goto done;
437 }
438 }
439
440 if (nbytes != completed_nbytes) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530441 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800442 goto done;
443 }
444
445 if (buf != CE_data) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530446 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800447 goto done;
448 }
449
450 i = 0;
451 while (ce_completed_recv_next
452 (ce_diag, NULL, NULL, &buf,
453 &completed_nbytes, &id,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530454 &flags) != QDF_STATUS_SUCCESS) {
455 qdf_mdelay(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800456 if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530457 status = QDF_STATUS_E_BUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800458 goto done;
459 }
460 }
461
462 if (nbytes != completed_nbytes) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530463 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800464 goto done;
465 }
466
467 if (buf != ce_phy_addr) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530468 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800469 goto done;
470 }
471
472 remaining_bytes -= nbytes;
473 address += nbytes;
474 CE_data += nbytes;
475 }
476
477done:
478 A_TARGET_ACCESS_UNLIKELY(scn);
479
480 if (data_buf) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530481 qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev,
482 orig_nbytes, data_buf, CE_data_base, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800483 }
484
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530485 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800486 HIF_ERROR("%s failure (0x%llu)", __func__,
487 (uint64_t)ce_phy_addr);
488 }
489
490 return status;
491}
492
493/* Write 4B data to Target memory or register */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530494QDF_STATUS hif_diag_write_access(struct hif_opaque_softc *hif_ctx,
Komal Seelam5584a7c2016-02-24 19:22:48 +0530495 uint32_t address, uint32_t data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800496{
Komal Seelam644263d2016-02-22 20:45:49 +0530497 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800498
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800499 if (address >= DRAM_BASE_ADDRESS) {
500 /* Assume range doesn't cross this boundary */
501 uint32_t data_buf = data;
502
Komal Seelam644263d2016-02-22 20:45:49 +0530503 return hif_diag_write_mem(hif_ctx, address,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800504 (uint8_t *) &data_buf,
505 sizeof(uint32_t));
506 } else {
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700507 if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
Houston Hoffman987ab442016-03-14 21:12:02 -0700508 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800509 A_TARGET_WRITE(scn, address, data);
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700510 if (Q_TARGET_ACCESS_END(scn) < 0)
Houston Hoffman987ab442016-03-14 21:12:02 -0700511 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800512
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530513 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800514 }
515}