[x86] add rootwait option to the kernel command line (#6209)
[openwrt.git] / target / linux / s3c24xx / files-2.6.31 / 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