4 * Copyright (c) 2004-2007 Atheros Communications Inc.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation;
12 * Software distributed under the License is distributed on an "AS
13 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * rights and limitations under the License.
24 #include "AR6Khwreg.h"
25 #include "targaddrs.h"
31 #include "common_drv.h"
33 #include "targaddrs.h"
35 #define HOST_INTEREST_ITEM_ADDRESS(target, item) \
36 (((TargetType) == TARGET_TYPE_AR6001) ? \
37 AR6001_HOST_INTEREST_ITEM_ADDRESS(item) : \
38 AR6002_HOST_INTEREST_ITEM_ADDRESS(item))
41 /* Compile the 4BYTE version of the window register setup routine,
42 * This mitigates host interconnect issues with non-4byte aligned bus requests, some
43 * interconnects use bus adapters that impose strict limitations.
44 * Since diag window access is not intended for performance critical operations, the 4byte mode should
45 * be satisfactory even though it generates 4X the bus activity. */
47 #ifdef USE_4BYTE_REGISTER_ACCESS
49 /* set the window address register (using 4-byte register access ). */
50 A_STATUS
ar6000_SetAddressWindowRegister(HIF_DEVICE
*hifDevice
, A_UINT32 RegisterAddr
, A_UINT32 Address
)
56 /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
57 * last to initiate the access cycle */
59 for (i
= 1; i
<= 3; i
++) {
60 /* fill the buffer with the address byte value we want to hit 4 times*/
61 addrValue
[0] = ((A_UINT8
*)&Address
)[i
];
62 addrValue
[1] = addrValue
[0];
63 addrValue
[2] = addrValue
[0];
64 addrValue
[3] = addrValue
[0];
66 /* hit each byte of the register address with a 4-byte write operation to the same address,
67 * this is a harmless operation */
68 status
= HIFReadWrite(hifDevice
,
80 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
81 RegisterAddr
, Address
));
85 /* write the address register again, this time write the whole 4-byte value.
86 * The effect here is that the LSB write causes the cycle to start, the extra
87 * 3 byte write to bytes 1,2,3 has no effect since we are writing the same values again */
88 status
= HIFReadWrite(hifDevice
,
90 (A_UCHAR
*)(&Address
),
96 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Cannot write 0x%x to window reg: 0x%X \n",
97 RegisterAddr
, Address
));
110 /* set the window address register */
111 A_STATUS
ar6000_SetAddressWindowRegister(HIF_DEVICE
*hifDevice
, A_UINT32 RegisterAddr
, A_UINT32 Address
)
115 /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
116 * last to initiate the access cycle */
117 status
= HIFReadWrite(hifDevice
,
118 RegisterAddr
+1, /* write upper 3 bytes */
119 ((A_UCHAR
*)(&Address
))+1,
121 HIF_WR_SYNC_BYTE_INC
,
124 if (status
!= A_OK
) {
125 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
126 RegisterAddr
, Address
));
130 /* write the LSB of the register, this initiates the operation */
131 status
= HIFReadWrite(hifDevice
,
133 (A_UCHAR
*)(&Address
),
135 HIF_WR_SYNC_BYTE_INC
,
138 if (status
!= A_OK
) {
139 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Cannot write 0x%x to window reg: 0x%X \n",
140 RegisterAddr
, Address
));
150 * Read from the AR6000 through its diagnostic window.
151 * No cooperation from the Target is required for this.
154 ar6000_ReadRegDiag(HIF_DEVICE
*hifDevice
, A_UINT32
*address
, A_UINT32
*data
)
158 /* set window register to start read cycle */
159 status
= ar6000_SetAddressWindowRegister(hifDevice
,
160 WINDOW_READ_ADDR_ADDRESS
,
163 if (status
!= A_OK
) {
168 status
= HIFReadWrite(hifDevice
,
172 HIF_RD_SYNC_BYTE_INC
,
174 if (status
!= A_OK
) {
175 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Cannot read from WINDOW_DATA_ADDRESS\n"));
184 * Write to the AR6000 through its diagnostic window.
185 * No cooperation from the Target is required for this.
188 ar6000_WriteRegDiag(HIF_DEVICE
*hifDevice
, A_UINT32
*address
, A_UINT32
*data
)
193 status
= HIFReadWrite(hifDevice
,
197 HIF_WR_SYNC_BYTE_INC
,
199 if (status
!= A_OK
) {
200 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", *data
));
204 /* set window register, which starts the write cycle */
205 return ar6000_SetAddressWindowRegister(hifDevice
,
206 WINDOW_WRITE_ADDR_ADDRESS
,
211 ar6000_ReadDataDiag(HIF_DEVICE
*hifDevice
, A_UINT32 address
,
212 A_UCHAR
*data
, A_UINT32 length
)
215 A_STATUS status
= A_OK
;
217 for (count
= 0; count
< length
; count
+= 4, address
+= 4) {
218 if ((status
= ar6000_ReadRegDiag(hifDevice
, &address
,
219 (A_UINT32
*)&data
[count
])) != A_OK
)
229 ar6000_WriteDataDiag(HIF_DEVICE
*hifDevice
, A_UINT32 address
,
230 A_UCHAR
*data
, A_UINT32 length
)
233 A_STATUS status
= A_OK
;
235 for (count
= 0; count
< length
; count
+= 4, address
+= 4) {
236 if ((status
= ar6000_WriteRegDiag(hifDevice
, &address
,
237 (A_UINT32
*)&data
[count
])) != A_OK
)
247 ar6000_reset_device_skipflash(HIF_DEVICE
*hifDevice
)
254 struct forceROM_s
*ForceROM
;
256 A_UINT32 instruction
;
258 static struct forceROM_s ForceROM_REV2
[] = {
259 /* NB: This works for old REV2 ROM (old). */
260 {0x00001ff0, 0x175b0027}, /* jump instruction at 0xa0001ff0 */
261 {0x00001ff4, 0x00000000}, /* nop instruction at 0xa0001ff4 */
263 {MC_REMAP_TARGET_ADDRESS
, 0x00001ff0}, /* remap to 0xa0001ff0 */
264 {MC_REMAP_COMPARE_ADDRESS
, 0x01000040},/* ...from 0xbfc00040 */
265 {MC_REMAP_SIZE_ADDRESS
, 0x00000000}, /* ...1 cache line */
266 {MC_REMAP_VALID_ADDRESS
, 0x00000001}, /* ...remap is valid */
268 {LOCAL_COUNT_ADDRESS
+0x10, 0}, /* clear BMI credit counter */
270 {RESET_CONTROL_ADDRESS
, RESET_CONTROL_WARM_RST_MASK
},
273 static struct forceROM_s ForceROM_NEW
[] = {
274 /* NB: This works for AR6000 ROM REV3 and beyond. */
275 {LOCAL_SCRATCH_ADDRESS
, AR6K_OPTION_IGNORE_FLASH
},
276 {LOCAL_COUNT_ADDRESS
+0x10, 0}, /* clear BMI credit counter */
277 {RESET_CONTROL_ADDRESS
, RESET_CONTROL_WARM_RST_MASK
},
281 * Examine a semi-arbitrary instruction that's different
282 * in REV2 and other revisions.
283 * NB: If a Host port does not require simultaneous support
284 * for multiple revisions of Target ROM, this code can be elided.
286 (void)ar6000_ReadDataDiag(hifDevice
, 0x01000040,
287 (A_UCHAR
*)&instruction
, 4);
289 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("instruction=0x%x\n", instruction
));
291 if (instruction
== 0x3c1aa200) {
292 /* It's an old ROM */
293 ForceROM
= ForceROM_REV2
;
294 szForceROM
= sizeof(ForceROM_REV2
)/sizeof(*ForceROM
);
295 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Using OLD method\n"));
297 ForceROM
= ForceROM_NEW
;
298 szForceROM
= sizeof(ForceROM_NEW
)/sizeof(*ForceROM
);
299 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Using NEW method\n"));
302 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Force Target to execute from ROM....\n"));
303 for (i
= 0; i
< szForceROM
; i
++)
305 if (ar6000_WriteRegDiag(hifDevice
,
307 &ForceROM
[i
].data
) != A_OK
)
309 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Cannot force Target to execute ROM!\n"));
314 msleep(50); /* delay to allow dragon to come to BMI phase */
319 A_STATUS
ar6000_reset_device(HIF_DEVICE
*hifDevice
, A_UINT32 TargetType
)
323 A_STATUS status
= A_OK
;
329 // address = RESET_CONTROL_ADDRESS;
330 data
= RESET_CONTROL_COLD_RST_MASK
;
332 /* Hardcode the address of RESET_CONTROL_ADDRESS based on the target type */
333 if (TargetType
== TARGET_TYPE_AR6001
) {
334 address
= 0x0C000000;
336 if (TargetType
== TARGET_TYPE_AR6002
) {
337 address
= 0x00004000;
343 status
= ar6000_WriteRegDiag(hifDevice
, &address
, &data
);
345 if (A_FAILED(status
)) {
350 * Read back the RESET CAUSE register to ensure that the cold reset
353 msleep(2000); /* 2 second delay to allow things to settle down */
356 // address = RESET_CAUSE_ADDRESS;
357 /* Hardcode the address of RESET_CAUSE_ADDRESS based on the target type */
358 if (TargetType
== TARGET_TYPE_AR6001
) {
359 address
= 0x0C0000CC;
361 if (TargetType
== TARGET_TYPE_AR6002
) {
362 address
= 0x000040C0;
369 status
= ar6000_ReadRegDiag(hifDevice
, &address
, &data
);
371 if (A_FAILED(status
)) {
375 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Reset Cause readback: 0x%X \n",data
));
376 data
&= RESET_CAUSE_LAST_MASK
;
378 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Unable to cold reset the target \n"));
383 if (A_FAILED(status
)) {
384 AR_DEBUG_PRINTF(ATH_LOG_ERR
, ("Failed to reset target \n"));
390 #define REG_DUMP_COUNT_AR6001 38 /* WORDs, derived from AR6001_regdump.h */
391 #define REG_DUMP_COUNT_AR6002 32 /* WORDs, derived from AR6002_regdump.h */
394 #if REG_DUMP_COUNT_AR6001 <= REG_DUMP_COUNT_AR6002
395 #define REGISTER_DUMP_LEN_MAX REG_DUMP_COUNT_AR6002
397 #define REGISTER_DUMP_LEN_MAX REG_DUMP_COUNT_AR6001
400 void ar6000_dump_target_assert_info(HIF_DEVICE
*hifDevice
, A_UINT32 TargetType
)
403 A_UINT32 regDumpArea
= 0;
405 A_UINT32 regDumpValues
[REGISTER_DUMP_LEN_MAX
];
406 A_UINT32 regDumpCount
= 0;
411 /* the reg dump pointer is copied to the host interest area */
412 address
= HOST_INTEREST_ITEM_ADDRESS(TargetType
, hi_failure_state
);
414 if (TargetType
== TARGET_TYPE_AR6001
) {
415 /* for AR6001, this is a fixed location because the ptr is actually stuck in cache,
416 * this may be fixed in later firmware versions */
418 regDumpCount
= REG_DUMP_COUNT_AR6001
;
420 } else if (TargetType
== TARGET_TYPE_AR6002
) {
422 regDumpCount
= REG_DUMP_COUNT_AR6002
;
428 /* read RAM location through diagnostic window */
429 status
= ar6000_ReadRegDiag(hifDevice
, &address
, ®DumpArea
);
431 if (A_FAILED(status
)) {
432 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("AR6K: Failed to get ptr to register dump area \n"));
436 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("AR6K: Location of register dump data: 0x%X \n",regDumpArea
));
438 if (regDumpArea
== 0) {
443 if (TargetType
== TARGET_TYPE_AR6001
) {
444 regDumpArea
&= 0x0FFFFFFF; /* convert to physical address in target memory */
447 /* fetch register dump data */
448 status
= ar6000_ReadDataDiag(hifDevice
,
450 (A_UCHAR
*)®DumpValues
[0],
451 regDumpCount
* (sizeof(A_UINT32
)));
453 if (A_FAILED(status
)) {
454 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("AR6K: Failed to get register dump \n"));
458 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,("AR6K: Register Dump: \n"));
460 for (i
= 0; i
< regDumpCount
; i
++) {
461 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
,(" %d : 0x%8.8X \n",i
, regDumpValues
[i
]));