Merge branch 'drm-nouveau-fixes-3.9' of git://anongit.freedesktop.org/git/nouveau...
[deliverable/linux.git] / drivers / staging / csr / csr_wifi_hip_download.c
CommitLineData
635d2b00
GKH
1/*****************************************************************************
2
95edd09e 3 (c) Cambridge Silicon Radio Limited 2012
635d2b00
GKH
4 All rights reserved and confidential information of CSR
5
6 Refer to LICENSE.txt included with this source for details
7 on the license terms.
8
9*****************************************************************************/
10
11/*
12 * ---------------------------------------------------------------------------
13 * FILE: csr_wifi_hip_download.c
14 *
15 * PURPOSE:
16 * Routines for downloading firmware to UniFi.
17 *
18 * ---------------------------------------------------------------------------
19 */
4fe9db37 20#include <linux/slab.h>
635d2b00
GKH
21#include "csr_wifi_hip_unifi.h"
22#include "csr_wifi_hip_unifiversion.h"
23#include "csr_wifi_hip_card.h"
24#include "csr_wifi_hip_xbv.h"
25
26#undef CSR_WIFI_IGNORE_PATCH_VERSION_MISMATCH
27
28static CsrResult do_patch_download(card_t *card, void *dlpriv,
26a6b2e1 29 xbv1_t *pfwinfo, u32 boot_ctrl_addr);
635d2b00
GKH
30
31static CsrResult do_patch_convert_download(card_t *card,
32 void *dlpriv, xbv1_t *pfwinfo);
33
34/*
35 * ---------------------------------------------------------------------------
36 * _find_in_slut
37 *
38 * Find the offset of the appropriate object in the SLUT of a card
39 *
40 * Arguments:
41 * card Pointer to card struct
42 * psym Pointer to symbol object.
43 * id set up by caller
44 * obj will be set up by this function
45 * pslut Pointer to SLUT address, if 0xffffffff then it must be
46 * read from the chip.
47 * Returns:
48 * CSR_RESULT_SUCCESS on success
49 * Non-zero on error,
50 * CSR_WIFI_HIP_RESULT_NOT_FOUND if not found
51 * ---------------------------------------------------------------------------
52 */
26a6b2e1 53static CsrResult _find_in_slut(card_t *card, symbol_t *psym, u32 *pslut)
635d2b00 54{
26a6b2e1 55 u32 slut_address;
8c87f69a 56 u16 finger_print;
635d2b00
GKH
57 CsrResult r;
58 CsrResult csrResult;
59
60 /* Get SLUT address */
61 if (*pslut == 0xffffffff)
62 {
63 r = card_wait_for_firmware_to_start(card, &slut_address);
64 if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
65 {
66 return r;
67 }
68 if (r != CSR_RESULT_SUCCESS)
69 {
70 unifi_error(card->ospriv, "Firmware hasn't started\n");
635d2b00
GKH
71 return r;
72 }
73 *pslut = slut_address;
74
75 /*
76 * Firmware has started so set the SDIO bus clock to the initial speed,
77 * faster than UNIFI_SDIO_CLOCK_SAFE_HZ, to speed up the f/w download.
78 */
79 csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_INIT_HZ);
80 if (csrResult != CSR_RESULT_SUCCESS)
81 {
82 r = ConvertCsrSdioToCsrHipResult(card, csrResult);
635d2b00
GKH
83 return r;
84 }
85 card->sdio_clock_speed = UNIFI_SDIO_CLOCK_INIT_HZ;
86 }
87 else
88 {
89 slut_address = *pslut; /* Use previously discovered address */
90 }
91 unifi_trace(card->ospriv, UDBG4, "SLUT addr: 0x%lX\n", slut_address);
92
93 /*
94 * Check the SLUT fingerprint.
95 * The slut_address is a generic pointer so we must use unifi_card_read16().
96 */
97 unifi_trace(card->ospriv, UDBG4, "Looking for SLUT finger print\n");
98 finger_print = 0;
99 r = unifi_card_read16(card, slut_address, &finger_print);
100 if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
101 {
102 return r;
103 }
104 if (r != CSR_RESULT_SUCCESS)
105 {
106 unifi_error(card->ospriv, "Failed to read SLUT finger print\n");
635d2b00
GKH
107 return r;
108 }
109
110 if (finger_print != SLUT_FINGERPRINT)
111 {
112 unifi_error(card->ospriv, "Failed to find SLUT fingerprint\n");
635d2b00
GKH
113 return CSR_RESULT_FAILURE;
114 }
115
116 /* Symbol table starts imedately after the fingerprint */
117 slut_address += 2;
118
119 while (1)
120 {
8c87f69a 121 u16 id;
26a6b2e1 122 u32 obj;
635d2b00
GKH
123
124 r = unifi_card_read16(card, slut_address, &id);
125 if (r != CSR_RESULT_SUCCESS)
126 {
635d2b00
GKH
127 return r;
128 }
129 slut_address += 2;
130
131 if (id == CSR_SLT_END)
132 {
133 /* End of table reached: not found */
134 r = CSR_WIFI_HIP_RESULT_RANGE;
135 break;
136 }
137
138 r = unifi_read32(card, slut_address, &obj);
139 if (r != CSR_RESULT_SUCCESS)
140 {
635d2b00
GKH
141 return r;
142 }
143 slut_address += 4;
144
145 unifi_trace(card->ospriv, UDBG3, " found SLUT id %02d.%08lx\n", id, obj);
146
147 r = CSR_WIFI_HIP_RESULT_NOT_FOUND;
148 /* Found search term? */
149 if (id == psym->id)
150 {
151 unifi_trace(card->ospriv, UDBG1, " matched SLUT id %02d.%08lx\n", id, obj);
152 psym->obj = obj;
153 r = CSR_RESULT_SUCCESS;
154 break;
155 }
156 }
157
635d2b00
GKH
158 return r;
159}
160
161
162/*
163 * ---------------------------------------------------------------------------
164 * do_patch_convert_download
165 *
166 * Download the given firmware image to the UniFi, converting from FWDL
167 * to PTDL XBV format.
168 *
169 * Arguments:
170 * card Pointer to card struct
171 * dlpriv Pointer to source firmware image
172 * fwinfo Pointer to source firmware info struct
173 *
174 * Returns:
175 * CSR_RESULT_SUCCESS on success, CSR error code on error
176 *
177 * Notes:
178 * ---------------------------------------------------------------------------
179 */
180static CsrResult do_patch_convert_download(card_t *card, void *dlpriv, xbv1_t *pfwinfo)
181{
182 CsrResult r;
26a6b2e1 183 u32 slut_base = 0xffffffff;
635d2b00 184 void *pfw;
26a6b2e1 185 u32 psize;
635d2b00
GKH
186 symbol_t sym;
187
188 /* Reset the chip to guarantee that the ROM loader is running */
189 r = unifi_init(card);
190 if (r != CSR_RESULT_SUCCESS)
191 {
192 unifi_error(card->ospriv,
193 "do_patch_convert_download: failed to re-init UniFi\n");
194 return r;
195 }
196
197 /* If no unifi_helper is running, the firmware version must be read */
198 if (card->build_id == 0)
199 {
26a6b2e1 200 u32 ver = 0;
635d2b00
GKH
201 sym.id = CSR_SLT_BUILD_ID_NUMBER;
202 sym.obj = 0; /* To be updated by _find_in_slut() */
203
204 unifi_trace(card->ospriv, UDBG1, "Need f/w version\n");
205
206 /* Find chip build id entry in SLUT */
207 r = _find_in_slut(card, &sym, &slut_base);
208 if (r != CSR_RESULT_SUCCESS)
209 {
210 unifi_error(card->ospriv, "Failed to find CSR_SLT_BUILD_ID_NUMBER\n");
211 return CSR_RESULT_FAILURE;
212 }
213
214 /* Read running f/w version */
215 r = unifi_read32(card, sym.obj, &ver);
216 if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
217 {
218 return r;
219 }
220 if (r != CSR_RESULT_SUCCESS)
221 {
222 unifi_error(card->ospriv, "Failed to read f/w id\n");
223 return CSR_RESULT_FAILURE;
224 }
225 card->build_id = ver;
226 }
227
228 /* Convert the ptest firmware to a patch against the running firmware */
229 pfw = xbv_to_patch(card, unifi_fw_read, dlpriv, pfwinfo, &psize);
230 if (!pfw)
231 {
232 unifi_error(card->ospriv, "Failed to convert f/w to patch");
233 return CSR_WIFI_HIP_RESULT_NO_MEMORY;
234 }
235 else
236 {
237 void *desc;
238 sym.id = CSR_SLT_BOOT_LOADER_CONTROL;
239 sym.obj = 0; /* To be updated by _find_in_slut() */
240
241 /* Find boot loader control entry in SLUT */
242 r = _find_in_slut(card, &sym, &slut_base);
243 if (r != CSR_RESULT_SUCCESS)
244 {
245 unifi_error(card->ospriv, "Failed to find BOOT_LOADER_CONTROL\n");
c8be681f 246 kfree(pfw);
635d2b00
GKH
247 return CSR_RESULT_FAILURE;
248 }
249
250 r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE);
251 if (r != CSR_RESULT_SUCCESS)
252 {
253 unifi_error(card->ospriv, "Failed to wake UniFi\n");
254 }
255
256 /* Get a dlpriv for the patch buffer so that unifi_fw_read() can
257 * access it.
258 */
259 desc = unifi_fw_open_buffer(card->ospriv, pfw, psize);
260 if (!desc)
261 {
c8be681f 262 kfree(pfw);
635d2b00
GKH
263 return CSR_WIFI_HIP_RESULT_NO_MEMORY;
264 }
265
266 /* Download the patch */
267 unifi_info(card->ospriv, "Downloading converted f/w as patch\n");
268 r = unifi_dl_patch(card, desc, sym.obj);
4fe9db37 269 kfree(pfw);
635d2b00
GKH
270 unifi_fw_close_buffer(card->ospriv, desc);
271
272 if (r != CSR_RESULT_SUCCESS)
273 {
274 unifi_error(card->ospriv, "Converted patch download failed\n");
635d2b00
GKH
275 return r;
276 }
277 else
278 {
279 unifi_trace(card->ospriv, UDBG1, "Converted patch downloaded\n");
280 }
281
282 /* This command starts the firmware */
283 r = unifi_do_loader_op(card, sym.obj + 6, UNIFI_BOOT_LOADER_RESTART);
284 if (r != CSR_RESULT_SUCCESS)
285 {
286 unifi_error(card->ospriv, "Failed to write loader restart cmd\n");
287 }
288
635d2b00
GKH
289 return r;
290 }
291}
292
293
294/*
295 * ---------------------------------------------------------------------------
296 * unifi_dl_firmware
297 *
298 * Download the given firmware image to the UniFi.
299 *
300 * Arguments:
301 * card Pointer to card struct
302 * dlpriv A context pointer from the calling function to be
303 * passed when calling unifi_fw_read().
304 *
305 * Returns:
306 * CSR_RESULT_SUCCESS on success,
307 * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed
308 * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file
309 * CSR_RESULT_FAILURE SDIO error
310 *
311 * Notes:
312 * Stops and resets the chip, does the download and runs the new
313 * firmware.
314 * ---------------------------------------------------------------------------
315 */
316CsrResult unifi_dl_firmware(card_t *card, void *dlpriv)
317{
318 xbv1_t *fwinfo;
319 CsrResult r;
320
70128792 321 fwinfo = kmalloc(sizeof(xbv1_t), GFP_KERNEL);
635d2b00
GKH
322 if (fwinfo == NULL)
323 {
324 unifi_error(card->ospriv, "Failed to allocate memory for firmware\n");
325 return CSR_WIFI_HIP_RESULT_NO_MEMORY;
326 }
327
328 /*
329 * Scan the firmware file to find the TLVs we are interested in.
330 * These are:
331 * - check we support the file format version in VERF
332 * - SLTP Symbol Lookup Table Pointer
333 * - FWDL firmware download segments
334 * - FWOV firmware overlay segment
335 * - VMEQ Register probe tests to verify matching h/w
336 */
337 r = xbv1_parse(card, unifi_fw_read, dlpriv, fwinfo);
338 if (r != CSR_RESULT_SUCCESS || fwinfo->mode != xbv_firmware)
339 {
340 unifi_error(card->ospriv, "File type is %s, expected firmware.\n",
341 fwinfo->mode == xbv_patch?"patch" : "unknown");
4fe9db37 342 kfree(fwinfo);
635d2b00
GKH
343 return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
344 }
345
346 /* UF6xxx doesn't accept firmware, only patches. Therefore we convert
347 * the file to patch format with version numbers matching the current
348 * running firmware, and then download via the patch mechanism.
349 * The sole purpose of this is to support production test firmware across
350 * different ROM releases, the test firmware being provided in non-patch
351 * format.
352 */
353 if (card->chip_id > SDIO_CARD_ID_UNIFI_2)
354 {
355 unifi_info(card->ospriv, "Must convert f/w to patch format\n");
356 r = do_patch_convert_download(card, dlpriv, fwinfo);
357 }
358 else
359 {
360 /* Older UniFi chips allowed firmware to be directly loaded onto the
361 * chip, which is no longer supported.
362 */
363 unifi_error(card->ospriv, "Only patch downloading supported\n");
364 r = CSR_WIFI_HIP_RESULT_INVALID_VALUE;
365 }
366
4fe9db37 367 kfree(fwinfo);
635d2b00
GKH
368 return r;
369} /* unifi_dl_firmware() */
370
371
372/*
373 * ---------------------------------------------------------------------------
374 * unifi_dl_patch
375 *
376 * Load the given patch set into UniFi.
377 *
378 * Arguments:
379 * card Pointer to card struct
380 * dlpriv The os specific handle to the firmware file.
381 * boot_ctrl The address of the boot loader control structure.
382 *
383 * Returns:
384 * CSR_RESULT_SUCCESS on success,
385 * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed
386 * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file
387 * CSR_RESULT_FAILURE SDIO error
388 *
389 * Notes:
390 * This ends up telling UniFi to restart.
391 * ---------------------------------------------------------------------------
392 */
26a6b2e1 393CsrResult unifi_dl_patch(card_t *card, void *dlpriv, u32 boot_ctrl)
635d2b00
GKH
394{
395 xbv1_t *fwinfo;
396 CsrResult r;
397
635d2b00
GKH
398 unifi_info(card->ospriv, "unifi_dl_patch %p %08x\n", dlpriv, boot_ctrl);
399
70128792 400 fwinfo = kmalloc(sizeof(xbv1_t), GFP_KERNEL);
635d2b00
GKH
401 if (fwinfo == NULL)
402 {
403 unifi_error(card->ospriv, "Failed to allocate memory for patches\n");
635d2b00
GKH
404 return CSR_WIFI_HIP_RESULT_NO_MEMORY;
405 }
406
407 /*
408 * Scan the firmware file to find the TLVs we are interested in.
409 * These are:
410 * - check we support the file format version in VERF
411 * - FWID The build ID of the ROM that we can patch
412 * - PTDL patch download segments
413 */
414 r = xbv1_parse(card, unifi_fw_read, dlpriv, fwinfo);
415 if (r != CSR_RESULT_SUCCESS || fwinfo->mode != xbv_patch)
416 {
4fe9db37 417 kfree(fwinfo);
635d2b00 418 unifi_error(card->ospriv, "Failed to read in patch file\n");
635d2b00
GKH
419 return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
420 }
421
422 /*
423 * We have to check the build id read from the SLUT against that
424 * for the patch file. They have to match exactly.
425 * "card->build_id" == XBV1.PTCH.FWID
426 */
427 if (card->build_id != fwinfo->build_id)
428 {
429 unifi_error(card->ospriv, "Wrong patch file for chip (chip = %lu, file = %lu)\n",
430 card->build_id, fwinfo->build_id);
4fe9db37 431 kfree(fwinfo);
635d2b00 432#ifndef CSR_WIFI_IGNORE_PATCH_VERSION_MISMATCH
635d2b00
GKH
433 return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
434#else
435 fwinfo = NULL;
436 dlpriv = NULL;
437 return CSR_RESULT_SUCCESS;
438#endif
439 }
440
441 r = do_patch_download(card, dlpriv, fwinfo, boot_ctrl);
442 if (r != CSR_RESULT_SUCCESS)
443 {
444 unifi_error(card->ospriv, "Failed to patch image\n");
445 }
446
4fe9db37 447 kfree(fwinfo);
635d2b00 448
635d2b00
GKH
449 return r;
450} /* unifi_dl_patch() */
451
452
163eb0d8 453void* unifi_dl_fw_read_start(card_t *card, s8 is_fw)
635d2b00
GKH
454{
455 card_info_t card_info;
456
457 unifi_card_info(card, &card_info);
458 unifi_trace(card->ospriv, UDBG5,
459 "id=%d, ver=0x%x, fw_build=%u, fw_hip=0x%x, block_size=%d\n",
460 card_info.chip_id, card_info.chip_version,
461 card_info.fw_build, card_info.fw_hip_version,
462 card_info.sdio_block_size);
463
464 return unifi_fw_read_start(card->ospriv, is_fw, &card_info);
465}
466
467
468/*
469 * ---------------------------------------------------------------------------
470 * safe_read_shared_location
471 *
472 * Read a shared memory location repeatedly until we get two readings
473 * the same.
474 *
475 * Arguments:
476 * card Pointer to card context struct.
477 * unifi_addr UniFi shared-data-memory address to access.
478 * pdata Pointer to a byte variable for the value read.
479 *
480 *
481 * Returns:
482 * CSR_RESULT_SUCCESS on success, CSR error code on failure
483 * ---------------------------------------------------------------------------
484 */
26a6b2e1 485static CsrResult safe_read_shared_location(card_t *card, u32 address, u8 *pdata)
635d2b00
GKH
486{
487 CsrResult r;
8c87f69a 488 u16 limit = 1000;
7e6f5794 489 u8 b, b2;
635d2b00
GKH
490
491 *pdata = 0;
492
493 r = unifi_read_8_or_16(card, address, &b);
494 if (r != CSR_RESULT_SUCCESS)
495 {
496 return r;
497 }
498
499 while (limit--)
500 {
501 r = unifi_read_8_or_16(card, address, &b2);
502 if (r != CSR_RESULT_SUCCESS)
503 {
504 return r;
505 }
506
507 /* When we have a stable value, return it */
508 if (b == b2)
509 {
510 *pdata = b;
511 return CSR_RESULT_SUCCESS;
512 }
513
514 b = b2;
515 }
516
517 return CSR_RESULT_FAILURE;
518} /* safe_read_shared_location() */
519
520
521/*
522 * ---------------------------------------------------------------------------
523 * unifi_do_loader_op
524 *
525 * Send a loader / boot_loader command to the UniFi and wait for
526 * it to complete.
527 *
528 * Arguments:
529 * card Pointer to card context struct.
530 * op_addr The address of the loader operation control word.
531 * opcode The operation to perform.
532 *
533 * Returns:
534 * CSR_RESULT_SUCCESS on success
535 * CSR_RESULT_FAILURE SDIO error or SDIO/XAP timeout
536 * ---------------------------------------------------------------------------
537 */
538
539/*
540 * Ideally instead of sleeping, we want to busy wait.
541 * Currently there is no framework API to do this. When it becomes available,
542 * we can use it to busy wait using usecs
543 */
544#define OPERATION_TIMEOUT_LOOPS (100) /* when OPERATION_TIMEOUT_DELAY==1, (500) otherwise */
545#define OPERATION_TIMEOUT_DELAY 1 /* msec, or 200usecs */
546
26a6b2e1 547CsrResult unifi_do_loader_op(card_t *card, u32 op_addr, u8 opcode)
635d2b00
GKH
548{
549 CsrResult r;
ab2b8c73 550 s16 op_retries;
635d2b00
GKH
551
552 unifi_trace(card->ospriv, UDBG4, "Loader cmd 0x%0x -> 0x%08x\n", opcode, op_addr);
553
554 /* Set the Operation command byte to the opcode */
555 r = unifi_write_8_or_16(card, op_addr, opcode);
556 if (r != CSR_RESULT_SUCCESS)
557 {
558 unifi_error(card->ospriv, "Failed to write loader copy command\n");
559 return r;
560 }
561
562 /* Wait for Operation command byte to be Idle */
563 /* Typically takes ~100us */
564 op_retries = 0;
565 r = CSR_RESULT_SUCCESS;
566 while (1)
567 {
7e6f5794 568 u8 op;
635d2b00
GKH
569
570 /*
571 * Read the memory location until two successive reads give
572 * the same value.
573 * Then handle it.
574 */
575 r = safe_read_shared_location(card, op_addr, &op);
576 if (r != CSR_RESULT_SUCCESS)
577 {
578 unifi_error(card->ospriv, "Failed to read loader status\n");
579 break;
580 }
581
582 if (op == UNIFI_LOADER_IDLE)
583 {
584 /* Success */
585 break;
586 }
587
588 if (op != opcode)
589 {
590 unifi_error(card->ospriv, "Error reported by loader: 0x%X\n", op);
591 r = CSR_RESULT_FAILURE;
592 break;
593 }
594
595 /* Allow 500us timeout */
596 if (++op_retries >= OPERATION_TIMEOUT_LOOPS)
597 {
598 unifi_error(card->ospriv, "Timeout waiting for loader to ack transfer\n");
599 /* Stop XAPs to aid post-mortem */
600 r = unifi_card_stop_processor(card, UNIFI_PROC_BOTH);
601 if (r != CSR_RESULT_SUCCESS)
602 {
603 unifi_error(card->ospriv, "Failed to stop UniFi processors\n");
604 }
605 else
606 {
607 r = CSR_RESULT_FAILURE;
608 }
609 break;
610 }
611 CsrThreadSleep(OPERATION_TIMEOUT_DELAY);
612 } /* Loop exits with r != CSR_RESULT_SUCCESS on error */
613
614 return r;
615} /* unifi_do_loader_op() */
616
617
618/*
619 * ---------------------------------------------------------------------------
620 * send_ptdl_to_unifi
621 *
622 * Copy a patch block from userland to the UniFi.
623 * This function reads data, 2K at a time, from userland and writes
624 * it to the UniFi.
625 *
626 * Arguments:
627 * card A pointer to the card structure
628 * dlpriv The os specific handle for the firmware file
629 * ptdl A pointer ot the PTDL block
630 * handle The buffer handle to use for the xfer
631 * op_addr The address of the loader operation control word
632 *
633 * Returns:
634 * Number of bytes sent (Positive) or negative value indicating
635 * error code:
636 * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed
637 * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file
638 * CSR_RESULT_FAILURE SDIO error
639 * ---------------------------------------------------------------------------
640 */
641static CsrResult send_ptdl_to_unifi(card_t *card, void *dlpriv,
26a6b2e1
GKH
642 const struct PTDL *ptdl, u32 handle,
643 u32 op_addr)
635d2b00 644{
26a6b2e1 645 u32 offset;
7e6f5794 646 u8 *buf;
95e326c2 647 s32 data_len;
26a6b2e1 648 u32 write_len;
635d2b00 649 CsrResult r;
8c87f69a 650 const u16 buf_size = 2 * 1024;
635d2b00
GKH
651
652 offset = ptdl->dl_offset;
653 data_len = ptdl->dl_size;
654
655 if (data_len > buf_size)
656 {
657 unifi_error(card->ospriv, "PTDL block is too large (%u)\n",
658 ptdl->dl_size);
659 return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
660 }
661
4becf12d 662 buf = kmalloc(buf_size, GFP_KERNEL);
635d2b00
GKH
663 if (buf == NULL)
664 {
665 unifi_error(card->ospriv, "Failed to allocate transfer buffer for firmware download\n");
666 return CSR_WIFI_HIP_RESULT_NO_MEMORY;
667 }
668
669 r = CSR_RESULT_SUCCESS;
670
671 if (unifi_fw_read(card->ospriv, dlpriv, offset, buf, data_len) != data_len)
672 {
673 unifi_error(card->ospriv, "Failed to read from file\n");
674 }
675 else
676 {
677 /* We can always round these if the host wants to */
678 if (card->sdio_io_block_pad)
679 {
680 write_len = (data_len + (card->sdio_io_block_size - 1)) &
681 ~(card->sdio_io_block_size - 1);
682
683 /* Zero out the rest of the buffer (This isn't needed, but it
684 * makes debugging things later much easier). */
b7244a31 685 memset(buf + data_len, 0, write_len - data_len);
635d2b00
GKH
686 }
687 else
688 {
689 write_len = data_len;
690 }
691
692 r = unifi_bulk_rw_noretry(card, handle, buf, write_len, UNIFI_SDIO_WRITE);
693 if (r != CSR_RESULT_SUCCESS)
694 {
695 unifi_error(card->ospriv, "CMD53 failed writing %d bytes to handle %ld\n",
696 data_len, handle);
697 }
698 else
699 {
700 /*
701 * Can change the order of things to overlap read from file
702 * with copy to unifi
703 */
704 r = unifi_do_loader_op(card, op_addr, UNIFI_BOOT_LOADER_PATCH);
705 }
706 }
707
4fe9db37 708 kfree(buf);
635d2b00
GKH
709
710 if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE)
711 {
712 unifi_error(card->ospriv, "Failed to copy block of %u bytes to UniFi\n",
713 ptdl->dl_size);
714 }
715
716 return r;
717} /* send_ptdl_to_unifi() */
718
719
720/*
721 * ---------------------------------------------------------------------------
722 * do_patch_download
723 *
724 * This function downloads a set of patches to UniFi and then
725 * causes it to restart.
726 *
727 * Arguments:
728 * card Pointer to card struct.
729 * dlpriv A context pointer from the calling function to be
730 * used when reading the XBV file. This can be NULL
731 * in which case not patches are applied.
732 * pfwinfo Pointer to a fwinfo struct describing the f/w
733 * XBV file.
734 * boot_ctrl_addr The address of the boot loader control structure.
735 *
736 * Returns:
737 * 0 on success, or an error code
738 * CSR_WIFI_HIP_RESULT_INVALID_VALUE for a bad laoader version number
739 * ---------------------------------------------------------------------------
740 */
26a6b2e1 741static CsrResult do_patch_download(card_t *card, void *dlpriv, xbv1_t *pfwinfo, u32 boot_ctrl_addr)
635d2b00
GKH
742{
743 CsrResult r;
95e326c2 744 s32 i;
8c87f69a
GKH
745 u16 loader_version;
746 u16 handle;
26a6b2e1 747 u32 total_bytes;
635d2b00
GKH
748
749 /*
750 * Read info from the SDIO Loader Control Data Structure
751 */
752 /* Check the loader version */
753 r = unifi_card_read16(card, boot_ctrl_addr, &loader_version);
754 if (r != CSR_RESULT_SUCCESS)
755 {
756 unifi_error(card->ospriv, "Patch download: Failed to read loader version\n");
757 return r;
758 }
759 unifi_trace(card->ospriv, UDBG2, "Patch download: boot loader version 0x%04X\n", loader_version);
760 switch (loader_version)
761 {
762 case 0x0000:
763 break;
764
765 default:
766 unifi_error(card->ospriv, "Patch loader version (0x%04X) is not supported by this driver\n",
767 loader_version);
768 return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
769 }
770
771 /* Retrieve the handle to use with CMD53 */
772 r = unifi_card_read16(card, boot_ctrl_addr + 4, &handle);
773 if (r != CSR_RESULT_SUCCESS)
774 {
775 unifi_error(card->ospriv, "Patch download: Failed to read loader handle\n");
776 return r;
777 }
778
779 /* Set the mask of LEDs to flash */
780 if (card->loader_led_mask)
781 {
782 r = unifi_card_write16(card, boot_ctrl_addr + 2,
8c87f69a 783 (u16)card->loader_led_mask);
635d2b00
GKH
784 if (r != CSR_RESULT_SUCCESS)
785 {
786 unifi_error(card->ospriv, "Patch download: Failed to write LED mask\n");
787 return r;
788 }
789 }
790
791 total_bytes = 0;
792
793 /* Copy download data to UniFi memory */
794 for (i = 0; i < pfwinfo->num_ptdl; i++)
795 {
796 unifi_trace(card->ospriv, UDBG3, "Patch download: %d Downloading for %d from offset %d\n",
797 i,
798 pfwinfo->ptdl[i].dl_size,
799 pfwinfo->ptdl[i].dl_offset);
800
801 r = send_ptdl_to_unifi(card, dlpriv, &pfwinfo->ptdl[i],
802 handle, boot_ctrl_addr + 6);
803 if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
804 {
805 return r;
806 }
807 if (r != CSR_RESULT_SUCCESS)
808 {
809 unifi_error(card->ospriv, "Patch failed after %u bytes\n",
810 total_bytes);
811 return r;
812 }
813 total_bytes += pfwinfo->ptdl[i].dl_size;
814 }
815
816 return CSR_RESULT_SUCCESS;
817} /* do_patch_download() */
818
819
This page took 0.138875 seconds and 5 git commands to generate.