diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/bluetooth/ath3k.c | 29 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_drv.h | 1 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_main.c | 24 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.c | 16 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 34 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 50 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_n.c | 347 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sdio.c | 1 |
8 files changed, 362 insertions, 140 deletions
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 230c552daf9..a0d7355ef12 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -27,6 +27,7 @@ #include <linux/device.h> #include <linux/firmware.h> #include <linux/usb.h> +#include <asm/unaligned.h> #include <net/bluetooth/bluetooth.h> #define VERSION "1.0" @@ -50,12 +51,12 @@ #define ATH3K_NAME_LEN 0xFF struct ath3k_version { - unsigned int rom_version; - unsigned int build_version; - unsigned int ram_version; - unsigned char ref_clock; - unsigned char reserved[0x07]; -}; + __le32 rom_version; + __le32 build_version; + __le32 ram_version; + __u8 ref_clock; + __u8 reserved[7]; +} __packed; static const struct usb_device_id ath3k_table[] = { /* Atheros AR3011 */ @@ -349,7 +350,8 @@ static int ath3k_load_patch(struct usb_device *udev) unsigned char fw_state; char filename[ATH3K_NAME_LEN] = {0}; const struct firmware *firmware; - struct ath3k_version fw_version, pt_version; + struct ath3k_version fw_version; + __u32 pt_rom_version, pt_build_version; int ret; ret = ath3k_get_state(udev, &fw_state); @@ -370,7 +372,7 @@ static int ath3k_load_patch(struct usb_device *udev) } snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu", - le32_to_cpu(fw_version.rom_version)); + le32_to_cpu(fw_version.rom_version)); ret = request_firmware(&firmware, filename, &udev->dev); if (ret < 0) { @@ -378,12 +380,13 @@ static int ath3k_load_patch(struct usb_device *udev) return ret; } - pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8); - pt_version.build_version = *(int *) - (firmware->data + firmware->size - 4); + pt_rom_version = get_unaligned_le32(firmware->data + + firmware->size - 8); + pt_build_version = get_unaligned_le32(firmware->data + + firmware->size - 4); - if ((pt_version.rom_version != fw_version.rom_version) || - (pt_version.build_version <= fw_version.build_version)) { + if (pt_rom_version != le32_to_cpu(fw_version.rom_version) || + pt_build_version <= le32_to_cpu(fw_version.build_version)) { BT_ERR("Patch file version did not match with firmware"); release_firmware(firmware); return -EINVAL; diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index caf684119a4..38ad66289ad 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -91,6 +91,7 @@ struct btmrvl_private { /* Vendor specific Bluetooth commands */ #define BT_CMD_PSCAN_WIN_REPORT_ENABLE 0xFC03 +#define BT_CMD_SET_BDADDR 0xFC22 #define BT_CMD_AUTO_SLEEP_MODE 0xFC23 #define BT_CMD_HOST_SLEEP_CONFIG 0xFC59 #define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index cc65fd2fe85..bae8e6a0ecf 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -539,6 +539,29 @@ static int btmrvl_setup(struct hci_dev *hdev) return 0; } +static int btmrvl_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) +{ + struct sk_buff *skb; + long ret; + u8 buf[8]; + + buf[0] = MRVL_VENDOR_PKT; + buf[1] = sizeof(bdaddr_t); + memcpy(buf + 2, bdaddr, sizeof(bdaddr_t)); + + skb = __hci_cmd_sync(hdev, BT_CMD_SET_BDADDR, sizeof(buf), buf, + HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + ret = PTR_ERR(skb); + BT_ERR("%s: changing btmrvl device address failed (%ld)", + hdev->name, ret); + return ret; + } + kfree_skb(skb); + + return 0; +} + /* * This function handles the event generated by firmware, rx data * received from firmware, and tx data sent from kernel. @@ -632,6 +655,7 @@ int btmrvl_register_hdev(struct btmrvl_private *priv) hdev->flush = btmrvl_flush; hdev->send = btmrvl_send_frame; hdev->setup = btmrvl_setup; + hdev->set_bdaddr = btmrvl_set_bdaddr; hdev->dev_type = priv->btmrvl_dev.dev_type; diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index efff06438b0..3e683b15325 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -1169,6 +1169,10 @@ static int btmrvl_sdio_suspend(struct device *dev) } priv = card->priv; + hcidev = priv->btmrvl_dev.hcidev; + BT_DBG("%s: SDIO suspend", hcidev->name); + hci_suspend_dev(hcidev); + skb_queue_purge(&priv->adapter->tx_queue); if (priv->adapter->hs_state != HS_ACTIVATED) { if (btmrvl_enable_hs(priv)) { @@ -1176,10 +1180,6 @@ static int btmrvl_sdio_suspend(struct device *dev) return -EBUSY; } } - hcidev = priv->btmrvl_dev.hcidev; - BT_DBG("%s: SDIO suspend", hcidev->name); - hci_suspend_dev(hcidev); - skb_queue_purge(&priv->adapter->tx_queue); priv->adapter->is_suspended = true; @@ -1221,13 +1221,13 @@ static int btmrvl_sdio_resume(struct device *dev) return 0; } - priv->adapter->is_suspended = false; - hcidev = priv->btmrvl_dev.hcidev; - BT_DBG("%s: SDIO resume", hcidev->name); - hci_resume_dev(hcidev); priv->hw_wakeup_firmware(priv); priv->adapter->hs_state = HS_DEACTIVATED; + hcidev = priv->btmrvl_dev.hcidev; BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name); + priv->adapter->is_suspended = false; + BT_DBG("%s: SDIO resume", hcidev->name); + hci_resume_dev(hcidev); return 0; } diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index ed7b33b06b4..292c38e8aa1 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -48,6 +48,7 @@ static struct usb_driver btusb_driver; #define BTUSB_INTEL 0x100 #define BTUSB_INTEL_BOOT 0x200 #define BTUSB_BCM_PATCHRAM 0x400 +#define BTUSB_MARVELL 0x800 static const struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -113,6 +114,9 @@ static const struct usb_device_id btusb_table[] = { { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01), .driver_info = BTUSB_BCM_PATCHRAM }, + /* ASUSTek Computer - Broadcom based */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01) }, + /* Belkin F8065bf - Broadcom based */ { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) }, @@ -242,6 +246,10 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, + /* Marvell device */ + { USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL }, + { USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL }, + { } /* Terminating entry */ }; @@ -1455,6 +1463,29 @@ static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr) return 0; } +static int btusb_set_bdaddr_marvell(struct hci_dev *hdev, + const bdaddr_t *bdaddr) +{ + struct sk_buff *skb; + u8 buf[8]; + long ret; + + buf[0] = 0xfe; + buf[1] = sizeof(bdaddr_t); + memcpy(buf + 2, bdaddr, sizeof(bdaddr_t)); + + skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(buf), buf, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + ret = PTR_ERR(skb); + BT_ERR("%s: changing Marvell device address failed (%ld)", + hdev->name, ret); + return ret; + } + kfree_skb(skb); + + return 0; +} + #define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}}) static int btusb_setup_bcm_patchram(struct hci_dev *hdev) @@ -1766,6 +1797,9 @@ static int btusb_probe(struct usb_interface *intf, hdev->set_bdaddr = btusb_set_bdaddr_intel; } + if (id->driver_info & BTUSB_MARVELL) + hdev->set_bdaddr = btusb_set_bdaddr_marvell; + if (id->driver_info & BTUSB_INTEL_BOOT) set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 3e127be06bf..47b6fa5fa5b 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4385,8 +4385,9 @@ static int b43_phy_versioning(struct b43_wldev *dev) u8 phy_type; u8 phy_rev; u16 radio_manuf; - u16 radio_ver; + u16 radio_id; u16 radio_rev; + u8 radio_ver; int unsupported = 0; /* Get PHY versioning */ @@ -4452,7 +4453,9 @@ static int b43_phy_versioning(struct b43_wldev *dev) radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA); b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1); - radio_ver = b43_read16(dev, B43_MMIO_RADIO24_DATA); + radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA); + + radio_ver = 0; /* Is there version somewhere? */ } else if (core_rev >= 24) { u16 radio24[3]; @@ -4461,12 +4464,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA); } - /* Broadcom uses "id" for our "ver" and has separated "ver" */ - /* radio_ver = (radio24[0] & 0xF0) >> 4; */ - radio_manuf = 0x17F; - radio_ver = (radio24[2] << 8) | radio24[1]; + radio_id = (radio24[2] << 8) | radio24[1]; radio_rev = (radio24[0] & 0xF); + radio_ver = (radio24[0] & 0xF0) >> 4; } else { if (dev->dev->chip_id == 0x4317) { if (dev->dev->chip_rev == 0) @@ -4485,15 +4486,16 @@ static int b43_phy_versioning(struct b43_wldev *dev) << 16; } radio_manuf = (tmp & 0x00000FFF); - radio_ver = (tmp & 0x0FFFF000) >> 12; + radio_id = (tmp & 0x0FFFF000) >> 12; radio_rev = (tmp & 0xF0000000) >> 28; + radio_ver = 0; /* Probably not available on old hw */ } if (radio_manuf != 0x17F /* Broadcom */) unsupported = 1; switch (phy_type) { case B43_PHYTYPE_A: - if (radio_ver != 0x2060) + if (radio_id != 0x2060) unsupported = 1; if (radio_rev != 1) unsupported = 1; @@ -4501,30 +4503,31 @@ static int b43_phy_versioning(struct b43_wldev *dev) unsupported = 1; break; case B43_PHYTYPE_B: - if ((radio_ver & 0xFFF0) != 0x2050) + if ((radio_id & 0xFFF0) != 0x2050) unsupported = 1; break; case B43_PHYTYPE_G: - if (radio_ver != 0x2050) + if (radio_id != 0x2050) unsupported = 1; break; case B43_PHYTYPE_N: - if (radio_ver != 0x2055 && radio_ver != 0x2056 && - radio_ver != 0x2057) + if (radio_id != 0x2055 && radio_id != 0x2056 && + radio_id != 0x2057) unsupported = 1; - if (radio_ver == 0x2057 && !(radio_rev == 9)) + if (radio_id == 0x2057 && + !(radio_rev == 9 || radio_rev == 14)) unsupported = 1; break; case B43_PHYTYPE_LP: - if (radio_ver != 0x2062 && radio_ver != 0x2063) + if (radio_id != 0x2062 && radio_id != 0x2063) unsupported = 1; break; case B43_PHYTYPE_HT: - if (radio_ver != 0x2059) + if (radio_id != 0x2059) unsupported = 1; break; case B43_PHYTYPE_LCN: - if (radio_ver != 0x2064) + if (radio_id != 0x2064) unsupported = 1; break; default: @@ -4532,15 +4535,17 @@ static int b43_phy_versioning(struct b43_wldev *dev) } if (unsupported) { b43err(dev->wl, - "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u)\n", - radio_manuf, radio_ver, radio_rev); + "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u, Version %u)\n", + radio_manuf, radio_id, radio_rev, radio_ver); return -EOPNOTSUPP; } - b43info(dev->wl, "Found Radio: Manuf 0x%X, ID 0x%X, Revision %u\n", - radio_manuf, radio_ver, radio_rev); + b43info(dev->wl, + "Found Radio: Manuf 0x%X, ID 0x%X, Revision %u, Version %u\n", + radio_manuf, radio_id, radio_rev, radio_ver); + /* FIXME: b43 treats "id" as "ver" and ignores the real "ver" */ phy->radio_manuf = radio_manuf; - phy->radio_ver = radio_ver; + phy->radio_ver = radio_id; phy->radio_rev = radio_rev; phy->analog = analog_type; @@ -5152,7 +5157,8 @@ static int b43_setup_bands(struct b43_wldev *dev, bool limited_2g; /* We don't support all 2 GHz channels on some devices */ - limited_2g = phy->radio_ver == 0x2057 && phy->radio_rev == 9; + limited_2g = phy->radio_ver == 0x2057 && + (phy->radio_rev == 9 || phy->radio_rev == 14); if (have_2ghz_phy) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = limited_2g ? diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 92bfe352ba0..11d754360d7 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -2708,25 +2708,39 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) struct ssb_sprom *sprom = dev->dev->bus_sprom; struct b43_phy *phy = &dev->phy; + /* TX to RX */ + u8 tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, }; + u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, }; + /* RX to TX */ u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, 0x1F }; u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; - u16 ntab7_15e_16e[] = { 0x10f, 0x10f }; + static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f }; u8 ntab7_138_146[] = { 0x11, 0x11 }; u8 ntab7_133[] = { 0x77, 0x11, 0x11 }; - u16 lpf_20, lpf_40, lpf_11b; - u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40; - u16 scap_val, scap_val_11b, scap_val_11n_20, scap_val_11n_40; + u16 lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2]; + u16 bcap_val; + s16 bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2]; + u16 scap_val; + s16 scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2]; bool rccal_ovrd = false; - u16 rx2tx_lut_20_11b, rx2tx_lut_20_11n, rx2tx_lut_40_11n; u16 bias, conv, filt; + u32 noise_tbl[2]; + u32 tmp32; u8 core; + b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125); + b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01b3); + b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105); + b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016e); + b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00cd); + b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020); + if (phy->rev == 7) { b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10); b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020); @@ -2746,11 +2760,18 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040); b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000); } - if (phy->rev <= 8) { + + if (phy->rev >= 16) { + b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x7ff); + b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x7ff); + } else if (phy->rev <= 8) { b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0); b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0); } - if (phy->rev >= 8) + + if (phy->rev >= 16) + b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0xa0); + else if (phy->rev >= 8) b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72); b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2); @@ -2758,9 +2779,11 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); tmp32 &= 0xffffff; b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); - b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15e), 2, ntab7_15e_16e); - b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16e), 2, ntab7_15e_16e); + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15d), 3, ntab7_15e_16e); + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16d), 3, ntab7_15e_16e); + b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, + ARRAY_SIZE(tx2rx_events)); if (b43_nphy_ipa(dev)) b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa, rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa)); @@ -2768,84 +2791,176 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000); b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000); - lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154); - lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159); - lpf_11b = b43_nphy_read_lpf_ctl(dev, 0x152); + for (core = 0; core < 2; core++) { + lpf_ofdm_20mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x154 + core * 0x10); + lpf_ofdm_40mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x159 + core * 0x10); + lpf_11b[core] = b43_nphy_read_lpf_ctl(dev, 0x152 + core * 0x10); + } + + bcap_val = b43_radio_read(dev, R2057_RCCAL_BCAP_VAL); + scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL); + if (b43_nphy_ipa(dev)) { - if ((phy->radio_rev == 5 && b43_is_40mhz(dev)) || - phy->radio_rev == 7 || phy->radio_rev == 8) { - bcap_val = b43_radio_read(dev, 0x16b); - scap_val = b43_radio_read(dev, 0x16a); - scap_val_11b = scap_val; - bcap_val_11b = bcap_val; - if (phy->radio_rev == 5 && b43_is_40mhz(dev)) { - scap_val_11n_20 = scap_val; - bcap_val_11n_20 = bcap_val; - scap_val_11n_40 = bcap_val_11n_40 = 0xc; + bool ghz2 = b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ; + + switch (phy->radio_rev) { + case 5: + /* Check radio version (to be 0) by PHY rev for now */ + if (phy->rev == 8 && b43_is_40mhz(dev)) { + for (core = 0; core < 2; core++) { + scap_val_11b[core] = scap_val; + bcap_val_11b[core] = bcap_val; + scap_val_11n_20[core] = scap_val; + bcap_val_11n_20[core] = bcap_val; + scap_val_11n_40[core] = 0xc; + bcap_val_11n_40[core] = 0xc; + } + rccal_ovrd = true; - } else { /* Rev 7/8 */ - lpf_20 = 4; - lpf_11b = 1; + } + if (phy->rev == 9) { + /* TODO: Radio version 1 (e.g. BCM5357B0) */ + } + break; + case 7: + case 8: + for (core = 0; core < 2; core++) { + scap_val_11b[core] = scap_val; + bcap_val_11b[core] = bcap_val; + lpf_ofdm_20mhz[core] = 4; + lpf_11b[core] = 1; if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - scap_val_11n_20 = 0xc; - bcap_val_11n_20 = 0xc; - scap_val_11n_40 = 0xa; - bcap_val_11n_40 = 0xa; + scap_val_11n_20[core] = 0xc; + bcap_val_11n_20[core] = 0xc; + scap_val_11n_40[core] = 0xa; + bcap_val_11n_40[core] = 0xa; } else { - scap_val_11n_20 = 0x14; - bcap_val_11n_20 = 0x14; - scap_val_11n_40 = 0xf; - bcap_val_11n_40 = 0xf; + scap_val_11n_20[core] = 0x14; + bcap_val_11n_20[core] = 0x14; + scap_val_11n_40[core] = 0xf; + bcap_val_11n_40[core] = 0xf; } - rccal_ovrd = true; } + + rccal_ovrd = true; + break; + case 9: + for (core = 0; core < 2; core++) { + bcap_val_11b[core] = bcap_val; + scap_val_11b[core] = scap_val; + lpf_11b[core] = 1; + + if (ghz2) { + bcap_val_11n_20[core] = bcap_val + 13; + scap_val_11n_20[core] = scap_val + 15; + } else { + bcap_val_11n_20[core] = bcap_val + 14; + scap_val_11n_20[core] = scap_val + 15; + } + lpf_ofdm_20mhz[core] = 4; + + if (ghz2) { + bcap_val_11n_40[core] = bcap_val - 7; + scap_val_11n_40[core] = scap_val - 5; + } else { + bcap_val_11n_40[core] = bcap_val + 2; + scap_val_11n_40[core] = scap_val + 4; + } + lpf_ofdm_40mhz[core] = 4; + } + + rccal_ovrd = true; + break; + case 14: + for (core = 0; core < 2; core++) { + bcap_val_11b[core] = bcap_val; + scap_val_11b[core] = scap_val; + lpf_11b[core] = 1; + } + + bcap_val_11n_20[0] = bcap_val + 20; + scap_val_11n_20[0] = scap_val + 20; + lpf_ofdm_20mhz[0] = 3; + + bcap_val_11n_20[1] = bcap_val + 16; + scap_val_11n_20[1] = scap_val + 16; + lpf_ofdm_20mhz[1] = 3; + + bcap_val_11n_40[0] = bcap_val + 20; + scap_val_11n_40[0] = scap_val + 20; + lpf_ofdm_40mhz[0] = 4; + + bcap_val_11n_40[1] = bcap_val + 10; + scap_val_11n_40[1] = scap_val + 10; + lpf_ofdm_40mhz[1] = 4; + + rccal_ovrd = true; + break; } } else { if (phy->radio_rev == 5) { - lpf_20 = 1; - lpf_40 = 3; - bcap_val = b43_radio_read(dev, 0x16b); - scap_val = b43_radio_read(dev, 0x16a); - scap_val_11b = scap_val; - bcap_val_11b = bcap_val; - scap_val_11n_20 = 0x11; - scap_val_11n_40 = 0x11; - bcap_val_11n_20 = 0x13; - bcap_val_11n_40 = 0x13; + for (core = 0; core < 2; core++) { + lpf_ofdm_20mhz[core] = 1; + lpf_ofdm_40mhz[core] = 3; + scap_val_11b[core] = scap_val; + bcap_val_11b[core] = bcap_val; + scap_val_11n_20[core] = 0x11; + scap_val_11n_40[core] = 0x11; + bcap_val_11n_20[core] = 0x13; + bcap_val_11n_40[core] = 0x13; + } + rccal_ovrd = true; } } if (rccal_ovrd) { - rx2tx_lut_20_11b = (bcap_val_11b << 8) | - (scap_val_11b << 3) | - lpf_11b; - rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) | - (scap_val_11n_20 << 3) | - lpf_20; - rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) | - (scap_val_11n_40 << 3) | - lpf_40; + u16 rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2]; + u8 rx2tx_lut_extra = 1; + + for (core = 0; core < 2; core++) { + bcap_val_11b[core] = clamp_val(bcap_val_11b[core], 0, 0x1f); + scap_val_11b[core] = clamp_val(scap_val_11b[core], 0, 0x1f); + bcap_val_11n_20[core] = clamp_val(bcap_val_11n_20[core], 0, 0x1f); + scap_val_11n_20[core] = clamp_val(scap_val_11n_20[core], 0, 0x1f); + bcap_val_11n_40[core] = clamp_val(bcap_val_11n_40[core], 0, 0x1f); + scap_val_11n_40[core] = clamp_val(scap_val_11n_40[core], 0, 0x1f); + + rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) | + (bcap_val_11b[core] << 8) | + (scap_val_11b[core] << 3) | + lpf_11b[core]; + rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) | + (bcap_val_11n_20[core] << 8) | + (scap_val_11n_20[core] << 3) | + lpf_ofdm_20mhz[core]; + rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) | + (bcap_val_11n_40[core] << 8) | + (scap_val_11n_40[core] << 3) | + lpf_ofdm_40mhz[core]; + } + for (core = 0; core < 2; core++) { b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16), - rx2tx_lut_20_11b); + rx2tx_lut_20_11b[core]); b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16), - rx2tx_lut_20_11n); + rx2tx_lut_20_11n[core]); b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16), - rx2tx_lut_20_11n); + rx2tx_lut_20_11n[core]); b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16), - rx2tx_lut_40_11n); + rx2tx_lut_40_11n[core]); b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16), - rx2tx_lut_40_11n); + rx2tx_lut_40_11n[core]); b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16), - rx2tx_lut_40_11n); + rx2tx_lut_40_11n[core]); b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16), - rx2tx_lut_40_11n); + rx2tx_lut_40_11n[core]); b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16), - rx2tx_lut_40_11n); + rx2tx_lut_40_11n[core]); } - b43_nphy_rf_ctl_override_rev7(dev, 16, 1, 3, false, 2); } + b43_phy_write(dev, 0x32F, 0x3); + if (phy->radio_rev == 4 || phy->radio_rev == 6) b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0); @@ -2893,7 +3008,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) 0x7f); } } - if (phy->radio_rev == 3) { + switch (phy->radio_rev) { + case 3: for (core = 0; core < 2; core++) { if (core == 0) { b43_radio_write(dev, 0x64, @@ -2919,7 +3035,9 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) 0x3E); } } - } else if (phy->radio_rev == 7 || phy->radio_rev == 8) { + break; + case 7: + case 8: if (!b43_is_40mhz(dev)) { b43_radio_write(dev, 0x5F, 0x14); b43_radio_write(dev, 0xE8, 0x12); @@ -2927,6 +3045,21 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) b43_radio_write(dev, 0x5F, 0x16); b43_radio_write(dev, 0xE8, 0x16); } + break; + case 14: + for (core = 0; core < 2; core++) { + int o = core ? 0x85 : 0; + + b43_radio_write(dev, o + R2057_IPA2G_CASCONV_CORE0, 0x13); + b43_radio_write(dev, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21); + b43_radio_write(dev, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff); + b43_radio_write(dev, o + R2057_PAD2G_IDACS_CORE0, 0x88); + b43_radio_write(dev, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23); + b43_radio_write(dev, o + R2057_IPA2G_IMAIN_CORE0, 0x16); + b43_radio_write(dev, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e); + b43_radio_write(dev, o + R2057_BACKUP1_CORE0, 0x10); + } + break; } } else { u16 freq = phy->chandef->chan->center_freq; @@ -2974,8 +3107,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1); b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1); b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1); - b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20); - b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20); + b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0); + b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0); b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4); b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4); @@ -2986,20 +3119,20 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2); b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20); - b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x138), 2, ntab7_138_146); + b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x138), 2, ntab7_138_146); b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77); - b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x133), 3, ntab7_133); - b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x146), 2, ntab7_138_146); + b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x133), 3, ntab7_133); + b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x146), 2, ntab7_138_146); b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77); b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77); - if (!b43_is_40mhz(dev)) { - b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x18D); - b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x18D); - } else { - b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x14D); - b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x14D); - } + b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x02), 1, noise_tbl); + noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D; + b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x02), 2, noise_tbl); + + b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x7E), 1, noise_tbl); + noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D; + b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x7E), 2, noise_tbl); b43_nphy_gain_ctl_workarounds(dev); @@ -4809,41 +4942,61 @@ static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core) } } +static void b43_nphy_pa_set_tx_dig_filter(struct b43_wldev *dev, u16 offset, + const s16 *filter) +{ + int i; + + offset = B43_PHY_N(offset); + + for (i = 0; i < 15; i++, offset++) + b43_phy_write(dev, offset, filter[i]); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev) { - int i; - for (i = 0; i < 15; i++) - b43_phy_write(dev, B43_PHY_N(0x2C5 + i), - tbl_tx_filter_coef_rev4[2][i]); + b43_nphy_pa_set_tx_dig_filter(dev, 0x2C5, + tbl_tx_filter_coef_rev4[2]); } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev) { - int i, j; /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */ static const u16 offset[] = { 0x186, 0x195, 0x2C5 }; + static const s16 dig_filter_phy_rev16[] = { + -375, 136, -407, 208, -1527, + 956, 93, 186, 93, 230, + -44, 230, 201, -191, 201, + }; + int i; for (i = 0; i < 3; i++) - for (j = 0; j < 15; j++) - b43_phy_write(dev, B43_PHY_N(offset[i] + j), - tbl_tx_filter_coef_rev4[i][j]); + b43_nphy_pa_set_tx_dig_filter(dev, offset[i], + tbl_tx_filter_coef_rev4[i]); + + /* Verified with BCM43227 and BCM43228 */ + if (dev->phy.rev == 16) + b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16); + + if (dev->dev->chip_id == BCMA_CHIP_ID_BCM43217) { + b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16); + b43_nphy_pa_set_tx_dig_filter(dev, 0x195, + tbl_tx_filter_coef_rev4[1]); + } if (b43_is_40mhz(dev)) { - for (j = 0; j < 15; j++) - b43_phy_write(dev, B43_PHY_N(offset[0] + j), - tbl_tx_filter_coef_rev4[3][j]); - } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { - for (j = 0; j < 15; j++) - b43_phy_write(dev, B43_PHY_N(offset[0] + j), - tbl_tx_filter_coef_rev4[5][j]); - } - - if (dev->phy.channel == 14) - for (j = 0; j < 15; j++) - b43_phy_write(dev, B43_PHY_N(offset[0] + j), - tbl_tx_filter_coef_rev4[6][j]); + b43_nphy_pa_set_tx_dig_filter(dev, 0x186, + tbl_tx_filter_coef_rev4[3]); + } else { + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + b43_nphy_pa_set_tx_dig_filter(dev, 0x186, + tbl_tx_filter_coef_rev4[5]); + if (dev->phy.channel == 14) + b43_nphy_pa_set_tx_dig_filter(dev, 0x186, + tbl_tx_filter_coef_rev4[6]); + } } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 3e48ef5ca53..1770fa3fc1e 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -1954,6 +1954,7 @@ static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) mmc_remove_host(target); /* 20ms delay is based on experiment with sdhci controller */ mdelay(20); + target->rescan_entered = 0; /* rescan non-removable cards */ mmc_add_host(target); } |