]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/wireless/b43/phy_n.c
b43: N-PHY: add clip detection reading/writing and some classifier function
[mv-sheeva.git] / drivers / net / wireless / b43 / phy_n.c
index be7b5604947b0d6b052c3486c559d7c84fc21fa4..72b1c410b7ff0ea9ba4dba3cdd45c173d3dc9b93 100644 (file)
 #include "b43.h"
 #include "phy_n.h"
 #include "tables_nphy.h"
+#include "main.h"
 
+struct nphy_txgains {
+       u16 txgm[2];
+       u16 pga[2];
+       u16 pad[2];
+       u16 ipa[2];
+};
+
+struct nphy_iqcal_params {
+       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;
+};
 
 void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
 {//TODO
@@ -137,7 +162,8 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
 
        b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
        msleep(1);
-       if ((sprom->revision != 4) || !(sprom->boardflags_hi & 0x0002)) {
+       if ((sprom->revision != 4) ||
+          !(sprom->boardflags_hi & B43_BFH_RSSIINV)) {
                if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) ||
                    (binfo->type != 0x46D) ||
                    (binfo->rev < 0x41)) {
@@ -202,38 +228,16 @@ void b43_nphy_radio_turn_off(struct b43_wldev *dev)
                        b43_ntab_write(dev, (offset) + i, (data)[i]);   \
        } while (0)
 
-/* Upload the N-PHY tables. */
+/*
+ * Upload the N-PHY tables.
+ * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
+ */
 static void b43_nphy_tables_init(struct b43_wldev *dev)
 {
-       /* Static tables */
-       ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct);
-       ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup);
-       ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap);
-       ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn);
-       ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel);
-       ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot);
-       ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt);
-       ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0);
-       ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1);
-       ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0);
-       ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1);
-       ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi);
-       ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest);
-       ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs);
-
-       /* Volatile tables */
-       ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10);
-       ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11);
-       ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0);
-       ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1);
-       ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0);
-       ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1);
-       ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0);
-       ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1);
-       ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0);
-       ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1);
-       ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0);
-       ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1);
+       if (dev->phy.rev < 3)
+               b43_nphy_rev0_1_2_tables_init(dev);
+       else
+               b43_nphy_rev3plus_tables_init(dev);
 }
 
 static void b43_nphy_workarounds(struct b43_wldev *dev)
@@ -340,18 +344,69 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
        b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
 }
 
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
+static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
+{
+       u32 tmslow;
+
+       if (dev->phy.type != B43_PHYTYPE_N)
+               return;
+
+       tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
+       if (force)
+               tmslow |= SSB_TMSLOW_FGC;
+       else
+               tmslow &= ~SSB_TMSLOW_FGC;
+       ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
 static void b43_nphy_reset_cca(struct b43_wldev *dev)
 {
        u16 bbcfg;
 
-       ssb_write32(dev->dev, SSB_TMSLOW,
-                   ssb_read32(dev->dev, SSB_TMSLOW) | SSB_TMSLOW_FGC);
+       b43_nphy_bmac_clock_fgc(dev, 1);
        bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
-       b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTCCA);
-       b43_phy_write(dev, B43_NPHY_BBCFG,
-                     bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
-       ssb_write32(dev->dev, SSB_TMSLOW,
-                   ssb_read32(dev->dev, SSB_TMSLOW) & ~SSB_TMSLOW_FGC);
+       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_nphy_bmac_clock_fgc(dev, 0);
+       /* TODO: N PHY Force RF Seq with argument 2 */
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
+static void b43_nphy_write_clip_detection(struct b43_wldev *dev, 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]);
+}
+
+/* http://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);
+}
+
+/* http://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->id.revision == 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->id.revision == 16)
+               b43_mac_enable(dev);
+
+       return tmp;
 }
 
 enum b43_nphy_rf_sequence {
@@ -410,81 +465,223 @@ static void b43_nphy_bphy_init(struct b43_wldev *dev)
        b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
 }
 
-/* RSSI Calibration */
-static void b43_nphy_rssi_cal(struct b43_wldev *dev, u8 type)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
+static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
 {
-       //TODO
+       /* TODO */
+}
+
+/* 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
+ */
+static void b43_nphy_rssi_cal(struct b43_wldev *dev)
+{
+       if (dev->phy.rev >= 3) {
+               b43_nphy_rev3_rssi_cal(dev);
+       } else {
+               b43_nphy_rev2_rssi_cal(dev, 2);
+               b43_nphy_rev2_rssi_cal(dev, 0);
+               b43_nphy_rev2_rssi_cal(dev, 1);
+       }
+}
+
+/*
+ * Init N-PHY
+ * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
+ */
 int b43_phy_initn(struct b43_wldev *dev)
 {
+       struct ssb_bus *bus = dev->dev->bus;
        struct b43_phy *phy = &dev->phy;
+       struct b43_phy_n *nphy = phy->n;
+       u8 tx_pwr_state;
+       struct nphy_txgains target;
        u16 tmp;
+       enum ieee80211_band tmp2;
+       bool do_rssi_cal;
 
-       //TODO: Spectral management
+       u16 clip[2];
+       bool do_cal = false;
+
+       if ((dev->phy.rev >= 3) &&
+          (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
+          (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
+               chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
+       }
+       nphy->deaf_count = 0;
        b43_nphy_tables_init(dev);
+       nphy->crsminpwr_adjusted = false;
+       nphy->noisevars_adjusted = false;
 
        /* Clear all overrides */
-       b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
+       if (dev->phy.rev >= 3) {
+               b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
+               b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
+               b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
+               b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
+       } else {
+               b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
+       }
        b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);
        b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);
-       b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
-       b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
+       if (dev->phy.rev < 6) {
+               b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
+               b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
+       }
        b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
                     ~(B43_NPHY_RFSEQMODE_CAOVER |
                       B43_NPHY_RFSEQMODE_TROVER));
+       if (dev->phy.rev >= 3)
+               b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0);
        b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);
 
-       tmp = (phy->rev < 2) ? 64 : 59;
-       b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
-                       ~B43_NPHY_BPHY_CTL3_SCALE,
-                       tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
-
+       if (dev->phy.rev <= 2) {
+               tmp = (dev->phy.rev == 2) ? 0x3B : 0x40;
+               b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
+                               ~B43_NPHY_BPHY_CTL3_SCALE,
+                               tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
+       }
        b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
        b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
 
-       b43_phy_write(dev, B43_NPHY_TXREALFD, 184);
-       b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 200);
-       b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 80);
-       b43_phy_write(dev, B43_NPHY_C2_BCLIPBKOFF, 511);
+       if (bus->sprom.boardflags2_lo & 0x100 ||
+           (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
+            bus->boardinfo.type == 0x8B))
+               b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
+       else
+               b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
+       b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8);
+       b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
+       b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
 
-       //TODO MIMO-Config
-       //TODO Update TX/RX chain
+       /* TODO MIMO-Config */
+       /* TODO Update TX/RX chain */
 
        if (phy->rev < 2) {
                b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
                b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
        }
+
+       tmp2 = b43_current_band(dev->wl);
+       if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) ||
+           (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) {
+               b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
+               b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
+                               nphy->papd_epsilon_offset[0] << 7);
+               b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);
+               b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F,
+                               nphy->papd_epsilon_offset[1] << 7);
+               /* TODO N PHY IPA Set TX Dig Filters */
+       } else if (phy->rev >= 5) {
+               /* TODO N PHY Ext PA Set TX Dig Filters */
+       }
+
        b43_nphy_workarounds(dev);
-       b43_nphy_reset_cca(dev);
 
-       ssb_write32(dev->dev, SSB_TMSLOW,
-                   ssb_read32(dev->dev, SSB_TMSLOW) | B43_TMSLOW_MACPHYCLKEN);
+       /* Reset CCA, in init code it differs a little from standard way */
+       /* b43_nphy_bmac_clock_fgc(dev, 1); */
+       tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
+       b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
+       b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
+       /* b43_nphy_bmac_clock_fgc(dev, 0); */
+
+       /* TODO N PHY MAC PHY Clock Set with argument 1 */
+
+       /* b43_nphy_pa_override(dev, false); */
        b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
        b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+       /* b43_nphy_pa_override(dev, true); */
+
+       b43_nphy_classifier(dev, 0, 0);
+       b43_nphy_read_clip_detection(dev, clip);
+       tx_pwr_state = nphy->txpwrctrl;
+       /* TODO N PHY TX power control with argument 0
+               (turning off power control) */
+       /* TODO Fix the TX Power Settings */
+       /* TODO N PHY TX Power Control Idle TSSI */
+       /* TODO N PHY TX Power Control Setup */
+
+       if (phy->rev >= 3) {
+               /* TODO */
+       } else {
+               /* TODO Write an N PHY table with ID 26, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */
+               /* TODO Write an N PHY table with ID 27, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */
+       }
 
-       b43_phy_read(dev, B43_NPHY_CLASSCTL); /* dummy read */
-       //TODO read core1/2 clip1 thres regs
-
-       if (1 /* FIXME Band is 2.4GHz */)
-               b43_nphy_bphy_init(dev);
-       //TODO disable TX power control
-       //TODO Fix the TX power settings
-       //TODO Init periodic calibration with reason 3
-       b43_nphy_rssi_cal(dev, 2);
-       b43_nphy_rssi_cal(dev, 0);
-       b43_nphy_rssi_cal(dev, 1);
-       //TODO get TX gain
-       //TODO init superswitch
-       //TODO calibrate LO
-       //TODO idle TSSI TX pctl
-       //TODO TX power control power setup
-       //TODO table writes
-       //TODO TX power control coefficients
-       //TODO enable TX power control
-       //TODO control antenna selection
-       //TODO init radar detection
-       //TODO reset channel if changed
+       if (nphy->phyrxchain != 3)
+               ;/* TODO N PHY RX Core Set State with phyrxchain as argument */
+       if (nphy->mphase_cal_phase_id > 0)
+               ;/* TODO PHY Periodic Calibration Multi-Phase Restart */
+
+       do_rssi_cal = false;
+       if (phy->rev >= 3) {
+               if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+                       do_rssi_cal = (nphy->rssical_chanspec_2G == 0);
+               else
+                       do_rssi_cal = (nphy->rssical_chanspec_5G == 0);
+
+               if (do_rssi_cal)
+                       b43_nphy_rssi_cal(dev);
+               else
+                       ;/* b43_nphy_restore_rssi_cal(dev); */
+       } else {
+               b43_nphy_rssi_cal(dev);
+       }
+
+       if (!((nphy->measure_hold & 0x6) != 0)) {
+               if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+                       do_cal = (nphy->iqcal_chanspec_2G == 0);
+               else
+                       do_cal = (nphy->iqcal_chanspec_5G == 0);
+
+               if (nphy->mute)
+                       do_cal = false;
+
+               if (do_cal) {
+                       /* target = b43_nphy_get_tx_gains(dev); */
+
+                       if (nphy->antsel_type == 2)
+                               ;/*TODO NPHY Superswitch Init with argument 1*/
+                       if (nphy->perical != 2) {
+                               /* b43_nphy_rssi_cal(dev); */
+                               if (phy->rev >= 3) {
+                                       nphy->cal_orig_pwr_idx[0] =
+                                           nphy->txpwrindex[0].index_internal;
+                                       nphy->cal_orig_pwr_idx[1] =
+                                           nphy->txpwrindex[1].index_internal;
+                                       /* TODO N PHY Pre Calibrate TX Gain */
+                                       /*target = b43_nphy_get_tx_gains(dev)*/
+                               }
+                       }
+               }
+       }
+
+       /*
+       if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) {
+               if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
+                       Call N PHY Save Cal
+               else if (nphy->mphase_cal_phase_id == 0)
+                       N PHY Periodic Calibration with argument 3
+       } else {
+               b43_nphy_restore_cal(dev);
+       }
+       */
+
+       /* b43_nphy_tx_pwr_ctrl_coef_setup(dev); */
+       /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */
+       b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015);
+       b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
+       if (phy->rev >= 3 && phy->rev <= 6)
+               b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014);
+       /* b43_nphy_tx_lp_fbw(dev); */
+       /* TODO N PHY Spur Workaround */
 
        b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n");
        return 0;