On Fri, Apr 17, 2020 at 2:28 PM <yhchuang@xxxxxxxxxxx> wrote: > > From: Tzu-En Huang <tehuang@xxxxxxxxxxx> > > 8822C devices have power trim, thermal and PA bias values > programmed in efuse. Driver should configure the RF components > according to the values. > > If the power trim is not configured, then the devices might have > distortion on the output tx power. > > Signed-off-by: Tzu-En Huang <tehuang@xxxxxxxxxxx> > Signed-off-by: Yan-Hsuan Chuang <yhchuang@xxxxxxxxxxx> > --- Reviewed-by: Chris Chiu <chiu@xxxxxxxxxxxx> > > v1 -> v2 > * disable DPD low rates > > v2 -> v3 > * use read_poll_timeout() > > drivers/net/wireless/realtek/rtw88/efuse.c | 20 ++++ > drivers/net/wireless/realtek/rtw88/efuse.h | 3 + > drivers/net/wireless/realtek/rtw88/rtw8822c.c | 113 ++++++++++++++++++ > drivers/net/wireless/realtek/rtw88/rtw8822c.h | 28 +++++ > 4 files changed, 164 insertions(+) > > diff --git a/drivers/net/wireless/realtek/rtw88/efuse.c b/drivers/net/wireless/realtek/rtw88/efuse.c > index 212c8376a8c9..54b01360a9b8 100644 > --- a/drivers/net/wireless/realtek/rtw88/efuse.c > +++ b/drivers/net/wireless/realtek/rtw88/efuse.c > @@ -116,6 +116,26 @@ static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map) > return 0; > } > > +int rtw_read8_physical_efuse(struct rtw_dev *rtwdev, u16 addr, u8 *data) > +{ > + u32 efuse_ctl; > + int ret; > + > + rtw_write32_mask(rtwdev, REG_EFUSE_CTRL, 0x3ff00, addr); > + rtw_write32_clr(rtwdev, REG_EFUSE_CTRL, BIT_EF_FLAG); > + > + ret = read_poll_timeout(rtw_read32, efuse_ctl, efuse_ctl & BIT_EF_FLAG, > + 1000, 100000, false, rtwdev, REG_EFUSE_CTRL); > + if (ret) { > + *data = EFUSE_READ_FAIL; > + return ret; > + } > + > + *data = rtw_read8(rtwdev, REG_EFUSE_CTRL); > + > + return 0; > +} > + > int rtw_parse_efuse_map(struct rtw_dev *rtwdev) > { > struct rtw_chip_info *chip = rtwdev->chip; > diff --git a/drivers/net/wireless/realtek/rtw88/efuse.h b/drivers/net/wireless/realtek/rtw88/efuse.h > index 115bbe85946a..97a51f0b0e46 100644 > --- a/drivers/net/wireless/realtek/rtw88/efuse.h > +++ b/drivers/net/wireless/realtek/rtw88/efuse.h > @@ -10,6 +10,8 @@ > #define EFUSE_HW_CAP_SUPP_BW80 7 > #define EFUSE_HW_CAP_SUPP_BW40 6 > > +#define EFUSE_READ_FAIL 0xff > + > #define GET_EFUSE_HW_CAP_HCI(hw_cap) \ > le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(3, 0)) > #define GET_EFUSE_HW_CAP_BW(hw_cap) \ > @@ -22,5 +24,6 @@ > le32_get_bits(*((__le32 *)(hw_cap) + 0x01), GENMASK(27, 26)) > > int rtw_parse_efuse_map(struct rtw_dev *rtwdev); > +int rtw_read8_physical_efuse(struct rtw_dev *rtwdev, u16 addr, u8 *data); > > #endif > diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c > index c99b1de54bfc..ee0d39135617 100644 > --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c > +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c > @@ -15,6 +15,7 @@ > #include "debug.h" > #include "util.h" > #include "bf.h" > +#include "efuse.h" > > static void rtw8822c_config_trx_mode(struct rtw_dev *rtwdev, u8 tx_path, > u8 rx_path, bool is_tx2_path); > @@ -1000,10 +1001,122 @@ static void rtw8822c_rf_x2_check(struct rtw_dev *rtwdev) > } > } > > +static void rtw8822c_set_power_trim(struct rtw_dev *rtwdev, s8 bb_gain[2][8]) > +{ > +#define RF_SET_POWER_TRIM(_path, _seq, _idx) \ > + do { \ > + rtw_write_rf(rtwdev, _path, 0x33, RFREG_MASK, _seq); \ > + rtw_write_rf(rtwdev, _path, 0x3f, RFREG_MASK, \ > + bb_gain[_path][_idx]); \ > + } while (0) > + u8 path; > + > + for (path = 0; path < rtwdev->hal.rf_path_num; path++) { > + rtw_write_rf(rtwdev, path, 0xee, BIT(19), 1); > + RF_SET_POWER_TRIM(path, 0x0, 0); > + RF_SET_POWER_TRIM(path, 0x1, 1); > + RF_SET_POWER_TRIM(path, 0x2, 2); > + RF_SET_POWER_TRIM(path, 0x3, 2); > + RF_SET_POWER_TRIM(path, 0x4, 3); > + RF_SET_POWER_TRIM(path, 0x5, 4); > + RF_SET_POWER_TRIM(path, 0x6, 5); > + RF_SET_POWER_TRIM(path, 0x7, 6); > + RF_SET_POWER_TRIM(path, 0x8, 7); > + RF_SET_POWER_TRIM(path, 0x9, 3); > + RF_SET_POWER_TRIM(path, 0xa, 4); > + RF_SET_POWER_TRIM(path, 0xb, 5); > + RF_SET_POWER_TRIM(path, 0xc, 6); > + RF_SET_POWER_TRIM(path, 0xd, 7); > + RF_SET_POWER_TRIM(path, 0xe, 7); > + rtw_write_rf(rtwdev, path, 0xee, BIT(19), 0); > + } > +#undef RF_SET_POWER_TRIM > +} > + > +static void rtw8822c_power_trim(struct rtw_dev *rtwdev) > +{ > + u8 pg_pwr = 0xff, i, path, idx; > + s8 bb_gain[2][8] = {0}; > + u16 rf_efuse_2g[3] = {PPG_2GL_TXAB, PPG_2GM_TXAB, PPG_2GH_TXAB}; > + u16 rf_efuse_5g[2][5] = {{PPG_5GL1_TXA, PPG_5GL2_TXA, PPG_5GM1_TXA, > + PPG_5GM2_TXA, PPG_5GH1_TXA}, > + {PPG_5GL1_TXB, PPG_5GL2_TXB, PPG_5GM1_TXB, > + PPG_5GM2_TXB, PPG_5GH1_TXB} }; > + bool set = false; > + > + for (i = 0; i < ARRAY_SIZE(rf_efuse_2g); i++) { > + rtw_read8_physical_efuse(rtwdev, rf_efuse_2g[i], &pg_pwr); > + if (pg_pwr == EFUSE_READ_FAIL) > + continue; > + set = true; > + bb_gain[RF_PATH_A][i] = FIELD_GET(PPG_2G_A_MASK, pg_pwr); > + bb_gain[RF_PATH_B][i] = FIELD_GET(PPG_2G_B_MASK, pg_pwr); > + } > + > + for (i = 0; i < ARRAY_SIZE(rf_efuse_5g[0]); i++) { > + for (path = 0; path < rtwdev->hal.rf_path_num; path++) { > + rtw_read8_physical_efuse(rtwdev, rf_efuse_5g[path][i], > + &pg_pwr); > + if (pg_pwr == EFUSE_READ_FAIL) > + continue; > + set = true; > + idx = i + ARRAY_SIZE(rf_efuse_2g); > + bb_gain[path][idx] = FIELD_GET(PPG_5G_MASK, pg_pwr); > + } > + } > + if (set) > + rtw8822c_set_power_trim(rtwdev, bb_gain); > + > + rtw_write32_mask(rtwdev, REG_DIS_DPD, DIS_DPD_MASK, DIS_DPD_RATEALL); > +} > + > +static void rtw8822c_thermal_trim(struct rtw_dev *rtwdev) > +{ > + u16 rf_efuse[2] = {PPG_THERMAL_A, PPG_THERMAL_B}; > + u8 pg_therm = 0xff, thermal[2] = {0}, path; > + > + for (path = 0; path < rtwdev->hal.rf_path_num; path++) { > + rtw_read8_physical_efuse(rtwdev, rf_efuse[path], &pg_therm); > + if (pg_therm == EFUSE_READ_FAIL) > + return; > + /* Efuse value of BIT(0) shall be move to BIT(3), and the value > + * of BIT(1) to BIT(3) should be right shifted 1 bit. > + */ > + thermal[path] = FIELD_GET(GENMASK(3, 1), pg_therm); > + thermal[path] |= FIELD_PREP(BIT(3), pg_therm & BIT(0)); > + rtw_write_rf(rtwdev, path, 0x43, RF_THEMAL_MASK, thermal[path]); > + } > +} > + > +static void rtw8822c_pa_bias(struct rtw_dev *rtwdev) > +{ > + u16 rf_efuse_2g[2] = {PPG_PABIAS_2GA, PPG_PABIAS_2GB}; > + u16 rf_efuse_5g[2] = {PPG_PABIAS_5GA, PPG_PABIAS_5GB}; > + u8 pg_pa_bias = 0xff, path; > + > + for (path = 0; path < rtwdev->hal.rf_path_num; path++) { > + rtw_read8_physical_efuse(rtwdev, rf_efuse_2g[path], > + &pg_pa_bias); > + if (pg_pa_bias == EFUSE_READ_FAIL) > + return; > + pg_pa_bias = FIELD_GET(PPG_PABIAS_MASK, pg_pa_bias); > + rtw_write_rf(rtwdev, path, 0x60, RF_PABIAS_2G_MASK, pg_pa_bias); > + } > + for (path = 0; path < rtwdev->hal.rf_path_num; path++) { > + rtw_read8_physical_efuse(rtwdev, rf_efuse_5g[path], > + &pg_pa_bias); > + pg_pa_bias = FIELD_GET(PPG_PABIAS_MASK, pg_pa_bias); > + rtw_write_rf(rtwdev, path, 0x60, RF_PABIAS_5G_MASK, pg_pa_bias); > + } > +} > + > static void rtw8822c_rf_init(struct rtw_dev *rtwdev) > { > rtw8822c_rf_dac_cal(rtwdev); > rtw8822c_rf_x2_check(rtwdev); > + rtw8822c_thermal_trim(rtwdev); > + rtw8822c_power_trim(rtwdev); > + rtw8822c_pa_bias(rtwdev); > } > > static void rtw8822c_pwrtrack_init(struct rtw_dev *rtwdev) > diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.h b/drivers/net/wireless/realtek/rtw88/rtw8822c.h > index dfd8662a0c0e..32b4771e04d0 100644 > --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h > +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h > @@ -309,4 +309,32 @@ const struct rtw_table name ## _tbl = { \ > #define BIT_GS_PWSF GENMASK(27, 0) > #define BIT_RPT_DGAIN GENMASK(27, 16) > #define BIT_TX_CFIR GENMASK(31, 30) > + > +#define PPG_THERMAL_A 0x1ef > +#define PPG_THERMAL_B 0x1b0 > +#define RF_THEMAL_MASK GENMASK(19, 16) > +#define PPG_2GL_TXAB 0x1d4 > +#define PPG_2GM_TXAB 0x1ee > +#define PPG_2GH_TXAB 0x1d2 > +#define PPG_2G_A_MASK GENMASK(3, 0) > +#define PPG_2G_B_MASK GENMASK(7, 4) > +#define PPG_5GL1_TXA 0x1ec > +#define PPG_5GL2_TXA 0x1e8 > +#define PPG_5GM1_TXA 0x1e4 > +#define PPG_5GM2_TXA 0x1e0 > +#define PPG_5GH1_TXA 0x1dc > +#define PPG_5GL1_TXB 0x1eb > +#define PPG_5GL2_TXB 0x1e7 > +#define PPG_5GM1_TXB 0x1e3 > +#define PPG_5GM2_TXB 0x1df > +#define PPG_5GH1_TXB 0x1db > +#define PPG_5G_MASK GENMASK(4, 0) > +#define PPG_PABIAS_2GA 0x1d6 > +#define PPG_PABIAS_2GB 0x1d5 > +#define PPG_PABIAS_5GA 0x1d8 > +#define PPG_PABIAS_5GB 0x1d7 > +#define PPG_PABIAS_MASK GENMASK(3, 0) > +#define RF_PABIAS_2G_MASK GENMASK(15, 12) > +#define RF_PABIAS_5G_MASK GENMASK(19, 16) > + > #endif > -- > 2.17.1 >