Add new sprom revision 11 variables to the nvram -> sprom reader. Signed-off-by: Ian Kent <ra...@themaw.net> --- .../111-bcm53xx-add-sprom-rev-11-vars.patch | 426 ++++++++++++++++++++ .../111-bcm53xx-add-sprom-rev-11-vars.patch | 432 ++++++++++++++++++++ 2 files changed, 858 insertions(+) create mode 100644 target/linux/bcm53xx/patches-3.14/111-bcm53xx-add-sprom-rev-11-vars.patch create mode 100644 target/linux/bcm53xx/patches-3.18/111-bcm53xx-add-sprom-rev-11-vars.patch
diff --git a/target/linux/bcm53xx/patches-3.14/111-bcm53xx-add-sprom-rev-11-vars.patch b/target/linux/bcm53xx/patches-3.14/111-bcm53xx-add-sprom-rev-11-vars.patch new file mode 100644 index 0000000..463c8b9 --- /dev/null +++ b/target/linux/bcm53xx/patches-3.14/111-bcm53xx-add-sprom-rev-11-vars.patch @@ -0,0 +1,426 @@ +bcm53xx - add sprom rev 11 vars + +From: Ian Kent <ra...@themaw.net> + +Up date bcm47xx-sprom.c to read new sprom revision 11 variables. + +Signed-off-by: Ian Kent <ra...@themaw.net> +--- a/drivers/bcma/sprom.c ++++ b/drivers/bcma/sprom.c +@@ -165,7 +165,7 @@ static int bcma_sprom_valid(struct bcma_ + return err; + + revision = sprom[words - 1] & SSB_SPROM_REVISION_REV; +- if (revision != 8 && revision != 9 && revision != 10) { ++ if (revision < 8 || revision > 11) { + pr_err("Unsupported SPROM revision: %d\n", revision); + return -ENOENT; + } +--- a/drivers/misc/bcm47xx-sprom.c ++++ b/drivers/misc/bcm47xx-sprom.c +@@ -187,6 +187,30 @@ static void nvram_read_alpha2(const stru + memcpy(val, buf, 2); + } + ++static void nvram_read_string(const struct bcm47xx_sprom_fill *fill, ++ const char *name, char *val, unsigned int len) ++{ ++ char buf[121]; ++ int err; ++ ++ *val = '\0'; ++ ++ if (len > 120) ++ return; ++ ++ memset(buf, 0, 121); ++ err = get_nvram_var(fill, NULL, name, buf, sizeof(buf) - 1); ++ if (err < 0) ++ return; ++ if (buf[0] == '0') ++ return; ++ if (buf[120] != '\0') { ++ pr_warn("string is too long %s\n", buf); ++ return; ++ } ++ strcpy(val, buf); ++} ++ + static void bcm47xx_sprom_fill_r1234589(struct ssb_sprom *sprom, + const struct bcm47xx_sprom_fill *fill) + { +@@ -439,6 +463,63 @@ static void bcm47xx_sprom_fill_r9(struct + nvram_read_u8(fill, NULL, "sar5g", &sprom->sar5g, 0); + } + ++static void bcm47xx_sprom_fill_r11(struct ssb_sprom *sprom, ++ const struct bcm47xx_sprom_fill *fill) ++{ ++ nvram_read_u8(fill, NULL, "agbg0", &sprom->agbg0, 0); ++ nvram_read_u8(fill, NULL, "agbg1", &sprom->agbg1, 0); ++ nvram_read_u8(fill, NULL, "agbg2", &sprom->agbg2, 0); ++ nvram_read_u8(fill, NULL, "aga0", &sprom->aga0, 0); ++ nvram_read_u8(fill, NULL, "aga1", &sprom->aga1, 0); ++ nvram_read_u8(fill, NULL, "aga2", &sprom->aga2, 0); ++ nvram_read_u8(fill, NULL, "tssiposslope2g", &sprom->tssiposslope2g, 0); ++ nvram_read_u8(fill, NULL, "epagain2g", &sprom->epagain2g, 0); ++ nvram_read_u8(fill, NULL, "pdgain2g", &sprom->pdgain2g, 0); ++ nvram_read_u8(fill, NULL, "tworangetssi2g", &sprom->tworangetssi2g, 0); ++ nvram_read_u8(fill, NULL, "papdcap2g", &sprom->papdcap2g, 0); ++ nvram_read_u8(fill, NULL, "femctrl", &sprom->femctrl, 0); ++ nvram_read_u8(fill, NULL, "tssiposslope5g", &sprom->tssiposslope5g, 0); ++ nvram_read_u8(fill, NULL, "epagain5g", &sprom->epagain5g, 0); ++ nvram_read_u8(fill, NULL, "pdgain5g", &sprom->pdgain5g, 0); ++ nvram_read_u8(fill, NULL, "tworangetssi5g", &sprom->tworangetssi5g, 0); ++ nvram_read_u8(fill, NULL, "papdcap5g", &sprom->papdcap5g, 0); ++ nvram_read_u8(fill, NULL, "gainctrlsph", &sprom->gainctrlsph, 0); ++ nvram_read_u16(fill, NULL, "pdoffset40ma0", &sprom->pdoffset40ma0, 0); ++ nvram_read_u16(fill, NULL, "pdoffset40ma1", &sprom->pdoffset40ma1, 0); ++ nvram_read_u16(fill, NULL, "pdoffset40ma2", &sprom->pdoffset40ma2, 0); ++ nvram_read_u16(fill, NULL, "pdoffset80ma0", &sprom->pdoffset80ma0, 0); ++ nvram_read_u16(fill, NULL, "pdoffset80ma1", &sprom->pdoffset80ma1, 0); ++ nvram_read_u16(fill, NULL, "pdoffset80ma2", &sprom->pdoffset80ma2, 0); ++ nvram_read_u16(fill, NULL, "dot11agofdmhrbw202gpo", &sprom->dot11agofdmhrbw202gpo, 0); ++ nvram_read_u16(fill, NULL, "ofdmlrbw202gpo", &sprom->ofdmlrbw202gpo, 0); ++ nvram_read_u16(fill, NULL, "mcsbw805glpo", &sprom->mcsbw805glpo, 0); ++ nvram_read_u16(fill, NULL, "mcsbw1605glpo", &sprom->mcsbw1605glpo, 0); ++ nvram_read_u16(fill, NULL, "mcsbw805ghpo", &sprom->mcsbw805ghpo, 0); ++ nvram_read_u16(fill, NULL, "mcsbw1605ghpo", &sprom->mcsbw1605ghpo, 0); ++ nvram_read_u16(fill, NULL, "mcslr5glpo", &sprom->ofdmlrbw202gpo, 0); ++ nvram_read_u16(fill, NULL, "mcslr5gmpo", &sprom->mcslr5gmpo, 0); ++ nvram_read_u16(fill, NULL, "mcslr5ghpo", &sprom->mcslr5ghpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in40hrrpo", &sprom->sb20in40hrrpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in80and160hr5glpo", &sprom->sb20in80and160hr5glpo, 0); ++ nvram_read_u16(fill, NULL, "sb40and80hr5glpo", &sprom->sb40and80hr5glpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in80and160hr5gmpo", &sprom->sb20in80and160hr5gmpo, 0); ++ nvram_read_u16(fill, NULL, "sb40and80hr5gmpo", &sprom->sb40and80hr5gmpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in80and160hr5ghpo", &sprom->sb20in80and160hr5ghpo, 0); ++ nvram_read_u16(fill, NULL, "sb40and80hr5ghpo", &sprom->sb40and80hr5ghpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in40lrpo", &sprom->sb20in40lrpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in80and160lr5glpo", &sprom->sb20in80and160lr5glpo, 0); ++ nvram_read_u16(fill, NULL, "sb40and80lr5glpo", &sprom->sb40and80lr5glpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in40lrpo", &sprom->sb20in40lrpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in80and160lr5gmpo", &sprom->sb20in80and160lr5gmpo, 0); ++ nvram_read_u16(fill, NULL, "sb40and80lr5gmpo", &sprom->sb40and80lr5gmpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in80and160lr5ghpo", &sprom->sb20in80and160lr5ghpo, 0); ++ nvram_read_u16(fill, NULL, "sb40and80lr5ghpo", &sprom->sb40and80lr5ghpo, 0); ++ nvram_read_u16(fill, NULL, "dot11agduphrpo", &sprom->dot11agduphrpo, 0); ++ nvram_read_u16(fill, NULL, "dot11agduplrpo", &sprom->dot11agduplrpo, 0); ++ nvram_read_u16(fill, NULL, "rxgainerr2g", &sprom->rxgainerr2g, 0); ++ nvram_read_u16(fill, NULL, "rxgainerr5g", &sprom->rxgainerr5g, 0); ++} ++ + static void bcm47xx_sprom_fill_path_r4589(struct ssb_sprom *sprom, + const struct bcm47xx_sprom_fill *fill) + { +@@ -487,6 +568,172 @@ static void bcm47xx_sprom_fill_path_r45( + } + } + ++static void bcm47xx_sprom_fill_path_r11(struct ssb_sprom *sprom, ++ const struct bcm47xx_sprom_fill *fill) ++{ ++ char postfix[2]; ++ unsigned int entry_count; ++ char tmp[40], val[100]; ++ int i, j; ++ ++ for (i = 0; i < ARRAY_SIZE(sprom->core_rxgains_info); i++) { ++ struct ssb_sprom_core_pwr_info *pwr_info; ++ struct ssb_sprom_core_rxgains_info *gains_info; ++ ++ gains_info = &sprom->core_rxgains_info[i]; ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5gmelnagaina); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5gmelnagaina"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5gmelnagaina[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5gmtrisoa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5gmtrisoa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5gmtrisoa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5gmtrelnabypa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5gmtrelnabypa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5gmtrelnabypa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5ghelnagaina); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5ghelnagaina"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5ghelnagaina[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5ghtrisoa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5ghtrisoa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5ghtrisoa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5ghtrelnabypa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5ghtrelnabypa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5ghtrelnabypa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains2gelnagaina); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains2gelnagaina"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains2gelnagaina[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains2gtrisoa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains2gtrisoa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains2gtrisoa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains2gtrelnabypa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains2gtrelnabypa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains2gtrelnabypa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5gelnagaina); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5gelnagaina"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5gelnagaina[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5gtrisoa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5gtrisoa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5gtrisoa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5gtrelnabypa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5gtrelnabypa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5gtrelnabypa[j], 0); ++ } ++ ++ pwr_info = &sprom->core_pwr_info[i]; ++ ++ entry_count = ARRAY_SIZE(pwr_info->pa2ga); ++ for (j = 0; j < entry_count; j++) { ++ char *str = &val[0]; ++ char *tok; ++ int k; ++ ++ snprintf(tmp, sizeof(tmp), "%i:%s%i", i, "pa2ga", j); ++ nvram_read_string(fill, tmp, val, 99); ++ ++ if (!*val) ++ continue; ++ ++ k = 0; ++ while ((tok = strsep(&str, ","))) { ++ unsigned long res; ++ int err; ++ ++ err = kstrtoul(tok, 0, &res); ++ if (err) ++ continue; ++ pwr_info->pa5ga[j][k] = (u16) res; ++ if (++k > 11) ++ break; ++ } ++ } ++ ++ entry_count = ARRAY_SIZE(pwr_info->pa5ga); ++ for (j = 0; j < entry_count; j++) { ++ char *str = &val[0]; ++ char *tok; ++ int k; ++ ++ snprintf(tmp, sizeof(tmp), "%i:%s%i", i, "pa5ga", j); ++ nvram_read_string(fill, tmp, val, 99); ++ ++ if (!*val) ++ continue; ++ ++ k = 0; ++ while ((tok = strsep(&str, ","))) { ++ unsigned long res; ++ int err; ++ ++ err = kstrtoul(tok, 0, &res); ++ if (err) ++ continue; ++ pwr_info->pa5ga[j][k] = (u16) res; ++ if (++k > 11) ++ break; ++ } ++ } ++ } ++} ++ + static bool bcm47xx_is_valid_mac(u8 *mac) + { + return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c); +@@ -568,6 +815,9 @@ static void bcm47xx_sprom_fill_board_dat + &sprom->boardflags_hi); + nvram_read_u32_2(fill, "boardflags2", &sprom->boardflags2_lo, + &sprom->boardflags2_hi); ++ if (sprom->revision > 10) ++ nvram_read_u32_2(fill, "boardflags3", &sprom->boardflags3_lo, ++ &sprom->boardflags3_hi); + } + + static void bcm47xx_sprom_fill(struct ssb_sprom *sprom, +@@ -625,6 +875,18 @@ static void bcm47xx_sprom_fill(struct ss + bcm47xx_sprom_fill_r9(sprom, fill); + bcm47xx_sprom_fill_path_r4589(sprom, fill); + break; ++ ++ case 11: ++ bcm47xx_sprom_fill_r1234589(sprom, fill); ++ bcm47xx_sprom_fill_r4589(sprom, fill); ++ bcm47xx_sprom_fill_r89(sprom, fill); ++ bcm47xx_sprom_fill_r9(sprom, fill); ++ bcm47xx_sprom_fill_r11(sprom, fill); ++ /* For maxp2ga and maxp5ga only */ ++ bcm47xx_sprom_fill_path_r4589(sprom, fill); ++ bcm47xx_sprom_fill_path_r11(sprom, fill); ++ break; ++ + default: + pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n", + sprom->revision); +--- a/include/linux/ssb/ssb.h ++++ b/include/linux/ssb/ssb.h +@@ -13,6 +13,8 @@ + + #include <linux/ssb/ssb_regs.h> + ++#define RXGAINS_PATH_COUNT 3 ++#define RXGAINS_ENTRY_COUNT 3 + + struct pcmcia_device; + struct ssb_bus; +@@ -22,6 +24,24 @@ struct ssb_sprom_core_pwr_info { + u8 itssi_2g, itssi_5g; + u8 maxpwr_2g, maxpwr_5gl, maxpwr_5g, maxpwr_5gh; + u16 pa_2g[4], pa_5gl[4], pa_5g[4], pa_5gh[4]; ++ /* rev 11 */ ++ u16 pa2ga[3][12], pa5ga[3][12]; ++}; ++ ++/* rev 11 rxnoise */ ++struct ssb_sprom_core_rxgains_info { ++ u8 rxgains5gmelnagaina[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5gmtrisoa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5gmtrelnabypa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5ghelnagaina[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5ghtrisoa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5ghtrelnabypa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains2gelnagaina[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains2gtrisoa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains2gtrelnabypa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5gelnagaina[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5gtrisoa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5gtrelnabypa[RXGAINS_ENTRY_COUNT]; + }; + + struct ssb_sprom { +@@ -93,6 +113,9 @@ struct ssb_sprom { + u16 boardflags2_lo; /* Board flags (bits 32-47) */ + u16 boardflags2_hi; /* Board flags (bits 48-63) */ + /* TODO store board flags in a single u64 */ ++ /* spromrev 11 */ ++ u16 boardflags3_lo; /* Board flags (bits 64-79) */ ++ u16 boardflags3_hi; /* Board flags (bits 80-95) */ + + struct ssb_sprom_core_pwr_info core_pwr_info[4]; + +@@ -185,6 +208,62 @@ struct ssb_sprom { + u16 legofdm40duppo; + u8 sar2g; + u8 sar5g; ++ ++ /* spromrev 11 */ ++ u8 agbg0; ++ u8 agbg1; ++ u8 agbg2; ++ u8 aga0; ++ u8 aga1; ++ u8 aga2; ++ u8 tssiposslope2g; ++ u8 epagain2g; ++ u8 pdgain2g; ++ u8 tworangetssi2g; ++ u8 papdcap2g; ++ u8 femctrl; ++ u8 tssiposslope5g; ++ u8 epagain5g; ++ u8 pdgain5g; ++ u8 tworangetssi5g; ++ u8 papdcap5g; ++ u8 gainctrlsph; ++ u16 pdoffset40ma0; ++ u16 pdoffset40ma1; ++ u16 pdoffset40ma2; ++ u16 pdoffset80ma0; ++ u16 pdoffset80ma1; ++ u16 pdoffset80ma2; ++ u16 dot11agofdmhrbw202gpo; ++ u16 ofdmlrbw202gpo; ++ u16 mcsbw805glpo; ++ u16 mcsbw1605glpo; ++ u16 mcsbw805ghpo; ++ u16 mcsbw1605ghpo; ++ u16 mcslr5glpo; ++ u16 mcslr5gmpo; ++ u16 mcslr5ghpo; ++ u16 sb20in40hrrpo; ++ u16 sb20in80and160hr5glpo; ++ u16 sb40and80hr5glpo; ++ u16 sb20in80and160hr5gmpo; ++ u16 sb40and80hr5gmpo; ++ u16 sb20in80and160hr5ghpo; ++ u16 sb40and80hr5ghpo; ++ u16 sb20in40lrpo; ++ u16 sb20in80and160lr5glpo; ++ u16 sb40and80lr5glpo; ++ u16 sb20in80and160lr5gmpo; ++ u16 sb40and80lr5gmpo; ++ u16 sb20in80and160lr5ghpo; ++ u16 sb40and80lr5ghpo; ++ u16 dot11agduphrpo; ++ u16 dot11agduplrpo; ++ u16 rxgainerr2g; ++ u16 rxgainerr5g; ++ ++ struct ssb_sprom_core_rxgains_info ++ core_rxgains_info[RXGAINS_PATH_COUNT]; + }; + + /* Information about the PCB the circuitry is soldered on. */ diff --git a/target/linux/bcm53xx/patches-3.18/111-bcm53xx-add-sprom-rev-11-vars.patch b/target/linux/bcm53xx/patches-3.18/111-bcm53xx-add-sprom-rev-11-vars.patch new file mode 100644 index 0000000..78590b5 --- /dev/null +++ b/target/linux/bcm53xx/patches-3.18/111-bcm53xx-add-sprom-rev-11-vars.patch @@ -0,0 +1,432 @@ +bcm53xx - add sprom rev 11 vars + +From: Ian Kent <ra...@themaw.net> + +Up date bcm47xx-sprom.c to read new sprom revision 11 variables. + +Signed-off-by: Ian Kent <ra...@themaw.net> +--- + drivers/bcma/sprom.c | 2 + + drivers/misc/bcm47xx-sprom.c | 72 ++++++++++++++++++++++++++++++++++++++++++ + include/linux/ssb/ssb.h | 56 +++++++++++++++++++++++++++++++++ + 3 files changed, 129 insertions(+), 1 deletion(-) + +--- a/drivers/bcma/sprom.c ++++ b/drivers/bcma/sprom.c +@@ -165,7 +165,7 @@ static int bcma_sprom_valid(struct bcma_ + return err; + + revision = sprom[words - 1] & SSB_SPROM_REVISION_REV; +- if (revision != 8 && revision != 9 && revision != 10) { ++ if (revision < 8 || revision > 11) { + pr_err("Unsupported SPROM revision: %d\n", revision); + return -ENOENT; + } +--- a/drivers/misc/bcm47xx-sprom.c ++++ b/drivers/misc/bcm47xx-sprom.c +@@ -187,6 +187,30 @@ static void nvram_read_alpha2(const stru + memcpy(val, buf, 2); + } + ++static void nvram_read_string(const struct bcm47xx_sprom_fill *fill, ++ const char *name, char *val, unsigned int len) ++{ ++ char buf[121]; ++ int err; ++ ++ *val = '\0'; ++ ++ if (len > 120) ++ return; ++ ++ memset(buf, 0, 121); ++ err = get_nvram_var(fill, NULL, name, buf, sizeof(buf) - 1); ++ if (err < 0) ++ return; ++ if (buf[0] == '0') ++ return; ++ if (buf[120] != '\0') { ++ pr_warn("string is too long %s\n", buf); ++ return; ++ } ++ strcpy(val, buf); ++} ++ + static void bcm47xx_sprom_fill_r1234589(struct ssb_sprom *sprom, + const struct bcm47xx_sprom_fill *fill) + { +@@ -439,6 +463,63 @@ static void bcm47xx_sprom_fill_r9(struct + nvram_read_u8(fill, NULL, "sar5g", &sprom->sar5g, 0); + } + ++static void bcm47xx_sprom_fill_r11(struct ssb_sprom *sprom, ++ const struct bcm47xx_sprom_fill *fill) ++{ ++ nvram_read_u8(fill, NULL, "agbg0", &sprom->agbg0, 0); ++ nvram_read_u8(fill, NULL, "agbg1", &sprom->agbg1, 0); ++ nvram_read_u8(fill, NULL, "agbg2", &sprom->agbg2, 0); ++ nvram_read_u8(fill, NULL, "aga0", &sprom->aga0, 0); ++ nvram_read_u8(fill, NULL, "aga1", &sprom->aga1, 0); ++ nvram_read_u8(fill, NULL, "aga2", &sprom->aga2, 0); ++ nvram_read_u8(fill, NULL, "tssiposslope2g", &sprom->tssiposslope2g, 0); ++ nvram_read_u8(fill, NULL, "epagain2g", &sprom->epagain2g, 0); ++ nvram_read_u8(fill, NULL, "pdgain2g", &sprom->pdgain2g, 0); ++ nvram_read_u8(fill, NULL, "tworangetssi2g", &sprom->tworangetssi2g, 0); ++ nvram_read_u8(fill, NULL, "papdcap2g", &sprom->papdcap2g, 0); ++ nvram_read_u8(fill, NULL, "femctrl", &sprom->femctrl, 0); ++ nvram_read_u8(fill, NULL, "tssiposslope5g", &sprom->tssiposslope5g, 0); ++ nvram_read_u8(fill, NULL, "epagain5g", &sprom->epagain5g, 0); ++ nvram_read_u8(fill, NULL, "pdgain5g", &sprom->pdgain5g, 0); ++ nvram_read_u8(fill, NULL, "tworangetssi5g", &sprom->tworangetssi5g, 0); ++ nvram_read_u8(fill, NULL, "papdcap5g", &sprom->papdcap5g, 0); ++ nvram_read_u8(fill, NULL, "gainctrlsph", &sprom->gainctrlsph, 0); ++ nvram_read_u16(fill, NULL, "pdoffset40ma0", &sprom->pdoffset40ma0, 0); ++ nvram_read_u16(fill, NULL, "pdoffset40ma1", &sprom->pdoffset40ma1, 0); ++ nvram_read_u16(fill, NULL, "pdoffset40ma2", &sprom->pdoffset40ma2, 0); ++ nvram_read_u16(fill, NULL, "pdoffset80ma0", &sprom->pdoffset80ma0, 0); ++ nvram_read_u16(fill, NULL, "pdoffset80ma1", &sprom->pdoffset80ma1, 0); ++ nvram_read_u16(fill, NULL, "pdoffset80ma2", &sprom->pdoffset80ma2, 0); ++ nvram_read_u16(fill, NULL, "dot11agofdmhrbw202gpo", &sprom->dot11agofdmhrbw202gpo, 0); ++ nvram_read_u16(fill, NULL, "ofdmlrbw202gpo", &sprom->ofdmlrbw202gpo, 0); ++ nvram_read_u16(fill, NULL, "mcsbw805glpo", &sprom->mcsbw805glpo, 0); ++ nvram_read_u16(fill, NULL, "mcsbw1605glpo", &sprom->mcsbw1605glpo, 0); ++ nvram_read_u16(fill, NULL, "mcsbw805ghpo", &sprom->mcsbw805ghpo, 0); ++ nvram_read_u16(fill, NULL, "mcsbw1605ghpo", &sprom->mcsbw1605ghpo, 0); ++ nvram_read_u16(fill, NULL, "mcslr5glpo", &sprom->ofdmlrbw202gpo, 0); ++ nvram_read_u16(fill, NULL, "mcslr5gmpo", &sprom->mcslr5gmpo, 0); ++ nvram_read_u16(fill, NULL, "mcslr5ghpo", &sprom->mcslr5ghpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in40hrrpo", &sprom->sb20in40hrrpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in80and160hr5glpo", &sprom->sb20in80and160hr5glpo, 0); ++ nvram_read_u16(fill, NULL, "sb40and80hr5glpo", &sprom->sb40and80hr5glpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in80and160hr5gmpo", &sprom->sb20in80and160hr5gmpo, 0); ++ nvram_read_u16(fill, NULL, "sb40and80hr5gmpo", &sprom->sb40and80hr5gmpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in80and160hr5ghpo", &sprom->sb20in80and160hr5ghpo, 0); ++ nvram_read_u16(fill, NULL, "sb40and80hr5ghpo", &sprom->sb40and80hr5ghpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in40lrpo", &sprom->sb20in40lrpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in80and160lr5glpo", &sprom->sb20in80and160lr5glpo, 0); ++ nvram_read_u16(fill, NULL, "sb40and80lr5glpo", &sprom->sb40and80lr5glpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in40lrpo", &sprom->sb20in40lrpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in80and160lr5gmpo", &sprom->sb20in80and160lr5gmpo, 0); ++ nvram_read_u16(fill, NULL, "sb40and80lr5gmpo", &sprom->sb40and80lr5gmpo, 0); ++ nvram_read_u16(fill, NULL, "sb20in80and160lr5ghpo", &sprom->sb20in80and160lr5ghpo, 0); ++ nvram_read_u16(fill, NULL, "sb40and80lr5ghpo", &sprom->sb40and80lr5ghpo, 0); ++ nvram_read_u16(fill, NULL, "dot11agduphrpo", &sprom->dot11agduphrpo, 0); ++ nvram_read_u16(fill, NULL, "dot11agduplrpo", &sprom->dot11agduplrpo, 0); ++ nvram_read_u16(fill, NULL, "rxgainerr2g", &sprom->rxgainerr2g, 0); ++ nvram_read_u16(fill, NULL, "rxgainerr5g", &sprom->rxgainerr5g, 0); ++} ++ + static void bcm47xx_sprom_fill_path_r4589(struct ssb_sprom *sprom, + const struct bcm47xx_sprom_fill *fill) + { +@@ -487,6 +568,172 @@ static void bcm47xx_sprom_fill_path_r45( + } + } + ++static void bcm47xx_sprom_fill_path_r11(struct ssb_sprom *sprom, ++ const struct bcm47xx_sprom_fill *fill) ++{ ++ char postfix[2]; ++ unsigned int entry_count; ++ char tmp[40], val[100]; ++ int i, j; ++ ++ for (i = 0; i < ARRAY_SIZE(sprom->core_rxgains_info); i++) { ++ struct ssb_sprom_core_pwr_info *pwr_info; ++ struct ssb_sprom_core_rxgains_info *gains_info; ++ ++ gains_info = &sprom->core_rxgains_info[i]; ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5gmelnagaina); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5gmelnagaina"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5gmelnagaina[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5gmtrisoa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5gmtrisoa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5gmtrisoa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5gmtrelnabypa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5gmtrelnabypa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5gmtrelnabypa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5ghelnagaina); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5ghelnagaina"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5ghelnagaina[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5ghtrisoa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5ghtrisoa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5ghtrisoa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5ghtrelnabypa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5ghtrelnabypa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5ghtrelnabypa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains2gelnagaina); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains2gelnagaina"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains2gelnagaina[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains2gtrisoa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains2gtrisoa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains2gtrisoa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains2gtrelnabypa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains2gtrelnabypa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains2gtrelnabypa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5gelnagaina); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5gelnagaina"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5gelnagaina[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5gtrisoa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5gtrisoa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5gtrisoa[j], 0); ++ } ++ ++ entry_count = ARRAY_SIZE(gains_info->rxgains5gtrelnabypa); ++ for (j = 0; j < entry_count; j++) { ++ snprintf(postfix, sizeof(postfix), "%i", j); ++ snprintf(tmp, sizeof(tmp), "%i:%s", i, "rxgains5gtrelnabypa"); ++ nvram_read_u8(fill, postfix, tmp, ++ &gains_info->rxgains5gtrelnabypa[j], 0); ++ } ++ ++ pwr_info = &sprom->core_pwr_info[i]; ++ ++ entry_count = ARRAY_SIZE(pwr_info->pa2ga); ++ for (j = 0; j < entry_count; j++) { ++ char *str = &val[0]; ++ char *tok; ++ int k; ++ ++ snprintf(tmp, sizeof(tmp), "%i:%s%i", i, "pa2ga", j); ++ nvram_read_string(fill, tmp, val, 99); ++ ++ if (!*val) ++ continue; ++ ++ k = 0; ++ while ((tok = strsep(&str, ","))) { ++ unsigned long res; ++ int err; ++ ++ err = kstrtoul(tok, 0, &res); ++ if (err) ++ continue; ++ pwr_info->pa5ga[j][k] = (u16) res; ++ if (++k > 11) ++ break; ++ } ++ } ++ ++ entry_count = ARRAY_SIZE(pwr_info->pa5ga); ++ for (j = 0; j < entry_count; j++) { ++ char *str = &val[0]; ++ char *tok; ++ int k; ++ ++ snprintf(tmp, sizeof(tmp), "%i:%s%i", i, "pa5ga", j); ++ nvram_read_string(fill, tmp, val, 99); ++ ++ if (!*val) ++ continue; ++ ++ k = 0; ++ while ((tok = strsep(&str, ","))) { ++ unsigned long res; ++ int err; ++ ++ err = kstrtoul(tok, 0, &res); ++ if (err) ++ continue; ++ pwr_info->pa5ga[j][k] = (u16) res; ++ if (++k > 11) ++ break; ++ } ++ } ++ } ++} ++ + static bool bcm47xx_is_valid_mac(u8 *mac) + { + return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c); +@@ -568,6 +815,9 @@ static void bcm47xx_sprom_fill_board_dat + &sprom->boardflags_hi); + nvram_read_u32_2(fill, "boardflags2", &sprom->boardflags2_lo, + &sprom->boardflags2_hi); ++ if (sprom->revision > 10) ++ nvram_read_u32_2(fill, "boardflags3", &sprom->boardflags3_lo, ++ &sprom->boardflags3_hi); + } + + static void bcm47xx_sprom_fill(struct ssb_sprom *sprom, +@@ -625,6 +875,18 @@ static void bcm47xx_sprom_fill(struct ss + bcm47xx_sprom_fill_r9(sprom, fill); + bcm47xx_sprom_fill_path_r4589(sprom, fill); + break; ++ ++ case 11: ++ bcm47xx_sprom_fill_r1234589(sprom, fill); ++ bcm47xx_sprom_fill_r4589(sprom, fill); ++ bcm47xx_sprom_fill_r89(sprom, fill); ++ bcm47xx_sprom_fill_r9(sprom, fill); ++ bcm47xx_sprom_fill_r11(sprom, fill); ++ /* For maxp2ga and maxp5ga only */ ++ bcm47xx_sprom_fill_path_r4589(sprom, fill); ++ bcm47xx_sprom_fill_path_r11(sprom, fill); ++ break; ++ + default: + pr_warn("Unsupported SPROM revision %d detected. Will extract v1\n", + sprom->revision); +--- a/include/linux/ssb/ssb.h ++++ b/include/linux/ssb/ssb.h +@@ -13,6 +13,8 @@ + + #include <linux/ssb/ssb_regs.h> + ++#define RXGAINS_PATH_COUNT 3 ++#define RXGAINS_ENTRY_COUNT 3 + + struct pcmcia_device; + struct ssb_bus; +@@ -22,6 +24,24 @@ struct ssb_sprom_core_pwr_info { + u8 itssi_2g, itssi_5g; + u8 maxpwr_2g, maxpwr_5gl, maxpwr_5g, maxpwr_5gh; + u16 pa_2g[4], pa_5gl[4], pa_5g[4], pa_5gh[4]; ++ /* rev 11 */ ++ u16 pa2ga[3][12], pa5ga[3][12]; ++}; ++ ++/* rev 11 rxnoise */ ++struct ssb_sprom_core_rxgains_info { ++ u8 rxgains5gmelnagaina[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5gmtrisoa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5gmtrelnabypa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5ghelnagaina[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5ghtrisoa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5ghtrelnabypa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains2gelnagaina[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains2gtrisoa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains2gtrelnabypa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5gelnagaina[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5gtrisoa[RXGAINS_ENTRY_COUNT]; ++ u8 rxgains5gtrelnabypa[RXGAINS_ENTRY_COUNT]; + }; + + struct ssb_sprom { +@@ -93,6 +113,9 @@ struct ssb_sprom { + u16 boardflags2_lo; /* Board flags (bits 32-47) */ + u16 boardflags2_hi; /* Board flags (bits 48-63) */ + /* TODO store board flags in a single u64 */ ++ /* spromrev 11 */ ++ u16 boardflags3_lo; /* Board flags (bits 64-79) */ ++ u16 boardflags3_hi; /* Board flags (bits 80-95) */ + + struct ssb_sprom_core_pwr_info core_pwr_info[4]; + +@@ -185,6 +208,62 @@ struct ssb_sprom { + u16 legofdm40duppo; + u8 sar2g; + u8 sar5g; ++ ++ /* spromrev 11 */ ++ u8 agbg0; ++ u8 agbg1; ++ u8 agbg2; ++ u8 aga0; ++ u8 aga1; ++ u8 aga2; ++ u8 tssiposslope2g; ++ u8 epagain2g; ++ u8 pdgain2g; ++ u8 tworangetssi2g; ++ u8 papdcap2g; ++ u8 femctrl; ++ u8 tssiposslope5g; ++ u8 epagain5g; ++ u8 pdgain5g; ++ u8 tworangetssi5g; ++ u8 papdcap5g; ++ u8 gainctrlsph; ++ u16 pdoffset40ma0; ++ u16 pdoffset40ma1; ++ u16 pdoffset40ma2; ++ u16 pdoffset80ma0; ++ u16 pdoffset80ma1; ++ u16 pdoffset80ma2; ++ u16 dot11agofdmhrbw202gpo; ++ u16 ofdmlrbw202gpo; ++ u16 mcsbw805glpo; ++ u16 mcsbw1605glpo; ++ u16 mcsbw805ghpo; ++ u16 mcsbw1605ghpo; ++ u16 mcslr5glpo; ++ u16 mcslr5gmpo; ++ u16 mcslr5ghpo; ++ u16 sb20in40hrrpo; ++ u16 sb20in80and160hr5glpo; ++ u16 sb40and80hr5glpo; ++ u16 sb20in80and160hr5gmpo; ++ u16 sb40and80hr5gmpo; ++ u16 sb20in80and160hr5ghpo; ++ u16 sb40and80hr5ghpo; ++ u16 sb20in40lrpo; ++ u16 sb20in80and160lr5glpo; ++ u16 sb40and80lr5glpo; ++ u16 sb20in80and160lr5gmpo; ++ u16 sb40and80lr5gmpo; ++ u16 sb20in80and160lr5ghpo; ++ u16 sb40and80lr5ghpo; ++ u16 dot11agduphrpo; ++ u16 dot11agduplrpo; ++ u16 rxgainerr2g; ++ u16 rxgainerr5g; ++ ++ struct ssb_sprom_core_rxgains_info ++ core_rxgains_info[RXGAINS_PATH_COUNT]; + }; + + /* Information about the PCB the circuitry is soldered on. */ _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel