Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e861b98d authored by Michael Buesch's avatar Michael Buesch Committed by David S. Miller
Browse files

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: default avatarMichael Buesch <mb@bu3sch.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 66c6b139
Loading
Loading
Loading
Loading
+0 −10
Original line number Diff line number Diff line
@@ -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)
+0 −5
Original line number Diff line number Diff line
@@ -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,
+1 −1
Original line number Diff line number Diff line
@@ -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
+65 −11
Original line number Diff line number Diff line
@@ -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 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
	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,

	/* 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.
@@ -446,8 +502,6 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
	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");
			kfree(buf);
			buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
				      GFP_KERNEL);
+17 −2
Original line number Diff line number Diff line
@@ -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 */
};
Loading