From 075cc964ceec3489aa89464eac35949a3f5307c2 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Tue, 8 Nov 2022 18:08:00 +0530 Subject: [PATCH] icnss2: Send rf_subtype to firmware via QMI command Send rf_subtype based on dt node "qcom, rf_subtype" to firmware using QMI_WLFW_WLAN_HW_INIT_CFG message after qmi server arrive. Firmware will initialize different halphy code based on rf_subtype sent by host. Currently, this change will be applicable only for adreastea targets which can have either slate RF or Apache RF attached. Change-Id: Iba327d0c221104a4ebb55a72d42e1a4b8dcb66c3 --- cnss_utils/wlan_firmware_service_v01.c | 122 ++++++++++++++++++++++++- cnss_utils/wlan_firmware_service_v01.h | 49 +++++++++- icnss2/main.c | 32 +++++++ icnss2/main.h | 4 + icnss2/qmi.c | 67 ++++++++++++++ icnss2/qmi.h | 8 ++ 6 files changed, 275 insertions(+), 7 deletions(-) diff --git a/cnss_utils/wlan_firmware_service_v01.c b/cnss_utils/wlan_firmware_service_v01.c index c26635fd06..033c5d863a 100644 --- a/cnss_utils/wlan_firmware_service_v01.c +++ b/cnss_utils/wlan_firmware_service_v01.c @@ -1,6 +1,6 @@ -// SPDX-License-Identifier: GPL-2.0-only +/* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ -/* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. */ +/* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include "wlan_firmware_service_v01.h" #include @@ -726,6 +726,44 @@ static struct qmi_elem_info wlfw_shadow_reg_v3_cfg_s_v01_ei[] = { }, }; +static struct qmi_elem_info wlfw_share_mem_info_s_v01_ei[] = { + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_share_mem_type_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct + wlfw_share_mem_info_s_v01, + type), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct + wlfw_share_mem_info_s_v01, + start), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct + wlfw_share_mem_info_s_v01, + size), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { { .data_type = QMI_OPT_FLAG, @@ -4023,6 +4061,37 @@ struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[] = { resp), .ei_array = qmi_response_type_v01_ei, }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_respond_mem_resp_msg_v01, + share_mem_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_respond_mem_resp_msg_v01, + share_mem_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_SHARE_MEM_V01, + .elem_size = sizeof(struct wlfw_share_mem_info_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_respond_mem_resp_msg_v01, + share_mem), + .ei_array = wlfw_share_mem_info_s_v01_ei, + }, { .data_type = QMI_EOTI, .array_type = NO_ARRAY, @@ -6183,6 +6252,55 @@ struct qmi_elem_info wlfw_phy_cap_resp_msg_v01_ei[] = { }; EXPORT_SYMBOL(wlfw_phy_cap_resp_msg_v01_ei); +struct qmi_elem_info wlfw_wlan_hw_init_cfg_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_wlan_hw_init_cfg_req_msg_v01, + rf_subtype_valid), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_wlan_rf_subtype_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_wlan_hw_init_cfg_req_msg_v01, + rf_subtype), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; +EXPORT_SYMBOL(wlfw_wlan_hw_init_cfg_req_msg_v01_ei); + +struct qmi_elem_info wlfw_wlan_hw_init_cfg_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_wlan_hw_init_cfg_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; +EXPORT_SYMBOL(wlfw_wlan_hw_init_cfg_resp_msg_v01_ei); + /** * wlfw_is_valid_dt_node_found - Check if valid device tree node present * diff --git a/cnss_utils/wlan_firmware_service_v01.h b/cnss_utils/wlan_firmware_service_v01.h index 7c9d8ddf58..b51fc66916 100644 --- a/cnss_utils/wlan_firmware_service_v01.h +++ b/cnss_utils/wlan_firmware_service_v01.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ -/* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. */ +/* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef WLAN_FIRMWARE_SERVICE_V01_H #define WLAN_FIRMWARE_SERVICE_V01_H @@ -60,6 +60,7 @@ #define QMI_WLFW_ANTENNA_GRANT_REQ_V01 0x0048 #define QMI_WLFW_BDF_DOWNLOAD_REQ_V01 0x0025 #define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037 +#define QMI_WLFW_WLAN_HW_INIT_CFG_REQ_V01 0x0058 #define QMI_WLFW_RESPOND_GET_INFO_IND_V01 0x004B #define QMI_WLFW_QDSS_TRACE_DATA_REQ_V01 0x0042 #define QMI_WLFW_CAL_DOWNLOAD_RESP_V01 0x0027 @@ -100,6 +101,7 @@ #define QMI_WLFW_WFC_CALL_STATUS_REQ_V01 0x0049 #define QMI_WLFW_DEVICE_INFO_RESP_V01 0x004C #define QMI_WLFW_MSA_READY_RESP_V01 0x002E +#define QMI_WLFW_WLAN_HW_INIT_CFG_RESP_V01 0x0058 #define QMI_WLFW_INI_FILE_DOWNLOAD_REQ_V01 0x0056 #define QMI_WLFW_QDSS_TRACE_FREE_IND_V01 0x0046 #define QMI_WLFW_QDSS_MEM_READY_IND_V01 0x0052 @@ -110,6 +112,7 @@ #define QMI_WLFW_MAX_NUM_SHADOW_REG_V01 24 #define QMI_WLFW_MAX_BUILD_ID_LEN_V01 128 #define QMI_WLFW_MAX_DEV_MEM_NUM_V01 4 +#define QMI_WLFW_MAX_NUM_SHARE_MEM_V01 8 #define QMI_WLFW_MAX_NUM_MLO_LINKS_PER_CHIP_V01 2 #define QMI_WLFW_MAX_NUM_SVC_V01 24 #define QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01 2 @@ -182,6 +185,16 @@ enum wlfw_mem_type_enum_v01 { WLFW_MEM_TYPE_ENUM_MAX_VAL_V01 = INT_MAX, }; +enum wlfw_share_mem_type_enum_v01 { + WLFW_SHARE_MEM_TYPE_ENUM_MIN_VAL_V01 = INT_MIN, + QMI_WLFW_SHARE_MEM_CRASHDBG_V01 = 0, + QMI_WLFW_SHARE_MEM_TXSAR_V01 = 1, + QMI_WLFW_SHARE_MEM_AFC_V01 = 2, + QMI_WLFW_SHARE_MEM_REMOTE_COPY_V01 = 3, + QMI_WLFW_SHARE_MEM_MAX_V01 = 8, + WLFW_SHARE_MEM_TYPE_ENUM_MAX_VAL_V01 = INT_MAX, +}; + enum wlfw_qdss_trace_mode_enum_v01 { WLFW_QDSS_TRACE_MODE_ENUM_MIN_VAL_V01 = INT_MIN, QMI_WLFW_QDSS_TRACE_OFF_V01 = 0, @@ -293,6 +306,13 @@ enum wlfw_ini_file_type_v01 { WLFW_INI_FILE_TYPE_MAX_VAL_V01 = INT_MAX, }; +enum wlfw_wlan_rf_subtype_v01 { + WLFW_WLAN_RF_SUBTYPE_MIN_VAL_V01 = INT_MIN, + WLFW_WLAN_RF_SLATE_V01 = 0, + WLFW_WLAN_RF_APACHE_V01 = 1, + WLFW_WLAN_RF_SUBTYPE_MAX_VAL_V01 = INT_MAX, +}; + #define QMI_WLFW_CE_ATTR_FLAGS_V01 ((u32)0x00) #define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01) #define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02) @@ -432,6 +452,12 @@ struct wlfw_shadow_reg_v3_cfg_s_v01 { u32 addr; }; +struct wlfw_share_mem_info_s_v01 { + enum wlfw_share_mem_type_enum_v01 type; + u64 start; + u64 size; +}; + struct wlfw_ind_register_req_msg_v01 { u8 fw_ready_enable_valid; u8 fw_ready_enable; @@ -520,7 +546,6 @@ struct wlfw_wlan_mode_req_msg_v01 { u8 wlan_en_delay_valid; u32 wlan_en_delay; }; - #define WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN 22 extern struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[]; @@ -616,7 +641,6 @@ struct wlfw_cap_resp_msg_v01 { u8 rxgainlut_support_valid; u8 rxgainlut_support; }; - #define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 1146 extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[]; @@ -924,8 +948,11 @@ extern struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[]; struct wlfw_respond_mem_resp_msg_v01 { struct qmi_response_type_v01 resp; + u8 share_mem_valid; + u32 share_mem_len; + struct wlfw_share_mem_info_s_v01 share_mem[QMI_WLFW_MAX_NUM_SHARE_MEM_V01]; }; -#define WLFW_RESPOND_MEM_RESP_MSG_V01_MAX_MSG_LEN 7 +#define WLFW_RESPOND_MEM_RESP_MSG_V01_MAX_MSG_LEN 171 extern struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[]; struct wlfw_fw_mem_ready_ind_msg_v01 { @@ -1024,7 +1051,6 @@ struct wlfw_qdss_trace_mem_info_req_msg_v01 { u8 end_valid; u8 end; }; - #define WLFW_QDSS_TRACE_MEM_INFO_REQ_MSG_V01_MAX_MSG_LEN 892 extern struct qmi_elem_info wlfw_qdss_trace_mem_info_req_msg_v01_ei[]; @@ -1365,4 +1391,17 @@ struct wlfw_phy_cap_resp_msg_v01 { #define WLFW_PHY_CAP_RESP_MSG_V01_MAX_MSG_LEN 18 extern struct qmi_elem_info wlfw_phy_cap_resp_msg_v01_ei[]; +struct wlfw_wlan_hw_init_cfg_req_msg_v01 { + u8 rf_subtype_valid; + enum wlfw_wlan_rf_subtype_v01 rf_subtype; +}; +#define WLFW_WLAN_HW_INIT_CFG_REQ_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_wlan_hw_init_cfg_req_msg_v01_ei[]; + +struct wlfw_wlan_hw_init_cfg_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; +#define WLFW_WLAN_HW_INIT_CFG_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_wlan_hw_init_cfg_resp_msg_v01_ei[]; + #endif diff --git a/icnss2/main.c b/icnss2/main.c index f59ac0f560..f398fc857d 100644 --- a/icnss2/main.c +++ b/icnss2/main.c @@ -787,12 +787,25 @@ void icnss_set_wlan_en_delay(struct icnss_priv *priv) } } +static enum wlfw_wlan_rf_subtype_v01 icnss_rf_subtype_value_to_type(u32 val) +{ + switch (val) { + case WLAN_RF_SLATE: + return WLFW_WLAN_RF_SLATE_V01; + case WLAN_RF_APACHE: + return WLFW_WLAN_RF_APACHE_V01; + default: + return WLFW_WLAN_RF_SUBTYPE_MAX_VAL_V01; + } +} + static int icnss_driver_event_server_arrive(struct icnss_priv *priv, void *data) { int ret = 0; int temp = 0; bool ignore_assert = false; + enum wlfw_wlan_rf_subtype_v01 rf_subtype; if (!priv) return -ENODEV; @@ -824,6 +837,19 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv, goto fail; } + if (priv->is_rf_subtype_valid) { + rf_subtype = icnss_rf_subtype_value_to_type(priv->rf_subtype); + if (rf_subtype != WLFW_WLAN_RF_SUBTYPE_MAX_VAL_V01) { + ret = wlfw_wlan_hw_init_cfg_msg(priv, rf_subtype); + if (ret < 0) + icnss_pr_dbg("Sending rf_subtype failed ret %d\n", + ret); + } else { + icnss_pr_dbg("Invalid rf subtype %d in DT\n", + priv->rf_subtype); + } + } + if (priv->device_id == WCN6750_DEVICE_ID) { if (!icnss_get_temperature(priv, &temp)) { icnss_pr_dbg("Temperature: %d\n", temp); @@ -3873,6 +3899,12 @@ static int icnss_resource_parse(struct icnss_priv *priv) priv->ce_irqs[i] = res->start; } } + + if (of_property_read_u32(pdev->dev.of_node, "qcom,rf_subtype", + &priv->rf_subtype) == 0) { + priv->is_rf_subtype_valid = true; + icnss_pr_dbg("RF subtype 0x%x\n", priv->rf_subtype); + } } else if (priv->device_id == WCN6750_DEVICE_ID) { res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "msi_addr"); diff --git a/icnss2/main.h b/icnss2/main.h index 5ed7bcaff9..cd669b04de 100644 --- a/icnss2/main.h +++ b/icnss2/main.h @@ -30,6 +30,8 @@ #define ICNSS_PCI_EP_WAKE_OFFSET 4 #define ICNSS_DISABLE_M3_SSR 0 #define ICNSS_ENABLE_M3_SSR 1 +#define WLAN_RF_SLATE 0 +#define WLAN_RF_APACHE 1 extern uint64_t dynamic_feature_mask; @@ -490,6 +492,8 @@ struct icnss_priv { struct workqueue_struct *soc_update_wq; unsigned long device_config; bool wpss_supported; + bool is_rf_subtype_valid; + u32 rf_subtype; }; struct icnss_reg_info { diff --git a/icnss2/qmi.c b/icnss2/qmi.c index ad1e1b55d9..5ee261f709 100644 --- a/icnss2/qmi.c +++ b/icnss2/qmi.c @@ -3457,3 +3457,70 @@ out: kfree(req); return ret; } + +int wlfw_wlan_hw_init_cfg_msg(struct icnss_priv *penv, + enum wlfw_wlan_rf_subtype_v01 type) +{ + int ret; + struct wlfw_wlan_hw_init_cfg_req_msg_v01 *req; + struct wlfw_wlan_hw_init_cfg_resp_msg_v01 *resp; + struct qmi_txn txn; + + if (!penv) + return -ENODEV; + + icnss_pr_dbg("Sending hw init cfg, rf_subtype: 0x%x\n", type); + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return -ENOMEM; + + resp = kzalloc(sizeof(*resp), GFP_KERNEL); + if (!resp) { + kfree(req); + return -ENOMEM; + } + + req->rf_subtype_valid = 1; + req->rf_subtype = type; + + ret = qmi_txn_init(&penv->qmi, &txn, + wlfw_wlan_hw_init_cfg_resp_msg_v01_ei, resp); + if (ret < 0) { + icnss_pr_err("Fail to init txn for hw init cfg, resp %d\n", + ret); + goto out; + } + + ret = qmi_send_request(&penv->qmi, NULL, &txn, + QMI_WLFW_WLAN_HW_INIT_CFG_REQ_V01, + WLFW_WLAN_HW_INIT_CFG_REQ_MSG_V01_MAX_MSG_LEN, + wlfw_wlan_hw_init_cfg_req_msg_v01_ei, req); + if (ret < 0) { + qmi_txn_cancel(&txn); + icnss_pr_err("Fail to send hw init cfg %d\n", ret); + goto out; + } + + ret = qmi_txn_wait(&txn, penv->ctrl_params.qmi_timeout); + if (ret < 0) { + icnss_pr_err("HW init cfg timed out with ret %d\n", + ret); + goto out; + + } else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { + icnss_pr_err("HW init cfg request rejected,result:%d error:%d\n", + resp->resp.result, resp->resp.error); + ret = -resp->resp.result; + goto out; + } + + kfree(resp); + kfree(req); + return 0; + +out: + kfree(req); + kfree(resp); + return ret; +} diff --git a/icnss2/qmi.h b/icnss2/qmi.h index 663485cd95..9c0d4ac5a1 100644 --- a/icnss2/qmi.h +++ b/icnss2/qmi.h @@ -203,6 +203,12 @@ int icnss_send_vbatt_update(struct icnss_priv *priv, uint64_t voltage_uv) { return 0; } + +int wlfw_wlan_hw_init_cfg_msg(struct icnss_priv *penv, + enum wlfw_wlan_rf_subtype_v01 type) +{ + return 0; +} #else int wlfw_ind_register_send_sync_msg(struct icnss_priv *priv); int icnss_connect_to_fw_server(struct icnss_priv *priv, void *data); @@ -258,6 +264,8 @@ void icnss_dms_deinit(struct icnss_priv *priv); int wlfw_subsys_restart_level_msg(struct icnss_priv *penv, uint8_t restart_level); int wlfw_cal_report_req(struct icnss_priv *priv); int icnss_send_vbatt_update(struct icnss_priv *priv, uint64_t voltage_uv); +int wlfw_wlan_hw_init_cfg_msg(struct icnss_priv *penv, + enum wlfw_wlan_rf_subtype_v01 type); #endif #endif /* __ICNSS_QMI_H__*/