2 * Copyright (c) 2010 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 #include <linux/kernel.h>
17 #include <linux/string.h>
18 #include <linux/etherdevice.h>
20 #include <linux/module.h>
21 #include <linux/pci.h>
30 #include <bcmsrom_tbl.h>
35 #define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \
36 (((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \
37 ((u8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \
38 ((u8 *)curmap + PCI_BAR0_SPROM_OFFSET))
41 #define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
42 #define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
45 typedef struct varbuf {
46 char *base; /* pointer to buffer base */
47 char *buf; /* pointer to current position */
48 unsigned int size; /* current (residual) size in bytes */
53 static int initvars_srom_si(si_t *sih, void *curmap, char **vars, uint *count);
54 static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b);
55 static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count);
56 static int initvars_flash_si(si_t *sih, char **vars, uint *count);
57 static int sprom_read_pci(si_t *sih, u16 *sprom,
58 uint wordoff, u16 *buf, uint nwords, bool check_crc);
59 #if defined(BCMNVRAMR)
60 static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz);
62 static u16 srom_cc_cmd(si_t *sih, void *ccregs, u32 cmd,
63 uint wordoff, u16 data);
65 static int initvars_table(char *start, char *end,
66 char **vars, uint *count);
67 static int initvars_flash(si_t *sih, char **vp,
70 /* Initialization of varbuf structure */
71 static void varbuf_init(varbuf_t *b, char *buf, uint size)
74 b->base = b->buf = buf;
77 /* append a null terminated var=value string */
78 static int varbuf_append(varbuf_t *b, const char *fmt, ...)
89 r = vsnprintf(b->buf, b->size, fmt, ap);
92 /* C99 snprintf behavior returns r >= size on overflow,
93 * others return -1 on overflow.
94 * All return -1 on format error.
95 * We need to leave room for 2 null terminations, one for the current var
96 * string, and one for final null of the var table. So check that the
97 * strlen written, r, leaves room for 2 chars.
99 if ((r == -1) || (r > (int)(b->size - 2))) {
104 /* Remove any earlier occurrence of the same variable */
105 s = strchr(b->buf, '=');
107 len = (size_t) (s - b->buf);
108 for (s = b->base; s < b->buf;) {
109 if ((memcmp(s, b->buf, len) == 0) && s[len] == '=') {
111 memmove(s, (s + len),
112 ((b->buf + r + 1) - (s + len)));
114 b->size += (unsigned int)len;
123 /* skip over this string's null termination */
132 * Initialize local vars from the right source for this platform.
133 * Return 0 on success, nonzero on error.
135 int srom_var_init(si_t *sih, uint bustype, void *curmap,
136 char **vars, uint *count)
142 if (vars == NULL || count == NULL)
151 return initvars_srom_si(sih, curmap, vars, count);
157 return initvars_srom_pci(sih, curmap, vars, count);
165 /* In chips with chipcommon rev 32 and later, the srom is in chipcommon,
166 * not in the bus cores.
169 srom_cc_cmd(si_t *sih, void *ccregs, u32 cmd,
170 uint wordoff, u16 data)
172 chipcregs_t *cc = (chipcregs_t *) ccregs;
173 uint wait_cnt = 1000;
175 if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
176 W_REG(&cc->sromaddress, wordoff * 2);
177 if (cmd == SRC_OP_WRITE)
178 W_REG(&cc->sromdata, data);
181 W_REG(&cc->sromcontrol, SRC_START | cmd);
184 if ((R_REG(&cc->sromcontrol) & SRC_BUSY) == 0)
191 if (cmd == SRC_OP_READ)
192 return (u16) R_REG(&cc->sromdata);
197 static inline void ltoh16_buf(u16 *buf, unsigned int size)
199 for (size /= 2; size; size--)
200 *(buf + size) = le16_to_cpu(*(buf + size));
203 static inline void htol16_buf(u16 *buf, unsigned int size)
205 for (size /= 2; size; size--)
206 *(buf + size) = cpu_to_le16(*(buf + size));
210 * Read in and validate sprom.
211 * Return 0 on success, nonzero on error.
214 sprom_read_pci(si_t *sih, u16 *sprom, uint wordoff,
215 u16 *buf, uint nwords, bool check_crc)
222 for (i = 0; i < nwords; i++) {
224 if (sih->ccrev > 31 && ISSIM_ENAB(sih)) {
225 /* use indirect since direct is too slow on QT */
226 if ((sih->cccaps & CC_CAP_SROM) == 0)
229 ccregs = (void *)((u8 *) sprom - CC_SROM_OTP);
231 srom_cc_cmd(sih, ccregs, SRC_OP_READ,
236 buf[i] = R_REG(&sprom[wordoff + i]);
238 buf[i] = R_REG(&sprom[wordoff + i]);
243 /* bypass crc checking for simulation to allow srom hack */
249 if (buf[0] == 0xffff) {
250 /* The hardware thinks that an srom that starts with 0xffff
251 * is blank, regardless of the rest of the content, so declare
257 /* fixup the endianness so crc8 will pass */
258 htol16_buf(buf, nwords * 2);
259 if (bcm_crc8((u8 *) buf, nwords * 2, CRC8_INIT_VALUE) !=
261 /* DBG only pci always read srom4 first, then srom8/9 */
264 /* now correct the endianness of the byte array */
265 ltoh16_buf(buf, nwords * 2);
270 #if defined(BCMNVRAMR)
271 static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz)
274 uint sz = OTP_SZ_MAX / 2; /* size in words */
277 otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
282 err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
284 memcpy(buf, otp, bufsz);
289 if (buf[0] == 0xffff) {
290 /* The hardware thinks that an srom that starts with 0xffff
291 * is blank, regardless of the rest of the content, so declare
297 /* fixup the endianness so crc8 will pass */
298 htol16_buf(buf, bufsz);
299 if (bcm_crc8((u8 *) buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) !=
303 /* now correct the endianness of the byte array */
304 ltoh16_buf(buf, bufsz);
308 #endif /* defined(BCMNVRAMR) */
310 * Create variable table from memory.
311 * Return 0 on success, nonzero on error.
313 static int initvars_table(char *start, char *end,
314 char **vars, uint *count)
316 int c = (int)(end - start);
318 /* do it only when there is more than just the null string */
320 char *vp = kmalloc(c, GFP_ATOMIC);
323 memcpy(vp, start, c);
335 * Find variables with <devpath> from flash. 'base' points to the beginning
336 * of the table upon enter and to the end of the table upon exit when success.
337 * Return 0 on success, nonzero on error.
339 static int initvars_flash(si_t *sih, char **base, uint len)
345 uint l, dl, copy_len;
346 char devpath[SI_DEVPATH_BUFSZ];
348 /* allocate memory and read in flash */
349 flash = kmalloc(NVRAM_SPACE, GFP_ATOMIC);
352 err = nvram_getall(flash, NVRAM_SPACE);
356 ai_devpath(sih, devpath, sizeof(devpath));
358 /* grab vars with the <devpath> prefix in name */
359 dl = strlen(devpath);
360 for (s = flash; s && *s; s += l + 1) {
363 /* skip non-matching variable */
364 if (strncmp(s, devpath, dl))
367 /* is there enough room to copy? */
368 copy_len = l - dl + 1;
369 if (len < copy_len) {
374 /* no prefix, just the name=value */
375 strncpy(vp, &s[dl], copy_len);
380 /* add null string as terminator */
394 * Initialize nonvolatile variable table from flash.
395 * Return 0 on success, nonzero on error.
397 static int initvars_flash_si(si_t *sih, char **vars, uint *count)
402 base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
406 err = initvars_flash(sih, &vp, MAXSZ_NVRAM_VARS);
408 err = initvars_table(base, vp, vars, count);
415 /* Parse SROM and create name=value pairs. 'srom' points to
416 * the SROM word array. 'off' specifies the offset of the
417 * first word 'srom' points to, which should be either 0 or
418 * SROM3_SWRG_OFF (full SROM or software region).
421 static uint mask_shift(u16 mask)
424 for (i = 0; i < (sizeof(mask) << 3); i++) {
431 static uint mask_width(u16 mask)
434 for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) {
436 return (uint) (i - mask_shift(mask) + 1);
441 static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b)
445 const sromvar_t *srv;
448 u32 sr = (1 << sromrev);
450 varbuf_append(b, "sromrev=%d", sromrev);
452 for (srv = pci_sromvars; srv->name != NULL; srv++) {
455 if ((srv->revmask & sr) == 0)
464 /* This entry is for mfgc only. Don't generate param for it, */
465 if (flags & SRFL_NOVAR)
468 if (flags & SRFL_ETHADDR) {
471 ea[0] = (srom[srv->off - off] >> 8) & 0xff;
472 ea[1] = srom[srv->off - off] & 0xff;
473 ea[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
474 ea[3] = srom[srv->off + 1 - off] & 0xff;
475 ea[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
476 ea[5] = srom[srv->off + 2 - off] & 0xff;
478 varbuf_append(b, "%s=%pM", name, ea);
480 w = srom[srv->off - off];
481 val = (w & srv->mask) >> mask_shift(srv->mask);
482 width = mask_width(srv->mask);
484 while (srv->flags & SRFL_MORE) {
486 if (srv->off == 0 || srv->off < off)
489 w = srom[srv->off - off];
491 ((w & srv->mask) >> mask_shift(srv->
494 width += mask_width(srv->mask);
497 if ((flags & SRFL_NOFFS)
498 && ((int)val == (1 << width) - 1))
501 if (flags & SRFL_CCODE) {
503 varbuf_append(b, "ccode=");
505 varbuf_append(b, "ccode=%c%c",
506 (val >> 8), (val & 0xff));
508 /* LED Powersave duty cycle has to be scaled:
509 *(oncount >> 24) (offcount >> 8)
511 else if (flags & SRFL_LEDDC) {
512 u32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */
513 (((val & 0xff)) << 8); /* offcount */
514 varbuf_append(b, "leddc=%d", w32);
515 } else if (flags & SRFL_PRHEX)
516 varbuf_append(b, "%s=0x%x", name, val);
517 else if ((flags & SRFL_PRSIGN)
518 && (val & (1 << (width - 1))))
519 varbuf_append(b, "%s=%d", name,
520 (int)(val | (~0 << width)));
522 varbuf_append(b, "%s=%u", name, val);
527 /* Do per-path variables */
532 psz = SROM8_PATH1 - SROM8_PATH0;
535 psz = SROM4_PATH1 - SROM4_PATH0;
538 for (p = 0; p < MAX_PATH_SROM; p++) {
539 for (srv = perpath_pci_sromvars; srv->name != NULL;
541 if ((srv->revmask & sr) == 0)
544 if (pb + srv->off < off)
547 /* This entry is for mfgc only. Don't generate param for it, */
548 if (srv->flags & SRFL_NOVAR)
551 w = srom[pb + srv->off - off];
552 val = (w & srv->mask) >> mask_shift(srv->mask);
553 width = mask_width(srv->mask);
555 /* Cheating: no per-path var is more than 1 word */
557 if ((srv->flags & SRFL_NOFFS)
558 && ((int)val == (1 << width) - 1))
561 if (srv->flags & SRFL_PRHEX)
562 varbuf_append(b, "%s%d=0x%x", srv->name,
565 varbuf_append(b, "%s%d=%d", srv->name,
574 * Initialize nonvolatile variable table from sprom.
575 * Return 0 on success, nonzero on error.
577 static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
579 u16 *srom, *sromwindow;
583 char *vp, *base = NULL;
588 * Apply CRC over SROM content regardless SROM is present or not,
589 * and use variable <devpath>sromrev's existence in flash to decide
590 * if we should return an error when CRC fails or read SROM variables
593 srom = kmalloc(SROM_MAX, GFP_ATOMIC);
597 sromwindow = (u16 *) SROM_OFFSET(sih);
598 if (ai_is_sprom_available(sih)) {
600 sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS,
603 if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
604 (((sih->buscoretype == PCIE_CORE_ID)
605 && (sih->buscorerev >= 6))
606 || ((sih->buscoretype == PCI_CORE_ID)
607 && (sih->buscorerev >= 0xe)))) {
608 /* sromrev >= 4, read more */
610 sprom_read_pci(sih, sromwindow, 0, srom,
612 sromrev = srom[SROM4_CRCREV] & 0xff;
613 } else if (err == 0) {
614 /* srom is good and is rev < 4 */
615 /* top word of sprom contains version and crc8 */
616 sromrev = srom[SROM_CRCREV] & 0xff;
617 /* bcm4401 sroms misprogrammed */
622 #if defined(BCMNVRAMR)
623 /* Use OTP if SPROM not available */
625 err = otp_read_pci(sih, srom, SROM_MAX);
627 /* OTP only contain SROM rev8/rev9 for now */
628 sromrev = srom[SROM4_CRCREV] & 0xff;
638 * We want internal/wltest driver to come up with default
639 * sromvars so we can program a blank SPROM/OTP.
646 value = ai_getdevpathvar(sih, "sromrev");
648 sromrev = (u8) simple_strtoul(value, NULL, 0);
653 value = ai_getnvramflvar(sih, "sromrev");
666 /* Bitmask for the sromrev */
669 /* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, 9 */
670 if ((sr & 0x33e) == 0) {
675 base = vp = kmalloc(MAXSZ_NVRAM_VARS, GFP_ATOMIC);
681 /* read variables from flash */
683 err = initvars_flash(sih, &vp, MAXSZ_NVRAM_VARS);
689 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
691 /* parse SROM into name=value pairs. */
692 _initvars_srom_pci(sromrev, srom, 0, &b);
694 /* final nullbyte terminator */
699 err = initvars_table(base, vp, vars, count);
710 static int initvars_srom_si(si_t *sih, void *curmap, char **vars, uint *varsz)
712 /* Search flash nvram section for srom variables */
713 return initvars_flash_si(sih, vars, varsz);