From ac82fab44f6b981e3f6b53784e2f23838f4908e1 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 9 Nov 2007 16:54:45 -0600 Subject: ssb: Add new SPROM structure while keeping the old The SPROM's for various devices utilizing the Sonics Silicon Backplane come with various revisions. The Revision 2 SPROM inherited the data layout of 1, and Revision 3 inherited the layout of 2. The first instance of Revision 4 has now been found in a BCM4328 wireless LAN card. This device does not inherit any layout from previous versions. Although it was possible to create a data structure that kept all the old layouts, we decided to start fresh, keep only those SPROM variables that are used by the drivers that utilize ssb, and to do the conversion in such a manner that neither compilation or execution will be affected if a bisection lands in the middle of these changes, while keeping the patches as small as possible. In this patch, the sprom structures are changed while maintaining the old ones. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- include/linux/ssb/ssb.h | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'include/linux/ssb/ssb.h') diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 2b5c312c496..cdd8a2fd4a6 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -78,13 +78,34 @@ struct ssb_sprom_r3 { u32 ofdmgpo; /* G-PHY OFDM Power Offset */ }; -struct ssb_sprom_r4 { - /* TODO */ -}; - struct ssb_sprom { u8 revision; - u8 crc; + u8 temp_fill[2 * sizeof(struct ssb_sprom_r1)]; + u8 il0mac[6]; /* MAC address for 802.11b/g */ + u8 et0mac[6]; /* MAC address for Ethernet */ + u8 et1mac[6]; /* MAC address for 802.11a */ + u8 et0phyaddr; /* MII address for enet0 */ + u8 et1phyaddr; /* MII address for enet1 */ + u8 country_code; /* Country Code */ + u16 pa0b0; + u16 pa0b1; + u16 pa0b2; + u16 pa1b0; + u16 pa1b1; + u16 pa1b2; + u8 gpio0; /* GPIO pin 0 */ + u8 gpio1; /* GPIO pin 1 */ + u8 gpio2; /* GPIO pin 2 */ + u8 gpio3; /* GPIO pin 3 */ + u16 maxpwr_a; /* A-PHY Amplifier Max Power (in dBm Q5.2) */ + u16 maxpwr_bg; /* B/G-PHY Amplifier Max Power (in dBm Q5.2) */ + u8 itssi_a; /* Idle TSSI Target for A-PHY */ + u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */ + u16 boardflags_lo; /* Boardflags (low 16 bits) */ + u8 antenna_gain_a; /* A-PHY Antenna gain (in dBm Q5.2) */ + u8 antenna_gain_bg; /* B/G-PHY Antenna gain (in dBm Q5.2) */ + + /* TODO - add any parameters needed from rev 2, 3, or 4 SPROMs */ /* The valid r# fields are selected by the "revision". * Revision 3 and lower inherit from lower revisions. */ @@ -94,7 +115,6 @@ struct ssb_sprom { struct ssb_sprom_r2 r2; struct ssb_sprom_r3 r3; }; - struct ssb_sprom_r4 r4; }; }; -- cgit v1.2.3-70-g09d2 From c272ef4403c271799a7f09a4ab7a236c86643843 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 9 Nov 2007 16:56:25 -0600 Subject: ssb: Convert to use of the new SPROM structure In disagreement with the SPROM specs, revision 3 devices appear to have moved the MAC address. Change ssb to handle the revision 4 SPROM, which is a different size. This change in size is handled by adding a new variable to the ssb_sprom struct and using it whenever possible. For those routines that do not have access to this structure, a 'u16 size' argument is added. The new PCI_ID for the BCM4328 is also added. Testing of the Revision 4 SPROM, which is used on the BCM4328, was done by Michael Gerdau . Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/ssb/b43_pci_bridge.c | 1 + drivers/ssb/main.c | 10 +- drivers/ssb/pci.c | 224 +++++++++++++++++++++++++------------------ include/linux/ssb/ssb.h | 1 + include/linux/ssb/ssb_regs.h | 38 +++++--- 5 files changed, 170 insertions(+), 104 deletions(-) (limited to 'include/linux/ssb/ssb.h') diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c index f145d8a4cfd..b8b7cb0b436 100644 --- a/drivers/ssb/b43_pci_bridge.c +++ b/drivers/ssb/b43_pci_bridge.c @@ -27,6 +27,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) }, { 0, }, }; MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 85a20546e82..9028ed5715a 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -872,14 +872,22 @@ EXPORT_SYMBOL(ssb_clockspeed); static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev) { + u32 rev = ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV; + /* The REJECT bit changed position in TMSLOW between * Backplane revisions. */ - switch (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_SSBREV) { + switch (rev) { case SSB_IDLOW_SSBREV_22: return SSB_TMSLOW_REJECT_22; case SSB_IDLOW_SSBREV_23: return SSB_TMSLOW_REJECT_23; + case SSB_IDLOW_SSBREV_24: /* TODO - find the proper REJECT bits */ + case SSB_IDLOW_SSBREV_25: /* same here */ + case SSB_IDLOW_SSBREV_26: /* same here */ + case SSB_IDLOW_SSBREV_27: /* same here */ + return SSB_TMSLOW_REJECT_23; /* this is a guess */ default: + printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev); WARN_ON(1); } return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23); diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 7226a716acd..8f600fcd243 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c @@ -212,29 +212,29 @@ static inline u8 ssb_crc8(u8 crc, u8 data) return t[crc ^ data]; } -static u8 ssb_sprom_crc(const u16 *sprom) +static u8 ssb_sprom_crc(const u16 *sprom, u16 size) { int word; u8 crc = 0xFF; - for (word = 0; word < SSB_SPROMSIZE_WORDS - 1; word++) { + for (word = 0; word < size - 1; word++) { crc = ssb_crc8(crc, sprom[word] & 0x00FF); crc = ssb_crc8(crc, (sprom[word] & 0xFF00) >> 8); } - crc = ssb_crc8(crc, sprom[SPOFF(SSB_SPROM_REVISION)] & 0x00FF); + crc = ssb_crc8(crc, sprom[size - 1] & 0x00FF); crc ^= 0xFF; return crc; } -static int sprom_check_crc(const u16 *sprom) +static int sprom_check_crc(const u16 *sprom, u16 size) { u8 crc; u8 expected_crc; u16 tmp; - crc = ssb_sprom_crc(sprom); - tmp = sprom[SPOFF(SSB_SPROM_REVISION)] & SSB_SPROM_REVISION_CRC; + crc = ssb_sprom_crc(sprom, size); + tmp = sprom[size - 1] & SSB_SPROM_REVISION_CRC; expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT; if (crc != expected_crc) return -EPROTO; @@ -246,7 +246,7 @@ static void sprom_do_read(struct ssb_bus *bus, u16 *sprom) { int i; - for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) + for (i = 0; i < bus->sprom_size; i++) sprom[i] = readw(bus->mmio + SSB_SPROM_BASE + (i * 2)); } @@ -255,6 +255,7 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) struct pci_dev *pdev = bus->host_pci; int i, err; u32 spromctl; + u16 size = bus->sprom_size; ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl); @@ -266,12 +267,12 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) goto err_ctlreg; ssb_printk(KERN_NOTICE PFX "[ 0%%"); msleep(500); - for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) { - if (i == SSB_SPROMSIZE_WORDS / 4) + for (i = 0; i < size; i++) { + if (i == size / 4) ssb_printk("25%%"); - else if (i == SSB_SPROMSIZE_WORDS / 2) + else if (i == size / 2) ssb_printk("50%%"); - else if (i == (SSB_SPROMSIZE_WORDS / 4) * 3) + else if (i == (size * 3) / 4) ssb_printk("75%%"); else if (i % 2) ssb_printk("."); @@ -350,95 +351,120 @@ static void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in) SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0); SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG, SSB_SPROM1_AGAIN_BG_SHIFT); - for (i = 0; i < 4; i++) { - v = in[SPOFF(SSB_SPROM1_OEM) + i]; - *(((__le16 *)out->oem) + i) = cpu_to_le16(v); - } } -static void sprom_extract_r2(struct ssb_sprom_r2 *out, const u16 *in) +static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) { int i; u16 v; + u16 loc[3]; - SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); - SPEX(maxpwr_a_hi, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0); - SPEX(maxpwr_a_lo, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO, - SSB_SPROM2_MAXP_A_LO_SHIFT); - SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0); - SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0); - SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0); - SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0); - SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0); - SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0); - SPEX(ofdm_pwr_off, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0); - for (i = 0; i < 4; i++) { - v = in[SPOFF(SSB_SPROM2_CCODE) + i]; - *(((__le16 *)out->country_str) + i) = cpu_to_le16(v); + if (out->revision == 3) { /* rev 3 moved MAC */ + loc[0] = SSB_SPROM3_IL0MAC; + loc[1] = SSB_SPROM3_ET0MAC; + loc[2] = SSB_SPROM3_ET1MAC; + } else { + loc[0] = SSB_SPROM1_IL0MAC; + loc[1] = SSB_SPROM1_ET0MAC; + loc[2] = SSB_SPROM1_ET1MAC; + } + for (i = 0; i < 3; i++) { + v = in[SPOFF(loc[0]) + i]; + *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); + } + for (i = 0; i < 3; i++) { + v = in[SPOFF(loc[1]) + i]; + *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); + } + for (i = 0; i < 3; i++) { + v = in[SPOFF(loc[2]) + i]; + *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); } + SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); + SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, + SSB_SPROM1_ETHPHY_ET1A_SHIFT); + SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, + SSB_SPROM1_BINF_CCODE_SHIFT); + SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0); + SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0); + SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0); + SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0); + SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0); + SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0); + SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0); + SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1, + SSB_SPROM1_GPIOA_P1_SHIFT); + SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0); + SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3, + SSB_SPROM1_GPIOB_P3_SHIFT); + SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A, + SSB_SPROM1_MAXPWR_A_SHIFT); + SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0); + SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A, + SSB_SPROM1_ITSSI_A_SHIFT); + SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); + SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); + SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0); + SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG, + SSB_SPROM1_AGAIN_BG_SHIFT); } -static void sprom_extract_r3(struct ssb_sprom_r3 *out, const u16 *in) +static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) { - out->ofdmapo = (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0xFF00) >> 8; - out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 0] & 0x00FF) << 8; - out->ofdmapo <<= 16; - out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0xFF00) >> 8; - out->ofdmapo |= (in[SPOFF(SSB_SPROM3_OFDMAPO) + 1] & 0x00FF) << 8; - - out->ofdmalpo = (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0xFF00) >> 8; - out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 0] & 0x00FF) << 8; - out->ofdmalpo <<= 16; - out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0xFF00) >> 8; - out->ofdmalpo |= (in[SPOFF(SSB_SPROM3_OFDMALPO) + 1] & 0x00FF) << 8; - - out->ofdmahpo = (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0xFF00) >> 8; - out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 0] & 0x00FF) << 8; - out->ofdmahpo <<= 16; - out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0xFF00) >> 8; - out->ofdmahpo |= (in[SPOFF(SSB_SPROM3_OFDMAHPO) + 1] & 0x00FF) << 8; - - SPEX(gpioldc_on_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_ON, - SSB_SPROM3_GPIOLDC_ON_SHIFT); - SPEX(gpioldc_off_cnt, SSB_SPROM3_GPIOLDC, SSB_SPROM3_GPIOLDC_OFF, - SSB_SPROM3_GPIOLDC_OFF_SHIFT); - SPEX(cckpo_1M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_1M, 0); - SPEX(cckpo_2M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_2M, - SSB_SPROM3_CCKPO_2M_SHIFT); - SPEX(cckpo_55M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_55M, - SSB_SPROM3_CCKPO_55M_SHIFT); - SPEX(cckpo_11M, SSB_SPROM3_CCKPO, SSB_SPROM3_CCKPO_11M, - SSB_SPROM3_CCKPO_11M_SHIFT); - - out->ofdmgpo = (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0xFF00) >> 8; - out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 0] & 0x00FF) << 8; - out->ofdmgpo <<= 16; - out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0xFF00) >> 8; - out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0x00FF) << 8; + int i; + u16 v; + + /* extract the r1 variables */ + for (i = 0; i < 3; i++) { + v = in[SPOFF(SSB_SPROM4_IL0MAC) + i]; + *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); + } + for (i = 0; i < 3; i++) { + v = in[SPOFF(SSB_SPROM4_ET0MAC) + i]; + *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); + } + for (i = 0; i < 3; i++) { + v = in[SPOFF(SSB_SPROM4_ET1MAC) + i]; + *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); + } + SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); + SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, + SSB_SPROM4_ETHPHY_ET1A_SHIFT); + SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); + SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); + SPEX(antenna_gain_a, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_0, 0); + SPEX(antenna_gain_bg, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_1, + SSB_SPROM4_AGAIN_1_SHIFT); + /* TODO - get remaining rev 4 stuff needed */ } -static int sprom_extract(struct ssb_bus *bus, - struct ssb_sprom *out, const u16 *in) +static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, + const u16 *in, u16 size) { memset(out, 0, sizeof(*out)); - SPEX(revision, SSB_SPROM_REVISION, SSB_SPROM_REVISION_REV, 0); - + out->revision = in[size - 1] & 0x00FF; if ((bus->chip_id & 0xFF00) == 0x4400) { /* Workaround: The BCM44XX chip has a stupid revision * number stored in the SPROM. * Always extract r1. */ + out->revision = 1; + sprom_extract_r123(out, in); sprom_extract_r1(&out->r1, in); + } else if (bus->chip_id == 0x4321) { + /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */ + out->revision = 4; + sprom_extract_r4(out, in); } else { if (out->revision == 0) goto unsupported; - if (out->revision >= 1 && out->revision <= 3) + if (out->revision >= 1 && out->revision <= 3) { + sprom_extract_r123(out, in); sprom_extract_r1(&out->r1, in); - if (out->revision >= 2 && out->revision <= 3) - sprom_extract_r2(&out->r2, in); - if (out->revision == 3) - sprom_extract_r3(&out->r3, in); - if (out->revision >= 4) + } + if (out->revision == 4) + sprom_extract_r4(out, in); + if (out->revision >= 5) goto unsupported; } @@ -456,16 +482,31 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, int err = -ENOMEM; u16 *buf; - buf = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL); + buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL); if (!buf) goto out; + bus->sprom_size = SSB_SPROMSIZE_WORDS_R123; sprom_do_read(bus, buf); - err = sprom_check_crc(buf); + err = sprom_check_crc(buf, bus->sprom_size); if (err) { - ssb_printk(KERN_WARNING PFX - "WARNING: Invalid SPROM CRC (corrupt SPROM)\n"); + /* check for rev 4 sprom - has special signature */ + if (buf [32] == 0x5372) { + ssb_printk(KERN_WARNING PFX "Extracting a rev 4" + " SPROM\n"); + kfree(buf); + buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), + GFP_KERNEL); + if (!buf) + goto out; + bus->sprom_size = SSB_SPROMSIZE_WORDS_R4; + sprom_do_read(bus, buf); + err = sprom_check_crc(buf, bus->sprom_size); + } + if (err) + ssb_printk(KERN_WARNING PFX "WARNING: Invalid" + " SPROM CRC (corrupt SPROM)\n"); } - err = sprom_extract(bus, sprom, buf); + err = sprom_extract(bus, sprom, buf, bus->sprom_size); kfree(buf); out: @@ -579,29 +620,28 @@ const struct ssb_bus_ops ssb_pci_ops = { .write32 = ssb_pci_write32, }; -static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len) +static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, u16 size) { int i, pos = 0; - for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) { + for (i = 0; i < size; i++) pos += snprintf(buf + pos, buf_len - pos - 1, "%04X", swab16(sprom[i]) & 0xFFFF); - } pos += snprintf(buf + pos, buf_len - pos - 1, "\n"); return pos + 1; } -static int hex2sprom(u16 *sprom, const char *dump, size_t len) +static int hex2sprom(u16 *sprom, const char *dump, size_t len, u16 size) { char tmp[5] = { 0 }; int cnt = 0; unsigned long parsed; - if (len < SSB_SPROMSIZE_BYTES * 2) + if (len < size * 2) return -EINVAL; - while (cnt < SSB_SPROMSIZE_WORDS) { + while (cnt < size) { memcpy(tmp, dump, 4); dump += 4; parsed = simple_strtoul(tmp, NULL, 16); @@ -625,7 +665,7 @@ static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev, if (!bus) goto out; err = -ENOMEM; - sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL); + sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL); if (!sprom) goto out; @@ -638,7 +678,7 @@ static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev, sprom_do_read(bus, sprom); mutex_unlock(&bus->pci_sprom_mutex); - count = sprom2hex(sprom, buf, PAGE_SIZE); + count = sprom2hex(sprom, buf, PAGE_SIZE, bus->sprom_size); err = 0; out_kfree: @@ -660,15 +700,15 @@ static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev, if (!bus) goto out; err = -ENOMEM; - sprom = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL); + sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL); if (!sprom) goto out; - err = hex2sprom(sprom, buf, count); + err = hex2sprom(sprom, buf, count, bus->sprom_size); if (err) { err = -EINVAL; goto out_kfree; } - err = sprom_check_crc(sprom); + err = sprom_check_crc(sprom, bus->sprom_size); if (err) { err = -EINVAL; goto out_kfree; diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index cdd8a2fd4a6..745de2aac85 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -308,6 +308,7 @@ struct ssb_bus { /* ID information about the Chip. */ u16 chip_id; u16 chip_rev; + u16 sprom_size; /* number of words in sprom */ u8 chip_package; /* List of devices (cores) on the backplane. */ diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index bcebcffd448..96bba69b127 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h @@ -147,6 +147,10 @@ #define SSB_IDLOW_SSBREV 0xF0000000 /* Sonics Backplane Revision code */ #define SSB_IDLOW_SSBREV_22 0x00000000 /* <= 2.2 */ #define SSB_IDLOW_SSBREV_23 0x10000000 /* 2.3 */ +#define SSB_IDLOW_SSBREV_24 0x40000000 /* ?? Found in BCM4328 */ +#define SSB_IDLOW_SSBREV_25 0x50000000 /* ?? Not Found yet */ +#define SSB_IDLOW_SSBREV_26 0x60000000 /* ?? Found in some BCM4311/2 */ +#define SSB_IDLOW_SSBREV_27 0x70000000 /* ?? Found in some BCM4311/2 */ #define SSB_IDHIGH 0x0FFC /* SB Identification High */ #define SSB_IDHIGH_RCLO 0x0000000F /* Revision Code (low part) */ #define SSB_IDHIGH_CC 0x00008FF0 /* Core Code */ @@ -162,6 +166,10 @@ */ #define SSB_SPROMSIZE_WORDS 64 #define SSB_SPROMSIZE_BYTES (SSB_SPROMSIZE_WORDS * sizeof(u16)) +#define SSB_SPROMSIZE_WORDS_R123 64 +#define SSB_SPROMSIZE_WORDS_R4 220 +#define SSB_SPROMSIZE_BYTES_R123 (SSB_SPROMSIZE_WORDS_R123 * sizeof(u16)) +#define SSB_SPROMSIZE_BYTES_R4 (SSB_SPROMSIZE_WORDS_R4 * sizeof(u16)) #define SSB_SPROM_BASE 0x1000 #define SSB_SPROM_REVISION 0x107E #define SSB_SPROM_REVISION_REV 0x00FF /* SPROM Revision number */ @@ -232,7 +240,10 @@ #define SSB_SPROM2_OPO_VALUE 0x00FF #define SSB_SPROM2_OPO_UNUSED 0xFF00 #define SSB_SPROM2_CCODE 0x107C /* Two char Country Code */ -/* SPROM Revision 3 (inherits from rev 2) */ +/* SPROM Revision 3 (inherits most data from rev 2) */ +#define SSB_SPROM3_IL0MAC 0x104A /* 6 bytes MAC address for 802.11b/g */ +#define SSB_SPROM3_ET0MAC 0x1050 /* 6 bytes MAC address for Ethernet ?? */ +#define SSB_SPROM3_ET1MAC 0x1050 /* 6 bytes MAC address for 802.11a ?? */ #define SSB_SPROM3_OFDMAPO 0x102C /* A-PHY OFDM Mid Power Offset (4 bytes, BigEndian) */ #define SSB_SPROM3_OFDMALPO 0x1030 /* A-PHY OFDM Low Power Offset (4 bytes, BigEndian) */ #define SSB_SPROM3_OFDMAHPO 0x1034 /* A-PHY OFDM High Power Offset (4 bytes, BigEndian) */ @@ -250,8 +261,10 @@ #define SSB_SPROM3_CCKPO_11M 0xF000 /* 11M Rate PO */ #define SSB_SPROM3_CCKPO_11M_SHIFT 12 #define SSB_SPROM3_OFDMGPO 0x107A /* G-PHY OFDM Power Offset (4 bytes, BigEndian) */ -/* SPROM Revision 4 */ +/* SPROM Revision 4 entries with ?? in comment are unknown */ #define SSB_SPROM4_IL0MAC 0x104C /* 6 byte MAC address for b/g */ +#define SSB_SPROM4_ET0MAC 0x1018 /* 6 bytes MAC address for Ethernet ?? */ +#define SSB_SPROM4_ET1MAC 0x1018 /* 6 bytes MAC address for 802.11a ?? */ #define SSB_SPROM4_ETHPHY 0x105A /* Ethernet PHY settings */ #define SSB_SPROM4_ETHPHY_ET0A 0x001F /* MII Address for enet0 */ #define SSB_SPROM4_ETHPHY_ET1A 0x03E0 /* MII Address for enet1 */ @@ -263,19 +276,22 @@ #define SSB_SPROM4_ANT_BG 0x105C /* B/G Antennas */ #define SSB_SPROM4_BFLLO 0x1044 /* Boardflags (low 16 bits) */ #define SSB_SPROM4_AGAIN 0x105E /* Antenna Gain (in dBm Q5.2) */ +#define SSB_SPROM4_AGAIN_0 0x00FF /* Antenna 0 */ +#define SSB_SPROM4_AGAIN_1 0xFF00 /* Antenna 1 */ +#define SSB_SPROM4_AGAIN_1_SHIFT 8 #define SSB_SPROM4_BFLHI 0x1046 /* Board Flags Hi */ -#define SSB_SPROM4_MAXP_A 0x1000 /* Max Power A */ +#define SSB_SPROM4_MAXP_A 0x1000 /* Max Power A ?? */ #define SSB_SPROM4_MAXP_A_HI 0x00FF /* Mask for Hi */ #define SSB_SPROM4_MAXP_A_LO 0xFF00 /* Mask for Lo */ #define SSB_SPROM4_MAXP_A_LO_SHIFT 16 /* Shift for Lo */ -#define SSB_SPROM4_PA1LOB0 0x1000 -#define SSB_SPROM4_PA1LOB1 0x1000 -#define SSB_SPROM4_PA1LOB2 0x1000 -#define SSB_SPROM4_PA1HIB0 0x1000 -#define SSB_SPROM4_PA1HIB1 0x1000 -#define SSB_SPROM4_PA1HIB2 0x1000 -#define SSB_SPROM4_OPO 0x1000 -#define SSB_SPROM4_OPO_VALUE 0x0000 +#define SSB_SPROM4_PA1LOB0 0x1000 /* ?? */ +#define SSB_SPROM4_PA1LOB1 0x1000 /* ?? */ +#define SSB_SPROM4_PA1LOB2 0x1000 /* ?? */ +#define SSB_SPROM4_PA1HIB0 0x1000 /* ?? */ +#define SSB_SPROM4_PA1HIB1 0x1000 /* ?? */ +#define SSB_SPROM4_PA1HIB2 0x1000 /* ?? */ +#define SSB_SPROM4_OPO 0x1000 /* ?? */ +#define SSB_SPROM4_OPO_VALUE 0x0000 /* ?? */ #define SSB_SPROM4_GPIOLDC 0x105A /* LED Powersave Duty Cycle */ #define SSB_SPROM4_GPIOLDC_OFF 0x0000FF00 /* Off Count */ #define SSB_SPROM4_GPIOLDC_OFF_SHIFT 8 -- cgit v1.2.3-70-g09d2 From d3c319f9c8d9ee2c042c60b8a1bbd909dcc42782 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 9 Nov 2007 16:58:20 -0600 Subject: ssb: Remove the old, now unused, data structures The old, now unused, data structures and SPROM extraction routines are removed. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/ssb/pci.c | 75 +++++++++----------------------------------- include/linux/ssb/ssb.h | 74 ------------------------------------------- include/linux/ssb/ssb_regs.h | 49 ++++++++++++++++------------- 3 files changed, 43 insertions(+), 155 deletions(-) (limited to 'include/linux/ssb/ssb.h') diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 8f600fcd243..9777dcb5bfe 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c @@ -297,62 +297,6 @@ err_ctlreg: return err; } -static void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in) -{ - int i; - u16 v; - - SPEX(pci_spid, SSB_SPROM1_SPID, 0xFFFF, 0); - SPEX(pci_svid, SSB_SPROM1_SVID, 0xFFFF, 0); - SPEX(pci_pid, SSB_SPROM1_PID, 0xFFFF, 0); - for (i = 0; i < 3; i++) { - v = in[SPOFF(SSB_SPROM1_IL0MAC) + i]; - *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); - } - for (i = 0; i < 3; i++) { - v = in[SPOFF(SSB_SPROM1_ET0MAC) + i]; - *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v); - } - for (i = 0; i < 3; i++) { - v = in[SPOFF(SSB_SPROM1_ET1MAC) + i]; - *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v); - } - SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); - SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, - SSB_SPROM1_ETHPHY_ET1A_SHIFT); - SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); - SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); - SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); - SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, - SSB_SPROM1_BINF_CCODE_SHIFT); - SPEX(antenna_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA, - SSB_SPROM1_BINF_ANTA_SHIFT); - SPEX(antenna_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG, - SSB_SPROM1_BINF_ANTBG_SHIFT); - SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0); - SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0); - SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0); - SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0); - SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0); - SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0); - SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0); - SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1, - SSB_SPROM1_GPIOA_P1_SHIFT); - SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0); - SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3, - SSB_SPROM1_GPIOB_P3_SHIFT); - SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A, - SSB_SPROM1_MAXPWR_A_SHIFT); - SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0); - SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A, - SSB_SPROM1_ITSSI_A_SHIFT); - SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); - SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); - SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0); - SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG, - SSB_SPROM1_AGAIN_BG_SHIFT); -} - static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) { int i; @@ -414,7 +358,7 @@ static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) int i; u16 v; - /* extract the r1 variables */ + /* extract the equivalent of the r1 variables */ for (i = 0; i < 3; i++) { v = in[SPOFF(SSB_SPROM4_IL0MAC) + i]; *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); @@ -435,6 +379,18 @@ static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) SPEX(antenna_gain_a, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_0, 0); SPEX(antenna_gain_bg, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_1, SSB_SPROM4_AGAIN_1_SHIFT); + SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0); + SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG, + SSB_SPROM4_ITSSI_BG_SHIFT); + SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0); + SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A, + SSB_SPROM4_ITSSI_A_SHIFT); + SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0); + SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1, + SSB_SPROM4_GPIOA_P1_SHIFT); + SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0); + SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3, + SSB_SPROM4_GPIOB_P3_SHIFT); /* TODO - get remaining rev 4 stuff needed */ } @@ -444,13 +400,13 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, memset(out, 0, sizeof(*out)); out->revision = in[size - 1] & 0x00FF; + ssb_printk(KERN_INFO PFX "SPROM revision %d detected.\n", out->revision); if ((bus->chip_id & 0xFF00) == 0x4400) { /* Workaround: The BCM44XX chip has a stupid revision * number stored in the SPROM. * Always extract r1. */ out->revision = 1; sprom_extract_r123(out, in); - sprom_extract_r1(&out->r1, in); } else if (bus->chip_id == 0x4321) { /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */ out->revision = 4; @@ -460,7 +416,6 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, goto unsupported; if (out->revision >= 1 && out->revision <= 3) { sprom_extract_r123(out, in); - sprom_extract_r1(&out->r1, in); } if (out->revision == 4) sprom_extract_r4(out, in); @@ -472,7 +427,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, unsupported: ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d " "detected. Will extract v1\n", out->revision); - sprom_extract_r1(&out->r1, in); + sprom_extract_r123(out, in); return 0; } diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 745de2aac85..a21ab29ff36 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -15,72 +15,8 @@ struct pcmcia_device; struct ssb_bus; struct ssb_driver; - -struct ssb_sprom_r1 { - u16 pci_spid; /* Subsystem Product ID for PCI */ - u16 pci_svid; /* Subsystem Vendor ID for PCI */ - u16 pci_pid; /* Product ID for PCI */ - u8 il0mac[6]; /* MAC address for 802.11b/g */ - u8 et0mac[6]; /* MAC address for Ethernet */ - u8 et1mac[6]; /* MAC address for 802.11a */ - u8 et0phyaddr:5; /* MII address for enet0 */ - u8 et1phyaddr:5; /* MII address for enet1 */ - u8 et0mdcport:1; /* MDIO for enet0 */ - u8 et1mdcport:1; /* MDIO for enet1 */ - u8 board_rev; /* Board revision */ - u8 country_code:4; /* Country Code */ - u8 antenna_a:2; /* Antenna 0/1 available for A-PHY */ - u8 antenna_bg:2; /* Antenna 0/1 available for B-PHY and G-PHY */ - u16 pa0b0; - u16 pa0b1; - u16 pa0b2; - u16 pa1b0; - u16 pa1b1; - u16 pa1b2; - u8 gpio0; /* GPIO pin 0 */ - u8 gpio1; /* GPIO pin 1 */ - u8 gpio2; /* GPIO pin 2 */ - u8 gpio3; /* GPIO pin 3 */ - u16 maxpwr_a; /* A-PHY Power Amplifier Max Power (in dBm Q5.2) */ - u16 maxpwr_bg; /* B/G-PHY Power Amplifier Max Power (in dBm Q5.2) */ - u8 itssi_a; /* Idle TSSI Target for A-PHY */ - u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */ - u16 boardflags_lo; /* Boardflags (low 16 bits) */ - u8 antenna_gain_a; /* A-PHY Antenna gain (in dBm Q5.2) */ - u8 antenna_gain_bg; /* B/G-PHY Antenna gain (in dBm Q5.2) */ - u8 oem[8]; /* OEM string (rev 1 only) */ -}; - -struct ssb_sprom_r2 { - u16 boardflags_hi; /* Boardflags (high 16 bits) */ - u8 maxpwr_a_lo; /* A-PHY Max Power Low */ - u8 maxpwr_a_hi; /* A-PHY Max Power High */ - u16 pa1lob0; /* A-PHY PA Low Settings */ - u16 pa1lob1; /* A-PHY PA Low Settings */ - u16 pa1lob2; /* A-PHY PA Low Settings */ - u16 pa1hib0; /* A-PHY PA High Settings */ - u16 pa1hib1; /* A-PHY PA High Settings */ - u16 pa1hib2; /* A-PHY PA High Settings */ - u8 ofdm_pwr_off; /* OFDM Power Offset from CCK Level */ - u8 country_str[2]; /* Two char Country Code */ -}; - -struct ssb_sprom_r3 { - u32 ofdmapo; /* A-PHY OFDM Mid Power Offset */ - u32 ofdmalpo; /* A-PHY OFDM Low Power Offset */ - u32 ofdmahpo; /* A-PHY OFDM High Power Offset */ - u8 gpioldc_on_cnt; /* GPIO LED Powersave Duty Cycle ON count */ - u8 gpioldc_off_cnt; /* GPIO LED Powersave Duty Cycle OFF count */ - u8 cckpo_1M:4; /* CCK Power Offset for Rate 1M */ - u8 cckpo_2M:4; /* CCK Power Offset for Rate 2M */ - u8 cckpo_55M:4; /* CCK Power Offset for Rate 5.5M */ - u8 cckpo_11M:4; /* CCK Power Offset for Rate 11M */ - u32 ofdmgpo; /* G-PHY OFDM Power Offset */ -}; - struct ssb_sprom { u8 revision; - u8 temp_fill[2 * sizeof(struct ssb_sprom_r1)]; u8 il0mac[6]; /* MAC address for 802.11b/g */ u8 et0mac[6]; /* MAC address for Ethernet */ u8 et1mac[6]; /* MAC address for 802.11a */ @@ -106,16 +42,6 @@ struct ssb_sprom { u8 antenna_gain_bg; /* B/G-PHY Antenna gain (in dBm Q5.2) */ /* TODO - add any parameters needed from rev 2, 3, or 4 SPROMs */ - /* The valid r# fields are selected by the "revision". - * Revision 3 and lower inherit from lower revisions. - */ - union { - struct { - struct ssb_sprom_r1 r1; - struct ssb_sprom_r2 r2; - struct ssb_sprom_r3 r3; - }; - }; }; /* Information about the PCB the circuitry is soldered on. */ diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index 96bba69b127..30222e89ad1 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h @@ -175,6 +175,7 @@ #define SSB_SPROM_REVISION_REV 0x00FF /* SPROM Revision number */ #define SSB_SPROM_REVISION_CRC 0xFF00 /* SPROM CRC8 value */ #define SSB_SPROM_REVISION_CRC_SHIFT 8 + /* SPROM Revision 1 */ #define SSB_SPROM1_SPID 0x1004 /* Subsystem Product ID for PCI */ #define SSB_SPROM1_SVID 0x1006 /* Subsystem Vendor ID for PCI */ @@ -223,7 +224,7 @@ #define SSB_SPROM1_AGAIN_A 0x00FF /* A-PHY */ #define SSB_SPROM1_AGAIN_BG 0xFF00 /* B-PHY and G-PHY */ #define SSB_SPROM1_AGAIN_BG_SHIFT 8 -#define SSB_SPROM1_OEM 0x1076 /* 8 bytes OEM string (rev 1 only) */ + /* SPROM Revision 2 (inherits from rev 1) */ #define SSB_SPROM2_BFLHI 0x1038 /* Boardflags (high 16 bits) */ #define SSB_SPROM2_MAXP_A 0x103A /* A-PHY Max Power */ @@ -240,6 +241,7 @@ #define SSB_SPROM2_OPO_VALUE 0x00FF #define SSB_SPROM2_OPO_UNUSED 0xFF00 #define SSB_SPROM2_CCODE 0x107C /* Two char Country Code */ + /* SPROM Revision 3 (inherits most data from rev 2) */ #define SSB_SPROM3_IL0MAC 0x104A /* 6 bytes MAC address for 802.11b/g */ #define SSB_SPROM3_ET0MAC 0x1050 /* 6 bytes MAC address for Ethernet ?? */ @@ -261,11 +263,12 @@ #define SSB_SPROM3_CCKPO_11M 0xF000 /* 11M Rate PO */ #define SSB_SPROM3_CCKPO_11M_SHIFT 12 #define SSB_SPROM3_OFDMGPO 0x107A /* G-PHY OFDM Power Offset (4 bytes, BigEndian) */ + /* SPROM Revision 4 entries with ?? in comment are unknown */ -#define SSB_SPROM4_IL0MAC 0x104C /* 6 byte MAC address for b/g */ +#define SSB_SPROM4_IL0MAC 0x104C /* 6 byte MAC address for a/b/g/n */ #define SSB_SPROM4_ET0MAC 0x1018 /* 6 bytes MAC address for Ethernet ?? */ #define SSB_SPROM4_ET1MAC 0x1018 /* 6 bytes MAC address for 802.11a ?? */ -#define SSB_SPROM4_ETHPHY 0x105A /* Ethernet PHY settings */ +#define SSB_SPROM4_ETHPHY 0x105A /* Ethernet PHY settings ?? */ #define SSB_SPROM4_ETHPHY_ET0A 0x001F /* MII Address for enet0 */ #define SSB_SPROM4_ETHPHY_ET1A 0x03E0 /* MII Address for enet1 */ #define SSB_SPROM4_ETHPHY_ET1A_SHIFT 5 @@ -280,24 +283,28 @@ #define SSB_SPROM4_AGAIN_1 0xFF00 /* Antenna 1 */ #define SSB_SPROM4_AGAIN_1_SHIFT 8 #define SSB_SPROM4_BFLHI 0x1046 /* Board Flags Hi */ -#define SSB_SPROM4_MAXP_A 0x1000 /* Max Power A ?? */ -#define SSB_SPROM4_MAXP_A_HI 0x00FF /* Mask for Hi */ -#define SSB_SPROM4_MAXP_A_LO 0xFF00 /* Mask for Lo */ -#define SSB_SPROM4_MAXP_A_LO_SHIFT 16 /* Shift for Lo */ -#define SSB_SPROM4_PA1LOB0 0x1000 /* ?? */ -#define SSB_SPROM4_PA1LOB1 0x1000 /* ?? */ -#define SSB_SPROM4_PA1LOB2 0x1000 /* ?? */ -#define SSB_SPROM4_PA1HIB0 0x1000 /* ?? */ -#define SSB_SPROM4_PA1HIB1 0x1000 /* ?? */ -#define SSB_SPROM4_PA1HIB2 0x1000 /* ?? */ -#define SSB_SPROM4_OPO 0x1000 /* ?? */ -#define SSB_SPROM4_OPO_VALUE 0x0000 /* ?? */ -#define SSB_SPROM4_GPIOLDC 0x105A /* LED Powersave Duty Cycle */ -#define SSB_SPROM4_GPIOLDC_OFF 0x0000FF00 /* Off Count */ -#define SSB_SPROM4_GPIOLDC_OFF_SHIFT 8 -#define SSB_SPROM4_GPIOLDC_ON 0x00FF0000 /* On Count */ -#define SSB_SPROM4_GPIOLDC_ON_SHIFT 16 - +#define SSB_SPROM4_MAXP_BG 0x1080 /* Max Power BG in path 1 */ +#define SSB_SPROM4_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */ +#define SSB_SPROM4_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */ +#define SSB_SPROM4_ITSSI_BG_SHIFT 8 +#define SSB_SPROM4_MAXP_A 0x108A /* Max Power A in path 1 */ +#define SSB_SPROM4_MAXP_A_MASK 0x00FF /* Mask for Max Power A */ +#define SSB_SPROM4_ITSSI_A 0xFF00 /* Mask for path 1 itssi_a */ +#define SSB_SPROM4_ITSSI_A_SHIFT 8 +#define SSB_SPROM4_GPIOA 0x1056 /* Gen. Purpose IO # 0 and 1 */ +#define SSB_SPROM4_GPIOA_P0 0x00FF /* Pin 0 */ +#define SSB_SPROM4_GPIOA_P1 0xFF00 /* Pin 1 */ +#define SSB_SPROM4_GPIOA_P1_SHIFT 8 +#define SSB_SPROM4_GPIOB 0x1058 /* Gen. Purpose IO # 2 and 3 */ +#define SSB_SPROM4_GPIOB_P2 0x00FF /* Pin 2 */ +#define SSB_SPROM4_GPIOB_P3 0xFF00 /* Pin 3 */ +#define SSB_SPROM4_GPIOB_P3_SHIFT 8 +#define SSB_SPROM4_PA0B0 0x1082 /* The paXbY locations are */ +#define SSB_SPROM4_PA0B1 0x1084 /* only guesses */ +#define SSB_SPROM4_PA0B2 0x1086 +#define SSB_SPROM4_PA1B0 0x108E +#define SSB_SPROM4_PA1B1 0x1090 +#define SSB_SPROM4_PA1B2 0x1092 /* Values for SSB_SPROM1_BINF_CCODE */ enum { -- cgit v1.2.3-70-g09d2 From e861b98d5e1be769ca6483b6df97149b956ea834 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 22 Dec 2007 21:51:30 +0100 Subject: ssb: Fix extraction of values from SPROM This fixes extraction of some values from the SPROM. It mainly fixes extraction of antenna related values, which is needed for another b43 fix sent later. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 10 ----- drivers/net/wireless/b43legacy/main.c | 5 --- drivers/net/wireless/b43legacy/phy.c | 2 +- drivers/ssb/pci.c | 76 ++++++++++++++++++++++++++++++----- include/linux/ssb/ssb.h | 19 ++++++++- include/linux/ssb/ssb_regs.h | 38 +++++++++++------- 6 files changed, 107 insertions(+), 43 deletions(-) (limited to 'include/linux/ssb/ssb.h') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index d7ea671394a..68bbe8eafd6 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3884,16 +3884,6 @@ static void b43_sprom_fixup(struct ssb_bus *bus) if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40) bus->sprom.boardflags_lo |= B43_BFL_PACTRL; - - /* Handle case when gain is not set in sprom */ - if (bus->sprom.antenna_gain_a == 0xFF) - bus->sprom.antenna_gain_a = 2; - if (bus->sprom.antenna_gain_bg == 0xFF) - bus->sprom.antenna_gain_bg = 2; - - /* Convert Antennagain values to Q5.2 */ - bus->sprom.antenna_gain_a <<= 2; - bus->sprom.antenna_gain_bg <<= 2; } static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 14087fc20f3..575fd9a5874 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3572,11 +3572,6 @@ static void b43legacy_sprom_fixup(struct ssb_bus *bus) bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40) bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL; - - /* Convert Antennagain values to Q5.2 */ - if (bus->sprom.antenna_gain_bg == 0xFF) - bus->sprom.antenna_gain_bg = 2; /* if unset, use 2 dBm */ - bus->sprom.antenna_gain_bg <<= 2; } static void b43legacy_wireless_exit(struct ssb_device *dev, diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c index 9d527e6d6ce..57c668f575f 100644 --- a/drivers/net/wireless/b43legacy/phy.c +++ b/drivers/net/wireless/b43legacy/phy.c @@ -1859,7 +1859,7 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev) * which accounts for the factor of 4 */ #define REG_MAX_PWR 20 max_pwr = min(REG_MAX_PWR * 4 - - dev->dev->bus->sprom.antenna_gain_bg + - dev->dev->bus->sprom.antenna_gain.ghz24.a0 - 0x6, max_pwr); /* find the desired power in Q5.2 - power_level is in dBm diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 9777dcb5bfe..ed2a3875227 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c @@ -247,7 +247,7 @@ static void sprom_do_read(struct ssb_bus *bus, u16 *sprom) int i; for (i = 0; i < bus->sprom_size; i++) - sprom[i] = readw(bus->mmio + SSB_SPROM_BASE + (i * 2)); + sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2)); } static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) @@ -297,10 +297,32 @@ err_ctlreg: return err; } +static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in, + u16 mask, u16 shift) +{ + u16 v; + u8 gain; + + v = in[SPOFF(SSB_SPROM1_AGAIN)]; + gain = (v & mask) >> shift; + if (gain == 0xFF) + gain = 2; /* If unset use 2dBm */ + if (sprom_revision == 1) { + /* Convert to Q5.2 */ + gain <<= 2; + } else { + /* Q5.2 Fractional part is stored in 0xC0 */ + gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2); + } + + return (s8)gain; +} + static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) { int i; u16 v; + s8 gain; u16 loc[3]; if (out->revision == 3) { /* rev 3 moved MAC */ @@ -327,8 +349,15 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, SSB_SPROM1_ETHPHY_ET1A_SHIFT); + SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); + SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); + SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, SSB_SPROM1_BINF_CCODE_SHIFT); + SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA, + SSB_SPROM1_BINF_ANTA_SHIFT); + SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG, + SSB_SPROM1_BINF_ANTBG_SHIFT); SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0); SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0); SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0); @@ -348,9 +377,22 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) SSB_SPROM1_ITSSI_A_SHIFT); SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); - SPEX(antenna_gain_a, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_A, 0); - SPEX(antenna_gain_bg, SSB_SPROM1_AGAIN, SSB_SPROM1_AGAIN_BG, - SSB_SPROM1_AGAIN_BG_SHIFT); + + /* Extract the antenna gain values. */ + gain = r123_extract_antgain(out->revision, in, + SSB_SPROM1_AGAIN_BG, + SSB_SPROM1_AGAIN_BG_SHIFT); + out->antenna_gain.ghz24.a0 = gain; + out->antenna_gain.ghz24.a1 = gain; + out->antenna_gain.ghz24.a2 = gain; + out->antenna_gain.ghz24.a3 = gain; + gain = r123_extract_antgain(out->revision, in, + SSB_SPROM1_AGAIN_A, + SSB_SPROM1_AGAIN_A_SHIFT); + out->antenna_gain.ghz5.a0 = gain; + out->antenna_gain.ghz5.a1 = gain; + out->antenna_gain.ghz5.a2 = gain; + out->antenna_gain.ghz5.a3 = gain; } static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) @@ -376,9 +418,10 @@ static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) SSB_SPROM4_ETHPHY_ET1A_SHIFT); SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); - SPEX(antenna_gain_a, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_0, 0); - SPEX(antenna_gain_bg, SSB_SPROM4_AGAIN, SSB_SPROM4_AGAIN_1, - SSB_SPROM4_AGAIN_1_SHIFT); + SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A, + SSB_SPROM4_ANTAVAIL_A_SHIFT); + SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG, + SSB_SPROM4_ANTAVAIL_BG_SHIFT); SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0); SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG, SSB_SPROM4_ITSSI_BG_SHIFT); @@ -391,6 +434,19 @@ static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0); SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3, SSB_SPROM4_GPIOB_P3_SHIFT); + + /* Extract the antenna gain values. */ + SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01, + SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT); + SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01, + SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT); + SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23, + SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT); + SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23, + SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT); + memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, + sizeof(out->antenna_gain.ghz5)); + /* TODO - get remaining rev 4 stuff needed */ } @@ -400,7 +456,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, memset(out, 0, sizeof(*out)); out->revision = in[size - 1] & 0x00FF; - ssb_printk(KERN_INFO PFX "SPROM revision %d detected.\n", out->revision); + ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision); if ((bus->chip_id & 0xFF00) == 0x4400) { /* Workaround: The BCM44XX chip has a stupid revision * number stored in the SPROM. @@ -445,9 +501,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus, err = sprom_check_crc(buf, bus->sprom_size); if (err) { /* check for rev 4 sprom - has special signature */ - if (buf [32] == 0x5372) { - ssb_printk(KERN_WARNING PFX "Extracting a rev 4" - " SPROM\n"); + if (buf[32] == 0x5372) { kfree(buf); buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), GFP_KERNEL); diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index a21ab29ff36..0eaa98424f0 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -22,7 +22,12 @@ struct ssb_sprom { u8 et1mac[6]; /* MAC address for 802.11a */ u8 et0phyaddr; /* MII address for enet0 */ u8 et1phyaddr; /* MII address for enet1 */ + u8 et0mdcport; /* MDIO for enet0 */ + u8 et1mdcport; /* MDIO for enet1 */ + u8 board_rev; /* Board revision number from SPROM. */ u8 country_code; /* Country Code */ + u8 ant_available_a; /* A-PHY antenna available bits (up to 4) */ + u8 ant_available_bg; /* B/G-PHY antenna available bits (up to 4) */ u16 pa0b0; u16 pa0b1; u16 pa0b2; @@ -38,8 +43,18 @@ struct ssb_sprom { u8 itssi_a; /* Idle TSSI Target for A-PHY */ u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */ u16 boardflags_lo; /* Boardflags (low 16 bits) */ - u8 antenna_gain_a; /* A-PHY Antenna gain (in dBm Q5.2) */ - u8 antenna_gain_bg; /* B/G-PHY Antenna gain (in dBm Q5.2) */ + + /* Antenna gain values for up to 4 antennas + * on each band. Values in dBm/4 (Q5.2). Negative gain means the + * loss in the connectors is bigger than the gain. */ + struct { + struct { + s8 a0, a1, a2, a3; + } ghz24; /* 2.4GHz band */ + struct { + s8 a0, a1, a2, a3; + } ghz5; /* 5GHz band */ + } antenna_gain; /* TODO - add any parameters needed from rev 2, 3, or 4 SPROMs */ }; diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index 30222e89ad1..ebad0bac980 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h @@ -193,10 +193,10 @@ #define SSB_SPROM1_BINF_BREV 0x00FF /* Board Revision */ #define SSB_SPROM1_BINF_CCODE 0x0F00 /* Country Code */ #define SSB_SPROM1_BINF_CCODE_SHIFT 8 -#define SSB_SPROM1_BINF_ANTA 0x3000 /* Available A-PHY antennas */ -#define SSB_SPROM1_BINF_ANTA_SHIFT 12 -#define SSB_SPROM1_BINF_ANTBG 0xC000 /* Available B-PHY antennas */ -#define SSB_SPROM1_BINF_ANTBG_SHIFT 14 +#define SSB_SPROM1_BINF_ANTBG 0x3000 /* Available B-PHY and G-PHY antennas */ +#define SSB_SPROM1_BINF_ANTBG_SHIFT 12 +#define SSB_SPROM1_BINF_ANTA 0xC000 /* Available A-PHY antennas */ +#define SSB_SPROM1_BINF_ANTA_SHIFT 14 #define SSB_SPROM1_PA0B0 0x105E #define SSB_SPROM1_PA0B1 0x1060 #define SSB_SPROM1_PA0B2 0x1062 @@ -221,9 +221,10 @@ #define SSB_SPROM1_ITSSI_A_SHIFT 8 #define SSB_SPROM1_BFLLO 0x1072 /* Boardflags (low 16 bits) */ #define SSB_SPROM1_AGAIN 0x1074 /* Antenna Gain (in dBm Q5.2) */ -#define SSB_SPROM1_AGAIN_A 0x00FF /* A-PHY */ -#define SSB_SPROM1_AGAIN_BG 0xFF00 /* B-PHY and G-PHY */ -#define SSB_SPROM1_AGAIN_BG_SHIFT 8 +#define SSB_SPROM1_AGAIN_BG 0x00FF /* B-PHY and G-PHY */ +#define SSB_SPROM1_AGAIN_BG_SHIFT 0 +#define SSB_SPROM1_AGAIN_A 0xFF00 /* A-PHY */ +#define SSB_SPROM1_AGAIN_A_SHIFT 8 /* SPROM Revision 2 (inherits from rev 1) */ #define SSB_SPROM2_BFLHI 0x1038 /* Boardflags (high 16 bits) */ @@ -264,7 +265,7 @@ #define SSB_SPROM3_CCKPO_11M_SHIFT 12 #define SSB_SPROM3_OFDMGPO 0x107A /* G-PHY OFDM Power Offset (4 bytes, BigEndian) */ -/* SPROM Revision 4 entries with ?? in comment are unknown */ +/* SPROM Revision 4 */ #define SSB_SPROM4_IL0MAC 0x104C /* 6 byte MAC address for a/b/g/n */ #define SSB_SPROM4_ET0MAC 0x1018 /* 6 bytes MAC address for Ethernet ?? */ #define SSB_SPROM4_ET1MAC 0x1018 /* 6 bytes MAC address for 802.11a ?? */ @@ -275,13 +276,22 @@ #define SSB_SPROM4_ETHPHY_ET0M (1<<14) /* MDIO for enet0 */ #define SSB_SPROM4_ETHPHY_ET1M (1<<15) /* MDIO for enet1 */ #define SSB_SPROM4_CCODE 0x1052 /* Country Code (2 bytes) */ -#define SSB_SPROM4_ANT_A 0x105D /* A Antennas */ -#define SSB_SPROM4_ANT_BG 0x105C /* B/G Antennas */ +#define SSB_SPROM4_ANTAVAIL 0x105D /* Antenna available bitfields */ +#define SSB_SPROM4_ANTAVAIL_A 0x00FF /* A-PHY bitfield */ +#define SSB_SPROM4_ANTAVAIL_A_SHIFT 0 +#define SSB_SPROM4_ANTAVAIL_BG 0xFF00 /* B-PHY and G-PHY bitfield */ +#define SSB_SPROM4_ANTAVAIL_BG_SHIFT 8 #define SSB_SPROM4_BFLLO 0x1044 /* Boardflags (low 16 bits) */ -#define SSB_SPROM4_AGAIN 0x105E /* Antenna Gain (in dBm Q5.2) */ -#define SSB_SPROM4_AGAIN_0 0x00FF /* Antenna 0 */ -#define SSB_SPROM4_AGAIN_1 0xFF00 /* Antenna 1 */ -#define SSB_SPROM4_AGAIN_1_SHIFT 8 +#define SSB_SPROM4_AGAIN01 0x105E /* Antenna Gain (in dBm Q5.2) */ +#define SSB_SPROM4_AGAIN0 0x00FF /* Antenna 0 */ +#define SSB_SPROM4_AGAIN0_SHIFT 0 +#define SSB_SPROM4_AGAIN1 0xFF00 /* Antenna 1 */ +#define SSB_SPROM4_AGAIN1_SHIFT 8 +#define SSB_SPROM4_AGAIN23 0x1060 +#define SSB_SPROM4_AGAIN2 0x00FF /* Antenna 2 */ +#define SSB_SPROM4_AGAIN2_SHIFT 0 +#define SSB_SPROM4_AGAIN3 0xFF00 /* Antenna 3 */ +#define SSB_SPROM4_AGAIN3_SHIFT 8 #define SSB_SPROM4_BFLHI 0x1046 /* Board Flags Hi */ #define SSB_SPROM4_MAXP_BG 0x1080 /* Max Power BG in path 1 */ #define SSB_SPROM4_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */ -- cgit v1.2.3-70-g09d2 From 993e1c780b323736a2cdc24564f35e80ce8d3337 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 22 Dec 2007 22:01:36 +0100 Subject: ssb: Fix PCMCIA lowlevel register access This fixes lowlevel register access for PCMCIA based devices. The patch also adds a temporary workaround for the device mac address. It simply adds generation of a random address. The real SPROM extraction will follow in another patch. The temporary workaround will be removed then, but for now it's OK. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/ssb/pcmcia.c | 71 ++++++++++++++++++++++++++++++------------------- include/linux/ssb/ssb.h | 3 ++- 2 files changed, 45 insertions(+), 29 deletions(-) (limited to 'include/linux/ssb/ssb.h') diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index bb44a76b3eb..46816cda8b9 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -94,7 +94,6 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus, struct ssb_device *dev) { int err; - unsigned long flags; #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG ssb_printk(KERN_INFO PFX @@ -103,11 +102,9 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus, dev->core_index); #endif - spin_lock_irqsave(&bus->bar_lock, flags); err = ssb_pcmcia_switch_coreidx(bus, dev->core_index); if (!err) bus->mapped_device = dev; - spin_unlock_irqrestore(&bus->bar_lock, flags); return err; } @@ -115,14 +112,12 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus, int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg) { int attempts = 0; - unsigned long flags; conf_reg_t reg; - int res, err = 0; + int res; SSB_WARN_ON((seg != 0) && (seg != 1)); reg.Offset = 0x34; reg.Function = 0; - spin_lock_irqsave(&bus->bar_lock, flags); while (1) { reg.Action = CS_WRITE; reg.Value = seg; @@ -143,13 +138,11 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg) udelay(10); } bus->mapped_pcmcia_seg = seg; -out_unlock: - spin_unlock_irqrestore(&bus->bar_lock, flags); - return err; + + return 0; error: ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n"); - err = -ENODEV; - goto out_unlock; + return -ENODEV; } static int select_core_and_segment(struct ssb_device *dev, @@ -182,22 +175,33 @@ static int select_core_and_segment(struct ssb_device *dev, static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset) { struct ssb_bus *bus = dev->bus; + unsigned long flags; + int err; + u16 value = 0xFFFF; - if (unlikely(select_core_and_segment(dev, &offset))) - return 0xFFFF; + spin_lock_irqsave(&bus->bar_lock, flags); + err = select_core_and_segment(dev, &offset); + if (likely(!err)) + value = readw(bus->mmio + offset); + spin_unlock_irqrestore(&bus->bar_lock, flags); - return readw(bus->mmio + offset); + return value; } static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset) { struct ssb_bus *bus = dev->bus; - u32 lo, hi; + unsigned long flags; + int err; + u32 lo = 0xFFFFFFFF, hi = 0xFFFFFFFF; - if (unlikely(select_core_and_segment(dev, &offset))) - return 0xFFFFFFFF; - lo = readw(bus->mmio + offset); - hi = readw(bus->mmio + offset + 2); + spin_lock_irqsave(&bus->bar_lock, flags); + err = select_core_and_segment(dev, &offset); + if (likely(!err)) { + lo = readw(bus->mmio + offset); + hi = readw(bus->mmio + offset + 2); + } + spin_unlock_irqrestore(&bus->bar_lock, flags); return (lo | (hi << 16)); } @@ -205,22 +209,31 @@ static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset) static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value) { struct ssb_bus *bus = dev->bus; + unsigned long flags; + int err; - if (unlikely(select_core_and_segment(dev, &offset))) - return; - writew(value, bus->mmio + offset); + spin_lock_irqsave(&bus->bar_lock, flags); + err = select_core_and_segment(dev, &offset); + if (likely(!err)) + writew(value, bus->mmio + offset); + mmiowb(); + spin_unlock_irqrestore(&bus->bar_lock, flags); } static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value) { struct ssb_bus *bus = dev->bus; + unsigned long flags; + int err; - if (unlikely(select_core_and_segment(dev, &offset))) - return; - writeb((value & 0xFF000000) >> 24, bus->mmio + offset + 3); - writeb((value & 0x00FF0000) >> 16, bus->mmio + offset + 2); - writeb((value & 0x0000FF00) >> 8, bus->mmio + offset + 1); - writeb((value & 0x000000FF) >> 0, bus->mmio + offset + 0); + spin_lock_irqsave(&bus->bar_lock, flags); + err = select_core_and_segment(dev, &offset); + if (likely(!err)) { + writew((value & 0x0000FFFF), bus->mmio + offset); + writew(((value & 0xFFFF0000) >> 16), bus->mmio + offset + 2); + } + mmiowb(); + spin_unlock_irqrestore(&bus->bar_lock, flags); } /* Not "static", as it's used in main.c */ @@ -231,10 +244,12 @@ const struct ssb_bus_ops ssb_pcmcia_ops = { .write32 = ssb_pcmcia_write32, }; +#include int ssb_pcmcia_get_invariants(struct ssb_bus *bus, struct ssb_init_invariants *iv) { //TODO + random_ether_addr(iv->sprom.il0mac); return 0; } diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 0eaa98424f0..cacbae53194 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -231,7 +231,8 @@ struct ssb_bus { struct ssb_device *mapped_device; /* Currently mapped PCMCIA segment. (bustype == SSB_BUSTYPE_PCMCIA only) */ u8 mapped_pcmcia_seg; - /* Lock for core and segment switching. */ + /* Lock for core and segment switching. + * On PCMCIA-host busses this is used to protect the whole MMIO access. */ spinlock_t bar_lock; /* The bus this backplane is running on. */ -- cgit v1.2.3-70-g09d2 From 961d57c883198831503c7be5c088a26101dfb16c Mon Sep 17 00:00:00 2001 From: Miguel Botón Date: Tue, 1 Jan 2008 01:16:46 +0100 Subject: ssb: add 'ssb_pcihost_set_power_state' function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds the 'ssb_pcihost_set_power_state' function. This function allows us to set the power state of a PCI device (for example b44 ethernet device). Signed-off-by: Miguel Botón Signed-off-by: John W. Linville --- include/linux/ssb/ssb.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux/ssb/ssb.h') diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index cacbae53194..1ab4688c678 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -365,6 +365,13 @@ static inline void ssb_pcihost_unregister(struct pci_driver *driver) { pci_unregister_driver(driver); } + +static inline +void ssb_pcihost_set_power_state(struct ssb_device *sdev, pci_power_t state) +{ + if (sdev->bus->bustype == SSB_BUSTYPE_PCI) + pci_set_power_state(sdev->bus->host_pci, state); +} #endif /* CONFIG_SSB_PCIHOST */ -- cgit v1.2.3-70-g09d2 From af4b7450788426a113057ce2d85c25b4f4e440d1 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 13 Jan 2008 21:08:24 +0100 Subject: ssb: Add boardflags_hi field to the sprom data structure Add boardflags-high. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/ssb/pci.c | 3 +++ include/linux/ssb/ssb.h | 1 + 2 files changed, 4 insertions(+) (limited to 'include/linux/ssb/ssb.h') diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index ed2a3875227..b434df75047 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c @@ -377,6 +377,8 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) SSB_SPROM1_ITSSI_A_SHIFT); SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); + if (out->revision >= 2) + SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); /* Extract the antenna gain values. */ gain = r123_extract_antgain(out->revision, in, @@ -418,6 +420,7 @@ static void sprom_extract_r4(struct ssb_sprom *out, const u16 *in) SSB_SPROM4_ETHPHY_ET1A_SHIFT); SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); + SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0); SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A, SSB_SPROM4_ANTAVAIL_A_SHIFT); SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG, diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 1ab4688c678..e18f5c23b93 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h @@ -43,6 +43,7 @@ struct ssb_sprom { u8 itssi_a; /* Idle TSSI Target for A-PHY */ u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */ u16 boardflags_lo; /* Boardflags (low 16 bits) */ + u16 boardflags_hi; /* Boardflags (high 16 bits) */ /* Antenna gain values for up to 4 antennas * on each band. Values in dBm/4 (Q5.2). Negative gain means the -- cgit v1.2.3-70-g09d2