Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rt2x00: add RT6352 specific calibration routines #626

Closed
wants to merge 7 commits into from
Closed

rt2x00: add RT6352 specific calibration routines #626

wants to merge 7 commits into from

Conversation

psyborg55
Copy link
Contributor

Add several calibration routines as found in mtk driver. Reduce power usage and revert AGC register value.

Signed-off-by: Tomislav Požega pozega.tomislav@gmail.com

This helps devices to sync at better TX/RX rates and improves overall
 performance.

Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
This helps devices to sync at better TX/RX rates and improves overall
 performance.

Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
Add TX self calibration based on mtk driver.

Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
Add r calibration code as found in mtk driver.

Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
Add RXDCOC calibration code from mtk driver. Please try if this makes any difference among various board/RF layouts.

Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
Add RXIQ calibration found in mtk driver. With old openwrt builds this gets us ~8Mbps more of RX bandwidth (test with iPA/eLNA layout).
Please try if this makes any difference among various board/RF layouts.

Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
@pepe2k pepe2k added kernel pull request/issue with Linux kernel related changes core packages pull request/issue for core (in-tree) packages labels Jan 8, 2018
Add TX LOFT calibration from mtk driver.

Signed-off-by: Tomislav Požega <pozega.tomislav@gmail.com>
Copy link
Member

@dangowrt dangowrt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[daniel@box patches]$ /usr/src/linux/scripts/checkpatch.pl 984-rt2x00-add-rxdcoc-calibration.patch 
CHECK: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt
#30: FILE: drivers/net/wireless/ralink/rt2x00/rt2800lib.c:7884:
+			udelay(50);

ERROR: spaces required around that '==' (ctx:VxV)
#52: FILE: drivers/net/wireless/ralink/rt2x00/rt2800lib.c:7906:
+		if ((bbpreg & 0x40)==0)
 		                   ^

CHECK: usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt
#54: FILE: drivers/net/wireless/ralink/rt2x00/rt2800lib.c:7908:
+		udelay(50);

WARNING: Unnecessary space before function pointer arguments
#99: FILE: drivers/net/wireless/ralink/rt2x00/rt2x00.h:576:
+	void (*rxdcoc_calibration) (struct rt2x00_dev *rt2x00dev);

ERROR: Missing Signed-off-by: line(s)

total: 2 errors, 1 warnings, 2 checks, 92 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

984-rt2x00-add-rxdcoc-calibration.patch has style problems, please review.

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


/* AGC init */
- if (rt2x00_rt(rt2x00dev, RT6352))
- reg = 0x04;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All vendor drivers I've seen got

R66 = 0x04 + 2 * GET_LNA_GAIN(pAd);

hence I doubt reverting to 0x1c instead of 0x04 is actually correct. However, if it actually measurably improves anything, I'm fine with giving it a spin.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

take a look at RT6352_VGA_TABLE in cmm_rf_cal.c ! there is no power entry for 0x04 value causing chip to stuck at very low throughput. mtk driver maybe writes this reg on-the-fly in STA mode

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RT6352_VGA_TABLE in cmm_rf_cal.c isn't actually used anywhere, apart from some traces in debug messages inside DPD calibration which isn't implemented in rt2x00...

And while it's true that RT6352_ChipAGCAdjust got an #ifdef CONFIG_STA_SUPPORT around it which hints that it's only being used in STA mode, there is also RT6352_RTMPSetAGCInitValue which sets register 66 in the way described above independently of the mode of operation.

My guess is that 0x04 is fine for ePA and works for iPA as well if we do DPD calibration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in rtmp_init_inf DPD is done before RT6352_Init_ExtPA_ExtLNA. with rt2x00 LNA is always on, can't even turn it off passing 0 to TX_PIN_CFG_LNA_PE_G0_EN or TX_PIN_CFG_LNA_PE_G1_EN. calibration as such does not help, but i'm also missing a piece of code from RtmpKickOutHwNullFrame. do you know is there an equivalent in rt2x00 that would transmit a packet?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

managed to run it with R66 0x04 without regression.and without improvement too so best to revert this reg and focus on other things

@@ -0,0 +1,89 @@
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create kernel patches like this 982-rt2x00-add-rf-self-txdc-calibration.patch file using git format-patch --to linux-wireless@vger.kernel.org --cc "Stanislaw Gruszka <sgruszka@redhat.com>" --cc "Kalle Valo <kvalo@codeaurora.org>" with commits on top of the wireless-drivers-next tree so they end up in the right patchwork. (your current patches should apply on that tree just fine)
Each commit should include a meaningful patch description starting with the rt2x00: prefix and your Signed-of-by: tag so they are fit for upstream submission. A basic description like the ones you wrote for the commits adding the patches to OpenWrt is fine, just also make sure to mention that this is for MT7620/RT6352 WiSoC in each patch description.

+ u8 r_cal_code = 0;
+ char d1 = 0, d2 = 0;
+ u8 rfvalue;
+ u32 MAC_RF_BYPASS0, MAC_RF_CONTROL0, MAC_PWR_PIN_CFG;
Copy link
Member

@dangowrt dangowrt Jan 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kernel style prohibits all-capital variable names. please change this and ideally use scripts/check-patch.pl to fix style issues prior to submission.

@dangowrt
Copy link
Member

Thanks for the great work! Just a few remaining style issues and this is ready to be included and submitted upstream.
As you mention 78720c8

With old openwrt builds this gets us ~8Mbps more of RX bandwidth (test with iPA/eLNA layout).

Which build did you test it with?

@psyborg55
Copy link
Contributor Author

Thanks for the great work! Just a few remaining style issues and this is ready to be included and submitted upstream.

besides code-style issues that i haven't checked for could you take a closer look at code that differentiates between chains, variables like chain or ch_idx? i'd like to use rt2x00 code for this but not sure which of the two would be correct to use ant->tx_chain_num or default_ant.tx_chain_num

Which build did you test it with?

CC, OpenWrt from archived branch with kernel 4.4

+
+ return root;
+}
+EXPORT_SYMBOL_GPL(rt2800_do_sqrt_accumulation);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You declare rt2800_do_sqrt_accumulation as static above which contradicts the export. Besides that, what would be the external user of that function?

+}
+EXPORT_SYMBOL_GPL(rt2800_do_sqrt_accumulation);
+
+void rt2800_rxiq_calibration(struct rt2x00_dev *rt2x00dev) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be static void ... as well?

+ rt2800_register_write(rt2x00dev, RF_BYPASS3, orig_RF_BYPASS3);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl);
+}
+EXPORT_SYMBOL_GPL(rt2800_rxiq_calibration);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no users of this function outside of this very file. No need to export it.

int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2);
void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev);
void rt2800_rxdcoc_calibration(struct rt2x00_dev *rt2x00dev);
+void rt2800_rxiq_calibration(struct rt2x00_dev *rt2x00dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to define it here. If you are calling the function before defining it in rt2800lib.c, just include the protoype in rt2800lib.c or move the function above the call within the file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tried to keep functions in the same order as with mtk driver, so i kept this one.

int (*calcrcalibrationcode) (struct rt2x00_dev *rt2x00dev, int d1, int d2);
void (*r_calibration) (struct rt2x00_dev *rt2x00dev);
void (*rxdcoc_calibration) (struct rt2x00_dev *rt2x00dev);
+ void (*rxiq_calibration) (struct rt2x00_dev *rt2x00dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to define it here (there is no call to the function using that function pointer)

}
EXPORT_SYMBOL_GPL(rt2800_r_calibration);

+void rt2800_rxdcoc_calibration(struct rt2x00_dev *rt2x00dev)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static void ...

+
+ rt2800_rfcsr_write_bank(rt2x00dev, 0, 2, saverfb0r2);
+}
+EXPORT_SYMBOL_GPL(rt2800_rxdcoc_calibration);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to export it if it's only being called below in rt2800_init_rfcsr_6352

void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev);
int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2);
void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev);
+void rt2800_rxdcoc_calibration(struct rt2x00_dev *rt2x00dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to define it here

void (*rf_self_txdc_cal) (struct rt2x00_dev *rt2x00dev);
int (*calcrcalibrationcode) (struct rt2x00_dev *rt2x00dev, int d1, int d2);
void (*r_calibration) (struct rt2x00_dev *rt2x00dev);
+ void (*rxdcoc_calibration) (struct rt2x00_dev *rt2x00dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nor here

}
EXPORT_SYMBOL_GPL(rt2800_rf_self_txdc_cal);

+int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static int ...

+
+ return calcode;
+}
+EXPORT_SYMBOL_GPL(rt2800_calcrcalibrationcode);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no export needed

+}
+EXPORT_SYMBOL_GPL(rt2800_calcrcalibrationcode);
+
+void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static void ...

+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, savemacsysctrl);
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, MAC_PWR_PIN_CFG);
+}
+EXPORT_SYMBOL_GPL(rt2800_r_calibration);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No export needed

void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev);
void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev);
void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev);
+int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need

void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev);
void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev);
+int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2);
+void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nor this

void (*vco_calibration) (struct rt2x00_dev *rt2x00dev);
void (*rf_self_txdc_cal) (struct rt2x00_dev *rt2x00dev);
+ int (*calcrcalibrationcode) (struct rt2x00_dev *rt2x00dev, int d1, int d2);
+ void (*r_calibration) (struct rt2x00_dev *rt2x00dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both above lines are unneeded (both functions are only being called within rt2800lib.c and only needed for that specific chip)

Copy link
Contributor Author

@psyborg55 psyborg55 Jan 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. so linking this code to rt2x00lib_ops in rt2800soc wouldn't help any? i ask beacuse i see all functions listed in the ops sections of soc/usb/pci

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is only needed for functions which have different implementations for different ralink chips and/or bus-access schemes. different driver code can then use the function pointers to call out to a chip-specific routine. calcrcalibration is only used inside of rt2800lib.c and doesn't any callers outside of it (should it?), the same applies to r_calibration. In case those functions should have any other callers (like reoccurently being called by a mac80211 tasklet or such) the situation may be different...

rt2800_led_open_drain_enable(rt2x00dev);
}

+void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static void ...

+ rt2x00_info(rt2x00dev, "RF Tx self calibration end\n");
+
+}
+EXPORT_SYMBOL_GPL(rt2800_rf_self_txdc_cal);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to export

const u32 count);
void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev);
void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev);
+void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unneeded

struct link_qual *qual, const u32 count);
void (*gain_calibration) (struct rt2x00_dev *rt2x00dev);
void (*vco_calibration) (struct rt2x00_dev *rt2x00dev);
+ void (*rf_self_txdc_cal) (struct rt2x00_dev *rt2x00dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here as well

+
+ return;
+}
+EXPORT_SYMBOL_GPL(rt2800_rf_configstore);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no export needed

+
+ return;
+}
+EXPORT_SYMBOL_GPL(rt2800_rf_configrecover);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to export

+
+ return;
+}
+EXPORT_SYMBOL_GPL(rt2800_setbbptonegenerator);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here too

+}
+EXPORT_SYMBOL_GPL(rt2800_setbbptonegenerator);
+
+u32 rt2800_do_fft_accumulation(struct rt2x00_dev *rt2x00dev, u8 tidx, u8 read_neg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static u32 ...

+
+ return pint;
+}
+EXPORT_SYMBOL_GPL(rt2800_do_fft_accumulation);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no export needed

+}
+EXPORT_SYMBOL_GPL(rt2800_do_fft_accumulation);
+
+u32 rt2800_read_fft_accumulation(struct rt2x00_dev *rt2x00dev, u8 tidx) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static u32 ...

+
+ return pint;
+}
+EXPORT_SYMBOL_GPL(rt2800_read_fft_accumulation);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no export

+
+ return;
+}
+EXPORT_SYMBOL_GPL(rt2800_write_dc);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no export

+
+ return;
+}
+EXPORT_SYMBOL_GPL(rt2800_loft_search);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no export

+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 19, 0xa2);
+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 20, 0x20);
+}
+EXPORT_SYMBOL_GPL(rt2800_rf_aux_tx0_loopback);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no export needed

+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 19, 0xa2);
+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 20, 0x20);
+}
+EXPORT_SYMBOL_GPL(rt2800_rf_aux_tx1_loopback);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no export

+}
+EXPORT_SYMBOL_GPL(rt2800_rf_aux_tx1_loopback);
+
+void rt2800_loft_iq_calibration(struct rt2x00_dev *rt2x00dev)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static void ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes no difference, builds just the same as without static declaration..

+
+ return;
+}
+EXPORT_SYMBOL_GPL(rt2800_loft_iq_calibration);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no export needed

+#define CHAIN_0 0x0
+#define CHAIN_1 0x1
+#define RF_ALC_NUM 6
+#define CHAIN_NUM 2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is specific for RT6252, we should get the number of (active) chains from driver runtime in rt2x00.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think it matters as long as there is no way to properly disable unused chain in b/g mode

void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev);
void rt2800_rxdcoc_calibration(struct rt2x00_dev *rt2x00dev);
void rt2800_rxiq_calibration(struct rt2x00_dev *rt2x00dev);
+void rt2800_loft_iq_calibration(struct rt2x00_dev *rt2x00dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needed? (ie. called form anywhere outside of rt2800lib.c?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has to be here

void (*r_calibration) (struct rt2x00_dev *rt2x00dev);
void (*rxdcoc_calibration) (struct rt2x00_dev *rt2x00dev);
void (*rxiq_calibration) (struct rt2x00_dev *rt2x00dev);
+ void (*loft_iq_calibration) (struct rt2x00_dev *rt2x00dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed? (ie. needs per-chip-type abstraction? imho this is only relevant for MT7620/RT6352 which is always rt2800mmio)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no. calibration will run without this. with doubts in it's efficiency.

@dangowrt
Copy link
Member

Are you still going to update this PR?
It'd be nice to move forward with this and also add TSSI as well as DPD to complete the set of RF calibration routines needed and finally end up with the expected TX-power values...

@dangowrt
Copy link
Member

dangowrt commented Jan 26, 2018

Sure, take your time, I just wanted to avoid redundant work on the same issue.
Regarding our ability to judge the necessity of certain calibration routines: Making such a judgment will require long-term testing in diverse environments (in terms of RF noise, temperature, number and type of stations, ...). It's already hard to argue for upstream inclusion of code which cannot be verified (due to lacking hardware description) in other ways than comparing it to the vendor implementation. Hence I believe the best would be to first of all really do exactly what the vendor driver does and then optimize on top of that later on (if needed).

About the binary: I don't own that hardware (miwifi mini), unfortunately. Can you make a build for either ZBT-WE1026 (iLNA/iPA) or Phicomm PSG1218B (eLNA,ePA )and share that instead?

@psyborg55 psyborg55 closed this Oct 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core packages pull request/issue for core (in-tree) packages kernel pull request/issue with Linux kernel related changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants