Skip to content

Commit af0cac1

Browse files
Ping-Ke ShihKalle Valo
authored andcommitted
rtw89: 8852c: implement chip_ops related to TX power
Three chip_ops are implemented in this patch. The ::set_txpwr_ctrl and ::init_txpwr_unit are called when we up interface and then configure TX power registers to initial values. The ::set_txpwr_ctrl is to configure 'txpwr_ref' to make basic output TX power of OFDM and CCK rate to be the same. The ::init_txpwr_unit is to initialize TSSI (a method to do TX power compensation depends on thermal value) control and bandedge. The ::set_txpwr is called once switching channel. First, it sets TX power for each rate section (e.g. CCK, OFDM), and then sets TX power offset between 1SS and 2SS rate. Finally, it sets TX power limit to prevent power over regulation. Signed-off-by: Ping-Ke Shih <[email protected]> Signed-off-by: Kalle Valo <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent cd89a47 commit af0cac1

File tree

2 files changed

+325
-0
lines changed

2 files changed

+325
-0
lines changed

drivers/net/wireless/realtek/rtw89/rtw8852c.c

Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,6 +1778,32 @@ static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev)
17781778
rtw89_fw_h2c_rf_ntfy_mcc(rtwdev);
17791779
}
17801780

1781+
static u32 rtw8852c_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev,
1782+
enum rtw89_phy_idx phy_idx, s16 ref)
1783+
{
1784+
s8 ofst_int = 0;
1785+
u8 base_cw_0db = 0x27;
1786+
u16 tssi_16dbm_cw = 0x12c;
1787+
s16 pwr_s10_3 = 0;
1788+
s16 rf_pwr_cw = 0;
1789+
u16 bb_pwr_cw = 0;
1790+
u32 pwr_cw = 0;
1791+
u32 tssi_ofst_cw = 0;
1792+
1793+
pwr_s10_3 = (ref << 1) + (s16)(ofst_int) + (s16)(base_cw_0db << 3);
1794+
bb_pwr_cw = FIELD_GET(GENMASK(2, 0), pwr_s10_3);
1795+
rf_pwr_cw = FIELD_GET(GENMASK(8, 3), pwr_s10_3);
1796+
rf_pwr_cw = clamp_t(s16, rf_pwr_cw, 15, 63);
1797+
pwr_cw = (rf_pwr_cw << 3) | bb_pwr_cw;
1798+
1799+
tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3));
1800+
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
1801+
"[TXPWR] tssi_ofst_cw=%d rf_cw=0x%x bb_cw=0x%x\n",
1802+
tssi_ofst_cw, rf_pwr_cw, bb_pwr_cw);
1803+
1804+
return (tssi_ofst_cw << 18) | (pwr_cw << 9) | (ref & GENMASK(8, 0));
1805+
}
1806+
17811807
static
17821808
void rtw8852c_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
17831809
s8 pw_ofst, enum rtw89_mac_idx mac_idx)
@@ -1813,6 +1839,301 @@ void rtw8852c_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
18131839
}
18141840
}
18151841

1842+
static void rtw8852c_set_txpwr_ref(struct rtw89_dev *rtwdev,
1843+
enum rtw89_phy_idx phy_idx)
1844+
{
1845+
static const u32 addr[RF_PATH_NUM_8852C] = {0x5800, 0x7800};
1846+
const u32 mask = 0x7FFFFFF;
1847+
const u8 ofst_ofdm = 0x4;
1848+
const u8 ofst_cck = 0x8;
1849+
s16 ref_ofdm = 0;
1850+
s16 ref_cck = 0;
1851+
u32 val;
1852+
u8 i;
1853+
1854+
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr reference\n");
1855+
1856+
rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_CTRL,
1857+
GENMASK(27, 10), 0x0);
1858+
1859+
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n");
1860+
val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm);
1861+
1862+
for (i = 0; i < RF_PATH_NUM_8852C; i++)
1863+
rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val,
1864+
phy_idx);
1865+
1866+
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb cck txpwr ref\n");
1867+
val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck);
1868+
1869+
for (i = 0; i < RF_PATH_NUM_8852C; i++)
1870+
rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val,
1871+
phy_idx);
1872+
}
1873+
1874+
static void rtw8852c_set_txpwr_byrate(struct rtw89_dev *rtwdev,
1875+
enum rtw89_phy_idx phy_idx)
1876+
{
1877+
u8 ch = rtwdev->hal.current_channel;
1878+
static const u8 rs[] = {
1879+
RTW89_RS_CCK,
1880+
RTW89_RS_OFDM,
1881+
RTW89_RS_MCS,
1882+
RTW89_RS_HEDCM,
1883+
};
1884+
s8 tmp;
1885+
u8 i, j;
1886+
u32 val, shf, addr = R_AX_PWR_BY_RATE;
1887+
struct rtw89_rate_desc cur;
1888+
1889+
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
1890+
"[TXPWR] set txpwr byrate with ch=%d\n", ch);
1891+
1892+
for (cur.nss = 0; cur.nss <= RTW89_NSS_2; cur.nss++) {
1893+
for (i = 0; i < ARRAY_SIZE(rs); i++) {
1894+
if (cur.nss >= rtw89_rs_nss_max[rs[i]])
1895+
continue;
1896+
1897+
val = 0;
1898+
cur.rs = rs[i];
1899+
1900+
for (j = 0; j < rtw89_rs_idx_max[rs[i]]; j++) {
1901+
cur.idx = j;
1902+
shf = (j % 4) * 8;
1903+
tmp = rtw89_phy_read_txpwr_byrate(rtwdev, &cur);
1904+
val |= (tmp << shf);
1905+
1906+
if ((j + 1) % 4)
1907+
continue;
1908+
1909+
rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
1910+
val = 0;
1911+
addr += 4;
1912+
}
1913+
}
1914+
}
1915+
}
1916+
1917+
static void rtw8852c_set_txpwr_offset(struct rtw89_dev *rtwdev,
1918+
enum rtw89_phy_idx phy_idx)
1919+
{
1920+
struct rtw89_rate_desc desc = {
1921+
.nss = RTW89_NSS_1,
1922+
.rs = RTW89_RS_OFFSET,
1923+
};
1924+
u32 val = 0;
1925+
s8 v;
1926+
1927+
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr offset\n");
1928+
1929+
for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_MAX; desc.idx++) {
1930+
v = rtw89_phy_read_txpwr_byrate(rtwdev, &desc);
1931+
val |= ((v & 0xf) << (4 * desc.idx));
1932+
}
1933+
1934+
rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_OFST_CTRL,
1935+
GENMASK(19, 0), val);
1936+
}
1937+
1938+
static void rtw8852c_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev,
1939+
u8 tx_shape_idx,
1940+
enum rtw89_phy_idx phy_idx)
1941+
{
1942+
#define __DFIR_CFG_MASK 0xffffff
1943+
#define __DFIR_CFG_NR 8
1944+
#define __DECL_DFIR_VAR(_prefix, _name, _val...) \
1945+
static const u32 _prefix ## _ ## _name[] = {_val}; \
1946+
static_assert(ARRAY_SIZE(_prefix ## _ ## _name) == __DFIR_CFG_NR)
1947+
#define __DECL_DFIR_PARAM(_name, _val...) __DECL_DFIR_VAR(param, _name, _val)
1948+
#define __DECL_DFIR_ADDR(_name, _val...) __DECL_DFIR_VAR(addr, _name, _val)
1949+
1950+
__DECL_DFIR_PARAM(flat,
1951+
0x003D23FF, 0x0029B354, 0x000FC1C8, 0x00FDB053,
1952+
0x00F86F9A, 0x00FAEF92, 0x00FE5FCC, 0x00FFDFF5);
1953+
__DECL_DFIR_PARAM(sharp,
1954+
0x003D83FF, 0x002C636A, 0x0013F204, 0x00008090,
1955+
0x00F87FB0, 0x00F99F83, 0x00FDBFBA, 0x00003FF5);
1956+
__DECL_DFIR_PARAM(sharp_14,
1957+
0x003B13FF, 0x001C42DE, 0x00FDB0AD, 0x00F60F6E,
1958+
0x00FD8F92, 0x0002D011, 0x0001C02C, 0x00FFF00A);
1959+
__DECL_DFIR_ADDR(filter,
1960+
0x45BC, 0x45CC, 0x45D0, 0x45D4, 0x45D8, 0x45C0,
1961+
0x45C4, 0x45C8);
1962+
u8 ch = rtwdev->hal.current_channel;
1963+
const u32 *param;
1964+
int i;
1965+
1966+
if (ch > 14) {
1967+
rtw89_warn(rtwdev,
1968+
"set tx shape dfir by unknown ch: %d on 2G\n", ch);
1969+
return;
1970+
}
1971+
1972+
if (ch == 14)
1973+
param = param_sharp_14;
1974+
else
1975+
param = tx_shape_idx == 0 ? param_flat : param_sharp;
1976+
1977+
for (i = 0; i < __DFIR_CFG_NR; i++) {
1978+
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
1979+
"set tx shape dfir: 0x%x: 0x%x\n", addr_filter[i],
1980+
param[i]);
1981+
rtw89_phy_write32_idx(rtwdev, addr_filter[i], __DFIR_CFG_MASK,
1982+
param[i], phy_idx);
1983+
}
1984+
1985+
#undef __DECL_DFIR_ADDR
1986+
#undef __DECL_DFIR_PARAM
1987+
#undef __DECL_DFIR_VAR
1988+
#undef __DFIR_CFG_NR
1989+
#undef __DFIR_CFG_MASK
1990+
}
1991+
1992+
static void rtw8852c_set_tx_shape(struct rtw89_dev *rtwdev,
1993+
enum rtw89_phy_idx phy_idx)
1994+
{
1995+
u8 band = rtwdev->hal.current_band_type;
1996+
u8 regd = rtw89_regd_get(rtwdev, band);
1997+
u8 tx_shape_cck = rtw89_8852c_tx_shape[band][RTW89_RS_CCK][regd];
1998+
u8 tx_shape_ofdm = rtw89_8852c_tx_shape[band][RTW89_RS_OFDM][regd];
1999+
2000+
if (band == RTW89_BAND_2G)
2001+
rtw8852c_bb_set_tx_shape_dfir(rtwdev, tx_shape_cck, phy_idx);
2002+
2003+
rtw89_phy_tssi_ctrl_set_bandedge_cfg(rtwdev,
2004+
(enum rtw89_mac_idx)phy_idx,
2005+
tx_shape_ofdm);
2006+
}
2007+
2008+
static void rtw8852c_set_txpwr_limit(struct rtw89_dev *rtwdev,
2009+
enum rtw89_phy_idx phy_idx)
2010+
{
2011+
#define __MAC_TXPWR_LMT_PAGE_SIZE 40
2012+
u8 ch = rtwdev->hal.current_channel;
2013+
u8 bw = rtwdev->hal.current_band_width;
2014+
struct rtw89_txpwr_limit lmt[NTX_NUM_8852C];
2015+
u32 addr, val;
2016+
const s8 *ptr;
2017+
u8 i, j, k;
2018+
2019+
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
2020+
"[TXPWR] set txpwr limit with ch=%d bw=%d\n", ch, bw);
2021+
2022+
for (i = 0; i < NTX_NUM_8852C; i++) {
2023+
rtw89_phy_fill_txpwr_limit(rtwdev, &lmt[i], i);
2024+
2025+
for (j = 0; j < __MAC_TXPWR_LMT_PAGE_SIZE; j += 4) {
2026+
addr = R_AX_PWR_LMT + j + __MAC_TXPWR_LMT_PAGE_SIZE * i;
2027+
ptr = (s8 *)&lmt[i] + j;
2028+
val = 0;
2029+
2030+
for (k = 0; k < 4; k++)
2031+
val |= (ptr[k] << (8 * k));
2032+
2033+
rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
2034+
}
2035+
}
2036+
#undef __MAC_TXPWR_LMT_PAGE_SIZE
2037+
}
2038+
2039+
static void rtw8852c_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
2040+
enum rtw89_phy_idx phy_idx)
2041+
{
2042+
#define __MAC_TXPWR_LMT_RU_PAGE_SIZE 24
2043+
u8 ch = rtwdev->hal.current_channel;
2044+
u8 bw = rtwdev->hal.current_band_width;
2045+
struct rtw89_txpwr_limit_ru lmt_ru[NTX_NUM_8852C];
2046+
u32 addr, val;
2047+
const s8 *ptr;
2048+
u8 i, j, k;
2049+
2050+
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
2051+
"[TXPWR] set txpwr limit ru with ch=%d bw=%d\n", ch, bw);
2052+
2053+
for (i = 0; i < NTX_NUM_8852C; i++) {
2054+
rtw89_phy_fill_txpwr_limit_ru(rtwdev, &lmt_ru[i], i);
2055+
2056+
for (j = 0; j < __MAC_TXPWR_LMT_RU_PAGE_SIZE; j += 4) {
2057+
addr = R_AX_PWR_RU_LMT + j +
2058+
__MAC_TXPWR_LMT_RU_PAGE_SIZE * i;
2059+
ptr = (s8 *)&lmt_ru[i] + j;
2060+
val = 0;
2061+
2062+
for (k = 0; k < 4; k++)
2063+
val |= (ptr[k] << (8 * k));
2064+
2065+
rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
2066+
}
2067+
}
2068+
2069+
#undef __MAC_TXPWR_LMT_RU_PAGE_SIZE
2070+
}
2071+
2072+
static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev)
2073+
{
2074+
rtw8852c_set_txpwr_byrate(rtwdev, RTW89_PHY_0);
2075+
rtw8852c_set_txpwr_offset(rtwdev, RTW89_PHY_0);
2076+
rtw8852c_set_tx_shape(rtwdev, RTW89_PHY_0);
2077+
rtw8852c_set_txpwr_limit(rtwdev, RTW89_PHY_0);
2078+
rtw8852c_set_txpwr_limit_ru(rtwdev, RTW89_PHY_0);
2079+
}
2080+
2081+
static void rtw8852c_set_txpwr_ctrl(struct rtw89_dev *rtwdev)
2082+
{
2083+
rtw8852c_set_txpwr_ref(rtwdev, RTW89_PHY_0);
2084+
}
2085+
2086+
static void
2087+
rtw8852c_init_tssi_ctrl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
2088+
{
2089+
static const struct rtw89_reg2_def ctrl_ini[] = {
2090+
{0xD938, 0x00010100},
2091+
{0xD93C, 0x0500D500},
2092+
{0xD940, 0x00000500},
2093+
{0xD944, 0x00000005},
2094+
{0xD94C, 0x00220000},
2095+
{0xD950, 0x00030000},
2096+
};
2097+
u32 addr;
2098+
int i;
2099+
2100+
for (addr = R_AX_TSSI_CTRL_HEAD; addr <= R_AX_TSSI_CTRL_TAIL; addr += 4)
2101+
rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, 0);
2102+
2103+
for (i = 0; i < ARRAY_SIZE(ctrl_ini); i++)
2104+
rtw89_mac_txpwr_write32(rtwdev, phy_idx, ctrl_ini[i].addr,
2105+
ctrl_ini[i].data);
2106+
2107+
rtw89_phy_tssi_ctrl_set_bandedge_cfg(rtwdev,
2108+
(enum rtw89_mac_idx)phy_idx,
2109+
RTW89_TSSI_BANDEDGE_FLAT);
2110+
}
2111+
2112+
static int
2113+
rtw8852c_init_txpwr_unit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
2114+
{
2115+
int ret;
2116+
2117+
ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_UL_CTRL2, 0x07763333);
2118+
if (ret)
2119+
return ret;
2120+
2121+
ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_COEXT_CTRL, 0x01ebf000);
2122+
if (ret)
2123+
return ret;
2124+
2125+
ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_UL_CTRL0, 0x0002f8ff);
2126+
if (ret)
2127+
return ret;
2128+
2129+
rtw8852c_set_txpwr_ul_tb_offset(rtwdev, 0, phy_idx == RTW89_PHY_1 ?
2130+
RTW89_MAC_1 :
2131+
RTW89_MAC_0);
2132+
rtw8852c_init_tssi_ctrl(rtwdev, phy_idx);
2133+
2134+
return 0;
2135+
}
2136+
18162137
static void rtw8852c_bb_cfg_rx_path(struct rtw89_dev *rtwdev, u8 rx_path)
18172138
{
18182139
struct rtw89_hal *hal = &rtwdev->hal;
@@ -2163,6 +2484,9 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
21632484
.rfk_init = rtw8852c_rfk_init,
21642485
.rfk_channel = rtw8852c_rfk_channel,
21652486
.power_trim = rtw8852c_power_trim,
2487+
.set_txpwr = rtw8852c_set_txpwr,
2488+
.set_txpwr_ctrl = rtw8852c_set_txpwr_ctrl,
2489+
.init_txpwr_unit = rtw8852c_init_txpwr_unit,
21662490
.read_rf = rtw89_phy_read_rf_v1,
21672491
.write_rf = rtw89_phy_write_rf_v1,
21682492
.set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset,

drivers/net/wireless/realtek/rtw89/rtw8852c.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#define RF_PATH_NUM_8852C 2
1111
#define BB_PATH_NUM_8852C 2
12+
#define NTX_NUM_8852C 2
1213

1314
struct rtw8852c_u_efuse {
1415
u8 rsvd[0x38];

0 commit comments

Comments
 (0)