2 * Misc useful routines to access NIC SROM
4 * Copyright 2004, Broadcom Corporation
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
19 #include <bcmendian.h>
24 #include <proto/ethernet.h> /* for sprom content groking */
26 #define VARS_MAX 4096 /* should be reduced */
28 static int initvars_srom_pci(void *curmap
, char **vars
, int *count
);
29 static int initvars_cis_pcmcia(void *sbh
, void *curmap
, void *osh
, char **vars
, int *count
);
30 static int sprom_cmd_pcmcia(void *osh
, uint8 cmd
);
31 static int sprom_read_pcmcia(void *osh
, uint16 addr
, uint16
*data
);
32 static int sprom_write_pcmcia(void *osh
, uint16 addr
, uint16 data
);
33 static int sprom_read_pci(uint16
*sprom
, uint byteoff
, uint16
*buf
, uint nbytes
, bool check_crc
);
36 * Initialize the vars from the right source for this platform.
37 * Return 0 on success, nonzero on error.
40 srom_var_init(void *sbh
, uint bus
, void *curmap
, void *osh
, char **vars
, int *count
)
47 /* These two could be asserts ... */
53 ASSERT(curmap
); /* can not be NULL */
54 return(initvars_srom_pci(curmap
, vars
, count
));
57 return(initvars_cis_pcmcia(sbh
, curmap
, osh
, vars
, count
));
67 /* support only 16-bit word read from srom */
69 srom_read(uint bus
, void *curmap
, void *osh
, uint byteoff
, uint nbytes
, uint16
*buf
)
74 /* check input - 16-bit access only */
75 if (byteoff
& 1 || nbytes
& 1 || (byteoff
+ nbytes
) > (SPROM_SIZE
* 2))
81 srom
= (void *)((uint
)curmap
+ PCI_BAR0_SPROM_OFFSET
);
82 if (sprom_read_pci(srom
, byteoff
, buf
, nbytes
, FALSE
))
84 } else if (bus
== PCMCIA_BUS
) {
87 for (i
= 0; i
< nw
; i
++) {
88 if (sprom_read_pcmcia(osh
, (uint16
)(off
+ i
), (uint16
*)(buf
+ i
)))
98 /* support only 16-bit word write into srom */
100 srom_write(uint bus
, void *curmap
, void *osh
, uint byteoff
, uint nbytes
, uint16
*buf
)
103 uint i
, off
, nw
, crc_range
;
104 uint16 image
[SPROM_SIZE
], *p
;
106 volatile uint32 val32
;
108 /* check input - 16-bit access only */
109 if (byteoff
& 1 || nbytes
& 1 || (byteoff
+ nbytes
) > (SPROM_SIZE
* 2))
112 crc_range
= ((bus
== PCMCIA_BUS
) ? SPROM_SIZE
: SPROM_CRC_RANGE
) * 2;
114 /* if changes made inside crc cover range */
115 if (byteoff
< crc_range
) {
116 nw
= (((byteoff
+ nbytes
) > crc_range
) ? byteoff
+ nbytes
: crc_range
) / 2;
117 /* read data including entire first 64 words from srom */
118 if (srom_read(bus
, curmap
, osh
, 0, nw
* 2, image
))
121 bcopy((void*)buf
, (void*)&image
[byteoff
/ 2], nbytes
);
123 htol16_buf(image
, crc_range
);
124 crc
= ~crc8((uint8
*)image
, crc_range
- 1, CRC8_INIT_VALUE
);
125 ltoh16_buf(image
, crc_range
);
126 image
[(crc_range
/ 2) - 1] = (crc
<< 8) | (image
[(crc_range
/ 2) - 1] & 0xff);
135 if (bus
== PCI_BUS
) {
136 srom
= (uint16
*)((uint
)curmap
+ PCI_BAR0_SPROM_OFFSET
);
137 /* enable writes to the SPROM */
138 val32
= OSL_PCI_READ_CONFIG(osh
, PCI_SPROM_CONTROL
, sizeof(uint32
));
139 val32
|= SPROM_WRITEEN
;
140 OSL_PCI_WRITE_CONFIG(osh
, PCI_SPROM_CONTROL
, sizeof(uint32
), val32
);
143 for (i
= 0; i
< nw
; i
++) {
144 W_REG(&srom
[off
+ i
], p
[i
]);
147 /* disable writes to the SPROM */
148 OSL_PCI_WRITE_CONFIG(osh
, PCI_SPROM_CONTROL
, sizeof(uint32
), val32
& ~SPROM_WRITEEN
);
149 } else if (bus
== PCMCIA_BUS
) {
150 /* enable writes to the SPROM */
151 if (sprom_cmd_pcmcia(osh
, SROM_WEN
))
155 for (i
= 0; i
< nw
; i
++) {
156 sprom_write_pcmcia(osh
, (uint16
)(off
+ i
), p
[i
]);
159 /* disable writes to the SPROM */
160 if (sprom_cmd_pcmcia(osh
, SROM_WDS
))
172 srom_parsecis(uint8
*cis
, char **vars
, int *count
)
176 uint8 tup
, tlen
, sromrev
= 1;
179 bool ag_init
= FALSE
;
185 base
= vp
= MALLOC(VARS_MAX
);
192 if ((i
+ tlen
) >= CIS_SIZE
)
197 vp
+= sprintf(vp
, "manfid=%d", (cis
[i
+ 1] << 8) + cis
[i
]);
199 vp
+= sprintf(vp
, "prodid=%d", (cis
[i
+ 3] << 8) + cis
[i
+ 2]);
204 if (cis
[i
] == LAN_NID
) {
205 ASSERT(cis
[i
+ 1] == ETHER_ADDR_LEN
);
206 bcm_ether_ntoa((uchar
*)&cis
[i
+ 2], eabuf
);
207 vp
+= sprintf(vp
, "il0macaddr=%s", eabuf
);
213 vp
+= sprintf(vp
, "regwindowsz=%d", (cis
[i
+ 7] << 8) | cis
[i
+ 6]);
217 case CISTPL_BRCM_HNBU
:
220 vp
+= sprintf(vp
, "vendid=%d", (cis
[i
+ 2] << 8) + cis
[i
+ 1]);
222 vp
+= sprintf(vp
, "devid=%d", (cis
[i
+ 4] << 8) + cis
[i
+ 3]);
225 vp
+= sprintf(vp
, "chiprev=%d", (cis
[i
+ 6] << 8) + cis
[i
+ 5]);
231 vp
+= sprintf(vp
, "boardrev=%d", cis
[i
+ 1]);
236 vp
+= sprintf(vp
, "aa0=%d", cis
[i
+ 1]);
241 vp
+= sprintf(vp
, "ag0=%d", cis
[i
+ 1]);
247 vp
+= sprintf(vp
, "cc=%d", cis
[i
+ 1]);
252 vp
+= sprintf(vp
, "pa0maxpwr=%d", cis
[i
+ tlen
- 1]);
256 for (j
= 0; j
< 3; j
++) {
257 vp
+= sprintf(vp
, "pa0b%d=%d", j
,
258 (cis
[i
+ (j
* 2) + 2] << 8) + cis
[i
+ (j
* 2) + 1]);
261 vp
+= sprintf(vp
, "pa0itssit=%d", cis
[i
+ 7]);
267 vp
+= sprintf(vp
, "oem=%02x%02x%02x%02x%02x%02x%02x%02x",
268 cis
[i
+ 1], cis
[i
+ 2], cis
[i
+ 3], cis
[i
+ 4],
269 cis
[i
+ 5], cis
[i
+ 6], cis
[i
+ 7], cis
[i
+ 8]);
272 case HNBU_BOARDFLAGS
:
273 w
= (cis
[i
+ 2] << 8) + cis
[i
+ 1];
274 if (w
== 0xffff) w
= 0;
275 vp
+= sprintf(vp
, "boardflags=%d", w
);
279 if (cis
[i
+ 1] != 0xff) {
280 vp
+= sprintf(vp
, "wl0gpio0=%d", cis
[i
+ 1]);
283 if (cis
[i
+ 2] != 0xff) {
284 vp
+= sprintf(vp
, "wl0gpio1=%d", cis
[i
+ 2]);
287 if (cis
[i
+ 3] != 0xff) {
288 vp
+= sprintf(vp
, "wl0gpio2=%d", cis
[i
+ 3]);
291 if (cis
[i
+ 4] != 0xff) {
292 vp
+= sprintf(vp
, "wl0gpio3=%d", cis
[i
+ 4]);
301 } while (tup
!= 0xff);
303 /* Set the srom version */
304 vp
+= sprintf(vp
, "sromrev=%d", sromrev
);
307 /* For now just set boardflags2 to zero */
308 vp
+= sprintf(vp
, "boardflags2=0");
311 /* if there is no antenna gain field, set default */
312 if (ag_init
== FALSE
) {
313 vp
+= sprintf(vp
, "ag0=%d", 0xff);
317 /* final nullbyte terminator */
319 varsize
= (uint
)vp
- (uint
)base
;
321 ASSERT(varsize
< VARS_MAX
);
323 if (varsize
== VARS_MAX
) {
326 vp
= MALLOC(varsize
);
328 bcopy(base
, vp
, varsize
);
329 MFREE(base
, VARS_MAX
);
338 /* set PCMCIA sprom command register */
340 sprom_cmd_pcmcia(void *osh
, uint8 cmd
)
343 uint wait_cnt
= 1000;
345 /* write sprom command register */
346 OSL_PCMCIA_WRITE_ATTR(osh
, SROM_CS
, &cmd
, 1);
350 OSL_PCMCIA_READ_ATTR(osh
, SROM_CS
, &status
, 1);
351 if (status
& SROM_DONE
)
358 /* read a word from the PCMCIA srom */
360 sprom_read_pcmcia(void *osh
, uint16 addr
, uint16
*data
)
362 uint8 addr_l
, addr_h
, data_l
, data_h
;
364 addr_l
= (uint8
)((addr
* 2) & 0xff);
365 addr_h
= (uint8
)(((addr
* 2) >> 8) & 0xff);
368 OSL_PCMCIA_WRITE_ATTR(osh
, SROM_ADDRH
, &addr_h
, 1);
369 OSL_PCMCIA_WRITE_ATTR(osh
, SROM_ADDRL
, &addr_l
, 1);
372 if (sprom_cmd_pcmcia(osh
, SROM_READ
))
376 OSL_PCMCIA_READ_ATTR(osh
, SROM_DATAH
, &data_h
, 1);
377 OSL_PCMCIA_READ_ATTR(osh
, SROM_DATAL
, &data_l
, 1);
379 *data
= (data_h
<< 8) | data_l
;
383 /* write a word to the PCMCIA srom */
385 sprom_write_pcmcia(void *osh
, uint16 addr
, uint16 data
)
387 uint8 addr_l
, addr_h
, data_l
, data_h
;
389 addr_l
= (uint8
)((addr
* 2) & 0xff);
390 addr_h
= (uint8
)(((addr
* 2) >> 8) & 0xff);
391 data_l
= (uint8
)(data
& 0xff);
392 data_h
= (uint8
)((data
>> 8) & 0xff);
395 OSL_PCMCIA_WRITE_ATTR(osh
, SROM_ADDRH
, &addr_h
, 1);
396 OSL_PCMCIA_WRITE_ATTR(osh
, SROM_ADDRL
, &addr_l
, 1);
399 OSL_PCMCIA_WRITE_ATTR(osh
, SROM_DATAH
, &data_h
, 1);
400 OSL_PCMCIA_WRITE_ATTR(osh
, SROM_DATAL
, &data_l
, 1);
403 return sprom_cmd_pcmcia(osh
, SROM_WRITE
);
407 * Read in and validate sprom.
408 * Return 0 on success, nonzero on error.
411 sprom_read_pci(uint16
*sprom
, uint byteoff
, uint16
*buf
, uint nbytes
, bool check_crc
)
418 nw
= ROUNDUP(nbytes
, 2) / 2;
421 for (i
= 0; i
< nw
; i
++)
422 buf
[i
] = R_REG(&sprom
[off
+ i
]);
425 /* fixup the endianness so crc8 will pass */
426 htol16_buf(buf
, nw
* 2);
427 if ((chk8
= crc8((uchar
*)buf
, nbytes
, CRC8_INIT_VALUE
)) != CRC8_GOOD_VALUE
)
429 /* now correct the endianness of the byte array */
430 ltoh16_buf(buf
, nw
* 2);
437 * Initialize nonvolatile variable table from sprom.
438 * Return 0 on success, nonzero on error.
442 initvars_srom_pci(void *curmap
, char **vars
, int *count
)
446 struct ether_addr ea
;
452 if (sprom_read_pci((void *)((uint
)curmap
+ PCI_BAR0_SPROM_OFFSET
), 0, b
, sizeof (b
), TRUE
))
455 /* top word of sprom contains version and crc8 */
456 sromrev
= b
[63] & 0xff;
457 if ((sromrev
!= 1) && (sromrev
!= 2)) {
464 base
= vp
= MALLOC(VARS_MAX
);
467 vp
+= sprintf(vp
, "sromrev=%d", sromrev
);
471 /* New section takes over the 4th hardware function space */
473 /* Word 29 is max power 11a high/low */
475 vp
+= sprintf(vp
, "pa1himaxpwr=%d", w
& 0xff);
477 vp
+= sprintf(vp
, "pa1lomaxpwr=%d", (w
>> 8) & 0xff);
480 /* Words 30-32 set the 11alow pa settings,
481 * 33-35 are the 11ahigh ones.
483 for (i
= 0; i
< 3; i
++) {
484 vp
+= sprintf(vp
, "pa1lob%d=%d", i
, b
[30 + i
]);
486 vp
+= sprintf(vp
, "pa1hib%d=%d", i
, b
[33 + i
]);
491 vp
+= sprintf(vp
, "ccode=");
493 vp
+= sprintf(vp
, "ccode=%c%c", (w
>> 8), (w
& 0xff));
498 /* parameter section of sprom starts at byte offset 72 */
501 /* first 6 bytes are il0macaddr */
502 ea
.octet
[0] = (b
[woff
] >> 8) & 0xff;
503 ea
.octet
[1] = b
[woff
] & 0xff;
504 ea
.octet
[2] = (b
[woff
+1] >> 8) & 0xff;
505 ea
.octet
[3] = b
[woff
+1] & 0xff;
506 ea
.octet
[4] = (b
[woff
+2] >> 8) & 0xff;
507 ea
.octet
[5] = b
[woff
+2] & 0xff;
508 woff
+= ETHER_ADDR_LEN
/2 ;
509 bcm_ether_ntoa((uchar
*)&ea
, eabuf
);
510 vp
+= sprintf(vp
, "il0macaddr=%s", eabuf
);
513 /* next 6 bytes are et0macaddr */
514 ea
.octet
[0] = (b
[woff
] >> 8) & 0xff;
515 ea
.octet
[1] = b
[woff
] & 0xff;
516 ea
.octet
[2] = (b
[woff
+1] >> 8) & 0xff;
517 ea
.octet
[3] = b
[woff
+1] & 0xff;
518 ea
.octet
[4] = (b
[woff
+2] >> 8) & 0xff;
519 ea
.octet
[5] = b
[woff
+2] & 0xff;
520 woff
+= ETHER_ADDR_LEN
/2 ;
521 bcm_ether_ntoa((uchar
*)&ea
, eabuf
);
522 vp
+= sprintf(vp
, "et0macaddr=%s", eabuf
);
525 /* next 6 bytes are et1macaddr */
526 ea
.octet
[0] = (b
[woff
] >> 8) & 0xff;
527 ea
.octet
[1] = b
[woff
] & 0xff;
528 ea
.octet
[2] = (b
[woff
+1] >> 8) & 0xff;
529 ea
.octet
[3] = b
[woff
+1] & 0xff;
530 ea
.octet
[4] = (b
[woff
+2] >> 8) & 0xff;
531 ea
.octet
[5] = b
[woff
+2] & 0xff;
532 woff
+= ETHER_ADDR_LEN
/2 ;
533 bcm_ether_ntoa((uchar
*)&ea
, eabuf
);
534 vp
+= sprintf(vp
, "et1macaddr=%s", eabuf
);
538 * Enet phy settings one or two singles or a dual
539 * Bits 4-0 : MII address for enet0 (0x1f for not there)
540 * Bits 9-5 : MII address for enet1 (0x1f for not there)
541 * Bit 14 : Mdio for enet0
542 * Bit 15 : Mdio for enet1
545 vp
+= sprintf(vp
, "et0phyaddr=%d", (w
& 0x1f));
547 vp
+= sprintf(vp
, "et1phyaddr=%d", ((w
>> 5) & 0x1f));
549 vp
+= sprintf(vp
, "et0mdcport=%d", ((w
>> 14) & 0x1));
551 vp
+= sprintf(vp
, "et1mdcport=%d", ((w
>> 15) & 0x1));
554 /* Word 46 has board rev, antennas 0/1 & Country code/control */
556 vp
+= sprintf(vp
, "boardrev=%d", w
& 0xff);
560 vp
+= sprintf(vp
, "cctl=%d", (w
>> 8) & 0xf);
562 vp
+= sprintf(vp
, "cc=%d", (w
>> 8) & 0xf);
565 vp
+= sprintf(vp
, "aa0=%d", (w
>> 12) & 0x3);
568 vp
+= sprintf(vp
, "aa1=%d", (w
>> 14) & 0x3);
571 /* Words 47-49 set the (wl) pa settings */
574 for (i
= 0; i
< 3; i
++) {
575 vp
+= sprintf(vp
, "pa0b%d=%d", i
, b
[woff
+i
]);
577 vp
+= sprintf(vp
, "pa1b%d=%d", i
, b
[woff
+i
+6]);
582 * Words 50-51 set the customer-configured wl led behavior.
583 * 8 bits/gpio pin. High bit: activehi=0, activelo=1;
584 * LED behavior values defined in wlioctl.h .
587 if ((w
!= 0) && (w
!= 0xffff)) {
589 vp
+= sprintf(vp
, "wl0gpio0=%d", (w
& 0xff));
593 vp
+= sprintf(vp
, "wl0gpio1=%d", (w
>> 8) & 0xff);
597 if ((w
!= 0) && (w
!= 0xffff)) {
599 vp
+= sprintf(vp
, "wl0gpio2=%d", w
& 0xff);
603 vp
+= sprintf(vp
, "wl0gpio3=%d", (w
>> 8) & 0xff);
607 /* Word 52 is max power 0/1 */
609 vp
+= sprintf(vp
, "pa0maxpwr=%d", w
& 0xff);
611 vp
+= sprintf(vp
, "pa1maxpwr=%d", (w
>> 8) & 0xff);
614 /* Word 56 is idle tssi target 0/1 */
616 vp
+= sprintf(vp
, "pa0itssit=%d", w
& 0xff);
618 vp
+= sprintf(vp
, "pa1itssit=%d", (w
>> 8) & 0xff);
621 /* Word 57 is boardflags, if not programmed make it zero */
623 if (bfl
== 0xffff) bfl
= 0;
625 /* Word 28 is boardflags2 */
626 bfl
|= (uint32
)b
[28] << 16;
628 vp
+= sprintf(vp
, "boardflags=%d", bfl
);
631 /* Word 58 is antenna gain 0/1 */
633 vp
+= sprintf(vp
, "ag0=%d", w
& 0xff);
636 vp
+= sprintf(vp
, "ag1=%d", (w
>> 8) & 0xff);
640 /* set the oem string */
641 vp
+= sprintf(vp
, "oem=%02x%02x%02x%02x%02x%02x%02x%02x",
642 ((b
[59] >> 8) & 0xff), (b
[59] & 0xff),
643 ((b
[60] >> 8) & 0xff), (b
[60] & 0xff),
644 ((b
[61] >> 8) & 0xff), (b
[61] & 0xff),
645 ((b
[62] >> 8) & 0xff), (b
[62] & 0xff));
649 /* Word 60 OFDM tx power offset from CCK level */
650 /* OFDM Power Offset - opo */
654 vp
+= sprintf(vp
, "opo=%d", w
);
659 /* final nullbyte terminator */
663 ASSERT(c
<= VARS_MAX
);
671 MFREE(base
, VARS_MAX
);
680 * Read the cis and call parsecis to initialize the vars.
681 * Return 0 on success, nonzero on error.
684 initvars_cis_pcmcia(void *sbh
, void *curmap
, void *osh
, char **vars
, int *count
)
690 data_sz
= (sb_pcmciarev(sbh
) == 1) ? (SPROM_SIZE
* 2) : CIS_SIZE
;
692 if ((cis
= MALLOC(data_sz
)) == NULL
)
695 if (sb_pcmciarev(sbh
) == 1) {
696 if (srom_read(PCMCIA_BUS
, (void *)NULL
, osh
, 0, data_sz
, (uint16
*)cis
)) {
700 /* fix up endianess for 16-bit data vs 8-bit parsing */
701 ltoh16_buf((uint16
*)cis
, data_sz
);
703 OSL_PCMCIA_READ_ATTR(osh
, 0, cis
, data_sz
);
705 rc
= srom_parsecis(cis
, vars
, count
);
This page took 0.090599 seconds and 5 git commands to generate.