mac80211: rt2x00: experimental improvements for MT7620 wifi
authorDaniel Golle <daniel@makrotopia.org>
Thu, 28 Jul 2022 11:40:12 +0000 (13:40 +0200)
committerDaniel Golle <daniel@makrotopia.org>
Mon, 12 Sep 2022 20:37:08 +0000 (21:37 +0100)
Serge Vasilugin reports:

To improve mt7620 built-in wifi performance some changes:
1. Correct BW20/BW40 switching (see comments with mark (1))
2. Correct TX_SW_CFG1 MAC reg from v3 of vendor driver see
https://gitlab.com/dm38/padavan-ng/-/blob/master/trunk/proprietary/rt_wifi/rtpci/3.0.X.X/mt76x2/chips/rt6352.c#L531
3. Set bbp66 for all chains.
4. US_CYC_CNT init based on Programming guide, default value was 33 (pci),
   set chipset bus clock with fallback to cpu clock/3.
5. Don't overwrite default values for mt7620.
6. Correct some typos.
7. Add support for external LNA:
    a) RF and BBP regs never be corrected for this mode
    b) eLNA is driven the same way as ePA with mt7620's pin PA
but vendor driver explicitly pin PA to gpio mode (for forrect calibration?)
so I'm not sure that request for pa_pin in dts-file will be enough

First 5 changes (really 2) improve performance for boards w/o eLNA/ePA.
Changes 7 add support for eLNA

Configuration w/o eLAN/ePA and with eLNA show results
tx/rx (from router point of view) for each stream:
 35-40/30-35 Mbps for HT20
 65-70/60-65 Mbps for HT40

Yes. Max results for 2T2R client is 140-145/135-140
with peaks 160/150, It correspond to mediatek driver results.
Boards with ePA untested.

Reported-by: Serge Vasilugin <vasilugin@yandex.ru>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
17 files changed:
package/kernel/mac80211/patches/rt2x00/992-rt2x00-more-fixes.patch [new file with mode: 0644]
target/linux/ramips/dts/mt7620a.dtsi
target/linux/ramips/dts/mt7620a_buffalo_whr-300hp2.dts
target/linux/ramips/dts/mt7620a_cameo_810.dtsi
target/linux/ramips/dts/mt7620a_dlink_dch-m225.dts
target/linux/ramips/dts/mt7620a_fon_fon2601.dts
target/linux/ramips/dts/mt7620a_hiwifi_hc5861.dts
target/linux/ramips/dts/mt7620a_lenovo_newifi-y1.dtsi
target/linux/ramips/dts/mt7620a_phicomm_k2-v22.4.dts
target/linux/ramips/dts/mt7620a_phicomm_k2-v22.5.dts
target/linux/ramips/dts/mt7620a_phicomm_k2g.dts
target/linux/ramips/dts/mt7620a_tplink_archer-c20-v1.dts
target/linux/ramips/dts/mt7620a_tplink_archer-c50-v1.dts
target/linux/ramips/dts/mt7620a_wavlink_wl-wn530hg4.dts
target/linux/ramips/dts/mt7620a_xiaomi_miwifi-mini.dts
target/linux/ramips/dts/mt7620a_youku_yk-l1.dtsi
target/linux/ramips/dts/mt7620a_zbtlink_zbt-ape522ii.dts

diff --git a/package/kernel/mac80211/patches/rt2x00/992-rt2x00-more-fixes.patch b/package/kernel/mac80211/patches/rt2x00/992-rt2x00-more-fixes.patch
new file mode 100644 (file)
index 0000000..2ad6219
--- /dev/null
@@ -0,0 +1,423 @@
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Mon, 12 Sep 2022 21:33:13 +0100
+Subject: [PATCH] rt2x00: various experimental fixes for MT7620
+
+Serge Vasilugin reports:
+
+To improve mt7620 built-in wifi performance some changes:
+1. Correct BW20/BW40 switching (see comments with mark see commets with mark (1))
+2. Correct TX_SW_CFG1 MAC reg from v3 of vendor driver see
+        https://gitlab.com/dm38/padavan-ng/-/blob/master/trunk/proprietary/rt_wifi/rtpci/3.0.X.X/mt76x2/chips/rt6352.c#L531
+3. Set bbp66 for all chains.
+4. US_CYC_CNT init based on Programming guide, default value was 33 (pci),
+   set chipset bus clock with fallback to cpu clock/3.
+5. Don't overwrite default values for mt7620.
+6. Correct some typos.
+7. Add support for external LNA:
+    a) RF and BBP regs never be corrected for this mode
+    b) eLNA is driven the same way as ePA with mt7620's pin PA
+        but vendor driver explicitly pin PA to gpio mode (for forrect calibration?)
+        so I'm not sure that request for pa_pin in dts-file will be enough
+
+First 5 changes (really 2) improve performance for boards w/o eLNA/ePA.
+Changes 7 add support for eLNA
+
+Configuration w/o eLAN/ePA and with eLNA show results
+tx/rx (from router point of view) for each stream:
+ 35-40/30-35 Mbps for HT20
+ 65-70/60-65 Mbps for HT40
+
+Yes. Max results for 2T2R client is 140-145/135-140
+with peaks 160/150, It correspond to mediatek driver results.
+Boards with ePA untested.
+
+Reported-by: Serge Vasilugin <vasilugin@yandex.ru>
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+---
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -137,6 +137,26 @@ static u8 rt2800_bbp_read(struct rt2x00_
+       return value;
+ }
++//serge: move here for use in test
++static void rt2800_bbp_glrt_write(struct rt2x00_dev *rt2x00dev,
++                                const u8 reg, const u8 value)
++{
++      rt2800_bbp_write(rt2x00dev, 195, reg);
++      rt2800_bbp_write(rt2x00dev, 196, value);
++}
++
++static void rt2800_bbp_dcoc_write(struct rt2x00_dev *rt2x00dev,
++                                const u8 reg, const u8 value)
++{
++      rt2800_bbp_write(rt2x00dev, 158, reg);
++      rt2800_bbp_write(rt2x00dev, 159, value);
++}
++
++static u8 rt2800_bbp_dcoc_read(struct rt2x00_dev *rt2x00dev, const u8 reg)
++{
++      rt2800_bbp_write(rt2x00dev, 158, reg);
++      return rt2800_bbp_read(rt2x00dev, 159);
++}
+ static void rt2800_rfcsr_write(struct rt2x00_dev *rt2x00dev,
+                              const unsigned int word, const u8 value)
+@@ -284,6 +304,28 @@ static void rt2800_rf_write(struct rt2x0
+       mutex_unlock(&rt2x00dev->csr_mutex);
+ }
++void rt6352_enable_pa_pin(struct rt2x00_dev *rt2x00dev, int enable)
++{
++      if (!rt2x00dev->pinctrl)
++              return;
++
++      if (enable) {
++              if (!rt2x00dev->pins_default) {
++                      rt2x00_warn(rt2x00dev, "cannot enable PA pin! no default pinctrl\n");
++                      return;
++              }
++
++              pinctrl_select_state(rt2x00dev->pinctrl, rt2x00dev->pins_default);
++      } else {
++              if (!rt2x00dev->pins_pa_gpio) {
++                      rt2x00_warn(rt2x00dev, "cannot disable PA pin! no pa_gpio pinctrl\n");
++                      return;
++              }
++
++              pinctrl_select_state(rt2x00dev->pinctrl, rt2x00dev->pins_pa_gpio);
++      }
++}
++
+ static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = {
+       [EEPROM_CHIP_ID]                = 0x0000,
+       [EEPROM_VERSION]                = 0x0001,
+@@ -3801,6 +3843,20 @@ static void rt2800_config_channel_rf7620
+               rfcsr |= tx_agc_fc;
+               rt2800_rfcsr_write_bank(rt2x00dev, 7, 59, rfcsr);
+       }
++
++      if (conf_is_ht40(conf)) {//serge:skipped this step (1)
++              rt2800_bbp_write(rt2x00dev, 195, 141);
++              rt2800_bbp_write(rt2x00dev, 196, 0x10);
++              rt2800_bbp_write(rt2x00dev, 195, 157);
++              rt2800_bbp_write(rt2x00dev, 196, 0x2f);
++              //rt2800_bbp_write(rt2x00dev, 105, 0x3C);
++      } else {
++              rt2800_bbp_write(rt2x00dev, 195, 141);
++              rt2800_bbp_write(rt2x00dev, 196, 0x1a);
++              rt2800_bbp_write(rt2x00dev, 195, 157);
++              rt2800_bbp_write(rt2x00dev, 196, 0x40);
++              //rt2800_bbp_write(rt2x00dev, 105, 0x1C);
++      }
+ }
+ static void rt2800_config_alc(struct rt2x00_dev *rt2x00dev,
+@@ -4172,6 +4228,11 @@ static void rt2800_config_channel(struct
+                       rt2800_bbp_write(rt2x00dev, 86, 0x46);
+               else
+                       rt2800_bbp_write(rt2x00dev, 86, 0);
++      } else if (rt2x00_rt(rt2x00dev, RT6352)) {//serge: don't overwite bbp r86 (5)
++              rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
++              rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
++              rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
++              rt2800_bbp_write(rt2x00dev, 86, 0x38);
+       } else {
+               rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+               rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+@@ -4377,7 +4438,8 @@ static void rt2800_config_channel(struct
+               reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2*rt2x00dev->lna_gain;
+               rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
+-              rt2800_iq_calibrate(rt2x00dev, rf->channel);
++              if (!rt2x00_rt(rt2x00dev, RT6352))//serge: this function for rt5592 only, for rt6352 it switch off compensations (5)
++                  rt2800_iq_calibrate(rt2x00dev, rf->channel);
+       }
+       if (rt2x00_rt(rt2x00dev, RT6352)) {
+@@ -4417,6 +4479,31 @@ static void rt2800_config_channel(struct
+                       rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN,
+                                             0x6C6C6B6C);
+               }
++
++              if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {//serge: for support eLNA (7a)
++                      rt2x00_warn(rt2x00dev, "Correct RF/BBP for eLNA!\n");
++                      reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
++                      reg |= 0x00000101;
++                      rt2800_register_write(rt2x00dev, RF_CONTROL3, reg);
++
++                      reg = rt2800_register_read(rt2x00dev, RF_BYPASS3);
++                      reg |= 0x00000101;
++                      rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
++
++                      rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66);
++                      rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20);
++                      rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x42);
++                      rt2800_bbp_write(rt2x00dev, 75, 0x68);//serge: move bbp eLNA init here?
++                      rt2800_bbp_write(rt2x00dev, 76, 0x4C);
++                      rt2800_bbp_write(rt2x00dev, 79, 0x1C);
++                      rt2800_bbp_write(rt2x00dev, 80, 0x0C);
++                      rt2800_bbp_write(rt2x00dev, 82, 0xB6);
++                      /* bank 0 RF reg 42 and glrt BBP reg 141
++                      will be set in config channel function
++                      in dependence of channel and HT20/HT40
++                      so don't touch it
++                      */
++              }
+       }
+       bbp = rt2800_bbp_read(rt2x00dev, 4);
+@@ -4457,6 +4544,9 @@ static void rt2800_config_channel(struct
+               rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);
+               rt2800_bbp_write(rt2x00dev, 49, bbp);
+       }
++//serge:just print results after config channel - don't forget to remove nahren (c) <- this is copyright, not ref to comments :)
++      bbp = rt2800_bbp_dcoc_read(rt2x00dev, 0x03);
++      pr_info("BBP tx/rx compensation control=0x%02x\n", bbp);
+ }
+ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
+@@ -5527,7 +5617,7 @@ void rt2800_vco_calibration(struct rt2x0
+       }
+       rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+-      if (rt2x00_rt(rt2x00dev, RT6352)) {
++      if (rt2x00_rt(rt2x00dev, RT6352)) {//serge:remark - move all this code to rfcsr_6352 init?
+               if (rt2x00dev->default_ant.rx_chain_num == 1) {
+                       rt2800_bbp_write(rt2x00dev, 91, 0x07);
+                       rt2800_bbp_write(rt2x00dev, 95, 0x1A);
+@@ -5695,7 +5785,8 @@ static inline void rt2800_set_vgc(struct
+       if (qual->vgc_level != vgc_level) {
+               if (rt2x00_rt(rt2x00dev, RT3572) ||
+                   rt2x00_rt(rt2x00dev, RT3593) ||
+-                  rt2x00_rt(rt2x00dev, RT3883)) {
++                  rt2x00_rt(rt2x00dev, RT3883) ||
++                  rt2x00_rt(rt2x00dev, RT6352)) {//serge: rt6352 too (3)
+                       rt2800_bbp_write_with_rx_chain(rt2x00dev, 66,
+                                                      vgc_level);
+               } else if (rt2x00_rt(rt2x00dev, RT5592)) {
+@@ -5930,7 +6021,7 @@ static int rt2800_init_registers(struct
+                                             0x00550055);
+               } else {
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000401);
+-                      rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0000);
++                      rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0001);//serge:was 0x000C0000 (2)
+                       rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+                       rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000);
+                       rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0);
+@@ -6195,6 +6286,29 @@ static int rt2800_init_registers(struct
+               reg = rt2800_register_read(rt2x00dev, US_CYC_CNT);
+               rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 125);
+               rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
++      } else if (rt2x00_is_soc(rt2x00dev)) {//serge:which value correct? (4)
++              struct clk *clk = clk_get_sys("bus", NULL);
++              int rate;
++
++              if (IS_ERR(clk)) {
++                      rt2x00_warn(rt2x00dev, "system bus clock undefined\n");
++                      clk = clk_get_sys("cpu", NULL);
++
++                      if (IS_ERR(clk))
++                          rate = 125;
++                      else {
++                          rate = clk_get_rate(clk) / 3000000;
++                          clk_put(clk);
++                      }
++              } else {
++                      rate = clk_get_rate(clk) / 1000000;
++                      clk_put(clk);
++              }
++
++              rt2x00_info(rt2x00dev, "set US_CYC=%dMHz\n", rate);
++              reg = rt2800_register_read(rt2x00dev, US_CYC_CNT);
++              rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, rate);
++              rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
+       }
+       reg = rt2800_register_read(rt2x00dev, HT_FBK_CFG0);
+@@ -6981,26 +7095,7 @@ static void rt2800_init_bbp_5592(struct
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C))
+               rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+ }
+-
+-static void rt2800_bbp_glrt_write(struct rt2x00_dev *rt2x00dev,
+-                                const u8 reg, const u8 value)
+-{
+-      rt2800_bbp_write(rt2x00dev, 195, reg);
+-      rt2800_bbp_write(rt2x00dev, 196, value);
+-}
+-
+-static void rt2800_bbp_dcoc_write(struct rt2x00_dev *rt2x00dev,
+-                                const u8 reg, const u8 value)
+-{
+-      rt2800_bbp_write(rt2x00dev, 158, reg);
+-      rt2800_bbp_write(rt2x00dev, 159, value);
+-}
+-
+-static u8 rt2800_bbp_dcoc_read(struct rt2x00_dev *rt2x00dev, const u8 reg)
+-{
+-      rt2800_bbp_write(rt2x00dev, 158, reg);
+-      return rt2800_bbp_read(rt2x00dev, 159);
+-}
++//serge: move these function upper
+ static void rt2800_init_bbp_6352(struct rt2x00_dev *rt2x00dev)
+ {
+@@ -8635,7 +8730,7 @@ static void rt2800_r_calibration(struct
+               r_cal_code = (u8)rcalcode;
+       rt2800_rfcsr_write_bank(rt2x00dev, 0, 7, r_cal_code);
+-
++      pr_info("RF bank 0 reg 5=0x%02x\n", r_cal_code);//serge: just for info to compare with vendor driver
+       rt2800_bbp_write(rt2x00dev, 22, 0x0);
+       bytevalue = rt2800_bbp_read(rt2x00dev, 21);
+@@ -8693,7 +8788,7 @@ static void rt2800_rxdcoc_calibration(st
+                       break;
+       }
+-      saverfb5r4 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 0);
++      saverfb5r4 = rt2800_rfcsr_read_bank(rt2x00dev, 5, 4);//serge: was 0 - typo? (6)
+       saverfb7r4 = rt2800_rfcsr_read_bank(rt2x00dev, 7, 4);
+       saverfb5r4 = saverfb5r4 & (~0x40);
+       saverfb7r4 = saverfb7r4 & (~0x40);
+@@ -9022,13 +9117,15 @@ static void rt2800_rxiq_calibration(stru
+                               rt2x00_info(rt2x00dev, "RXIQ G_imb=%d, Ph_rx=%d\n", g_imb, ph_rx);
+                               if ((ph_rx > 20) || (ph_rx < -20)) {
++                                      rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL(ph_rx=%d out of [-20..20]", ph_rx);//serge:just to see value
+                                       ph_rx = 0;
+-                                      rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL");
++                                      //rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL");
+                               }
+                               if ((g_imb > 12) || (g_imb < -12)) {
++                                      rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL(g_imb=%d out of (-12..12]", g_imb);//serge:just to see the reason
+                                       g_imb = 0;
+-                                      rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL");
++                                      //rt2x00_warn(rt2x00dev, "RXIQ calibration FAIL");
+                               }
+                       }
+               else {
+@@ -9039,11 +9136,21 @@ static void rt2800_rxiq_calibration(stru
+               }
+               if (ch_idx == 0) {
++                      //serge: just to see values
++                      pr_info("RXIQ RX0 g_imb (0x37, %2x) ph_rx (0x35, %2x)\n",
++                          g_imb & 0x3f,
++                          ph_rx & 0x3f
++                      );
+                       rt2800_bbp_write(rt2x00dev, 158, 0x37);
+                       rt2800_bbp_write(rt2x00dev, 159, g_imb & 0x3f);
+                       rt2800_bbp_write(rt2x00dev, 158, 0x35);
+                       rt2800_bbp_write(rt2x00dev, 159, ph_rx & 0x3f);
+               } else {
++                      //serge: just to see values
++                      pr_info("RXIQ RX1 g_imb (0x55, %2x) ph_rx (0x53, %2x)\n",
++                          g_imb & 0x3f,
++                          ph_rx & 0x3f
++                      );
+                       rt2800_bbp_write(rt2x00dev, 158, 0x55);
+                       rt2800_bbp_write(rt2x00dev, 159, g_imb & 0x3f);
+                       rt2800_bbp_write(rt2x00dev, 158, 0x53);
+@@ -9745,6 +9852,15 @@ void rt2800_loft_iq_calibration(struct r
+       }
+       for (rf_alc_idx = 0; rf_alc_idx < 3; rf_alc_idx++) {
++              //serge: just to see values
++              pr_info("LOFT ALC (0xb0, %2x) I0 (0xb1, %2x) Q0 (0xb2, %2x) I1 (0xb8, %2x) Q1 (0xb9, %2x)\n",
++                  rf_alc_idx,
++                  loft_dc_search_result[CHAIN_0][rf_alc_idx][0x00] & 0x3F,
++                  loft_dc_search_result[CHAIN_0][rf_alc_idx][0x01] & 0x3F,
++                  loft_dc_search_result[CHAIN_1][rf_alc_idx][0x00] & 0x3F,
++                  loft_dc_search_result[CHAIN_1][rf_alc_idx][0x01] & 0x3F
++              );
++
+               for (idx = 0; idx < 4; idx++) {
+                       rt2800_bbp_write(rt2x00dev, 158, 0xB0);
+                       bbp = (idx<<2) + rf_alc_idx;
+@@ -10669,6 +10785,7 @@ static void rt2800_init_rfcsr_6352(struc
+               rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C);
+       }
++      rt6352_enable_pa_pin(rt2x00dev, 0);//serge: vendor driver do it before calibration (7b)
+       rt2800_r_calibration(rt2x00dev);
+       rt2800_rf_self_txdc_cal(rt2x00dev);
+       rt2800_rxdcoc_calibration(rt2x00dev);
+@@ -10676,6 +10793,29 @@ static void rt2800_init_rfcsr_6352(struc
+       rt2800_bw_filter_calibration(rt2x00dev, false);
+       rt2800_loft_iq_calibration(rt2x00dev);
+       rt2800_rxiq_calibration(rt2x00dev);
++      rt6352_enable_pa_pin(rt2x00dev, 1);//serge: vendor driver do it after calibration (7b)
++      /* Vendor driver restore iLNA/iPA before
++      recalibration and set correct values after.
++      Openwrt driver init iLNA and iPA but restore only
++      ePA values after recalibration.
++      So set eLNA values only
++      */
++      if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {//serge: rf regs never corrected for eLNA (7a)
++              rt2x00_info(rt2x00dev, "Correct RF/BBP for eLNA!\n");
++              rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66);
++              rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20);
++              rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x42);
++              rt2800_bbp_write(rt2x00dev, 75, 0x68);//serge: move bbp eLNA init here?
++              rt2800_bbp_write(rt2x00dev, 76, 0x4C);
++              rt2800_bbp_write(rt2x00dev, 79, 0x1C);
++              rt2800_bbp_write(rt2x00dev, 80, 0x0C);
++              rt2800_bbp_write(rt2x00dev, 82, 0xB6);
++              /* bank 0 RF reg 42 and glrt BBP reg 141
++              will be set in config channel function
++              in dependence of channel and HT20/HT40
++              so don't touch it
++              */
++      }
+ }
+ static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+@@ -28,6 +28,7 @@
+ #include <linux/average.h>
+ #include <linux/usb.h>
+ #include <linux/clk.h>
++#include <linux/pinctrl/consumer.h>
+ #include <linux/rt2x00_platform.h>
+ #include <net/mac80211.h>
+@@ -1029,6 +1030,11 @@ struct rt2x00_dev {
+       /* Clock for System On Chip devices. */
+       struct clk *clk;
++
++      /* pinctrl and states for System On Chip devices with PA/LNA. */
++      struct pinctrl *pinctrl;
++      struct pinctrl_state *pins_default;
++      struct pinctrl_state *pins_pa_gpio;
+ };
+ struct rt2x00_bar_list_entry {
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
+@@ -97,6 +97,21 @@ int rt2x00soc_probe(struct platform_devi
+       if (retval)
+               goto exit_free_reg;
++      rt2x00dev->pinctrl = devm_pinctrl_get(&pdev->dev);
++      if (IS_ERR(rt2x00dev->pinctrl)) {
++              rt2x00dev->pinctrl = NULL;
++              rt2x00dev->pins_default = NULL;
++              rt2x00dev->pins_pa_gpio = NULL;
++      } else {
++              rt2x00dev->pins_default = pinctrl_lookup_state(rt2x00dev->pinctrl, "default");
++              if (IS_ERR(rt2x00dev->pins_default))
++                      rt2x00dev->pins_default = NULL;
++
++              rt2x00dev->pins_pa_gpio = pinctrl_lookup_state(rt2x00dev->pinctrl, "pa_gpio");
++              if (IS_ERR(rt2x00dev->pins_pa_gpio))
++                      rt2x00dev->pins_pa_gpio = NULL;
++      }
++
+       return 0;
+ exit_free_reg:
index c33dd135fef11b736ea40819a6ea1e7f9b5db43c..4b6fa60dc8b72ea8b89a5fae53b83c44f487b4e5 100644 (file)
                        };
                };
 
+               pa_gpio_pins: pa_gpio {
+                       pa {
+                               groups = "pa";
+                               function = "gpio";
+                       };
+               };
+
                sdhci_pins: sdhci {
                        sdhci {
                                groups = "nd_sd";
index 7c8caa5066bb7bae996c2094a7d332e88c249a6c..4b960da312b96590073f55c81b49b7a3dc99a9f0 100644 (file)
 
 &wmac {
        ralink,mtd-eeprom = <&factory 0x0>;
-       pinctrl-names = "default";
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 };
 
 &factory {
index 3174b98bbf8876a7308474cc71e4d53fa644dbed..d0113f55603b4282381cd302dc69a060144650aa 100644 (file)
 };
 
 &wmac {
-       pinctrl-names = "default";
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 
        ralink,mtd-eeprom = <&factory 0x0>;
        nvmem-cells = <&macaddr_factory_28>;
index 68b733cade28ba924fc177fb212979aa8ca5f726..2884bfdb0460dc12c80b9880b7bc1cc1748726d0 100644 (file)
 
 &wmac {
        ralink,mtd-eeprom = <&factory 0x0>;
-       pinctrl-names = "default";
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 };
 
 &factory {
index 69ddea589b989d3ab7c4688cbf1a2e41cff6d879..8f95204ad19deb3bee494508085a0a6be4423d20 100644 (file)
 
 &wmac {
        ralink,mtd-eeprom = <&factory 0x0>;
-       pinctrl-names = "default";
+
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>, <&wled_pins>;
+       pinctrl-1 = <&pa_gpio_pins>, <&wled_pins>;
 };
 
 &pcie {
index 10aa0ddf6f960d2e1ac355527dc3c3362cc9ff32..87eacb13d7802ff69ead8e48882dcb2cbd930b24 100644 (file)
 };
 
 &wmac {
-       pinctrl-names = "default";
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 };
index c7b7ea7b90a4c5d76e3ea944345b13688f51e70d..5e834d291dc6b2a8fd433ce6c2bc9f3b0f93d0b6 100644 (file)
 };
 
 &wmac {
-       ralink,mtd-eeprom = <&factory 0x0>;
-       pinctrl-names = "default";
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
+
+       ralink,mtd-eeprom = <&factory 0x0>;
 };
 
 &state_default {
index 4e9fc1307ba565cb6bfb51588a41a3e11430c104..52d131556d5e7466f69ac26fd8f4a69573a26a62 100644 (file)
@@ -18,6 +18,7 @@
 };
 
 &wmac {
-       pinctrl-names = "default";
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 };
index 2a682872c67c02330a37bb8006fc5c79119ac80b..cf9d0b290ca27bc8ddf68a6194fd76f27a37b2a7 100644 (file)
@@ -24,6 +24,7 @@
 };
 
 &wmac {
-       pinctrl-names = "default";
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 };
index d113edc19fd34d331f258218bd7a79d392107ab2..bc934d705845e229e7979167994d8ca49b6fedc6 100644 (file)
@@ -42,6 +42,7 @@
 };
 
 &wmac {
-       pinctrl-names = "default";
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 };
index e3c077cb0d5395ac2583f9a16b0c8de8ab776656..8fe5b9c3a2c779a09233e943fdef5b6bad410117 100644 (file)
@@ -69,8 +69,9 @@
 };
 
 &wmac {
-       pinctrl-names = "default";
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 
        nvmem-cells = <&macaddr_rom_f100>;
        nvmem-cell-names = "mac-address";
index aefd951f43c5c6a9772a411578d5b37262d5ef27..4dbd1b2a98670e859c66a3264bc11af8890fe6cc 100644 (file)
@@ -69,8 +69,9 @@
 };
 
 &wmac {
-       pinctrl-names = "default";
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 
        nvmem-cells = <&macaddr_rom_f100>;
        nvmem-cell-names = "mac-address";
index b0522de7d0ce1fb126fb0babb6154e0990271259..9f58fb86ee83ceefabe0597d6790ca2a9eee893c 100644 (file)
 };
 
 &wmac {
-       pinctrl-names = "default";
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 
        ralink,mtd-eeprom = <&factory 0x0>;
 };
index 9f5df5dd795a552786bf9b7795693900de78293c..1dd3f2eb471afd37714ef1d9d9b9f5b6a232892b 100644 (file)
 
 &wmac {
        ralink,mtd-eeprom = <&factory 0x0>;
-       pinctrl-names = "default";
+
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 };
 
 &pcie {
index ac874cef3d82f18032f59f3d2c8b9e35d943f1c0..d15d2c0f4b66ec25d32cbd923f01d98b4be88473 100644 (file)
 
 &wmac {
        ralink,mtd-eeprom = <&factory 0x0>;
+
+       pinctrl-names = "default", "pa_gpio";
+       pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 };
 
 &sdhci {
index 6fcda971a6930340943a559bd8be73045c09ab65..ceb348e1d24e6b4b3cf4ffb99188204060fe1b17 100644 (file)
 
 &wmac {
        ralink,mtd-eeprom = <&factory 0x0>;
-       pinctrl-names = "default";
+
+       pinctrl-names = "default", "pa_gpio";
        pinctrl-0 = <&pa_pins>;
+       pinctrl-1 = <&pa_gpio_pins>;
 };
 
 &pcie {