summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r--drivers/net/wireless/b43/b43.h15
-rw-r--r--drivers/net/wireless/b43/main.c128
-rw-r--r--drivers/net/wireless/b43/phy_n.c532
-rw-r--r--drivers/net/wireless/b43/phy_n.h1
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c76
-rw-r--r--drivers/net/wireless/b43/tables_nphy.h14
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[];