diff options
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r-- | drivers/net/wireless/b43/b43.h | 15 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 128 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_n.c | 532 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_n.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/b43/tables_nphy.c | 76 | ||||
-rw-r--r-- | drivers/net/wireless/b43/tables_nphy.h | 14 |
6 files changed, 564 insertions, 202 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 16e8f8058155..67c13af6f206 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -932,6 +932,9 @@ struct b43_wl { /* Flag that implement the queues stopping. */ bool tx_queue_stopped[B43_QOS_QUEUE_NUM]; + /* firmware loading work */ + struct work_struct firmware_load; + /* The device LEDs. */ struct b43_leds leds; @@ -999,6 +1002,12 @@ static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value) dev->dev->write16(dev->dev, offset, value); } +static inline void b43_maskset16(struct b43_wldev *dev, u16 offset, u16 mask, + u16 set) +{ + b43_write16(dev, offset, (b43_read16(dev, offset) & mask) | set); +} + static inline u32 b43_read32(struct b43_wldev *dev, u16 offset) { return dev->dev->read32(dev->dev, offset); @@ -1009,6 +1018,12 @@ static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value) dev->dev->write32(dev->dev, offset, value); } +static inline void b43_maskset32(struct b43_wldev *dev, u16 offset, u32 mask, + u32 set) +{ + b43_write32(dev, offset, (b43_read32(dev, offset) & mask) | set); +} + static inline void b43_block_read(struct b43_wldev *dev, void *buffer, size_t count, u16 offset, u8 reg_width) { diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 23ffb1b9a86f..c79e6638c88d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -580,22 +580,14 @@ void b43_tsf_read(struct b43_wldev *dev, u64 *tsf) static void b43_time_lock(struct b43_wldev *dev) { - u32 macctl; - - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl |= B43_MACCTL_TBTTHOLD; - b43_write32(dev, B43_MMIO_MACCTL, macctl); + b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_TBTTHOLD); /* Commit the write */ b43_read32(dev, B43_MMIO_MACCTL); } static void b43_time_unlock(struct b43_wldev *dev) { - u32 macctl; - - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl &= ~B43_MACCTL_TBTTHOLD; - b43_write32(dev, B43_MMIO_MACCTL, macctl); + b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_TBTTHOLD, 0); /* Commit the write */ b43_read32(dev, B43_MMIO_MACCTL); } @@ -2398,8 +2390,14 @@ error: return err; } -static int b43_request_firmware(struct b43_wldev *dev) +static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl); +static void b43_one_core_detach(struct b43_bus_dev *dev); + +static void b43_request_firmware(struct work_struct *work) { + struct b43_wl *wl = container_of(work, + struct b43_wl, firmware_load); + struct b43_wldev *dev = wl->current_dev; struct b43_request_fw_context *ctx; unsigned int i; int err; @@ -2407,23 +2405,23 @@ static int b43_request_firmware(struct b43_wldev *dev) ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) - return -ENOMEM; + return; ctx->dev = dev; ctx->req_type = B43_FWTYPE_PROPRIETARY; err = b43_try_request_fw(ctx); if (!err) - goto out; /* Successfully loaded it. */ - err = ctx->fatal_failure; - if (err) + goto start_ieee80211; /* Successfully loaded it. */ + /* Was fw version known? */ + if (ctx->fatal_failure) goto out; + /* proprietary fw not found, try open source */ ctx->req_type = B43_FWTYPE_OPENSOURCE; err = b43_try_request_fw(ctx); if (!err) - goto out; /* Successfully loaded it. */ - err = ctx->fatal_failure; - if (err) + goto start_ieee80211; /* Successfully loaded it. */ + if(ctx->fatal_failure) goto out; /* Could not find a usable firmware. Print the errors. */ @@ -2433,11 +2431,20 @@ static int b43_request_firmware(struct b43_wldev *dev) b43err(dev->wl, errmsg); } b43_print_fw_helptext(dev->wl, 1); - err = -ENOENT; + goto out; + +start_ieee80211: + err = ieee80211_register_hw(wl->hw); + if (err) + goto err_one_core_detach; + b43_leds_register(wl->current_dev); + goto out; + +err_one_core_detach: + b43_one_core_detach(dev->dev); out: kfree(ctx); - return err; } static int b43_upload_microcode(struct b43_wldev *dev) @@ -2487,10 +2494,8 @@ static int b43_upload_microcode(struct b43_wldev *dev) b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_ALL); /* Start the microcode PSM */ - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl &= ~B43_MACCTL_PSM_JMP0; - macctl |= B43_MACCTL_PSM_RUN; - b43_write32(dev, B43_MMIO_MACCTL, macctl); + b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PSM_JMP0, + B43_MACCTL_PSM_RUN); /* Wait for the microcode to load and respond */ i = 0; @@ -2590,10 +2595,9 @@ static int b43_upload_microcode(struct b43_wldev *dev) return 0; error: - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl &= ~B43_MACCTL_PSM_RUN; - macctl |= B43_MACCTL_PSM_JMP0; - b43_write32(dev, B43_MMIO_MACCTL, macctl); + /* Stop the microcode PSM. */ + b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PSM_RUN, + B43_MACCTL_PSM_JMP0); return err; } @@ -2708,11 +2712,8 @@ static int b43_gpio_init(struct b43_wldev *dev) struct ssb_device *gpiodev; u32 mask, set; - b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) - & ~B43_MACCTL_GPOUTSMSK); - - b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK) - | 0x000F); + b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0); + b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xF); mask = 0x0000001F; set = 0x0000000F; @@ -2720,6 +2721,8 @@ static int b43_gpio_init(struct b43_wldev *dev) mask |= 0x0060; set |= 0x0060; } + if (dev->dev->chip_id == 0x5354) + set &= 0xff02; if (0 /* FIXME: conditional unknown */ ) { b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK) @@ -2800,9 +2803,7 @@ void b43_mac_enable(struct b43_wldev *dev) dev->mac_suspended--; B43_WARN_ON(dev->mac_suspended < 0); if (dev->mac_suspended == 0) { - b43_write32(dev, B43_MMIO_MACCTL, - b43_read32(dev, B43_MMIO_MACCTL) - | B43_MACCTL_ENABLED); + b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_ENABLED); b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_MAC_SUSPENDED); /* Commit writes */ @@ -2823,9 +2824,7 @@ void b43_mac_suspend(struct b43_wldev *dev) if (dev->mac_suspended == 0) { b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); - b43_write32(dev, B43_MMIO_MACCTL, - b43_read32(dev, B43_MMIO_MACCTL) - & ~B43_MACCTL_ENABLED); + b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_ENABLED, 0); /* force pci to flush the write */ b43_read32(dev, B43_MMIO_MACCTL); for (i = 35; i; i--) { @@ -2931,15 +2930,10 @@ static void b43_adjust_opmode(struct b43_wldev *dev) * so always disable it. If we want to implement PMQ, * we need to enable it here (clear DISCPMQ) in AP mode. */ - if (0 /* ctl & B43_MACCTL_AP */) { - b43_write32(dev, B43_MMIO_MACCTL, - b43_read32(dev, B43_MMIO_MACCTL) - & ~B43_MACCTL_DISCPMQ); - } else { - b43_write32(dev, B43_MMIO_MACCTL, - b43_read32(dev, B43_MMIO_MACCTL) - | B43_MACCTL_DISCPMQ); - } + if (0 /* ctl & B43_MACCTL_AP */) + b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_DISCPMQ, 0); + else + b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_DISCPMQ); } static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm) @@ -3044,9 +3038,6 @@ static int b43_chip_init(struct b43_wldev *dev) macctl |= B43_MACCTL_INFRA; b43_write32(dev, B43_MMIO_MACCTL, macctl); - err = b43_request_firmware(dev); - if (err) - goto out; err = b43_upload_microcode(dev); if (err) goto out; /* firmware is released later */ @@ -3083,10 +3074,8 @@ static int b43_chip_init(struct b43_wldev *dev) if (dev->dev->core_rev < 5) b43_write32(dev, 0x010C, 0x01000000); - b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) - & ~B43_MACCTL_INFRA); - b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) - | B43_MACCTL_INFRA); + b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_INFRA, 0); + b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_INFRA); /* Probe Response Timeout value */ /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ @@ -4178,6 +4167,7 @@ redo: mutex_unlock(&wl->mutex); cancel_delayed_work_sync(&dev->periodic_work); cancel_work_sync(&wl->tx_work); + cancel_work_sync(&wl->firmware_load); mutex_lock(&wl->mutex); dev = wl->current_dev; if (!dev || b43_status(dev) < B43_STAT_STARTED) { @@ -4564,8 +4554,6 @@ static void b43_set_pretbtt(struct b43_wldev *dev) /* Locking: wl->mutex */ static void b43_wireless_core_exit(struct b43_wldev *dev) { - u32 macctl; - B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED); if (!dev || b43_status(dev) != B43_STAT_INITIALIZED) return; @@ -4576,10 +4564,8 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) b43_set_status(dev, B43_STAT_UNINIT); /* Stop the microcode PSM. */ - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl &= ~B43_MACCTL_PSM_RUN; - macctl |= B43_MACCTL_PSM_JMP0; - b43_write32(dev, B43_MMIO_MACCTL, macctl); + b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PSM_RUN, + B43_MACCTL_PSM_JMP0); b43_dma_free(dev); b43_pio_free(dev); @@ -5341,16 +5327,13 @@ static int b43_bcma_probe(struct bcma_device *core) if (err) goto bcma_err_wireless_exit; - err = ieee80211_register_hw(wl->hw); - if (err) - goto bcma_err_one_core_detach; - b43_leds_register(wl->current_dev); + /* setup and start work to load firmware */ + INIT_WORK(&wl->firmware_load, b43_request_firmware); + schedule_work(&wl->firmware_load); bcma_out: return err; -bcma_err_one_core_detach: - b43_one_core_detach(dev); bcma_err_wireless_exit: ieee80211_free_hw(wl->hw); return err; @@ -5417,18 +5400,13 @@ int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id) if (err) goto err_wireless_exit; - if (first) { - err = ieee80211_register_hw(wl->hw); - if (err) - goto err_one_core_detach; - b43_leds_register(wl->current_dev); - } + /* setup and start work to load firmware */ + INIT_WORK(&wl->firmware_load, b43_request_firmware); + schedule_work(&wl->firmware_load); out: return err; - err_one_core_detach: - b43_one_core_detach(dev); err_wireless_exit: if (first) b43_wireless_exit(dev, wl); diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index bf5a43855358..108118820b36 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -85,22 +85,11 @@ static inline bool b43_nphy_ipa(struct b43_wldev *dev) (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ)); } -/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */ -static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */ +static u8 b43_nphy_get_rx_core_state(struct b43_wldev *dev) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - if (dev->phy.rev >= 6) { - if (dev->dev->chip_id == 47162) - return txpwrctrl_tx_gain_ipa_rev5; - return txpwrctrl_tx_gain_ipa_rev6; - } else if (dev->phy.rev >= 5) { - return txpwrctrl_tx_gain_ipa_rev5; - } else { - return txpwrctrl_tx_gain_ipa; - } - } else { - return txpwrctrl_tx_gain_ipa_5g; - } + return (b43_phy_read(dev, B43_NPHY_RFSEQCA) & B43_NPHY_RFSEQCA_RXEN) >> + B43_NPHY_RFSEQCA_RXEN_SHIFT; } /************************************************** @@ -229,7 +218,7 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, reg = (i == 0) ? B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2; - b43_phy_mask(dev, reg, 0xFBFF); + b43_phy_set(dev, reg, 0x400); switch (field) { case 0: @@ -245,7 +234,7 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_START); for (j = 0; j < 100; j++) { - if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START) { + if (!(b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START)) { j = 0; break; } @@ -264,7 +253,7 @@ static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_RXTX); for (j = 0; j < 100; j++) { - if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX) { + if (!(b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX)) { j = 0; break; } @@ -1231,12 +1220,12 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, u16 s[2]; if (dev->phy.rev >= 3) { - save_regs_phy[0] = b43_phy_read(dev, + save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); + save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); + save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1); - save_regs_phy[1] = b43_phy_read(dev, + save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2); - save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); - save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); @@ -1285,12 +1274,12 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]); if (dev->phy.rev >= 3) { + b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]); + b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]); b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, - save_regs_phy[0]); + save_regs_phy[2]); b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, - save_regs_phy[1]); - b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]); - b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]); + save_regs_phy[3]); b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]); b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]); b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); @@ -1308,6 +1297,186 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, return out; } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ +static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + + u16 saved_regs_phy_rfctl[2]; + u16 saved_regs_phy[13]; + u16 regs_to_store[] = { + B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER, + B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2, + B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER, + B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1, + B43_NPHY_RFCTL_CMD, + B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2, + B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2 + }; + + u16 class; + + u16 clip_state[2]; + u16 clip_off[2] = { 0xFFFF, 0xFFFF }; + + u8 vcm_final = 0; + s8 offset[4]; + s32 results[8][4] = { }; + s32 results_min[4] = { }; + s32 poll_results[4] = { }; + + u16 *rssical_radio_regs = NULL; + u16 *rssical_phy_regs = NULL; + + u16 r; /* routing */ + u8 rx_core_state; + u8 core, i, j; + + class = b43_nphy_classifier(dev, 0, 0); + b43_nphy_classifier(dev, 7, 4); + b43_nphy_read_clip_detection(dev, clip_state); + b43_nphy_write_clip_detection(dev, clip_off); + + saved_regs_phy_rfctl[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); + saved_regs_phy_rfctl[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); + for (i = 0; i < ARRAY_SIZE(regs_to_store); i++) + saved_regs_phy[i] = b43_phy_read(dev, regs_to_store[i]); + + b43_nphy_rf_control_intc_override(dev, 0, 0, 7); + b43_nphy_rf_control_intc_override(dev, 1, 1, 7); + b43_nphy_rf_control_override(dev, 0x1, 0, 0, false); + b43_nphy_rf_control_override(dev, 0x2, 1, 0, false); + b43_nphy_rf_control_override(dev, 0x80, 1, 0, false); + b43_nphy_rf_control_override(dev, 0x40, 1, 0, false); + + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + b43_nphy_rf_control_override(dev, 0x20, 0, 0, false); + b43_nphy_rf_control_override(dev, 0x10, 1, 0, false); + } else { + b43_nphy_rf_control_override(dev, 0x10, 0, 0, false); + b43_nphy_rf_control_override(dev, 0x20, 1, 0, false); + } + + rx_core_state = b43_nphy_get_rx_core_state(dev); + for (core = 0; core < 2; core++) { + if (!(rx_core_state & (1 << core))) + continue; + r = core ? B2056_RX1 : B2056_RX0; + b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 0, 2); + b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, 2); + for (i = 0; i < 8; i++) { + b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 0xE3, + i << 2); + b43_nphy_poll_rssi(dev, 2, results[i], 8); + } + for (i = 0; i < 4; i++) { + s32 curr; + s32 mind = 40; + s32 minpoll = 249; + u8 minvcm = 0; + if (2 * core != i) + continue; + for (j = 0; j < 8; j++) { + curr = results[j][i] * results[j][i] + + results[j][i + 1] * results[j][i]; + if (curr < mind) { + mind = curr; + minvcm = j; + } + if (results[j][i] < minpoll) + minpoll = results[j][i]; + } + vcm_final = minvcm; + results_min[i] = minpoll; + } + b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 0xE3, + vcm_final << 2); + for (i = 0; i < 4; i++) { + if (core != i / 2) + continue; + offset[i] = -results[vcm_final][i]; + if (offset[i] < 0) + offset[i] = -((abs(offset[i]) + 4) / 8); + else + offset[i] = (offset[i] + 4) / 8; + if (results_min[i] == 248) + offset[i] = -32; + b43_nphy_scale_offset_rssi(dev, 0, offset[i], + (i / 2 == 0) ? 1 : 2, + (i % 2 == 0) ? 0 : 1, + 2); + } + } + for (core = 0; core < 2; core++) { + if (!(rx_core_state & (1 << core))) + continue; + for (i = 0; i < 2; i++) { + b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 0, i); + b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, i); + b43_nphy_poll_rssi(dev, i, poll_results, 8); + for (j = 0; j < 4; j++) { + if (j / 2 == core) + offset[j] = 232 - poll_results[j]; + if (offset[j] < 0) + offset[j] = -(abs(offset[j] + 4) / 8); + else + offset[j] = (offset[j] + 4) / 8; + b43_nphy_scale_offset_rssi(dev, 0, + offset[2 * core], core + 1, j % 2, i); + } + } + } + + b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, saved_regs_phy_rfctl[0]); + b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, saved_regs_phy_rfctl[1]); + + b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); + + b43_phy_set(dev, B43_NPHY_TXF_40CO_B1S1, 0x1); + b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_START); + b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1, ~0x1); + + b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1); + b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_RXTX); + b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1, ~0x1); + + for (i = 0; i < ARRAY_SIZE(regs_to_store); i++) + b43_phy_write(dev, regs_to_store[i], saved_regs_phy[i]); + + /* Store for future configuration */ + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; + rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; + } else { + rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; + rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; + } + rssical_radio_regs[0] = b43_radio_read(dev, 0x602B); + rssical_radio_regs[0] = b43_radio_read(dev, 0x702B); + rssical_phy_regs[0] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Z); + rssical_phy_regs[1] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z); + rssical_phy_regs[2] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Z); + rssical_phy_regs[3] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z); + rssical_phy_regs[4] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_X); + rssical_phy_regs[5] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_X); + rssical_phy_regs[6] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_X); + rssical_phy_regs[7] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_X); + rssical_phy_regs[8] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Y); + rssical_phy_regs[9] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y); + rssical_phy_regs[10] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Y); + rssical_phy_regs[11] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y); + + /* Remember for which channel we store configuration */ + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + nphy->rssical_chanspec_2G.center_freq = dev->phy.channel_freq; + else + nphy->rssical_chanspec_5G.center_freq = dev->phy.channel_freq; + + /* End of calibration, restore configuration */ + b43_nphy_classifier(dev, 7, class); + b43_nphy_write_clip_detection(dev, clip_state); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) { @@ -1472,12 +1641,6 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) b43_nphy_reset_cca(dev); } -/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ -static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) -{ - /* TODO */ -} - /* * RSSI Calibration * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal @@ -2229,27 +2392,12 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) */ for (i = 0; i < 2; i++) { - if (dev->phy.rev >= 3) { - if (b43_nphy_ipa(dev)) { - txgain = *(b43_nphy_get_ipa_gain_table(dev) + - txpi[i]); - } else if (b43_current_band(dev->wl) == - IEEE80211_BAND_5GHZ) { - /* FIXME: use 5GHz tables */ - txgain = - b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]]; - } else { - if (dev->phy.rev >= 5 && - sprom->fem.ghz5.extpa_gain == 3) - ; /* FIXME: 5GHz_txgain_HiPwrEPA */ - txgain = - b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]]; - } + txgain = *(b43_nphy_get_tx_gain_table(dev) + txpi[i]); + + if (dev->phy.rev >= 3) radio_gain = (txgain >> 16) & 0x1FFFF; - } else { - txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]]; + else radio_gain = (txgain >> 16) & 0x1FFF; - } if (dev->phy.rev >= 7) dac_gain = (txgain >> 8) & 0x7; @@ -2420,55 +2568,252 @@ static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev) nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF; } -static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev) +/* http://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */ +static void b43_nphy_tx_prepare_adjusted_power_table(struct b43_wldev *dev) { - struct b43_phy *phy = &dev->phy; + struct b43_phy_n *nphy = dev->phy.n; - const u32 *table = NULL; -#if 0 - TODO: b43_ntab_papd_pga_gain_delta_ipa_2* - u32 rfpwr_offset; - u8 pga_gain; - int i; -#endif + u8 idx, delta; + u8 i, stf_mode; - if (phy->rev >= 3) { - if (b43_nphy_ipa(dev)) { - table = b43_nphy_get_ipa_gain_table(dev); + for (i = 0; i < 4; i++) + nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i]; + + for (stf_mode = 0; stf_mode < 4; stf_mode++) { + delta = 0; + switch (stf_mode) { + case 0: + if (dev->phy.is_40mhz && dev->phy.rev >= 5) { + idx = 68; + } else { + delta = 1; + idx = dev->phy.is_40mhz ? 52 : 4; + } + break; + case 1: + idx = dev->phy.is_40mhz ? 76 : 28; + break; + case 2: + idx = dev->phy.is_40mhz ? 84 : 36; + break; + case 3: + idx = dev->phy.is_40mhz ? 92 : 44; + break; + } + + for (i = 0; i < 20; i++) { + nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] = + nphy->tx_power_offset[idx]; + if (i == 0) + idx += delta; + if (i == 14) + idx += 1 - delta; + if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 || + i == 13) + idx += 1; + } + } +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */ +static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + struct ssb_sprom *sprom = dev->dev->bus_sprom; + + s16 a1[2], b0[2], b1[2]; + u8 idle[2]; + s8 target[2]; + s32 num, den, pwr; + u32 regval[64]; + + u16 freq = dev->phy.channel_freq; + u16 tmp; + u16 r; /* routing */ + u8 i, c; + + if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) { + b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000); + b43_read32(dev, B43_MMIO_MACCTL); + udelay(1); + } + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, true); + + b43_phy_set(dev, B43_NPHY_TSSIMODE, B43_NPHY_TSSIMODE_EN); + if (dev->phy.rev >= 3) + b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, + ~B43_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF); + else + b43_phy_set(dev, B43_NPHY_TXPCTL_CMD, + B43_NPHY_TXPCTL_CMD_PCTLEN); + + if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) + b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0); + + if (sprom->revision < 4) { + idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g; + idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g; + target[0] = target[1] = 52; + a1[0] = a1[1] = -424; + b0[0] = b0[1] = 5612; + b1[0] = b1[1] = -1393; + } else { + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + for (c = 0; c < 2; c++) { + idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g; + target[c] = sprom->core_pwr_info[c].maxpwr_2g; + a1[c] = sprom->core_pwr_info[c].pa_2g[0]; + b0[c] = sprom->core_pwr_info[c].pa_2g[1]; + b1[c] = sprom->core_pwr_info[c].pa_2g[2]; + } + } else if (freq >= 4900 && freq < 5100) { + for (c = 0; c < 2; c++) { + idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; + target[c] = sprom->core_pwr_info[c].maxpwr_5gl; + a1[c] = sprom->core_pwr_info[c].pa_5gl[0]; + b0[c] = sprom->core_pwr_info[c].pa_5gl[1]; + b1[c] = sprom->core_pwr_info[c].pa_5gl[2]; + } + } else if (freq >= 5100 && freq < 5500) { + for (c = 0; c < 2; c++) { + idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; + target[c] = sprom->core_pwr_info[c].maxpwr_5g; + a1[c] = sprom->core_pwr_info[c].pa_5g[0]; + b0[c] = sprom->core_pwr_info[c].pa_5g[1]; + b1[c] = sprom->core_pwr_info[c].pa_5g[2]; + } + } else if (freq >= 5500) { + for (c = 0; c < 2; c++) { + idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; + target[c] = sprom->core_pwr_info[c].maxpwr_5gh; + a1[c] = sprom->core_pwr_info[c].pa_5gh[0]; + b0[c] = sprom->core_pwr_info[c].pa_5gh[1]; + b1[c] = sprom->core_pwr_info[c].pa_5gh[2]; + } } else { - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { - if (phy->rev == 3) - table = b43_ntab_tx_gain_rev3_5ghz; - if (phy->rev == 4) - table = b43_ntab_tx_gain_rev4_5ghz; - else - table = b43_ntab_tx_gain_rev5plus_5ghz; + idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g; + idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g; + target[0] = target[1] = 52; + a1[0] = a1[1] = -424; + b0[0] = b0[1] = 5612; + b1[0] = b1[1] = -1393; + } + } + /* target[0] = target[1] = nphy->tx_power_max; */ + + if (dev->phy.rev >= 3) { + if (sprom->fem.ghz2.tssipos) + b43_phy_set(dev, B43_NPHY_TXPCTL_ITSSI, 0x4000); + if (dev->phy.rev >= 7) { + for (c = 0; c < 2; c++) { + r = c ? 0x190 : 0x170; + if (b43_nphy_ipa(dev)) + b43_radio_write(dev, r + 0x9, (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ? 0xE : 0xC); + } + } else { + if (b43_nphy_ipa(dev)) { + tmp = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; + b43_radio_write(dev, + B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp); + b43_radio_write(dev, + B2056_TX1 | B2056_TX_TX_SSI_MUX, tmp); } else { - table = b43_ntab_tx_gain_rev3plus_2ghz; + b43_radio_write(dev, + B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11); + b43_radio_write(dev, + B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11); } } + } + + if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) { + b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000); + b43_read32(dev, B43_MMIO_MACCTL); + udelay(1); + } + + if (dev->phy.rev >= 7) { + b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, + ~B43_NPHY_TXPCTL_CMD_INIT, 0x19); + b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, + ~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x19); } else { - table = b43_ntab_tx_gain_rev0_1_2; + b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, + ~B43_NPHY_TXPCTL_CMD_INIT, 0x40); + if (dev->phy.rev > 1) + b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, + ~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x40); + } + + if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) + b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0); + + b43_phy_write(dev, B43_NPHY_TXPCTL_N, + 0xF0 << B43_NPHY_TXPCTL_N_TSSID_SHIFT | + 3 << B43_NPHY_TXPCTL_N_NPTIL2_SHIFT); + b43_phy_write(dev, B43_NPHY_TXPCTL_ITSSI, + idle[0] << B43_NPHY_TXPCTL_ITSSI_0_SHIFT | + idle[1] << B43_NPHY_TXPCTL_ITSSI_1_SHIFT | + B43_NPHY_TXPCTL_ITSSI_BINF); + b43_phy_write(dev, B43_NPHY_TXPCTL_TPWR, + target[0] << B43_NPHY_TXPCTL_TPWR_0_SHIFT | + target[1] << B43_NPHY_TXPCTL_TPWR_1_SHIFT); + + for (c = 0; c < 2; c++) { + for (i = 0; i < 64; i++) { + num = 8 * (16 * b0[c] + b1[c] * i); + den = 32768 + a1[c] * i; + pwr = max((4 * num + den / 2) / den, -8); + if (dev->phy.rev < 3 && (i <= (31 - idle[c] + 1))) + pwr = max(pwr, target[c] + 1); + regval[i] = pwr; + } + b43_ntab_write_bulk(dev, B43_NTAB32(26 + c, 0), 64, regval); } + + b43_nphy_tx_prepare_adjusted_power_table(dev); + /* + b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84, nphy->adj_pwr_tbl); + b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84, nphy->adj_pwr_tbl); + */ + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, false); +} + +static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev) +{ + struct b43_phy *phy = &dev->phy; + + const u32 *table = NULL; + u32 rfpwr_offset; + u8 pga_gain; + int i; + + table = b43_nphy_get_tx_gain_table(dev); b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table); b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table); if (phy->rev >= 3) { #if 0 nphy->gmval = (table[0] >> 16) & 0x7000; +#endif for (i = 0; i < 128; i++) { pga_gain = (table[i] >> 24) & 0xF; if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain]; + rfpwr_offset = + b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain]; else - rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_5g[pga_gain]; + rfpwr_offset = + 0; /* FIXME */ b43_ntab_write(dev, B43_NTAB32(26, 576 + i), rfpwr_offset); b43_ntab_write(dev, B43_NTAB32(27, 576 + i), rfpwr_offset); } -#endif } } @@ -3139,32 +3484,13 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; for (i = 0; i < 2; ++i) { + table = b43_nphy_get_tx_gain_table(dev); if (dev->phy.rev >= 3) { - enum ieee80211_band band = - b43_current_band(dev->wl); - - if (b43_nphy_ipa(dev)) { - table = b43_nphy_get_ipa_gain_table(dev); - } else { - if (band == IEEE80211_BAND_5GHZ) { - if (dev->phy.rev == 3) - table = b43_ntab_tx_gain_rev3_5ghz; - else if (dev->phy.rev == 4) - table = b43_ntab_tx_gain_rev4_5ghz; - else - table = b43_ntab_tx_gain_rev5plus_5ghz; - } else { - table = b43_ntab_tx_gain_rev3plus_2ghz; - } - } - target.ipa[i] = (table[index[i]] >> 16) & 0xF; target.pad[i] = (table[index[i]] >> 20) & 0xF; target.pga[i] = (table[index[i]] >> 24) & 0xF; target.txgm[i] = (table[index[i]] >> 28) & 0xF; } else { - table = b43_ntab_tx_gain_rev0_1_2; - target.ipa[i] = (table[index[i]] >> 16) & 0x3; target.pad[i] = (table[index[i]] >> 18) & 0x3; target.pga[i] = (table[index[i]] >> 20) & 0x7; @@ -3968,13 +4294,10 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) #endif } - b43_write32(dev, B43_MMIO_MACCTL, - b43_read32(dev, B43_MMIO_MACCTL) & - ~B43_MACCTL_GPOUTSMSK); - b43_write16(dev, B43_MMIO_GPIO_MASK, - b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00); - b43_write16(dev, B43_MMIO_GPIO_CONTROL, - b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00); + b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0); + b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xFC00); + b43_maskset16(dev, B43_MMIO_GPIO_CONTROL, (~0xFC00 & 0xFFFF), + 0); if (init) { b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); @@ -4110,7 +4433,7 @@ int b43_phy_initn(struct b43_wldev *dev) b43_nphy_tx_power_ctrl(dev, false); b43_nphy_tx_power_fix(dev); b43_nphy_tx_power_ctl_idle_tssi(dev); - /* TODO N PHY TX Power Control Setup */ + b43_nphy_tx_power_ctl_setup(dev); b43_nphy_tx_gain_table_upload(dev); if (nphy->phyrxchain != 3) @@ -4530,8 +4853,7 @@ static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, { check_phyreg(dev, reg); b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - b43_write16(dev, B43_MMIO_PHY_DATA, - (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); + b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set); } static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 5de8f74cc02f..fd12b386fea1 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -798,6 +798,7 @@ struct b43_phy_n { bool txpwrctrl; bool pwg_gain_5ghz; u8 tx_pwr_idx[2]; + s8 tx_power_offset[101]; u16 adj_pwr_tbl[84]; u16 txcal_bbmult; u16 txiqlocal_bestc[11]; diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index f7def13524dd..f0d8377429c6 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -2214,7 +2214,7 @@ static const u16 b43_ntab_antswctl2g_r3[4][32] = { }; /* TX gain tables */ -const u32 b43_ntab_tx_gain_rev0_1_2[] = { +static const u32 b43_ntab_tx_gain_rev0_1_2[] = { 0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42, 0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44, 0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844, @@ -2249,7 +2249,7 @@ const u32 b43_ntab_tx_gain_rev0_1_2[] = { 0x03801442, 0x03801344, 0x03801342, 0x00002b00, }; -const u32 b43_ntab_tx_gain_rev3plus_2ghz[] = { +static const u32 b43_ntab_tx_gain_rev3plus_2ghz[] = { 0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e, 0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037, 0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e, @@ -2284,7 +2284,7 @@ const u32 b43_ntab_tx_gain_rev3plus_2ghz[] = { 0x1041003c, 0x1041003b, 0x10410039, 0x10410037, }; -const u32 b43_ntab_tx_gain_rev3_5ghz[] = { +static const u32 b43_ntab_tx_gain_rev3_5ghz[] = { 0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e, 0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037, 0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e, @@ -2319,7 +2319,7 @@ const u32 b43_ntab_tx_gain_rev3_5ghz[] = { 0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037, }; -const u32 b43_ntab_tx_gain_rev4_5ghz[] = { +static const u32 b43_ntab_tx_gain_rev4_5ghz[] = { 0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e, 0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037, 0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e, @@ -2354,7 +2354,7 @@ const u32 b43_ntab_tx_gain_rev4_5ghz[] = { 0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034, }; -const u32 b43_ntab_tx_gain_rev5plus_5ghz[] = { +static const u32 b43_ntab_tx_gain_rev5plus_5ghz[] = { 0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044, 0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c, 0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e, @@ -2389,7 +2389,7 @@ const u32 b43_ntab_tx_gain_rev5plus_5ghz[] = { 0x0062003b, 0x00620039, 0x00620037, 0x00620035, }; -const u32 txpwrctrl_tx_gain_ipa[] = { +static const u32 txpwrctrl_tx_gain_ipa[] = { 0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029, 0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025, 0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029, @@ -2424,7 +2424,7 @@ const u32 txpwrctrl_tx_gain_ipa[] = { 0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025, }; -const u32 txpwrctrl_tx_gain_ipa_rev5[] = { +static const u32 txpwrctrl_tx_gain_ipa_rev5[] = { 0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029, 0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025, 0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029, @@ -2459,7 +2459,7 @@ const u32 txpwrctrl_tx_gain_ipa_rev5[] = { 0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025, }; -const u32 txpwrctrl_tx_gain_ipa_rev6[] = { +static const u32 txpwrctrl_tx_gain_ipa_rev6[] = { 0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029, 0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025, 0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029, @@ -2494,7 +2494,7 @@ const u32 txpwrctrl_tx_gain_ipa_rev6[] = { 0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025, }; -const u32 txpwrctrl_tx_gain_ipa_5g[] = { +static const u32 txpwrctrl_tx_gain_ipa_5g[] = { 0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031, 0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b, 0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027, @@ -2529,6 +2529,11 @@ const u32 txpwrctrl_tx_gain_ipa_5g[] = { 0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f, }; +const s8 b43_ntab_papd_pga_gain_delta_ipa_2g[] = { + -114, -108, -98, -91, -84, -78, -70, -62, + -54, -46, -39, -31, -23, -15, -8, 0 +}; + const u16 tbl_iqcal_gainparams[2][9][8] = { { { 0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69 }, @@ -2739,11 +2744,11 @@ const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[] = { { 0x0001, 0, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0002 (fls 2) */ { 0x0002, 1, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0004 (fls 3) */ { 0x0004, 2, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0008 (fls 4) */ - { 0x0016, 4, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0010 (fls 5) */ + { 0x0010, 4, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0010 (fls 5) */ { 0x0020, 5, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0020 (fls 6) */ { 0x0040, 6, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0040 (fls 7) */ - { 0x0080, 6, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0080 (fls 8) */ - { 0x0100, 7, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0100 (fls 9) */ + { 0x0080, 7, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0080 (fls 8) */ + { 0x0100, 8, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0100 (fls 9) */ { 0x0007, 0, 0xE7, 0xF8, 0xEC, 0xFA }, /* field == 0x0200 (fls 10) */ { 0x0070, 4, 0xE7, 0xF8, 0xEC, 0xFA }, /* field == 0x0400 (fls 11) */ { 0xE000, 13, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0800 (fls 12) */ @@ -3126,6 +3131,53 @@ void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev) B43_WARN_ON(1); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */ +static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) +{ + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (dev->phy.rev >= 6) { + if (dev->dev->chip_id == 47162) + return txpwrctrl_tx_gain_ipa_rev5; + return txpwrctrl_tx_gain_ipa_rev6; + } else if (dev->phy.rev >= 5) { + return txpwrctrl_tx_gain_ipa_rev5; + } else { + return txpwrctrl_tx_gain_ipa; + } + } else { + return txpwrctrl_tx_gain_ipa_5g; + } +} + +const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev) +{ + enum ieee80211_band band = b43_current_band(dev->wl); + struct ssb_sprom *sprom = dev->dev->bus_sprom; + + if (dev->phy.rev < 3) + return b43_ntab_tx_gain_rev0_1_2; + + /* rev 3+ */ + if ((dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) || + (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ)) { + return b43_nphy_get_ipa_gain_table(dev); + } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + if (dev->phy.rev == 3) + return b43_ntab_tx_gain_rev3_5ghz; + if (dev->phy.rev == 4) + return sprom->fem.ghz5.extpa_gain == 3 ? + b43_ntab_tx_gain_rev4_5ghz : + b43_ntab_tx_gain_rev4_5ghz; /* FIXME */ + else + return b43_ntab_tx_gain_rev5plus_5ghz; + } else { + if (dev->phy.rev >= 5 && sprom->fem.ghz5.extpa_gain == 3) + return b43_ntab_tx_gain_rev3plus_2ghz; /* FIXME */ + else + return b43_ntab_tx_gain_rev3plus_2ghz; + } +} + struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent( struct b43_wldev *dev, bool ghz5, bool ext_lna) { diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 97038c481930..f348953c0230 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -177,16 +177,10 @@ void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset, void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev); void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev); -extern const u32 b43_ntab_tx_gain_rev0_1_2[]; -extern const u32 b43_ntab_tx_gain_rev3plus_2ghz[]; -extern const u32 b43_ntab_tx_gain_rev3_5ghz[]; -extern const u32 b43_ntab_tx_gain_rev4_5ghz[]; -extern const u32 b43_ntab_tx_gain_rev5plus_5ghz[]; - -extern const u32 txpwrctrl_tx_gain_ipa[]; -extern const u32 txpwrctrl_tx_gain_ipa_rev5[]; -extern const u32 txpwrctrl_tx_gain_ipa_rev6[]; -extern const u32 txpwrctrl_tx_gain_ipa_5g[]; +const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev); + +extern const s8 b43_ntab_papd_pga_gain_delta_ipa_2g[]; + extern const u16 tbl_iqcal_gainparams[2][9][8]; extern const struct nphy_txiqcal_ladder ladder_lo[]; extern const struct nphy_txiqcal_ladder ladder_iq[]; |