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 struct 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 bool pendingEventsFuncCheck = false;
57 static u32 *pBMICmdCredits;
58 static u8 *pBMICmdBuf;
59 #define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
60 sizeof(u32) /* cmd */ + \
61 sizeof(u32) /* addr */ + \
62 sizeof(u32))/* length */
63 #define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ)
64
65 /* APIs visible to the driver */
66 void
BMIInit(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 = (u32 *)A_MALLOC_NOWAIT(4);
83 A_ASSERT(pBMICmdCredits);
84 }
85
86 if (!pBMICmdBuf) {
87 pBMICmdBuf = (u8 *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ);
88 A_ASSERT(pBMICmdBuf);
89 }
90
91 A_REGISTER_MODULE_DEBUG_INFO(bmi);
92 }
93
94 void
BMICleanup(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 int
BMIDone(struct hif_device * device)109 BMIDone(struct hif_device *device)
110 {
111 int status;
112 u32 cid;
113
114 if (bmiDone) {
115 AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n"));
116 return 0;
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, (u8 *)&cid, sizeof(cid));
124 if (status) {
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 0;
142 }
143
144 int
BMIGetTargetInfo(struct hif_device * device,struct bmi_target_info * targ_info)145 BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info)
146 {
147 int status;
148 u32 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, (u8 *)&cid, sizeof(cid));
159 if (status) {
160 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
161 return A_ERROR;
162 }
163
164 status = bmiBufferReceive(device, (u8 *)&targ_info->target_ver,
165 sizeof(targ_info->target_ver), true);
166 if (status) {
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, (u8 *)&targ_info->target_info_byte_count,
174 sizeof(targ_info->target_info_byte_count), true);
175 if (status) {
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 ((u8 *)targ_info)+sizeof(targ_info->target_info_byte_count),
189 sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), true);
190 if (status) {
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 0;
201 }
202
203 int
BMIReadMemory(struct hif_device * device,u32 address,u8 * buffer,u32 length)204 BMIReadMemory(struct hif_device *device,
205 u32 address,
206 u8 *buffer,
207 u32 length)
208 {
209 u32 cid;
210 int status;
211 u32 offset;
212 u32 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 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
235 offset += sizeof(cid);
236 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
237 offset += sizeof(address);
238 memcpy(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen));
239 offset += sizeof(length);
240
241 status = bmiBufferSend(device, pBMICmdBuf, offset);
242 if (status) {
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) {
248 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
249 return A_ERROR;
250 }
251 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 0;
257 }
258
259 int
BMIWriteMemory(struct hif_device * device,u32 address,u8 * buffer,u32 length)260 BMIWriteMemory(struct hif_device *device,
261 u32 address,
262 u8 *buffer,
263 u32 length)
264 {
265 u32 cid;
266 int status;
267 u32 offset;
268 u32 remaining, txlen;
269 const u32 header = sizeof(cid) + sizeof(address) + sizeof(length);
270 u8 alignedBuffer[BMI_DATASZ_MAX];
271 u8 *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 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
304 offset += sizeof(cid);
305 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
306 offset += sizeof(address);
307 memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
308 offset += sizeof(txlen);
309 memcpy(&(pBMICmdBuf[offset]), src, txlen);
310 offset += txlen;
311 status = bmiBufferSend(device, pBMICmdBuf, offset);
312 if (status) {
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 0;
322 }
323
324 int
BMIExecute(struct hif_device * device,u32 address,u32 * param)325 BMIExecute(struct hif_device *device,
326 u32 address,
327 u32 *param)
328 {
329 u32 cid;
330 int status;
331 u32 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 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
349 offset += sizeof(cid);
350 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
351 offset += sizeof(address);
352 memcpy(&(pBMICmdBuf[offset]), param, sizeof(*param));
353 offset += sizeof(*param);
354 status = bmiBufferSend(device, pBMICmdBuf, offset);
355 if (status) {
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) {
362 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
363 return A_ERROR;
364 }
365
366 memcpy(param, pBMICmdBuf, sizeof(*param));
367
368 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param));
369 return 0;
370 }
371
372 int
BMISetAppStart(struct hif_device * device,u32 address)373 BMISetAppStart(struct hif_device *device,
374 u32 address)
375 {
376 u32 cid;
377 int status;
378 u32 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 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
396 offset += sizeof(cid);
397 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
398 offset += sizeof(address);
399 status = bmiBufferSend(device, pBMICmdBuf, offset);
400 if (status) {
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 0;
407 }
408
409 int
BMIReadSOCRegister(struct hif_device * device,u32 address,u32 * param)410 BMIReadSOCRegister(struct hif_device *device,
411 u32 address,
412 u32 *param)
413 {
414 u32 cid;
415 int status;
416 u32 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 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
434 offset += sizeof(cid);
435 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
436 offset += sizeof(address);
437
438 status = bmiBufferSend(device, pBMICmdBuf, offset);
439 if (status) {
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) {
446 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
447 return A_ERROR;
448 }
449 memcpy(param, pBMICmdBuf, sizeof(*param));
450
451 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param));
452 return 0;
453 }
454
455 int
BMIWriteSOCRegister(struct hif_device * device,u32 address,u32 param)456 BMIWriteSOCRegister(struct hif_device *device,
457 u32 address,
458 u32 param)
459 {
460 u32 cid;
461 int status;
462 u32 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 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
480 offset += sizeof(cid);
481 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
482 offset += sizeof(address);
483 memcpy(&(pBMICmdBuf[offset]), ¶m, sizeof(param));
484 offset += sizeof(param);
485 status = bmiBufferSend(device, pBMICmdBuf, offset);
486 if (status) {
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 0;
493 }
494
495 int
BMIrompatchInstall(struct hif_device * device,u32 ROM_addr,u32 RAM_addr,u32 nbytes,u32 do_activate,u32 * rompatch_id)496 BMIrompatchInstall(struct hif_device *device,
497 u32 ROM_addr,
498 u32 RAM_addr,
499 u32 nbytes,
500 u32 do_activate,
501 u32 *rompatch_id)
502 {
503 u32 cid;
504 int status;
505 u32 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 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
525 offset += sizeof(cid);
526 memcpy(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr));
527 offset += sizeof(ROM_addr);
528 memcpy(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr));
529 offset += sizeof(RAM_addr);
530 memcpy(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes));
531 offset += sizeof(nbytes);
532 memcpy(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate));
533 offset += sizeof(do_activate);
534 status = bmiBufferSend(device, pBMICmdBuf, offset);
535 if (status) {
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) {
542 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
543 return A_ERROR;
544 }
545 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 0;
549 }
550
551 int
BMIrompatchUninstall(struct hif_device * device,u32 rompatch_id)552 BMIrompatchUninstall(struct hif_device *device,
553 u32 rompatch_id)
554 {
555 u32 cid;
556 int status;
557 u32 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 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
575 offset += sizeof(cid);
576 memcpy(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id));
577 offset += sizeof(rompatch_id);
578 status = bmiBufferSend(device, pBMICmdBuf, offset);
579 if (status) {
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 0;
586 }
587
588 static int
_BMIrompatchChangeActivation(struct hif_device * device,u32 rompatch_count,u32 * rompatch_list,u32 do_activate)589 _BMIrompatchChangeActivation(struct hif_device *device,
590 u32 rompatch_count,
591 u32 *rompatch_list,
592 u32 do_activate)
593 {
594 u32 cid;
595 int status;
596 u32 offset;
597 u32 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 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
615 offset += sizeof(cid);
616 memcpy(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count));
617 offset += sizeof(rompatch_count);
618 length = rompatch_count * sizeof(*rompatch_list);
619 memcpy(&(pBMICmdBuf[offset]), rompatch_list, length);
620 offset += length;
621 status = bmiBufferSend(device, pBMICmdBuf, offset);
622 if (status) {
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 0;
630 }
631
632 int
BMIrompatchActivate(struct hif_device * device,u32 rompatch_count,u32 * rompatch_list)633 BMIrompatchActivate(struct hif_device *device,
634 u32 rompatch_count,
635 u32 *rompatch_list)
636 {
637 return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1);
638 }
639
640 int
BMIrompatchDeactivate(struct hif_device * device,u32 rompatch_count,u32 * rompatch_list)641 BMIrompatchDeactivate(struct hif_device *device,
642 u32 rompatch_count,
643 u32 *rompatch_list)
644 {
645 return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0);
646 }
647
648 int
BMILZData(struct hif_device * device,u8 * buffer,u32 length)649 BMILZData(struct hif_device *device,
650 u8 *buffer,
651 u32 length)
652 {
653 u32 cid;
654 int status;
655 u32 offset;
656 u32 remaining, txlen;
657 const u32 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 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
680 offset += sizeof(cid);
681 memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
682 offset += sizeof(txlen);
683 memcpy(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen);
684 offset += txlen;
685 status = bmiBufferSend(device, pBMICmdBuf, offset);
686 if (status) {
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 0;
696 }
697
698 int
BMILZStreamStart(struct hif_device * device,u32 address)699 BMILZStreamStart(struct hif_device *device,
700 u32 address)
701 {
702 u32 cid;
703 int status;
704 u32 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 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
721 offset += sizeof(cid);
722 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
723 offset += sizeof(address);
724 status = bmiBufferSend(device, pBMICmdBuf, offset);
725 if (status) {
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 0;
733 }
734
735 /* BMI Access routines */
736 int
bmiBufferSend(struct hif_device * device,u8 * buffer,u32 length)737 bmiBufferSend(struct hif_device *device,
738 u8 *buffer,
739 u32 length)
740 {
741 int status;
742 u32 timeout;
743 u32 address;
744 u32 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, (u8 *)pBMICmdCredits, 4,
759 HIF_RD_SYNC_BYTE_INC, NULL);
760 if (status) {
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) {
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 int
bmiBufferReceive(struct hif_device * device,u8 * buffer,u32 length,bool want_timeout)785 bmiBufferReceive(struct hif_device *device,
786 u8 *buffer,
787 u32 length,
788 bool want_timeout)
789 {
790 int status;
791 u32 address;
792 u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
793 struct 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 u32 word_available;
861 u32 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) {
872 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n"));
873 break;
874 }
875
876 if (hifPendingEvents.AvailableRecvBytes >= sizeof(u32)) {
877 word_available = 1;
878 }
879 continue;
880 }
881
882 status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (u8 *)&word_available,
883 sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL);
884 if (status) {
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 u32 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, (u8 *)pBMICmdCredits, sizeof(*pBMICmdCredits),
934 HIF_RD_SYNC_BYTE_FIX, NULL);
935 if (status) {
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) {
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 0;
958 }
959
960 int
961 BMIFastDownload(struct hif_device *device, u32 address, u8 *buffer, u32 length)
962 {
963 int status = A_ERROR;
964 u32 lastWord = 0;
965 u32 lastWordOffset = length & ~0x3;
966 u32 unalignedBytes = length & 0x3;
967
968 status = BMILZStreamStart (device, address);
969 if (status) {
970 return A_ERROR;
971 }
972
973 if (unalignedBytes) {
974 /* copy the last word into a zero padded buffer */
975 memcpy(&lastWord, &buffer[lastWordOffset], unalignedBytes);
976 }
977
978 status = BMILZData(device, buffer, lastWordOffset);
979
980 if (status) {
981 return A_ERROR;
982 }
983
984 if (unalignedBytes) {
985 status = BMILZData(device, (u8 *)&lastWord, 4);
986 }
987
988 if (!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 (status) {
994 return A_ERROR;
995 }
996 }
997 return status;
998 }
999
1000 int
1001 BMIRawWrite(struct hif_device *device, u8 *buffer, u32 length)
1002 {
1003 return bmiBufferSend(device, buffer, length);
1004 }
1005
1006 int
1007 BMIRawRead(struct hif_device *device, u8 *buffer, u32 length, bool want_timeout)
1008 {
1009 return bmiBufferReceive(device, buffer, length, want_timeout);
1010 }
1011