diff mbox series

[04/13] mt76x0: pci: introduce mt76x0_phy_calirate routine

Message ID 326458a15d0c242e7419e3bfc0033ccdc9083676.1539338611.git.lorenzo.bianconi@redhat.com (mailing list archive)
State Accepted
Delegated to: Kalle Valo
Headers show
Series add calibration logics for mt76x0e driver | expand

Commit Message

Lorenzo Bianconi Oct. 12, 2018, 10:16 a.m. UTC
Add mt76x0_phy_calirate routine in order to perform
phy calibration for mt76x0e devices.

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
---
 .../net/wireless/mediatek/mt76/mt76x0/mcu.h   |  3 ++
 .../wireless/mediatek/mt76/mt76x0/mt76x0.h    |  1 +
 .../net/wireless/mediatek/mt76/mt76x0/pci.c   |  1 +
 .../net/wireless/mediatek/mt76/mt76x0/phy.c   | 53 +++++++++++++++++--
 4 files changed, 55 insertions(+), 3 deletions(-)

Comments

Stanislaw Gruszka Oct. 12, 2018, 12:32 p.m. UTC | #1
On Fri, Oct 12, 2018 at 12:16:20PM +0200, Lorenzo Bianconi wrote:
> Add mt76x0_phy_calirate routine in order to perform
> phy calibration for mt76x0e devices.
<snip>
> @@ -671,9 +713,14 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
>  	/* Vendor driver don't do it */
>  	/* mt76x0_phy_set_tx_power(dev, channel, rf_bw_band); */
>  
> -	mt76x0_vco_cal(dev, channel);
> -	if (scan)
> -		mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1, false);
> +	if (mt76_is_usb(dev)) {
> +		mt76x0_vco_cal(dev, channel);
> +		if (scan)
> +			mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1,
> +					      false);
> +	} else {
> +		mt76x0_phy_calibrate(dev, false);
> +	}

Why this should be diffrent for USB and PCI ? RF calibration seems
not to be realted to bus type, so perhaps this should be based on
mt76xx_rev() check?

Thanks
Stanislaw
Lorenzo Bianconi Oct. 12, 2018, 12:51 p.m. UTC | #2
>
> On Fri, Oct 12, 2018 at 12:16:20PM +0200, Lorenzo Bianconi wrote:
> > Add mt76x0_phy_calirate routine in order to perform
> > phy calibration for mt76x0e devices.
> <snip>
> > @@ -671,9 +713,14 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
> >       /* Vendor driver don't do it */
> >       /* mt76x0_phy_set_tx_power(dev, channel, rf_bw_band); */
> >
> > -     mt76x0_vco_cal(dev, channel);
> > -     if (scan)
> > -             mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1, false);
> > +     if (mt76_is_usb(dev)) {
> > +             mt76x0_vco_cal(dev, channel);
> > +             if (scan)
> > +                     mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1,
> > +                                           false);
> > +     } else {
> > +             mt76x0_phy_calibrate(dev, false);
> > +     }
>
> Why this should be diffrent for USB and PCI ? RF calibration seems
> not to be realted to bus type, so perhaps this should be based on
> mt76xx_rev() check?
>

actually mt76x0e is running a newer firmware version than mt76x0u one and
phy calibration is based on it (vco/full calibration cmds).
My plan is to update usb driver to use the same pcie fw (from some
preliminary tests
mt76x0u driver seems to work properly with pcie fw) but we are pretty
close to merging window
now for that kind of changes.
Moreover I guess we can do the same with mt76x2/mt76x2u

Regards,
Lorenzo

> Thanks
> Stanislaw

Regards,
Lorenzo
diff mbox series

Patch

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h
index b66e70f6cd89..3b34e1d2769f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.h
@@ -39,6 +39,9 @@  enum mcu_calibrate {
 	MCU_CAL_TXDCOC,
 	MCU_CAL_RX_GROUP_DELAY,
 	MCU_CAL_TX_GROUP_DELAY,
+	MCU_CAL_VCO,
+	MCU_CAL_NO_SIGNAL = 0xfe,
+	MCU_CAL_FULL = 0xff,
 };
 
 int mt76x0e_mcu_init(struct mt76x02_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
index 1bff2be45a13..6717d83e0ff6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
@@ -72,6 +72,7 @@  int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
 			    struct cfg80211_chan_def *chandef);
 void mt76x0_phy_recalibrate_after_assoc(struct mt76x02_dev *dev);
 void mt76x0_phy_set_txpower(struct mt76x02_dev *dev);
+void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on);
 
 /* MAC */
 void mt76x0_mac_work(struct work_struct *work);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index 10845f37af37..f31c63444c82 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -28,6 +28,7 @@  static int mt76x0e_start(struct ieee80211_hw *hw)
 	mutex_lock(&dev->mt76.mutex);
 
 	mt76x02_mac_start(dev);
+	mt76x0_phy_calibrate(dev, true);
 	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
 				     MT_CALIBRATE_INTERVAL);
 	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index 9a8e1fcee26b..6bd5aa67d400 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -581,6 +581,48 @@  void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
 	mt76x02_phy_set_txpower(dev, info[0], info[1]);
 }
 
+void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on)
+{
+	struct ieee80211_channel *chan = dev->mt76.chandef.chan;
+	u32 val, tx_alc, reg_val;
+
+	if (power_on) {
+		mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0, false);
+		mt76x02_mcu_calibrate(dev, MCU_CAL_VCO, chan->hw_value,
+				      false);
+		usleep_range(10, 20);
+		/* XXX: tssi */
+	}
+
+	tx_alc = mt76_rr(dev, MT_TX_ALC_CFG_0);
+	mt76_wr(dev, MT_TX_ALC_CFG_0, 0);
+	usleep_range(500, 700);
+
+	reg_val = mt76_rr(dev, MT_BBP(IBI, 9));
+	mt76_wr(dev, MT_BBP(IBI, 9), 0xffffff7e);
+
+	if (chan->band == NL80211_BAND_5GHZ) {
+		if (chan->hw_value < 100)
+			val = 0x701;
+		else if (chan->hw_value < 140)
+			val = 0x801;
+		else
+			val = 0x901;
+	} else {
+		val = 0x600;
+	}
+
+	mt76x02_mcu_calibrate(dev, MCU_CAL_FULL, val, false);
+	msleep(350);
+	mt76x02_mcu_calibrate(dev, MCU_CAL_LC, 1, false);
+	usleep_range(15000, 20000);
+
+	mt76_wr(dev, MT_BBP(IBI, 9), reg_val);
+	mt76_wr(dev, MT_TX_ALC_CFG_0, tx_alc);
+	mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1, false);
+}
+EXPORT_SYMBOL_GPL(mt76x0_phy_calibrate);
+
 int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
 			   struct cfg80211_chan_def *chandef)
 {
@@ -671,9 +713,14 @@  int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
 	/* Vendor driver don't do it */
 	/* mt76x0_phy_set_tx_power(dev, channel, rf_bw_band); */
 
-	mt76x0_vco_cal(dev, channel);
-	if (scan)
-		mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1, false);
+	if (mt76_is_usb(dev)) {
+		mt76x0_vco_cal(dev, channel);
+		if (scan)
+			mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1,
+					      false);
+	} else {
+		mt76x0_phy_calibrate(dev, false);
+	}
 
 	mt76x0_phy_set_txpower(dev);