+ if (dev->dev->bus->chip_id == 0x4325) {
+ // TODO SSB PMU recalibration
+ }
+ }
+}
+
+struct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; };
+
+static void lpphy_set_rc_cap(struct b43_wldev *dev)
+{
+ u8 rc_cap = dev->phy.lp->rc_cap;
+
+ b43_radio_write(dev, B2062_N_RXBB_CALIB2, max_t(u8, rc_cap-4, 0x80));
+ b43_radio_write(dev, B2062_N_TX_CTL_A, ((rc_cap & 0x1F) >> 1) | 0x80);
+ b43_radio_write(dev, B2062_S_RXG_CNT16, ((rc_cap & 0x1F) >> 2) | 0x80);
+}
+
+static u8 lpphy_get_bb_mult(struct b43_wldev *dev)
+{
+ return (b43_lptab_read(dev, B43_LPTAB16(0, 87)) & 0xFF00) >> 8;
+}
+
+static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult)
+{
+ b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8);
+}
+
+static void lpphy_disable_crs(struct b43_wldev *dev)
+{
+ b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFDF);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFBF);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x7);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x38);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F);
+ b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x100);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFDFF);
+ b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL0, 0);
+ b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL1, 1);
+ b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL2, 0x20);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFBFF);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xF7FF);
+ b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
+ b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45AF);
+ b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF);
+}
+
+static void lpphy_restore_crs(struct b43_wldev *dev)
+{
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+ b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x60);
+ else
+ b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x20);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00);
+}
+
+struct lpphy_tx_gains { u16 gm, pga, pad, dac; };
+
+static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev)
+{
+ struct lpphy_tx_gains gains;
+ u16 tmp;
+
+ gains.dac = (b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0x380) >> 7;
+ if (dev->phy.rev < 2) {
+ tmp = b43_phy_read(dev,
+ B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7FF;
+ gains.gm = tmp & 0x0007;
+ gains.pga = (tmp & 0x0078) >> 3;
+ gains.pad = (tmp & 0x780) >> 7;
+ } else {
+ tmp = b43_phy_read(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL);
+ gains.pad = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0xFF;
+ gains.gm = tmp & 0xFF;
+ gains.pga = (tmp >> 8) & 0xFF;
+ }
+
+ return gains;
+}
+
+static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac)
+{
+ u16 ctl = b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0xC7F;
+ ctl |= dac << 7;
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl);
+}
+
+static void lpphy_set_tx_gains(struct b43_wldev *dev,
+ struct lpphy_tx_gains gains)
+{
+ u16 rf_gain, pa_gain;
+
+ if (dev->phy.rev < 2) {
+ rf_gain = (gains.pad << 7) | (gains.pga << 3) | gains.gm;
+ b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+ 0xF800, rf_gain);
+ } else {
+ pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F00;
+ b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+ (gains.pga << 8) | gains.gm);
+ b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+ 0x8000, gains.pad | pa_gain);
+ b43_phy_write(dev, B43_PHY_OFDM(0xFC),
+ (gains.pga << 8) | gains.gm);
+ b43_phy_maskset(dev, B43_PHY_OFDM(0xFD),
+ 0x8000, gains.pad | pa_gain);
+ }
+ lpphy_set_dac_gain(dev, gains.dac);
+ if (dev->phy.rev < 2) {
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8);
+ } else {
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14);
+ }
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFBF, 1 << 4);
+}
+
+static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+ u16 trsw = gain & 0x1;
+ u16 lna = (gain & 0xFFFC) | ((gain & 0xC) >> 2);
+ u16 ext_lna = (gain & 2) >> 1;
+
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xFBFF, ext_lna << 10);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xF7FF, ext_lna << 11);
+ b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
+}
+
+static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+ u16 low_gain = gain & 0xFFFF;
+ u16 high_gain = (gain >> 16) & 0xF;
+ u16 ext_lna = (gain >> 21) & 0x1;
+ u16 trsw = ~(gain >> 20) & 0x1;
+ u16 tmp;
+
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xFDFF, ext_lna << 9);
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xFBFF, ext_lna << 10);
+ b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
+ b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF0, high_gain);
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ tmp = (gain >> 2) & 0x3;
+ b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+ 0xE7FF, tmp<<11);
+ b43_phy_maskset(dev, B43_PHY_OFDM(0xE6), 0xFFE7, tmp << 3);
+ }
+}
+
+static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
+{
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
+ if (dev->phy.rev >= 2) {
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
+ if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ)
+ return;
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFF7);
+ } else {
+ b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);