Message ID | TYAP286MB031579E1EB23ED9ACF194373BC00A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM |
---|---|
State | Accepted |
Delegated to: | Daniel Golle |
Headers | show |
Series | [1/2] mac80211: rework MT7620 PA/LNA RF calibration | expand |
Hi! Thank you for your contribution. I (probably) found a minor typo, see below: On Wed, Jul 26, 2023 at 09:22:22PM +0800, Shiji Yang wrote: > From: Shiji Yang <yangshiji66@qq.com> > > This patch makes some improvements to the MT7620 RF calibration. > > 1. Move MT7620 PA/LNA calibration code to dedicated functions. > 2. Restore RF and BBP registers before R-Calibration. > 3. Do Rx DCOC calibration again before RXIQ calibration. > 4. Correct MAC_RX_EN mask in rt2800_r_calibration()[1]. > > [1] This change may fix the "BBP/RF register access failed" error: > ieee80211 phy0: rt2800_wait_bbp_rf_ready: Error - BBP/RF register access failed, aborting > > Signed-off-by: Shiji Yang <yangshiji66@qq.com> > --- > ...-rework-MT7620-PA-LNA-RF-calibration.patch | 312 ++++++++++++++++++ > 1 file changed, 312 insertions(+) > create mode 100644 package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch > > diff --git a/package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch b/package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch > new file mode 100644 > index 0000000000..0cf34f3a6c > --- /dev/null > +++ b/package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch > @@ -0,0 +1,312 @@ > +From: Shiji Yang <yangshiji66@outlook.com> > +Date: Tue, 25 Jul 2023 20:05:06 +0800 > +Subject: [PATCH] wifi: rt2x00: rework MT7620 PA/LNA RF calibration > + > +1. Move MT7620 PA/LNA calibration code to dedicated functions. > + Calibration stage 1 is executed before configuring channels and > + stage 2 is executed after configuring channels. > +2. For external PA/LNA devices, restore RF and BBP registers before > + R-Calibration. > +3. Do Rx DCOC calibration again before RXIQ calibration. > +4. Correct MAC_SYS_CTRL register RX mask to 0x08 in R-Calibration > + function. For MAC_SYS_CTRL register, Bit[2] controls MAC_TX_EN > + and Bit[3] controls MAC_RX_EN (Bit index starts from 0). > +5. Adjust the register operation sequence according to the vendor > + driver code. This may not be useful, but it can make things > + clearer when developers try to review it. > + > +Signed-off-by: Shiji Yang <yangshiji66@outlook.com> > +--- > + .../net/wireless/ralink/rt2x00/rt2800lib.c | 220 ++++++++++++------ > + drivers/net/wireless/ralink/rt2x00/rt2x00.h | 6 + > + 2 files changed, 151 insertions(+), 75 deletions(-) > + > +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c > ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c > +@@ -62,6 +62,9 @@ MODULE_PARM_DESC(watchdog, "Enable watch > + rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \ > + H2M_MAILBOX_CSR_OWNER, (__reg)) > + > ++static void rt6352_init_palna_stage1(struct rt2x00_dev *rt2x00dev); > ++static void rt6352_init_palna_stage2(struct rt2x00_dev *rt2x00dev); > ++ > + static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev) > + { > + /* check for rt2872 on SoC */ > +@@ -4151,6 +4154,9 @@ static void rt2800_config_channel(struct > + rt2800_txpower_to_dev(rt2x00dev, rf->channel, > + info->default_power3); > + > ++ if (rt2x00_rt(rt2x00dev, RT6352)) > ++ rt6352_init_palna_stage1(rt2x00dev); > ++ > + switch (rt2x00dev->chip.rt) { > + case RT3883: > + rt3883_bbp_adjust(rt2x00dev, rf); > +@@ -4482,66 +4488,6 @@ static void rt2800_config_channel(struct > + rt2800_iq_calibrate(rt2x00dev, rf->channel); > + } > + > +- if (rt2x00_rt(rt2x00dev, RT6352)) { > +- if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, > +- &rt2x00dev->cap_flags)) { > +- 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, 43, 0x73); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xC8); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xA4); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xC8); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xA4); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xC8); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xA4); > +- rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05); > +- rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00); > +- > +- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, > +- 0x36303636); > +- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, > +- 0x6C6C6B6C); > +- rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, > +- 0x6C6C6B6C); > +- } > +- > +- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { > +- 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); > +- 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); > + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); > + rt2800_bbp_write(rt2x00dev, 4, bbp); > +@@ -4550,6 +4496,9 @@ static void rt2800_config_channel(struct > + rt2x00_set_field8(&bbp, BBP3_HT40_MINUS, conf_is_ht40_minus(conf)); > + rt2800_bbp_write(rt2x00dev, 3, bbp); > + > ++ if (rt2x00_rt(rt2x00dev, RT6352)) > ++ rt6352_init_palna_stage2(rt2x00dev); > ++ > + if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { > + if (conf_is_ht40(conf)) { > + rt2800_bbp_write(rt2x00dev, 69, 0x1a); > +@@ -8650,7 +8599,7 @@ static void rt2800_r_calibration(struct > + rt2x00_warn(rt2x00dev, "Wait MAC Tx Status to MAX !!!\n"); > + > + maccfg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); > +- maccfg &= (~0x04); > ++ maccfg &= (~0x08); > + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, maccfg); > + > + if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY_RX))) > +@@ -10688,30 +10637,151 @@ static void rt2800_init_rfcsr_6352(struc > + rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); > + rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); > + } > ++} > + > +- rt6352_enable_pa_pin(rt2x00dev, 0); > +- rt2800_r_calibration(rt2x00dev); > +- rt2800_rf_self_txdc_cal(rt2x00dev); > +- rt2800_rxdcoc_calibration(rt2x00dev); > +- rt2800_bw_filter_calibration(rt2x00dev, true); > +- rt2800_bw_filter_calibration(rt2x00dev, false); > +- rt2800_loft_iq_calibration(rt2x00dev); > +- rt2800_rxiq_calibration(rt2x00dev); > +- rt6352_enable_pa_pin(rt2x00dev, 1); > ++static void rt6352_inint_ext_palna(struct rt2x00_dev *rt2x00dev) 'inint' should probably be 'init' (?) > ++{ > ++ u32 reg; > ++ > ++ if (rt2x00_has_cap_external_pa(rt2x00dev)) { > ++ 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); > ++ } > + > +- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { > ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && > ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { > + rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66); > + rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20); > + rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x42); > ++ } > ++ > ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && > ++ rt2x00_has_cap_external_pa(rt2x00dev)) { > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0x73); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xC8); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xA4); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xC8); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xA4); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xC8); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xA4); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05); > ++ } > ++ > ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && > ++ rt2x00_has_cap_external_pa(rt2x00dev)) { > ++ rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00); > ++ } > ++ > ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && > ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { > + rt2800_bbp_write(rt2x00dev, 75, 0x68); > + 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 them here. > +- */ > ++ } > ++ > ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && > ++ rt2x00_has_cap_external_pa(rt2x00dev)) { > ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, 0x36303636); > ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6C6C6B6C); > ++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, 0x6C6C6B6C); > ++ } > ++} > ++ > ++static void rt6352_restore_rf_bbp(struct rt2x00_dev *rt2x00dev) > ++{ > ++ if (rt2x00_has_cap_external_pa(rt2x00dev)) { > ++ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x0); > ++ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0); > ++ } > ++ > ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && > ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x02); > ++ } > ++ > ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && > ++ rt2x00_has_cap_external_pa(rt2x00dev)) > ++ { > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xB3); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xFF); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x1C); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x20); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7); > ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09); > ++ } > ++ > ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && > ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { > ++ rt2800_bbp_write(rt2x00dev, 75, 0x60); > ++ rt2800_bbp_write(rt2x00dev, 76, 0x44); > ++ rt2800_bbp_write(rt2x00dev, 79, 0x1C); > ++ rt2800_bbp_write(rt2x00dev, 80, 0x0C); > ++ rt2800_bbp_write(rt2x00dev, 82, 0xB6); > ++ } > ++ > ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 > ++ && rt2x00_has_cap_external_pa(rt2x00dev)) { > ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, 0x3630363A); > ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6C6C666C); > ++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, 0x6C6C666C); > ++ } > ++} > ++ > ++/* MT7620 PA/LNA initialization before switching channels */ > ++static void rt6352_init_palna_stage1(struct rt2x00_dev *rt2x00dev) > ++{ > ++ if (rt2x00_has_cap_external_pa(rt2x00dev) || > ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { > ++ rt6352_enable_pa_pin(rt2x00dev, 0); > ++ rt6352_restore_rf_bbp(rt2x00dev); > ++ } > ++ > ++ rt2800_r_calibration(rt2x00dev); > ++} > ++ > ++/* MT7620 PA/LNA initialization after switching channels */ > ++static void rt6352_init_palna_stage2(struct rt2x00_dev *rt2x00dev) > ++{ > ++ rt2800_rf_self_txdc_cal(rt2x00dev); > ++ rt2800_rxdcoc_calibration(rt2x00dev); > ++ rt2800_bw_filter_calibration(rt2x00dev, true); > ++ rt2800_bw_filter_calibration(rt2x00dev, false); > ++ rt2800_loft_iq_calibration(rt2x00dev); > ++ > ++ /* missing DPD Calibration for devices using internal PA */ > ++ > ++ rt2800_rxdcoc_calibration(rt2x00dev); > ++ rt2800_rxiq_calibration(rt2x00dev); > ++ > ++ if(rt2x00_has_cap_external_pa(rt2x00dev) || > ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { > ++ rt6352_enable_pa_pin(rt2x00dev, 1); > ++ rt6352_inint_ext_palna(rt2x00dev); > + } > + } > + > +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h > ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h > +@@ -1277,6 +1277,12 @@ rt2x00_has_cap_external_lna_bg(struct rt > + } > + > + static inline bool > ++rt2x00_has_cap_external_pa(struct rt2x00_dev *rt2x00dev) > ++{ > ++ return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_PA_TX0); > ++} > ++ > ++static inline bool > + rt2x00_has_cap_double_antenna(struct rt2x00_dev *rt2x00dev) > + { > + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_DOUBLE_ANTENNA); > -- > 2.39.2 >
Thanks for your review! on July 26, 2023, 1:49 p.m. UTC, Daniel Golle wrote: >Hi! > >Thank you for your contribution. >I (probably) found a minor typo, see below: > >On Wed, Jul 26, 2023 at 09:22:22PM +0800, Shiji Yang wrote: >> From: Shiji Yang <yangshiji66@qq.com> >> >> This patch makes some improvements to the MT7620 RF calibration. >> >> 1. Move MT7620 PA/LNA calibration code to dedicated functions. >> 2. Restore RF and BBP registers before R-Calibration. >> 3. Do Rx DCOC calibration again before RXIQ calibration. >> 4. Correct MAC_RX_EN mask in rt2800_r_calibration()[1]. >> >> [1] This change may fix the "BBP/RF register access failed" error: >> ieee80211 phy0: rt2800_wait_bbp_rf_ready: Error - BBP/RF register access failed, aborting >> >> Signed-off-by: Shiji Yang <yangshiji66@qq.com> >> --- >> ...-rework-MT7620-PA-LNA-RF-calibration.patch | 312 ++++++++++++++++++ >> 1 file changed, 312 insertions(+) >> create mode 100644 package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch >> >> diff --git a/package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch b/package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch >> new file mode 100644 >> index 0000000000..0cf34f3a6c >> +@@ -10688,30 +10637,151 @@ static void rt2800_init_rfcsr_6352(struc >> + rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); >> + rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); >> + } >> ++} >> + >> +- rt6352_enable_pa_pin(rt2x00dev, 0); >> +- rt2800_r_calibration(rt2x00dev); >> +- rt2800_rf_self_txdc_cal(rt2x00dev); >> +- rt2800_rxdcoc_calibration(rt2x00dev); >> +- rt2800_bw_filter_calibration(rt2x00dev, true); >> +- rt2800_bw_filter_calibration(rt2x00dev, false); >> +- rt2800_loft_iq_calibration(rt2x00dev); >> +- rt2800_rxiq_calibration(rt2x00dev); >> +- rt6352_enable_pa_pin(rt2x00dev, 1); >> ++static void rt6352_inint_ext_palna(struct rt2x00_dev *rt2x00dev) > >'inint' should probably be 'init' (?) Yes, you are right. It should be 'init'. >> ++/* MT7620 PA/LNA initialization after switching channels */ >> ++static void rt6352_init_palna_stage2(struct rt2x00_dev *rt2x00dev) >> ++{ >> ++ rt2800_rf_self_txdc_cal(rt2x00dev); >> ++ rt2800_rxdcoc_calibration(rt2x00dev); >> ++ rt2800_bw_filter_calibration(rt2x00dev, true); >> ++ rt2800_bw_filter_calibration(rt2x00dev, false); >> ++ rt2800_loft_iq_calibration(rt2x00dev); >> ++ >> ++ /* missing DPD Calibration for devices using internal PA */ >> ++ >> ++ rt2800_rxdcoc_calibration(rt2x00dev); >> ++ rt2800_rxiq_calibration(rt2x00dev); >> ++ >> ++ if(rt2x00_has_cap_external_pa(rt2x00dev) || >> ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { >> ++ rt6352_enable_pa_pin(rt2x00dev, 1); >> ++ rt6352_inint_ext_palna(rt2x00dev); And same typo error 'inint' here. Do I need to send a v2 version to fix it? Or maybe you would like to manually edit it to avoid too many emails? Best Regards, Shiji Yang
On Wed, Jul 26, 2023 at 02:57:08PM +0000, 杨 世基 wrote: > Thanks for your review! > > on July 26, 2023, 1:49 p.m. UTC, Daniel Golle wrote: > >Hi! > > > >Thank you for your contribution. > >I (probably) found a minor typo, see below: > > > >On Wed, Jul 26, 2023 at 09:22:22PM +0800, Shiji Yang wrote: > >> From: Shiji Yang <yangshiji66@qq.com> > >> > >> This patch makes some improvements to the MT7620 RF calibration. > >> > >> 1. Move MT7620 PA/LNA calibration code to dedicated functions. > >> 2. Restore RF and BBP registers before R-Calibration. > >> 3. Do Rx DCOC calibration again before RXIQ calibration. > >> 4. Correct MAC_RX_EN mask in rt2800_r_calibration()[1]. > >> > >> [1] This change may fix the "BBP/RF register access failed" error: > >> ieee80211 phy0: rt2800_wait_bbp_rf_ready: Error - BBP/RF register access failed, aborting > >> > >> Signed-off-by: Shiji Yang <yangshiji66@qq.com> > >> --- > >> ...-rework-MT7620-PA-LNA-RF-calibration.patch | 312 ++++++++++++++++++ > >> 1 file changed, 312 insertions(+) > >> create mode 100644 package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch > >> > >> diff --git a/package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch b/package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch > >> new file mode 100644 > >> index 0000000000..0cf34f3a6c > >> +@@ -10688,30 +10637,151 @@ static void rt2800_init_rfcsr_6352(struc > >> + rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); > >> + rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); > >> + } > >> ++} > >> + > >> +- rt6352_enable_pa_pin(rt2x00dev, 0); > >> +- rt2800_r_calibration(rt2x00dev); > >> +- rt2800_rf_self_txdc_cal(rt2x00dev); > >> +- rt2800_rxdcoc_calibration(rt2x00dev); > >> +- rt2800_bw_filter_calibration(rt2x00dev, true); > >> +- rt2800_bw_filter_calibration(rt2x00dev, false); > >> +- rt2800_loft_iq_calibration(rt2x00dev); > >> +- rt2800_rxiq_calibration(rt2x00dev); > >> +- rt6352_enable_pa_pin(rt2x00dev, 1); > >> ++static void rt6352_inint_ext_palna(struct rt2x00_dev *rt2x00dev) > > > >'inint' should probably be 'init' (?) > > > Yes, you are right. It should be 'init'. > > > >> ++/* MT7620 PA/LNA initialization after switching channels */ > >> ++static void rt6352_init_palna_stage2(struct rt2x00_dev *rt2x00dev) > >> ++{ > >> ++ rt2800_rf_self_txdc_cal(rt2x00dev); > >> ++ rt2800_rxdcoc_calibration(rt2x00dev); > >> ++ rt2800_bw_filter_calibration(rt2x00dev, true); > >> ++ rt2800_bw_filter_calibration(rt2x00dev, false); > >> ++ rt2800_loft_iq_calibration(rt2x00dev); > >> ++ > >> ++ /* missing DPD Calibration for devices using internal PA */ > >> ++ > >> ++ rt2800_rxdcoc_calibration(rt2x00dev); > >> ++ rt2800_rxiq_calibration(rt2x00dev); > >> ++ > >> ++ if(rt2x00_has_cap_external_pa(rt2x00dev) || > >> ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { > >> ++ rt6352_enable_pa_pin(rt2x00dev, 1); > >> ++ rt6352_inint_ext_palna(rt2x00dev); > > > And same typo error 'inint' here. > > Do I need to send a v2 version to fix it? Or maybe you would like to > manually edit it to avoid too many emails? The best would be you'd give it a day for further reviews from others, and then send v2 with all comments up to this point fixed. To me this looks good, and I hope you will also send this and your previous patch for rt2x00 to the linux-wireless mailing list to have it included upstream. Thank you again for your work! > > Best Regards, > Shiji Yang
>On Wed, Jul 26, 2023 at 02:57:08PM +0000, 杨 世基 wrote: >> Thanks for your review! >> >> on July 26, 2023, 1:49 p.m. UTC, Daniel Golle wrote: >> >Hi! >> > >> >Thank you for your contribution. >> >I (probably) found a minor typo, see below: >> > >> >On Wed, Jul 26, 2023 at 09:22:22PM +0800, Shiji Yang wrote: >> >> From: Shiji Yang <yangshiji66@qq.com> >> >> >> >> This patch makes some improvements to the MT7620 RF calibration. >> >> >> >> 1. Move MT7620 PA/LNA calibration code to dedicated functions. >> >> 2. Restore RF and BBP registers before R-Calibration. >> >> 3. Do Rx DCOC calibration again before RXIQ calibration. >> >> 4. Correct MAC_RX_EN mask in rt2800_r_calibration()[1]. >> >> >> >> [1] This change may fix the "BBP/RF register access failed" error: >> >> ieee80211 phy0: rt2800_wait_bbp_rf_ready: Error - BBP/RF register access failed, aborting >> >> >> >> Signed-off-by: Shiji Yang <yangshiji66@qq.com> >> >> --- >> >> ...-rework-MT7620-PA-LNA-RF-calibration.patch | 312 ++++++++++++++++++ >> >> 1 file changed, 312 insertions(+) >> >> create mode 100644 package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch >> >> >> >> diff --git a/package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch b/package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch >> >> new file mode 100644 >> >> index 0000000000..0cf34f3a6c >> >> +@@ -10688,30 +10637,151 @@ static void rt2800_init_rfcsr_6352(struc >> >> + rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); >> >> + rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); >> >> + } >> >> ++} >> >> + >> >> +- rt6352_enable_pa_pin(rt2x00dev, 0); >> >> +- rt2800_r_calibration(rt2x00dev); >> >> +- rt2800_rf_self_txdc_cal(rt2x00dev); >> >> +- rt2800_rxdcoc_calibration(rt2x00dev); >> >> +- rt2800_bw_filter_calibration(rt2x00dev, true); >> >> +- rt2800_bw_filter_calibration(rt2x00dev, false); >> >> +- rt2800_loft_iq_calibration(rt2x00dev); >> >> +- rt2800_rxiq_calibration(rt2x00dev); >> >> +- rt6352_enable_pa_pin(rt2x00dev, 1); >> >> ++static void rt6352_inint_ext_palna(struct rt2x00_dev *rt2x00dev) >> > >> >'inint' should probably be 'init' (?) >> >> >> Yes, you are right. It should be 'init'. >> >> >> >> ++/* MT7620 PA/LNA initialization after switching channels */ >> >> ++static void rt6352_init_palna_stage2(struct rt2x00_dev *rt2x00dev) >> >> ++{ >> >> ++ rt2800_rf_self_txdc_cal(rt2x00dev); >> >> ++ rt2800_rxdcoc_calibration(rt2x00dev); >> >> ++ rt2800_bw_filter_calibration(rt2x00dev, true); >> >> ++ rt2800_bw_filter_calibration(rt2x00dev, false); >> >> ++ rt2800_loft_iq_calibration(rt2x00dev); >> >> ++ >> >> ++ /* missing DPD Calibration for devices using internal PA */ >> >> ++ >> >> ++ rt2800_rxdcoc_calibration(rt2x00dev); >> >> ++ rt2800_rxiq_calibration(rt2x00dev); >> >> ++ >> >> ++ if(rt2x00_has_cap_external_pa(rt2x00dev) || >> >> ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { >> >> ++ rt6352_enable_pa_pin(rt2x00dev, 1); >> >> ++ rt6352_inint_ext_palna(rt2x00dev); >> >> >> And same typo error 'inint' here. >> >> Do I need to send a v2 version to fix it? Or maybe you would like to >> manually edit it to avoid too many emails? > >The best would be you'd give it a day for further reviews from others, >and then send v2 with all comments up to this point fixed. > >To me this looks good, and I hope you will also send this and your >previous patch for rt2x00 to the linux-wireless mailing list to have >it included upstream. > >Thank you again for your work! > >> >> Best Regards, >> Shiji Yang Thanks, I'll definitely send them to Linux mailing lists later. But before that, I have to confirm that they are fully compatible with upstream version, as we have a lot of local patches. By the way, I have sent the patch[2/2] to the upstream: https://lore.kernel.org/all/TYAP286MB0315A9671B4BA0347E70D9E0BC00A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM/ I will send the v2 version this weekend. Regards Shiji Yang
diff --git a/package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch b/package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch new file mode 100644 index 0000000000..0cf34f3a6c --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/998-wifi-rt2x00-rework-MT7620-PA-LNA-RF-calibration.patch @@ -0,0 +1,312 @@ +From: Shiji Yang <yangshiji66@outlook.com> +Date: Tue, 25 Jul 2023 20:05:06 +0800 +Subject: [PATCH] wifi: rt2x00: rework MT7620 PA/LNA RF calibration + +1. Move MT7620 PA/LNA calibration code to dedicated functions. + Calibration stage 1 is executed before configuring channels and + stage 2 is executed after configuring channels. +2. For external PA/LNA devices, restore RF and BBP registers before + R-Calibration. +3. Do Rx DCOC calibration again before RXIQ calibration. +4. Correct MAC_SYS_CTRL register RX mask to 0x08 in R-Calibration + function. For MAC_SYS_CTRL register, Bit[2] controls MAC_TX_EN + and Bit[3] controls MAC_RX_EN (Bit index starts from 0). +5. Adjust the register operation sequence according to the vendor + driver code. This may not be useful, but it can make things + clearer when developers try to review it. + +Signed-off-by: Shiji Yang <yangshiji66@outlook.com> +--- + .../net/wireless/ralink/rt2x00/rt2800lib.c | 220 ++++++++++++------ + drivers/net/wireless/ralink/rt2x00/rt2x00.h | 6 + + 2 files changed, 151 insertions(+), 75 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -62,6 +62,9 @@ MODULE_PARM_DESC(watchdog, "Enable watch + rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \ + H2M_MAILBOX_CSR_OWNER, (__reg)) + ++static void rt6352_init_palna_stage1(struct rt2x00_dev *rt2x00dev); ++static void rt6352_init_palna_stage2(struct rt2x00_dev *rt2x00dev); ++ + static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev) + { + /* check for rt2872 on SoC */ +@@ -4151,6 +4154,9 @@ static void rt2800_config_channel(struct + rt2800_txpower_to_dev(rt2x00dev, rf->channel, + info->default_power3); + ++ if (rt2x00_rt(rt2x00dev, RT6352)) ++ rt6352_init_palna_stage1(rt2x00dev); ++ + switch (rt2x00dev->chip.rt) { + case RT3883: + rt3883_bbp_adjust(rt2x00dev, rf); +@@ -4482,66 +4488,6 @@ static void rt2800_config_channel(struct + rt2800_iq_calibrate(rt2x00dev, rf->channel); + } + +- if (rt2x00_rt(rt2x00dev, RT6352)) { +- if (test_bit(CAPABILITY_EXTERNAL_PA_TX0, +- &rt2x00dev->cap_flags)) { +- 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, 43, 0x73); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xC8); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xA4); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xC8); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xA4); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xC8); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xA4); +- rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05); +- rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00); +- +- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, +- 0x36303636); +- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, +- 0x6C6C6B6C); +- rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, +- 0x6C6C6B6C); +- } +- +- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { +- 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); +- 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); + rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); + rt2800_bbp_write(rt2x00dev, 4, bbp); +@@ -4550,6 +4496,9 @@ static void rt2800_config_channel(struct + rt2x00_set_field8(&bbp, BBP3_HT40_MINUS, conf_is_ht40_minus(conf)); + rt2800_bbp_write(rt2x00dev, 3, bbp); + ++ if (rt2x00_rt(rt2x00dev, RT6352)) ++ rt6352_init_palna_stage2(rt2x00dev); ++ + if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { + if (conf_is_ht40(conf)) { + rt2800_bbp_write(rt2x00dev, 69, 0x1a); +@@ -8650,7 +8599,7 @@ static void rt2800_r_calibration(struct + rt2x00_warn(rt2x00dev, "Wait MAC Tx Status to MAX !!!\n"); + + maccfg = rt2800_register_read(rt2x00dev, MAC_SYS_CTRL); +- maccfg &= (~0x04); ++ maccfg &= (~0x08); + rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, maccfg); + + if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev, MAC_STATUS_CFG_BBP_RF_BUSY_RX))) +@@ -10688,30 +10637,151 @@ static void rt2800_init_rfcsr_6352(struc + rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); + rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); + } ++} + +- rt6352_enable_pa_pin(rt2x00dev, 0); +- rt2800_r_calibration(rt2x00dev); +- rt2800_rf_self_txdc_cal(rt2x00dev); +- rt2800_rxdcoc_calibration(rt2x00dev); +- rt2800_bw_filter_calibration(rt2x00dev, true); +- rt2800_bw_filter_calibration(rt2x00dev, false); +- rt2800_loft_iq_calibration(rt2x00dev); +- rt2800_rxiq_calibration(rt2x00dev); +- rt6352_enable_pa_pin(rt2x00dev, 1); ++static void rt6352_inint_ext_palna(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ ++ if (rt2x00_has_cap_external_pa(rt2x00dev)) { ++ 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); ++ } + +- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { + rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x66); + rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x20); + rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x42); ++ } ++ ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && ++ rt2x00_has_cap_external_pa(rt2x00dev)) { ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0x73); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xC8); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xA4); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xC8); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xA4); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xC8); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xA4); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05); ++ } ++ ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && ++ rt2x00_has_cap_external_pa(rt2x00dev)) { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00); ++ } ++ ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { + rt2800_bbp_write(rt2x00dev, 75, 0x68); + 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 them here. +- */ ++ } ++ ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && ++ rt2x00_has_cap_external_pa(rt2x00dev)) { ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, 0x36303636); ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6C6C6B6C); ++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, 0x6C6C6B6C); ++ } ++} ++ ++static void rt6352_restore_rf_bbp(struct rt2x00_dev *rt2x00dev) ++{ ++ if (rt2x00_has_cap_external_pa(rt2x00dev)) { ++ rt2800_register_write(rt2x00dev, RF_CONTROL3, 0x0); ++ rt2800_register_write(rt2x00dev, RF_BYPASS3, 0x0); ++ } ++ ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x02); ++ } ++ ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && ++ rt2x00_has_cap_external_pa(rt2x00dev)) ++ { ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xB3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xFF); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x1C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x20); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09); ++ } ++ ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 && ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { ++ rt2800_bbp_write(rt2x00dev, 75, 0x60); ++ rt2800_bbp_write(rt2x00dev, 76, 0x44); ++ rt2800_bbp_write(rt2x00dev, 79, 0x1C); ++ rt2800_bbp_write(rt2x00dev, 80, 0x0C); ++ rt2800_bbp_write(rt2x00dev, 82, 0xB6); ++ } ++ ++ if (rt2800_hw_get_chippkg(rt2x00dev) == 1 ++ && rt2x00_has_cap_external_pa(rt2x00dev)) { ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, 0x3630363A); ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6C6C666C); ++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, 0x6C6C666C); ++ } ++} ++ ++/* MT7620 PA/LNA initialization before switching channels */ ++static void rt6352_init_palna_stage1(struct rt2x00_dev *rt2x00dev) ++{ ++ if (rt2x00_has_cap_external_pa(rt2x00dev) || ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { ++ rt6352_enable_pa_pin(rt2x00dev, 0); ++ rt6352_restore_rf_bbp(rt2x00dev); ++ } ++ ++ rt2800_r_calibration(rt2x00dev); ++} ++ ++/* MT7620 PA/LNA initialization after switching channels */ ++static void rt6352_init_palna_stage2(struct rt2x00_dev *rt2x00dev) ++{ ++ rt2800_rf_self_txdc_cal(rt2x00dev); ++ rt2800_rxdcoc_calibration(rt2x00dev); ++ rt2800_bw_filter_calibration(rt2x00dev, true); ++ rt2800_bw_filter_calibration(rt2x00dev, false); ++ rt2800_loft_iq_calibration(rt2x00dev); ++ ++ /* missing DPD Calibration for devices using internal PA */ ++ ++ rt2800_rxdcoc_calibration(rt2x00dev); ++ rt2800_rxiq_calibration(rt2x00dev); ++ ++ if(rt2x00_has_cap_external_pa(rt2x00dev) || ++ rt2x00_has_cap_external_lna_bg(rt2x00dev)) { ++ rt6352_enable_pa_pin(rt2x00dev, 1); ++ rt6352_inint_ext_palna(rt2x00dev); + } + } + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h +@@ -1277,6 +1277,12 @@ rt2x00_has_cap_external_lna_bg(struct rt + } + + static inline bool ++rt2x00_has_cap_external_pa(struct rt2x00_dev *rt2x00dev) ++{ ++ return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_PA_TX0); ++} ++ ++static inline bool + rt2x00_has_cap_double_antenna(struct rt2x00_dev *rt2x00dev) + { + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_DOUBLE_ANTENNA);