2 * Hermes download helper.
5 * - is capable of writing to the volatile area of the hermes device
6 * - is currently not capable of writing to non-volatile areas
7 * - provide helpers to identify and update plugin data
8 * - is not capable of interpreting a fw image directly. That is up to
9 * the main card driver.
10 * - deals with Hermes I devices. It can probably be modified to deal
11 * with Hermes II devices
13 * Copyright (C) 2007, David Kilroy
15 * Plug data code slightly modified from spectrum_cs driver
16 * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
17 * Portions based on information in wl_lkm_718 Agere driver
18 * COPYRIGHT (C) 2001-2004 by Agere Systems Inc. All Rights Reserved
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License
23 * at http://www.mozilla.org/MPL/
25 * Software distributed under the License is distributed on an "AS IS"
26 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
27 * the License for the specific language governing rights and
28 * limitations under the License.
30 * Alternatively, the contents of this file may be used under the
31 * terms of the GNU General Public License version 2 (the "GPL"), in
32 * which case the provisions of the GPL are applicable instead of the
33 * above. If you wish to allow the use of your version of this file
34 * only under the terms of the GPL and not to allow others to use your
35 * version of this file under the MPL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and
37 * other provisions required by the GPL. If you do not delete the
38 * provisions above, a recipient may use your version of this file
39 * under either the MPL or the GPL.
42 #include <linux/module.h>
43 #include <linux/delay.h>
45 #include "hermes_dld.h"
47 #define PFX "hermes_dld: "
50 * AUX port access. To unlock the AUX port write the access keys to the
51 * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
52 * register. Then read it and make sure it's HERMES_AUX_ENABLED.
54 #define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
55 #define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
56 #define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
57 #define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */
59 #define HERMES_AUX_PW0 0xFE01
60 #define HERMES_AUX_PW1 0xDC23
61 #define HERMES_AUX_PW2 0xBA45
63 /* HERMES_CMD_DOWNLD */
64 #define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD)
65 #define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD)
66 #define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
67 #define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD)
69 /* End markers used in dblocks */
70 #define PDI_END 0x00000000 /* End of PDA */
71 #define BLOCK_END 0xFFFFFFFF /* Last image block */
72 #define TEXT_END 0x1A /* End of text header */
75 * PDA == Production Data Area
77 * In principle, the max. size of the PDA is is 4096 words. Currently,
78 * however, only about 500 bytes of this area are used.
80 * Some USB implementations can't handle sizes in excess of 1016. Note
81 * that PDA is not actually used in those USB environments, but may be
82 * retrieved by common code.
84 #define MAX_PDA_SIZE 1000
86 /* Limit the amout we try to download in a single shot.
89 #define MAX_DL_SIZE 1024
90 #define LIMIT_PROGRAM_SIZE 0
93 * The following structures have little-endian fields denoted by
94 * the leading underscore. Don't access them directly - use inline
95 * functions defined below.
99 * The binary image to be downloaded consists of series of data blocks.
100 * Each block has the following structure.
103 __le32 addr; /* adapter address where to write the block */
104 __le16 len; /* length of the data only, in bytes */
105 char data[0]; /* data to be written */
106 } __attribute__ ((packed));
109 * Plug Data References are located in in the image after the last data
110 * block. They refer to areas in the adapter memory where the plug data
111 * items with matching ID should be written.
114 __le32 id; /* record ID */
115 __le32 addr; /* adapter address where to write the data */
116 __le32 len; /* expected length of the data, in bytes */
117 char next[0]; /* next PDR starts here */
118 } __attribute__ ((packed));
121 * Plug Data Items are located in the EEPROM read from the adapter by
122 * primary firmware. They refer to the device-specific data that should
123 * be plugged into the secondary firmware.
126 __le16 len; /* length of ID and data, in words */
127 __le16 id; /* record ID */
128 char data[0]; /* plug data */
129 } __attribute__ ((packed));
131 /*** FW data block access functions ***/
134 dblock_addr(const struct dblock *blk)
136 return le32_to_cpu(blk->addr);
140 dblock_len(const struct dblock *blk)
142 return le16_to_cpu(blk->len);
145 /*** PDR Access functions ***/
148 pdr_id(const struct pdr *pdr)
150 return le32_to_cpu(pdr->id);
154 pdr_addr(const struct pdr *pdr)
156 return le32_to_cpu(pdr->addr);
160 pdr_len(const struct pdr *pdr)
162 return le32_to_cpu(pdr->len);
165 /*** PDI Access functions ***/
168 pdi_id(const struct pdi *pdi)
170 return le16_to_cpu(pdi->id);
173 /* Return length of the data only, in bytes */
175 pdi_len(const struct pdi *pdi)
177 return 2 * (le16_to_cpu(pdi->len) - 1);
180 /*** Hermes AUX control ***/
183 hermes_aux_setaddr(hermes_t *hw, u32 addr)
185 hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
186 hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
190 hermes_aux_control(hermes_t *hw, int enabled)
192 int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
193 int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
197 if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
200 hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
201 hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
202 hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
203 hermes_write_reg(hw, HERMES_CONTROL, action);
205 for (i = 0; i < 20; i++) {
207 if (hermes_read_reg(hw, HERMES_CONTROL) ==
215 /*** Plug Data Functions ***/
218 * Scan PDR for the record with the specified RECORD_ID.
219 * If it's not found, return NULL.
222 hermes_find_pdr(struct pdr *first_pdr, u32 record_id)
224 struct pdr *pdr = first_pdr;
225 void *end = (void *)first_pdr + MAX_PDA_SIZE;
227 while (((void *)pdr < end) &&
228 (pdr_id(pdr) != PDI_END)) {
230 * PDR area is currently not terminated by PDI_END.
231 * It's followed by CRC records, which have the type
232 * field where PDR has length. The type can be 0 or 1.
234 if (pdr_len(pdr) < 2)
237 /* If the record ID matches, we are done */
238 if (pdr_id(pdr) == record_id)
241 pdr = (struct pdr *) pdr->next;
246 /* Scan production data items for a particular entry */
248 hermes_find_pdi(struct pdi *first_pdi, u32 record_id)
250 struct pdi *pdi = first_pdi;
252 while (pdi_id(pdi) != PDI_END) {
254 /* If the record ID matches, we are done */
255 if (pdi_id(pdi) == record_id)
258 pdi = (struct pdi *) &pdi->data[pdi_len(pdi)];
263 /* Process one Plug Data Item - find corresponding PDR and plug it */
265 hermes_plug_pdi(hermes_t *hw, struct pdr *first_pdr, const struct pdi *pdi)
269 /* Find the PDR corresponding to this PDI */
270 pdr = hermes_find_pdr(first_pdr, pdi_id(pdi));
272 /* No match is found, safe to ignore */
276 /* Lengths of the data in PDI and PDR must match */
277 if (pdi_len(pdi) != pdr_len(pdr))
280 /* do the actual plugging */
281 hermes_aux_setaddr(hw, pdr_addr(pdr));
282 hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi));
287 /* Read PDA from the adapter */
288 int hermes_read_pda(hermes_t *hw,
292 int use_eeprom) /* can we get this into hw? */
296 u16 data_len = pda_len;
300 /* PDA of spectrum symbol is in eeprom */
302 /* Issue command to read EEPROM */
303 ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
307 /* wl_lkm does not include PDA size in the PDA area.
308 * We will pad the information into pda, so other routines
309 * don't have to be modified */
310 pda[0] = cpu_to_le16(pda_len - 2);
311 /* Includes CFG_PROD_DATA but not itself */
312 pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
313 data_len = pda_len - 4;
317 /* Open auxiliary port */
318 ret = hermes_aux_control(hw, 1);
319 printk(KERN_DEBUG PFX "AUX enable returned %d\n", ret);
323 /* read PDA from EEPROM */
324 hermes_aux_setaddr(hw, pda_addr);
325 hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
328 ret = hermes_aux_control(hw, 0);
329 printk(KERN_DEBUG PFX "AUX disable returned %d\n", ret);
331 /* Check PDA length */
332 pda_size = le16_to_cpu(pda[0]);
333 printk(KERN_DEBUG PFX "Actual PDA length %d, Max allowed %d\n",
335 if (pda_size > pda_len)
341 /* Parse PDA and write the records into the adapter
343 * Attempt to write every records that is in the specified pda
344 * which also has a valid production data record for the firmware.
346 int hermes_apply_pda(hermes_t *hw,
347 const char *first_pdr,
351 const struct pdi *pdi;
354 pdr = (struct pdr *) first_pdr;
356 /* Go through every PDI and plug them into the adapter */
357 pdi = (const struct pdi *) (pda + 2);
358 while (pdi_id(pdi) != PDI_END) {
359 ret = hermes_plug_pdi(hw, pdr, pdi);
363 /* Increment to the next PDI */
364 pdi = (const struct pdi *) &pdi->data[pdi_len(pdi)];
369 /* Identify the total number of bytes in all blocks
370 * including the header data.
373 hermes_blocks_length(const char *first_block)
375 const struct dblock *blk = (const struct dblock *) first_block;
379 /* Skip all blocks to locate Plug Data References
381 while (dblock_addr(blk) != BLOCK_END) {
382 len = dblock_len(blk);
383 total_len += sizeof(*blk) + len;
384 blk = (struct dblock *) &blk->data[len];
390 /*** Hermes programming ***/
392 /* About to start programming data (Hermes I)
393 * offset is the entry point
395 * Spectrum_cs' Symbol fw does not require this
396 * wl_lkm Agere fw does
397 * Don't know about intersil
399 int hermesi_program_init(hermes_t *hw, u32 offset)
403 /* Disable interrupts?*/
405 /*hermes_write_regn(hw, INTEN, 0);*/
406 /*hermes_set_irqmask(hw, 0);*/
408 /* Acknowledge any outstanding command */
409 hermes_write_regn(hw, EVACK, 0xFFFF);
411 /* Using doicmd_wait rather than docmd_wait */
412 err = hermes_doicmd_wait(hw,
413 0x0100 | HERMES_CMD_INIT,
418 err = hermes_doicmd_wait(hw,
419 0x0000 | HERMES_CMD_INIT,
424 err = hermes_aux_control(hw, 1);
425 printk(KERN_DEBUG PFX "AUX enable returned %d\n", err);
430 printk(KERN_DEBUG PFX "Enabling volatile, EP 0x%08x\n", offset);
431 err = hermes_doicmd_wait(hw,
432 HERMES_PROGRAM_ENABLE_VOLATILE,
437 printk(KERN_DEBUG PFX "PROGRAM_ENABLE returned %d\n",
443 /* Done programming data (Hermes I)
445 * Spectrum_cs' Symbol fw does not require this
446 * wl_lkm Agere fw does
447 * Don't know about intersil
449 int hermesi_program_end(hermes_t *hw)
451 struct hermes_response resp;
455 rc = hermes_docmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
457 printk(KERN_DEBUG PFX "PROGRAM_DISABLE returned %d, "
458 "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
459 rc, resp.resp0, resp.resp1, resp.resp2);
462 ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
465 err = hermes_aux_control(hw, 0);
466 printk(KERN_DEBUG PFX "AUX disable returned %d\n", err);
468 /* Acknowledge any outstanding command */
469 hermes_write_regn(hw, EVACK, 0xFFFF);
471 /* Reinitialise, ignoring return */
472 (void) hermes_doicmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
475 return rc ? rc : err;
478 /* Program the data blocks */
479 int hermes_program(hermes_t *hw, const char *first_block, const char *end)
481 const struct dblock *blk;
484 #if LIMIT_PROGRAM_SIZE
489 blk = (const struct dblock *) first_block;
491 if ((const char *) blk > (end - sizeof(*blk)))
494 blkaddr = dblock_addr(blk);
495 blklen = dblock_len(blk);
497 while ((blkaddr != BLOCK_END) &&
498 (((const char *) blk + blklen) <= end)) {
499 printk(KERN_DEBUG PFX
500 "Programming block of length %d to address 0x%08x\n",
503 #if !LIMIT_PROGRAM_SIZE
504 /* wl_lkm driver splits this into writes of 2000 bytes */
505 hermes_aux_setaddr(hw, blkaddr);
506 hermes_write_bytes(hw, HERMES_AUXDATA, blk->data,
509 len = (blklen < MAX_DL_SIZE) ? blklen : MAX_DL_SIZE;
512 while (addr < (blkaddr + blklen)) {
513 printk(KERN_DEBUG PFX
514 "Programming subblock of length %d "
515 "to address 0x%08x. Data @ %p\n",
516 len, addr, &blk->data[addr - blkaddr]);
518 hermes_aux_setaddr(hw, addr);
519 hermes_write_bytes(hw, HERMES_AUXDATA,
520 &blk->data[addr - blkaddr],
524 len = ((blkaddr + blklen - addr) < MAX_DL_SIZE) ?
525 (blkaddr + blklen - addr) : MAX_DL_SIZE;
528 blk = (const struct dblock *) &blk->data[blklen];
530 if ((const char *) blk > (end - sizeof(*blk)))
533 blkaddr = dblock_addr(blk);
534 blklen = dblock_len(blk);
539 /*** Default plugging data for Hermes I ***/
540 /* Values from wl_lkm_718/hcf/dhf.c */
542 #define DEFINE_DEFAULT_PDR(pid, length, data) \
543 static const struct { \
547 } __attribute__ ((packed)) default_pdr_data_##pid = { \
548 cpu_to_le16((sizeof(default_pdr_data_##pid)/ \
549 sizeof(__le16)) - 1), \
554 #define DEFAULT_PDR(pid) default_pdr_data_##pid
556 /* HWIF Compatiblity */
557 DEFINE_DEFAULT_PDR(0x0005, 10, "\x00\x00\x06\x00\x01\x00\x01\x00\x01\x00");
560 DEFINE_DEFAULT_PDR(0x0108, 4, "\x00\x00\x00\x00");
563 DEFINE_DEFAULT_PDR(0x0109, 10, "\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00");
565 /* Antenna diversity */
566 DEFINE_DEFAULT_PDR(0x0150, 2, "\x00\x3F");
568 /* Modem VCO band Set-up */
569 DEFINE_DEFAULT_PDR(0x0160, 28,
570 "\x00\x00\x00\x00\x00\x00\x00\x00"
571 "\x00\x00\x00\x00\x00\x00\x00\x00"
572 "\x00\x00\x00\x00\x00\x00\x00\x00"
575 /* Modem Rx Gain Table Values */
576 DEFINE_DEFAULT_PDR(0x0161, 256,
577 "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
578 "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
579 "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
580 "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
581 "\x3F\x01\x3E\01\x3E\x01\x3D\x01"
582 "\x3D\x01\x3C\01\x3C\x01\x3B\x01"
583 "\x3B\x01\x3A\01\x3A\x01\x39\x01"
584 "\x39\x01\x38\01\x38\x01\x37\x01"
585 "\x37\x01\x36\01\x36\x01\x35\x01"
586 "\x35\x01\x34\01\x34\x01\x33\x01"
587 "\x33\x01\x32\x01\x32\x01\x31\x01"
588 "\x31\x01\x30\x01\x30\x01\x7B\x01"
589 "\x7B\x01\x7A\x01\x7A\x01\x79\x01"
590 "\x79\x01\x78\x01\x78\x01\x77\x01"
591 "\x77\x01\x76\x01\x76\x01\x75\x01"
592 "\x75\x01\x74\x01\x74\x01\x73\x01"
593 "\x73\x01\x72\x01\x72\x01\x71\x01"
594 "\x71\x01\x70\x01\x70\x01\x68\x01"
595 "\x68\x01\x67\x01\x67\x01\x66\x01"
596 "\x66\x01\x65\x01\x65\x01\x57\x01"
597 "\x57\x01\x56\x01\x56\x01\x55\x01"
598 "\x55\x01\x54\x01\x54\x01\x53\x01"
599 "\x53\x01\x52\x01\x52\x01\x51\x01"
600 "\x51\x01\x50\x01\x50\x01\x48\x01"
601 "\x48\x01\x47\x01\x47\x01\x46\x01"
602 "\x46\x01\x45\x01\x45\x01\x44\x01"
603 "\x44\x01\x43\x01\x43\x01\x42\x01"
604 "\x42\x01\x41\x01\x41\x01\x40\x01"
605 "\x40\x01\x40\x01\x40\x01\x40\x01"
606 "\x40\x01\x40\x01\x40\x01\x40\x01"
607 "\x40\x01\x40\x01\x40\x01\x40\x01"
608 "\x40\x01\x40\x01\x40\x01\x40\x01");
610 /* Write PDA according to certain rules.
612 * For every production data record, look for a previous setting in
613 * the pda, and use that.
615 * For certain records, use defaults if they are not found in pda.
617 int hermes_apply_pda_with_defaults(hermes_t *hw,
618 const char *first_pdr,
621 const struct pdr *pdr = (const struct pdr *) first_pdr;
622 struct pdi *first_pdi = (struct pdi *) &pda[2];
624 struct pdi *default_pdi = NULL;
625 struct pdi *outdoor_pdi;
626 void *end = (void *)first_pdr + MAX_PDA_SIZE;
629 while (((void *)pdr < end) &&
630 (pdr_id(pdr) != PDI_END)) {
632 * For spectrum_cs firmwares,
633 * PDR area is currently not terminated by PDI_END.
634 * It's followed by CRC records, which have the type
635 * field where PDR has length. The type can be 0 or 1.
637 if (pdr_len(pdr) < 2)
639 record_id = pdr_id(pdr);
641 pdi = hermes_find_pdi(first_pdi, record_id);
643 printk(KERN_DEBUG PFX "Found record 0x%04x at %p\n",
647 case 0x110: /* Modem REFDAC values */
648 case 0x120: /* Modem VGDAC values */
649 outdoor_pdi = hermes_find_pdi(first_pdi, record_id + 1);
653 printk(KERN_DEBUG PFX
654 "Using outdoor record 0x%04x at %p\n",
658 case 0x5: /* HWIF Compatiblity */
659 default_pdi = (struct pdi *) &DEFAULT_PDR(0x0005);
661 case 0x108: /* PPPPSign */
662 default_pdi = (struct pdi *) &DEFAULT_PDR(0x0108);
664 case 0x109: /* PPPPProf */
665 default_pdi = (struct pdi *) &DEFAULT_PDR(0x0109);
667 case 0x150: /* Antenna diversity */
668 default_pdi = (struct pdi *) &DEFAULT_PDR(0x0150);
670 case 0x160: /* Modem VCO band Set-up */
671 default_pdi = (struct pdi *) &DEFAULT_PDR(0x0160);
673 case 0x161: /* Modem Rx Gain Table Values */
674 default_pdi = (struct pdi *) &DEFAULT_PDR(0x0161);
680 if (!pdi && default_pdi) {
683 printk(KERN_DEBUG PFX
684 "Using default record 0x%04x at %p\n",
689 /* Lengths of the data in PDI and PDR must match */
690 if (pdi_len(pdi) == pdr_len(pdr)) {
691 /* do the actual plugging */
692 hermes_aux_setaddr(hw, pdr_addr(pdr));
693 hermes_write_bytes(hw, HERMES_AUXDATA,
694 pdi->data, pdi_len(pdi));