when changing the mac address of a bridge interface, keep member interface addresses...
[openwrt.git] / target / linux / s3c24xx / files-2.6.30 / drivers / ar6000 / miscdrv / common_drv.c
1
2 /*
3 *
4 * Copyright (c) 2004-2007 Atheros Communications Inc.
5 * All rights reserved.
6 *
7 *
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;
11 *
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.
16 *
17 *
18 *
19 */
20
21 #include "a_config.h"
22 #include "athdefs.h"
23 #include "a_types.h"
24 #include "AR6Khwreg.h"
25 #include "targaddrs.h"
26 #include "a_osapi.h"
27 #include "hif.h"
28 #include "htc_api.h"
29 #include "bmi.h"
30 #include "bmi_msg.h"
31 #include "common_drv.h"
32 #include "a_debug.h"
33 #include "targaddrs.h"
34
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))
39
40
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. */
46
47 #ifdef USE_4BYTE_REGISTER_ACCESS
48
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)
51 {
52 A_STATUS status;
53 A_UINT8 addrValue[4];
54 int i;
55
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 */
58
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];
65
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,
69 RegisterAddr+i,
70 addrValue,
71 4,
72 HIF_WR_SYNC_BYTE_FIX,
73 NULL);
74 if (status != A_OK) {
75 break;
76 }
77 }
78
79 if (status != A_OK) {
80 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
81 RegisterAddr, Address));
82 return status;
83 }
84
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,
89 RegisterAddr,
90 (A_UCHAR *)(&Address),
91 4,
92 HIF_WR_SYNC_BYTE_INC,
93 NULL);
94
95 if (status != A_OK) {
96 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
97 RegisterAddr, Address));
98 return status;
99 }
100
101 return A_OK;
102
103
104
105 }
106
107
108 #else
109
110 /* set the window address register */
111 A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
112 {
113 A_STATUS status;
114
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,
120 sizeof(A_UINT32)-1,
121 HIF_WR_SYNC_BYTE_INC,
122 NULL);
123
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));
127 return status;
128 }
129
130 /* write the LSB of the register, this initiates the operation */
131 status = HIFReadWrite(hifDevice,
132 RegisterAddr,
133 (A_UCHAR *)(&Address),
134 sizeof(A_UINT8),
135 HIF_WR_SYNC_BYTE_INC,
136 NULL);
137
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));
141 return status;
142 }
143
144 return A_OK;
145 }
146
147 #endif
148
149 /*
150 * Read from the AR6000 through its diagnostic window.
151 * No cooperation from the Target is required for this.
152 */
153 A_STATUS
154 ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
155 {
156 A_STATUS status;
157
158 /* set window register to start read cycle */
159 status = ar6000_SetAddressWindowRegister(hifDevice,
160 WINDOW_READ_ADDR_ADDRESS,
161 *address);
162
163 if (status != A_OK) {
164 return status;
165 }
166
167 /* read the data */
168 status = HIFReadWrite(hifDevice,
169 WINDOW_DATA_ADDRESS,
170 (A_UCHAR *)data,
171 sizeof(A_UINT32),
172 HIF_RD_SYNC_BYTE_INC,
173 NULL);
174 if (status != A_OK) {
175 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n"));
176 return status;
177 }
178
179 return status;
180 }
181
182
183 /*
184 * Write to the AR6000 through its diagnostic window.
185 * No cooperation from the Target is required for this.
186 */
187 A_STATUS
188 ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
189 {
190 A_STATUS status;
191
192 /* set write data */
193 status = HIFReadWrite(hifDevice,
194 WINDOW_DATA_ADDRESS,
195 (A_UCHAR *)data,
196 sizeof(A_UINT32),
197 HIF_WR_SYNC_BYTE_INC,
198 NULL);
199 if (status != A_OK) {
200 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", *data));
201 return status;
202 }
203
204 /* set window register, which starts the write cycle */
205 return ar6000_SetAddressWindowRegister(hifDevice,
206 WINDOW_WRITE_ADDR_ADDRESS,
207 *address);
208 }
209
210 A_STATUS
211 ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
212 A_UCHAR *data, A_UINT32 length)
213 {
214 A_UINT32 count;
215 A_STATUS status = A_OK;
216
217 for (count = 0; count < length; count += 4, address += 4) {
218 if ((status = ar6000_ReadRegDiag(hifDevice, &address,
219 (A_UINT32 *)&data[count])) != A_OK)
220 {
221 break;
222 }
223 }
224
225 return status;
226 }
227
228 A_STATUS
229 ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
230 A_UCHAR *data, A_UINT32 length)
231 {
232 A_UINT32 count;
233 A_STATUS status = A_OK;
234
235 for (count = 0; count < length; count += 4, address += 4) {
236 if ((status = ar6000_WriteRegDiag(hifDevice, &address,
237 (A_UINT32 *)&data[count])) != A_OK)
238 {
239 break;
240 }
241 }
242
243 return status;
244 }
245
246 A_STATUS
247 ar6000_reset_device_skipflash(HIF_DEVICE *hifDevice)
248 {
249 int i;
250 struct forceROM_s {
251 A_UINT32 addr;
252 A_UINT32 data;
253 };
254 struct forceROM_s *ForceROM;
255 int szForceROM;
256 A_UINT32 instruction;
257
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 */
262
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 */
267
268 {LOCAL_COUNT_ADDRESS+0x10, 0}, /* clear BMI credit counter */
269
270 {RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK},
271 };
272
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},
278 };
279
280 /*
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.
285 */
286 (void)ar6000_ReadDataDiag(hifDevice, 0x01000040,
287 (A_UCHAR *)&instruction, 4);
288
289 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("instruction=0x%x\n", instruction));
290
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"));
296 } else {
297 ForceROM = ForceROM_NEW;
298 szForceROM = sizeof(ForceROM_NEW)/sizeof(*ForceROM);
299 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Using NEW method\n"));
300 }
301
302 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Force Target to execute from ROM....\n"));
303 for (i = 0; i < szForceROM; i++)
304 {
305 if (ar6000_WriteRegDiag(hifDevice,
306 &ForceROM[i].addr,
307 &ForceROM[i].data) != A_OK)
308 {
309 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot force Target to execute ROM!\n"));
310 return A_ERROR;
311 }
312 }
313
314 msleep(50); /* delay to allow dragon to come to BMI phase */
315 return A_OK;
316 }
317
318 /* reset device */
319 A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
320 {
321
322 #if !defined(DWSIM)
323 A_STATUS status = A_OK;
324 A_UINT32 address;
325 A_UINT32 data;
326
327 do {
328
329 // address = RESET_CONTROL_ADDRESS;
330 data = RESET_CONTROL_COLD_RST_MASK;
331
332 /* Hardcode the address of RESET_CONTROL_ADDRESS based on the target type */
333 if (TargetType == TARGET_TYPE_AR6001) {
334 address = 0x0C000000;
335 } else {
336 if (TargetType == TARGET_TYPE_AR6002) {
337 address = 0x00004000;
338 } else {
339 A_ASSERT(0);
340 }
341 }
342
343 status = ar6000_WriteRegDiag(hifDevice, &address, &data);
344
345 if (A_FAILED(status)) {
346 break;
347 }
348
349 /*
350 * Read back the RESET CAUSE register to ensure that the cold reset
351 * went through.
352 */
353 msleep(2000); /* 2 second delay to allow things to settle down */
354
355
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;
360 } else {
361 if (TargetType == TARGET_TYPE_AR6002) {
362 address = 0x000040C0;
363 } else {
364 A_ASSERT(0);
365 }
366 }
367
368 data = 0;
369 status = ar6000_ReadRegDiag(hifDevice, &address, &data);
370
371 if (A_FAILED(status)) {
372 break;
373 }
374
375 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Reset Cause readback: 0x%X \n",data));
376 data &= RESET_CAUSE_LAST_MASK;
377 if (data != 2) {
378 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Unable to cold reset the target \n"));
379 }
380
381 } while (FALSE);
382
383 if (A_FAILED(status)) {
384 AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n"));
385 }
386 #endif
387 return A_OK;
388 }
389
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 */
392
393
394 #if REG_DUMP_COUNT_AR6001 <= REG_DUMP_COUNT_AR6002
395 #define REGISTER_DUMP_LEN_MAX REG_DUMP_COUNT_AR6002
396 #else
397 #define REGISTER_DUMP_LEN_MAX REG_DUMP_COUNT_AR6001
398 #endif
399
400 void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
401 {
402 A_UINT32 address;
403 A_UINT32 regDumpArea = 0;
404 A_STATUS status;
405 A_UINT32 regDumpValues[REGISTER_DUMP_LEN_MAX];
406 A_UINT32 regDumpCount = 0;
407 A_UINT32 i;
408
409 do {
410
411 /* the reg dump pointer is copied to the host interest area */
412 address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state);
413
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 */
417 address = 0x18a0;
418 regDumpCount = REG_DUMP_COUNT_AR6001;
419
420 } else if (TargetType == TARGET_TYPE_AR6002) {
421
422 regDumpCount = REG_DUMP_COUNT_AR6002;
423
424 } else {
425 A_ASSERT(0);
426 }
427
428 /* read RAM location through diagnostic window */
429 status = ar6000_ReadRegDiag(hifDevice, &address, &regDumpArea);
430
431 if (A_FAILED(status)) {
432 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n"));
433 break;
434 }
435
436 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x%X \n",regDumpArea));
437
438 if (regDumpArea == 0) {
439 /* no reg dump */
440 break;
441 }
442
443 if (TargetType == TARGET_TYPE_AR6001) {
444 regDumpArea &= 0x0FFFFFFF; /* convert to physical address in target memory */
445 }
446
447 /* fetch register dump data */
448 status = ar6000_ReadDataDiag(hifDevice,
449 regDumpArea,
450 (A_UCHAR *)&regDumpValues[0],
451 regDumpCount * (sizeof(A_UINT32)));
452
453 if (A_FAILED(status)) {
454 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n"));
455 break;
456 }
457
458 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n"));
459
460 for (i = 0; i < regDumpCount; i++) {
461 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" %d : 0x%8.8X \n",i, regDumpValues[i]));
462 }
463
464 } while (FALSE);
465
466 }
467
This page took 0.095056 seconds and 5 git commands to generate.