blob: 7bbb9db299c9d1a1074dceaa58563b4c4afc23f2 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
hangtian3a6512a2019-01-16 17:32:06 +08002 * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019#include "targcfg.h"
Pratik Gandhi034cb7c2017-11-10 16:46:06 +053020#include "target_type.h"
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053021#include "qdf_lock.h"
22#include "qdf_status.h"
23#include "qdf_status.h"
24#include <qdf_atomic.h> /* qdf_atomic_read */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080025#include <targaddrs.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080026#include "hif_io32.h"
27#include <hif.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080028#include "regtable.h"
29#include <a_debug.h>
30#include "hif_main.h"
31#include "ce_api.h"
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053032#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080033#include "hif_debug.h"
Pratik Gandhidc82a772018-01-30 18:57:05 +053034#include "qdf_module.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080035
Komal Seelam5584a7c2016-02-24 19:22:48 +053036void
Poddar, Siddarthe41943f2016-04-27 15:33:48 +053037hif_ce_dump_target_memory(struct hif_softc *scn, void *ramdump_base,
Komal Seelam5584a7c2016-02-24 19:22:48 +053038 uint32_t address, uint32_t size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080039{
40 uint32_t loc = address;
41 uint32_t val = 0;
42 uint32_t j = 0;
43 u8 *temp = ramdump_base;
44
Houston Hoffmanbac94542016-03-14 21:11:59 -070045 if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
46 return;
47
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048 while (j < size) {
Nirav Shahf1e3fb52018-06-12 14:39:34 +053049 val = hif_read32_mb(scn, scn->mem + loc + j);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053050 qdf_mem_copy(temp, &val, 4);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080051 j += 4;
52 temp += 4;
53 }
Houston Hoffmanbac94542016-03-14 21:11:59 -070054
55 Q_TARGET_ACCESS_END(scn);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080056}
57/*
58 * TBDXXX: Should be a function call specific to each Target-type.
59 * This convoluted macro converts from Target CPU Virtual Address
60 * Space to CE Address Space. As part of this process, we
61 * conservatively fetch the current PCIE_BAR. MOST of the time,
62 * this should match the upper bits of PCI space for this device;
63 * but that's not guaranteed.
64 */
65#ifdef QCA_WIFI_3_0
Nirav Shahf1e3fb52018-06-12 14:39:34 +053066#define TARG_CPU_SPACE_TO_CE_SPACE(sc, pci_addr, addr) \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080067 (scn->mem_pa + addr)
68#else
Nirav Shahf1e3fb52018-06-12 14:39:34 +053069#define TARG_CPU_SPACE_TO_CE_SPACE(sc, pci_addr, addr) \
70 (((hif_read32_mb(sc, (pci_addr) + \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080071 (SOC_CORE_BASE_ADDRESS|CORE_CTRL_ADDRESS)) & 0x7ff) << 21) \
72 | 0x100000 | ((addr) & 0xfffff))
73#endif
Houston Hoffmanfb698ef2016-05-05 19:50:44 -070074
Nirav Shahf1e3fb52018-06-12 14:39:34 +053075#define TARG_CPU_SPACE_TO_CE_SPACE_IPQ4019(scn, pci_addr, addr) \
76 (hif_read32_mb(scn, (pci_addr) + (WIFICMN_PCIE_BAR_REG_ADDRESS)) \
Houston Hoffmanfb698ef2016-05-05 19:50:44 -070077 | ((addr) & 0xfffff))
78
Nirav Shahf1e3fb52018-06-12 14:39:34 +053079#define TARG_CPU_SPACE_TO_CE_SPACE_AR900B(scn, pci_addr, addr) \
80 (hif_read32_mb(scn, (pci_addr) + (WIFICMN_PCIE_BAR_REG_ADDRESS)) \
Houston Hoffmanfb698ef2016-05-05 19:50:44 -070081 | 0x100000 | ((addr) & 0xfffff))
82
83#define SRAM_BASE_ADDRESS 0xc0000
84#define SRAM_END_ADDRESS 0x100000
85#define WIFI0_IPQ4019_BAR 0xa000000
86#define WIFI1_IPQ4019_BAR 0xa800000
87
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080088/* Wait up to this many Ms for a Diagnostic Access CE operation to complete */
89#define DIAG_ACCESS_CE_TIMEOUT_MS 10
90
Houston Hoffmanfb698ef2016-05-05 19:50:44 -070091/**
92 * get_ce_phy_addr() - get the physical address of an soc virtual address
93 * @sc: hif context
94 * @address: soc virtual address
95 * @target_type: target type being used.
96 *
97 * Return: soc physical address
98 */
Jeff Johnson6950fdb2016-10-07 13:00:59 -070099static qdf_dma_addr_t get_ce_phy_addr(struct hif_softc *sc, uint32_t address,
100 unsigned int target_type)
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700101{
102 qdf_dma_addr_t ce_phy_addr;
103 struct hif_softc *scn = sc;
104 unsigned int region = address & 0xfffff;
105 unsigned int bar = address & 0xfff00000;
106 unsigned int sramregion = 0;
107
108 if ((target_type == TARGET_TYPE_IPQ4019) &&
109 (region >= SRAM_BASE_ADDRESS && region <= SRAM_END_ADDRESS)
110 && (bar == WIFI0_IPQ4019_BAR ||
111 bar == WIFI1_IPQ4019_BAR || bar == 0)) {
112 sramregion = 1;
113 }
114
115 if ((target_type == TARGET_TYPE_IPQ4019) && sramregion == 1) {
Nirav Shahf1e3fb52018-06-12 14:39:34 +0530116 ce_phy_addr = TARG_CPU_SPACE_TO_CE_SPACE_IPQ4019(sc, sc->mem,
117 address);
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700118 } else if ((target_type == TARGET_TYPE_AR900B) ||
119 (target_type == TARGET_TYPE_QCA9984) ||
120 (target_type == TARGET_TYPE_IPQ4019) ||
121 (target_type == TARGET_TYPE_QCA9888)) {
122 ce_phy_addr =
Nirav Shahf1e3fb52018-06-12 14:39:34 +0530123 TARG_CPU_SPACE_TO_CE_SPACE_AR900B(sc, sc->mem, address);
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700124 } else {
125 ce_phy_addr =
Nirav Shahf1e3fb52018-06-12 14:39:34 +0530126 TARG_CPU_SPACE_TO_CE_SPACE(sc, sc->mem, address);
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700127 }
128
129 return ce_phy_addr;
130}
131
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800132/*
133 * Diagnostic read/write access is provided for startup/config/debug usage.
134 * Caller must guarantee proper alignment, when applicable, and single user
135 * at any moment.
136 */
137
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700138#define FW_SRAM_ADDRESS 0x000C0000
139
140QDF_STATUS hif_diag_read_mem(struct hif_opaque_softc *hif_ctx,
141 uint32_t address, uint8_t *data, int nbytes)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800142{
Komal Seelam644263d2016-02-22 20:45:49 +0530143 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700144
Komal Seelam02cf2f82016-02-22 20:44:25 +0530145 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530146 QDF_STATUS status = QDF_STATUS_SUCCESS;
147 qdf_dma_addr_t buf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148 unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
149 unsigned int id;
150 unsigned int flags;
151 struct CE_handle *ce_diag;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530152 qdf_dma_addr_t CE_data; /* Host buffer address in CE space */
153 qdf_dma_addr_t CE_data_base = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800154 void *data_buf = NULL;
155 int i;
156 unsigned int mux_id = 0;
157 unsigned int transaction_id = 0xffff;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530158 qdf_dma_addr_t ce_phy_addr = address;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159 unsigned int toeplitz_hash_result;
160 unsigned int user_flags = 0;
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700161 unsigned int target_type = 0;
162 unsigned int boundary_addr = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530164 ce_diag = hif_state->ce_diag;
165 if (ce_diag == NULL) {
166 HIF_ERROR("%s: DIAG CE not present", __func__);
167 return QDF_STATUS_E_INVAL;
168 }
Yun Park3fb36442017-08-17 17:37:53 -0700169 /* not supporting diag ce on srng based systems, therefore we know this
170 * isn't an srng based system */
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530171
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800172 transaction_id = (mux_id & MUX_ID_MASK) |
173 (transaction_id & TRANSACTION_ID_MASK);
174#ifdef QCA_WIFI_3_0
175 user_flags &= DESC_DATA_FLAG_MASK;
176#endif
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700177 target_type = (hif_get_target_info_handle(hif_ctx))->target_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178
179 /* This code cannot handle reads to non-memory space. Redirect to the
180 * register read fn but preserve the multi word read capability of
181 * this fn
182 */
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700183 if ((target_type == TARGET_TYPE_IPQ4019) ||
184 (target_type == TARGET_TYPE_AR900B) ||
185 (target_type == TARGET_TYPE_QCA9984) ||
Aravind Narasimhane79befa2016-06-24 12:03:15 +0530186 (target_type == TARGET_TYPE_AR9888) ||
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700187 (target_type == TARGET_TYPE_QCA9888))
188 boundary_addr = FW_SRAM_ADDRESS;
189 else
190 boundary_addr = DRAM_BASE_ADDRESS;
191
192 if (address < boundary_addr) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800193
194 if ((address & 0x3) || ((uintptr_t) data & 0x3))
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530195 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800196
197 while ((nbytes >= 4) &&
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530198 (QDF_STATUS_SUCCESS == (status =
Komal Seelam644263d2016-02-22 20:45:49 +0530199 hif_diag_read_access(hif_ctx, address,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800200 (uint32_t *)data)))) {
201
202 nbytes -= sizeof(uint32_t);
203 address += sizeof(uint32_t);
204 data += sizeof(uint32_t);
205
206 }
207
208 return status;
209 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210
211 A_TARGET_ACCESS_LIKELY(scn);
212
213 /*
214 * Allocate a temporary bounce buffer to hold caller's data
215 * to be DMA'ed from Target. This guarantees
216 * 1) 4-byte alignment
217 * 2) Buffer in DMA-able space
218 */
219 orig_nbytes = nbytes;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530220 data_buf = qdf_mem_alloc_consistent(scn->qdf_dev, scn->qdf_dev->dev,
221 orig_nbytes, &CE_data_base);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 if (!data_buf) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530223 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224 goto done;
225 }
hangtian3a6512a2019-01-16 17:32:06 +0800226 qdf_mem_zero(data_buf, orig_nbytes);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530227 qdf_mem_dma_sync_single_for_device(scn->qdf_dev, CE_data_base,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228 orig_nbytes, DMA_FROM_DEVICE);
229
230 remaining_bytes = orig_nbytes;
231 CE_data = CE_data_base;
232 while (remaining_bytes) {
233 nbytes = min(remaining_bytes, DIAG_TRANSFER_LIMIT);
234 {
235 status = ce_recv_buf_enqueue(ce_diag, NULL, CE_data);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530236 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800237 goto done;
238 }
239
Poddar, Siddarth55d6da02017-03-31 18:42:54 +0530240 if (Q_TARGET_ACCESS_BEGIN(scn) < 0) {
241 status = QDF_STATUS_E_FAILURE;
242 goto done;
243 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800244
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700245 /* convert soc virtual address to physical address */
246 ce_phy_addr = get_ce_phy_addr(scn, address, target_type);
247
Poddar, Siddarth55d6da02017-03-31 18:42:54 +0530248 if (Q_TARGET_ACCESS_END(scn) < 0) {
249 status = QDF_STATUS_E_FAILURE;
250 goto done;
251 }
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700252
253 /* Request CE to send from Target(!)
Manikandan Mohanafd6e882017-04-07 17:46:41 -0700254 * address to Host buffer
255 */
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700256 status = ce_send(ce_diag, NULL, ce_phy_addr, nbytes,
257 transaction_id, 0, user_flags);
258 if (status != QDF_STATUS_SUCCESS)
259 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800260
261 i = 0;
262 while (ce_completed_send_next(ce_diag, NULL, NULL, &buf,
263 &completed_nbytes, &id, NULL, NULL,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530264 &toeplitz_hash_result) != QDF_STATUS_SUCCESS) {
265 qdf_mdelay(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800266 if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530267 status = QDF_STATUS_E_BUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800268 goto done;
269 }
270 }
271 if (nbytes != completed_nbytes) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530272 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800273 goto done;
274 }
275 if (buf != ce_phy_addr) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530276 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800277 goto done;
278 }
279
280 i = 0;
281 while (ce_completed_recv_next
282 (ce_diag, NULL, NULL, &buf,
283 &completed_nbytes, &id,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530284 &flags) != QDF_STATUS_SUCCESS) {
285 qdf_mdelay(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286 if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530287 status = QDF_STATUS_E_BUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800288 goto done;
289 }
290 }
291 if (nbytes != completed_nbytes) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530292 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293 goto done;
294 }
295 if (buf != CE_data) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530296 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800297 goto done;
298 }
299
300 remaining_bytes -= nbytes;
301 address += nbytes;
302 CE_data += nbytes;
303 }
304
305done:
306 A_TARGET_ACCESS_UNLIKELY(scn);
307
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530308 if (status == QDF_STATUS_SUCCESS)
309 qdf_mem_copy(data, data_buf, orig_nbytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800310 else
311 HIF_ERROR("%s failure (0x%x)", __func__, address);
312
313 if (data_buf)
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530314 qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev,
315 orig_nbytes, data_buf, CE_data_base, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316
317 return status;
318}
Pratik Gandhidc82a772018-01-30 18:57:05 +0530319qdf_export_symbol(hif_diag_read_mem);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800320
321/* Read 4-byte aligned data from Target memory or register */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530322QDF_STATUS hif_diag_read_access(struct hif_opaque_softc *hif_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800323 uint32_t address, uint32_t *data)
324{
Komal Seelam644263d2016-02-22 20:45:49 +0530325 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800326
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800327 if (address >= DRAM_BASE_ADDRESS) {
328 /* Assume range doesn't cross this boundary */
Komal Seelam644263d2016-02-22 20:45:49 +0530329 return hif_diag_read_mem(hif_ctx, address, (uint8_t *) data,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800330 sizeof(uint32_t));
331 } else {
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700332 if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
Houston Hoffman987ab442016-03-14 21:12:02 -0700333 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800334 *data = A_TARGET_READ(scn, address);
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700335 if (Q_TARGET_ACCESS_END(scn) < 0)
Houston Hoffman987ab442016-03-14 21:12:02 -0700336 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800337
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530338 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800339 }
340}
341
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700342/**
343 * hif_diag_write_mem() - write data into the soc memory
344 * @hif_ctx: hif context
345 * @address: soc virtual address
346 * @data: data to copy into the soc address
347 * @nbytes: number of bytes to coppy
348 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530349QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *hif_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800350 uint32_t address, uint8_t *data, int nbytes)
351{
Komal Seelam644263d2016-02-22 20:45:49 +0530352 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Komal Seelam02cf2f82016-02-22 20:44:25 +0530353 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530354 QDF_STATUS status = QDF_STATUS_SUCCESS;
355 qdf_dma_addr_t buf;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800356 unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
357 unsigned int id;
358 unsigned int flags;
359 struct CE_handle *ce_diag;
360 void *data_buf = NULL;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530361 qdf_dma_addr_t CE_data; /* Host buffer address in CE space */
362 qdf_dma_addr_t CE_data_base = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800363 int i;
364 unsigned int mux_id = 0;
365 unsigned int transaction_id = 0xffff;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530366 qdf_dma_addr_t ce_phy_addr = address;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800367 unsigned int toeplitz_hash_result;
368 unsigned int user_flags = 0;
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700369 unsigned int target_type = 0;
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530370
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800371 ce_diag = hif_state->ce_diag;
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530372 if (ce_diag == NULL) {
373 HIF_ERROR("%s: DIAG CE not present", __func__);
374 return QDF_STATUS_E_INVAL;
375 }
Yun Park3fb36442017-08-17 17:37:53 -0700376 /* not supporting diag ce on srng based systems, therefore we know this
377 * isn't an srng based system */
Kiran Venkatappae17e3b62017-02-10 16:31:49 +0530378
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800379 transaction_id = (mux_id & MUX_ID_MASK) |
380 (transaction_id & TRANSACTION_ID_MASK);
381#ifdef QCA_WIFI_3_0
382 user_flags &= DESC_DATA_FLAG_MASK;
383#endif
384
385 A_TARGET_ACCESS_LIKELY(scn);
386
387 /*
388 * Allocate a temporary bounce buffer to hold caller's data
389 * to be DMA'ed to Target. This guarantees
390 * 1) 4-byte alignment
391 * 2) Buffer in DMA-able space
392 */
393 orig_nbytes = nbytes;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530394 data_buf = qdf_mem_alloc_consistent(scn->qdf_dev, scn->qdf_dev->dev,
395 orig_nbytes, &CE_data_base);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800396 if (!data_buf) {
Rakesh Pillai13146452017-06-22 12:52:31 +0530397 status = QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800398 goto done;
399 }
400
401 /* Copy caller's data to allocated DMA buf */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530402 qdf_mem_copy(data_buf, data, orig_nbytes);
403 qdf_mem_dma_sync_single_for_device(scn->qdf_dev, CE_data_base,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800404 orig_nbytes, DMA_TO_DEVICE);
405
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700406 target_type = (hif_get_target_info_handle(hif_ctx))->target_type;
407
Poddar, Siddarth55d6da02017-03-31 18:42:54 +0530408 if (Q_TARGET_ACCESS_BEGIN(scn) < 0) {
409 status = QDF_STATUS_E_FAILURE;
410 goto done;
411 }
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700412
413 /* convert soc virtual address to physical address */
414 ce_phy_addr = get_ce_phy_addr(scn, address, target_type);
415
Poddar, Siddarth55d6da02017-03-31 18:42:54 +0530416 if (Q_TARGET_ACCESS_END(scn) < 0) {
417 status = QDF_STATUS_E_FAILURE;
418 goto done;
419 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800420
421 remaining_bytes = orig_nbytes;
422 CE_data = CE_data_base;
423 while (remaining_bytes) {
424 nbytes = min(remaining_bytes, DIAG_TRANSFER_LIMIT);
425
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700426 /* Set up to receive directly into Target(!) address */
427 status = ce_recv_buf_enqueue(ce_diag, NULL, ce_phy_addr);
428 if (status != QDF_STATUS_SUCCESS)
429 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800430
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700431 /*
432 * Request CE to send caller-supplied data that
433 * was copied to bounce buffer to Target(!) address.
434 */
435 status = ce_send(ce_diag, NULL, (qdf_dma_addr_t) CE_data,
436 nbytes, transaction_id, 0, user_flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800437
Houston Hoffmanfb698ef2016-05-05 19:50:44 -0700438 if (status != QDF_STATUS_SUCCESS)
439 goto done;
440
441 /* poll for transfer complete */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800442 i = 0;
443 while (ce_completed_send_next(ce_diag, NULL, NULL, &buf,
444 &completed_nbytes, &id,
445 NULL, NULL, &toeplitz_hash_result) !=
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530446 QDF_STATUS_SUCCESS) {
447 qdf_mdelay(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800448 if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530449 status = QDF_STATUS_E_BUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800450 goto done;
451 }
452 }
453
454 if (nbytes != completed_nbytes) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530455 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800456 goto done;
457 }
458
459 if (buf != CE_data) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530460 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800461 goto done;
462 }
463
464 i = 0;
465 while (ce_completed_recv_next
466 (ce_diag, NULL, NULL, &buf,
467 &completed_nbytes, &id,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530468 &flags) != QDF_STATUS_SUCCESS) {
469 qdf_mdelay(1);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800470 if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530471 status = QDF_STATUS_E_BUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800472 goto done;
473 }
474 }
475
476 if (nbytes != completed_nbytes) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530477 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800478 goto done;
479 }
480
481 if (buf != ce_phy_addr) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530482 status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800483 goto done;
484 }
485
486 remaining_bytes -= nbytes;
487 address += nbytes;
488 CE_data += nbytes;
489 }
490
491done:
492 A_TARGET_ACCESS_UNLIKELY(scn);
493
494 if (data_buf) {
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530495 qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev,
496 orig_nbytes, data_buf, CE_data_base, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497 }
498
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530499 if (status != QDF_STATUS_SUCCESS) {
Manikandan Mohanafd6e882017-04-07 17:46:41 -0700500 HIF_ERROR("%s failure (0x%llx)", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800501 (uint64_t)ce_phy_addr);
502 }
503
504 return status;
505}
506
507/* Write 4B data to Target memory or register */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530508QDF_STATUS hif_diag_write_access(struct hif_opaque_softc *hif_ctx,
Komal Seelam5584a7c2016-02-24 19:22:48 +0530509 uint32_t address, uint32_t data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510{
Komal Seelam644263d2016-02-22 20:45:49 +0530511 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800512
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800513 if (address >= DRAM_BASE_ADDRESS) {
514 /* Assume range doesn't cross this boundary */
515 uint32_t data_buf = data;
516
Komal Seelam644263d2016-02-22 20:45:49 +0530517 return hif_diag_write_mem(hif_ctx, address,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518 (uint8_t *) &data_buf,
519 sizeof(uint32_t));
520 } else {
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700521 if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
Houston Hoffman987ab442016-03-14 21:12:02 -0700522 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800523 A_TARGET_WRITE(scn, address, data);
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700524 if (Q_TARGET_ACCESS_END(scn) < 0)
Houston Hoffman987ab442016-03-14 21:12:02 -0700525 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800526
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530527 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 }
529}