b43: HT-PHY: finish calculating values for idle TSSI
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / b43 / phy_ht.c
index ae9cd2978060e9f8f16a8825fae684cee30a67ed..fd9e249e95b8aa53a17d7b85069ad464a1f33392 100644 (file)
@@ -37,8 +37,9 @@
 static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
                        const struct b43_phy_ht_channeltab_e_radio2059 *e)
 {
-       u8 i;
-       u16 routing;
+       static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, };
+       u16 r;
+       int core;
 
        b43_radio_write(dev, 0x16, e->radio_syn16);
        b43_radio_write(dev, 0x17, e->radio_syn17);
@@ -53,25 +54,17 @@ static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
        b43_radio_write(dev, 0x41, e->radio_syn41);
        b43_radio_write(dev, 0x43, e->radio_syn43);
        b43_radio_write(dev, 0x47, e->radio_syn47);
-       b43_radio_write(dev, 0x4a, e->radio_syn4a);
-       b43_radio_write(dev, 0x58, e->radio_syn58);
-       b43_radio_write(dev, 0x5a, e->radio_syn5a);
-       b43_radio_write(dev, 0x6a, e->radio_syn6a);
-       b43_radio_write(dev, 0x6d, e->radio_syn6d);
-       b43_radio_write(dev, 0x6e, e->radio_syn6e);
-       b43_radio_write(dev, 0x92, e->radio_syn92);
-       b43_radio_write(dev, 0x98, e->radio_syn98);
-
-       for (i = 0; i < 2; i++) {
-               routing = i ? R2059_RXRX1 : R2059_TXRX0;
-               b43_radio_write(dev, routing | 0x4a, e->radio_rxtx4a);
-               b43_radio_write(dev, routing | 0x58, e->radio_rxtx58);
-               b43_radio_write(dev, routing | 0x5a, e->radio_rxtx5a);
-               b43_radio_write(dev, routing | 0x6a, e->radio_rxtx6a);
-               b43_radio_write(dev, routing | 0x6d, e->radio_rxtx6d);
-               b43_radio_write(dev, routing | 0x6e, e->radio_rxtx6e);
-               b43_radio_write(dev, routing | 0x92, e->radio_rxtx92);
-               b43_radio_write(dev, routing | 0x98, e->radio_rxtx98);
+
+       for (core = 0; core < 3; core++) {
+               r = routing[core];
+               b43_radio_write(dev, r | 0x4a, e->radio_rxtx4a);
+               b43_radio_write(dev, r | 0x58, e->radio_rxtx58);
+               b43_radio_write(dev, r | 0x5a, e->radio_rxtx5a);
+               b43_radio_write(dev, r | 0x6a, e->radio_rxtx6a);
+               b43_radio_write(dev, r | 0x6d, e->radio_rxtx6d);
+               b43_radio_write(dev, r | 0x6e, e->radio_rxtx6e);
+               b43_radio_write(dev, r | 0x92, e->radio_rxtx92);
+               b43_radio_write(dev, r | 0x98, e->radio_rxtx98);
        }
 
        udelay(50);
@@ -87,7 +80,7 @@ static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
 
 static void b43_radio_2059_init(struct b43_wldev *dev)
 {
-       const u16 routing[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1 };
+       const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3 };
        const u16 radio_values[3][2] = {
                { 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
        };
@@ -106,17 +99,17 @@ static void b43_radio_2059_init(struct b43_wldev *dev)
        b43_radio_mask(dev, 0xc0, ~0x0080);
 
        if (1) { /* FIXME */
-               b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x1);
+               b43_radio_set(dev, R2059_C3 | 0x4, 0x1);
                udelay(10);
-               b43_radio_set(dev, R2059_RXRX1 | 0x0BF, 0x1);
-               b43_radio_maskset(dev, R2059_RXRX1 | 0x19B, 0x3, 0x2);
+               b43_radio_set(dev, R2059_C3 | 0x0BF, 0x1);
+               b43_radio_maskset(dev, R2059_C3 | 0x19B, 0x3, 0x2);
 
-               b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x2);
+               b43_radio_set(dev, R2059_C3 | 0x4, 0x2);
                udelay(100);
-               b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x2);
+               b43_radio_mask(dev, R2059_C3 | 0x4, ~0x2);
 
                for (i = 0; i < 10000; i++) {
-                       if (b43_radio_read(dev, R2059_RXRX1 | 0x145) & 1) {
+                       if (b43_radio_read(dev, R2059_C3 | 0x145) & 1) {
                                i = 0;
                                break;
                        }
@@ -125,7 +118,7 @@ static void b43_radio_2059_init(struct b43_wldev *dev)
                if (i)
                        b43err(dev->wl, "radio 0x945 timeout\n");
 
-               b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x1);
+               b43_radio_mask(dev, R2059_C3 | 0x4, ~0x1);
                b43_radio_set(dev, 0xa, 0x60);
 
                for (i = 0; i < 3; i++) {
@@ -297,7 +290,6 @@ static void b43_phy_ht_bphy_init(struct b43_wldev *dev)
  * Samples
  **************************************************/
 
-#if 0
 static void b43_phy_ht_stop_playback(struct b43_wldev *dev)
 {
        struct b43_phy_ht *phy_ht = dev->phy.ht;
@@ -385,13 +377,11 @@ static void b43_phy_ht_tx_tone(struct b43_wldev *dev)
        samp = b43_phy_ht_load_samples(dev);
        b43_phy_ht_run_samples(dev, samp, 0xFFFF, 0);
 }
-#endif
 
 /**************************************************
  * RSSI
  **************************************************/
 
-#if 0
 static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
                                   u8 rssi_type)
 {
@@ -400,7 +390,7 @@ static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
                { B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, },
                { B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, },
        };
-       static const u16 radio_r[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1, };
+       static const u16 radio_r[] = { R2059_C1, R2059_C2, R2059_C3, };
        int core;
 
        if (core_sel == 0) {
@@ -420,7 +410,7 @@ static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
                                b43_phy_set(dev, ctl_regs[core][1], 0x1 << 9);
                                b43_phy_set(dev, ctl_regs[core][1], 0x1 << 10);
 
-                               b43_radio_set(dev, R2059_RXRX1 | 0xbf, 0x1);
+                               b43_radio_set(dev, R2059_C3 | 0xbf, 0x1);
                                b43_radio_write(dev, radio_r[core] | 0x159,
                                                0x11);
                                break;
@@ -471,7 +461,6 @@ static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
        for (i = 0; i < 12; i++)
                b43_phy_write(dev, phy_regs_to_save[i], phy_regs_values[i]);
 }
-#endif
 
 /**************************************************
  * Tx/Rx
@@ -499,7 +488,6 @@ static void b43_phy_ht_tx_power_fix(struct b43_wldev *dev)
        }
 }
 
-#if 0
 static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable)
 {
        struct b43_phy_ht *phy_ht = dev->phy.ht;
@@ -541,9 +529,21 @@ static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable)
 static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
 {
        struct b43_phy_ht *phy_ht = dev->phy.ht;
+       static const u16 base[] = { 0x840, 0x860, 0x880 };
+       u16 save_regs[3][3];
        s32 rssi_buf[6];
+       int core;
 
-       /* TODO */
+       for (core = 0; core < 3; core++) {
+               save_regs[core][1] = b43_phy_read(dev, base[core] + 6);
+               save_regs[core][2] = b43_phy_read(dev, base[core] + 7);
+               save_regs[core][0] = b43_phy_read(dev, base[core] + 0);
+
+               b43_phy_write(dev, base[core] + 6, 0);
+               b43_phy_mask(dev, base[core] + 7, ~0xF); /* 0xF? Or just 0x6? */
+               b43_phy_set(dev, base[core] + 0, 0x0400);
+               b43_phy_set(dev, base[core] + 0, 0x1000);
+       }
 
        b43_phy_ht_tx_tone(dev);
        udelay(20);
@@ -555,10 +555,121 @@ static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
        phy_ht->idle_tssi[1] = rssi_buf[2] & 0xff;
        phy_ht->idle_tssi[2] = rssi_buf[4] & 0xff;
 
-       /* TODO */
+       for (core = 0; core < 3; core++) {
+               b43_phy_write(dev, base[core] + 0, save_regs[core][0]);
+               b43_phy_write(dev, base[core] + 6, save_regs[core][1]);
+               b43_phy_write(dev, base[core] + 7, save_regs[core][2]);
+       }
 }
+
+static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev)
+{
+       struct b43_phy_ht *phy_ht = dev->phy.ht;
+       struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+       u8 *idle = phy_ht->idle_tssi;
+       u8 target[3];
+       s16 a1[3], b0[3], b1[3];
+
+       u16 freq = dev->phy.channel_freq;
+       int i, c;
+
+       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+               for (c = 0; c < 3; c++) {
+                       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 < 3; c++) {
+                       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 < 3; c++) {
+                       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 < 3; c++) {
+                       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 {
+               target[0] = target[1] = target[2] = 52;
+               a1[0] = a1[1] = a1[2] = -424;
+               b0[0] = b0[1] = b0[2] = 5612;
+               b1[0] = b1[1] = b1[2] = -1393;
+       }
+
+       b43_phy_set(dev, B43_PHY_HT_TSSIMODE, B43_PHY_HT_TSSIMODE_EN);
+       b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1,
+                    ~B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN & 0xFFFF);
+
+       /* TODO: Does it depend on sprom->fem.ghz2.tssipos? */
+       b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 0x4000);
+
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1,
+                       ~B43_PHY_HT_TXPCTL_CMD_C1_INIT, 0x19);
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C2,
+                       ~B43_PHY_HT_TXPCTL_CMD_C2_INIT, 0x19);
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C3,
+                       ~B43_PHY_HT_TXPCTL_CMD_C3_INIT, 0x19);
+
+       b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI,
+                   B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF);
+
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI,
+                       ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C1,
+                       idle[0] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT);
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI,
+                       ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C2,
+                       idle[1] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT);
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI2,
+                       ~B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3,
+                       idle[2] << B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT);
+
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_TSSID,
+                       0xf0);
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_NPTIL2,
+                       0x3 << B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT);
+#if 0
+       /* TODO: what to mask/set? */
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x800, 0)
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x400, 0)
 #endif
 
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR,
+                       ~B43_PHY_HT_TXPCTL_TARG_PWR_C1,
+                       target[0] << B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT);
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR,
+                       ~B43_PHY_HT_TXPCTL_TARG_PWR_C2 & 0xFFFF,
+                       target[1] << B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT);
+       b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR2,
+                       ~B43_PHY_HT_TXPCTL_TARG_PWR2_C3,
+                       target[2] << B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT);
+
+       for (c = 0; c < 3; c++) {
+               s32 num, den, pwr;
+               u32 regval[64];
+
+               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);
+                       regval[i] = pwr;
+               }
+               b43_httab_write_bulk(dev, B43_HTTAB16(26 + c, 0), 64, regval);
+       }
+}
+
 /**************************************************
  * Channel switching ops.
  **************************************************/
@@ -841,12 +952,10 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev)
 
        saved_tx_pwr_ctl = phy_ht->tx_pwr_ctl;
        b43_phy_ht_tx_power_fix(dev);
-#if 0
        b43_phy_ht_tx_power_ctl(dev, false);
        b43_phy_ht_tx_power_ctl_idle_tssi(dev);
-       /* TODO */
+       b43_phy_ht_tx_power_ctl_setup(dev);
        b43_phy_ht_tx_power_ctl(dev, saved_tx_pwr_ctl);
-#endif
 
        return 0;
 }
@@ -911,8 +1020,9 @@ static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on)
 static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev,
                                        unsigned int new_channel)
 {
-       struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
-       enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+       struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
+       enum nl80211_channel_type channel_type =
+               cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
 
        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
                if ((new_channel < 1) || (new_channel > 14))