OLD | NEW |
(Empty) | |
| 1 //------------------------------------------------------------------------------ |
| 2 // <copyright file="common_drv.c" company="Atheros"> |
| 3 // Copyright (c) 2004-2008 Atheros Corporation. All rights reserved. |
| 4 // |
| 5 // This program is free software; you can redistribute it and/or modify |
| 6 // it under the terms of the GNU General Public License version 2 as |
| 7 // published by the Free Software Foundation; |
| 8 // |
| 9 // Software distributed under the License is distributed on an "AS |
| 10 // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
| 11 // implied. See the License for the specific language governing |
| 12 // rights and limitations under the License. |
| 13 // |
| 14 // |
| 15 //------------------------------------------------------------------------------ |
| 16 //============================================================================== |
| 17 // Author(s): ="Atheros" |
| 18 //============================================================================== |
| 19 #include "a_config.h" |
| 20 #include "athdefs.h" |
| 21 #include "a_types.h" |
| 22 |
| 23 #include "AR6002/hw/mbox_host_reg.h" |
| 24 #include "AR6002/hw/apb_map.h" |
| 25 #include "AR6002/hw/si_reg.h" |
| 26 #include "AR6002/hw/gpio_reg.h" |
| 27 #include "AR6002/hw/rtc_reg.h" |
| 28 #include "AR6002/hw/vmc_reg.h" |
| 29 #include "AR6002/hw/mbox_reg.h" |
| 30 |
| 31 #include "targaddrs.h" |
| 32 #include "a_osapi.h" |
| 33 #include "hif.h" |
| 34 #include "htc_api.h" |
| 35 #include "wmi.h" |
| 36 #include "bmi.h" |
| 37 #include "bmi_msg.h" |
| 38 #include "common_drv.h" |
| 39 #define ATH_MODULE_NAME misc |
| 40 #include "a_debug.h" |
| 41 #include "ar6000_diag.h" |
| 42 |
| 43 static ATH_DEBUG_MODULE_DBG_INFO *g_pModuleInfoHead = NULL; |
| 44 static A_MUTEX_T g_ModuleListLock; |
| 45 static A_BOOL g_ModuleDebugInit = FALSE; |
| 46 |
| 47 #ifdef DEBUG |
| 48 |
| 49 ATH_DEBUG_INSTANTIATE_MODULE_VAR(misc, |
| 50 "misc", |
| 51 "Common and misc APIs", |
| 52 ATH_DEBUG_MASK_DEFAULTS, |
| 53 0, |
| 54 NULL); |
| 55 |
| 56 #endif |
| 57 |
| 58 #define HOST_INTEREST_ITEM_ADDRESS(target, item) \ |
| 59 (((target) == TARGET_TYPE_AR6001) ? AR6001_HOST_INTEREST_ITEM_ADDRESS(it
em) : \ |
| 60 (((target) == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(it
em) : \ |
| 61 (((target) == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(it
em) : 0))) |
| 62 |
| 63 |
| 64 #define AR6001_LOCAL_COUNT_ADDRESS 0x0c014080 |
| 65 #define AR6002_LOCAL_COUNT_ADDRESS 0x00018080 |
| 66 #define AR6003_LOCAL_COUNT_ADDRESS 0x00018080 |
| 67 #define CPU_DBG_SEL_ADDRESS 0x00000483 |
| 68 #define CPU_DBG_ADDRESS 0x00000484 |
| 69 |
| 70 /* Compile the 4BYTE version of the window register setup routine, |
| 71 * This mitigates host interconnect issues with non-4byte aligned bus requests,
some |
| 72 * interconnects use bus adapters that impose strict limitations. |
| 73 * Since diag window access is not intended for performance critical operations,
the 4byte mode should |
| 74 * be satisfactory even though it generates 4X the bus activity. */ |
| 75 |
| 76 #ifdef USE_4BYTE_REGISTER_ACCESS |
| 77 |
| 78 /* set the window address register (using 4-byte register access ). */ |
| 79 A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 Registe
rAddr, A_UINT32 Address) |
| 80 { |
| 81 A_STATUS status; |
| 82 A_UINT8 addrValue[4]; |
| 83 A_INT32 i; |
| 84 |
| 85 /* write bytes 1,2,3 of the register to set the upper address bytes, the
LSB is written |
| 86 * last to initiate the access cycle */ |
| 87 |
| 88 for (i = 1; i <= 3; i++) { |
| 89 /* fill the buffer with the address byte value we want to hit 4 time
s*/ |
| 90 addrValue[0] = ((A_UINT8 *)&Address)[i]; |
| 91 addrValue[1] = addrValue[0]; |
| 92 addrValue[2] = addrValue[0]; |
| 93 addrValue[3] = addrValue[0]; |
| 94 |
| 95 /* hit each byte of the register address with a 4-byte write operati
on to the same address, |
| 96 * this is a harmless operation */ |
| 97 status = HIFReadWrite(hifDevice, |
| 98 RegisterAddr+i, |
| 99 addrValue, |
| 100 4, |
| 101 HIF_WR_SYNC_BYTE_FIX, |
| 102 NULL); |
| 103 if (status != A_OK) { |
| 104 break; |
| 105 } |
| 106 } |
| 107 |
| 108 if (status != A_OK) { |
| 109 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to win
dow reg: 0x%X \n", |
| 110 Address, RegisterAddr)); |
| 111 return status; |
| 112 } |
| 113 |
| 114 /* write the address register again, this time write the whole 4-byte va
lue. |
| 115 * The effect here is that the LSB write causes the cycle to start, the
extra |
| 116 * 3 byte write to bytes 1,2,3 has no effect since we are writing the sa
me values again */ |
| 117 status = HIFReadWrite(hifDevice, |
| 118 RegisterAddr, |
| 119 (A_UCHAR *)(&Address), |
| 120 4, |
| 121 HIF_WR_SYNC_BYTE_INC, |
| 122 NULL); |
| 123 |
| 124 if (status != A_OK) { |
| 125 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n"
, |
| 126 Address, RegisterAddr)); |
| 127 return status; |
| 128 } |
| 129 |
| 130 return A_OK; |
| 131 |
| 132 |
| 133 |
| 134 } |
| 135 |
| 136 |
| 137 #else |
| 138 |
| 139 /* set the window address register */ |
| 140 A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 Registe
rAddr, A_UINT32 Address) |
| 141 { |
| 142 A_STATUS status; |
| 143 |
| 144 /* write bytes 1,2,3 of the register to set the upper address bytes, the
LSB is written |
| 145 * last to initiate the access cycle */ |
| 146 status = HIFReadWrite(hifDevice, |
| 147 RegisterAddr+1, /* write upper 3 bytes */ |
| 148 ((A_UCHAR *)(&Address))+1, |
| 149 sizeof(A_UINT32)-1, |
| 150 HIF_WR_SYNC_BYTE_INC, |
| 151 NULL); |
| 152 |
| 153 if (status != A_OK) { |
| 154 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to win
dow reg: 0x%X \n", |
| 155 RegisterAddr, Address)); |
| 156 return status; |
| 157 } |
| 158 |
| 159 /* write the LSB of the register, this initiates the operation */ |
| 160 status = HIFReadWrite(hifDevice, |
| 161 RegisterAddr, |
| 162 (A_UCHAR *)(&Address), |
| 163 sizeof(A_UINT8), |
| 164 HIF_WR_SYNC_BYTE_INC, |
| 165 NULL); |
| 166 |
| 167 if (status != A_OK) { |
| 168 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n"
, |
| 169 RegisterAddr, Address)); |
| 170 return status; |
| 171 } |
| 172 |
| 173 return A_OK; |
| 174 } |
| 175 |
| 176 #endif |
| 177 |
| 178 /* |
| 179 * Read from the AR6000 through its diagnostic window. |
| 180 * No cooperation from the Target is required for this. |
| 181 */ |
| 182 A_STATUS |
| 183 ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data) |
| 184 { |
| 185 A_STATUS status; |
| 186 |
| 187 /* set window register to start read cycle */ |
| 188 status = ar6000_SetAddressWindowRegister(hifDevice, |
| 189 WINDOW_READ_ADDR_ADDRESS, |
| 190 *address); |
| 191 |
| 192 if (status != A_OK) { |
| 193 return status; |
| 194 } |
| 195 |
| 196 /* read the data */ |
| 197 status = HIFReadWrite(hifDevice, |
| 198 WINDOW_DATA_ADDRESS, |
| 199 (A_UCHAR *)data, |
| 200 sizeof(A_UINT32), |
| 201 HIF_RD_SYNC_BYTE_INC, |
| 202 NULL); |
| 203 if (status != A_OK) { |
| 204 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n"))
; |
| 205 return status; |
| 206 } |
| 207 |
| 208 return status; |
| 209 } |
| 210 |
| 211 |
| 212 /* |
| 213 * Write to the AR6000 through its diagnostic window. |
| 214 * No cooperation from the Target is required for this. |
| 215 */ |
| 216 A_STATUS |
| 217 ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data) |
| 218 { |
| 219 A_STATUS status; |
| 220 |
| 221 /* set write data */ |
| 222 status = HIFReadWrite(hifDevice, |
| 223 WINDOW_DATA_ADDRESS, |
| 224 (A_UCHAR *)data, |
| 225 sizeof(A_UINT32), |
| 226 HIF_WR_SYNC_BYTE_INC, |
| 227 NULL); |
| 228 if (status != A_OK) { |
| 229 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\
n", *data)); |
| 230 return status; |
| 231 } |
| 232 |
| 233 /* set window register, which starts the write cycle */ |
| 234 return ar6000_SetAddressWindowRegister(hifDevice, |
| 235 WINDOW_WRITE_ADDR_ADDRESS, |
| 236 *address); |
| 237 } |
| 238 |
| 239 A_STATUS |
| 240 ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address, |
| 241 A_UCHAR *data, A_UINT32 length) |
| 242 { |
| 243 A_UINT32 count; |
| 244 A_STATUS status = A_OK; |
| 245 |
| 246 for (count = 0; count < length; count += 4, address += 4) { |
| 247 if ((status = ar6000_ReadRegDiag(hifDevice, &address, |
| 248 (A_UINT32 *)&data[count])) != A_OK) |
| 249 { |
| 250 break; |
| 251 } |
| 252 } |
| 253 |
| 254 return status; |
| 255 } |
| 256 |
| 257 A_STATUS |
| 258 ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address, |
| 259 A_UCHAR *data, A_UINT32 length) |
| 260 { |
| 261 A_UINT32 count; |
| 262 A_STATUS status = A_OK; |
| 263 |
| 264 for (count = 0; count < length; count += 4, address += 4) { |
| 265 if ((status = ar6000_WriteRegDiag(hifDevice, &address, |
| 266 (A_UINT32 *)&data[count])) != A_OK) |
| 267 { |
| 268 break; |
| 269 } |
| 270 } |
| 271 |
| 272 return status; |
| 273 } |
| 274 |
| 275 A_STATUS |
| 276 ar6k_ReadTargetRegister(HIF_DEVICE *hifDevice, int regsel, A_UINT32 *regval) |
| 277 { |
| 278 A_STATUS status; |
| 279 A_UCHAR vals[4]; |
| 280 A_UCHAR register_selection[4]; |
| 281 |
| 282 register_selection[0] = register_selection[1] = register_selection[2] = regi
ster_selection[3] = (regsel & 0xff); |
| 283 status = HIFReadWrite(hifDevice, |
| 284 CPU_DBG_SEL_ADDRESS, |
| 285 register_selection, |
| 286 4, |
| 287 HIF_WR_SYNC_BYTE_FIX, |
| 288 NULL); |
| 289 |
| 290 if (status != A_OK) { |
| 291 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write CPU_DBG_SEL (%d)\n", regsel)
); |
| 292 return status; |
| 293 } |
| 294 |
| 295 status = HIFReadWrite(hifDevice, |
| 296 CPU_DBG_ADDRESS, |
| 297 (A_UCHAR *)vals, |
| 298 sizeof(vals), |
| 299 HIF_RD_SYNC_BYTE_INC, |
| 300 NULL); |
| 301 if (status != A_OK) { |
| 302 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from CPU_DBG_ADDRESS\n")); |
| 303 return status; |
| 304 } |
| 305 |
| 306 *regval = vals[0]<<0 | vals[1]<<8 | vals[2]<<16 | vals[3]<<24; |
| 307 |
| 308 return status; |
| 309 } |
| 310 |
| 311 void |
| 312 ar6k_FetchTargetRegs(HIF_DEVICE *hifDevice, A_UINT32 *targregs) |
| 313 { |
| 314 int i; |
| 315 A_UINT32 val; |
| 316 |
| 317 for (i=0; i<AR6003_FETCH_TARG_REGS_COUNT; i++) { |
| 318 val=0xffffffff; |
| 319 (void)ar6k_ReadTargetRegister(hifDevice, i, &val); |
| 320 targregs[i] = val; |
| 321 } |
| 322 } |
| 323 |
| 324 #if 0 |
| 325 static A_STATUS |
| 326 _do_write_diag(HIF_DEVICE *hifDevice, A_UINT32 addr, A_UINT32 value) |
| 327 { |
| 328 A_STATUS status; |
| 329 |
| 330 status = ar6000_WriteRegDiag(hifDevice, &addr, &value); |
| 331 if (status != A_OK) |
| 332 { |
| 333 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot force Target to execute ROM!\n")); |
| 334 } |
| 335 |
| 336 return status; |
| 337 } |
| 338 #endif |
| 339 |
| 340 |
| 341 /* |
| 342 * Delay up to wait_msecs millisecs to allow Target to enter BMI phase, |
| 343 * which is a good sign that it's alive and well. This is used after |
| 344 * explicitly forcing the Target to reset. |
| 345 * |
| 346 * The wait_msecs time should be sufficiently long to cover any reasonable |
| 347 * boot-time delay. For instance, AR6001 firmware allow one second for a |
| 348 * low frequency crystal to settle before it calibrates the refclk frequency. |
| 349 * |
| 350 * TBD: Might want to add special handling for AR6K_OPTION_BMI_DISABLE. |
| 351 */ |
| 352 #if 0 |
| 353 static A_STATUS |
| 354 _delay_until_target_alive(HIF_DEVICE *hifDevice, A_INT32 wait_msecs, A_UINT32 Ta
rgetType) |
| 355 { |
| 356 A_INT32 actual_wait; |
| 357 A_INT32 i; |
| 358 A_UINT32 address; |
| 359 |
| 360 actual_wait = 0; |
| 361 |
| 362 /* Hardcode the address of LOCAL_COUNT_ADDRESS based on the target type */ |
| 363 if (TargetType == TARGET_TYPE_AR6001) { |
| 364 address = AR6001_LOCAL_COUNT_ADDRESS; |
| 365 } else if (TargetType == TARGET_TYPE_AR6002) { |
| 366 address = AR6002_LOCAL_COUNT_ADDRESS; |
| 367 } else if (TargetType == TARGET_TYPE_AR6003) { |
| 368 address = AR6003_LOCAL_COUNT_ADDRESS; |
| 369 } else { |
| 370 A_ASSERT(0); |
| 371 } |
| 372 address += 0x10; |
| 373 for (i=0; actual_wait < wait_msecs; i++) { |
| 374 A_UINT32 data; |
| 375 |
| 376 A_MDELAY(100); |
| 377 actual_wait += 100; |
| 378 |
| 379 data = 0; |
| 380 if (ar6000_ReadRegDiag(hifDevice, &address, &data) != A_OK) { |
| 381 return A_ERROR; |
| 382 } |
| 383 |
| 384 if (data != 0) { |
| 385 /* No need to wait longer -- we have a BMI credit */ |
| 386 return A_OK; |
| 387 } |
| 388 } |
| 389 return A_ERROR; /* timed out */ |
| 390 } |
| 391 #endif |
| 392 |
| 393 #define AR6001_RESET_CONTROL_ADDRESS 0x0C000000 |
| 394 #define AR6002_RESET_CONTROL_ADDRESS 0x00004000 |
| 395 #define AR6003_RESET_CONTROL_ADDRESS 0x00004000 |
| 396 /* reset device */ |
| 397 A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_BOOL
waitForCompletion, A_BOOL coldReset) |
| 398 { |
| 399 A_STATUS status = A_OK; |
| 400 A_UINT32 address; |
| 401 A_UINT32 data; |
| 402 |
| 403 do { |
| 404 // Workaround BEGIN |
| 405 // address = RESET_CONTROL_ADDRESS; |
| 406 |
| 407 if (coldReset) { |
| 408 data = RESET_CONTROL_COLD_RST_MASK; |
| 409 } |
| 410 else { |
| 411 data = RESET_CONTROL_MBOX_RST_MASK; |
| 412 } |
| 413 |
| 414 /* Hardcode the address of RESET_CONTROL_ADDRESS based on the target t
ype */ |
| 415 if (TargetType == TARGET_TYPE_AR6001) { |
| 416 address = AR6001_RESET_CONTROL_ADDRESS; |
| 417 } else if (TargetType == TARGET_TYPE_AR6002) { |
| 418 address = AR6002_RESET_CONTROL_ADDRESS; |
| 419 } else if (TargetType == TARGET_TYPE_AR6003) { |
| 420 address = AR6003_RESET_CONTROL_ADDRESS; |
| 421 } else { |
| 422 A_ASSERT(0); |
| 423 } |
| 424 |
| 425 |
| 426 status = ar6000_WriteRegDiag(hifDevice, &address, &data); |
| 427 |
| 428 if (A_FAILED(status)) { |
| 429 break; |
| 430 } |
| 431 |
| 432 if (!waitForCompletion) { |
| 433 break; |
| 434 } |
| 435 |
| 436 #if 0 |
| 437 /* Up to 2 second delay to allow things to settle down */ |
| 438 (void)_delay_until_target_alive(hifDevice, 2000, TargetType); |
| 439 |
| 440 /* |
| 441 * Read back the RESET CAUSE register to ensure that the cold reset |
| 442 * went through. |
| 443 */ |
| 444 |
| 445 // address = RESET_CAUSE_ADDRESS; |
| 446 /* Hardcode the address of RESET_CAUSE_ADDRESS based on the target type
*/ |
| 447 if (TargetType == TARGET_TYPE_AR6001) { |
| 448 address = 0x0C0000CC; |
| 449 } else if (TargetType == TARGET_TYPE_AR6002) { |
| 450 address = 0x000040C0; |
| 451 } else if (TargetType == TARGET_TYPE_AR6003) { |
| 452 address = 0x000040C0; |
| 453 } else { |
| 454 A_ASSERT(0); |
| 455 } |
| 456 |
| 457 data = 0; |
| 458 status = ar6000_ReadRegDiag(hifDevice, &address, &data); |
| 459 |
| 460 if (A_FAILED(status)) { |
| 461 break; |
| 462 } |
| 463 |
| 464 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Reset Cause readback: 0x%X \n",data)); |
| 465 data &= RESET_CAUSE_LAST_MASK; |
| 466 if (data != 2) { |
| 467 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Unable to cold reset the target \n"))
; |
| 468 } |
| 469 #endif |
| 470 // Workaroud END |
| 471 |
| 472 } while (FALSE); |
| 473 |
| 474 if (A_FAILED(status)) { |
| 475 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n")); |
| 476 } |
| 477 |
| 478 return A_OK; |
| 479 } |
| 480 |
| 481 #define REG_DUMP_COUNT_AR6001 38 /* WORDs, derived from AR600x_regdump.h */ |
| 482 #define REG_DUMP_COUNT_AR6002 32 |
| 483 #define REG_DUMP_COUNT_AR6003 60 |
| 484 #define REGISTER_DUMP_LEN_MAX 60 |
| 485 #if REG_DUMP_COUNT_AR6001 > REGISTER_DUMP_LEN_MAX |
| 486 #error "REG_DUMP_COUNT_AR6001 too large" |
| 487 #endif |
| 488 #if REG_DUMP_COUNT_AR6002 > REGISTER_DUMP_LEN_MAX |
| 489 #error "REG_DUMP_COUNT_AR6002 too large" |
| 490 #endif |
| 491 #if REG_DUMP_COUNT_AR6003 > REGISTER_DUMP_LEN_MAX |
| 492 #error "REG_DUMP_COUNT_AR6003 too large" |
| 493 #endif |
| 494 |
| 495 |
| 496 void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType) |
| 497 { |
| 498 A_UINT32 address; |
| 499 A_UINT32 regDumpArea = 0; |
| 500 A_STATUS status; |
| 501 A_UINT32 regDumpValues[REGISTER_DUMP_LEN_MAX]; |
| 502 A_UINT32 regDumpCount = 0; |
| 503 A_UINT32 i; |
| 504 |
| 505 do { |
| 506 |
| 507 /* the reg dump pointer is copied to the host interest area */ |
| 508 address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state); |
| 509 address = TARG_VTOP(TargetType, address); |
| 510 |
| 511 if (TargetType == TARGET_TYPE_AR6001) { |
| 512 /* for AR6001, this is a fixed location because the ptr is actua
lly stuck in cache, |
| 513 * this may be fixed in later firmware versions */ |
| 514 address = 0x18a0; |
| 515 regDumpCount = REG_DUMP_COUNT_AR6001; |
| 516 } else if (TargetType == TARGET_TYPE_AR6002) { |
| 517 regDumpCount = REG_DUMP_COUNT_AR6002; |
| 518 } else if (TargetType == TARGET_TYPE_AR6003) { |
| 519 regDumpCount = REG_DUMP_COUNT_AR6003; |
| 520 } else { |
| 521 A_ASSERT(0); |
| 522 } |
| 523 |
| 524 /* read RAM location through diagnostic window */ |
| 525 status = ar6000_ReadRegDiag(hifDevice, &address, ®DumpArea); |
| 526 |
| 527 if (A_FAILED(status)) { |
| 528 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register
dump area \n")); |
| 529 break; |
| 530 } |
| 531 |
| 532 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x
%X \n",regDumpArea)); |
| 533 |
| 534 if (regDumpArea == 0) { |
| 535 /* no reg dump */ |
| 536 break; |
| 537 } |
| 538 |
| 539 regDumpArea = TARG_VTOP(TargetType, regDumpArea); |
| 540 |
| 541 /* fetch register dump data */ |
| 542 status = ar6000_ReadDataDiag(hifDevice, |
| 543 regDumpArea, |
| 544 (A_UCHAR *)®DumpValues[0], |
| 545 regDumpCount * (sizeof(A_UINT32))); |
| 546 |
| 547 if (A_FAILED(status)) { |
| 548 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n
")); |
| 549 break; |
| 550 } |
| 551 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n")); |
| 552 |
| 553 for (i = 0; i < regDumpCount; i++) { |
| 554 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" %d : 0x%8.8X \n",i, regDumpValues[
i])); |
| 555 #ifdef UNDER_CE |
| 556 logPrintf(ATH_DEBUG_ERR," %d: 0x%8.8X \n",i, regDumpValues[i]); |
| 557 #endif |
| 558 } |
| 559 |
| 560 } while (FALSE); |
| 561 |
| 562 } |
| 563 |
| 564 /* set HTC/Mbox operational parameters, this can only be called when the target
is in the |
| 565 * BMI phase */ |
| 566 A_STATUS ar6000_set_htc_params(HIF_DEVICE *hifDevice, |
| 567 A_UINT32 TargetType, |
| 568 A_UINT32 MboxIsrYieldValue, |
| 569 A_UINT8 HtcControlBuffers) |
| 570 { |
| 571 A_STATUS status; |
| 572 A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX]; |
| 573 |
| 574 do { |
| 575 /* get the block sizes */ |
| 576 status = HIFConfigureDevice(hifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, |
| 577 blocksizes, sizeof(blocksizes)); |
| 578 |
| 579 if (A_FAILED(status)) { |
| 580 AR_DEBUG_PRINTF(ATH_LOG_ERR,("Failed to get block size info from HIF
layer...\n")); |
| 581 break; |
| 582 } |
| 583 /* note: we actually get the block size for mailbox 1, for SDIO the
block |
| 584 * size on mailbox 0 is artificially set to 1 */ |
| 585 /* must be a power of 2 */ |
| 586 A_ASSERT((blocksizes[1] & (blocksizes[1] - 1)) == 0); |
| 587 |
| 588 if (HtcControlBuffers != 0) { |
| 589 /* set override for number of control buffers to use */ |
| 590 blocksizes[1] |= ((A_UINT32)HtcControlBuffers) << 16; |
| 591 } |
| 592 |
| 593 /* set the host interest area for the block size */ |
| 594 status = BMIWriteMemory(hifDevice, |
| 595 HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_i
o_block_sz), |
| 596 (A_UCHAR *)&blocksizes[1], |
| 597 4); |
| 598 |
| 599 if (A_FAILED(status)) { |
| 600 AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for IO block size faile
d \n")); |
| 601 break; |
| 602 } |
| 603 |
| 604 AR_DEBUG_PRINTF(ATH_LOG_INF,("Block Size Set: %d (target address:0x%X)\n
", |
| 605 blocksizes[1], HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io
_block_sz))); |
| 606 |
| 607 if (MboxIsrYieldValue != 0) { |
| 608 /* set the host interest area for the mbox ISR yield limit */ |
| 609 status = BMIWriteMemory(hifDevice, |
| 610 HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mb
ox_isr_yield_limit), |
| 611 (A_UCHAR *)&MboxIsrYieldValue, |
| 612 4); |
| 613 |
| 614 if (A_FAILED(status)) { |
| 615 AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for yield limit fai
led \n")); |
| 616 break; |
| 617 } |
| 618 } |
| 619 |
| 620 } while (FALSE); |
| 621 |
| 622 return status; |
| 623 } |
| 624 |
| 625 |
| 626 static A_STATUS prepare_ar6002(HIF_DEVICE *hifDevice, A_UINT32 TargetVersion) |
| 627 { |
| 628 A_STATUS status = A_OK; |
| 629 |
| 630 /* placeholder */ |
| 631 |
| 632 return status; |
| 633 } |
| 634 |
| 635 static A_STATUS prepare_ar6003(HIF_DEVICE *hifDevice, A_UINT32 TargetVersion) |
| 636 { |
| 637 A_STATUS status = A_OK; |
| 638 |
| 639 /* placeholder */ |
| 640 |
| 641 return status; |
| 642 } |
| 643 |
| 644 /* this function assumes the caller has already initialized the BMI APIs */ |
| 645 A_STATUS ar6000_prepare_target(HIF_DEVICE *hifDevice, |
| 646 A_UINT32 TargetType, |
| 647 A_UINT32 TargetVersion) |
| 648 { |
| 649 if (TargetType == TARGET_TYPE_AR6002) { |
| 650 /* do any preparations for AR6002 devices */ |
| 651 return prepare_ar6002(hifDevice,TargetVersion); |
| 652 } else if (TargetType == TARGET_TYPE_AR6003) { |
| 653 return prepare_ar6003(hifDevice,TargetVersion); |
| 654 } |
| 655 |
| 656 return A_OK; |
| 657 } |
| 658 |
| 659 #if defined(CONFIG_AR6002_REV1_FORCE_HOST) |
| 660 /* |
| 661 * Call this function just before the call to BMIInit |
| 662 * in order to force* AR6002 rev 1.x firmware to detect a Host. |
| 663 * THIS IS FOR USE ONLY WITH AR6002 REV 1.x. |
| 664 * TBDXXX: Remove this function when REV 1.x is desupported. |
| 665 */ |
| 666 A_STATUS |
| 667 ar6002_REV1_reset_force_host (HIF_DEVICE *hifDevice) |
| 668 { |
| 669 A_INT32 i; |
| 670 struct forceROM_s { |
| 671 A_UINT32 addr; |
| 672 A_UINT32 data; |
| 673 }; |
| 674 struct forceROM_s *ForceROM; |
| 675 A_INT32 szForceROM; |
| 676 A_STATUS status = A_OK; |
| 677 A_UINT32 address; |
| 678 A_UINT32 data; |
| 679 |
| 680 /* Force AR6002 REV1.x to recognize Host presence. |
| 681 * |
| 682 * Note: Use RAM at 0x52df80..0x52dfa0 with ROM Remap entry 0 |
| 683 * so that this workaround functions with AR6002.war1.sh. We |
| 684 * could fold that entire workaround into this one, but it's not |
| 685 * worth the effort at this point. This workaround cannot be |
| 686 * merged into the other workaround because this must be done |
| 687 * before BMI. |
| 688 */ |
| 689 |
| 690 static struct forceROM_s ForceROM_NEW[] = { |
| 691 {0x52df80, 0x20f31c07}, |
| 692 {0x52df84, 0x92374420}, |
| 693 {0x52df88, 0x1d120c03}, |
| 694 {0x52df8c, 0xff8216f0}, |
| 695 {0x52df90, 0xf01d120c}, |
| 696 {0x52df94, 0x81004136}, |
| 697 {0x52df98, 0xbc9100bd}, |
| 698 {0x52df9c, 0x00bba100}, |
| 699 |
| 700 {0x00008000|MC_TCAM_TARGET_ADDRESS, 0x0012dfe0}, /* Use remap entry 0 */ |
| 701 {0x00008000|MC_TCAM_COMPARE_ADDRESS, 0x000e2380}, |
| 702 {0x00008000|MC_TCAM_MASK_ADDRESS, 0x00000000}, |
| 703 {0x00008000|MC_TCAM_VALID_ADDRESS, 0x00000001}, |
| 704 |
| 705 {0x00018000|(LOCAL_COUNT_ADDRESS+0x10), 0}, /* clear BMI credit counter
*/ |
| 706 |
| 707 {0x00004000|AR6002_RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK}, |
| 708 }; |
| 709 |
| 710 address = 0x004ed4b0; /* REV1 target software ID is stored here */ |
| 711 status = ar6000_ReadRegDiag(hifDevice, &address, &data); |
| 712 if (A_FAILED(status) || (data != AR6002_VERSION_REV1)) { |
| 713 return A_ERROR; /* Not AR6002 REV1 */ |
| 714 } |
| 715 |
| 716 ForceROM = ForceROM_NEW; |
| 717 szForceROM = sizeof(ForceROM_NEW)/sizeof(*ForceROM); |
| 718 |
| 719 ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Force Target to recognize H
ost....\n")); |
| 720 for (i = 0; i < szForceROM; i++) |
| 721 { |
| 722 if (ar6000_WriteRegDiag(hifDevice, |
| 723 &ForceROM[i].addr, |
| 724 &ForceROM[i].data) != A_OK) |
| 725 { |
| 726 ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Cannot force Target
to recognize Host!\n")); |
| 727 return A_ERROR; |
| 728 } |
| 729 } |
| 730 |
| 731 A_MDELAY(1000); |
| 732 |
| 733 return A_OK; |
| 734 } |
| 735 |
| 736 #endif /* CONFIG_AR6002_REV1_FORCE_HOST */ |
| 737 |
| 738 void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription) |
| 739 { |
| 740 A_CHAR stream[60]; |
| 741 A_CHAR byteOffsetStr[10]; |
| 742 A_UINT32 i; |
| 743 A_UINT16 offset, count, byteOffset; |
| 744 |
| 745 A_PRINTF("<---------Dumping %d Bytes : %s ------>\n", length, pDescription); |
| 746 |
| 747 count = 0; |
| 748 offset = 0; |
| 749 byteOffset = 0; |
| 750 for(i = 0; i < length; i++) { |
| 751 A_SPRINTF(stream + offset, "%2.2X ", buffer[i]); |
| 752 count ++; |
| 753 offset += 3; |
| 754 |
| 755 if(count == 16) { |
| 756 count = 0; |
| 757 offset = 0; |
| 758 A_SPRINTF(byteOffsetStr,"%4.4X",byteOffset); |
| 759 A_PRINTF("[%s]: %s\n", byteOffsetStr, stream); |
| 760 A_MEMZERO(stream, 60); |
| 761 byteOffset += 16; |
| 762 } |
| 763 } |
| 764 |
| 765 if(offset != 0) { |
| 766 A_SPRINTF(byteOffsetStr,"%4.4X",byteOffset); |
| 767 A_PRINTF("[%s]: %s\n", byteOffsetStr, stream); |
| 768 } |
| 769 |
| 770 A_PRINTF("<------------------------------------------------->\n"); |
| 771 } |
| 772 |
| 773 void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo) |
| 774 { |
| 775 int i; |
| 776 ATH_DEBUG_MASK_DESCRIPTION *pDesc; |
| 777 |
| 778 if (pInfo == NULL) { |
| 779 return; |
| 780 } |
| 781 |
| 782 pDesc = pInfo->pMaskDescriptions; |
| 783 |
| 784 A_PRINTF("========================================================\n\n"); |
| 785 A_PRINTF("Module Debug Info => Name : %s \n", pInfo->ModuleName); |
| 786 A_PRINTF(" => Descr. : %s \n", pInfo->ModuleDescription); |
| 787 A_PRINTF("\n Current mask => 0x%8.8X \n", pInfo->CurrentMask); |
| 788 A_PRINTF("\n Avail. Debug Masks :\n\n"); |
| 789 |
| 790 for (i = 0; i < pInfo->MaxDescriptions; i++,pDesc++) { |
| 791 A_PRINTF(" => 0x%8.8X -- %s \n", pDesc->Mask, pDesc->De
scription); |
| 792 } |
| 793 |
| 794 if (0 == i) { |
| 795 A_PRINTF(" => * none defined * \n"); |
| 796 } |
| 797 |
| 798 A_PRINTF("\n Standard Debug Masks :\n\n"); |
| 799 /* print standard masks */ |
| 800 A_PRINTF(" => 0x%8.8X -- Errors \n", ATH_DEBUG_ERR); |
| 801 A_PRINTF(" => 0x%8.8X -- Warnings \n", ATH_DEBUG_WARN); |
| 802 A_PRINTF(" => 0x%8.8X -- Informational \n", ATH_DEBUG_INFO)
; |
| 803 A_PRINTF(" => 0x%8.8X -- Tracing \n", ATH_DEBUG_TRC); |
| 804 A_PRINTF("\n========================================================\n"); |
| 805 |
| 806 } |
| 807 |
| 808 |
| 809 static ATH_DEBUG_MODULE_DBG_INFO *FindModule(A_CHAR *module_name) |
| 810 { |
| 811 ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead; |
| 812 |
| 813 if (!g_ModuleDebugInit) { |
| 814 return NULL; |
| 815 } |
| 816 |
| 817 while (pInfo != NULL) { |
| 818 /* TODO: need to use something other than strlen */ |
| 819 if (A_MEMCMP(pInfo->ModuleName,module_name,strlen(module_name)) == 0) { |
| 820 break; |
| 821 } |
| 822 pInfo = pInfo->pNext; |
| 823 } |
| 824 |
| 825 return pInfo; |
| 826 } |
| 827 |
| 828 |
| 829 void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo) |
| 830 { |
| 831 if (!g_ModuleDebugInit) { |
| 832 return; |
| 833 } |
| 834 |
| 835 A_MUTEX_LOCK(&g_ModuleListLock); |
| 836 |
| 837 if (!(pInfo->Flags & ATH_DEBUG_INFO_FLAGS_REGISTERED)) { |
| 838 if (g_pModuleInfoHead == NULL) { |
| 839 g_pModuleInfoHead = pInfo; |
| 840 } else { |
| 841 pInfo->pNext = g_pModuleInfoHead; |
| 842 g_pModuleInfoHead = pInfo; |
| 843 } |
| 844 pInfo->Flags |= ATH_DEBUG_INFO_FLAGS_REGISTERED; |
| 845 } |
| 846 |
| 847 A_MUTEX_UNLOCK(&g_ModuleListLock); |
| 848 } |
| 849 |
| 850 void a_dump_module_debug_info_by_name(A_CHAR *module_name) |
| 851 { |
| 852 ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead; |
| 853 |
| 854 if (!g_ModuleDebugInit) { |
| 855 return; |
| 856 } |
| 857 |
| 858 if (A_MEMCMP(module_name,"all",3) == 0) { |
| 859 /* dump all */ |
| 860 while (pInfo != NULL) { |
| 861 a_dump_module_debug_info(pInfo); |
| 862 pInfo = pInfo->pNext; |
| 863 } |
| 864 return; |
| 865 } |
| 866 |
| 867 pInfo = FindModule(module_name); |
| 868 |
| 869 if (pInfo != NULL) { |
| 870 a_dump_module_debug_info(pInfo); |
| 871 } |
| 872 |
| 873 } |
| 874 |
| 875 A_STATUS a_get_module_mask(A_CHAR *module_name, A_UINT32 *pMask) |
| 876 { |
| 877 ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name); |
| 878 |
| 879 if (NULL == pInfo) { |
| 880 return A_ERROR; |
| 881 } |
| 882 |
| 883 *pMask = pInfo->CurrentMask; |
| 884 return A_OK; |
| 885 } |
| 886 |
| 887 A_STATUS a_set_module_mask(A_CHAR *module_name, A_UINT32 Mask) |
| 888 { |
| 889 ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name); |
| 890 |
| 891 if (NULL == pInfo) { |
| 892 return A_ERROR; |
| 893 } |
| 894 |
| 895 pInfo->CurrentMask = Mask; |
| 896 A_PRINTF("Module %s, new mask: 0x%8.8X \n",module_name,pInfo->CurrentMask); |
| 897 return A_OK; |
| 898 } |
| 899 |
| 900 |
| 901 void a_module_debug_support_init(void) |
| 902 { |
| 903 if (g_ModuleDebugInit) { |
| 904 return; |
| 905 } |
| 906 A_MUTEX_INIT(&g_ModuleListLock); |
| 907 g_pModuleInfoHead = NULL; |
| 908 g_ModuleDebugInit = TRUE; |
| 909 A_REGISTER_MODULE_DEBUG_INFO(misc); |
| 910 } |
| 911 |
| 912 void a_module_debug_support_cleanup(void) |
| 913 { |
| 914 ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead; |
| 915 ATH_DEBUG_MODULE_DBG_INFO *pCur; |
| 916 |
| 917 if (!g_ModuleDebugInit) { |
| 918 return; |
| 919 } |
| 920 |
| 921 g_ModuleDebugInit = FALSE; |
| 922 |
| 923 A_MUTEX_LOCK(&g_ModuleListLock); |
| 924 |
| 925 while (pInfo != NULL) { |
| 926 pCur = pInfo; |
| 927 pInfo = pInfo->pNext; |
| 928 pCur->pNext = NULL; |
| 929 /* clear registered flag */ |
| 930 pCur->Flags &= ~ATH_DEBUG_INFO_FLAGS_REGISTERED; |
| 931 } |
| 932 |
| 933 A_MUTEX_UNLOCK(&g_ModuleListLock); |
| 934 |
| 935 A_MUTEX_DELETE(&g_ModuleListLock); |
| 936 g_pModuleInfoHead = NULL; |
| 937 } |
| 938 |
| 939 /* can only be called during bmi init stage */ |
| 940 A_STATUS ar6000_set_hci_bridge_flags(HIF_DEVICE *hifDevice, |
| 941 A_UINT32 TargetType, |
| 942 A_UINT32 Flags) |
| 943 { |
| 944 A_STATUS status = A_OK; |
| 945 |
| 946 do { |
| 947 |
| 948 if (TargetType != TARGET_TYPE_AR6003) { |
| 949 AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Target Type:%d, does not support H
CI bridging! \n", |
| 950 TargetType)); |
| 951 break; |
| 952 } |
| 953 |
| 954 /* set hci bridge flags */ |
| 955 status = BMIWriteMemory(hifDevice, |
| 956 HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_hci_br
idge_flags), |
| 957 (A_UCHAR *)&Flags, |
| 958 4); |
| 959 |
| 960 |
| 961 } while (FALSE); |
| 962 |
| 963 return status; |
| 964 } |
| 965 |
OLD | NEW |