1 /* 2 * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved. 3 * 4 * 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 19 #include "targcfg.h" 20 #include "target_type.h" 21 #include "qdf_lock.h" 22 #include "qdf_status.h" 23 #include "qdf_status.h" 24 #include <qdf_atomic.h> /* qdf_atomic_read */ 25 #include <targaddrs.h> 26 #include "hif_io32.h" 27 #include <hif.h> 28 #include "regtable.h" 29 #include <a_debug.h> 30 #include "hif_main.h" 31 #include "ce_api.h" 32 #include "qdf_trace.h" 33 #include "hif_debug.h" 34 #include "qdf_module.h" 35 36 void 37 hif_ce_dump_target_memory(struct hif_softc *scn, void *ramdump_base, 38 uint32_t address, uint32_t size) 39 { 40 uint32_t loc = address; 41 uint32_t val = 0; 42 uint32_t j = 0; 43 u8 *temp = ramdump_base; 44 45 if (Q_TARGET_ACCESS_BEGIN(scn) < 0) 46 return; 47 48 while (j < size) { 49 val = hif_read32_mb(scn, scn->mem + loc + j); 50 qdf_mem_copy(temp, &val, 4); 51 j += 4; 52 temp += 4; 53 } 54 55 Q_TARGET_ACCESS_END(scn); 56 } 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 66 #define TARG_CPU_SPACE_TO_CE_SPACE(sc, pci_addr, addr) \ 67 (scn->mem_pa + addr) 68 #else 69 #define TARG_CPU_SPACE_TO_CE_SPACE(sc, pci_addr, addr) \ 70 (((hif_read32_mb(sc, (pci_addr) + \ 71 (SOC_CORE_BASE_ADDRESS|CORE_CTRL_ADDRESS)) & 0x7ff) << 21) \ 72 | 0x100000 | ((addr) & 0xfffff)) 73 #endif 74 75 #define TARG_CPU_SPACE_TO_CE_SPACE_IPQ4019(scn, pci_addr, addr) \ 76 (hif_read32_mb(scn, (pci_addr) + (WIFICMN_PCIE_BAR_REG_ADDRESS)) \ 77 | ((addr) & 0xfffff)) 78 79 #define TARG_CPU_SPACE_TO_CE_SPACE_AR900B(scn, pci_addr, addr) \ 80 (hif_read32_mb(scn, (pci_addr) + (WIFICMN_PCIE_BAR_REG_ADDRESS)) \ 81 | 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 88 /* Wait up to this many Ms for a Diagnostic Access CE operation to complete */ 89 #define DIAG_ACCESS_CE_TIMEOUT_MS 10 90 91 /** 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 */ 99 static qdf_dma_addr_t get_ce_phy_addr(struct hif_softc *sc, uint32_t address, 100 unsigned int target_type) 101 { 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) { 116 ce_phy_addr = TARG_CPU_SPACE_TO_CE_SPACE_IPQ4019(sc, sc->mem, 117 address); 118 } 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 = 123 TARG_CPU_SPACE_TO_CE_SPACE_AR900B(sc, sc->mem, address); 124 } else { 125 ce_phy_addr = 126 TARG_CPU_SPACE_TO_CE_SPACE(sc, sc->mem, address); 127 } 128 129 return ce_phy_addr; 130 } 131 132 /* 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 138 #define FW_SRAM_ADDRESS 0x000C0000 139 140 QDF_STATUS hif_diag_read_mem(struct hif_opaque_softc *hif_ctx, 141 uint32_t address, uint8_t *data, int nbytes) 142 { 143 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 144 145 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); 146 QDF_STATUS status = QDF_STATUS_SUCCESS; 147 qdf_dma_addr_t buf; 148 unsigned int completed_nbytes, orig_nbytes, remaining_bytes; 149 unsigned int id; 150 unsigned int flags; 151 struct CE_handle *ce_diag; 152 qdf_dma_addr_t CE_data; /* Host buffer address in CE space */ 153 qdf_dma_addr_t CE_data_base = 0; 154 void *data_buf = NULL; 155 int i; 156 unsigned int mux_id = 0; 157 unsigned int transaction_id = 0xffff; 158 qdf_dma_addr_t ce_phy_addr = address; 159 unsigned int toeplitz_hash_result; 160 unsigned int user_flags = 0; 161 unsigned int target_type = 0; 162 unsigned int boundary_addr = 0; 163 164 ce_diag = hif_state->ce_diag; 165 if (!ce_diag) { 166 hif_err("DIAG CE not present"); 167 return QDF_STATUS_E_INVAL; 168 } 169 /* not supporting diag ce on srng based systems, therefore we know this 170 * isn't an srng based system */ 171 172 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 177 target_type = (hif_get_target_info_handle(hif_ctx))->target_type; 178 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 */ 183 if ((target_type == TARGET_TYPE_IPQ4019) || 184 (target_type == TARGET_TYPE_AR900B) || 185 (target_type == TARGET_TYPE_QCA9984) || 186 (target_type == TARGET_TYPE_AR9888) || 187 (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) { 193 194 if ((address & 0x3) || ((uintptr_t) data & 0x3)) 195 return QDF_STATUS_E_INVAL; 196 197 while ((nbytes >= 4) && 198 (QDF_STATUS_SUCCESS == (status = 199 hif_diag_read_access(hif_ctx, address, 200 (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 } 210 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; 220 data_buf = qdf_mem_alloc_consistent(scn->qdf_dev, scn->qdf_dev->dev, 221 orig_nbytes, &CE_data_base); 222 if (!data_buf) { 223 status = QDF_STATUS_E_NOMEM; 224 goto done; 225 } 226 qdf_mem_zero(data_buf, orig_nbytes); 227 228 remaining_bytes = orig_nbytes; 229 CE_data = CE_data_base; 230 while (remaining_bytes) { 231 nbytes = min(remaining_bytes, DIAG_TRANSFER_LIMIT); 232 { 233 status = ce_recv_buf_enqueue(ce_diag, NULL, CE_data); 234 if (status != QDF_STATUS_SUCCESS) 235 goto done; 236 } 237 238 if (Q_TARGET_ACCESS_BEGIN(scn) < 0) { 239 status = QDF_STATUS_E_FAILURE; 240 goto done; 241 } 242 243 /* convert soc virtual address to physical address */ 244 ce_phy_addr = get_ce_phy_addr(scn, address, target_type); 245 246 if (Q_TARGET_ACCESS_END(scn) < 0) { 247 status = QDF_STATUS_E_FAILURE; 248 goto done; 249 } 250 251 /* Request CE to send from Target(!) 252 * address to Host buffer 253 */ 254 status = ce_send(ce_diag, NULL, ce_phy_addr, nbytes, 255 transaction_id, 0, user_flags); 256 if (status != QDF_STATUS_SUCCESS) 257 goto done; 258 259 i = 0; 260 while (ce_completed_send_next(ce_diag, NULL, NULL, &buf, 261 &completed_nbytes, &id, NULL, NULL, 262 &toeplitz_hash_result) != 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_phy_addr) { 274 status = QDF_STATUS_E_FAILURE; 275 goto done; 276 } 277 278 i = 0; 279 while (ce_completed_recv_next 280 (ce_diag, NULL, NULL, &buf, 281 &completed_nbytes, &id, 282 &flags) != QDF_STATUS_SUCCESS) { 283 qdf_mdelay(1); 284 if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { 285 status = QDF_STATUS_E_BUSY; 286 goto done; 287 } 288 } 289 if (nbytes != completed_nbytes) { 290 status = QDF_STATUS_E_FAILURE; 291 goto done; 292 } 293 if (buf != CE_data) { 294 status = QDF_STATUS_E_FAILURE; 295 goto done; 296 } 297 298 remaining_bytes -= nbytes; 299 address += nbytes; 300 CE_data += nbytes; 301 } 302 303 done: 304 A_TARGET_ACCESS_UNLIKELY(scn); 305 306 if (status == QDF_STATUS_SUCCESS) 307 qdf_mem_copy(data, data_buf, orig_nbytes); 308 else 309 hif_err("Failure (0x%x)", address); 310 311 if (data_buf) 312 qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, 313 orig_nbytes, data_buf, CE_data_base, 0); 314 315 return status; 316 } 317 qdf_export_symbol(hif_diag_read_mem); 318 319 /* Read 4-byte aligned data from Target memory or register */ 320 QDF_STATUS hif_diag_read_access(struct hif_opaque_softc *hif_ctx, 321 uint32_t address, uint32_t *data) 322 { 323 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 324 325 if (address >= DRAM_BASE_ADDRESS) { 326 /* Assume range doesn't cross this boundary */ 327 return hif_diag_read_mem(hif_ctx, address, (uint8_t *) data, 328 sizeof(uint32_t)); 329 } else { 330 if (Q_TARGET_ACCESS_BEGIN(scn) < 0) 331 return QDF_STATUS_E_FAILURE; 332 *data = A_TARGET_READ(scn, address); 333 if (Q_TARGET_ACCESS_END(scn) < 0) 334 return QDF_STATUS_E_FAILURE; 335 336 return QDF_STATUS_SUCCESS; 337 } 338 } 339 340 /** 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 */ 347 QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *hif_ctx, 348 uint32_t address, uint8_t *data, int nbytes) 349 { 350 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 351 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx); 352 QDF_STATUS status = QDF_STATUS_SUCCESS; 353 qdf_dma_addr_t buf; 354 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; 359 qdf_dma_addr_t CE_data; /* Host buffer address in CE space */ 360 qdf_dma_addr_t CE_data_base = 0; 361 int i; 362 unsigned int mux_id = 0; 363 unsigned int transaction_id = 0xffff; 364 qdf_dma_addr_t ce_phy_addr = address; 365 unsigned int toeplitz_hash_result; 366 unsigned int user_flags = 0; 367 unsigned int target_type = 0; 368 369 ce_diag = hif_state->ce_diag; 370 if (!ce_diag) { 371 hif_err("DIAG CE not present"); 372 return QDF_STATUS_E_INVAL; 373 } 374 /* not supporting diag ce on srng based systems, therefore we know this 375 * isn't an srng based system */ 376 377 transaction_id = (mux_id & MUX_ID_MASK) | 378 (transaction_id & TRANSACTION_ID_MASK); 379 #ifdef QCA_WIFI_3_0 380 user_flags &= DESC_DATA_FLAG_MASK; 381 #endif 382 383 A_TARGET_ACCESS_LIKELY(scn); 384 385 /* 386 * Allocate a temporary bounce buffer to hold caller's data 387 * to be DMA'ed to Target. This guarantees 388 * 1) 4-byte alignment 389 * 2) Buffer in DMA-able space 390 */ 391 orig_nbytes = nbytes; 392 data_buf = qdf_mem_alloc_consistent(scn->qdf_dev, scn->qdf_dev->dev, 393 orig_nbytes, &CE_data_base); 394 if (!data_buf) { 395 status = QDF_STATUS_E_NOMEM; 396 goto done; 397 } 398 399 /* Copy caller's data to allocated DMA buf */ 400 qdf_mem_copy(data_buf, data, orig_nbytes); 401 qdf_mem_dma_sync_single_for_device(scn->qdf_dev, CE_data_base, 402 orig_nbytes, DMA_TO_DEVICE); 403 404 target_type = (hif_get_target_info_handle(hif_ctx))->target_type; 405 406 if (Q_TARGET_ACCESS_BEGIN(scn) < 0) { 407 status = QDF_STATUS_E_FAILURE; 408 goto done; 409 } 410 411 /* convert soc virtual address to physical address */ 412 ce_phy_addr = get_ce_phy_addr(scn, address, target_type); 413 414 if (Q_TARGET_ACCESS_END(scn) < 0) { 415 status = QDF_STATUS_E_FAILURE; 416 goto done; 417 } 418 419 remaining_bytes = orig_nbytes; 420 CE_data = CE_data_base; 421 while (remaining_bytes) { 422 nbytes = min(remaining_bytes, DIAG_TRANSFER_LIMIT); 423 424 /* Set up to receive directly into Target(!) address */ 425 status = ce_recv_buf_enqueue(ce_diag, NULL, ce_phy_addr); 426 if (status != QDF_STATUS_SUCCESS) 427 goto done; 428 429 /* 430 * Request CE to send caller-supplied data that 431 * was copied to bounce buffer to Target(!) address. 432 */ 433 status = ce_send(ce_diag, NULL, (qdf_dma_addr_t) CE_data, 434 nbytes, transaction_id, 0, user_flags); 435 436 if (status != QDF_STATUS_SUCCESS) 437 goto done; 438 439 /* poll for transfer complete */ 440 i = 0; 441 while (ce_completed_send_next(ce_diag, NULL, NULL, &buf, 442 &completed_nbytes, &id, 443 NULL, NULL, &toeplitz_hash_result) != 444 QDF_STATUS_SUCCESS) { 445 qdf_mdelay(1); 446 if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { 447 status = QDF_STATUS_E_BUSY; 448 goto done; 449 } 450 } 451 452 if (nbytes != completed_nbytes) { 453 status = QDF_STATUS_E_FAILURE; 454 goto done; 455 } 456 457 if (buf != CE_data) { 458 status = QDF_STATUS_E_FAILURE; 459 goto done; 460 } 461 462 i = 0; 463 while (ce_completed_recv_next 464 (ce_diag, NULL, NULL, &buf, 465 &completed_nbytes, &id, 466 &flags) != QDF_STATUS_SUCCESS) { 467 qdf_mdelay(1); 468 if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { 469 status = QDF_STATUS_E_BUSY; 470 goto done; 471 } 472 } 473 474 if (nbytes != completed_nbytes) { 475 status = QDF_STATUS_E_FAILURE; 476 goto done; 477 } 478 479 if (buf != ce_phy_addr) { 480 status = QDF_STATUS_E_FAILURE; 481 goto done; 482 } 483 484 remaining_bytes -= nbytes; 485 address += nbytes; 486 CE_data += nbytes; 487 } 488 489 done: 490 A_TARGET_ACCESS_UNLIKELY(scn); 491 492 if (data_buf) { 493 qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, 494 orig_nbytes, data_buf, CE_data_base, 0); 495 } 496 497 if (status != QDF_STATUS_SUCCESS) { 498 hif_err("Failure (0x%llx)", (uint64_t)ce_phy_addr); 499 } 500 501 return status; 502 } 503 504 /* Write 4B data to Target memory or register */ 505 QDF_STATUS hif_diag_write_access(struct hif_opaque_softc *hif_ctx, 506 uint32_t address, uint32_t data) 507 { 508 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 509 510 if (address >= DRAM_BASE_ADDRESS) { 511 /* Assume range doesn't cross this boundary */ 512 uint32_t data_buf = data; 513 514 return hif_diag_write_mem(hif_ctx, address, 515 (uint8_t *) &data_buf, 516 sizeof(uint32_t)); 517 } else { 518 if (Q_TARGET_ACCESS_BEGIN(scn) < 0) 519 return QDF_STATUS_E_FAILURE; 520 A_TARGET_WRITE(scn, address, data); 521 if (Q_TARGET_ACCESS_END(scn) < 0) 522 return QDF_STATUS_E_FAILURE; 523 524 return QDF_STATUS_SUCCESS; 525 } 526 } 527