Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/wireless/broadcom/b43/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 196 kB image not shown  

Quelle  phy_n.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*

  Broadcom B43 wireless driver
  IEEE 802.11n PHY support

  Copyright (c) 2008 Michael Buesch <m@bues.ch>
  Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com>


*/


#include <linux/cordic.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/types.h>

#include "b43.h"
#include "phy_n.h"
#include "tables_nphy.h"
#include "radio_2055.h"
#include "radio_2056.h"
#include "radio_2057.h"
#include "main.h"
#include "ppr.h"

struct nphy_txgains {
 u16 tx_lpf[2];
 u16 txgm[2];
 u16 pga[2];
 u16 pad[2];
 u16 ipa[2];
};

struct nphy_iqcal_params {
 u16 tx_lpf;
 u16 txgm;
 u16 pga;
 u16 pad;
 u16 ipa;
 u16 cal_gain;
 u16 ncorr[5];
};

struct nphy_iq_est {
 s32 iq0_prod;
 u32 i0_pwr;
 u32 q0_pwr;
 s32 iq1_prod;
 u32 i1_pwr;
 u32 q1_pwr;
};

enum b43_nphy_rf_sequence {
 B43_RFSEQ_RX2TX,
 B43_RFSEQ_TX2RX,
 B43_RFSEQ_RESET2RX,
 B43_RFSEQ_UPDATE_GAINH,
 B43_RFSEQ_UPDATE_GAINL,
 B43_RFSEQ_UPDATE_GAINU,
};

enum n_rf_ctl_over_cmd {
 N_RF_CTL_OVER_CMD_RXRF_PU = 0,
 N_RF_CTL_OVER_CMD_RX_PU = 1,
 N_RF_CTL_OVER_CMD_TX_PU = 2,
 N_RF_CTL_OVER_CMD_RX_GAIN = 3,
 N_RF_CTL_OVER_CMD_TX_GAIN = 4,
};

enum n_intc_override {
 N_INTC_OVERRIDE_OFF = 0,
 N_INTC_OVERRIDE_TRSW = 1,
 N_INTC_OVERRIDE_PA = 2,
 N_INTC_OVERRIDE_EXT_LNA_PU = 3,
 N_INTC_OVERRIDE_EXT_LNA_GAIN = 4,
};

enum n_rssi_type {
 N_RSSI_W1 = 0,
 N_RSSI_W2,
 N_RSSI_NB,
 N_RSSI_IQ,
 N_RSSI_TSSI_2G,
 N_RSSI_TSSI_5G,
 N_RSSI_TBD,
};

enum n_rail_type {
 N_RAIL_I = 0,
 N_RAIL_Q = 1,
};

static inline bool b43_nphy_ipa(struct b43_wldev *dev)
{
 enum nl80211_band band = b43_current_band(dev->wl);
 return ((dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) ||
  (dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ));
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */
static u8 b43_nphy_get_rx_core_state(struct b43_wldev *dev)
{
 return (b43_phy_read(dev, B43_NPHY_RFSEQCA) & B43_NPHY_RFSEQCA_RXEN) >>
  B43_NPHY_RFSEQCA_RXEN_SHIFT;
}

/**************************************************
 * RF (just without b43_nphy_rf_ctl_intc_override)
 **************************************************/


/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
           enum b43_nphy_rf_sequence seq)
{
 static const u16 trigger[] = {
  [B43_RFSEQ_RX2TX]  = B43_NPHY_RFSEQTR_RX2TX,
  [B43_RFSEQ_TX2RX]  = B43_NPHY_RFSEQTR_TX2RX,
  [B43_RFSEQ_RESET2RX]  = B43_NPHY_RFSEQTR_RST2RX,
  [B43_RFSEQ_UPDATE_GAINH] = B43_NPHY_RFSEQTR_UPGH,
  [B43_RFSEQ_UPDATE_GAINL] = B43_NPHY_RFSEQTR_UPGL,
  [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU,
 };
 int i;
 u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);

 B43_WARN_ON(seq >= ARRAY_SIZE(trigger));

 b43_phy_set(dev, B43_NPHY_RFSEQMODE,
      B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
 b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
 for (i = 0; i < 200; i++) {
  if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
   goto ok;
  msleep(1);
 }
 b43err(dev->wl, "RF sequence status timeout\n");
ok:
 b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
}

static void b43_nphy_rf_ctl_override_rev19(struct b43_wldev *dev, u16 field,
        u16 value, u8 core, bool off,
        u8 override_id)
{
 /* TODO */
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
       u16 value, u8 core, bool off,
       u8 override)
{
 struct b43_phy *phy = &dev->phy;
 const struct nphy_rf_control_override_rev7 *e;
 u16 en_addrs[3][2] = {
  { 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 }
 };
 u16 en_addr;
 u16 en_mask = field;
 u16 val_addr;
 u8 i;

 if (phy->rev >= 19 || phy->rev < 3) {
  B43_WARN_ON(1);
  return;
 }

 /* Remember: we can get NULL! */
 e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override);

 for (i = 0; i < 2; i++) {
  if (override >= ARRAY_SIZE(en_addrs)) {
   b43err(dev->wl, "Invalid override value %d\n", override);
   return;
  }
  en_addr = en_addrs[override][i];

  if (e)
   val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1;

  if (off) {
   b43_phy_mask(dev, en_addr, ~en_mask);
   if (e) /* Do it safer, better than wl */
    b43_phy_mask(dev, val_addr, ~e->val_mask);
  } else {
   if (!core || (core & (1 << i))) {
    b43_phy_set(dev, en_addr, en_mask);
    if (e)
     b43_phy_maskset(dev, val_addr, ~e->val_mask, (value << e->val_shift));
   }
  }
 }
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */
static void b43_nphy_rf_ctl_override_one_to_many(struct b43_wldev *dev,
       enum n_rf_ctl_over_cmd cmd,
       u16 value, u8 core, bool off)
{
 struct b43_phy *phy = &dev->phy;
 u16 tmp;

 B43_WARN_ON(phy->rev < 7);

 switch (cmd) {
 case N_RF_CTL_OVER_CMD_RXRF_PU:
  b43_nphy_rf_ctl_override_rev7(dev, 0x20, value, core, off, 1);
  b43_nphy_rf_ctl_override_rev7(dev, 0x10, value, core, off, 1);
  b43_nphy_rf_ctl_override_rev7(dev, 0x08, value, core, off, 1);
  break;
 case N_RF_CTL_OVER_CMD_RX_PU:
  b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 1);
  b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
  b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 1);
  b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 2);
  b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 0, core, off, 1);
  break;
 case N_RF_CTL_OVER_CMD_TX_PU:
  b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 0);
  b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
  b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 2);
  b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 1, core, off, 1);
  break;
 case N_RF_CTL_OVER_CMD_RX_GAIN:
  tmp = value & 0xFF;
  b43_nphy_rf_ctl_override_rev7(dev, 0x0800, tmp, core, off, 0);
  tmp = value >> 8;
  b43_nphy_rf_ctl_override_rev7(dev, 0x6000, tmp, core, off, 0);
  break;
 case N_RF_CTL_OVER_CMD_TX_GAIN:
  tmp = value & 0x7FFF;
  b43_nphy_rf_ctl_override_rev7(dev, 0x1000, tmp, core, off, 0);
  tmp = value >> 14;
  b43_nphy_rf_ctl_override_rev7(dev, 0x4000, tmp, core, off, 0);
  break;
 }
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
static void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field,
         u16 value, u8 core, bool off)
{
 int i;
 u8 index = fls(field);
 u8 addr, en_addr, val_addr;
 /* we expect only one bit set */
 B43_WARN_ON(field & (~(1 << (index - 1))));

 if (dev->phy.rev >= 3) {
  const struct nphy_rf_control_override_rev3 *rf_ctrl;
  for (i = 0; i < 2; i++) {
   if (index == 0 || index == 16) {
    b43err(dev->wl,
     "Unsupported RF Ctrl Override call\n");
    return;
   }

   rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
   en_addr = B43_PHY_N((i == 0) ?
    rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
   val_addr = B43_PHY_N((i == 0) ?
    rf_ctrl->val_addr0 : rf_ctrl->val_addr1);

   if (off) {
    b43_phy_mask(dev, en_addr, ~(field));
    b43_phy_mask(dev, val_addr,
      ~(rf_ctrl->val_mask));
   } else {
    if (core == 0 || ((1 << i) & core)) {
     b43_phy_set(dev, en_addr, field);
     b43_phy_maskset(dev, val_addr,
      ~(rf_ctrl->val_mask),
      (value << rf_ctrl->val_shift));
    }
   }
  }
 } else {
  const struct nphy_rf_control_override_rev2 *rf_ctrl;
  if (off) {
   b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field));
   value = 0;
  } else {
   b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field);
  }

  for (i = 0; i < 2; i++) {
   if (index <= 1 || index == 16) {
    b43err(dev->wl,
     "Unsupported RF Ctrl Override call\n");
    return;
   }

   if (index == 2 || index == 10 ||
       (index >= 13 && index <= 15)) {
    core = 1;
   }

   rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
   addr = B43_PHY_N((i == 0) ?
    rf_ctrl->addr0 : rf_ctrl->addr1);

   if ((1 << i) & core)
    b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask),
      (value << rf_ctrl->shift));

   b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
   b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
     B43_NPHY_RFCTL_CMD_START);
   udelay(1);
   b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE);
  }
 }
}

static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev,
            enum n_intc_override intc_override,
            u16 value, u8 core_sel)
{
 u16 reg, tmp, tmp2, val;
 int core;

 /* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */

 for (core = 0; core < 2; core++) {
  if ((core_sel == 1 && core != 0) ||
      (core_sel == 2 && core != 1))
   continue;

  reg = (core == 0) ? B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;

  switch (intc_override) {
  case N_INTC_OVERRIDE_OFF:
   b43_phy_write(dev, reg, 0);
   b43_phy_mask(dev, 0x2ff, ~0x2000);
   b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
   break;
  case N_INTC_OVERRIDE_TRSW:
   b43_phy_maskset(dev, reg, ~0xC0, value << 6);
   b43_phy_set(dev, reg, 0x400);

   b43_phy_mask(dev, 0x2ff, ~0xC000 & 0xFFFF);
   b43_phy_set(dev, 0x2ff, 0x2000);
   b43_phy_set(dev, 0x2ff, 0x0001);
   break;
  case N_INTC_OVERRIDE_PA:
   tmp = 0x0030;
   if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
    val = value << 5;
   else
    val = value << 4;
   b43_phy_maskset(dev, reg, ~tmp, val);
   b43_phy_set(dev, reg, 0x1000);
   break;
  case N_INTC_OVERRIDE_EXT_LNA_PU:
   if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
    tmp = 0x0001;
    tmp2 = 0x0004;
    val = value;
   } else {
    tmp = 0x0004;
    tmp2 = 0x0001;
    val = value << 2;
   }
   b43_phy_maskset(dev, reg, ~tmp, val);
   b43_phy_mask(dev, reg, ~tmp2);
   break;
  case N_INTC_OVERRIDE_EXT_LNA_GAIN:
   if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
    tmp = 0x0002;
    tmp2 = 0x0008;
    val = value << 1;
   } else {
    tmp = 0x0008;
    tmp2 = 0x0002;
    val = value << 3;
   }
   b43_phy_maskset(dev, reg, ~tmp, val);
   b43_phy_mask(dev, reg, ~tmp2);
   break;
  }
 }
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
static void b43_nphy_rf_ctl_intc_override(struct b43_wldev *dev,
       enum n_intc_override intc_override,
       u16 value, u8 core)
{
 u8 i, j;
 u16 reg, tmp, val;

 if (dev->phy.rev >= 7) {
  b43_nphy_rf_ctl_intc_override_rev7(dev, intc_override, value,
         core);
  return;
 }

 B43_WARN_ON(dev->phy.rev < 3);

 for (i = 0; i < 2; i++) {
  if ((core == 1 && i == 1) || (core == 2 && !i))
   continue;

  reg = (i == 0) ?
   B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
  b43_phy_set(dev, reg, 0x400);

  switch (intc_override) {
  case N_INTC_OVERRIDE_OFF:
   b43_phy_write(dev, reg, 0);
   b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
   break;
  case N_INTC_OVERRIDE_TRSW:
   if (!i) {
    b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1,
      0xFC3F, (value << 6));
    b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1,
      0xFFFE, 1);
    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)) {
      j = 0;
      break;
     }
     udelay(10);
    }
    if (j)
     b43err(dev->wl,
      "intc override timeout\n");
    b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1,
      0xFFFE);
   } else {
    b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2,
      0xFC3F, (value << 6));
    b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
      0xFFFE, 1);
    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)) {
      j = 0;
      break;
     }
     udelay(10);
    }
    if (j)
     b43err(dev->wl,
      "intc override timeout\n");
    b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
      0xFFFE);
   }
   break;
  case N_INTC_OVERRIDE_PA:
   if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
    tmp = 0x0020;
    val = value << 5;
   } else {
    tmp = 0x0010;
    val = value << 4;
   }
   b43_phy_maskset(dev, reg, ~tmp, val);
   break;
  case N_INTC_OVERRIDE_EXT_LNA_PU:
   if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
    tmp = 0x0001;
    val = value;
   } else {
    tmp = 0x0004;
    val = value << 2;
   }
   b43_phy_maskset(dev, reg, ~tmp, val);
   break;
  case N_INTC_OVERRIDE_EXT_LNA_GAIN:
   if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
    tmp = 0x0002;
    val = value << 1;
   } else {
    tmp = 0x0008;
    val = value << 3;
   }
   b43_phy_maskset(dev, reg, ~tmp, val);
   break;
  }
 }
}

/**************************************************
 * Various PHY ops
 **************************************************/


/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
static void b43_nphy_write_clip_detection(struct b43_wldev *dev,
       const u16 *clip_st)
{
 b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
 b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
{
 clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
 clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
{
 u16 tmp;

 if (dev->dev->core_rev == 16)
  b43_mac_suspend(dev);

 tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
 tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
  B43_NPHY_CLASSCTL_WAITEDEN);
 tmp &= ~mask;
 tmp |= (val & mask);
 b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);

 if (dev->dev->core_rev == 16)
  b43_mac_enable(dev);

 return tmp;
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
static void b43_nphy_reset_cca(struct b43_wldev *dev)
{
 u16 bbcfg;

 b43_phy_force_clock(dev, 1);
 bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
 b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
 udelay(1);
 b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
 b43_phy_force_clock(dev, 0);
 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
{
 struct b43_phy *phy = &dev->phy;
 struct b43_phy_n *nphy = phy->n;

 if (enable) {
  static const u16 clip[] = { 0xFFFF, 0xFFFF };
  if (nphy->deaf_count++ == 0) {
   nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
   b43_nphy_classifier(dev, 0x7,
         B43_NPHY_CLASSCTL_WAITEDEN);
   b43_nphy_read_clip_detection(dev, nphy->clip_state);
   b43_nphy_write_clip_detection(dev, clip);
  }
  b43_nphy_reset_cca(dev);
 } else {
  if (--nphy->deaf_count == 0) {
   b43_nphy_classifier(dev, 0x7, nphy->classifier_state);
   b43_nphy_write_clip_detection(dev, nphy->clip_state);
  }
 }
}

/* https://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
{
 if (!offset)
  offset = b43_is_40mhz(dev) ? 0x159 : 0x154;
 return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
{
 struct b43_phy_n *nphy = dev->phy.n;

 u8 i;
 s16 tmp;
 u16 data[4];
 s16 gain[2];
 u16 minmax[2];
 static const s16 lna_gain[4] = { -2, 10, 19, 25 };

 if (nphy->hang_avoid)
  b43_nphy_stay_in_carrier_search(dev, 1);

 if (nphy->gain_boost) {
  if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   gain[0] = 6;
   gain[1] = 6;
  } else {
   tmp = 40370 - 315 * dev->phy.channel;
   gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
   tmp = 23242 - 224 * dev->phy.channel;
   gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
  }
 } else {
  gain[0] = 0;
  gain[1] = 0;
 }

 for (i = 0; i < 2; i++) {
  if (nphy->elna_gain_config) {
   data[0] = 19 + gain[i];
   data[1] = 25 + gain[i];
   data[2] = 25 + gain[i];
   data[3] = 25 + gain[i];
  } else {
   data[0] = lna_gain[0] + gain[i];
   data[1] = lna_gain[1] + gain[i];
   data[2] = lna_gain[2] + gain[i];
   data[3] = lna_gain[3] + gain[i];
  }
  b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data);

  minmax[i] = 23 + gain[i];
 }

 b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN,
    minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT);
 b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN,
    minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT);

 if (nphy->hang_avoid)
  b43_nphy_stay_in_carrier_search(dev, 0);
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
     u8 *events, u8 *delays, u8 length)
{
 struct b43_phy_n *nphy = dev->phy.n;
 u8 i;
 u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F;
 u16 offset1 = cmd << 4;
 u16 offset2 = offset1 + 0x80;

 if (nphy->hang_avoid)
  b43_nphy_stay_in_carrier_search(dev, true);

 b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events);
 b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays);

 for (i = length; i < 16; i++) {
  b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end);
  b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1);
 }

 if (nphy->hang_avoid)
  b43_nphy_stay_in_carrier_search(dev, false);
}

/**************************************************
 * Radio 0x2057
 **************************************************/


static void b43_radio_2057_chantab_upload(struct b43_wldev *dev,
       const struct b43_nphy_chantabent_rev7 *e_r7,
       const struct b43_nphy_chantabent_rev7_2g *e_r7_2g)
{
 if (e_r7_2g) {
  b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7_2g->radio_vcocal_countval0);
  b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7_2g->radio_vcocal_countval1);
  b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7_2g->radio_rfpll_refmaster_sparextalsize);
  b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7_2g->radio_rfpll_loopfilter_r1);
  b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7_2g->radio_rfpll_loopfilter_c2);
  b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7_2g->radio_rfpll_loopfilter_c1);
  b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7_2g->radio_cp_kpd_idac);
  b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7_2g->radio_rfpll_mmd0);
  b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7_2g->radio_rfpll_mmd1);
  b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7_2g->radio_vcobuf_tune);
  b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7_2g->radio_logen_mx2g_tune);
  b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7_2g->radio_logen_indbuf2g_tune);
  b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7_2g->radio_txmix2g_tune_boost_pu_core0);
  b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7_2g->radio_pad2g_tune_pus_core0);
  b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7_2g->radio_lna2g_tune_core0);
  b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7_2g->radio_txmix2g_tune_boost_pu_core1);
  b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7_2g->radio_pad2g_tune_pus_core1);
  b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7_2g->radio_lna2g_tune_core1);

 } else {
  b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7->radio_vcocal_countval0);
  b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7->radio_vcocal_countval1);
  b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7->radio_rfpll_refmaster_sparextalsize);
  b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7->radio_rfpll_loopfilter_r1);
  b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7->radio_rfpll_loopfilter_c2);
  b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7->radio_rfpll_loopfilter_c1);
  b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7->radio_cp_kpd_idac);
  b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7->radio_rfpll_mmd0);
  b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7->radio_rfpll_mmd1);
  b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7->radio_vcobuf_tune);
  b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7->radio_logen_mx2g_tune);
  b43_radio_write(dev, R2057_LOGEN_MX5G_TUNE, e_r7->radio_logen_mx5g_tune);
  b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7->radio_logen_indbuf2g_tune);
  b43_radio_write(dev, R2057_LOGEN_INDBUF5G_TUNE, e_r7->radio_logen_indbuf5g_tune);
  b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7->radio_txmix2g_tune_boost_pu_core0);
  b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7->radio_pad2g_tune_pus_core0);
  b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE0, e_r7->radio_pga_boost_tune_core0);
  b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE0, e_r7->radio_txmix5g_boost_tune_core0);
  b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE0, e_r7->radio_pad5g_tune_misc_pus_core0);
  b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7->radio_lna2g_tune_core0);
  b43_radio_write(dev, R2057_LNA5G_TUNE_CORE0, e_r7->radio_lna5g_tune_core0);
  b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7->radio_txmix2g_tune_boost_pu_core1);
  b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7->radio_pad2g_tune_pus_core1);
  b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE1, e_r7->radio_pga_boost_tune_core1);
  b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE1, e_r7->radio_txmix5g_boost_tune_core1);
  b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE1, e_r7->radio_pad5g_tune_misc_pus_core1);
  b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7->radio_lna2g_tune_core1);
  b43_radio_write(dev, R2057_LNA5G_TUNE_CORE1, e_r7->radio_lna5g_tune_core1);
 }
}

static void b43_radio_2057_setup(struct b43_wldev *dev,
     const struct b43_nphy_chantabent_rev7 *tabent_r7,
     const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g)
{
 struct b43_phy *phy = &dev->phy;

 b43_radio_2057_chantab_upload(dev, tabent_r7, tabent_r7_2g);

 switch (phy->radio_rev) {
 case 0 ... 4:
 case 6:
  if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x3f);
   b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
   b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8);
   b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
  } else {
   b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1f);
   b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
   b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8);
   b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
  }
  break;
 case 9: /* e.g. PHY rev 16 */
  b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x20);
  b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x18);
  if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
   b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x38);
   b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x0f);

   if (b43_is_40mhz(dev)) {
    /* TODO */
   } else {
    b43_radio_write(dev,
      R2057_PAD_BIAS_FILTER_BWS_CORE0,
      0x3c);
    b43_radio_write(dev,
      R2057_PAD_BIAS_FILTER_BWS_CORE1,
      0x3c);
   }
  }
  break;
 case 14: /* 2 GHz only */
  b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1b);
  b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
  b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x1f);
  b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x1f);
  break;
 }

 if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
  u16 txmix2g_tune_boost_pu = 0;
  u16 pad2g_tune_pus = 0;

  if (b43_nphy_ipa(dev)) {
   switch (phy->radio_rev) {
   case 9:
    txmix2g_tune_boost_pu = 0x0041;
    /* TODO */
    break;
   case 14:
    txmix2g_tune_boost_pu = 0x21;
    pad2g_tune_pus = 0x23;
    break;
   }
  }

  if (txmix2g_tune_boost_pu)
   b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
     txmix2g_tune_boost_pu);
  if (pad2g_tune_pus)
   b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0,
     pad2g_tune_pus);
  if (txmix2g_tune_boost_pu)
   b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
     txmix2g_tune_boost_pu);
  if (pad2g_tune_pus)
   b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1,
     pad2g_tune_pus);
 }

 usleep_range(50, 100);

 /* VCO calibration */
 b43_radio_mask(dev, R2057_RFPLL_MISC_EN, ~0x01);
 b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x04);
 b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x4);
 b43_radio_set(dev, R2057_RFPLL_MISC_EN, 0x01);
 usleep_range(300, 600);
}

/* Calibrate resistors in LPF of PLL?
 * https://bcm-v4.sipsolutions.net/PHY/radio205x_rcal
 */

static u8 b43_radio_2057_rcal(struct b43_wldev *dev)
{
 struct b43_phy *phy = &dev->phy;
 u16 saved_regs_phy[12];
 u16 saved_regs_phy_rf[6];
 u16 saved_regs_radio[2] = { };
 static const u16 phy_to_store[] = {
  B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2,
  B43_NPHY_RFCTL_LUT_TRSW_LO1, B43_NPHY_RFCTL_LUT_TRSW_LO2,
  B43_NPHY_RFCTL_RXG1, B43_NPHY_RFCTL_RXG2,
  B43_NPHY_RFCTL_TXG1, B43_NPHY_RFCTL_TXG2,
  B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
  B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
 };
 static const u16 phy_to_store_rf[] = {
  B43_NPHY_REV3_RFCTL_OVER0, B43_NPHY_REV3_RFCTL_OVER1,
  B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
  B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
 };
 u16 tmp;
 int i;

 /* Save */
 for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
  saved_regs_phy[i] = b43_phy_read(dev, phy_to_store[i]);
 for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
  saved_regs_phy_rf[i] = b43_phy_read(dev, phy_to_store_rf[i]);

 /* Set */
 for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
  b43_phy_write(dev, phy_to_store[i], 0);
 b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER0, 0x07ff);
 b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER1, 0x07ff);
 b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x07ff);
 b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0x07ff);
 b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0x007f);
 b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0x007f);

 switch (phy->radio_rev) {
 case 5:
  b43_phy_mask(dev, B43_NPHY_REV7_RF_CTL_OVER3, ~0x2);
  udelay(10);
  b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1);
  b43_radio_maskset(dev, R2057v7_IQTEST_SEL_PU2, ~0x2, 0x1);
  break;
 case 9:
  b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
  b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
  saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
  b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x11);
  break;
 case 14:
  saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
  saved_regs_radio[1] = b43_radio_read(dev, R2057v7_IQTEST_SEL_PU2);
  b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
  b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
  b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, 0x2);
  b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x1);
  break;
 }

 /* Enable */
 b43_radio_set(dev, R2057_RCAL_CONFIG, 0x1);
 udelay(10);

 /* Start */
 b43_radio_set(dev, R2057_RCAL_CONFIG, 0x2);
 usleep_range(100, 200);

 /* Stop */
 b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2);

 /* Wait and check for result */
 if (!b43_radio_wait_value(dev, R2057_RCAL_STATUS, 1, 1, 100, 1000000)) {
  b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
  return 0;
 }
 tmp = b43_radio_read(dev, R2057_RCAL_STATUS) & 0x3E;

 /* Disable */
 b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1);

 /* Restore */
 for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
  b43_phy_write(dev, phy_to_store_rf[i], saved_regs_phy_rf[i]);
 for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
  b43_phy_write(dev, phy_to_store[i], saved_regs_phy[i]);

 switch (phy->radio_rev) {
 case 0 ... 4:
 case 6:
  b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp);
  b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0,
      tmp << 2);
  break;
 case 5:
  b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1);
  b43_radio_mask(dev, R2057v7_IQTEST_SEL_PU2, ~0x2);
  break;
 case 9:
  b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
  break;
 case 14:
  b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
  b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, saved_regs_radio[1]);
  break;
 }

 return tmp & 0x3e;
}

/* Calibrate the internal RC oscillator?
 * https://bcm-v4.sipsolutions.net/PHY/radio2057_rccal
 */

static u16 b43_radio_2057_rccal(struct b43_wldev *dev)
{
 struct b43_phy *phy = &dev->phy;
 bool special = (phy->radio_rev == 3 || phy->radio_rev == 4 ||
   phy->radio_rev == 6);
 u16 tmp;

 /* Setup cal */
 if (special) {
  b43_radio_write(dev, R2057_RCCAL_MASTER, 0x61);
  b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0);
 } else {
  b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x61);
  b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE9);
 }
 b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);

 /* Start, wait, stop */
 b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
 if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
      5000000))
  b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
 usleep_range(35, 70);
 b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
 usleep_range(70, 140);

 /* Setup cal */
 if (special) {
  b43_radio_write(dev, R2057_RCCAL_MASTER, 0x69);
  b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
 } else {
  b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x69);
  b43_radio_write(dev, R2057_RCCAL_TRC0, 0xD5);
 }
 b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);

 /* Start, wait, stop */
 usleep_range(35, 70);
 b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
 usleep_range(70, 140);
 if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
      5000000))
  b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
 usleep_range(35, 70);
 b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
 usleep_range(70, 140);

 /* Setup cal */
 if (special) {
  b43_radio_write(dev, R2057_RCCAL_MASTER, 0x73);
  b43_radio_write(dev, R2057_RCCAL_X1, 0x28);
  b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
 } else {
  b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x73);
  b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
  b43_radio_write(dev, R2057_RCCAL_TRC0, 0x99);
 }

 /* Start, wait, stop */
 usleep_range(35, 70);
 b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
 usleep_range(70, 140);
 if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
      5000000)) {
  b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
  return 0;
 }
 tmp = b43_radio_read(dev, R2057_RCCAL_DONE_OSCCAP);
 usleep_range(35, 70);
 b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
 usleep_range(70, 140);

 if (special)
  b43_radio_mask(dev, R2057_RCCAL_MASTER, ~0x1);
 else
  b43_radio_mask(dev, R2057v7_RCCAL_MASTER, ~0x1);

 return tmp;
}

static void b43_radio_2057_init_pre(struct b43_wldev *dev)
{
 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_CHIP0PU);
 /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_OEPORFORCE);
 b43_phy_set(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
 b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_CHIP0PU);
}

static void b43_radio_2057_init_post(struct b43_wldev *dev)
{
 b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1);

 if (0) /* FIXME: Is this BCM43217 specific? */
  b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x2);

 b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78);
 b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80);
 usleep_range(2000, 3000);
 b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x78);
 b43_radio_mask(dev, R2057_XTAL_CONFIG2, ~0x80);

 if (dev->phy.do_full_init) {
  b43_radio_2057_rcal(dev);
  b43_radio_2057_rccal(dev);
 }
 b43_radio_mask(dev, R2057_RFPLL_MASTER, ~0x8);
}

/* https://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */
static void b43_radio_2057_init(struct b43_wldev *dev)
{
 b43_radio_2057_init_pre(dev);
 r2057_upload_inittabs(dev);
 b43_radio_2057_init_post(dev);
}

/**************************************************
 * Radio 0x2056
 **************************************************/


static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
    const struct b43_nphy_channeltab_entry_rev3 *e)
{
 b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1);
 b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2);
 b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv);
 b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2);
 b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1);
 b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1,
     e->radio_syn_pll_loopfilter1);
 b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2,
     e->radio_syn_pll_loopfilter2);
 b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3,
     e->radio_syn_pll_loopfilter3);
 b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4,
     e->radio_syn_pll_loopfilter4);
 b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5,
     e->radio_syn_pll_loopfilter5);
 b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27,
     e->radio_syn_reserved_addr27);
 b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28,
     e->radio_syn_reserved_addr28);
 b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29,
     e->radio_syn_reserved_addr29);
 b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1,
     e->radio_syn_logen_vcobuf1);
 b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2);
 b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3);
 b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4);

 b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE,
     e->radio_rx0_lnaa_tune);
 b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE,
     e->radio_rx0_lnag_tune);

 b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE,
     e->radio_tx0_intpaa_boost_tune);
 b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE,
     e->radio_tx0_intpag_boost_tune);
 b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE,
     e->radio_tx0_pada_boost_tune);
 b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE,
     e->radio_tx0_padg_boost_tune);
 b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE,
     e->radio_tx0_pgaa_boost_tune);
 b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE,
     e->radio_tx0_pgag_boost_tune);
 b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE,
     e->radio_tx0_mixa_boost_tune);
 b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE,
     e->radio_tx0_mixg_boost_tune);

 b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE,
     e->radio_rx1_lnaa_tune);
 b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE,
     e->radio_rx1_lnag_tune);

 b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE,
     e->radio_tx1_intpaa_boost_tune);
 b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE,
     e->radio_tx1_intpag_boost_tune);
 b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE,
     e->radio_tx1_pada_boost_tune);
 b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE,
     e->radio_tx1_padg_boost_tune);
 b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE,
     e->radio_tx1_pgaa_boost_tune);
 b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE,
     e->radio_tx1_pgag_boost_tune);
 b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE,
     e->radio_tx1_mixa_boost_tune);
 b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE,
     e->radio_tx1_mixg_boost_tune);
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
static void b43_radio_2056_setup(struct b43_wldev *dev,
    const struct b43_nphy_channeltab_entry_rev3 *e)
{
 struct b43_phy *phy = &dev->phy;
 struct ssb_sprom *sprom = dev->dev->bus_sprom;
 enum nl80211_band band = b43_current_band(dev->wl);
 u16 offset;
 u8 i;
 u16 bias, cbias;
 u16 pag_boost, padg_boost, pgag_boost, mixg_boost;
 u16 paa_boost, pada_boost, pgaa_boost, mixa_boost;
 bool is_pkg_fab_smic;

 B43_WARN_ON(dev->phy.rev < 3);

 is_pkg_fab_smic =
  ((dev->dev->chip_id == BCMA_CHIP_ID_BCM43224 ||
    dev->dev->chip_id == BCMA_CHIP_ID_BCM43225 ||
    dev->dev->chip_id == BCMA_CHIP_ID_BCM43421) &&
   dev->dev->chip_pkg == BCMA_PKG_ID_BCM43224_FAB_SMIC);

 b43_chantab_radio_2056_upload(dev, e);
 b2056_upload_syn_pll_cp2(dev, band == NL80211_BAND_5GHZ);

 if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
     b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
  b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
  b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
  if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
      dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) {
   b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14);
   b43_radio_write(dev, B2056_SYN_PLL_CP2, 0);
  } else {
   b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0B);
   b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14);
  }
 }
 if (sprom->boardflags2_hi & B43_BFH2_GPLL_WAR2 &&
     b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
  b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1f);
  b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1f);
  b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0b);
  b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x20);
 }
 if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
     b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
  b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
  b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
  b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05);
  b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C);
 }

 if (dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) {
  for (i = 0; i < 2; i++) {
   offset = i ? B2056_TX1 : B2056_TX0;
   if (dev->phy.rev >= 5) {
    b43_radio_write(dev,
     offset | B2056_TX_PADG_IDAC, 0xcc);

    if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
        dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) {
     bias = 0x40;
     cbias = 0x45;
     pag_boost = 0x5;
     pgag_boost = 0x33;
     mixg_boost = 0x55;
    } else {
     bias = 0x25;
     cbias = 0x20;
     if (is_pkg_fab_smic) {
      bias = 0x2a;
      cbias = 0x38;
     }
     pag_boost = 0x4;
     pgag_boost = 0x03;
     mixg_boost = 0x65;
    }
    padg_boost = 0x77;

    b43_radio_write(dev,
     offset | B2056_TX_INTPAG_IMAIN_STAT,
     bias);
    b43_radio_write(dev,
     offset | B2056_TX_INTPAG_IAUX_STAT,
     bias);
    b43_radio_write(dev,
     offset | B2056_TX_INTPAG_CASCBIAS,
     cbias);
    b43_radio_write(dev,
     offset | B2056_TX_INTPAG_BOOST_TUNE,
     pag_boost);
    b43_radio_write(dev,
     offset | B2056_TX_PGAG_BOOST_TUNE,
     pgag_boost);
    b43_radio_write(dev,
     offset | B2056_TX_PADG_BOOST_TUNE,
     padg_boost);
    b43_radio_write(dev,
     offset | B2056_TX_MIXG_BOOST_TUNE,
     mixg_boost);
   } else {
    bias = b43_is_40mhz(dev) ? 0x40 : 0x20;
    b43_radio_write(dev,
     offset | B2056_TX_INTPAG_IMAIN_STAT,
     bias);
    b43_radio_write(dev,
     offset | B2056_TX_INTPAG_IAUX_STAT,
     bias);
    b43_radio_write(dev,
     offset | B2056_TX_INTPAG_CASCBIAS,
     0x30);
   }
   b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
  }
 } else if (dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ) {
  u16 freq = phy->chandef->chan->center_freq;
  if (freq < 5100) {
   paa_boost = 0xA;
   pada_boost = 0x77;
   pgaa_boost = 0xF;
   mixa_boost = 0xF;
  } else if (freq < 5340) {
   paa_boost = 0x8;
   pada_boost = 0x77;
   pgaa_boost = 0xFB;
   mixa_boost = 0xF;
  } else if (freq < 5650) {
   paa_boost = 0x0;
   pada_boost = 0x77;
   pgaa_boost = 0xB;
   mixa_boost = 0xF;
  } else {
   paa_boost = 0x0;
   pada_boost = 0x77;
   if (freq != 5825)
    pgaa_boost = -(freq - 18) / 36 + 168;
   else
    pgaa_boost = 6;
   mixa_boost = 0xF;
  }

  cbias = is_pkg_fab_smic ? 0x35 : 0x30;

  for (i = 0; i < 2; i++) {
   offset = i ? B2056_TX1 : B2056_TX0;

   b43_radio_write(dev,
    offset | B2056_TX_INTPAA_BOOST_TUNE, paa_boost);
   b43_radio_write(dev,
    offset | B2056_TX_PADA_BOOST_TUNE, pada_boost);
   b43_radio_write(dev,
    offset | B2056_TX_PGAA_BOOST_TUNE, pgaa_boost);
   b43_radio_write(dev,
    offset | B2056_TX_MIXA_BOOST_TUNE, mixa_boost);
   b43_radio_write(dev,
    offset | B2056_TX_TXSPARE1, 0x30);
   b43_radio_write(dev,
    offset | B2056_TX_PA_SPARE2, 0xee);
   b43_radio_write(dev,
    offset | B2056_TX_PADA_CASCBIAS, 0x03);
   b43_radio_write(dev,
    offset | B2056_TX_INTPAA_IAUX_STAT, 0x30);
   b43_radio_write(dev,
    offset | B2056_TX_INTPAA_IMAIN_STAT, 0x30);
   b43_radio_write(dev,
    offset | B2056_TX_INTPAA_CASCBIAS, cbias);
  }
 }

 udelay(50);
 /* VCO calibration */
 b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
 b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
 b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18);
 b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
 b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39);
 udelay(300);
}

static u8 b43_radio_2056_rcal(struct b43_wldev *dev)
{
 struct b43_phy *phy = &dev->phy;
 u16 mast2, tmp;

 if (phy->rev != 3)
  return 0;

 mast2 = b43_radio_read(dev, B2056_SYN_PLL_MAST2);
 b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2 | 0x7);

 udelay(10);
 b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01);
 udelay(10);
 b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x09);

 if (!b43_radio_wait_value(dev, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100,
      1000000)) {
  b43err(dev->wl, "Radio recalibration timeout\n");
  return 0;
 }

 b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01);
 tmp = b43_radio_read(dev, B2056_SYN_RCAL_CODE_OUT);
 b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x00);

 b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2);

 return tmp & 0x1f;
}

static void b43_radio_init2056_pre(struct b43_wldev *dev)
{
 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
       ~B43_NPHY_RFCTL_CMD_CHIP0PU);
 /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
       B43_NPHY_RFCTL_CMD_OEPORFORCE);
 b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
      ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
 b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
      B43_NPHY_RFCTL_CMD_CHIP0PU);
}

static void b43_radio_init2056_post(struct b43_wldev *dev)
{
 b43_radio_set(dev, B2056_SYN_COM_CTRL, 0xB);
 b43_radio_set(dev, B2056_SYN_COM_PU, 0x2);
 b43_radio_set(dev, B2056_SYN_COM_RESET, 0x2);
 msleep(1);
 b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2);
 b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC);
 b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1);
 if (dev->phy.do_full_init)
  b43_radio_2056_rcal(dev);
}

/*
 * Initialize a Broadcom 2056 N-radio
 * https://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
 */

static void b43_radio_init2056(struct b43_wldev *dev)
{
 b43_radio_init2056_pre(dev);
 b2056_upload_inittabs(dev, 0, 0);
 b43_radio_init2056_post(dev);
}

/**************************************************
 * Radio 0x2055
 **************************************************/


static void b43_chantab_radio_upload(struct b43_wldev *dev,
    const struct b43_nphy_channeltab_entry_rev2 *e)
{
 b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref);
 b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
 b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
 b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
 b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */

 b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
 b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
 b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
 b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
 b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */

 b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
 b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
 b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
 b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
 b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */

 b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
 b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
 b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
 b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
 b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */

 b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
 b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
 b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
 b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
 b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */

 b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
 b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
static void b43_radio_2055_setup(struct b43_wldev *dev,
    const struct b43_nphy_channeltab_entry_rev2 *e)
{
 B43_WARN_ON(dev->phy.rev >= 3);

 b43_chantab_radio_upload(dev, e);
 udelay(50);
 b43_radio_write(dev, B2055_VCO_CAL10, 0x05);
 b43_radio_write(dev, B2055_VCO_CAL10, 0x45);
 b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
 b43_radio_write(dev, B2055_VCO_CAL10, 0x65);
 udelay(300);
}

static void b43_radio_init2055_pre(struct b43_wldev *dev)
{
 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
       ~B43_NPHY_RFCTL_CMD_PORFORCE);
 b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
      B43_NPHY_RFCTL_CMD_CHIP0PU |
      B43_NPHY_RFCTL_CMD_OEPORFORCE);
 b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
      B43_NPHY_RFCTL_CMD_PORFORCE);
}

static void b43_radio_init2055_post(struct b43_wldev *dev)
{
 struct b43_phy_n *nphy = dev->phy.n;
 struct ssb_sprom *sprom = dev->dev->bus_sprom;
 bool workaround = false;

 if (sprom->revision < 4)
  workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
         && dev->dev->board_type == SSB_BOARD_CB2_4321
         && dev->dev->board_rev >= 0x41);
 else
  workaround =
   !(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);

 b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
 if (workaround) {
  b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
  b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F);
 }
 b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C);
 b43_radio_write(dev, B2055_CAL_MISC, 0x3C);
 b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
 b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
 b43_radio_set(dev, B2055_CAL_MISC, 0x1);
 msleep(1);
 b43_radio_set(dev, B2055_CAL_MISC, 0x40);
 if (!b43_radio_wait_value(dev, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000))
  b43err(dev->wl, "radio post init timeout\n");
 b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
 b43_switch_channel(dev, dev->phy.channel);
 b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9);
 b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9);
 b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
 b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
 b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6);
 b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6);
 if (!nphy->gain_boost) {
  b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2);
  b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2);
 } else {
  b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD);
  b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD);
 }
 udelay(2);
}

/*
 * Initialize a Broadcom 2055 N-radio
 * https://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
 */

static void b43_radio_init2055(struct b43_wldev *dev)
{
 b43_radio_init2055_pre(dev);
 if (b43_status(dev) < B43_STAT_INITIALIZED) {
  /* Follow wl, not specs. Do not force uploading all regs */
  b2055_upload_inittab(dev, 0, 0);
 } else {
  bool ghz5 = b43_current_band(dev->wl) == NL80211_BAND_5GHZ;
  b2055_upload_inittab(dev, ghz5, 0);
 }
 b43_radio_init2055_post(dev);
}

/**************************************************
 * Samples
 **************************************************/


/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
static int b43_nphy_load_samples(struct b43_wldev *dev,
     struct cordic_iq *samples, u16 len) {
 struct b43_phy_n *nphy = dev->phy.n;
 u16 i;
 u32 *data;

 data = kcalloc(len, sizeof(u32), GFP_KERNEL);
 if (!data) {
  b43err(dev->wl, "allocation for samples loading failed\n");
  return -ENOMEM;
 }
 if (nphy->hang_avoid)
  b43_nphy_stay_in_carrier_search(dev, 1);

 for (i = 0; i < len; i++) {
  data[i] = (samples[i].i & 0x3FF << 10);
  data[i] |= samples[i].q & 0x3FF;
 }
 b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data);

 kfree(data);
 if (nphy->hang_avoid)
  b43_nphy_stay_in_carrier_search(dev, 0);
 return 0;
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
     bool test)
{
 int i;
 u16 bw, len, rot, angle;
 struct cordic_iq *samples;

 bw = b43_is_40mhz(dev) ? 40 : 20;
 len = bw << 3;

 if (test) {
  if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX)
   bw = 82;
  else
   bw = 80;

  if (b43_is_40mhz(dev))
   bw <<= 1;

  len = bw << 1;
 }

 samples = kcalloc(len, sizeof(struct cordic_iq), GFP_KERNEL);
 if (!samples) {
  b43err(dev->wl, "allocation for samples generation failed\n");
  return 0;
 }
 rot = (((freq * 36) / bw) << 16) / 100;
 angle = 0;

 for (i = 0; i < len; i++) {
  samples[i] = cordic_calc_iq(CORDIC_FIXED(angle));
  angle += rot;
  samples[i].q = CORDIC_FLOAT(samples[i].q * max);
  samples[i].i = CORDIC_FLOAT(samples[i].i * max);
 }

 i = b43_nphy_load_samples(dev, samples, len);
 kfree(samples);
 return (i < 0) ? 0 : len;
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
     u16 wait, bool iqmode, bool dac_test,
     bool modify_bbmult)
{
 struct b43_phy *phy = &dev->phy;
 struct b43_phy_n *nphy = dev->phy.n;
 int i;
 u16 seq_mode;
 u32 tmp;

 b43_nphy_stay_in_carrier_search(dev, true);

 if (phy->rev >= 7) {
  bool lpf_bw3, lpf_bw4;

  lpf_bw3 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER3) & 0x80;
  lpf_bw4 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER4) & 0x80;

  if (lpf_bw3 || lpf_bw4) {
   /* TODO */
  } else {
   u16 value = b43_nphy_read_lpf_ctl(dev, 0);
   if (phy->rev >= 19)
    b43_nphy_rf_ctl_override_rev19(dev, 0x80, value,
              0, false, 1);
   else
    b43_nphy_rf_ctl_override_rev7(dev, 0x80, value,
             0, false, 1);
   nphy->lpf_bw_overrode_for_sample_play = true;
  }
 }

 if ((nphy->bb_mult_save & 0x80000000) == 0) {
  tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
  nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
 }

 if (modify_bbmult) {
  tmp = !b43_is_40mhz(dev) ? 0x6464 : 0x4747;
  b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
 }

 b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));

 if (loops != 0xFFFF)
  b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1));
 else
  b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops);

 b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait);

 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);

 b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER);
 if (iqmode) {
  b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
  b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
 } else {
  tmp = dac_test ? 5 : 1;
  b43_phy_write(dev, B43_NPHY_SAMP_CMD, tmp);
 }
 for (i = 0; i < 100; i++) {
  if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & 1)) {
   i = 0;
   break;
  }
  udelay(10);
 }
 if (i)
  b43err(dev->wl, "run samples timeout\n");

 b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);

 b43_nphy_stay_in_carrier_search(dev, false);
}

/**************************************************
 * RSSI
 **************************************************/


/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
     s8 offset, u8 core,
     enum n_rail_type rail,
     enum n_rssi_type rssi_type)
{
 u16 tmp;
 bool core1or5 = (core == 1) || (core == 5);
 bool core2or5 = (core == 2) || (core == 5);

 offset = clamp_val(offset, -32, 31);
 tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);

 switch (rssi_type) {
 case N_RSSI_NB:
  if (core1or5 && rail == N_RAIL_I)
   b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
  if (core1or5 && rail == N_RAIL_Q)
   b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
  if (core2or5 && rail == N_RAIL_I)
   b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
  if (core2or5 && rail == N_RAIL_Q)
   b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
  break;
 case N_RSSI_W1:
  if (core1or5 && rail == N_RAIL_I)
   b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
  if (core1or5 && rail == N_RAIL_Q)
   b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
  if (core2or5 && rail == N_RAIL_I)
   b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
  if (core2or5 && rail == N_RAIL_Q)
   b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
  break;
 case N_RSSI_W2:
  if (core1or5 && rail == N_RAIL_I)
   b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
  if (core1or5 && rail == N_RAIL_Q)
   b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
  if (core2or5 && rail == N_RAIL_I)
   b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
  if (core2or5 && rail == N_RAIL_Q)
   b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
  break;
 case N_RSSI_TBD:
  if (core1or5 && rail == N_RAIL_I)
   b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
  if (core1or5 && rail == N_RAIL_Q)
   b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
  if (core2or5 && rail == N_RAIL_I)
   b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
  if (core2or5 && rail == N_RAIL_Q)
   b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
  break;
 case N_RSSI_IQ:
  if (core1or5 && rail == N_RAIL_I)
   b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
  if (core1or5 && rail == N_RAIL_Q)
   b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
  if (core2or5 && rail == N_RAIL_I)
   b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
  if (core2or5 && rail == N_RAIL_Q)
   b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
  break;
 case N_RSSI_TSSI_2G:
  if (core1or5)
   b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
  if (core2or5)
   b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
  break;
 case N_RSSI_TSSI_5G:
  if (core1or5)
   b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
  if (core2or5)
   b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
  break;
 }
}

static void b43_nphy_rssi_select_rev19(struct b43_wldev *dev, u8 code,
           enum n_rssi_type rssi_type)
{
 /* TODO */
}

static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code,
          enum n_rssi_type rssi_type)
{
 u8 i;
 u16 reg, val;

 if (code == 0) {
  b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF);
  b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF);
  b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF);
  b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF);
  b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF);
  b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF);
  b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3);
  b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3);
 } else {
  for (i = 0; i < 2; i++) {
   if ((code == 1 && i == 1) || (code == 2 && !i))
    continue;

   reg = (i == 0) ?
    B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
   b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);

   if (rssi_type == N_RSSI_W1 ||
       rssi_type == N_RSSI_W2 ||
       rssi_type == N_RSSI_NB) {
    reg = (i == 0) ?
     B43_NPHY_AFECTL_C1 :
     B43_NPHY_AFECTL_C2;
    b43_phy_maskset(dev, reg, 0xFCFF, 0);

    reg = (i == 0) ?
     B43_NPHY_RFCTL_LUT_TRSW_UP1 :
     B43_NPHY_RFCTL_LUT_TRSW_UP2;
    b43_phy_maskset(dev, reg, 0xFFC3, 0);

    if (rssi_type == N_RSSI_W1)
     val = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 4 : 8;
    else if (rssi_type == N_RSSI_W2)
     val = 16;
    else
     val = 32;
    b43_phy_set(dev, reg, val);

    reg = (i == 0) ?
     B43_NPHY_TXF_40CO_B1S0 :
     B43_NPHY_TXF_40CO_B32S1;
    b43_phy_set(dev, reg, 0x0020);
   } else {
    if (rssi_type == N_RSSI_TBD)
     val = 0x0100;
    else if (rssi_type == N_RSSI_IQ)
     val = 0x0200;
    else
     val = 0x0300;

    reg = (i == 0) ?
     B43_NPHY_AFECTL_C1 :
     B43_NPHY_AFECTL_C2;

    b43_phy_maskset(dev, reg, 0xFCFF, val);
    b43_phy_maskset(dev, reg, 0xF3FF, val << 2);

    if (rssi_type != N_RSSI_IQ &&
        rssi_type != N_RSSI_TBD) {
     enum nl80211_band band =
      b43_current_band(dev->wl);

     if (dev->phy.rev < 7) {
      if (b43_nphy_ipa(dev))
       val = (band == NL80211_BAND_5GHZ) ? 0xC : 0xE;
      else
       val = 0x11;
      reg = (i == 0) ? B2056_TX0 : B2056_TX1;
      reg |= B2056_TX_TX_SSI_MUX;
      b43_radio_write(dev, reg, val);
     }

     reg = (i == 0) ?
      B43_NPHY_AFECTL_OVER1 :
      B43_NPHY_AFECTL_OVER;
     b43_phy_set(dev, reg, 0x0200);
    }
   }
  }
 }
}

static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code,
          enum n_rssi_type rssi_type)
{
 u16 val;
 bool rssi_w1_w2_nb = false;

 switch (rssi_type) {
 case N_RSSI_W1:
 case N_RSSI_W2:
 case N_RSSI_NB:
  val = 0;
  rssi_w1_w2_nb = true;
  break;
 case N_RSSI_TBD:
  val = 1;
  break;
 case N_RSSI_IQ:
  val = 2;
  break;
 default:
  val = 3;
 }

 val = (val << 12) | (val << 14);
 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);

 if (rssi_w1_w2_nb) {
  b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
    (rssi_type + 1) << 4);
  b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
    (rssi_type + 1) << 4);
 }

 if (code == 0) {
  b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
  if (rssi_w1_w2_nb) {
   b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
    ~(B43_NPHY_RFCTL_CMD_RXEN |
      B43_NPHY_RFCTL_CMD_CORESEL));
   b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
    ~(0x1 << 12 |
      0x1 << 5 |
      0x1 << 1 |
      0x1));
   b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
    ~B43_NPHY_RFCTL_CMD_START);
   udelay(20);
   b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
  }
 } else {
  b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000);
  if (rssi_w1_w2_nb) {
   b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
    ~(B43_NPHY_RFCTL_CMD_RXEN |
      B43_NPHY_RFCTL_CMD_CORESEL),
    (B43_NPHY_RFCTL_CMD_RXEN |
     code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT));
   b43_phy_set(dev, B43_NPHY_RFCTL_OVER,
    (0x1 << 12 |
      0x1 << 5 |
      0x1 << 1 |
      0x1));
   b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
    B43_NPHY_RFCTL_CMD_START);
   udelay(20);
   b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
  }
 }
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code,
     enum n_rssi_type type)
{
 if (dev->phy.rev >= 19)
  b43_nphy_rssi_select_rev19(dev, code, type);
 else if (dev->phy.rev >= 3)
  b43_nphy_rev3_rssi_select(dev, code, type);
 else
  b43_nphy_rev2_rssi_select(dev, code, type);
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev,
           enum n_rssi_type rssi_type, u8 *buf)
{
 int i;
 for (i = 0; i < 2; i++) {
  if (rssi_type == N_RSSI_NB) {
   if (i == 0) {
    b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
        0xFC, buf[0]);
    b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
        0xFC, buf[1]);
   } else {
    b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM,
        0xFC, buf[2 * i]);
    b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
        0xFC, buf[2 * i + 1]);
   }
  } else {
   if (i == 0)
    b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
        0xF3, buf[0] << 2);
   else
    b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
        0xF3, buf[2 * i + 1] << 2);
  }
 }
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
static int b43_nphy_poll_rssi(struct b43_wldev *dev, enum n_rssi_type rssi_type,
         s32 *buf, u8 nsamp)
{
 int i;
 int out;
 u16 save_regs_phy[9];
 u16 s[2];

 /* TODO: rev7+ is treated like rev3+, what about rev19+? */

 if (dev->phy.rev >= 3) {
  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[3] = b43_phy_read(dev,
      B43_NPHY_RFCTL_LUT_TRSW_UP2);
  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);
  save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
  save_regs_phy[8] = 0;
 } else {
  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_AFECTL_OVER);
  save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD);
  save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
  save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
  save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
  save_regs_phy[7] = 0;
  save_regs_phy[8] = 0;
 }

 b43_nphy_rssi_select(dev, 5, rssi_type);

 if (dev->phy.rev < 2) {
  save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
  b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5);
 }

 for (i = 0; i < 4; i++)
  buf[i] = 0;

 for (i = 0; i < nsamp; i++) {
  if (dev->phy.rev < 2) {
   s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
   s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
  } else {
   s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
   s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
  }

  buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
  buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
  buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
  buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
 }
 out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
  (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);

 if (dev->phy.rev < 2)
  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[2]);
  b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
    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]);
  b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
 } else {
  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_AFECTL_OVER, save_regs_phy[2]);
  b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]);
  b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]);
  b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]);
  b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]);
 }

 return out;
}

/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
{
 struct b43_phy *phy = &dev->phy;
 struct b43_phy_n *nphy = dev->phy.n;

 u16 saved_regs_phy_rfctl[2];
 u16 saved_regs_phy[22];
 u16 regs_to_store_rev3[] = {
  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 regs_to_store_rev7[] = {
  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_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
  B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
  0x2ff,
  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_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
  B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
  B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2
 };
 u16 *regs_to_store;
 int regs_amount;

 u16 class;

 u16 clip_state[2];
 u16 clip_off[2] = { 0xFFFF, 0xFFFF };

 u8 vcm_final = 0;
 s32 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;
 int core, i, j, vcm;

 if (dev->phy.rev >= 7) {
  regs_to_store = regs_to_store_rev7;
  regs_amount = ARRAY_SIZE(regs_to_store_rev7);
 } else {
  regs_to_store = regs_to_store_rev3;
  regs_amount = ARRAY_SIZE(regs_to_store_rev3);
 }
 BUG_ON(regs_amount > ARRAY_SIZE(saved_regs_phy));

 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 < regs_amount; i++)
  saved_regs_phy[i] = b43_phy_read(dev, regs_to_store[i]);

 b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_OFF, 0, 7);
 b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7);

 if (dev->phy.rev >= 7) {
  b43_nphy_rf_ctl_override_one_to_many(dev,
           N_RF_CTL_OVER_CMD_RXRF_PU,
           0, 0, false);
  b43_nphy_rf_ctl_override_one_to_many(dev,
           N_RF_CTL_OVER_CMD_RX_PU,
           1, 0, false);
  b43_nphy_rf_ctl_override_rev7(dev, 0x80, 1, 0, false, 0);
  b43_nphy_rf_ctl_override_rev7(dev, 0x40, 1, 0, false, 0);
  if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
   b43_nphy_rf_ctl_override_rev7(dev, 0x20, 0, 0, false,
            0);
   b43_nphy_rf_ctl_override_rev7(dev, 0x10, 1, 0, false,
            0);
  } else {
   b43_nphy_rf_ctl_override_rev7(dev, 0x10, 0, 0, false,
            0);
   b43_nphy_rf_ctl_override_rev7(dev, 0x20, 1, 0, false,
            0);
  }
 } else {
  b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false);
  b43_nphy_rf_ctl_override(dev, 0x2, 1, 0, false);
  b43_nphy_rf_ctl_override(dev, 0x80, 1, 0, false);
  b43_nphy_rf_ctl_override(dev, 0x40, 1, 0, false);
  if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=94 H=92 G=92

¤ Dauer der Verarbeitung: 0.9 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.