mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 10:33:41 +02:00
wifi: rtw89: phy: initialize AFE by firmware element table
A power-on sequence table is introduced to initialize AFE (Analogue Front End) connecting to RF components. Build the sequence in firmware file, and use a parser to execute the sequences including write/poll/delay actions. Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Link: https://patch.msgid.link/20250915065314.38846-1-pkshih@realtek.com
This commit is contained in:
parent
e156d2ab36
commit
298f39f0d9
|
|
@ -5417,6 +5417,8 @@ int rtw89_core_start(struct rtw89_dev *rtwdev)
|
|||
{
|
||||
int ret;
|
||||
|
||||
rtw89_phy_init_bb_afe(rtwdev);
|
||||
|
||||
ret = rtw89_mac_init(rtwdev);
|
||||
if (ret) {
|
||||
rtw89_err(rtwdev, "mac init fail, ret:%d\n", ret);
|
||||
|
|
|
|||
|
|
@ -4690,6 +4690,7 @@ struct rtw89_fw_elm_info {
|
|||
struct rtw89_fw_txpwr_track_cfg *txpwr_trk;
|
||||
struct rtw89_phy_rfk_log_fmt *rfk_log_fmt;
|
||||
const struct rtw89_regd_data *regd;
|
||||
const struct rtw89_fw_element_hdr *afe;
|
||||
};
|
||||
|
||||
enum rtw89_fw_mss_dev_type {
|
||||
|
|
|
|||
|
|
@ -1285,6 +1285,18 @@ int rtw89_recognize_regd_from_elm(struct rtw89_dev *rtwdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int rtw89_build_afe_pwr_seq_from_elm(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_fw_element_hdr *elm,
|
||||
const union rtw89_fw_element_arg arg)
|
||||
{
|
||||
struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
|
||||
|
||||
elm_info->afe = elm;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
|
||||
[RTW89_FW_ELEMENT_ID_BBMCU0] = {__rtw89_fw_recognize_from_elm,
|
||||
{ .fw_type = RTW89_FW_BBMCU0 }, NULL},
|
||||
|
|
@ -1370,6 +1382,9 @@ static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
|
|||
[RTW89_FW_ELEMENT_ID_REGD] = {
|
||||
rtw89_recognize_regd_from_elm, {}, "REGD",
|
||||
},
|
||||
[RTW89_FW_ELEMENT_ID_AFE_PWR_SEQ] = {
|
||||
rtw89_build_afe_pwr_seq_from_elm, {}, "AFE",
|
||||
},
|
||||
};
|
||||
|
||||
int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev)
|
||||
|
|
|
|||
|
|
@ -3984,6 +3984,7 @@ enum rtw89_fw_element_id {
|
|||
RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_2GHZ = 24,
|
||||
RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_5GHZ = 25,
|
||||
RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_6GHZ = 26,
|
||||
RTW89_FW_ELEMENT_ID_AFE_PWR_SEQ = 27,
|
||||
|
||||
RTW89_FW_ELEMENT_ID_NUM,
|
||||
};
|
||||
|
|
@ -4089,6 +4090,30 @@ struct rtw89_fw_txpwr_track_cfg {
|
|||
BIT(RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_N) | \
|
||||
BIT(RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_P))
|
||||
|
||||
enum rtw89_fw_afe_action {
|
||||
RTW89_FW_AFE_ACTION_WRITE = 0,
|
||||
RTW89_FW_AFE_ACTION_DELAY = 1,
|
||||
RTW89_FW_AFE_ACTION_POLL = 2,
|
||||
};
|
||||
|
||||
enum rtw89_fw_afe_cat {
|
||||
RTW89_FW_AFE_CAT_BB = 0,
|
||||
RTW89_FW_AFE_CAT_BB1 = 1,
|
||||
RTW89_FW_AFE_CAT_MAC = 2,
|
||||
RTW89_FW_AFE_CAT_MAC1 = 3,
|
||||
RTW89_FW_AFE_CAT_AFEDIG = 4,
|
||||
RTW89_FW_AFE_CAT_AFEDIG1 = 5,
|
||||
};
|
||||
|
||||
enum rtw89_fw_afe_class {
|
||||
RTW89_FW_AFE_CLASS_P0 = 0,
|
||||
RTW89_FW_AFE_CLASS_P1 = 1,
|
||||
RTW89_FW_AFE_CLASS_P2 = 2,
|
||||
RTW89_FW_AFE_CLASS_P3 = 3,
|
||||
RTW89_FW_AFE_CLASS_P4 = 4,
|
||||
RTW89_FW_AFE_CLASS_CMN = 5,
|
||||
};
|
||||
|
||||
struct rtw89_fw_element_hdr {
|
||||
__le32 id; /* enum rtw89_fw_element_id */
|
||||
__le32 size; /* exclude header size */
|
||||
|
|
@ -4126,6 +4151,17 @@ struct rtw89_fw_element_hdr {
|
|||
u8 rsvd1[3];
|
||||
__le16 offset[];
|
||||
} __packed rfk_log_fmt;
|
||||
struct {
|
||||
u8 rsvd[8];
|
||||
struct rtw89_phy_afe_info {
|
||||
__le32 action; /* enum rtw89_fw_afe_action */
|
||||
__le32 cat; /* enum rtw89_fw_afe_cat */
|
||||
__le32 class; /* enum rtw89_fw_afe_class */
|
||||
__le32 addr;
|
||||
__le32 mask;
|
||||
__le32 val;
|
||||
} __packed infos[];
|
||||
} __packed afe;
|
||||
struct __rtw89_fw_txpwr_element txpwr;
|
||||
struct __rtw89_fw_regd_element regd;
|
||||
} __packed u;
|
||||
|
|
|
|||
|
|
@ -1702,6 +1702,91 @@ void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev)
|
|||
rtw89_phy_bb_reset(rtwdev);
|
||||
}
|
||||
|
||||
void rtw89_phy_init_bb_afe(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
|
||||
const struct rtw89_fw_element_hdr *afe_elm = elm_info->afe;
|
||||
const struct rtw89_phy_afe_info *info;
|
||||
u32 action, cat, class;
|
||||
u32 addr, mask, val;
|
||||
u32 poll, rpt;
|
||||
u32 n, i;
|
||||
|
||||
if (!afe_elm)
|
||||
return;
|
||||
|
||||
n = le32_to_cpu(afe_elm->size) / sizeof(*info);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
info = &afe_elm->u.afe.infos[i];
|
||||
|
||||
class = le32_to_cpu(info->class);
|
||||
switch (class) {
|
||||
case RTW89_FW_AFE_CLASS_P0:
|
||||
case RTW89_FW_AFE_CLASS_P1:
|
||||
case RTW89_FW_AFE_CLASS_CMN:
|
||||
/* Currently support two paths */
|
||||
break;
|
||||
case RTW89_FW_AFE_CLASS_P2:
|
||||
case RTW89_FW_AFE_CLASS_P3:
|
||||
case RTW89_FW_AFE_CLASS_P4:
|
||||
default:
|
||||
rtw89_warn(rtwdev, "unexpected AFE class %u\n", class);
|
||||
continue;
|
||||
}
|
||||
|
||||
addr = le32_to_cpu(info->addr);
|
||||
mask = le32_to_cpu(info->mask);
|
||||
val = le32_to_cpu(info->val);
|
||||
cat = le32_to_cpu(info->cat);
|
||||
action = le32_to_cpu(info->action);
|
||||
|
||||
switch (action) {
|
||||
case RTW89_FW_AFE_ACTION_WRITE:
|
||||
switch (cat) {
|
||||
case RTW89_FW_AFE_CAT_MAC:
|
||||
case RTW89_FW_AFE_CAT_MAC1:
|
||||
rtw89_write32_mask(rtwdev, addr, mask, val);
|
||||
break;
|
||||
case RTW89_FW_AFE_CAT_AFEDIG:
|
||||
case RTW89_FW_AFE_CAT_AFEDIG1:
|
||||
rtw89_write32_mask(rtwdev, addr, mask, val);
|
||||
break;
|
||||
case RTW89_FW_AFE_CAT_BB:
|
||||
rtw89_phy_write32_idx(rtwdev, addr, mask, val, RTW89_PHY_0);
|
||||
break;
|
||||
case RTW89_FW_AFE_CAT_BB1:
|
||||
rtw89_phy_write32_idx(rtwdev, addr, mask, val, RTW89_PHY_1);
|
||||
break;
|
||||
default:
|
||||
rtw89_warn(rtwdev,
|
||||
"unexpected AFE writing action %u\n", action);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RTW89_FW_AFE_ACTION_POLL:
|
||||
for (poll = 0; poll <= 10; poll++) {
|
||||
/*
|
||||
* For CAT_BB, AFE reads register with mcu_offset 0,
|
||||
* so both CAT_MAC and CAT_BB use the same method.
|
||||
*/
|
||||
rpt = rtw89_read32_mask(rtwdev, addr, mask);
|
||||
if (rpt == val)
|
||||
goto poll_done;
|
||||
|
||||
fsleep(1);
|
||||
}
|
||||
rtw89_warn(rtwdev, "failed to poll AFE cat=%u addr=0x%x mask=0x%x\n",
|
||||
cat, addr, mask);
|
||||
poll_done:
|
||||
break;
|
||||
case RTW89_FW_AFE_ACTION_DELAY:
|
||||
fsleep(addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static u32 rtw89_phy_nctl_poll(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
rtw89_phy_write32(rtwdev, 0x8080, 0x4);
|
||||
|
|
|
|||
|
|
@ -829,6 +829,7 @@ bool rtw89_phy_write_rf_v1(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
|||
bool rtw89_phy_write_rf_v2(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
|
||||
u32 addr, u32 mask, u32 data);
|
||||
void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev);
|
||||
void rtw89_phy_init_bb_afe(struct rtw89_dev *rtwdev);
|
||||
void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio);
|
||||
void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_reg2_def *reg,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user