2 * Copyright (c) 2004-2007 Atheros Communications Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation;
10 * Software distributed under the License is distributed on an "AS
11 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12 * implied. See the License for the specific language governing
13 * rights and limitations under the License.
22 #include "bmi_internal.h"
25 Although we had envisioned BMI to run on top of HTC, this is not what the
26 final implementation boiled down to on dragon. Its a part of BSP and does
27 not use the HTC protocol either. On the host side, however, we were still
28 living with the original idea. I think the time has come to accept the truth
29 and separate it from HTC which has been carrying BMI's burden all this while.
30 It shall make HTC state machine relatively simpler
33 /* APIs visible to the driver */
41 BMIDone(HIF_DEVICE
*device
)
47 AR_DEBUG_PRINTF (ATH_DEBUG_BMI
, ("BMIDone skipped\n"));
51 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI Done: Enter (device: 0x%p)\n", device
));
55 status
= bmiBufferSend(device
, (A_UCHAR
*)&cid
, sizeof(cid
));
57 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to write to the device\n"));
60 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI Done: Exit\n"));
66 BMIGetTargetInfo(HIF_DEVICE
*device
, struct bmi_target_info
*targ_info
)
72 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Command disallowed\n"));
76 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI Get Target Info: Enter (device: 0x%p)\n", device
));
77 cid
= BMI_GET_TARGET_INFO
;
79 status
= bmiBufferSend(device
, (A_UCHAR
*)&cid
, sizeof(cid
));
81 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to write to the device\n"));
85 status
= bmiBufferReceive(device
, (A_UCHAR
*)&targ_info
->target_ver
,
86 sizeof(targ_info
->target_ver
));
88 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to read Target Version from the device\n"));
92 if (targ_info
->target_ver
== TARGET_VERSION_SENTINAL
) {
93 /* Determine how many bytes are in the Target's targ_info */
94 status
= bmiBufferReceive(device
, (A_UCHAR
*)&targ_info
->target_info_byte_count
,
95 sizeof(targ_info
->target_info_byte_count
));
97 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to read Target Info Byte Count from the device\n"));
102 * The Target's targ_info doesn't match the Host's targ_info.
103 * We need to do some backwards compatibility work to make this OK.
105 A_ASSERT(targ_info
->target_info_byte_count
== sizeof(*targ_info
));
107 /* Read the remainder of the targ_info */
108 status
= bmiBufferReceive(device
,
109 ((A_UCHAR
*)targ_info
)+sizeof(targ_info
->target_info_byte_count
),
110 sizeof(*targ_info
)-sizeof(targ_info
->target_info_byte_count
));
111 if (status
!= A_OK
) {
112 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to read Target Info (%d bytes) from the device\n",
113 targ_info
->target_info_byte_count
));
118 * Target must be an AR6001 whose firmware does not
119 * support BMI_GET_TARGET_INFO. Construct the data
120 * that it would have sent.
122 targ_info
->target_info_byte_count
= sizeof(targ_info
);
123 targ_info
->target_type
= TARGET_TYPE_AR6001
;
126 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
127 targ_info
->target_ver
, targ_info
->target_type
));
128 printk("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
129 targ_info
->target_ver
, targ_info
->target_type
);
135 BMIReadMemory(HIF_DEVICE
*device
,
143 A_UINT32 remaining
, rxlen
;
144 static A_UCHAR data
[BMI_DATASZ_MAX
+ sizeof(cid
) + sizeof(address
) + sizeof(length
)];
145 memset (&data
, 0, BMI_DATASZ_MAX
+ sizeof(cid
) + sizeof(address
) + sizeof(length
));
148 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Command disallowed\n"));
152 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
,
153 ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
154 device
, address
, length
));
156 cid
= BMI_READ_MEMORY
;
162 rxlen
= (remaining
< BMI_DATASZ_MAX
) ? remaining
: BMI_DATASZ_MAX
;
164 A_MEMCPY(&data
[offset
], &cid
, sizeof(cid
));
165 offset
+= sizeof(cid
);
166 A_MEMCPY(&data
[offset
], &address
, sizeof(address
));
167 offset
+= sizeof(address
);
168 A_MEMCPY(&data
[offset
], &rxlen
, sizeof(rxlen
));
169 offset
+= sizeof(length
);
171 status
= bmiBufferSend(device
, data
, offset
);
172 if (status
!= A_OK
) {
173 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to write to the device\n"));
176 status
= bmiBufferReceive(device
, data
, rxlen
);
177 if (status
!= A_OK
) {
178 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to read from the device\n"));
181 A_MEMCPY(&buffer
[length
- remaining
], data
, rxlen
);
182 remaining
-= rxlen
; address
+= rxlen
;
185 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI Read Memory: Exit\n"));
190 BMIWriteMemory(HIF_DEVICE
*device
,
198 A_UINT32 remaining
, txlen
;
199 const A_UINT32 header
= sizeof(cid
) + sizeof(address
) + sizeof(length
);
200 static A_UCHAR data
[BMI_DATASZ_MAX
+ sizeof(cid
) + sizeof(address
) + sizeof(length
)];
201 memset (&data
, 0, header
);
204 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Command disallowed\n"));
208 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
,
209 ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
210 device
, address
, length
));
212 cid
= BMI_WRITE_MEMORY
;
217 txlen
= (remaining
< (BMI_DATASZ_MAX
- header
)) ?
218 remaining
: (BMI_DATASZ_MAX
- header
);
220 A_MEMCPY(&data
[offset
], &cid
, sizeof(cid
));
221 offset
+= sizeof(cid
);
222 A_MEMCPY(&data
[offset
], &address
, sizeof(address
));
223 offset
+= sizeof(address
);
224 A_MEMCPY(&data
[offset
], &txlen
, sizeof(txlen
));
225 offset
+= sizeof(txlen
);
226 A_MEMCPY(&data
[offset
], &buffer
[length
- remaining
], txlen
);
228 status
= bmiBufferSend(device
, data
, offset
);
229 if (status
!= A_OK
) {
230 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to write to the device\n"));
233 remaining
-= txlen
; address
+= txlen
;
236 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI Write Memory: Exit\n"));
242 BMIExecute(HIF_DEVICE
*device
,
249 static A_UCHAR data
[sizeof(cid
) + sizeof(address
) + sizeof(*param
)];
250 memset (&data
, 0, sizeof(cid
) + sizeof(address
) + sizeof(*param
));
253 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Command disallowed\n"));
257 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
,
258 ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
259 device
, address
, *param
));
264 A_MEMCPY(&data
[offset
], &cid
, sizeof(cid
));
265 offset
+= sizeof(cid
);
266 A_MEMCPY(&data
[offset
], &address
, sizeof(address
));
267 offset
+= sizeof(address
);
268 A_MEMCPY(&data
[offset
], param
, sizeof(*param
));
269 offset
+= sizeof(*param
);
270 status
= bmiBufferSend(device
, data
, offset
);
271 if (status
!= A_OK
) {
272 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to write to the device\n"));
276 status
= bmiBufferReceive(device
, data
, sizeof(*param
));
277 if (status
!= A_OK
) {
278 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to read from the device\n"));
282 A_MEMCPY(param
, data
, sizeof(*param
));
284 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI Execute: Exit (param: %d)\n", *param
));
289 BMISetAppStart(HIF_DEVICE
*device
,
295 static A_UCHAR data
[sizeof(cid
) + sizeof(address
)];
296 memset (&data
, 0, sizeof(cid
) + sizeof(address
));
299 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Command disallowed\n"));
303 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
,
304 ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n",
307 cid
= BMI_SET_APP_START
;
310 A_MEMCPY(&data
[offset
], &cid
, sizeof(cid
));
311 offset
+= sizeof(cid
);
312 A_MEMCPY(&data
[offset
], &address
, sizeof(address
));
313 offset
+= sizeof(address
);
314 status
= bmiBufferSend(device
, data
, offset
);
315 if (status
!= A_OK
) {
316 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to write to the device\n"));
320 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI Set App Start: Exit\n"));
325 BMIReadSOCRegister(HIF_DEVICE
*device
,
332 static A_UCHAR data
[sizeof(cid
) + sizeof(address
)];
333 memset (&data
, 0, sizeof(cid
) + sizeof(address
));
336 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Command disallowed\n"));
340 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
,
341 ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n",
344 cid
= BMI_READ_SOC_REGISTER
;
347 A_MEMCPY(&data
[offset
], &cid
, sizeof(cid
));
348 offset
+= sizeof(cid
);
349 A_MEMCPY(&data
[offset
], &address
, sizeof(address
));
350 offset
+= sizeof(address
);
352 status
= bmiBufferSend(device
, data
, offset
);
353 if (status
!= A_OK
) {
354 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to write to the device\n"));
358 status
= bmiBufferReceive(device
, data
, sizeof(*param
));
359 if (status
!= A_OK
) {
360 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to read from the device\n"));
363 A_MEMCPY(param
, data
, sizeof(*param
));
365 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI Read SOC Register: Exit (value: %d)\n", *param
));
370 BMIWriteSOCRegister(HIF_DEVICE
*device
,
377 static A_UCHAR data
[sizeof(cid
) + sizeof(address
) + sizeof(param
)];
379 memset (&data
, 0, sizeof(cid
) + sizeof(address
) + sizeof(param
));
382 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Command disallowed\n"));
386 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
,
387 ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
388 device
, address
, param
));
390 cid
= BMI_WRITE_SOC_REGISTER
;
393 A_MEMCPY(&data
[offset
], &cid
, sizeof(cid
));
394 offset
+= sizeof(cid
);
395 A_MEMCPY(&data
[offset
], &address
, sizeof(address
));
396 offset
+= sizeof(address
);
397 A_MEMCPY(&data
[offset
], ¶m
, sizeof(param
));
398 offset
+= sizeof(param
);
399 status
= bmiBufferSend(device
, data
, offset
);
400 if (status
!= A_OK
) {
401 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to write to the device\n"));
405 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI Read SOC Register: Exit\n"));
410 BMIrompatchInstall(HIF_DEVICE
*device
,
414 A_UINT32 do_activate
,
415 A_UINT32
*rompatch_id
)
420 static A_UCHAR data
[sizeof(cid
) + sizeof(ROM_addr
) + sizeof(RAM_addr
) +
421 sizeof(nbytes
) + sizeof(do_activate
)];
423 memset (&data
, 0, sizeof(cid
) + sizeof(ROM_addr
) + sizeof(RAM_addr
) +
424 sizeof(nbytes
) + sizeof(do_activate
));
427 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Command disallowed\n"));
431 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
,
432 ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n",
433 device
, ROM_addr
, RAM_addr
, nbytes
, do_activate
));
435 cid
= BMI_ROMPATCH_INSTALL
;
438 A_MEMCPY(&data
[offset
], &cid
, sizeof(cid
));
439 offset
+= sizeof(cid
);
440 A_MEMCPY(&data
[offset
], &ROM_addr
, sizeof(ROM_addr
));
441 offset
+= sizeof(ROM_addr
);
442 A_MEMCPY(&data
[offset
], &RAM_addr
, sizeof(RAM_addr
));
443 offset
+= sizeof(RAM_addr
);
444 A_MEMCPY(&data
[offset
], &nbytes
, sizeof(nbytes
));
445 offset
+= sizeof(nbytes
);
446 A_MEMCPY(&data
[offset
], &do_activate
, sizeof(do_activate
));
447 offset
+= sizeof(do_activate
);
448 status
= bmiBufferSend(device
, data
, offset
);
449 if (status
!= A_OK
) {
450 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to write to the device\n"));
454 status
= bmiBufferReceive(device
, (A_UCHAR
*)rompatch_id
, sizeof(*rompatch_id
));
455 if (status
!= A_OK
) {
456 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to read from the device\n"));
460 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id
));
465 BMIrompatchUninstall(HIF_DEVICE
*device
,
466 A_UINT32 rompatch_id
)
471 static A_UCHAR data
[sizeof(cid
) + sizeof(rompatch_id
)];
472 memset (&data
, 0, sizeof(cid
) + sizeof(rompatch_id
));
475 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Command disallowed\n"));
479 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
,
480 ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n",
481 device
, rompatch_id
));
483 cid
= BMI_ROMPATCH_UNINSTALL
;
486 A_MEMCPY(&data
[offset
], &cid
, sizeof(cid
));
487 offset
+= sizeof(cid
);
488 A_MEMCPY(&data
[offset
], &rompatch_id
, sizeof(rompatch_id
));
489 offset
+= sizeof(rompatch_id
);
490 status
= bmiBufferSend(device
, data
, offset
);
491 if (status
!= A_OK
) {
492 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to write to the device\n"));
496 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id
));
501 _BMIrompatchChangeActivation(HIF_DEVICE
*device
,
502 A_UINT32 rompatch_count
,
503 A_UINT32
*rompatch_list
,
504 A_UINT32 do_activate
)
509 static A_UCHAR data
[BMI_DATASZ_MAX
+ sizeof(cid
) + sizeof(rompatch_count
)];
512 memset (&data
, 0, BMI_DATASZ_MAX
+ sizeof(cid
) + sizeof(rompatch_count
));
515 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Command disallowed\n"));
519 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
,
520 ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n",
521 device
, rompatch_count
));
523 cid
= do_activate
? BMI_ROMPATCH_ACTIVATE
: BMI_ROMPATCH_DEACTIVATE
;
526 A_MEMCPY(&data
[offset
], &cid
, sizeof(cid
));
527 offset
+= sizeof(cid
);
528 A_MEMCPY(&data
[offset
], &rompatch_count
, sizeof(rompatch_count
));
529 offset
+= sizeof(rompatch_count
);
530 length
= rompatch_count
* sizeof(*rompatch_list
);
531 A_MEMCPY(&data
[offset
], rompatch_list
, length
);
533 status
= bmiBufferSend(device
, data
, offset
);
534 if (status
!= A_OK
) {
535 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to write to the device\n"));
539 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI Change rompatch Activation: Exit\n"));
545 BMIrompatchActivate(HIF_DEVICE
*device
,
546 A_UINT32 rompatch_count
,
547 A_UINT32
*rompatch_list
)
549 return _BMIrompatchChangeActivation(device
, rompatch_count
, rompatch_list
, 1);
553 BMIrompatchDeactivate(HIF_DEVICE
*device
,
554 A_UINT32 rompatch_count
,
555 A_UINT32
*rompatch_list
)
557 return _BMIrompatchChangeActivation(device
, rompatch_count
, rompatch_list
, 0);
560 /* BMI Access routines */
562 bmiBufferSend(HIF_DEVICE
*device
,
569 static A_UINT32 cmdCredits
;
570 A_UINT32 mboxAddress
[HTC_MAILBOX_NUM_MAX
];
572 HIFConfigureDevice(device
, HIF_DEVICE_GET_MBOX_ADDR
,
573 &mboxAddress
, sizeof(mboxAddress
));
576 timeout
= BMI_COMMUNICATION_TIMEOUT
;
578 while(timeout
-- && !cmdCredits
) {
579 /* Read the counter register to get the command credits */
580 address
= COUNT_DEC_ADDRESS
+ (HTC_MAILBOX_NUM_MAX
+ ENDPOINT1
) * 4;
581 /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause
582 * a decrement, while the remaining 3 bytes has no effect. The rationale behind this is to
583 * make all HIF accesses 4-byte aligned */
584 status
= HIFReadWrite(device
, address
, (A_UINT8
*)&cmdCredits
, 4,
585 HIF_RD_SYNC_BYTE_INC
, NULL
);
586 if (status
!= A_OK
) {
587 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to decrement the command credit count register\n"));
590 /* the counter is only 8=bits, ignore anything in the upper 3 bytes */
595 address
= mboxAddress
[ENDPOINT1
];
596 status
= HIFReadWrite(device
, address
, buffer
, length
,
597 HIF_WR_SYNC_BYTE_INC
, NULL
);
598 if (status
!= A_OK
) {
599 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to send the BMI data to the device\n"));
603 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("BMI Communication timeout\n"));
611 bmiBufferReceive(HIF_DEVICE
*device
,
618 static A_UINT32 cmdCredits
;
619 A_UINT32 mboxAddress
[HTC_MAILBOX_NUM_MAX
];
621 HIFConfigureDevice(device
, HIF_DEVICE_GET_MBOX_ADDR
,
622 &mboxAddress
, sizeof(mboxAddress
));
625 timeout
= BMI_COMMUNICATION_TIMEOUT
;
626 while(timeout
-- && !cmdCredits
) {
627 /* Read the counter register to get the command credits */
628 address
= COUNT_ADDRESS
+ (HTC_MAILBOX_NUM_MAX
+ ENDPOINT1
) * 1;
629 /* read the counter using a 4-byte read. Since the counter is NOT auto-decrementing,
630 * we can read this counter multiple times using a non-incrementing address mode.
631 * The rationale here is to make all HIF accesses a multiple of 4 bytes */
632 status
= HIFReadWrite(device
, address
, (A_UINT8
*)&cmdCredits
, sizeof(cmdCredits
),
633 HIF_RD_SYNC_BYTE_FIX
, NULL
);
634 if (status
!= A_OK
) {
635 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to read the command credit count register\n"));
638 /* we did a 4-byte read to the same count register so mask off upper bytes */
644 address
= mboxAddress
[ENDPOINT1
];
645 status
= HIFReadWrite(device
, address
, buffer
, length
,
646 HIF_RD_SYNC_BYTE_INC
, NULL
);
647 if (status
!= A_OK
) {
648 AR_DEBUG_PRINTF(ATH_DEBUG_ERR
, ("Unable to read the BMI data from the device\n"));
652 AR_DEBUG_PRINTF(ATH_DEBUG_BMI
, ("BMI Communication timeout\n"));