* [RFC] ssb: Add code for SPROM Rev 4
@ 2007-11-03 15:19 Larry Finger
2007-11-05 12:51 ` Michael Buesch
0 siblings, 1 reply; 4+ messages in thread
From: Larry Finger @ 2007-11-03 15:19 UTC (permalink / raw)
To: Michael Buesch; +Cc: Bcm43xx-dev, linux-wireless
The BCM4328 has a revision 4 SPROM. The necessary changes to handle the
layout and different size of this revision are implemented. The size of
the SPROM is now stored in the ssb_bus struct and used from that location
whenever possible. For those routines that need the size, but do not have
access to that struct, a size argument is added.
Recognition of the PCI_ID of the BCM4328 is also implemented. Note that
the PCI_ID is 0x4328, but the chipid is 0x4321.
This code has been tested by Michael Gerdau <mgerdau@tiscali.de>.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
Michael,
Please comment on this patch. It is intended to be applied to wireless-2.6/everything.
Larry
---
drivers/ssb/b43_pci_bridge.c | 1
drivers/ssb/main.c | 8 ++-
drivers/ssb/pci.c | 103 ++++++++++++++++++++++++++++++++-----------
include/linux/ssb/ssb.h | 35 ++++++++++++++
include/linux/ssb/ssb_regs.h | 27 ++++++++++-
5 files changed, 144 insertions(+), 30 deletions(-)
Index: wireless-2.6/drivers/ssb/b43_pci_bridge.c
===================================================================
--- wireless-2.6.orig/drivers/ssb/b43_pci_bridge.c
+++ wireless-2.6/drivers/ssb/b43_pci_bridge.c
@@ -27,6 +27,7 @@ static const struct pci_device_id b43_pc
{ 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);
Index: wireless-2.6/drivers/ssb/pci.c
===================================================================
--- wireless-2.6.orig/drivers/ssb/pci.c
+++ wireless-2.6/drivers/ssb/pci.c
@@ -212,29 +212,29 @@ static inline u8 ssb_crc8(u8 crc, u8 dat
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
{
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
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
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(".");
@@ -417,6 +418,35 @@ static void sprom_extract_r3(struct ssb_
out->ofdmgpo |= (in[SPOFF(SSB_SPROM3_OFDMGPO) + 1] & 0x00FF) << 8;
}
+static void sprom_extract_r4(struct ssb_sprom_r4 *out, const u16 *in)
+{
+ int i;
+ u16 v;
+
+ SPEX(pci_spid, SSB_SPROM4_SPID, 0xFFFF, 0);
+ SPEX(pci_svid, SSB_SPROM4_SVID, 0xFFFF, 0);
+ SPEX(pci_pid, SSB_SPROM4_PID, 0xFFFF, 0);
+ for (i = 0; i < 3; i++) {
+ v = in[SPOFF(SSB_SPROM4_IL0MAC) + i];
+ *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
+ *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
+ *(((__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(et0mdcport, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0M, 14);
+ SPEX(et1mdcport, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1M, 15);
+ SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
+ SPEX(antenna_a, SSB_SPROM4_ANT_A, 0xFFFF, 0);
+ SPEX(antenna_bg, SSB_SPROM4_ANT_BG, 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)
{
@@ -431,6 +461,10 @@ static int sprom_extract(struct ssb_bus
* number stored in the SPROM.
* Always extract r1. */
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->r4, in);
} else {
if (out->revision == 0)
goto unsupported;
@@ -448,6 +482,7 @@ static int sprom_extract(struct ssb_bus
unsupported:
ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d "
"detected. Will extract v1\n", out->revision);
+
sprom_extract_r1(&out->r1, in);
return 0;
}
@@ -458,14 +493,29 @@ static int ssb_pci_sprom_get(struct ssb_
int err = -ENOMEM;
u16 *buf;
- buf = kcalloc(SSB_SPROMSIZE_WORDS, sizeof(u16), GFP_KERNEL);
+ buf = kcalloc(SSB_SPROMSIZE_WORDS_R13, sizeof(u16), GFP_KERNEL);
if (!buf)
goto out;
+ bus->sprom_size = SSB_SPROMSIZE_WORDS_R13;
sprom_do_read(bus, buf);
- err = sprom_check_crc(buf);
+ err = sprom_check_crc(buf, SSB_SPROMSIZE_WORDS_R13);
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, SSB_SPROMSIZE_WORDS_R4);
+ }
+ if (err)
+ ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
+ " SPROM CRC (corrupt SPROM)\n");
}
err = sprom_extract(bus, sprom, buf);
@@ -483,6 +533,8 @@ static void ssb_pci_get_boardinfo(struct
&bi->type);
pci_read_config_word(bus->host_pci, PCI_REVISION_ID,
&bi->rev);
+ printk(KERN_INFO "ssb: vendor, type, rev: 0x%X 0x%X 0x%X\n",
+ bi->vendor, bi->type, bi->rev);
}
int ssb_pci_get_invariants(struct ssb_bus *bus,
@@ -581,29 +633,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, int 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);
@@ -627,7 +678,7 @@ static ssize_t ssb_pci_attr_sprom_show(s
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;
@@ -640,7 +691,7 @@ static ssize_t ssb_pci_attr_sprom_show(s
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:
@@ -662,15 +713,15 @@ static ssize_t ssb_pci_attr_sprom_store(
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;
Index: wireless-2.6/include/linux/ssb/ssb_regs.h
===================================================================
--- wireless-2.6.orig/include/linux/ssb/ssb_regs.h
+++ wireless-2.6/include/linux/ssb/ssb_regs.h
@@ -147,6 +147,8 @@
#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 /* 2.4 */
+#define SSB_IDLOW_SSBREV_27 0x70000000 /* 2.? */
#define SSB_IDHIGH 0x0FFC /* SB Identification High */
#define SSB_IDHIGH_RCLO 0x0000000F /* Revision Code (low part) */
#define SSB_IDHIGH_CC 0x00008FF0 /* Core Code */
@@ -160,8 +162,10 @@
* two bytes wide. Note that the SPROM can _only_ be read
* in two-byte quantinies.
*/
-#define SSB_SPROMSIZE_WORDS 64
-#define SSB_SPROMSIZE_BYTES (SSB_SPROMSIZE_WORDS * sizeof(u16))
+#define SSB_SPROMSIZE_WORDS_R13 64
+#define SSB_SPROMSIZE_WORDS_R4 220
+#define SSB_SPROMSIZE_BYTES_R13 (SSB_SPROMSIZE_WORDS_R13 * 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 */
@@ -250,6 +254,25 @@
#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 */
+#define SSB_SPROM4_SPID 0x1004 /* Subsys. Prod. ID for PCI */
+#define SSB_SPROM4_SVID 0x1006 /* Subsys. Vendor ID for PCI */
+#define SSB_SPROM4_PID 0x1008 /* Product ID for PCI */
+#define SSB_SPROM4_IL0MAC 0x104C /* 6 byte MAC address for b/g */
+#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
+#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_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
/* Values for SSB_SPROM1_BINF_CCODE */
enum {
Index: wireless-2.6/drivers/ssb/main.c
===================================================================
--- wireless-2.6.orig/drivers/ssb/main.c
+++ wireless-2.6/drivers/ssb/main.c
@@ -876,15 +876,21 @@ 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_27: /* same here */
+ return SSB_TMSLOW_REJECT_23 | SSB_TMSLOW_REJECT_22;
default:
WARN_ON(1);
+ printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
}
return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23);
}
Index: wireless-2.6/include/linux/ssb/ssb.h
===================================================================
--- wireless-2.6.orig/include/linux/ssb/ssb.h
+++ wireless-2.6/include/linux/ssb/ssb.h
@@ -79,7 +79,39 @@ struct ssb_sprom_r3 {
};
struct ssb_sprom_r4 {
- /* TODO */
+ 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 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) */
+ /* The variables above this point must match those of ssb_sprom_r1 */
+ /* TODO - add any special ssb_sprom_r4 variables below this point. */
};
struct ssb_sprom {
@@ -288,6 +320,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. */
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] ssb: Add code for SPROM Rev 4
2007-11-03 15:19 [RFC] ssb: Add code for SPROM Rev 4 Larry Finger
@ 2007-11-05 12:51 ` Michael Buesch
2007-11-05 16:03 ` Larry Finger
0 siblings, 1 reply; 4+ messages in thread
From: Michael Buesch @ 2007-11-05 12:51 UTC (permalink / raw)
To: bcm43xx-dev; +Cc: Larry Finger, linux-wireless
On Saturday 03 November 2007 16:19:46 Larry Finger wrote:
> The BCM4328 has a revision 4 SPROM. The necessary changes to handle the
> layout and different size of this revision are implemented. The size of
> the SPROM is now stored in the ssb_bus struct and used from that location
> whenever possible. For those routines that need the size, but do not have
> access to that struct, a size argument is added.
>
> Recognition of the PCI_ID of the BCM4328 is also implemented. Note that
> the PCI_ID is 0x4328, but the chipid is 0x4321.
>
> This code has been tested by Michael Gerdau <mgerdau@tiscali.de>.
>
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
> ---
> Index: wireless-2.6/include/linux/ssb/ssb.h
> ===================================================================
> --- wireless-2.6.orig/include/linux/ssb/ssb.h
> +++ wireless-2.6/include/linux/ssb/ssb.h
> @@ -79,7 +79,39 @@ struct ssb_sprom_r3 {
> };
>
> struct ssb_sprom_r4 {
> - /* TODO */
> + 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 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) */
> + /* The variables above this point must match those of ssb_sprom_r1 */
> + /* TODO - add any special ssb_sprom_r4 variables below this point. */
> };
>
> struct ssb_sprom {
> @@ -288,6 +320,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. */
Larry, I did not forget your patch.
But I need to think a little bit more about this.
The union above is not really what I'd like to have here. In fact,
I think to get the v4 sprom implemented the sprom struct has to be
redesigned.
I think we must leave the path of partitioning the sprom struct into
versions, because that obviously doesn't work anymore.
Instead, I think we must develop _one_ common struct that is capable
of holding the information from any sprom. (Note that the struct layout
does not need to reflect the real hardware layout).
And I think we should also remove the fields that are not needed at all,
like the PCI ID stuff.
something like this:
struct ssb_sprom_pathvar {
bool this_pathvar_is_available;
...foobar data
};
struct ssb_sprom {
u8 wl_mac_addr[ETH_ALEN];
u8 eth0_mac_addr[ETH_ALEN];
u8 eth1_mac_addr[ETH_ALEN];
...
u8 gpio0;
u8 gpio1;
...
antennagain...
struct ssb_sprom_pathvar pv0;
struct ssb_sprom_pathvar pv1;
...
};
Note that I did _not_ look closely at the pathvar stuff, so this
might be a bad idea to design it this way.
But the point I was going to make with that was; we probably need
some "this data is valid" bits for different parts of the sprom
struct, as for example v1-3 don't have these pathvars (So the drivers
must be told it's invalid data).
The reason for all this "valid-bit" stuff is that I think we should
remove any sprom-versioning knowledge from the drivers. That
should be abstracted.
Any idea on how to improve that?
--
Greetings Michael.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] ssb: Add code for SPROM Rev 4
2007-11-05 12:51 ` Michael Buesch
@ 2007-11-05 16:03 ` Larry Finger
2007-11-05 16:31 ` Michael Buesch
0 siblings, 1 reply; 4+ messages in thread
From: Larry Finger @ 2007-11-05 16:03 UTC (permalink / raw)
To: Michael Buesch; +Cc: bcm43xx-dev, linux-wireless
Michael Buesch wrote:
> Larry, I did not forget your patch.
> But I need to think a little bit more about this.
I knew that this one would take some time.
> The union above is not really what I'd like to have here. In fact,
> I think to get the v4 sprom implemented the sprom struct has to be
> redesigned.
The way I implemented it was as a "straw man" designed to get shot down. :-) The only benefit it had
was that this format has allowed my tester to get started enough to get b43 loaded. He is rapidly
implementing that part of the specs that are needed to get the BCM4328 with an N PHY working in G mode.
> I think we must leave the path of partitioning the sprom struct into
> versions, because that obviously doesn't work anymore.
> Instead, I think we must develop _one_ common struct that is capable
> of holding the information from any sprom. (Note that the struct layout
> does not need to reflect the real hardware layout).
>
> And I think we should also remove the fields that are not needed at all,
> like the PCI ID stuff.
I agree.
> something like this:
>
>
> struct ssb_sprom_pathvar {
> bool this_pathvar_is_available;
>
> ...foobar data
> };
>
> struct ssb_sprom {
> u8 wl_mac_addr[ETH_ALEN];
> u8 eth0_mac_addr[ETH_ALEN];
> u8 eth1_mac_addr[ETH_ALEN];
>
> ...
>
> u8 gpio0;
> u8 gpio1;
> ...
>
> antennagain...
>
> struct ssb_sprom_pathvar pv0;
> struct ssb_sprom_pathvar pv1;
I think this section can be
u8 path_data0[SPROM_PATH_DATA_SIZE];
u8 path_data1 ...
where SPROM_PATH_DATA_SIZE = 0x26. Once we see how the data are used, it may make more sense to have
these data be u16, or even a union so that we can have it both ways.
> ...
> };
>
> Note that I did _not_ look closely at the pathvar stuff, so this
> might be a bad idea to design it this way.
> But the point I was going to make with that was; we probably need
> some "this data is valid" bits for different parts of the sprom
> struct, as for example v1-3 don't have these pathvars (So the drivers
> must be told it's invalid data).
> The reason for all this "valid-bit" stuff is that I think we should
> remove any sprom-versioning knowledge from the drivers. That
> should be abstracted.
I agree.
> Any idea on how to improve that?
I'm not sure we need a separate "valid bit" for path data. In the sprom that we are working with,
only paths 1 & 2 are implemented - the paths 3 & 4 region contains all 1's just like any
unimplemented sprom data. It should be OK to initialize the first word of each path to 0xFFFF to
indicate it is unused.
To let you know how the specs translate into a device, here is the dump of the BCM4328 sprom:
ssb: SPROM r4 dump
ssb: 0x0000: 0x2801 0x0000 0x0009 0x1028 0x0000 0x0DBE 0xFF00 0x2BC4
ssb: 0x0010: 0x2A64 0x2964 0x2C64 0x3CE7 0xFFFF 0xFFFF 0xFFFF 0xFFFF
ssb: 0x0020: 0x4328 0x8000 0x0002 0x0000 0x1001 0x1800 0x0000 0x0000
ssb: 0x0030: 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF
ssb: 0x0040: 0x5372 0x004C 0x4A01 0x0000 0x0004 0x0000 0x0019 0x7DA5
ssb: 0x0050: 0x1912 0x0000 0x0001 0x83FF 0xFFFF 0xFFFF 0x0303 0x0202
ssb: 0x0060: 0xFFFF 0x3437 0x5B5B 0x1420 0x5B5B 0x0D0C 0x5B5B 0x1A1E
ssb: 0x0070: 0x5B5B 0x3844 0x3838 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF
ssb: 0x0080: 0x3E4E 0xFEC6 0x15D3 0xFB3D 0x0000 0x3E3C 0x3C3C 0xFE6C
ssb: 0x0090: 0x1664 0xFA7B 0x0000 0xFE37 0x1401 0xFAE7 0x0000 0xFE5A
ssb: 0x00A0: 0x147E 0xFAC7 0x0000 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0x3E4E
ssb: 0x00B0: 0xFEC1 0x15BC 0xFB2F 0x0000 0x3E3C 0x3C3C 0xFE69 0x1608
ssb: 0x00C0: 0xFA81 0x0000 0xFE2A 0x1321 0xFB0B 0x0000 0xFE66 0x1595
ssb: 0x00D0: 0xFA88 0x0000 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF
ssb: 0x00E0: 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF
ssb: 0x00F0: 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF
ssb: 0x0100: 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF
ssb: 0x0110: 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF
ssb: 0x0120: 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF
ssb: 0x0130: 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0x0000 0x0000 0x0000 0x0000
ssb: 0x0140: 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
ssb: 0x0150: 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
ssb: 0x0160: 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
ssb: 0x0170: 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
ssb: 0x0180: 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000
ssb: 0x0190: 0x0000 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF
ssb: 0x01A0: 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF 0xFFFF
ssb: 0x01B0: 0xFFFF 0xFFFF 0xFFFF 0x9404
As I said earlier, my current patch is working OK for present needs. Once we come to an agreement
regarding the sprom data structures, I will begin implementing them. As I see it, conversion will be
a 3-step process. We will need a patch to add the new structure, a second to populate that
structure, patches to convert b44, b43, and b43legacy to use the new data, and a final patch to
remove the old structure. In this manner, bisection will be supported.
Larry
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] ssb: Add code for SPROM Rev 4
2007-11-05 16:03 ` Larry Finger
@ 2007-11-05 16:31 ` Michael Buesch
0 siblings, 0 replies; 4+ messages in thread
From: Michael Buesch @ 2007-11-05 16:31 UTC (permalink / raw)
To: Larry Finger; +Cc: bcm43xx-dev, linux-wireless
On Monday 05 November 2007 17:03:47 Larry Finger wrote:
> u8 path_data0[SPROM_PATH_DATA_SIZE];
> u8 path_data1 ...
>
> where SPROM_PATH_DATA_SIZE = 0x26. Once we see how the data are used, it may make more sense to have
> these data be u16,
> or even a union so that we can have it both ways.
^^^^^ ^^^^^^^^^
Whoops, endianess broken :)
> I'm not sure we need a separate "valid bit" for path data. In the sprom that we are working with,
Ok, even better then.
The "valid bit" was just an idea for stuff in the sprom which cannot
be determined valid or not in another way.
> As I said earlier, my current patch is working OK for present needs. Once we come to an agreement
> regarding the sprom data structures, I will begin implementing them. As I see it, conversion will be
> a 3-step process. We will need a patch to add the new structure, a second to populate that
> structure, patches to convert b44, b43, and b43legacy to use the new data, and a final patch to
> remove the old structure. In this manner, bisection will be supported.
cool :)
Are you going to try a redesign of the structure?
I'm not too motivated to do it, as I don't know too much about
the v4 sprom, yet.
--
Greetings Michael.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-11-05 16:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-03 15:19 [RFC] ssb: Add code for SPROM Rev 4 Larry Finger
2007-11-05 12:51 ` Michael Buesch
2007-11-05 16:03 ` Larry Finger
2007-11-05 16:31 ` Michael Buesch
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).