/drivers/staging/ath6kl/bmi/src/bmi.c
C | 1010 lines | 724 code | 150 blank | 136 comment | 76 complexity | a99ec6d66cbbd4901f8d529a644639c6 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
1//------------------------------------------------------------------------------ 2// <copyright file="bmi.c" company="Atheros"> 3// Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. 4// 5// 6// Permission to use, copy, modify, and/or distribute this software for any 7// purpose with or without fee is hereby granted, provided that the above 8// copyright notice and this permission notice appear in all copies. 9// 10// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17// 18// 19//------------------------------------------------------------------------------ 20//============================================================================== 21// 22// Author(s): ="Atheros" 23//============================================================================== 24 25 26#ifdef THREAD_X 27#include <string.h> 28#endif 29 30#include "hif.h" 31#include "bmi.h" 32#include "htc_api.h" 33#include "bmi_internal.h" 34 35#ifdef ATH_DEBUG_MODULE 36static struct ath_debug_mask_description bmi_debug_desc[] = { 37 { ATH_DEBUG_BMI , "BMI Tracing"}, 38}; 39 40ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi, 41 "bmi", 42 "Boot Manager Interface", 43 ATH_DEBUG_MASK_DEFAULTS, 44 ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc), 45 bmi_debug_desc); 46 47#endif 48 49/* 50Although we had envisioned BMI to run on top of HTC, this is not how the 51final implementation ended up. On the Target side, BMI is a part of the BSP 52and does not use the HTC protocol nor even DMA -- it is intentionally kept 53very simple. 54*/ 55 56static bool pendingEventsFuncCheck = false; 57static u32 *pBMICmdCredits; 58static u8 *pBMICmdBuf; 59#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \ 60 sizeof(u32) /* cmd */ + \ 61 sizeof(u32) /* addr */ + \ 62 sizeof(u32))/* length */ 63#define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ) 64 65/* APIs visible to the driver */ 66void 67BMIInit(void) 68{ 69 bmiDone = false; 70 pendingEventsFuncCheck = false; 71 72 /* 73 * On some platforms, it's not possible to DMA to a static variable 74 * in a device driver (e.g. Linux loadable driver module). 75 * So we need to A_MALLOC space for "command credits" and for commands. 76 * 77 * Note: implicitly relies on A_MALLOC to provide a buffer that is 78 * suitable for DMA (or PIO). This buffer will be passed down the 79 * bus stack. 80 */ 81 if (!pBMICmdCredits) { 82 pBMICmdCredits = (u32 *)A_MALLOC_NOWAIT(4); 83 A_ASSERT(pBMICmdCredits); 84 } 85 86 if (!pBMICmdBuf) { 87 pBMICmdBuf = (u8 *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ); 88 A_ASSERT(pBMICmdBuf); 89 } 90 91 A_REGISTER_MODULE_DEBUG_INFO(bmi); 92} 93 94void 95BMICleanup(void) 96{ 97 if (pBMICmdCredits) { 98 kfree(pBMICmdCredits); 99 pBMICmdCredits = NULL; 100 } 101 102 if (pBMICmdBuf) { 103 kfree(pBMICmdBuf); 104 pBMICmdBuf = NULL; 105 } 106} 107 108int 109BMIDone(struct hif_device *device) 110{ 111 int status; 112 u32 cid; 113 114 if (bmiDone) { 115 AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n")); 116 return 0; 117 } 118 119 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device)); 120 bmiDone = true; 121 cid = BMI_DONE; 122 123 status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid)); 124 if (status) { 125 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); 126 return A_ERROR; 127 } 128 129 if (pBMICmdCredits) { 130 kfree(pBMICmdCredits); 131 pBMICmdCredits = NULL; 132 } 133 134 if (pBMICmdBuf) { 135 kfree(pBMICmdBuf); 136 pBMICmdBuf = NULL; 137 } 138 139 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n")); 140 141 return 0; 142} 143 144int 145BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info) 146{ 147 int status; 148 u32 cid; 149 150 if (bmiDone) { 151 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); 152 return A_ERROR; 153 } 154 155 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device)); 156 cid = BMI_GET_TARGET_INFO; 157 158 status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid)); 159 if (status) { 160 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); 161 return A_ERROR; 162 } 163 164 status = bmiBufferReceive(device, (u8 *)&targ_info->target_ver, 165 sizeof(targ_info->target_ver), true); 166 if (status) { 167 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n")); 168 return A_ERROR; 169 } 170 171 if (targ_info->target_ver == TARGET_VERSION_SENTINAL) { 172 /* Determine how many bytes are in the Target's targ_info */ 173 status = bmiBufferReceive(device, (u8 *)&targ_info->target_info_byte_count, 174 sizeof(targ_info->target_info_byte_count), true); 175 if (status) { 176 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n")); 177 return A_ERROR; 178 } 179 180 /* 181 * The Target's targ_info doesn't match the Host's targ_info. 182 * We need to do some backwards compatibility work to make this OK. 183 */ 184 A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info)); 185 186 /* Read the remainder of the targ_info */ 187 status = bmiBufferReceive(device, 188 ((u8 *)targ_info)+sizeof(targ_info->target_info_byte_count), 189 sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), true); 190 if (status) { 191 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n", 192 targ_info->target_info_byte_count)); 193 return A_ERROR; 194 } 195 } 196 197 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n", 198 targ_info->target_ver, targ_info->target_type)); 199 200 return 0; 201} 202 203int 204BMIReadMemory(struct hif_device *device, 205 u32 address, 206 u8 *buffer, 207 u32 length) 208{ 209 u32 cid; 210 int status; 211 u32 offset; 212 u32 remaining, rxlen; 213 214 A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length))); 215 memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)); 216 217 if (bmiDone) { 218 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); 219 return A_ERROR; 220 } 221 222 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, 223 ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n", 224 device, address, length)); 225 226 cid = BMI_READ_MEMORY; 227 228 remaining = length; 229 230 while (remaining) 231 { 232 rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX; 233 offset = 0; 234 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); 235 offset += sizeof(cid); 236 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); 237 offset += sizeof(address); 238 memcpy(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen)); 239 offset += sizeof(length); 240 241 status = bmiBufferSend(device, pBMICmdBuf, offset); 242 if (status) { 243 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); 244 return A_ERROR; 245 } 246 status = bmiBufferReceive(device, pBMICmdBuf, rxlen, true); 247 if (status) { 248 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); 249 return A_ERROR; 250 } 251 memcpy(&buffer[length - remaining], pBMICmdBuf, rxlen); 252 remaining -= rxlen; address += rxlen; 253 } 254 255 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n")); 256 return 0; 257} 258 259int 260BMIWriteMemory(struct hif_device *device, 261 u32 address, 262 u8 *buffer, 263 u32 length) 264{ 265 u32 cid; 266 int status; 267 u32 offset; 268 u32 remaining, txlen; 269 const u32 header = sizeof(cid) + sizeof(address) + sizeof(length); 270 u8 alignedBuffer[BMI_DATASZ_MAX]; 271 u8 *src; 272 273 A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header)); 274 memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + header); 275 276 if (bmiDone) { 277 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); 278 return A_ERROR; 279 } 280 281 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, 282 ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n", 283 device, address, length)); 284 285 cid = BMI_WRITE_MEMORY; 286 287 remaining = length; 288 while (remaining) 289 { 290 src = &buffer[length - remaining]; 291 if (remaining < (BMI_DATASZ_MAX - header)) { 292 if (remaining & 3) { 293 /* align it with 4 bytes */ 294 remaining = remaining + (4 - (remaining & 3)); 295 memcpy(alignedBuffer, src, remaining); 296 src = alignedBuffer; 297 } 298 txlen = remaining; 299 } else { 300 txlen = (BMI_DATASZ_MAX - header); 301 } 302 offset = 0; 303 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); 304 offset += sizeof(cid); 305 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); 306 offset += sizeof(address); 307 memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen)); 308 offset += sizeof(txlen); 309 memcpy(&(pBMICmdBuf[offset]), src, txlen); 310 offset += txlen; 311 status = bmiBufferSend(device, pBMICmdBuf, offset); 312 if (status) { 313 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); 314 return A_ERROR; 315 } 316 remaining -= txlen; address += txlen; 317 } 318 319 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n")); 320 321 return 0; 322} 323 324int 325BMIExecute(struct hif_device *device, 326 u32 address, 327 u32 *param) 328{ 329 u32 cid; 330 int status; 331 u32 offset; 332 333 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param))); 334 memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param)); 335 336 if (bmiDone) { 337 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); 338 return A_ERROR; 339 } 340 341 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, 342 ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n", 343 device, address, *param)); 344 345 cid = BMI_EXECUTE; 346 347 offset = 0; 348 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); 349 offset += sizeof(cid); 350 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); 351 offset += sizeof(address); 352 memcpy(&(pBMICmdBuf[offset]), param, sizeof(*param)); 353 offset += sizeof(*param); 354 status = bmiBufferSend(device, pBMICmdBuf, offset); 355 if (status) { 356 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); 357 return A_ERROR; 358 } 359 360 status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), false); 361 if (status) { 362 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); 363 return A_ERROR; 364 } 365 366 memcpy(param, pBMICmdBuf, sizeof(*param)); 367 368 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param)); 369 return 0; 370} 371 372int 373BMISetAppStart(struct hif_device *device, 374 u32 address) 375{ 376 u32 cid; 377 int status; 378 u32 offset; 379 380 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); 381 memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address)); 382 383 if (bmiDone) { 384 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); 385 return A_ERROR; 386 } 387 388 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, 389 ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n", 390 device, address)); 391 392 cid = BMI_SET_APP_START; 393 394 offset = 0; 395 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); 396 offset += sizeof(cid); 397 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); 398 offset += sizeof(address); 399 status = bmiBufferSend(device, pBMICmdBuf, offset); 400 if (status) { 401 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); 402 return A_ERROR; 403 } 404 405 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n")); 406 return 0; 407} 408 409int 410BMIReadSOCRegister(struct hif_device *device, 411 u32 address, 412 u32 *param) 413{ 414 u32 cid; 415 int status; 416 u32 offset; 417 418 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); 419 memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address)); 420 421 if (bmiDone) { 422 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); 423 return A_ERROR; 424 } 425 426 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, 427 ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n", 428 device, address)); 429 430 cid = BMI_READ_SOC_REGISTER; 431 432 offset = 0; 433 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); 434 offset += sizeof(cid); 435 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); 436 offset += sizeof(address); 437 438 status = bmiBufferSend(device, pBMICmdBuf, offset); 439 if (status) { 440 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); 441 return A_ERROR; 442 } 443 444 status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), true); 445 if (status) { 446 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); 447 return A_ERROR; 448 } 449 memcpy(param, pBMICmdBuf, sizeof(*param)); 450 451 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param)); 452 return 0; 453} 454 455int 456BMIWriteSOCRegister(struct hif_device *device, 457 u32 address, 458 u32 param) 459{ 460 u32 cid; 461 int status; 462 u32 offset; 463 464 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param))); 465 memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param)); 466 467 if (bmiDone) { 468 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); 469 return A_ERROR; 470 } 471 472 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, 473 ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n", 474 device, address, param)); 475 476 cid = BMI_WRITE_SOC_REGISTER; 477 478 offset = 0; 479 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); 480 offset += sizeof(cid); 481 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); 482 offset += sizeof(address); 483 memcpy(&(pBMICmdBuf[offset]), ¶m, sizeof(param)); 484 offset += sizeof(param); 485 status = bmiBufferSend(device, pBMICmdBuf, offset); 486 if (status) { 487 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); 488 return A_ERROR; 489 } 490 491 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n")); 492 return 0; 493} 494 495int 496BMIrompatchInstall(struct hif_device *device, 497 u32 ROM_addr, 498 u32 RAM_addr, 499 u32 nbytes, 500 u32 do_activate, 501 u32 *rompatch_id) 502{ 503 u32 cid; 504 int status; 505 u32 offset; 506 507 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) + 508 sizeof(nbytes) + sizeof(do_activate))); 509 memset(pBMICmdBuf, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) + 510 sizeof(nbytes) + sizeof(do_activate)); 511 512 if (bmiDone) { 513 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); 514 return A_ERROR; 515 } 516 517 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, 518 ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n", 519 device, ROM_addr, RAM_addr, nbytes, do_activate)); 520 521 cid = BMI_ROMPATCH_INSTALL; 522 523 offset = 0; 524 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); 525 offset += sizeof(cid); 526 memcpy(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr)); 527 offset += sizeof(ROM_addr); 528 memcpy(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr)); 529 offset += sizeof(RAM_addr); 530 memcpy(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes)); 531 offset += sizeof(nbytes); 532 memcpy(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate)); 533 offset += sizeof(do_activate); 534 status = bmiBufferSend(device, pBMICmdBuf, offset); 535 if (status) { 536 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); 537 return A_ERROR; 538 } 539 540 status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), true); 541 if (status) { 542 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); 543 return A_ERROR; 544 } 545 memcpy(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id)); 546 547 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id)); 548 return 0; 549} 550 551int 552BMIrompatchUninstall(struct hif_device *device, 553 u32 rompatch_id) 554{ 555 u32 cid; 556 int status; 557 u32 offset; 558 559 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(rompatch_id))); 560 memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(rompatch_id)); 561 562 if (bmiDone) { 563 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); 564 return A_ERROR; 565 } 566 567 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, 568 ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n", 569 device, rompatch_id)); 570 571 cid = BMI_ROMPATCH_UNINSTALL; 572 573 offset = 0; 574 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); 575 offset += sizeof(cid); 576 memcpy(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id)); 577 offset += sizeof(rompatch_id); 578 status = bmiBufferSend(device, pBMICmdBuf, offset); 579 if (status) { 580 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); 581 return A_ERROR; 582 } 583 584 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id)); 585 return 0; 586} 587 588static int 589_BMIrompatchChangeActivation(struct hif_device *device, 590 u32 rompatch_count, 591 u32 *rompatch_list, 592 u32 do_activate) 593{ 594 u32 cid; 595 int status; 596 u32 offset; 597 u32 length; 598 599 A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count))); 600 memset(pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)); 601 602 if (bmiDone) { 603 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); 604 return A_ERROR; 605 } 606 607 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, 608 ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n", 609 device, rompatch_count)); 610 611 cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE; 612 613 offset = 0; 614 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); 615 offset += sizeof(cid); 616 memcpy(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count)); 617 offset += sizeof(rompatch_count); 618 length = rompatch_count * sizeof(*rompatch_list); 619 memcpy(&(pBMICmdBuf[offset]), rompatch_list, length); 620 offset += length; 621 status = bmiBufferSend(device, pBMICmdBuf, offset); 622 if (status) { 623 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); 624 return A_ERROR; 625 } 626 627 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n")); 628 629 return 0; 630} 631 632int 633BMIrompatchActivate(struct hif_device *device, 634 u32 rompatch_count, 635 u32 *rompatch_list) 636{ 637 return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1); 638} 639 640int 641BMIrompatchDeactivate(struct hif_device *device, 642 u32 rompatch_count, 643 u32 *rompatch_list) 644{ 645 return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0); 646} 647 648int 649BMILZData(struct hif_device *device, 650 u8 *buffer, 651 u32 length) 652{ 653 u32 cid; 654 int status; 655 u32 offset; 656 u32 remaining, txlen; 657 const u32 header = sizeof(cid) + sizeof(length); 658 659 A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX+header)); 660 memset (pBMICmdBuf, 0, BMI_DATASZ_MAX+header); 661 662 if (bmiDone) { 663 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); 664 return A_ERROR; 665 } 666 667 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, 668 ("BMI Send LZ Data: Enter (device: 0x%p, length: %d)\n", 669 device, length)); 670 671 cid = BMI_LZ_DATA; 672 673 remaining = length; 674 while (remaining) 675 { 676 txlen = (remaining < (BMI_DATASZ_MAX - header)) ? 677 remaining : (BMI_DATASZ_MAX - header); 678 offset = 0; 679 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); 680 offset += sizeof(cid); 681 memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen)); 682 offset += sizeof(txlen); 683 memcpy(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen); 684 offset += txlen; 685 status = bmiBufferSend(device, pBMICmdBuf, offset); 686 if (status) { 687 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); 688 return A_ERROR; 689 } 690 remaining -= txlen; 691 } 692 693 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Data: Exit\n")); 694 695 return 0; 696} 697 698int 699BMILZStreamStart(struct hif_device *device, 700 u32 address) 701{ 702 u32 cid; 703 int status; 704 u32 offset; 705 706 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); 707 memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address)); 708 709 if (bmiDone) { 710 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); 711 return A_ERROR; 712 } 713 714 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, 715 ("BMI LZ Stream Start: Enter (device: 0x%p, address: 0x%x)\n", 716 device, address)); 717 718 cid = BMI_LZ_STREAM_START; 719 offset = 0; 720 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid)); 721 offset += sizeof(cid); 722 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address)); 723 offset += sizeof(address); 724 status = bmiBufferSend(device, pBMICmdBuf, offset); 725 if (status) { 726 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to Start LZ Stream to the device\n")); 727 return A_ERROR; 728 } 729 730 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Stream Start: Exit\n")); 731 732 return 0; 733} 734 735/* BMI Access routines */ 736int 737bmiBufferSend(struct hif_device *device, 738 u8 *buffer, 739 u32 length) 740{ 741 int status; 742 u32 timeout; 743 u32 address; 744 u32 mboxAddress[HTC_MAILBOX_NUM_MAX]; 745 746 HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR, 747 &mboxAddress[0], sizeof(mboxAddress)); 748 749 *pBMICmdCredits = 0; 750 timeout = BMI_COMMUNICATION_TIMEOUT; 751 752 while(timeout-- && !(*pBMICmdCredits)) { 753 /* Read the counter register to get the command credits */ 754 address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4; 755 /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause 756 * a decrement, while the remaining 3 bytes has no effect. The rationale behind this is to 757 * make all HIF accesses 4-byte aligned */ 758 status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, 4, 759 HIF_RD_SYNC_BYTE_INC, NULL); 760 if (status) { 761 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n")); 762 return A_ERROR; 763 } 764 /* the counter is only 8=bits, ignore anything in the upper 3 bytes */ 765 (*pBMICmdCredits) &= 0xFF; 766 } 767 768 if (*pBMICmdCredits) { 769 address = mboxAddress[ENDPOINT1]; 770 status = HIFReadWrite(device, address, buffer, length, 771 HIF_WR_SYNC_BYTE_INC, NULL); 772 if (status) { 773 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n")); 774 return A_ERROR; 775 } 776 } else { 777 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferSend\n")); 778 return A_ERROR; 779 } 780 781 return status; 782} 783 784int 785bmiBufferReceive(struct hif_device *device, 786 u8 *buffer, 787 u32 length, 788 bool want_timeout) 789{ 790 int status; 791 u32 address; 792 u32 mboxAddress[HTC_MAILBOX_NUM_MAX]; 793 struct hif_pending_events_info hifPendingEvents; 794 static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL; 795 796 if (!pendingEventsFuncCheck) { 797 /* see if the HIF layer implements an alternative function to get pending events 798 * do this only once! */ 799 HIFConfigureDevice(device, 800 HIF_DEVICE_GET_PENDING_EVENTS_FUNC, 801 &getPendingEventsFunc, 802 sizeof(getPendingEventsFunc)); 803 pendingEventsFuncCheck = true; 804 } 805 806 HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR, 807 &mboxAddress[0], sizeof(mboxAddress)); 808 809 /* 810 * During normal bootup, small reads may be required. 811 * Rather than issue an HIF Read and then wait as the Target 812 * adds successive bytes to the FIFO, we wait here until 813 * we know that response data is available. 814 * 815 * This allows us to cleanly timeout on an unexpected 816 * Target failure rather than risk problems at the HIF level. In 817 * particular, this avoids SDIO timeouts and possibly garbage 818 * data on some host controllers. And on an interconnect 819 * such as Compact Flash (as well as some SDIO masters) which 820 * does not provide any indication on data timeout, it avoids 821 * a potential hang or garbage response. 822 * 823 * Synchronization is more difficult for reads larger than the 824 * size of the MBOX FIFO (128B), because the Target is unable 825 * to push the 129th byte of data until AFTER the Host posts an 826 * HIF Read and removes some FIFO data. So for large reads the 827 * Host proceeds to post an HIF Read BEFORE all the data is 828 * actually available to read. Fortunately, large BMI reads do 829 * not occur in practice -- they're supported for debug/development. 830 * 831 * So Host/Target BMI synchronization is divided into these cases: 832 * CASE 1: length < 4 833 * Should not happen 834 * 835 * CASE 2: 4 <= length <= 128 836 * Wait for first 4 bytes to be in FIFO 837 * If CONSERVATIVE_BMI_READ is enabled, also wait for 838 * a BMI command credit, which indicates that the ENTIRE 839 * response is available in the the FIFO 840 * 841 * CASE 3: length > 128 842 * Wait for the first 4 bytes to be in FIFO 843 * 844 * For most uses, a small timeout should be sufficient and we will 845 * usually see a response quickly; but there may be some unusual 846 * (debug) cases of BMI_EXECUTE where we want an larger timeout. 847 * For now, we use an unbounded busy loop while waiting for 848 * BMI_EXECUTE. 849 * 850 * If BMI_EXECUTE ever needs to support longer-latency execution, 851 * especially in production, this code needs to be enhanced to sleep 852 * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently 853 * a function of Host processor speed. 854 */ 855 if (length >= 4) { /* NB: Currently, always true */ 856 /* 857 * NB: word_available is declared static for esoteric reasons 858 * having to do with protection on some OSes. 859 */ 860 static u32 word_available; 861 u32 timeout; 862 863 word_available = 0; 864 timeout = BMI_COMMUNICATION_TIMEOUT; 865 while((!want_timeout || timeout--) && !word_available) { 866 867 if (getPendingEventsFunc != NULL) { 868 status = getPendingEventsFunc(device, 869 &hifPendingEvents, 870 NULL); 871 if (status) { 872 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n")); 873 break; 874 } 875 876 if (hifPendingEvents.AvailableRecvBytes >= sizeof(u32)) { 877 word_available = 1; 878 } 879 continue; 880 } 881 882 status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (u8 *)&word_available, 883 sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL); 884 if (status) { 885 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n")); 886 return A_ERROR; 887 } 888 /* We did a 4-byte read to the same register; all we really want is one bit */ 889 word_available &= (1 << ENDPOINT1); 890 } 891 892 if (!word_available) { 893 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferReceive FIFO empty\n")); 894 return A_ERROR; 895 } 896 } 897 898#define CONSERVATIVE_BMI_READ 0 899#if CONSERVATIVE_BMI_READ 900 /* 901 * This is an extra-conservative CREDIT check. It guarantees 902 * that ALL data is available in the FIFO before we start to 903 * read from the interconnect. 904 * 905 * This credit check is useless when firmware chooses to 906 * allow multiple outstanding BMI Command Credits, since the next 907 * credit will already be present. To restrict the Target to one 908 * BMI Command Credit, see HI_OPTION_BMI_CRED_LIMIT. 909 * 910 * And for large reads (when HI_OPTION_BMI_CRED_LIMIT is set) 911 * we cannot wait for the next credit because the Target's FIFO 912 * will not hold the entire response. So we need the Host to 913 * start to empty the FIFO sooner. (And again, large reads are 914 * not used in practice; they are for debug/development only.) 915 * 916 * For a more conservative Host implementation (which would be 917 * safer for a Compact Flash interconnect): 918 * Set CONSERVATIVE_BMI_READ (above) to 1 919 * Set HI_OPTION_BMI_CRED_LIMIT and 920 * reduce BMI_DATASZ_MAX to 32 or 64 921 */ 922 if ((length > 4) && (length < 128)) { /* check against MBOX FIFO size */ 923 u32 timeout; 924 925 *pBMICmdCredits = 0; 926 timeout = BMI_COMMUNICATION_TIMEOUT; 927 while((!want_timeout || timeout--) && !(*pBMICmdCredits) { 928 /* Read the counter register to get the command credits */ 929 address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1; 930 /* read the counter using a 4-byte read. Since the counter is NOT auto-decrementing, 931 * we can read this counter multiple times using a non-incrementing address mode. 932 * The rationale here is to make all HIF accesses a multiple of 4 bytes */ 933 status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, sizeof(*pBMICmdCredits), 934 HIF_RD_SYNC_BYTE_FIX, NULL); 935 if (status) { 936 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n")); 937 return A_ERROR; 938 } 939 /* we did a 4-byte read to the same count register so mask off upper bytes */ 940 (*pBMICmdCredits) &= 0xFF; 941 } 942 943 if (!(*pBMICmdCredits)) { 944 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout- bmiBufferReceive no credit\n")); 945 return A_ERROR; 946 } 947 } 948#endif 949 950 address = mboxAddress[ENDPOINT1]; 951 status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL); 952 if (status) { 953 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n")); 954 return A_ERROR; 955 } 956 957 return 0; 958} 959 960int 961BMIFastDownload(struct hif_device *device, u32 address, u8 *buffer, u32 length) 962{ 963 int status = A_ERROR; 964 u32 lastWord = 0; 965 u32 lastWordOffset = length & ~0x3; 966 u32 unalignedBytes = length & 0x3; 967 968 status = BMILZStreamStart (device, address); 969 if (status) { 970 return A_ERROR; 971 } 972 973 if (unalignedBytes) { 974 /* copy the last word into a zero padded buffer */ 975 memcpy(&lastWord, &buffer[lastWordOffset], unalignedBytes); 976 } 977 978 status = BMILZData(device, buffer, lastWordOffset); 979 980 if (status) { 981 return A_ERROR; 982 } 983 984 if (unalignedBytes) { 985 status = BMILZData(device, (u8 *)&lastWord, 4); 986 } 987 988 if (!status) { 989 // 990 // Close compressed stream and open a new (fake) one. This serves mainly to flush Target caches. 991 // 992 status = BMILZStreamStart (device, 0x00); 993 if (status) { 994 return A_ERROR; 995 } 996 } 997 return status; 998} 999 1000int 1001BMIRawWrite(struct hif_device *device, u8 *buffer, u32 length) 1002{ 1003 return bmiBufferSend(device, buffer, length); 1004} 1005 1006int 1007BMIRawRead(struct hif_device *device, u8 *buffer, u32 length, bool want_timeout) 1008{ 1009 return bmiBufferReceive(device, buffer, length, want_timeout); 1010}