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