Root/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 ). */
50A_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 */
111A_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 */
153A_STATUS
154ar6000_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 */
187A_STATUS
188ar6000_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
210A_STATUS
211ar6000_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
228A_STATUS
229ar6000_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
246A_STATUS
247ar6000_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 */
319A_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
400void 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
468

Archive Download this file



interactive