Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelv...
[pandora-kernel.git] / drivers / staging / ath6kl / bmi / src / bmi.c
1 //------------------------------------------------------------------------------
2 // <copyright file="bmi.c" company="Atheros">
3 //    Copyright (c) 2004-2010 Atheros Corporation.  All rights reserved.
4 // 
5 //
6 // Permission to use, copy, modify, and/or distribute this software for any
7 // purpose with or without fee is hereby granted, provided that the above
8 // copyright notice and this permission notice appear in all copies.
9 //
10 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 //
18 //
19 //------------------------------------------------------------------------------
20 //==============================================================================
21 //
22 // Author(s): ="Atheros"
23 //==============================================================================
24
25
26 #ifdef THREAD_X
27 #include <string.h>
28 #endif
29
30 #include "hif.h"
31 #include "bmi.h"
32 #include "htc_api.h"
33 #include "bmi_internal.h"
34
35 #ifdef ATH_DEBUG_MODULE
36 static ATH_DEBUG_MASK_DESCRIPTION bmi_debug_desc[] = {
37     { ATH_DEBUG_BMI , "BMI Tracing"},
38 };
39
40 ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi,
41                                  "bmi",
42                                  "Boot Manager Interface",
43                                  ATH_DEBUG_MASK_DEFAULTS,
44                                  ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc),
45                                  bmi_debug_desc);
46                                  
47 #endif
48
49 /*
50 Although we had envisioned BMI to run on top of HTC, this is not how the
51 final implementation ended up. On the Target side, BMI is a part of the BSP
52 and does not use the HTC protocol nor even DMA -- it is intentionally kept
53 very simple.
54 */
55
56 static A_BOOL pendingEventsFuncCheck = FALSE; 
57 static A_UINT32 *pBMICmdCredits;
58 static A_UCHAR *pBMICmdBuf;
59 #define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
60                        sizeof(A_UINT32) /* cmd */ + \
61                        sizeof(A_UINT32) /* addr */ + \
62                        sizeof(A_UINT32))/* length */
63 #define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ)
64     
65 /* APIs visible to the driver */
66 void
67 BMIInit(void)
68 {
69     bmiDone = FALSE;
70     pendingEventsFuncCheck = FALSE;
71
72     /*
73      * On some platforms, it's not possible to DMA to a static variable
74      * in a device driver (e.g. Linux loadable driver module).
75      * So we need to A_MALLOC space for "command credits" and for commands.
76      *
77      * Note: implicitly relies on A_MALLOC to provide a buffer that is
78      * suitable for DMA (or PIO).  This buffer will be passed down the
79      * bus stack.
80      */
81     if (!pBMICmdCredits) {
82         pBMICmdCredits = (A_UINT32 *)A_MALLOC_NOWAIT(4);
83         A_ASSERT(pBMICmdCredits);
84     }
85
86     if (!pBMICmdBuf) {
87         pBMICmdBuf = (A_UCHAR *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ);
88         A_ASSERT(pBMICmdBuf);
89     }
90     
91     A_REGISTER_MODULE_DEBUG_INFO(bmi);
92 }
93
94 void
95 BMICleanup(void)
96 {
97     if (pBMICmdCredits) {
98         A_FREE(pBMICmdCredits);
99         pBMICmdCredits = NULL;
100     }
101
102     if (pBMICmdBuf) {
103         A_FREE(pBMICmdBuf);
104         pBMICmdBuf = NULL;
105     }
106 }
107
108 A_STATUS
109 BMIDone(HIF_DEVICE *device)
110 {
111     A_STATUS status;
112     A_UINT32 cid;
113
114     if (bmiDone) {
115         AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n"));
116         return A_OK;
117     }
118
119     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device));
120     bmiDone = TRUE;
121     cid = BMI_DONE;
122
123     status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
124     if (status != A_OK) {
125         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
126         return A_ERROR;
127     }
128
129     if (pBMICmdCredits) {
130         A_FREE(pBMICmdCredits);
131         pBMICmdCredits = NULL;
132     }
133
134     if (pBMICmdBuf) {
135         A_FREE(pBMICmdBuf);
136         pBMICmdBuf = NULL;
137     }
138
139     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n"));
140
141     return A_OK;
142 }
143
144 A_STATUS
145 BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
146 {
147     A_STATUS status;
148     A_UINT32 cid;
149
150     if (bmiDone) {
151         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
152         return A_ERROR;
153     }
154
155     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device));
156     cid = BMI_GET_TARGET_INFO;
157
158     status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
159     if (status != A_OK) {
160         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
161         return A_ERROR;
162     }
163
164     status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_ver,
165                                                 sizeof(targ_info->target_ver), TRUE);
166     if (status != A_OK) {
167         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n"));
168         return A_ERROR;
169     }
170
171     if (targ_info->target_ver == TARGET_VERSION_SENTINAL) {
172         /* Determine how many bytes are in the Target's targ_info */
173         status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_info_byte_count,
174                                             sizeof(targ_info->target_info_byte_count), TRUE);
175         if (status != A_OK) {
176             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n"));
177             return A_ERROR;
178         }
179
180         /*
181          * The Target's targ_info doesn't match the Host's targ_info.
182          * We need to do some backwards compatibility work to make this OK.
183          */
184         A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info));
185
186         /* Read the remainder of the targ_info */
187         status = bmiBufferReceive(device,
188                         ((A_UCHAR *)targ_info)+sizeof(targ_info->target_info_byte_count),
189                         sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), TRUE);
190         if (status != A_OK) {
191             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n",
192                                                                 targ_info->target_info_byte_count));
193             return A_ERROR;
194         }
195     }
196
197     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
198                                                                 targ_info->target_ver, targ_info->target_type));
199
200     return A_OK;
201 }
202
203 A_STATUS
204 BMIReadMemory(HIF_DEVICE *device,
205               A_UINT32 address,
206               A_UCHAR *buffer,
207               A_UINT32 length)
208 {
209     A_UINT32 cid;
210     A_STATUS status;
211     A_UINT32 offset;
212     A_UINT32 remaining, rxlen;
213
214     A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)));
215     memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length));
216
217     if (bmiDone) {
218         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
219         return A_ERROR;
220     }
221
222     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
223                         ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
224                                 device, address, length));
225
226     cid = BMI_READ_MEMORY;
227
228     remaining = length;
229
230     while (remaining)
231     {
232         rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX;
233         offset = 0;
234         A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
235         offset += sizeof(cid);
236         A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
237         offset += sizeof(address);
238         A_MEMCPY(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen));
239         offset += sizeof(length);
240
241         status = bmiBufferSend(device, pBMICmdBuf, offset);
242         if (status != A_OK) {
243             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
244             return A_ERROR;
245         }
246         status = bmiBufferReceive(device, pBMICmdBuf, rxlen, TRUE);
247         if (status != A_OK) {
248             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
249             return A_ERROR;
250         }
251         A_MEMCPY(&buffer[length - remaining], pBMICmdBuf, rxlen);
252         remaining -= rxlen; address += rxlen;
253     }
254
255     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n"));
256     return A_OK;
257 }
258
259 A_STATUS
260 BMIWriteMemory(HIF_DEVICE *device,
261                A_UINT32 address,
262                A_UCHAR *buffer,
263                A_UINT32 length)
264 {
265     A_UINT32 cid;
266     A_STATUS status;
267     A_UINT32 offset;
268     A_UINT32 remaining, txlen;
269     const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(length);
270     A_UCHAR alignedBuffer[BMI_DATASZ_MAX];
271     A_UCHAR *src;
272
273     A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header));
274     memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + header);
275
276     if (bmiDone) {
277         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
278         return A_ERROR;
279     }
280
281     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
282          ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
283          device, address, length));
284
285     cid = BMI_WRITE_MEMORY;
286
287     remaining = length;
288     while (remaining)
289     {
290         src = &buffer[length - remaining];
291         if (remaining < (BMI_DATASZ_MAX - header)) {
292             if (remaining & 3) {
293                 /* align it with 4 bytes */
294                 remaining = remaining + (4 - (remaining & 3));
295                 memcpy(alignedBuffer, src, remaining);
296                 src = alignedBuffer;
297             } 
298             txlen = remaining;
299         } else {
300             txlen = (BMI_DATASZ_MAX - header);
301         }
302         offset = 0;
303         A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
304         offset += sizeof(cid);
305         A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
306         offset += sizeof(address);
307         A_MEMCPY(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
308         offset += sizeof(txlen);
309         A_MEMCPY(&(pBMICmdBuf[offset]), src, txlen);
310         offset += txlen;
311         status = bmiBufferSend(device, pBMICmdBuf, offset);
312         if (status != A_OK) {
313             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
314             return A_ERROR;
315         }
316         remaining -= txlen; address += txlen;
317     }
318
319     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n"));
320
321     return A_OK;
322 }
323
324 A_STATUS
325 BMIExecute(HIF_DEVICE *device,
326            A_UINT32 address,
327            A_UINT32 *param)
328 {
329     A_UINT32 cid;
330     A_STATUS status;
331     A_UINT32 offset;
332
333     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
334     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
335
336     if (bmiDone) {
337         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
338         return A_ERROR;
339     }
340
341     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
342        ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
343         device, address, *param));
344
345     cid = BMI_EXECUTE;
346
347     offset = 0;
348     A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
349     offset += sizeof(cid);
350     A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
351     offset += sizeof(address);
352     A_MEMCPY(&(pBMICmdBuf[offset]), param, sizeof(*param));
353     offset += sizeof(*param);
354     status = bmiBufferSend(device, pBMICmdBuf, offset);
355     if (status != A_OK) {
356         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
357         return A_ERROR;
358     }
359
360     status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), FALSE);
361     if (status != A_OK) {
362         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
363         return A_ERROR;
364     }
365
366     A_MEMCPY(param, pBMICmdBuf, sizeof(*param));
367
368     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param));
369     return A_OK;
370 }
371
372 A_STATUS
373 BMISetAppStart(HIF_DEVICE *device,
374                A_UINT32 address)
375 {
376     A_UINT32 cid;
377     A_STATUS status;
378     A_UINT32 offset;
379
380     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
381     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
382
383     if (bmiDone) {
384         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
385         return A_ERROR;
386     }
387
388     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
389        ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n",
390         device, address));
391
392     cid = BMI_SET_APP_START;
393
394     offset = 0;
395     A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
396     offset += sizeof(cid);
397     A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
398     offset += sizeof(address);
399     status = bmiBufferSend(device, pBMICmdBuf, offset);
400     if (status != A_OK) {
401         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
402         return A_ERROR;
403     }
404
405     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n"));
406     return A_OK;
407 }
408
409 A_STATUS
410 BMIReadSOCRegister(HIF_DEVICE *device,
411                    A_UINT32 address,
412                    A_UINT32 *param)
413 {
414     A_UINT32 cid;
415     A_STATUS status;
416     A_UINT32 offset;
417
418     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
419     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
420
421     if (bmiDone) {
422         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
423         return A_ERROR;
424     }
425
426     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
427        ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n",
428        device, address));
429
430     cid = BMI_READ_SOC_REGISTER;
431
432     offset = 0;
433     A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
434     offset += sizeof(cid);
435     A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
436     offset += sizeof(address);
437
438     status = bmiBufferSend(device, pBMICmdBuf, offset);
439     if (status != A_OK) {
440         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
441         return A_ERROR;
442     }
443
444     status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), TRUE);
445     if (status != A_OK) {
446         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
447         return A_ERROR;
448     }
449     A_MEMCPY(param, pBMICmdBuf, sizeof(*param));
450
451     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param));
452     return A_OK;
453 }
454
455 A_STATUS
456 BMIWriteSOCRegister(HIF_DEVICE *device,
457                     A_UINT32 address,
458                     A_UINT32 param)
459 {
460     A_UINT32 cid;
461     A_STATUS status;
462     A_UINT32 offset;
463
464     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
465     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
466
467     if (bmiDone) {
468         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
469         return A_ERROR;
470     }
471
472     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
473      ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
474      device, address, param));
475
476     cid = BMI_WRITE_SOC_REGISTER;
477
478     offset = 0;
479     A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
480     offset += sizeof(cid);
481     A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
482     offset += sizeof(address);
483     A_MEMCPY(&(pBMICmdBuf[offset]), &param, sizeof(param));
484     offset += sizeof(param);
485     status = bmiBufferSend(device, pBMICmdBuf, offset);
486     if (status != A_OK) {
487         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
488         return A_ERROR;
489     }
490
491     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n"));
492     return A_OK;
493 }
494
495 A_STATUS
496 BMIrompatchInstall(HIF_DEVICE *device,
497                    A_UINT32 ROM_addr,
498                    A_UINT32 RAM_addr,
499                    A_UINT32 nbytes,
500                    A_UINT32 do_activate,
501                    A_UINT32 *rompatch_id)
502 {
503     A_UINT32 cid;
504     A_STATUS status;
505     A_UINT32 offset;
506
507     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
508                                 sizeof(nbytes) + sizeof(do_activate)));
509     memset(pBMICmdBuf, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
510                         sizeof(nbytes) + sizeof(do_activate));
511
512     if (bmiDone) {
513         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
514         return A_ERROR;
515     }
516
517     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
518          ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n",
519          device, ROM_addr, RAM_addr, nbytes, do_activate));
520
521     cid = BMI_ROMPATCH_INSTALL;
522
523     offset = 0;
524     A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
525     offset += sizeof(cid);
526     A_MEMCPY(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr));
527     offset += sizeof(ROM_addr);
528     A_MEMCPY(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr));
529     offset += sizeof(RAM_addr);
530     A_MEMCPY(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes));
531     offset += sizeof(nbytes);
532     A_MEMCPY(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate));
533     offset += sizeof(do_activate);
534     status = bmiBufferSend(device, pBMICmdBuf, offset);
535     if (status != A_OK) {
536         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
537         return A_ERROR;
538     }
539
540     status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), TRUE);
541     if (status != A_OK) {
542         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
543         return A_ERROR;
544     }
545     A_MEMCPY(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id));
546
547     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id));
548     return A_OK;
549 }
550
551 A_STATUS
552 BMIrompatchUninstall(HIF_DEVICE *device,
553                      A_UINT32 rompatch_id)
554 {
555     A_UINT32 cid;
556     A_STATUS status;
557     A_UINT32 offset;
558
559     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(rompatch_id)));
560     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(rompatch_id));
561
562     if (bmiDone) {
563         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
564         return A_ERROR;
565     }
566
567     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
568          ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n",
569                                                                          device, rompatch_id));
570
571     cid = BMI_ROMPATCH_UNINSTALL;
572
573     offset = 0;
574     A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
575     offset += sizeof(cid);
576     A_MEMCPY(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id));
577     offset += sizeof(rompatch_id);
578     status = bmiBufferSend(device, pBMICmdBuf, offset);
579     if (status != A_OK) {
580         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
581         return A_ERROR;
582     }
583
584     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id));
585     return A_OK;
586 }
587
588 static A_STATUS
589 _BMIrompatchChangeActivation(HIF_DEVICE *device,
590                              A_UINT32 rompatch_count,
591                              A_UINT32 *rompatch_list,
592                              A_UINT32 do_activate)
593 {
594     A_UINT32 cid;
595     A_STATUS status;
596     A_UINT32 offset;
597     A_UINT32 length;
598
599     A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)));
600     memset(pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count));
601
602     if (bmiDone) {
603         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
604         return A_ERROR;
605     }
606
607     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
608          ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n",
609            device, rompatch_count));
610
611     cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE;
612
613     offset = 0;
614     A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
615     offset += sizeof(cid);
616     A_MEMCPY(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count));
617     offset += sizeof(rompatch_count);
618     length = rompatch_count * sizeof(*rompatch_list);
619     A_MEMCPY(&(pBMICmdBuf[offset]), rompatch_list, length);
620     offset += length;
621     status = bmiBufferSend(device, pBMICmdBuf, offset);
622     if (status != A_OK) {
623         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
624         return A_ERROR;
625     }
626
627     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n"));
628
629     return A_OK;
630 }
631
632 A_STATUS
633 BMIrompatchActivate(HIF_DEVICE *device,
634                     A_UINT32 rompatch_count,
635                     A_UINT32 *rompatch_list)
636 {
637     return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1);
638 }
639
640 A_STATUS
641 BMIrompatchDeactivate(HIF_DEVICE *device,
642                       A_UINT32 rompatch_count,
643                       A_UINT32 *rompatch_list)
644 {
645     return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0);
646 }
647
648 A_STATUS
649 BMILZData(HIF_DEVICE *device,
650           A_UCHAR *buffer,
651           A_UINT32 length)
652 {
653     A_UINT32 cid;
654     A_STATUS status;
655     A_UINT32 offset;
656     A_UINT32 remaining, txlen;
657     const A_UINT32 header = sizeof(cid) + sizeof(length);
658
659     A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX+header));
660     memset (pBMICmdBuf, 0, BMI_DATASZ_MAX+header);
661
662     if (bmiDone) {
663         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
664         return A_ERROR;
665     }
666
667     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
668          ("BMI Send LZ Data: Enter (device: 0x%p, length: %d)\n",
669          device, length));
670
671     cid = BMI_LZ_DATA;
672
673     remaining = length;
674     while (remaining)
675     {
676         txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
677                                        remaining : (BMI_DATASZ_MAX - header);
678         offset = 0;
679         A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
680         offset += sizeof(cid);
681         A_MEMCPY(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
682         offset += sizeof(txlen);
683         A_MEMCPY(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen);
684         offset += txlen;
685         status = bmiBufferSend(device, pBMICmdBuf, offset);
686         if (status != A_OK) {
687             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
688             return A_ERROR;
689         }
690         remaining -= txlen;
691     }
692
693     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Data: Exit\n"));
694
695     return A_OK;
696 }
697
698 A_STATUS
699 BMILZStreamStart(HIF_DEVICE *device,
700                  A_UINT32 address)
701 {
702     A_UINT32 cid;
703     A_STATUS status;
704     A_UINT32 offset;
705
706     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
707     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
708
709     if (bmiDone) {
710         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
711         return A_ERROR;
712     }
713
714     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
715          ("BMI LZ Stream Start: Enter (device: 0x%p, address: 0x%x)\n",
716          device, address));
717
718     cid = BMI_LZ_STREAM_START;
719     offset = 0;
720     A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
721     offset += sizeof(cid);
722     A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
723     offset += sizeof(address);
724     status = bmiBufferSend(device, pBMICmdBuf, offset);
725     if (status != A_OK) {
726         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to Start LZ Stream to the device\n"));
727         return A_ERROR;
728     }
729
730     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Stream Start: Exit\n"));
731
732     return A_OK;
733 }
734
735 /* BMI Access routines */
736 A_STATUS
737 bmiBufferSend(HIF_DEVICE *device,
738               A_UCHAR *buffer,
739               A_UINT32 length)
740 {
741     A_STATUS status;
742     A_UINT32 timeout;
743     A_UINT32 address;
744     A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
745
746     HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
747                        &mboxAddress[0], sizeof(mboxAddress));
748
749     *pBMICmdCredits = 0;
750     timeout = BMI_COMMUNICATION_TIMEOUT;
751
752     while(timeout-- && !(*pBMICmdCredits)) {
753         /* Read the counter register to get the command credits */
754         address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
755         /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause
756          * a decrement, while the remaining 3 bytes has no effect.  The rationale behind this is to
757          * make all HIF accesses 4-byte aligned */
758         status = HIFReadWrite(device, address, (A_UINT8 *)pBMICmdCredits, 4,
759             HIF_RD_SYNC_BYTE_INC, NULL);
760         if (status != A_OK) {
761             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n"));
762             return A_ERROR;
763         }
764         /* the counter is only 8=bits, ignore anything in the upper 3 bytes */
765         (*pBMICmdCredits) &= 0xFF;
766     }
767
768     if (*pBMICmdCredits) {
769         address = mboxAddress[ENDPOINT1];
770         status = HIFReadWrite(device, address, buffer, length,
771             HIF_WR_SYNC_BYTE_INC, NULL);
772         if (status != A_OK) {
773             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n"));
774             return A_ERROR;
775         }
776     } else {
777         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferSend\n"));
778         return A_ERROR;
779     }
780
781     return status;
782 }
783
784 A_STATUS
785 bmiBufferReceive(HIF_DEVICE *device,
786                  A_UCHAR *buffer,
787                  A_UINT32 length,
788                  A_BOOL want_timeout)
789 {
790     A_STATUS status;
791     A_UINT32 address;
792     A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
793     HIF_PENDING_EVENTS_INFO     hifPendingEvents;
794     static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL;
795     
796     if (!pendingEventsFuncCheck) {
797             /* see if the HIF layer implements an alternative function to get pending events
798              * do this only once! */
799         HIFConfigureDevice(device,
800                            HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
801                            &getPendingEventsFunc,
802                            sizeof(getPendingEventsFunc));
803         pendingEventsFuncCheck = TRUE;
804     }
805                        
806     HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
807                        &mboxAddress[0], sizeof(mboxAddress));
808
809     /*
810      * During normal bootup, small reads may be required.
811      * Rather than issue an HIF Read and then wait as the Target
812      * adds successive bytes to the FIFO, we wait here until
813      * we know that response data is available.
814      *
815      * This allows us to cleanly timeout on an unexpected
816      * Target failure rather than risk problems at the HIF level.  In
817      * particular, this avoids SDIO timeouts and possibly garbage
818      * data on some host controllers.  And on an interconnect
819      * such as Compact Flash (as well as some SDIO masters) which
820      * does not provide any indication on data timeout, it avoids
821      * a potential hang or garbage response.
822      *
823      * Synchronization is more difficult for reads larger than the
824      * size of the MBOX FIFO (128B), because the Target is unable
825      * to push the 129th byte of data until AFTER the Host posts an
826      * HIF Read and removes some FIFO data.  So for large reads the
827      * Host proceeds to post an HIF Read BEFORE all the data is
828      * actually available to read.  Fortunately, large BMI reads do
829      * not occur in practice -- they're supported for debug/development.
830      *
831      * So Host/Target BMI synchronization is divided into these cases:
832      *  CASE 1: length < 4
833      *        Should not happen
834      *
835      *  CASE 2: 4 <= length <= 128
836      *        Wait for first 4 bytes to be in FIFO
837      *        If CONSERVATIVE_BMI_READ is enabled, also wait for
838      *        a BMI command credit, which indicates that the ENTIRE
839      *        response is available in the the FIFO
840      *
841      *  CASE 3: length > 128
842      *        Wait for the first 4 bytes to be in FIFO
843      *
844      * For most uses, a small timeout should be sufficient and we will
845      * usually see a response quickly; but there may be some unusual
846      * (debug) cases of BMI_EXECUTE where we want an larger timeout.
847      * For now, we use an unbounded busy loop while waiting for
848      * BMI_EXECUTE.
849      *
850      * If BMI_EXECUTE ever needs to support longer-latency execution,
851      * especially in production, this code needs to be enhanced to sleep
852      * and yield.  Also note that BMI_COMMUNICATION_TIMEOUT is currently
853      * a function of Host processor speed.
854      */
855     if (length >= 4) { /* NB: Currently, always true */
856         /*
857          * NB: word_available is declared static for esoteric reasons
858          * having to do with protection on some OSes.
859          */
860         static A_UINT32 word_available;
861         A_UINT32 timeout;
862
863         word_available = 0;
864         timeout = BMI_COMMUNICATION_TIMEOUT;
865         while((!want_timeout || timeout--) && !word_available) {
866             
867             if (getPendingEventsFunc != NULL) {
868                 status = getPendingEventsFunc(device,
869                                               &hifPendingEvents,
870                                               NULL);
871                 if (status != A_OK) {
872                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n"));
873                     break;
874                 }
875   
876                 if (hifPendingEvents.AvailableRecvBytes >= sizeof(A_UINT32)) {
877                     word_available = 1;    
878                 }
879                 continue;    
880             }
881             
882             status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (A_UINT8 *)&word_available,
883                 sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL);
884             if (status != A_OK) {
885                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n"));
886                 return A_ERROR;
887             }
888             /* We did a 4-byte read to the same register; all we really want is one bit */ 
889             word_available &= (1 << ENDPOINT1);
890         }
891
892         if (!word_available) {
893             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferReceive FIFO empty\n"));
894             return A_ERROR;
895         }
896     }
897
898 #define CONSERVATIVE_BMI_READ 0
899 #if CONSERVATIVE_BMI_READ
900     /*
901      * This is an extra-conservative CREDIT check.  It guarantees
902      * that ALL data is available in the FIFO before we start to
903      * read from the interconnect.
904      *
905      * This credit check is useless when firmware chooses to
906      * allow multiple outstanding BMI Command Credits, since the next
907      * credit will already be present.  To restrict the Target to one
908      * BMI Command Credit, see HI_OPTION_BMI_CRED_LIMIT.
909      *
910      * And for large reads (when HI_OPTION_BMI_CRED_LIMIT is set)
911      * we cannot wait for the next credit because the Target's FIFO
912      * will not hold the entire response.  So we need the Host to
913      * start to empty the FIFO sooner.  (And again, large reads are
914      * not used in practice; they are for debug/development only.)
915      *
916      * For a more conservative Host implementation (which would be
917      * safer for a Compact Flash interconnect):
918      *   Set CONSERVATIVE_BMI_READ (above) to 1
919      *   Set HI_OPTION_BMI_CRED_LIMIT and
920      *   reduce BMI_DATASZ_MAX to 32 or 64
921      */
922     if ((length > 4) && (length < 128)) { /* check against MBOX FIFO size */
923         A_UINT32 timeout;
924
925         *pBMICmdCredits = 0;
926         timeout = BMI_COMMUNICATION_TIMEOUT;
927         while((!want_timeout || timeout--) && !(*pBMICmdCredits) {
928             /* Read the counter register to get the command credits */
929             address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1;
930             /* read the counter using a 4-byte read.  Since the counter is NOT auto-decrementing,
931              * we can read this counter multiple times using a non-incrementing address mode.
932              * The rationale here is to make all HIF accesses a multiple of 4 bytes */
933             status = HIFReadWrite(device, address, (A_UINT8 *)pBMICmdCredits, sizeof(*pBMICmdCredits),
934                 HIF_RD_SYNC_BYTE_FIX, NULL);
935             if (status != A_OK) {
936                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n"));
937                 return A_ERROR;
938             }
939                 /* we did a 4-byte read to the same count register so mask off upper bytes */
940             (*pBMICmdCredits) &= 0xFF;
941         }
942
943         if (!(*pBMICmdCredits)) {
944             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout- bmiBufferReceive no credit\n"));
945             return A_ERROR;
946         }
947     }
948 #endif
949
950     address = mboxAddress[ENDPOINT1];
951     status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL);
952     if (status != A_OK) {
953         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n"));
954         return A_ERROR;
955     }
956
957     return A_OK;
958 }
959
960 A_STATUS
961 BMIFastDownload(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length)
962 {
963     A_STATUS status = A_ERROR;
964     A_UINT32  lastWord = 0;
965     A_UINT32  lastWordOffset = length & ~0x3;
966     A_UINT32  unalignedBytes = length & 0x3;
967
968     status = BMILZStreamStart (device, address);
969     if (A_FAILED(status)) {
970             return A_ERROR;
971     }
972
973     if (unalignedBytes) {
974             /* copy the last word into a zero padded buffer */
975         A_MEMCPY(&lastWord, &buffer[lastWordOffset], unalignedBytes);
976     }
977
978     status = BMILZData(device, buffer, lastWordOffset);
979
980     if (A_FAILED(status)) {
981         return A_ERROR;
982     }
983
984     if (unalignedBytes) {
985         status = BMILZData(device, (A_UINT8 *)&lastWord, 4);
986     }
987
988     if (A_SUCCESS(status)) {
989         //
990         // Close compressed stream and open a new (fake) one.  This serves mainly to flush Target caches.
991         //
992         status = BMILZStreamStart (device, 0x00);
993         if (A_FAILED(status)) {
994            return A_ERROR;
995         }
996     }
997         return status;
998 }
999
1000 A_STATUS
1001 BMIRawWrite(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length)
1002 {
1003     return bmiBufferSend(device, buffer, length);
1004 }
1005
1006 A_STATUS
1007 BMIRawRead(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length, A_BOOL want_timeout)
1008 {
1009     return bmiBufferReceive(device, buffer, length, want_timeout);
1010 }