]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/ssb/pci.c
ssb: pci: trivial: correct amount of maximum retries
[linux-2.6.git] / drivers / ssb / pci.c
index 9e50896233aa969e5fa145bcf630dd0ba9055363..a467b20baac8d652ea322daff5b996b07f98072e 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/ssb/ssb.h>
 #include <linux/ssb/ssb_regs.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 
@@ -167,7 +168,7 @@ err_pci:
 }
 
 /* Get the word-offset for a SSB_SPROM_XXX define. */
-#define SPOFF(offset)  (((offset) - SSB_SPROM_BASE) / sizeof(u16))
+#define SPOFF(offset)  ((offset) / sizeof(u16))
 /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
 #define SPEX16(_outvar, _offset, _mask, _shift)        \
        out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
@@ -253,7 +254,7 @@ static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
        int i;
 
        for (i = 0; i < bus->sprom_size; i++)
-               sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2));
+               sprom[i] = ioread16(bus->mmio + bus->sprom_offset + (i * 2));
 
        return 0;
 }
@@ -284,7 +285,7 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
                        ssb_printk("75%%");
                else if (i % 2)
                        ssb_printk(".");
-               writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2));
+               writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
                mmiowb();
                msleep(20);
        }
@@ -405,6 +406,46 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
        out->antenna_gain.ghz5.a3 = gain;
 }
 
+/* Revs 4 5 and 8 have partially shared layout */
+static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
+{
+       SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01,
+            SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT);
+       SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01,
+            SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT);
+       SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23,
+            SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT);
+       SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23,
+            SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT);
+
+       SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01,
+            SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT);
+       SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01,
+            SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT);
+       SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23,
+            SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT);
+       SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23,
+            SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT);
+
+       SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01,
+            SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT);
+       SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01,
+            SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT);
+       SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23,
+            SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT);
+       SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23,
+            SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT);
+
+       SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01,
+            SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT);
+       SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01,
+            SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT);
+       SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23,
+            SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT);
+       SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23,
+            SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT);
+}
+
 static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
 {
        int i;
@@ -427,10 +468,14 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
                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(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
+               SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
        } else {
                SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
                SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
                SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
+               SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
+               SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
        }
        SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
             SSB_SPROM4_ANTAVAIL_A_SHIFT);
@@ -470,6 +515,8 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
        memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
               sizeof(out->antenna_gain.ghz5));
 
+       sprom_extract_r458(out, in);
+
        /* TODO - get remaining rev 4 stuff needed */
 }
 
@@ -560,6 +607,8 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
        memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
               sizeof(out->antenna_gain.ghz5));
 
+       sprom_extract_r458(out, in);
+
        /* TODO - get remaining rev 8 stuff needed */
 }
 
@@ -572,37 +621,34 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
        ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
        memset(out->et0mac, 0xFF, 6);           /* preset et0 and et1 mac */
        memset(out->et1mac, 0xFF, 6);
+
        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;
+               ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision);
+       }
+
+       switch (out->revision) {
+       case 1:
+       case 2:
+       case 3:
                sprom_extract_r123(out, in);
-       } else if (bus->chip_id == 0x4321) {
-               /* the BCM4328 has a chipid == 0x4321 and a rev 4 SPROM */
-               out->revision = 4;
+               break;
+       case 4:
+       case 5:
                sprom_extract_r45(out, in);
-       } else {
-               switch (out->revision) {
-               case 1:
-               case 2:
-               case 3:
-                       sprom_extract_r123(out, in);
-                       break;
-               case 4:
-               case 5:
-                       sprom_extract_r45(out, in);
-                       break;
-               case 8:
-                       sprom_extract_r8(out, in);
-                       break;
-               default:
-                       ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
-                                  "  revision %d detected. Will extract"
-                                  " v1\n", out->revision);
-                       out->revision = 1;
-                       sprom_extract_r123(out, in);
-               }
+               break;
+       case 8:
+               sprom_extract_r8(out, in);
+               break;
+       default:
+               ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
+                          " revision %d detected. Will extract"
+                          " v1\n", out->revision);
+               out->revision = 1;
+               sprom_extract_r123(out, in);
        }
 
        if (out->boardflags_lo == 0xFFFF)
@@ -617,12 +663,34 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
                             struct ssb_sprom *sprom)
 {
        const struct ssb_sprom *fallback;
-       int err = -ENOMEM;
+       int err;
        u16 *buf;
 
+       if (!ssb_is_sprom_available(bus)) {
+               ssb_printk(KERN_ERR PFX "No SPROM available!\n");
+               return -ENODEV;
+       }
+       if (bus->chipco.dev) {  /* can be unavailible! */
+               /*
+                * get SPROM offset: SSB_SPROM_BASE1 except for
+                * chipcommon rev >= 31 or chip ID is 0x4312 and
+                * chipcommon status & 3 == 2
+                */
+               if (bus->chipco.dev->id.revision >= 31)
+                       bus->sprom_offset = SSB_SPROM_BASE31;
+               else if (bus->chip_id == 0x4312 &&
+                        (bus->chipco.status & 0x03) == 2)
+                       bus->sprom_offset = SSB_SPROM_BASE31;
+               else
+                       bus->sprom_offset = SSB_SPROM_BASE1;
+       } else {
+               bus->sprom_offset = SSB_SPROM_BASE1;
+       }
+       ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
+
        buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
        if (!buf)
-               goto out;
+               return -ENOMEM;
        bus->sprom_size = SSB_SPROMSIZE_WORDS_R123;
        sprom_do_read(bus, buf);
        err = sprom_check_crc(buf, bus->sprom_size);
@@ -632,7 +700,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
                buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
                              GFP_KERNEL);
                if (!buf)
-                       goto out;
+                       return -ENOMEM;
                bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
                sprom_do_read(bus, buf);
                err = sprom_check_crc(buf, bus->sprom_size);
@@ -654,7 +722,6 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
 
 out_free:
        kfree(buf);
-out:
        return err;
 }