b43legacy: fix initvals loading on bcm4303
[sfrench/cifs-2.6.git] / drivers / net / wireless / b43legacy / main.c
index 2d5735ddad8cca63176ab332b0e815f8ea256f4e..0f7a6e7bd96a74fad4172f547bfbe7dc75a0bfe7 100644 (file)
@@ -3,7 +3,7 @@
  *  Broadcom B43legacy wireless driver
  *
  *  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
- *  Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
+ *  Copyright (c) 2005-2008 Stefano Brivio <stefano.brivio@polimi.it>
  *  Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
  *  Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
  *  Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -60,6 +60,8 @@ MODULE_AUTHOR("Stefano Brivio");
 MODULE_AUTHOR("Michael Buesch");
 MODULE_LICENSE("GPL");
 
+MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID);
+
 #if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO)
 static int modparam_pio;
 module_param_named(pio, modparam_pio, int, 0444);
@@ -225,8 +227,8 @@ static void b43legacy_ram_write(struct b43legacy_wldev *dev, u16 offset,
 
        B43legacy_WARN_ON(offset % 4 != 0);
 
-       status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-       if (status & B43legacy_SBF_XFER_REG_BYTESWAP)
+       status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+       if (status & B43legacy_MACCTL_BE)
                val = swab32(val);
 
        b43legacy_write32(dev, B43legacy_MMIO_RAM_CONTROL, offset);
@@ -434,9 +436,9 @@ static void b43legacy_time_lock(struct b43legacy_wldev *dev)
 {
        u32 status;
 
-       status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-       status |= B43legacy_SBF_TIME_UPDATE;
-       b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+       status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+       status |= B43legacy_MACCTL_TBTTHOLD;
+       b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
        mmiowb();
 }
 
@@ -444,9 +446,9 @@ static void b43legacy_time_unlock(struct b43legacy_wldev *dev)
 {
        u32 status;
 
-       status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-       status &= ~B43legacy_SBF_TIME_UPDATE;
-       b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+       status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+       status &= ~B43legacy_MACCTL_TBTTHOLD;
+       b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
 }
 
 static void b43legacy_tsf_write_locked(struct b43legacy_wldev *dev, u64 tsf)
@@ -647,7 +649,7 @@ void b43legacy_dummy_transmission(struct b43legacy_wldev *dev)
                b43legacy_ram_write(dev, i * 4, buffer[i]);
 
        /* dummy read follows */
-       b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+       b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
 
        b43legacy_write16(dev, 0x0568, 0x0000);
        b43legacy_write16(dev, 0x07C0, 0x0000);
@@ -794,9 +796,9 @@ static void b43legacy_jssi_write(struct b43legacy_wldev *dev, u32 jssi)
 static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev)
 {
        b43legacy_jssi_write(dev, 0x7F7F7F7F);
-       b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
+       b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
                          b43legacy_read32(dev,
-                         B43legacy_MMIO_STATUS2_BITFIELD)
+                         B43legacy_MMIO_MACCMD)
                          | (1 << 4));
        B43legacy_WARN_ON(dev->noisecalc.channel_at_start !=
                            dev->phy.channel);
@@ -895,8 +897,8 @@ static void handle_irq_atim_end(struct b43legacy_wldev *dev)
 {
        if (!dev->reg124_set_0x4) /*FIXME rename this variable*/
                return;
-       b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
-                         b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD)
+       b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+                         b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
                          | 0x4);
 }
 
@@ -1106,9 +1108,9 @@ static void b43legacy_update_templates(struct b43legacy_wldev *dev)
        b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
                                            B43legacy_CCK_RATE_11MB);
 
-       status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD);
+       status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
        status |= 0x03;
-       b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, status);
+       b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status);
 }
 
 static void b43legacy_refresh_templates(struct b43legacy_wldev *dev,
@@ -1166,7 +1168,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
                return;
 
        dev->irq_savedstate &= ~B43legacy_IRQ_BEACON;
-       status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD);
+       status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
 
        if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {
                /* ACK beacon IRQ. */
@@ -1182,14 +1184,14 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
                b43legacy_write_beacon_template(dev, 0x68, 0x18,
                                                B43legacy_CCK_RATE_1MB);
                status |= 0x1;
-               b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
+               b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
                                  status);
        }
        if (!(status & 0x2)) {
                b43legacy_write_beacon_template(dev, 0x468, 0x1A,
                                                B43legacy_CCK_RATE_1MB);
                status |= 0x2;
-               b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
+               b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
                                  status);
        }
 }
@@ -1486,6 +1488,7 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
        }
        if (!fw->initvals) {
                switch (dev->phy.type) {
+               case B43legacy_PHYTYPE_B:
                case B43legacy_PHYTYPE_G:
                        if ((rev >= 5) && (rev <= 10))
                                filename = "b0g0initvals5";
@@ -1503,6 +1506,7 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
        }
        if (!fw->initvals_band) {
                switch (dev->phy.type) {
+               case B43legacy_PHYTYPE_B:
                case B43legacy_PHYTYPE_G:
                        if ((rev >= 5) && (rev <= 10))
                                filename = "b0g0bsinitvals5";
@@ -1548,9 +1552,20 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
        u16 fwpatch;
        u16 fwdate;
        u16 fwtime;
-       u32 tmp;
+       u32 tmp, macctl;
        int err = 0;
 
+       /* Jump the microcode PSM to offset 0 */
+       macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+       B43legacy_WARN_ON(macctl & B43legacy_MACCTL_PSM_RUN);
+       macctl |= B43legacy_MACCTL_PSM_JMP0;
+       b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+       /* Zero out all microcode PSM registers and shared memory. */
+       for (i = 0; i < 64; i++)
+               b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, i, 0);
+       for (i = 0; i < 4096; i += 2)
+               b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, i, 0);
+
        /* Upload Microcode. */
        data = (__be32 *) (dev->fw.ucode->data + hdr_len);
        len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32);
@@ -1581,7 +1596,12 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
 
        b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
                          B43legacy_IRQ_ALL);
-       b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0x00020402);
+
+       /* Start the microcode PSM */
+       macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+       macctl &= ~B43legacy_MACCTL_PSM_JMP0;
+       macctl |= B43legacy_MACCTL_PSM_RUN;
+       b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
 
        /* Wait for the microcode to load and respond */
        i = 0;
@@ -1594,9 +1614,13 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
                        b43legacyerr(dev->wl, "Microcode not responding\n");
                        b43legacy_print_fw_helptext(dev->wl);
                        err = -ENODEV;
-                       goto out;
+                       goto error;
+               }
+               msleep_interruptible(50);
+               if (signal_pending(current)) {
+                       err = -EINTR;
+                       goto error;
                }
-               udelay(10);
        }
        /* dummy read follows */
        b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
@@ -1617,19 +1641,26 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
                             " is supported. You must change your firmware"
                             " files.\n");
                b43legacy_print_fw_helptext(dev->wl);
-               b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0);
                err = -EOPNOTSUPP;
-               goto out;
+               goto error;
        }
-       b43legacydbg(dev->wl, "Loading firmware version 0x%X, patch level %u "
-              "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch,
-              (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF,
-              (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F);
+       b43legacyinfo(dev->wl, "Loading firmware version 0x%X, patch level %u "
+                     "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch,
+                     (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF,
+                     (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F,
+                     fwtime & 0x1F);
 
        dev->fw.rev = fwrev;
        dev->fw.patch = fwpatch;
 
-out:
+       return 0;
+
+error:
+       macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+       macctl &= ~B43legacy_MACCTL_PSM_RUN;
+       macctl |= B43legacy_MACCTL_PSM_JMP0;
+       b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+
        return err;
 }
 
@@ -1736,9 +1767,9 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
        u32 mask;
        u32 set;
 
-       b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
+       b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
                          b43legacy_read32(dev,
-                         B43legacy_MMIO_STATUS_BITFIELD)
+                         B43legacy_MMIO_MACCTL)
                          & 0xFFFF3FFF);
 
        b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
@@ -1798,14 +1829,14 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev)
        B43legacy_WARN_ON(dev->mac_suspended < 0);
        B43legacy_WARN_ON(irqs_disabled());
        if (dev->mac_suspended == 0) {
-               b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
+               b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
                                  b43legacy_read32(dev,
-                                 B43legacy_MMIO_STATUS_BITFIELD)
-                                 | B43legacy_SBF_MAC_ENABLED);
+                                 B43legacy_MMIO_MACCTL)
+                                 | B43legacy_MACCTL_ENABLED);
                b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
                                  B43legacy_IRQ_MAC_SUSPENDED);
                /* the next two are dummy reads */
-               b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+               b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
                b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
                b43legacy_power_saving_ctl_bits(dev, -1, -1);
 
@@ -1836,10 +1867,10 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev)
                dev->irq_savedstate = tmp;
 
                b43legacy_power_saving_ctl_bits(dev, -1, 1);
-               b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
+               b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
                                  b43legacy_read32(dev,
-                                 B43legacy_MMIO_STATUS_BITFIELD)
-                                 & ~B43legacy_SBF_MAC_ENABLED);
+                                 B43legacy_MMIO_MACCTL)
+                                 & ~B43legacy_MACCTL_ENABLED);
                b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
                for (i = 40; i; i--) {
                        tmp = b43legacy_read32(dev,
@@ -2007,12 +2038,15 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
        struct b43legacy_phy *phy = &dev->phy;
        int err;
        int tmp;
-       u32 value32;
+       u32 value32, macctl;
        u16 value16;
 
-       b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
-                         B43legacy_SBF_CORE_READY
-                         | B43legacy_SBF_400);
+       /* Initialize the MAC control */
+       macctl = B43legacy_MACCTL_IHR_ENABLED | B43legacy_MACCTL_SHM_ENABLED;
+       if (dev->phy.gmode)
+               macctl |= B43legacy_MACCTL_GMODE;
+       macctl |= B43legacy_MACCTL_INFRA;
+       b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
 
        err = b43legacy_request_firmware(dev);
        if (err)
@@ -2052,12 +2086,12 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
        if (dev->dev->id.revision < 5)
                b43legacy_write32(dev, 0x010C, 0x01000000);
 
-       value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-       value32 &= ~B43legacy_SBF_MODE_NOTADHOC;
-       b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32);
-       value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
-       value32 |= B43legacy_SBF_MODE_NOTADHOC;
-       b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32);
+       value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+       value32 &= ~B43legacy_MACCTL_INFRA;
+       b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32);
+       value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+       value32 |= B43legacy_MACCTL_INFRA;
+       b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32);
 
        if (b43legacy_using_pio(dev)) {
                b43legacy_write32(dev, 0x0210, 0x00000100);
@@ -2847,8 +2881,6 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
        memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
        memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
 
-       /* Flags */
-       phy->locked = 0;
        /* Assume the radio is enabled. If it's not enabled, the state will
         * immediately get fixed on the first periodic work run. */
        dev->radio_hw_enable = 1;
@@ -2881,7 +2913,6 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
        phy->lofcal = 0xFFFF;
        phy->initval = 0xFFFF;
 
-       spin_lock_init(&phy->lock);
        phy->interfmode = B43legacy_INTERFMODE_NONE;
        phy->channel = 0xFF;
 }
@@ -2954,12 +2985,19 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
 {
        struct b43legacy_wl *wl = dev->wl;
        struct b43legacy_phy *phy = &dev->phy;
+       u32 macctl;
 
        B43legacy_WARN_ON(b43legacy_status(dev) > B43legacy_STAT_INITIALIZED);
        if (b43legacy_status(dev) != B43legacy_STAT_INITIALIZED)
                return;
        b43legacy_set_status(dev, B43legacy_STAT_UNINIT);
 
+       /* Stop the microcode PSM. */
+       macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+       macctl &= ~B43legacy_MACCTL_PSM_RUN;
+       macctl |= B43legacy_MACCTL_PSM_JMP0;
+       b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+
        mutex_unlock(&wl->mutex);
        /* Must unlock as it would otherwise deadlock. No races here.
         * Cancel possibly pending workqueues. */
@@ -3013,7 +3051,6 @@ static void prepare_phy_data_for_init(struct b43legacy_wldev *dev)
 
        /* Flags */
        phy->calibrated = 0;
-       phy->locked = 0;
 
        if (phy->_lo_pairs)
                memset(phy->_lo_pairs, 0,
@@ -3128,8 +3165,6 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
        b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4);
 
        ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
-       memset(wl->bssid, 0, ETH_ALEN);
-       memset(wl->mac_addr, 0, ETH_ALEN);
        b43legacy_upload_card_macaddress(dev);
        b43legacy_security_init(dev);
        b43legacy_rng_init(wl);
@@ -3225,17 +3260,27 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
        struct b43legacy_wldev *dev = wl->current_dev;
        int did_init = 0;
        int err = 0;
+       bool do_rfkill_exit = 0;
 
        /* First register RFkill.
         * LEDs that are registered later depend on it. */
        b43legacy_rfkill_init(dev);
 
+       /* Kill all old instance specific information to make sure
+        * the card won't use it in the short timeframe between start
+        * and mac80211 reconfiguring it. */
+       memset(wl->bssid, 0, ETH_ALEN);
+       memset(wl->mac_addr, 0, ETH_ALEN);
+       wl->filter_flags = 0;
+
        mutex_lock(&wl->mutex);
 
        if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
                err = b43legacy_wireless_core_init(dev);
-               if (err)
+               if (err) {
+                       do_rfkill_exit = 1;
                        goto out_mutex_unlock;
+               }
                did_init = 1;
        }
 
@@ -3244,6 +3289,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
                if (err) {
                        if (did_init)
                                b43legacy_wireless_core_exit(dev);
+                       do_rfkill_exit = 1;
                        goto out_mutex_unlock;
                }
        }
@@ -3251,6 +3297,9 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
 out_mutex_unlock:
        mutex_unlock(&wl->mutex);
 
+       if (do_rfkill_exit)
+               b43legacy_rfkill_exit(dev);
+
        return err;
 }
 
@@ -3762,6 +3811,32 @@ static struct ssb_driver b43legacy_ssb_driver = {
        .resume         = b43legacy_resume,
 };
 
+static void b43legacy_print_driverinfo(void)
+{
+       const char *feat_pci = "", *feat_leds = "", *feat_rfkill = "",
+                  *feat_pio = "", *feat_dma = "";
+
+#ifdef CONFIG_B43LEGACY_PCI_AUTOSELECT
+       feat_pci = "P";
+#endif
+#ifdef CONFIG_B43LEGACY_LEDS
+       feat_leds = "L";
+#endif
+#ifdef CONFIG_B43LEGACY_RFKILL
+       feat_rfkill = "R";
+#endif
+#ifdef CONFIG_B43LEGACY_PIO
+       feat_pio = "I";
+#endif
+#ifdef CONFIG_B43LEGACY_DMA
+       feat_dma = "D";
+#endif
+       printk(KERN_INFO "Broadcom 43xx-legacy driver loaded "
+              "[ Features: %s%s%s%s%s, Firmware-ID: "
+              B43legacy_SUPPORTED_FIRMWARE_ID " ]\n",
+              feat_pci, feat_leds, feat_rfkill, feat_pio, feat_dma);
+}
+
 static int __init b43legacy_init(void)
 {
        int err;
@@ -3772,6 +3847,8 @@ static int __init b43legacy_init(void)
        if (err)
                goto err_dfs_exit;
 
+       b43legacy_print_driverinfo();
+
        return err;
 
 err_dfs_exit: