On Wed, Apr 15, 2020 at 5:59 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> > --- > drivers/net/wireless/realtek/rtw88/efuse.c | 21 ++++ > drivers/net/wireless/realtek/rtw88/efuse.h | 3 + > drivers/net/wireless/realtek/rtw88/rtw8822c.c | 111 ++++++++++++++++++ > drivers/net/wireless/realtek/rtw88/rtw8822c.h | 28 +++++ > 4 files changed, 163 insertions(+) > > diff --git a/drivers/net/wireless/realtek/rtw88/efuse.c b/drivers/net/wireless/realtek/rtw88/efuse.c > index 212c8376a8c9..f037fa586915 100644 > --- a/drivers/net/wireless/realtek/rtw88/efuse.c > +++ b/drivers/net/wireless/realtek/rtw88/efuse.c > @@ -116,6 +116,27 @@ 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, cnt; > + > + rtw_write32_mask(rtwdev, REG_EFUSE_CTRL, 0x3ff00, addr); > + rtw_write32_clr(rtwdev, REG_EFUSE_CTRL, BIT_EF_FLAG); > + cnt = 1000; > + do { > + mdelay(1); > + efuse_ctl = rtw_read32(rtwdev, REG_EFUSE_CTRL); > + if (--cnt == 0) { > + *data = EFUSE_READ_FAIL; > + return -EBUSY; > + } > + } while (!(efuse_ctl & BIT_EF_FLAG)); I believe this can be replaced by read_poll_timeout(). The rest of the patch looks OK to me. > + > + *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; > +} > + > +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); > +} > + > +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); > } > > 2.17.1 >