+++ /dev/null
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-
-#include <brcm_hw_ids.h>
-#include <chipcommon.h>
-#include "aiutils.h"
-#include "otp.h"
-
-#define OTPS_GUP_MASK          0x00000f00
-#define OTPS_GUP_SHIFT         8
-/* h/w subregion is programmed */
-#define OTPS_GUP_HW            0x00000100
-/* s/w subregion is programmed */
-#define OTPS_GUP_SW            0x00000200
-/* chipid/pkgopt subregion is programmed */
-#define OTPS_GUP_CI            0x00000400
-/* fuse subregion is programmed */
-#define OTPS_GUP_FUSE          0x00000800
-
-/* Fields in otpprog in rev >= 21 */
-#define OTPP_COL_MASK          0x000000ff
-#define OTPP_COL_SHIFT         0
-#define OTPP_ROW_MASK          0x0000ff00
-#define OTPP_ROW_SHIFT         8
-#define OTPP_OC_MASK           0x0f000000
-#define OTPP_OC_SHIFT          24
-#define OTPP_READERR           0x10000000
-#define OTPP_VALUE_MASK                0x20000000
-#define OTPP_VALUE_SHIFT       29
-#define OTPP_START_BUSY                0x80000000
-#define        OTPP_READ               0x40000000
-
-/* Opcodes for OTPP_OC field */
-#define OTPPOC_READ            0
-#define OTPPOC_BIT_PROG                1
-#define OTPPOC_VERIFY          3
-#define OTPPOC_INIT            4
-#define OTPPOC_SET             5
-#define OTPPOC_RESET           6
-#define OTPPOC_OCST            7
-#define OTPPOC_ROW_LOCK                8
-#define OTPPOC_PRESCN_TEST     9
-
-#define OTPTYPE_IPX(ccrev)     ((ccrev) == 21 || (ccrev) >= 23)
-
-#define OTPP_TRIES     10000000        /* # of tries for OTPP */
-
-#define MAXNUMRDES             9       /* Maximum OTP redundancy entries */
-
-/* Fixed size subregions sizes in words */
-#define OTPGU_CI_SZ            2
-
-struct otpinfo;
-
-/* OTP function struct */
-struct otp_fn_s {
-       int (*init)(struct si_pub *sih, struct otpinfo *oi);
-       int (*read_region)(struct otpinfo *oi, int region, u16 *data,
-                          uint *wlen);
-};
-
-struct otpinfo {
-       struct bcma_device *core; /* chipc core */
-       const struct otp_fn_s *fn;      /* OTP functions */
-       struct si_pub *sih;             /* Saved sb handle */
-
-       /* IPX OTP section */
-       u16 wsize;              /* Size of otp in words */
-       u16 rows;               /* Geometry */
-       u16 cols;               /* Geometry */
-       u32 status;             /* Flag bits (lock/prog/rv).
-                                * (Reflected only when OTP is power cycled)
-                                */
-       u16 hwbase;             /* hardware subregion offset */
-       u16 hwlim;              /* hardware subregion boundary */
-       u16 swbase;             /* software subregion offset */
-       u16 swlim;              /* software subregion boundary */
-       u16 fbase;              /* fuse subregion offset */
-       u16 flim;               /* fuse subregion boundary */
-       int otpgu_base;         /* offset to General Use Region */
-};
-
-/* OTP layout */
-/* CC revs 21, 24 and 27 OTP General Use Region word offset */
-#define REVA4_OTPGU_BASE       12
-
-/* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */
-#define REVB8_OTPGU_BASE       20
-
-/* CC rev 36 OTP General Use Region word offset */
-#define REV36_OTPGU_BASE       12
-
-/* Subregion word offsets in General Use region */
-#define OTPGU_HSB_OFF          0
-#define OTPGU_SFB_OFF          1
-#define OTPGU_CI_OFF           2
-#define OTPGU_P_OFF            3
-#define OTPGU_SROM_OFF         4
-
-/* Flag bit offsets in General Use region  */
-#define OTPGU_HWP_OFF          60
-#define OTPGU_SWP_OFF          61
-#define OTPGU_CIP_OFF          62
-#define OTPGU_FUSEP_OFF                63
-#define OTPGU_CIP_MSK          0x4000
-#define OTPGU_P_MSK            0xf000
-#define OTPGU_P_SHIFT          (OTPGU_HWP_OFF % 16)
-
-/* OTP Size */
-#define OTP_SZ_FU_324          ((roundup(324, 8))/8)   /* 324 bits */
-#define OTP_SZ_FU_288          (288/8) /* 288 bits */
-#define OTP_SZ_FU_216          (216/8) /* 216 bits */
-#define OTP_SZ_FU_72           (72/8)  /* 72 bits */
-#define OTP_SZ_CHECKSUM                (16/8)  /* 16 bits */
-#define OTP4315_SWREG_SZ       178     /* 178 bytes */
-#define OTP_SZ_FU_144          (144/8) /* 144 bits */
-
-static u16
-ipxotp_otpr(struct otpinfo *oi, uint wn)
-{
-       return bcma_read16(oi->core,
-                          CHIPCREGOFFS(sromotp[wn]));
-}
-
-/*
- * Calculate max HW/SW region byte size by subtracting fuse region
- * and checksum size, osizew is oi->wsize (OTP size - GU size) in words
- */
-static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
-{
-       int ret = 0;
-
-       switch (ai_get_chip_id(sih)) {
-       case BCM43224_CHIP_ID:
-       case BCM43225_CHIP_ID:
-               ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
-               break;
-       case BCM4313_CHIP_ID:
-               ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
-               break;
-       default:
-               break;  /* Don't know about this chip */
-       }
-
-       return ret;
-}
-
-static void _ipxotp_init(struct otpinfo *oi)
-{
-       uint k;
-       u32 otpp, st;
-       int ccrev = ai_get_ccrev(oi->sih);
-
-
-       /*
-        * record word offset of General Use Region
-        * for various chipcommon revs
-        */
-       if (ccrev == 21 || ccrev == 24
-           || ccrev == 27) {
-               oi->otpgu_base = REVA4_OTPGU_BASE;
-       } else if (ccrev == 36) {
-               /*
-                * OTP size greater than equal to 2KB (128 words),
-                * otpgu_base is similar to rev23
-                */
-               if (oi->wsize >= 128)
-                       oi->otpgu_base = REVB8_OTPGU_BASE;
-               else
-                       oi->otpgu_base = REV36_OTPGU_BASE;
-       } else if (ccrev == 23 || ccrev >= 25) {
-               oi->otpgu_base = REVB8_OTPGU_BASE;
-       }
-
-       /* First issue an init command so the status is up to date */
-       otpp =
-           OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
-
-       bcma_write32(oi->core, CHIPCREGOFFS(otpprog), otpp);
-       st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog));
-       for (k = 0; (st & OTPP_START_BUSY) && (k < OTPP_TRIES); k++)
-               st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog));
-       if (k >= OTPP_TRIES)
-               return;
-
-       /* Read OTP lock bits and subregion programmed indication bits */
-       oi->status = bcma_read32(oi->core, CHIPCREGOFFS(otpstatus));
-
-       if ((ai_get_chip_id(oi->sih) == BCM43224_CHIP_ID)
-           || (ai_get_chip_id(oi->sih) == BCM43225_CHIP_ID)) {
-               u32 p_bits;
-               p_bits = (ipxotp_otpr(oi, oi->otpgu_base + OTPGU_P_OFF) &
-                         OTPGU_P_MSK) >> OTPGU_P_SHIFT;
-               oi->status |= (p_bits << OTPS_GUP_SHIFT);
-       }
-
-       /*
-        * h/w region base and fuse region limit are fixed to
-        * the top and the bottom of the general use region.
-        * Everything else can be flexible.
-        */
-       oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF;
-       oi->hwlim = oi->wsize;
-       if (oi->status & OTPS_GUP_HW) {
-               oi->hwlim =
-                   ipxotp_otpr(oi, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
-               oi->swbase = oi->hwlim;
-       } else
-               oi->swbase = oi->hwbase;
-
-       /* subtract fuse and checksum from beginning */
-       oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2;
-
-       if (oi->status & OTPS_GUP_SW) {
-               oi->swlim =
-                   ipxotp_otpr(oi, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
-               oi->fbase = oi->swlim;
-       } else
-               oi->fbase = oi->swbase;
-
-       oi->flim = oi->wsize;
-}
-
-static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
-{
-       /* Make sure we're running IPX OTP */
-       if (!OTPTYPE_IPX(ai_get_ccrev(sih)))
-               return -EBADE;
-
-       /* Make sure OTP is not disabled */
-       if (ai_is_otp_disabled(sih))
-               return -EBADE;
-
-       /* Check for otp size */
-       switch ((ai_get_cccaps(sih) & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
-       case 0:
-               /* Nothing there */
-               return -EBADE;
-       case 1:         /* 32x64 */
-               oi->rows = 32;
-               oi->cols = 64;
-               oi->wsize = 128;
-               break;
-       case 2:         /* 64x64 */
-               oi->rows = 64;
-               oi->cols = 64;
-               oi->wsize = 256;
-               break;
-       case 5:         /* 96x64 */
-               oi->rows = 96;
-               oi->cols = 64;
-               oi->wsize = 384;
-               break;
-       case 7:         /* 16x64 *//* 1024 bits */
-               oi->rows = 16;
-               oi->cols = 64;
-               oi->wsize = 64;
-               break;
-       default:
-               /* Don't know the geometry */
-               return -EBADE;
-       }
-
-       /* Retrieve OTP region info */
-       _ipxotp_init(oi);
-       return 0;
-}
-
-static int
-ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen)
-{
-       uint base, i, sz;
-
-       /* Validate region selection */
-       switch (region) {
-       case OTP_HW_RGN:
-               sz = (uint) oi->hwlim - oi->hwbase;
-               if (!(oi->status & OTPS_GUP_HW)) {
-                       *wlen = sz;
-                       return -ENODATA;
-               }
-               if (*wlen < sz) {
-                       *wlen = sz;
-                       return -EOVERFLOW;
-               }
-               base = oi->hwbase;
-               break;
-       case OTP_SW_RGN:
-               sz = ((uint) oi->swlim - oi->swbase);
-               if (!(oi->status & OTPS_GUP_SW)) {
-                       *wlen = sz;
-                       return -ENODATA;
-               }
-               if (*wlen < sz) {
-                       *wlen = sz;
-                       return -EOVERFLOW;
-               }
-               base = oi->swbase;
-               break;
-       case OTP_CI_RGN:
-               sz = OTPGU_CI_SZ;
-               if (!(oi->status & OTPS_GUP_CI)) {
-                       *wlen = sz;
-                       return -ENODATA;
-               }
-               if (*wlen < sz) {
-                       *wlen = sz;
-                       return -EOVERFLOW;
-               }
-               base = oi->otpgu_base + OTPGU_CI_OFF;
-               break;
-       case OTP_FUSE_RGN:
-               sz = (uint) oi->flim - oi->fbase;
-               if (!(oi->status & OTPS_GUP_FUSE)) {
-                       *wlen = sz;
-                       return -ENODATA;
-               }
-               if (*wlen < sz) {
-                       *wlen = sz;
-                       return -EOVERFLOW;
-               }
-               base = oi->fbase;
-               break;
-       case OTP_ALL_RGN:
-               sz = ((uint) oi->flim - oi->hwbase);
-               if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) {
-                       *wlen = sz;
-                       return -ENODATA;
-               }
-               if (*wlen < sz) {
-                       *wlen = sz;
-                       return -EOVERFLOW;
-               }
-               base = oi->hwbase;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       /* Read the data */
-       for (i = 0; i < sz; i++)
-               data[i] = ipxotp_otpr(oi, base + i);
-
-       *wlen = sz;
-       return 0;
-}
-
-static const struct otp_fn_s ipxotp_fn = {
-       (int (*)(struct si_pub *, struct otpinfo *)) ipxotp_init,
-       (int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region,
-};
-
-static int otp_init(struct si_pub *sih, struct otpinfo *oi)
-{
-       int ret;
-
-       memset(oi, 0, sizeof(struct otpinfo));
-
-       oi->core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
-
-       if (OTPTYPE_IPX(ai_get_ccrev(sih)))
-               oi->fn = &ipxotp_fn;
-
-       if (oi->fn == NULL)
-               return -EBADE;
-
-       oi->sih = sih;
-
-       ret = (oi->fn->init)(sih, oi);
-
-       return ret;
-}
-
-int
-otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) {
-       struct otpinfo otpinfo;
-       struct otpinfo *oi = &otpinfo;
-       int err = 0;
-
-       if (ai_is_otp_disabled(sih)) {
-               err = -EPERM;
-               goto out;
-       }
-
-       err = otp_init(sih, oi);
-       if (err)
-               goto out;
-
-       err = ((oi)->fn->read_region)(oi, region, data, wlen);
-
- out:
-       return err;
-}
 
+++ /dev/null
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/io.h>
-#include <linux/etherdevice.h>
-#include <linux/crc8.h>
-#include <stdarg.h>
-
-#include <chipcommon.h>
-#include <brcmu_utils.h>
-#include "pub.h"
-#include "nicpci.h"
-#include "aiutils.h"
-#include "otp.h"
-#include "srom.h"
-#include "soc.h"
-
-/*
- * SROM CRC8 polynomial value:
- *
- * x^8 + x^7 +x^6 + x^4 + x^2 + 1
- */
-#define SROM_CRC8_POLY         0xAB
-
-/* Maximum srom: 6 Kilobits == 768 bytes */
-#define        SROM_MAX                768
-
-/* PCI fields */
-#define PCI_F0DEVID            48
-
-#define        SROM_WORDS              64
-
-#define        SROM_SSID               2
-
-#define        SROM_WL1LHMAXP          29
-
-#define        SROM_WL1LPAB0           30
-#define        SROM_WL1LPAB1           31
-#define        SROM_WL1LPAB2           32
-
-#define        SROM_WL1HPAB0           33
-#define        SROM_WL1HPAB1           34
-#define        SROM_WL1HPAB2           35
-
-#define        SROM_MACHI_IL0          36
-#define        SROM_MACMID_IL0         37
-#define        SROM_MACLO_IL0          38
-#define        SROM_MACHI_ET1          42
-#define        SROM_MACMID_ET1         43
-#define        SROM_MACLO_ET1          44
-
-#define        SROM_BXARSSI2G          40
-#define        SROM_BXARSSI5G          41
-
-#define        SROM_TRI52G             42
-#define        SROM_TRI5GHL            43
-
-#define        SROM_RXPO52G            45
-
-#define        SROM_AABREV             46
-/* Fields in AABREV */
-#define        SROM_BR_MASK            0x00ff
-#define        SROM_CC_MASK            0x0f00
-#define        SROM_CC_SHIFT           8
-#define        SROM_AA0_MASK           0x3000
-#define        SROM_AA0_SHIFT          12
-#define        SROM_AA1_MASK           0xc000
-#define        SROM_AA1_SHIFT          14
-
-#define        SROM_WL0PAB0            47
-#define        SROM_WL0PAB1            48
-#define        SROM_WL0PAB2            49
-
-#define        SROM_LEDBH10            50
-#define        SROM_LEDBH32            51
-
-#define        SROM_WL10MAXP           52
-
-#define        SROM_WL1PAB0            53
-#define        SROM_WL1PAB1            54
-#define        SROM_WL1PAB2            55
-
-#define        SROM_ITT                56
-
-#define        SROM_BFL                57
-#define        SROM_BFL2               28
-
-#define        SROM_AG10               58
-
-#define        SROM_CCODE              59
-
-#define        SROM_OPO                60
-
-#define        SROM_CRCREV             63
-
-#define        SROM4_WORDS             220
-
-#define SROM4_TXCHAIN_MASK     0x000f
-#define SROM4_RXCHAIN_MASK     0x00f0
-#define SROM4_SWITCH_MASK      0xff00
-
-/* Per-path fields */
-#define        MAX_PATH_SROM           4
-
-#define        SROM4_CRCREV            219
-
-/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6.
- * This is acombined srom for both MIMO and SISO boards, usable in
- * the .130 4Kilobit OTP with hardware redundancy.
- */
-#define        SROM8_BREV              65
-
-#define        SROM8_BFL0              66
-#define        SROM8_BFL1              67
-#define        SROM8_BFL2              68
-#define        SROM8_BFL3              69
-
-#define        SROM8_MACHI             70
-#define        SROM8_MACMID            71
-#define        SROM8_MACLO             72
-
-#define        SROM8_CCODE             73
-#define        SROM8_REGREV            74
-
-#define        SROM8_LEDBH10           75
-#define        SROM8_LEDBH32           76
-
-#define        SROM8_LEDDC             77
-
-#define        SROM8_AA                78
-
-#define        SROM8_AG10              79
-#define        SROM8_AG32              80
-
-#define        SROM8_TXRXC             81
-
-#define        SROM8_BXARSSI2G         82
-#define        SROM8_BXARSSI5G         83
-#define        SROM8_TRI52G            84
-#define        SROM8_TRI5GHL           85
-#define        SROM8_RXPO52G           86
-
-#define SROM8_FEM2G            87
-#define SROM8_FEM5G            88
-#define SROM8_FEM_ANTSWLUT_MASK                0xf800
-#define SROM8_FEM_ANTSWLUT_SHIFT       11
-#define SROM8_FEM_TR_ISO_MASK          0x0700
-#define SROM8_FEM_TR_ISO_SHIFT         8
-#define SROM8_FEM_PDET_RANGE_MASK      0x00f8
-#define SROM8_FEM_PDET_RANGE_SHIFT     3
-#define SROM8_FEM_EXTPA_GAIN_MASK      0x0006
-#define SROM8_FEM_EXTPA_GAIN_SHIFT     1
-#define SROM8_FEM_TSSIPOS_MASK         0x0001
-#define SROM8_FEM_TSSIPOS_SHIFT                0
-
-#define SROM8_THERMAL          89
-
-/* Temp sense related entries */
-#define SROM8_MPWR_RAWTS               90
-#define SROM8_TS_SLP_OPT_CORRX 91
-/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable,
- * IQSWP: IQ CAL swap disable */
-#define SROM8_FOC_HWIQ_IQSWP   92
-
-/* Temperature delta for PHY calibration */
-#define SROM8_PHYCAL_TEMPDELTA 93
-
-/* Per-path offsets & fields */
-#define        SROM8_PATH0             96
-#define        SROM8_PATH1             112
-#define        SROM8_PATH2             128
-#define        SROM8_PATH3             144
-
-#define        SROM8_2G_ITT_MAXP       0
-#define        SROM8_2G_PA             1
-#define        SROM8_5G_ITT_MAXP       4
-#define        SROM8_5GLH_MAXP         5
-#define        SROM8_5G_PA             6
-#define        SROM8_5GL_PA            9
-#define        SROM8_5GH_PA            12
-
-/* All the miriad power offsets */
-#define        SROM8_2G_CCKPO          160
-
-#define        SROM8_2G_OFDMPO         161
-#define        SROM8_5G_OFDMPO         163
-#define        SROM8_5GL_OFDMPO        165
-#define        SROM8_5GH_OFDMPO        167
-
-#define        SROM8_2G_MCSPO          169
-#define        SROM8_5G_MCSPO          177
-#define        SROM8_5GL_MCSPO         185
-#define        SROM8_5GH_MCSPO         193
-
-#define        SROM8_CDDPO             201
-#define        SROM8_STBCPO            202
-#define        SROM8_BW40PO            203
-#define        SROM8_BWDUPPO           204
-
-/* SISO PA parameters are in the path0 spaces */
-#define        SROM8_SISO              96
-
-/* Legacy names for SISO PA paramters */
-#define        SROM8_W0_ITTMAXP        (SROM8_SISO + SROM8_2G_ITT_MAXP)
-#define        SROM8_W0_PAB0           (SROM8_SISO + SROM8_2G_PA)
-#define        SROM8_W0_PAB1           (SROM8_SISO + SROM8_2G_PA + 1)
-#define        SROM8_W0_PAB2           (SROM8_SISO + SROM8_2G_PA + 2)
-#define        SROM8_W1_ITTMAXP        (SROM8_SISO + SROM8_5G_ITT_MAXP)
-#define        SROM8_W1_MAXP_LCHC      (SROM8_SISO + SROM8_5GLH_MAXP)
-#define        SROM8_W1_PAB0           (SROM8_SISO + SROM8_5G_PA)
-#define        SROM8_W1_PAB1           (SROM8_SISO + SROM8_5G_PA + 1)
-#define        SROM8_W1_PAB2           (SROM8_SISO + SROM8_5G_PA + 2)
-#define        SROM8_W1_PAB0_LC        (SROM8_SISO + SROM8_5GL_PA)
-#define        SROM8_W1_PAB1_LC        (SROM8_SISO + SROM8_5GL_PA + 1)
-#define        SROM8_W1_PAB2_LC        (SROM8_SISO + SROM8_5GL_PA + 2)
-#define        SROM8_W1_PAB0_HC        (SROM8_SISO + SROM8_5GH_PA)
-#define        SROM8_W1_PAB1_HC        (SROM8_SISO + SROM8_5GH_PA + 1)
-#define        SROM8_W1_PAB2_HC        (SROM8_SISO + SROM8_5GH_PA + 2)
-
-/* SROM REV 9 */
-#define SROM9_2GPO_CCKBW20     160
-#define SROM9_2GPO_CCKBW20UL   161
-#define SROM9_2GPO_LOFDMBW20   162
-#define SROM9_2GPO_LOFDMBW20UL 164
-
-#define SROM9_5GLPO_LOFDMBW20  166
-#define SROM9_5GLPO_LOFDMBW20UL        168
-#define SROM9_5GMPO_LOFDMBW20  170
-#define SROM9_5GMPO_LOFDMBW20UL        172
-#define SROM9_5GHPO_LOFDMBW20  174
-#define SROM9_5GHPO_LOFDMBW20UL        176
-
-#define SROM9_2GPO_MCSBW20     178
-#define SROM9_2GPO_MCSBW20UL   180
-#define SROM9_2GPO_MCSBW40     182
-
-#define SROM9_5GLPO_MCSBW20    184
-#define SROM9_5GLPO_MCSBW20UL  186
-#define SROM9_5GLPO_MCSBW40    188
-#define SROM9_5GMPO_MCSBW20    190
-#define SROM9_5GMPO_MCSBW20UL  192
-#define SROM9_5GMPO_MCSBW40    194
-#define SROM9_5GHPO_MCSBW20    196
-#define SROM9_5GHPO_MCSBW20UL  198
-#define SROM9_5GHPO_MCSBW40    200
-
-#define SROM9_PO_MCS32         202
-#define SROM9_PO_LOFDM40DUP    203
-
-/* SROM flags (see sromvar_t) */
-
-/* value continues as described by the next entry */
-#define SRFL_MORE      1
-#define        SRFL_NOFFS      2       /* value bits can't be all one's */
-#define        SRFL_PRHEX      4       /* value is in hexdecimal format */
-#define        SRFL_PRSIGN     8       /* value is in signed decimal format */
-#define        SRFL_CCODE      0x10    /* value is in country code format */
-#define        SRFL_ETHADDR    0x20    /* value is an Ethernet address */
-#define SRFL_LEDDC     0x40    /* value is an LED duty cycle */
-/* do not generate a nvram param, entry is for mfgc */
-#define SRFL_NOVAR     0x80
-
-/* Max. nvram variable table size */
-#define        MAXSZ_NVRAM_VARS        4096
-
-/*
- * indicates type of value.
- */
-enum brcms_srom_var_type {
-       BRCMS_SROM_STRING,
-       BRCMS_SROM_SNUMBER,
-       BRCMS_SROM_UNUMBER
-};
-
-/*
- * storage type for srom variable.
- *
- * var_list: for linked list operations.
- * varid: identifier of the variable.
- * var_type: type of variable.
- * buf: variable value when var_type == BRCMS_SROM_STRING.
- * uval: unsigned variable value when var_type == BRCMS_SROM_UNUMBER.
- * sval: signed variable value when var_type == BRCMS_SROM_SNUMBER.
- */
-struct brcms_srom_list_head {
-       struct list_head var_list;
-       enum brcms_srom_id varid;
-       enum brcms_srom_var_type var_type;
-       union {
-               char buf[0];
-               u32 uval;
-               s32 sval;
-       };
-};
-
-struct brcms_sromvar {
-       enum brcms_srom_id varid;
-       u32 revmask;
-       u32 flags;
-       u16 off;
-       u16 mask;
-};
-
-struct brcms_varbuf {
-       char *base;             /* pointer to buffer base */
-       char *buf;              /* pointer to current position */
-       unsigned int size;      /* current (residual) size in bytes */
-};
-
-/*
- * Assumptions:
- * - Ethernet address spans across 3 consecutive words
- *
- * Table rules:
- * - Add multiple entries next to each other if a value spans across multiple
- *   words (even multiple fields in the same word) with each entry except the
- *   last having it's SRFL_MORE bit set.
- * - Ethernet address entry does not follow above rule and must not have
- *   SRFL_MORE bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
- * - The last entry's name field must be NULL to indicate the end of the table.
- *   Other entries must have non-NULL name.
- */
-static const struct brcms_sromvar pci_sromvars[] = {
-       {BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID,
-        0xffff},
-       {BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
-       {BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff},
-       {BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff},
-       {BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
-       {BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff},
-       {BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff},
-       {BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
-       {BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
-       {BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
-       {BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
-       {BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
-       {BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
-       {BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
-       {BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
-       {BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
-       {BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
-       {BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff},
-       {BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00},
-       {BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff},
-       {BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00},
-       {BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff},
-       {BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00},
-       {BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
-       {BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
-       {BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
-       {BRCMS_SROM_PA1LOB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
-       {BRCMS_SROM_PA1LOB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
-       {BRCMS_SROM_PA1LOB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
-       {BRCMS_SROM_PA1HIB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
-       {BRCMS_SROM_PA1HIB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
-       {BRCMS_SROM_PA1HIB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
-       {BRCMS_SROM_PA1ITSSIT, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00},
-       {BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
-       {BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
-       {BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
-       {BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
-       {BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
-       {BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
-       {BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
-       {BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
-       {BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
-       {BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
-       {BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
-       {BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
-       {BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00},
-       {BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
-       {BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
-       {BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
-       {BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
-       {BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
-        SROM4_TXCHAIN_MASK},
-       {BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
-        SROM4_RXCHAIN_MASK},
-       {BRCMS_SROM_ANTSWITCH, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
-        SROM4_SWITCH_MASK},
-       {BRCMS_SROM_TSSIPOS2G, 0xffffff00, 0, SROM8_FEM2G,
-        SROM8_FEM_TSSIPOS_MASK},
-       {BRCMS_SROM_EXTPAGAIN2G, 0xffffff00, 0, SROM8_FEM2G,
-        SROM8_FEM_EXTPA_GAIN_MASK},
-       {BRCMS_SROM_PDETRANGE2G, 0xffffff00, 0, SROM8_FEM2G,
-        SROM8_FEM_PDET_RANGE_MASK},
-       {BRCMS_SROM_TRISO2G, 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
-       {BRCMS_SROM_ANTSWCTL2G, 0xffffff00, 0, SROM8_FEM2G,
-        SROM8_FEM_ANTSWLUT_MASK},
-       {BRCMS_SROM_TSSIPOS5G, 0xffffff00, 0, SROM8_FEM5G,
-        SROM8_FEM_TSSIPOS_MASK},
-       {BRCMS_SROM_EXTPAGAIN5G, 0xffffff00, 0, SROM8_FEM5G,
-        SROM8_FEM_EXTPA_GAIN_MASK},
-       {BRCMS_SROM_PDETRANGE5G, 0xffffff00, 0, SROM8_FEM5G,
-        SROM8_FEM_PDET_RANGE_MASK},
-       {BRCMS_SROM_TRISO5G, 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
-       {BRCMS_SROM_ANTSWCTL5G, 0xffffff00, 0, SROM8_FEM5G,
-        SROM8_FEM_ANTSWLUT_MASK},
-       {BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00},
-       {BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
-
-       {BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
-       {BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
-       {BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC,
-        0xffff},
-       {BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
-        0x01ff},
-       {BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
-        0xfe00},
-       {BRCMS_SROM_TEMPSENSE_SLOPE, 0xffffff00, SRFL_PRHEX,
-        SROM8_TS_SLP_OPT_CORRX, 0x00ff},
-       {BRCMS_SROM_TEMPCORRX, 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
-        0xfc00},
-       {BRCMS_SROM_TEMPSENSE_OPTION, 0xffffff00, SRFL_PRHEX,
-        SROM8_TS_SLP_OPT_CORRX, 0x0300},
-       {BRCMS_SROM_FREQOFFSET_CORR, 0xffffff00, SRFL_PRHEX,
-        SROM8_FOC_HWIQ_IQSWP, 0x000f},
-       {BRCMS_SROM_IQCAL_SWP_DIS, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
-        0x0010},
-       {BRCMS_SROM_HW_IQCAL_EN, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
-        0x0020},
-       {BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA,
-        0x00ff},
-
-       {BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
-       {BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
-       {BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM8_5G_OFDMPO + 1, 0xffff},
-       {BRCMS_SROM_OFDM5GLPO, 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
-       {BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
-       {BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
-       {BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
-       {BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
-       {BRCMS_SROM_MCS2GPO3, 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff},
-       {BRCMS_SROM_MCS2GPO4, 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff},
-       {BRCMS_SROM_MCS2GPO5, 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff},
-       {BRCMS_SROM_MCS2GPO6, 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff},
-       {BRCMS_SROM_MCS2GPO7, 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff},
-       {BRCMS_SROM_MCS5GPO0, 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
-       {BRCMS_SROM_MCS5GPO1, 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff},
-       {BRCMS_SROM_MCS5GPO2, 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff},
-       {BRCMS_SROM_MCS5GPO3, 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff},
-       {BRCMS_SROM_MCS5GPO4, 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff},
-       {BRCMS_SROM_MCS5GPO5, 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff},
-       {BRCMS_SROM_MCS5GPO6, 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff},
-       {BRCMS_SROM_MCS5GPO7, 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff},
-       {BRCMS_SROM_MCS5GLPO0, 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
-       {BRCMS_SROM_MCS5GLPO1, 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff},
-       {BRCMS_SROM_MCS5GLPO2, 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff},
-       {BRCMS_SROM_MCS5GLPO3, 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff},
-       {BRCMS_SROM_MCS5GLPO4, 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff},
-       {BRCMS_SROM_MCS5GLPO5, 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff},
-       {BRCMS_SROM_MCS5GLPO6, 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff},
-       {BRCMS_SROM_MCS5GLPO7, 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff},
-       {BRCMS_SROM_MCS5GHPO0, 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
-       {BRCMS_SROM_MCS5GHPO1, 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff},
-       {BRCMS_SROM_MCS5GHPO2, 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff},
-       {BRCMS_SROM_MCS5GHPO3, 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff},
-       {BRCMS_SROM_MCS5GHPO4, 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff},
-       {BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
-       {BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
-       {BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
-       {BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff},
-       {BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff},
-       {BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff},
-       {BRCMS_SROM_BWDUPPO, 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
-
-       /* power per rate from sromrev 9 */
-       {BRCMS_SROM_CCKBW202GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff},
-       {BRCMS_SROM_CCKBW20UL2GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
-       {BRCMS_SROM_LEGOFDMBW202GPO, 0xfffffe00, SRFL_MORE,
-        SROM9_2GPO_LOFDMBW20, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff},
-       {BRCMS_SROM_LEGOFDMBW20UL2GPO, 0xfffffe00, SRFL_MORE,
-        SROM9_2GPO_LOFDMBW20UL, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff},
-       {BRCMS_SROM_LEGOFDMBW205GLPO, 0xfffffe00, SRFL_MORE,
-        SROM9_5GLPO_LOFDMBW20, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff},
-       {BRCMS_SROM_LEGOFDMBW20UL5GLPO, 0xfffffe00, SRFL_MORE,
-        SROM9_5GLPO_LOFDMBW20UL, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff},
-       {BRCMS_SROM_LEGOFDMBW205GMPO, 0xfffffe00, SRFL_MORE,
-        SROM9_5GMPO_LOFDMBW20, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff},
-       {BRCMS_SROM_LEGOFDMBW20UL5GMPO, 0xfffffe00, SRFL_MORE,
-        SROM9_5GMPO_LOFDMBW20UL, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff},
-       {BRCMS_SROM_LEGOFDMBW205GHPO, 0xfffffe00, SRFL_MORE,
-        SROM9_5GHPO_LOFDMBW20, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff},
-       {BRCMS_SROM_LEGOFDMBW20UL5GHPO, 0xfffffe00, SRFL_MORE,
-        SROM9_5GHPO_LOFDMBW20UL, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff},
-       {BRCMS_SROM_MCSBW202GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff},
-       {BRCMS_SROM_MCSBW20UL2GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff},
-       {BRCMS_SROM_MCSBW402GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff},
-       {BRCMS_SROM_MCSBW205GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff},
-       {BRCMS_SROM_MCSBW20UL5GLPO, 0xfffffe00, SRFL_MORE,
-        SROM9_5GLPO_MCSBW20UL, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff},
-       {BRCMS_SROM_MCSBW405GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff},
-       {BRCMS_SROM_MCSBW205GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff},
-       {BRCMS_SROM_MCSBW20UL5GMPO, 0xfffffe00, SRFL_MORE,
-        SROM9_5GMPO_MCSBW20UL, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff},
-       {BRCMS_SROM_MCSBW405GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff},
-       {BRCMS_SROM_MCSBW205GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff},
-       {BRCMS_SROM_MCSBW20UL5GHPO, 0xfffffe00, SRFL_MORE,
-        SROM9_5GHPO_MCSBW20UL, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff},
-       {BRCMS_SROM_MCSBW405GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff},
-       {BRCMS_SROM_MCS32PO, 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff},
-       {BRCMS_SROM_LEGOFDM40DUPPO, 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff},
-
-       {BRCMS_SROM_NULL, 0, 0, 0, 0}
-};
-
-static const struct brcms_sromvar perpath_pci_sromvars[] = {
-       {BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
-       {BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
-       {BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
-       {BRCMS_SROM_PA2GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
-       {BRCMS_SROM_PA2GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff},
-       {BRCMS_SROM_PA2GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff},
-       {BRCMS_SROM_MAXP5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff},
-       {BRCMS_SROM_MAXP5GHA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff},
-       {BRCMS_SROM_MAXP5GLA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00},
-       {BRCMS_SROM_PA5GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
-       {BRCMS_SROM_PA5GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff},
-       {BRCMS_SROM_PA5GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff},
-       {BRCMS_SROM_PA5GLW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
-       {BRCMS_SROM_PA5GLW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1,
-        0xffff},
-       {BRCMS_SROM_PA5GLW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2,
-        0xffff},
-       {BRCMS_SROM_PA5GHW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
-       {BRCMS_SROM_PA5GHW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1,
-        0xffff},
-       {BRCMS_SROM_PA5GHW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2,
-        0xffff},
-       {BRCMS_SROM_NULL, 0, 0, 0, 0}
-};
-
-/* crc table has the same contents for every device instance, so it can be
- * shared between devices. */
-static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE];
-
-static uint mask_shift(u16 mask)
-{
-       uint i;
-       for (i = 0; i < (sizeof(mask) << 3); i++) {
-               if (mask & (1 << i))
-                       return i;
-       }
-       return 0;
-}
-
-static uint mask_width(u16 mask)
-{
-       int i;
-       for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) {
-               if (mask & (1 << i))
-                       return (uint) (i - mask_shift(mask) + 1);
-       }
-       return 0;
-}
-
-static inline void le16_to_cpu_buf(u16 *buf, uint nwords)
-{
-       while (nwords--)
-               *(buf + nwords) = le16_to_cpu(*(__le16 *)(buf + nwords));
-}
-
-static inline void cpu_to_le16_buf(u16 *buf, uint nwords)
-{
-       while (nwords--)
-               *(__le16 *)(buf + nwords) = cpu_to_le16(*(buf + nwords));
-}
-
-/*
- * convert binary srom data into linked list of srom variable items.
- */
-static int
-_initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
-{
-       struct brcms_srom_list_head *entry;
-       enum brcms_srom_id id;
-       u16 w;
-       u32 val = 0;
-       const struct brcms_sromvar *srv;
-       uint width;
-       uint flags;
-       u32 sr = (1 << sromrev);
-       uint p;
-       uint pb =  SROM8_PATH0;
-       const uint psz = SROM8_PATH1 - SROM8_PATH0;
-
-       /* first store the srom revision */
-       entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL);
-       if (!entry)
-               return -ENOMEM;
-
-       entry->varid = BRCMS_SROM_REV;
-       entry->var_type = BRCMS_SROM_UNUMBER;
-       entry->uval = sromrev;
-       list_add(&entry->var_list, var_list);
-
-       for (srv = pci_sromvars; srv->varid != BRCMS_SROM_NULL; srv++) {
-               enum brcms_srom_var_type type;
-               u8 ea[ETH_ALEN];
-               u8 extra_space = 0;
-
-               if ((srv->revmask & sr) == 0)
-                       continue;
-
-               flags = srv->flags;
-               id = srv->varid;
-
-               /* This entry is for mfgc only. Don't generate param for it, */
-               if (flags & SRFL_NOVAR)
-                       continue;
-
-               if (flags & SRFL_ETHADDR) {
-                       /*
-                        * stored in string format XX:XX:XX:XX:XX:XX (17 chars)
-                        */
-                       ea[0] = (srom[srv->off] >> 8) & 0xff;
-                       ea[1] = srom[srv->off] & 0xff;
-                       ea[2] = (srom[srv->off + 1] >> 8) & 0xff;
-                       ea[3] = srom[srv->off + 1] & 0xff;
-                       ea[4] = (srom[srv->off + 2] >> 8) & 0xff;
-                       ea[5] = srom[srv->off + 2] & 0xff;
-                       /* 17 characters + string terminator - union size */
-                       extra_space = 18 - sizeof(s32);
-                       type = BRCMS_SROM_STRING;
-               } else {
-                       w = srom[srv->off];
-                       val = (w & srv->mask) >> mask_shift(srv->mask);
-                       width = mask_width(srv->mask);
-
-                       while (srv->flags & SRFL_MORE) {
-                               srv++;
-                               if (srv->off == 0)
-                                       continue;
-
-                               w = srom[srv->off];
-                               val +=
-                                   ((w & srv->mask) >> mask_shift(srv->
-                                                                  mask)) <<
-                                   width;
-                               width += mask_width(srv->mask);
-                       }
-
-                       if ((flags & SRFL_NOFFS)
-                           && ((int)val == (1 << width) - 1))
-                               continue;
-
-                       if (flags & SRFL_CCODE) {
-                               type = BRCMS_SROM_STRING;
-                       } else if (flags & SRFL_LEDDC) {
-                               /* LED Powersave duty cycle has to be scaled:
-                                *(oncount >> 24) (offcount >> 8)
-                                */
-                               u32 w32 = /* oncount */
-                                         (((val >> 8) & 0xff) << 24) |
-                                         /* offcount */
-                                         (((val & 0xff)) << 8);
-                               type = BRCMS_SROM_UNUMBER;
-                               val = w32;
-                       } else if ((flags & SRFL_PRSIGN)
-                                && (val & (1 << (width - 1)))) {
-                               type = BRCMS_SROM_SNUMBER;
-                               val |= ~0 << width;
-                       } else
-                               type = BRCMS_SROM_UNUMBER;
-               }
-
-               entry = kzalloc(sizeof(struct brcms_srom_list_head) +
-                               extra_space, GFP_KERNEL);
-               if (!entry)
-                       return -ENOMEM;
-               entry->varid = id;
-               entry->var_type = type;
-               if (flags & SRFL_ETHADDR) {
-                       snprintf(entry->buf, 18, "%pM", ea);
-               } else if (flags & SRFL_CCODE) {
-                       if (val == 0)
-                               entry->buf[0] = '\0';
-                       else
-                               snprintf(entry->buf, 3, "%c%c",
-                                        (val >> 8), (val & 0xff));
-               } else {
-                       entry->uval = val;
-               }
-
-               list_add(&entry->var_list, var_list);
-       }
-
-       for (p = 0; p < MAX_PATH_SROM; p++) {
-               for (srv = perpath_pci_sromvars;
-                    srv->varid != BRCMS_SROM_NULL; srv++) {
-                       if ((srv->revmask & sr) == 0)
-                               continue;
-
-                       if (srv->flags & SRFL_NOVAR)
-                               continue;
-
-                       w = srom[pb + srv->off];
-                       val = (w & srv->mask) >> mask_shift(srv->mask);
-                       width = mask_width(srv->mask);
-
-                       /* Cheating: no per-path var is more than
-                        * 1 word */
-                       if ((srv->flags & SRFL_NOFFS)
-                           && ((int)val == (1 << width) - 1))
-                               continue;
-
-                       entry =
-                           kzalloc(sizeof(struct brcms_srom_list_head),
-                                   GFP_KERNEL);
-                       if (!entry)
-                               return -ENOMEM;
-                       entry->varid = srv->varid+p;
-                       entry->var_type = BRCMS_SROM_UNUMBER;
-                       entry->uval = val;
-                       list_add(&entry->var_list, var_list);
-               }
-               pb += psz;
-       }
-       return 0;
-}
-
-/*
- * The crc check is done on a little-endian array, we need
- * to switch the bytes around before checking crc (and
- * then switch it back).
- */
-static int do_crc_check(u16 *buf, unsigned nwords)
-{
-       u8 crc;
-
-       cpu_to_le16_buf(buf, nwords);
-       crc = crc8(brcms_srom_crc8_table, (void *)buf, nwords << 1, CRC8_INIT_VALUE);
-       le16_to_cpu_buf(buf, nwords);
-
-       return crc == CRC8_GOOD_VALUE(brcms_srom_crc8_table);
-}
-
-/*
- * Read in and validate sprom.
- * Return 0 on success, nonzero on error.
- */
-static int
-sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
-{
-       int err = 0;
-       uint i;
-       struct bcma_device *core;
-       uint sprom_offset;
-
-       /* determine core to read */
-       if (ai_get_ccrev(sih) < 32) {
-               core = ai_findcore(sih, BCMA_CORE_80211, 0);
-               sprom_offset = PCI_BAR0_SPROM_OFFSET;
-       } else {
-               core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
-               sprom_offset = CHIPCREGOFFS(sromotp);
-       }
-
-       /* read the sprom */
-       for (i = 0; i < nwords; i++)
-               buf[i] = bcma_read16(core, sprom_offset+i*2);
-
-       if (buf[0] == 0xffff)
-               /*
-                * The hardware thinks that an srom that starts with
-                * 0xffff is blank, regardless of the rest of the
-                * content, so declare it bad.
-                */
-               return -ENODATA;
-
-       if (check_crc && !do_crc_check(buf, nwords))
-               err = -EIO;
-
-       return err;
-}
-
-static int otp_read_pci(struct si_pub *sih, u16 *buf, uint nwords)
-{
-       u8 *otp;
-       uint sz = OTP_SZ_MAX / 2;       /* size in words */
-       int err = 0;
-
-       otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC);
-       if (otp == NULL)
-               return -ENOMEM;
-
-       err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
-
-       sz = min_t(uint, sz, nwords);
-       memcpy(buf, otp, sz * 2);
-
-       kfree(otp);
-
-       /* Check CRC */
-       if (buf[0] == 0xffff)
-               /* The hardware thinks that an srom that starts with 0xffff
-                * is blank, regardless of the rest of the content, so declare
-                * it bad.
-                */
-               return -ENODATA;
-
-       /* fixup the endianness so crc8 will pass */
-       cpu_to_le16_buf(buf, sz);
-       if (crc8(brcms_srom_crc8_table, (u8 *) buf, sz * 2,
-                CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table))
-               err = -EIO;
-       else
-               /* now correct the endianness of the byte array */
-               le16_to_cpu_buf(buf, sz);
-
-       return err;
-}
-
-/*
- * Initialize nonvolatile variable table from sprom.
- * Return 0 on success, nonzero on error.
- */
-int srom_var_init(struct si_pub *sih)
-{
-       u16 *srom;
-       u8 sromrev = 0;
-       u32 sr;
-       int err = 0;
-
-       /*
-        * Apply CRC over SROM content regardless SROM is present or not.
-        */
-       srom = kmalloc(SROM_MAX, GFP_ATOMIC);
-       if (!srom)
-               return -ENOMEM;
-
-       crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY);
-       if (ai_is_sprom_available(sih)) {
-               err = sprom_read_pci(sih, srom, SROM4_WORDS, true);
-
-               if (err == 0)
-                       /* srom read and passed crc */
-                       /* top word of sprom contains version and crc8 */
-                       sromrev = srom[SROM4_CRCREV] & 0xff;
-       } else {
-               /* Use OTP if SPROM not available */
-               err = otp_read_pci(sih, srom, SROM4_WORDS);
-               if (err == 0)
-                       /* OTP only contain SROM rev8/rev9 for now */
-                       sromrev = srom[SROM4_CRCREV] & 0xff;
-       }
-
-       if (!err) {
-               struct si_info *sii = (struct si_info *)sih;
-
-               /* Bitmask for the sromrev */
-               sr = 1 << sromrev;
-
-               /*
-                * srom version check: Current valid versions: 8, 9
-                */
-               if ((sr & 0x300) == 0) {
-                       err = -EINVAL;
-                       goto errout;
-               }
-
-               INIT_LIST_HEAD(&sii->var_list);
-
-               /* parse SROM into name=value pairs. */
-               err = _initvars_srom_pci(sromrev, srom, &sii->var_list);
-               if (err)
-                       srom_free_vars(sih);
-       }
-
-errout:
-       kfree(srom);
-       return err;
-}
-
-void srom_free_vars(struct si_pub *sih)
-{
-       struct si_info *sii;
-       struct brcms_srom_list_head *entry, *next;
-
-       sii = (struct si_info *)sih;
-       list_for_each_entry_safe(entry, next, &sii->var_list, var_list) {
-               list_del(&entry->var_list);
-               kfree(entry);
-       }
-}
-
-/*
- * Search the name=value vars for a specific one and return its value.
- * Returns NULL if not found.
- */
-char *getvar(struct si_pub *sih, enum brcms_srom_id id)
-{
-       struct si_info *sii;
-       struct brcms_srom_list_head *entry;
-
-       sii = (struct si_info *)sih;
-
-       list_for_each_entry(entry, &sii->var_list, var_list)
-               if (entry->varid == id)
-                       return &entry->buf[0];
-
-       /* nothing found */
-       return NULL;
-}
-
-/*
- * Search the vars for a specific one and return its value as
- * an integer. Returns 0 if not found.-
- */
-int getintvar(struct si_pub *sih, enum brcms_srom_id id)
-{
-       struct si_info *sii;
-       struct brcms_srom_list_head *entry;
-       unsigned long res;
-
-       sii = (struct si_info *)sih;
-
-       list_for_each_entry(entry, &sii->var_list, var_list)
-               if (entry->varid == id) {
-                       if (entry->var_type == BRCMS_SROM_SNUMBER ||
-                           entry->var_type == BRCMS_SROM_UNUMBER)
-                               return (int)entry->sval;
-                       else if (!kstrtoul(&entry->buf[0], 0, &res))
-                               return (int)res;
-               }
-
-       return 0;
-}