wlan_platform: Bring initial files for ICNSS family drivers
Bring ICNSS family drivers from msm-5.10 kernel as of commit 'cb298739ee51 ("icnss2: Download bdf file for helium targets")' to WLAN platform project. Updated wlan_firmware_service files and makefiles to support ICNSS2 compilation. Change-Id: I02cf792b61772f07ac0607be7bb6b3bfda7815e4
This commit is contained in:
@@ -93,3 +93,12 @@ LOCAL_MODULE_TAGS := optional
|
|||||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||||
|
################################ icnss2 ################################
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_SRC_FILES := $(CNSS_SRC_FILES)
|
||||||
|
LOCAL_MODULE := icnss2.ko
|
||||||
|
LOCAL_MODULE_KBUILD_NAME := icnss2/icnss2.ko
|
||||||
|
LOCAL_MODULE_TAGS := optional
|
||||||
|
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||||
|
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||||
|
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||||
|
9
Kbuild
9
Kbuild
@@ -10,6 +10,14 @@ ifeq ($(CONFIG_CNSS2_QMI),y)
|
|||||||
KBUILD_CPPFLAGS += -DCONFIG_CNSS2_QMI
|
KBUILD_CPPFLAGS += -DCONFIG_CNSS2_QMI
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_ICNSS2_DEBUG),y)
|
||||||
|
KBUILD_CPPFLAGS += -DCONFIG_ICNSS2_DEBUG
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_ICNSS2_QMI),y)
|
||||||
|
KBUILD_CPPFLAGS += -DCONFIG_ICNSS2_QMI
|
||||||
|
endif
|
||||||
|
|
||||||
# CONFIG_CNSS_PLAT_IPC_QMI_SVC should never be "y" here since it
|
# CONFIG_CNSS_PLAT_IPC_QMI_SVC should never be "y" here since it
|
||||||
# can be only compiled as a module from out-of-kernel-tree source.
|
# can be only compiled as a module from out-of-kernel-tree source.
|
||||||
ifeq ($(CONFIG_CNSS_PLAT_IPC_QMI_SVC),m)
|
ifeq ($(CONFIG_CNSS_PLAT_IPC_QMI_SVC),m)
|
||||||
@@ -17,6 +25,7 @@ KBUILD_CPPFLAGS += -DCONFIG_CNSS_PLAT_IPC_QMI_SVC
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
obj-$(CONFIG_CNSS2) += cnss2/
|
obj-$(CONFIG_CNSS2) += cnss2/
|
||||||
|
obj-$(CONFIG_ICNSS2) += icnss2/
|
||||||
obj-$(CONFIG_CNSS_GENL) += cnss_genl/
|
obj-$(CONFIG_CNSS_GENL) += cnss_genl/
|
||||||
obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc/
|
obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc/
|
||||||
obj-y += cnss_utils/
|
obj-y += cnss_utils/
|
||||||
|
3
Makefile
3
Makefile
@@ -11,8 +11,11 @@ WLAN_PLATFORM_ROOT = $(shell pwd)
|
|||||||
KBUILD_OPTIONS := WLAN_PLATFORM_ROOT=$(WLAN_PLATFORM_ROOT)
|
KBUILD_OPTIONS := WLAN_PLATFORM_ROOT=$(WLAN_PLATFORM_ROOT)
|
||||||
KBUILD_OPTIONS += CONFIG_CNSS_OUT_OF_TREE=y
|
KBUILD_OPTIONS += CONFIG_CNSS_OUT_OF_TREE=y
|
||||||
KBUILD_OPTIONS += CONFIG_CNSS2=m
|
KBUILD_OPTIONS += CONFIG_CNSS2=m
|
||||||
|
KBUILD_OPTIONS += CONFIG_ICNSS2=m
|
||||||
KBUILD_OPTIONS += CONFIG_CNSS2_QMI=y
|
KBUILD_OPTIONS += CONFIG_CNSS2_QMI=y
|
||||||
|
KBUILD_OPTIONS += CONFIG_ICNSS2_QMI=y
|
||||||
KBUILD_OPTIONS += CONFIG_CNSS2_DEBUG=y
|
KBUILD_OPTIONS += CONFIG_CNSS2_DEBUG=y
|
||||||
|
KBUILD_OPTIONS += CONFIG_ICNSS2_DEBUG=y
|
||||||
KBUILD_OPTIONS += CONFIG_CNSS_QMI_SVC=m
|
KBUILD_OPTIONS += CONFIG_CNSS_QMI_SVC=m
|
||||||
KBUILD_OPTIONS += CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
KBUILD_OPTIONS += CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
|
||||||
KBUILD_OPTIONS += CONFIG_CNSS_GENL=m
|
KBUILD_OPTIONS += CONFIG_CNSS_GENL=m
|
||||||
|
@@ -1766,6 +1766,106 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = {
|
|||||||
dev_mem_info),
|
dev_mem_info),
|
||||||
.ei_array = wlfw_dev_mem_info_s_v01_ei,
|
.ei_array = wlfw_dev_mem_info_s_v01_ei,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_OPT_FLAG,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u8),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x1D,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_cap_resp_msg_v01,
|
||||||
|
foundry_name_valid),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_STRING,
|
||||||
|
.elem_len = QMI_WLFW_MAX_STR_LEN_V01 + 1,
|
||||||
|
.elem_size = sizeof(char),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x1D,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_cap_resp_msg_v01,
|
||||||
|
foundry_name),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_OPT_FLAG,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u8),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x1E,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_cap_resp_msg_v01,
|
||||||
|
hang_data_addr_offset_valid),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u32),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x1E,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_cap_resp_msg_v01,
|
||||||
|
hang_data_addr_offset),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_OPT_FLAG,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u8),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x1F,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_cap_resp_msg_v01,
|
||||||
|
hang_data_length_valid),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_UNSIGNED_2_BYTE,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u16),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x1F,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_cap_resp_msg_v01,
|
||||||
|
hang_data_length),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_OPT_FLAG,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u8),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x20,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_cap_resp_msg_v01,
|
||||||
|
bdf_dnld_method_valid),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_SIGNED_4_BYTE_ENUM,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(enum wlfw_bdf_dnld_method_v01),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x20,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_cap_resp_msg_v01,
|
||||||
|
bdf_dnld_method),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_OPT_FLAG,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u8),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x21,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_cap_resp_msg_v01,
|
||||||
|
hwid_bitmap_valid),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u8),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x21,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_cap_resp_msg_v01,
|
||||||
|
hwid_bitmap),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.data_type = QMI_EOTI,
|
.data_type = QMI_EOTI,
|
||||||
.array_type = NO_ARRAY,
|
.array_type = NO_ARRAY,
|
||||||
@@ -3475,6 +3575,76 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = {
|
|||||||
wlfw_host_cap_req_msg_v01,
|
wlfw_host_cap_req_msg_v01,
|
||||||
wake_msi_addr),
|
wake_msi_addr),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_OPT_FLAG,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u8),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x2B,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_host_cap_req_msg_v01,
|
||||||
|
wlan_enable_delay_valid),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u32),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x2B,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_host_cap_req_msg_v01,
|
||||||
|
wlan_enable_delay),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_OPT_FLAG,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u8),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x2C,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_host_cap_req_msg_v01,
|
||||||
|
ddr_type_valid),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u32),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x2C,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_host_cap_req_msg_v01,
|
||||||
|
ddr_type),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_OPT_FLAG,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u8),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x2D,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_host_cap_req_msg_v01,
|
||||||
|
gpio_info_valid),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_DATA_LEN,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u8),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x2D,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_host_cap_req_msg_v01,
|
||||||
|
gpio_info_len),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
|
.elem_len = QMI_WLFW_MAX_NUM_GPIO_INFO_V01,
|
||||||
|
.elem_size = sizeof(u32),
|
||||||
|
.array_type = VAR_LEN_ARRAY,
|
||||||
|
.tlv_type = 0x2D,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_host_cap_req_msg_v01,
|
||||||
|
gpio_info),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.data_type = QMI_EOTI,
|
.data_type = QMI_EOTI,
|
||||||
.array_type = NO_ARRAY,
|
.array_type = NO_ARRAY,
|
||||||
@@ -5458,6 +5628,55 @@ struct qmi_elem_info wlfw_m3_dump_upload_segments_req_ind_msg_v01_ei[] = {
|
|||||||
};
|
};
|
||||||
EXPORT_SYMBOL(wlfw_m3_dump_upload_segments_req_ind_msg_v01_ei);
|
EXPORT_SYMBOL(wlfw_m3_dump_upload_segments_req_ind_msg_v01_ei);
|
||||||
|
|
||||||
|
struct qmi_elem_info wlfw_subsys_restart_level_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_subsys_restart_level_req_msg_v01,
|
||||||
|
restart_level_type_valid),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||||
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(u8),
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = 0x10,
|
||||||
|
.offset = offsetof(struct
|
||||||
|
wlfw_subsys_restart_level_req_msg_v01,
|
||||||
|
restart_level_type),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.data_type = QMI_EOTI,
|
||||||
|
.array_type = NO_ARRAY,
|
||||||
|
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL(wlfw_subsys_restart_level_req_msg_v01_ei);
|
||||||
|
|
||||||
|
struct qmi_elem_info wlfw_subsys_restart_level_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_subsys_restart_level_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_subsys_restart_level_resp_msg_v01_ei);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wlfw_is_valid_dt_node_found - Check if valid device tree node present
|
* wlfw_is_valid_dt_node_found - Check if valid device tree node present
|
||||||
*
|
*
|
||||||
|
@@ -9,6 +9,8 @@
|
|||||||
#define WLFW_SERVICE_ID_V01 0x45
|
#define WLFW_SERVICE_ID_V01 0x45
|
||||||
#define WLFW_SERVICE_VERS_V01 0x01
|
#define WLFW_SERVICE_VERS_V01 0x01
|
||||||
|
|
||||||
|
#define QMI_WLFW_SUBSYS_RESTART_LEVEL_RESP_V01 0x0055
|
||||||
|
#define QMI_WLFW_SUBSYS_RESTART_LEVEL_REQ_V01 0x0055
|
||||||
#define QMI_WLFW_POWER_SAVE_RESP_V01 0x0050
|
#define QMI_WLFW_POWER_SAVE_RESP_V01 0x0050
|
||||||
#define QMI_WLFW_CAP_REQ_V01 0x0024
|
#define QMI_WLFW_CAP_REQ_V01 0x0024
|
||||||
#define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026
|
#define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026
|
||||||
@@ -107,6 +109,7 @@
|
|||||||
#define QMI_WLFW_MAX_NUM_SVC_V01 24
|
#define QMI_WLFW_MAX_NUM_SVC_V01 24
|
||||||
#define QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01 2
|
#define QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01 2
|
||||||
#define QMI_WLFW_MAC_ADDR_SIZE_V01 6
|
#define QMI_WLFW_MAC_ADDR_SIZE_V01 6
|
||||||
|
#define QMI_WLFW_MAX_NUM_GPIO_INFO_V01 20
|
||||||
#define QMI_WLFW_MAX_NUM_MEM_CFG_V01 2
|
#define QMI_WLFW_MAX_NUM_MEM_CFG_V01 2
|
||||||
#define QMI_WLFW_MAX_NUM_MEM_SEG_V01 52
|
#define QMI_WLFW_MAX_NUM_MEM_SEG_V01 52
|
||||||
#define QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01 256
|
#define QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01 256
|
||||||
@@ -166,6 +169,7 @@ enum wlfw_mem_type_enum_v01 {
|
|||||||
QMI_WLFW_MEM_HANG_DATA_V01 = 7,
|
QMI_WLFW_MEM_HANG_DATA_V01 = 7,
|
||||||
QMI_WLFW_MLO_GLOBAL_MEM_V01 = 8,
|
QMI_WLFW_MLO_GLOBAL_MEM_V01 = 8,
|
||||||
QMI_WLFW_PAGEABLE_MEM_V01 = 9,
|
QMI_WLFW_PAGEABLE_MEM_V01 = 9,
|
||||||
|
QMI_WLFW_AFC_MEM_V01 = 10,
|
||||||
WLFW_MEM_TYPE_ENUM_MAX_VAL_V01 = INT_MAX,
|
WLFW_MEM_TYPE_ENUM_MAX_VAL_V01 = INT_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -248,10 +252,28 @@ enum cnss_feature_v01 {
|
|||||||
CNSS_FEATURE_MIN_VAL_V01 = INT_MIN,
|
CNSS_FEATURE_MIN_VAL_V01 = INT_MIN,
|
||||||
BOOTSTRAP_CLOCK_SELECT_V01 = 0,
|
BOOTSTRAP_CLOCK_SELECT_V01 = 0,
|
||||||
CNSS_DRV_SUPPORT_V01 = 1,
|
CNSS_DRV_SUPPORT_V01 = 1,
|
||||||
|
CNSS_WLAN_EN_SUPPORT_V01 = 2,
|
||||||
CNSS_MAX_FEATURE_V01 = 64,
|
CNSS_MAX_FEATURE_V01 = 64,
|
||||||
CNSS_FEATURE_MAX_VAL_V01 = INT_MAX,
|
CNSS_FEATURE_MAX_VAL_V01 = INT_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum wlfw_bdf_dnld_method_v01 {
|
||||||
|
WLFW_BDF_DNLD_METHOD_MIN_VAL_V01 = INT_MIN,
|
||||||
|
WLFW_DIRECT_BDF_COPY_V01 = 0,
|
||||||
|
WLFW_SEND_BDF_OVER_QMI_V01 = 1,
|
||||||
|
WLFW_BDF_DNLD_METHOD_MAX_VAL_V01 = INT_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum wlfw_gpio_info_type_v01 {
|
||||||
|
WLFW_GPIO_INFO_TYPE_MIN_VAL_V01 = INT_MIN,
|
||||||
|
WLAN_EN_GPIO_V01 = 0,
|
||||||
|
BT_EN_GPIO_V01 = 1,
|
||||||
|
HOST_SOL_GPIO_V01 = 2,
|
||||||
|
TARGET_SOL_GPIO_V01 = 3,
|
||||||
|
GPIO_TYPE_MAX_V01 = 4,
|
||||||
|
WLFW_GPIO_INFO_TYPE_MAX_VAL_V01 = INT_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
#define QMI_WLFW_CE_ATTR_FLAGS_V01 ((u32)0x00)
|
#define QMI_WLFW_CE_ATTR_FLAGS_V01 ((u32)0x00)
|
||||||
#define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01)
|
#define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01)
|
||||||
#define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02)
|
#define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02)
|
||||||
@@ -530,8 +552,19 @@ struct wlfw_cap_resp_msg_v01 {
|
|||||||
enum wlfw_rd_card_chain_cap_v01 rd_card_chain_cap;
|
enum wlfw_rd_card_chain_cap_v01 rd_card_chain_cap;
|
||||||
u8 dev_mem_info_valid;
|
u8 dev_mem_info_valid;
|
||||||
struct wlfw_dev_mem_info_s_v01 dev_mem_info[QMI_WLFW_MAX_DEV_MEM_NUM_V01];
|
struct wlfw_dev_mem_info_s_v01 dev_mem_info[QMI_WLFW_MAX_DEV_MEM_NUM_V01];
|
||||||
|
u8 foundry_name_valid;
|
||||||
|
char foundry_name[QMI_WLFW_MAX_STR_LEN_V01 + 1];
|
||||||
|
u8 hang_data_addr_offset_valid;
|
||||||
|
u32 hang_data_addr_offset;
|
||||||
|
u8 hang_data_length_valid;
|
||||||
|
u16 hang_data_length;
|
||||||
|
u8 bdf_dnld_method_valid;
|
||||||
|
enum wlfw_bdf_dnld_method_v01 bdf_dnld_method;
|
||||||
|
u8 hwid_bitmap_valid;
|
||||||
|
u8 hwid_bitmap;
|
||||||
};
|
};
|
||||||
#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 320
|
|
||||||
|
#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 362
|
||||||
extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[];
|
extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[];
|
||||||
|
|
||||||
struct wlfw_bdf_download_req_msg_v01 {
|
struct wlfw_bdf_download_req_msg_v01 {
|
||||||
@@ -803,9 +836,16 @@ struct wlfw_host_cap_req_msg_v01 {
|
|||||||
u8 num_wlan_vaps;
|
u8 num_wlan_vaps;
|
||||||
u8 wake_msi_addr_valid;
|
u8 wake_msi_addr_valid;
|
||||||
u32 wake_msi_addr;
|
u32 wake_msi_addr;
|
||||||
|
u8 wlan_enable_delay_valid;
|
||||||
|
u32 wlan_enable_delay;
|
||||||
|
u8 ddr_type_valid;
|
||||||
|
u32 ddr_type;
|
||||||
|
u8 gpio_info_valid;
|
||||||
|
u32 gpio_info_len;
|
||||||
|
u32 gpio_info[QMI_WLFW_MAX_NUM_GPIO_INFO_V01];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 389
|
#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 487
|
||||||
extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
|
extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
|
||||||
|
|
||||||
struct wlfw_host_cap_resp_msg_v01 {
|
struct wlfw_host_cap_resp_msg_v01 {
|
||||||
@@ -1268,4 +1308,19 @@ struct wlfw_m3_dump_upload_segments_req_ind_msg_v01 {
|
|||||||
#define WLFW_M3_DUMP_UPLOAD_SEGMENTS_REQ_IND_MSG_V01_MAX_MSG_LEN 387
|
#define WLFW_M3_DUMP_UPLOAD_SEGMENTS_REQ_IND_MSG_V01_MAX_MSG_LEN 387
|
||||||
extern struct qmi_elem_info wlfw_m3_dump_upload_segments_req_ind_msg_v01_ei[];
|
extern struct qmi_elem_info wlfw_m3_dump_upload_segments_req_ind_msg_v01_ei[];
|
||||||
|
|
||||||
|
struct wlfw_subsys_restart_level_req_msg_v01 {
|
||||||
|
u8 restart_level_type_valid;
|
||||||
|
u8 restart_level_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define WLFW_SUBSYS_RESTART_LEVEL_REQ_MSG_V01_MAX_MSG_LEN 4
|
||||||
|
extern struct qmi_elem_info wlfw_subsys_restart_level_req_msg_v01_ei[];
|
||||||
|
|
||||||
|
struct wlfw_subsys_restart_level_resp_msg_v01 {
|
||||||
|
struct qmi_response_type_v01 resp;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define WLFW_SUBSYS_RESTART_LEVEL_RESP_MSG_V01_MAX_MSG_LEN 7
|
||||||
|
extern struct qmi_elem_info wlfw_subsys_restart_level_resp_msg_v01_ei[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
38
icnss2/Kconfig
Normal file
38
icnss2/Kconfig
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
config ICNSS2
|
||||||
|
tristate "Platform driver for Wi-Fi Module module"
|
||||||
|
select CNSS_UTILS
|
||||||
|
help
|
||||||
|
This module adds support for Q6 integrated WLAN connectivity
|
||||||
|
subsystem with iWCN architecture. This module is responsible for
|
||||||
|
communicating WLAN on/off control messages to FW over QMI channel.
|
||||||
|
It is also responsible for handling WLAN PD restart notifications.
|
||||||
|
|
||||||
|
config ICNSS2_DEBUG
|
||||||
|
bool "ICNSS2 Platform Driver Debug Support"
|
||||||
|
depends on ICNSS2
|
||||||
|
help
|
||||||
|
Say 'Y' here to enable ICNSS driver debug support. Debug support
|
||||||
|
primarily consists of logs consisting of information related to
|
||||||
|
hardware register access and enabling BUG_ON for certain cases to aid
|
||||||
|
the debugging.
|
||||||
|
|
||||||
|
config ICNSS2_QMI
|
||||||
|
bool "ICNSS2 Platform Driver QMI support"
|
||||||
|
depends on ICNSS2
|
||||||
|
select CNSS_QMI_SVC
|
||||||
|
help
|
||||||
|
Say 'Y' here to enable ICNSS QMI support. ICNSS driver will use
|
||||||
|
QMI framework to communicate with WLAN FW. It will send coldboot
|
||||||
|
handshake messages to WLAN FW, which includes hardware capabilities
|
||||||
|
and configurations. It also send WLAN on/off control message to FW
|
||||||
|
over QMI channel.
|
||||||
|
|
||||||
|
config CNSS_QCA6750
|
||||||
|
bool "Enable ICNSS QCA6750 chipset specific changes"
|
||||||
|
depends on ICNSS2
|
||||||
|
help
|
||||||
|
This enables the changes from WLAN host driver that are specific to
|
||||||
|
CNSS QCA6750 chipset.
|
||||||
|
These changes are needed to support the new hardware architecture
|
||||||
|
for CNSS QCA6750 chipset.
|
16
icnss2/Makefile
Normal file
16
icnss2/Makefile
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_CNSS_OUT_OF_TREE),y)
|
||||||
|
ccflags-y += -I$(WLAN_PLATFORM_ROOT)/cnss_utils
|
||||||
|
ccflags-y += -I$(WLAN_PLATFORM_ROOT)/inc
|
||||||
|
else
|
||||||
|
ccflags-y += -I$(srctree)/drivers/net/wireless/cnss_utils/
|
||||||
|
endif
|
||||||
|
|
||||||
|
obj-$(CONFIG_ICNSS2) += icnss2.o
|
||||||
|
|
||||||
|
icnss2-y := main.o
|
||||||
|
icnss2-y += debug.o
|
||||||
|
icnss2-y += power.o
|
||||||
|
icnss2-y += genl.o
|
||||||
|
icnss2-$(CONFIG_ICNSS2_QMI) += qmi.o
|
891
icnss2/debug.c
Normal file
891
icnss2/debug.c
Normal file
@@ -0,0 +1,891 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include "main.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "qmi.h"
|
||||||
|
#include "power.h"
|
||||||
|
|
||||||
|
void *icnss_ipc_log_context;
|
||||||
|
void *icnss_ipc_log_long_context;
|
||||||
|
void *icnss_ipc_log_smp2p_context;
|
||||||
|
void *icnss_ipc_soc_wake_context;
|
||||||
|
|
||||||
|
static ssize_t icnss_regwrite_write(struct file *fp,
|
||||||
|
const char __user *user_buf,
|
||||||
|
size_t count, loff_t *off)
|
||||||
|
{
|
||||||
|
struct icnss_priv *priv =
|
||||||
|
((struct seq_file *)fp->private_data)->private;
|
||||||
|
char buf[64];
|
||||||
|
char *sptr, *token;
|
||||||
|
unsigned int len = 0;
|
||||||
|
uint32_t reg_offset, mem_type, reg_val;
|
||||||
|
const char *delim = " ";
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!test_bit(ICNSS_FW_READY, &priv->state) ||
|
||||||
|
!test_bit(ICNSS_POWER_ON, &priv->state))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
len = min(count, sizeof(buf) - 1);
|
||||||
|
if (copy_from_user(buf, user_buf, len))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
buf[len] = '\0';
|
||||||
|
sptr = buf;
|
||||||
|
|
||||||
|
token = strsep(&sptr, delim);
|
||||||
|
if (!token)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!sptr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (kstrtou32(token, 0, &mem_type))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
token = strsep(&sptr, delim);
|
||||||
|
if (!token)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!sptr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (kstrtou32(token, 0, ®_offset))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
token = strsep(&sptr, delim);
|
||||||
|
if (!token)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (kstrtou32(token, 0, ®_val))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = wlfw_athdiag_write_send_sync_msg(priv, reg_offset, mem_type,
|
||||||
|
sizeof(uint32_t),
|
||||||
|
(uint8_t *)®_val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_regwrite_show(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
struct icnss_priv *priv = s->private;
|
||||||
|
|
||||||
|
seq_puts(s, "Usage: echo <mem_type> <offset> <reg_val> > <debugfs>/icnss/reg_write\n");
|
||||||
|
|
||||||
|
if (!test_bit(ICNSS_FW_READY, &priv->state))
|
||||||
|
seq_puts(s, "Firmware is not ready yet!, wait for FW READY\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_regwrite_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, icnss_regwrite_show, inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations icnss_regwrite_fops = {
|
||||||
|
.read = seq_read,
|
||||||
|
.write = icnss_regwrite_write,
|
||||||
|
.open = icnss_regwrite_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int icnss_regread_show(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
struct icnss_priv *priv = s->private;
|
||||||
|
|
||||||
|
mutex_lock(&priv->dev_lock);
|
||||||
|
if (!priv->diag_reg_read_buf) {
|
||||||
|
seq_puts(s, "Usage: echo <mem_type> <offset> <data_len> > <debugfs>/icnss/reg_read\n");
|
||||||
|
|
||||||
|
if (!test_bit(ICNSS_FW_READY, &priv->state))
|
||||||
|
seq_puts(s, "Firmware is not ready yet!, wait for FW READY\n");
|
||||||
|
|
||||||
|
mutex_unlock(&priv->dev_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
seq_printf(s, "REGREAD: Addr 0x%x Type 0x%x Length 0x%x\n",
|
||||||
|
priv->diag_reg_read_addr, priv->diag_reg_read_mem_type,
|
||||||
|
priv->diag_reg_read_len);
|
||||||
|
|
||||||
|
seq_hex_dump(s, "", DUMP_PREFIX_OFFSET, 32, 4, priv->diag_reg_read_buf,
|
||||||
|
priv->diag_reg_read_len, false);
|
||||||
|
|
||||||
|
priv->diag_reg_read_len = 0;
|
||||||
|
kfree(priv->diag_reg_read_buf);
|
||||||
|
priv->diag_reg_read_buf = NULL;
|
||||||
|
mutex_unlock(&priv->dev_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_regread_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, icnss_regread_show, inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t icnss_reg_parse(const char __user *user_buf, size_t count,
|
||||||
|
struct icnss_reg_info *reg_info_ptr)
|
||||||
|
{
|
||||||
|
char buf[64] = {0};
|
||||||
|
char *sptr = NULL, *token = NULL;
|
||||||
|
const char *delim = " ";
|
||||||
|
unsigned int len = 0;
|
||||||
|
|
||||||
|
if (user_buf == NULL)
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
len = min(count, sizeof(buf) - 1);
|
||||||
|
if (copy_from_user(buf, user_buf, len))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
buf[len] = '\0';
|
||||||
|
sptr = buf;
|
||||||
|
|
||||||
|
token = strsep(&sptr, delim);
|
||||||
|
if (!token)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!sptr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (kstrtou32(token, 0, ®_info_ptr->mem_type))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
token = strsep(&sptr, delim);
|
||||||
|
if (!token)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!sptr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (kstrtou32(token, 0, ®_info_ptr->reg_offset))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
token = strsep(&sptr, delim);
|
||||||
|
if (!token)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (kstrtou32(token, 0, ®_info_ptr->data_len))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (reg_info_ptr->data_len == 0 ||
|
||||||
|
reg_info_ptr->data_len > WLFW_MAX_DATA_SIZE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t icnss_regread_write(struct file *fp, const char __user *user_buf,
|
||||||
|
size_t count, loff_t *off)
|
||||||
|
{
|
||||||
|
struct icnss_priv *priv =
|
||||||
|
((struct seq_file *)fp->private_data)->private;
|
||||||
|
uint8_t *reg_buf = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
struct icnss_reg_info reg_info;
|
||||||
|
|
||||||
|
if (!test_bit(ICNSS_FW_READY, &priv->state) ||
|
||||||
|
!test_bit(ICNSS_POWER_ON, &priv->state))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = icnss_reg_parse(user_buf, count, ®_info);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
mutex_lock(&priv->dev_lock);
|
||||||
|
kfree(priv->diag_reg_read_buf);
|
||||||
|
priv->diag_reg_read_buf = NULL;
|
||||||
|
|
||||||
|
reg_buf = kzalloc(reg_info.data_len, GFP_KERNEL);
|
||||||
|
if (!reg_buf) {
|
||||||
|
mutex_unlock(&priv->dev_lock);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wlfw_athdiag_read_send_sync_msg(priv, reg_info.reg_offset,
|
||||||
|
reg_info.mem_type,
|
||||||
|
reg_info.data_len,
|
||||||
|
reg_buf);
|
||||||
|
if (ret) {
|
||||||
|
kfree(reg_buf);
|
||||||
|
mutex_unlock(&priv->dev_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->diag_reg_read_addr = reg_info.reg_offset;
|
||||||
|
priv->diag_reg_read_mem_type = reg_info.mem_type;
|
||||||
|
priv->diag_reg_read_len = reg_info.data_len;
|
||||||
|
priv->diag_reg_read_buf = reg_buf;
|
||||||
|
mutex_unlock(&priv->dev_lock);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations icnss_regread_fops = {
|
||||||
|
.read = seq_read,
|
||||||
|
.write = icnss_regread_write,
|
||||||
|
.open = icnss_regread_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t icnss_stats_write(struct file *fp, const char __user *buf,
|
||||||
|
size_t count, loff_t *off)
|
||||||
|
{
|
||||||
|
struct icnss_priv *priv =
|
||||||
|
((struct seq_file *)fp->private_data)->private;
|
||||||
|
int ret;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
ret = kstrtou32_from_user(buf, count, 0, &val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
memset(&priv->stats, 0, sizeof(priv->stats));
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_stats_show_rejuvenate_info(struct seq_file *s,
|
||||||
|
struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
if (priv->stats.rejuvenate_ind) {
|
||||||
|
seq_puts(s, "\n<---------------- Rejuvenate Info ----------------->\n");
|
||||||
|
seq_printf(s, "Number of Rejuvenations: %u\n",
|
||||||
|
priv->stats.rejuvenate_ind);
|
||||||
|
seq_printf(s, "Cause for Rejuvenation: 0x%x\n",
|
||||||
|
priv->cause_for_rejuvenation);
|
||||||
|
seq_printf(s, "Requesting Sub-System: 0x%x\n",
|
||||||
|
priv->requesting_sub_system);
|
||||||
|
seq_printf(s, "Line Number: %u\n",
|
||||||
|
priv->line_number);
|
||||||
|
seq_printf(s, "Function Name: %s\n",
|
||||||
|
priv->function_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_stats_show_irqs(struct seq_file *s, struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
seq_puts(s, "\n<------------------ IRQ stats ------------------->\n");
|
||||||
|
seq_printf(s, "%4s %4s %8s %8s %8s %8s\n", "CE_ID", "IRQ", "Request",
|
||||||
|
"Free", "Enable", "Disable");
|
||||||
|
for (i = 0; i < ICNSS_MAX_IRQ_REGISTRATIONS; i++)
|
||||||
|
seq_printf(s, "%4d: %4u %8u %8u %8u %8u\n", i,
|
||||||
|
priv->ce_irqs[i], priv->stats.ce_irqs[i].request,
|
||||||
|
priv->stats.ce_irqs[i].free,
|
||||||
|
priv->stats.ce_irqs[i].enable,
|
||||||
|
priv->stats.ce_irqs[i].disable);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_stats_show_capability(struct seq_file *s,
|
||||||
|
struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
if (test_bit(ICNSS_FW_READY, &priv->state)) {
|
||||||
|
seq_puts(s, "\n<---------------- FW Capability ----------------->\n");
|
||||||
|
seq_printf(s, "Chip ID: 0x%x\n", priv->chip_info.chip_id);
|
||||||
|
seq_printf(s, "Chip family: 0x%x\n",
|
||||||
|
priv->chip_info.chip_family);
|
||||||
|
seq_printf(s, "Board ID: 0x%x\n", priv->board_id);
|
||||||
|
seq_printf(s, "SOC Info: 0x%x\n", priv->soc_id);
|
||||||
|
seq_printf(s, "Firmware Version: 0x%x\n",
|
||||||
|
priv->fw_version_info.fw_version);
|
||||||
|
seq_printf(s, "Firmware Build Timestamp: %s\n",
|
||||||
|
priv->fw_version_info.fw_build_timestamp);
|
||||||
|
seq_printf(s, "Firmware Build ID: %s\n",
|
||||||
|
priv->fw_build_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_stats_show_events(struct seq_file *s, struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
seq_puts(s, "\n<----------------- Events stats ------------------->\n");
|
||||||
|
seq_printf(s, "%24s %16s %16s\n", "Events", "Posted", "Processed");
|
||||||
|
for (i = 0; i < ICNSS_DRIVER_EVENT_MAX; i++)
|
||||||
|
seq_printf(s, "%24s %16u %16u\n",
|
||||||
|
icnss_driver_event_to_str(i),
|
||||||
|
priv->stats.events[i].posted,
|
||||||
|
priv->stats.events[i].processed);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
enum icnss_driver_state i;
|
||||||
|
int skip = 0;
|
||||||
|
unsigned long state;
|
||||||
|
|
||||||
|
seq_printf(s, "\nState: 0x%lx(", priv->state);
|
||||||
|
for (i = 0, state = priv->state; state != 0; state >>= 1, i++) {
|
||||||
|
|
||||||
|
if (!(state & 0x1))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (skip++)
|
||||||
|
seq_puts(s, " | ");
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case ICNSS_WLFW_CONNECTED:
|
||||||
|
seq_puts(s, "FW CONN");
|
||||||
|
continue;
|
||||||
|
case ICNSS_POWER_ON:
|
||||||
|
seq_puts(s, "POWER ON");
|
||||||
|
continue;
|
||||||
|
case ICNSS_FW_READY:
|
||||||
|
seq_puts(s, "FW READY");
|
||||||
|
continue;
|
||||||
|
case ICNSS_DRIVER_PROBED:
|
||||||
|
seq_puts(s, "DRIVER PROBED");
|
||||||
|
continue;
|
||||||
|
case ICNSS_FW_TEST_MODE:
|
||||||
|
seq_puts(s, "FW TEST MODE");
|
||||||
|
continue;
|
||||||
|
case ICNSS_PM_SUSPEND:
|
||||||
|
seq_puts(s, "PM SUSPEND");
|
||||||
|
continue;
|
||||||
|
case ICNSS_PM_SUSPEND_NOIRQ:
|
||||||
|
seq_puts(s, "PM SUSPEND NOIRQ");
|
||||||
|
continue;
|
||||||
|
case ICNSS_SSR_REGISTERED:
|
||||||
|
seq_puts(s, "SSR REGISTERED");
|
||||||
|
continue;
|
||||||
|
case ICNSS_PDR_REGISTERED:
|
||||||
|
seq_puts(s, "PDR REGISTERED");
|
||||||
|
continue;
|
||||||
|
case ICNSS_PD_RESTART:
|
||||||
|
seq_puts(s, "PD RESTART");
|
||||||
|
continue;
|
||||||
|
case ICNSS_WLFW_EXISTS:
|
||||||
|
seq_puts(s, "WLAN FW EXISTS");
|
||||||
|
continue;
|
||||||
|
case ICNSS_SHUTDOWN_DONE:
|
||||||
|
seq_puts(s, "SHUTDOWN DONE");
|
||||||
|
continue;
|
||||||
|
case ICNSS_HOST_TRIGGERED_PDR:
|
||||||
|
seq_puts(s, "HOST TRIGGERED PDR");
|
||||||
|
continue;
|
||||||
|
case ICNSS_FW_DOWN:
|
||||||
|
seq_puts(s, "FW DOWN");
|
||||||
|
continue;
|
||||||
|
case ICNSS_DRIVER_UNLOADING:
|
||||||
|
seq_puts(s, "DRIVER UNLOADING");
|
||||||
|
continue;
|
||||||
|
case ICNSS_REJUVENATE:
|
||||||
|
seq_puts(s, "FW REJUVENATE");
|
||||||
|
continue;
|
||||||
|
case ICNSS_MODE_ON:
|
||||||
|
seq_puts(s, "MODE ON DONE");
|
||||||
|
continue;
|
||||||
|
case ICNSS_BLOCK_SHUTDOWN:
|
||||||
|
seq_puts(s, "BLOCK SHUTDOWN");
|
||||||
|
continue;
|
||||||
|
case ICNSS_PDR:
|
||||||
|
seq_puts(s, "PDR TRIGGERED");
|
||||||
|
continue;
|
||||||
|
case ICNSS_DEL_SERVER:
|
||||||
|
seq_puts(s, "DEL SERVER");
|
||||||
|
continue;
|
||||||
|
case ICNSS_COLD_BOOT_CAL:
|
||||||
|
seq_puts(s, "COLD BOOT CALIBRATION");
|
||||||
|
continue;
|
||||||
|
case ICNSS_QMI_DMS_CONNECTED:
|
||||||
|
seq_puts(s, "DMS_CONNECTED");
|
||||||
|
}
|
||||||
|
|
||||||
|
seq_printf(s, "UNKNOWN-%d", i);
|
||||||
|
}
|
||||||
|
seq_puts(s, ")\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ICNSS_STATS_DUMP(_s, _priv, _x) \
|
||||||
|
seq_printf(_s, "%24s: %u\n", #_x, _priv->stats._x)
|
||||||
|
|
||||||
|
static int icnss_stats_show(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct icnss_priv *priv = s->private;
|
||||||
|
|
||||||
|
ICNSS_STATS_DUMP(s, priv, ind_register_req);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, ind_register_resp);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, ind_register_err);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, cap_req);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, cap_resp);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, cap_err);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, pin_connect_result);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, cfg_req);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, cfg_resp);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, cfg_req_err);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, mode_req);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, mode_resp);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, mode_req_err);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, ini_req);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, ini_resp);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, ini_req_err);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, recovery.pdr_fw_crash);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, recovery.pdr_host_error);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, recovery.root_pd_crash);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, recovery.root_pd_shutdown);
|
||||||
|
|
||||||
|
seq_puts(s, "\n<------------------ PM stats ------------------->\n");
|
||||||
|
ICNSS_STATS_DUMP(s, priv, pm_suspend);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, pm_suspend_err);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, pm_resume);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, pm_resume_err);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, pm_suspend_noirq);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, pm_suspend_noirq_err);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, pm_resume_noirq);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, pm_resume_noirq_err);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, pm_stay_awake);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, pm_relax);
|
||||||
|
|
||||||
|
if (priv->device_id != WCN6750_DEVICE_ID) {
|
||||||
|
seq_puts(s, "\n<------------------ MSA stats ------------------->\n");
|
||||||
|
ICNSS_STATS_DUMP(s, priv, msa_info_req);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, msa_info_resp);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, msa_info_err);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, msa_ready_req);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, msa_ready_resp);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, msa_ready_err);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, msa_ready_ind);
|
||||||
|
|
||||||
|
seq_puts(s, "\n<------------------ Rejuvenate stats ------------------->\n");
|
||||||
|
ICNSS_STATS_DUMP(s, priv, rejuvenate_ind);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, rejuvenate_ack_req);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, rejuvenate_ack_resp);
|
||||||
|
ICNSS_STATS_DUMP(s, priv, rejuvenate_ack_err);
|
||||||
|
icnss_stats_show_rejuvenate_info(s, priv);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
icnss_stats_show_irqs(s, priv);
|
||||||
|
|
||||||
|
icnss_stats_show_capability(s, priv);
|
||||||
|
|
||||||
|
icnss_stats_show_events(s, priv);
|
||||||
|
|
||||||
|
icnss_stats_show_state(s, priv);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_stats_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, icnss_stats_show, inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations icnss_stats_fops = {
|
||||||
|
.read = seq_read,
|
||||||
|
.write = icnss_stats_write,
|
||||||
|
.release = single_release,
|
||||||
|
.open = icnss_stats_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int icnss_fw_debug_show(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
struct icnss_priv *priv = s->private;
|
||||||
|
|
||||||
|
seq_puts(s, "\nUsage: echo <CMD> <VAL> > <DEBUGFS>/icnss/fw_debug\n");
|
||||||
|
|
||||||
|
seq_puts(s, "\nCMD: test_mode\n");
|
||||||
|
seq_puts(s, " VAL: 0 (Test mode disable)\n");
|
||||||
|
seq_puts(s, " VAL: 1 (WLAN FW test)\n");
|
||||||
|
seq_puts(s, " VAL: 2 (CCPM test)\n");
|
||||||
|
seq_puts(s, " VAL: 3 (Trigger Recovery)\n");
|
||||||
|
seq_puts(s, " VAL: 4 (allow recursive recovery)\n");
|
||||||
|
seq_puts(s, " VAL: 3 (Disallow recursive recovery)\n");
|
||||||
|
|
||||||
|
seq_puts(s, "\nCMD: dynamic_feature_mask\n");
|
||||||
|
seq_puts(s, " VAL: (64 bit feature mask)\n");
|
||||||
|
|
||||||
|
if (!test_bit(ICNSS_FW_READY, &priv->state)) {
|
||||||
|
seq_puts(s, "Firmware is not ready yet, can't run test_mode!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_bit(ICNSS_DRIVER_PROBED, &priv->state)) {
|
||||||
|
seq_puts(s, "Machine mode is running, can't run test_mode!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_bit(ICNSS_FW_TEST_MODE, &priv->state)) {
|
||||||
|
seq_puts(s, "test_mode is running, can't run test_mode!\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
seq_puts(s, "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_test_mode_fw_test_off(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!test_bit(ICNSS_FW_READY, &priv->state)) {
|
||||||
|
icnss_pr_err("Firmware is not ready yet!, wait for FW READY: state: 0x%lx\n",
|
||||||
|
priv->state);
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_bit(ICNSS_DRIVER_PROBED, &priv->state)) {
|
||||||
|
icnss_pr_err("Machine mode is running, can't run test mode: state: 0x%lx\n",
|
||||||
|
priv->state);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!test_bit(ICNSS_FW_TEST_MODE, &priv->state)) {
|
||||||
|
icnss_pr_err("Test mode not started, state: 0x%lx\n",
|
||||||
|
priv->state);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
icnss_wlan_disable(&priv->pdev->dev, ICNSS_OFF);
|
||||||
|
|
||||||
|
ret = icnss_hw_power_off(priv);
|
||||||
|
|
||||||
|
clear_bit(ICNSS_FW_TEST_MODE, &priv->state);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_test_mode_fw_test(struct icnss_priv *priv,
|
||||||
|
enum icnss_driver_mode mode)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!test_bit(ICNSS_FW_READY, &priv->state)) {
|
||||||
|
icnss_pr_err("Firmware is not ready yet!, wait for FW READY, state: 0x%lx\n",
|
||||||
|
priv->state);
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_bit(ICNSS_DRIVER_PROBED, &priv->state)) {
|
||||||
|
icnss_pr_err("Machine mode is running, can't run test mode, state: 0x%lx\n",
|
||||||
|
priv->state);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_bit(ICNSS_FW_TEST_MODE, &priv->state)) {
|
||||||
|
icnss_pr_err("Test mode already started, state: 0x%lx\n",
|
||||||
|
priv->state);
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = icnss_hw_power_on(priv);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
set_bit(ICNSS_FW_TEST_MODE, &priv->state);
|
||||||
|
|
||||||
|
ret = icnss_wlan_enable(&priv->pdev->dev, NULL, mode, NULL);
|
||||||
|
if (ret)
|
||||||
|
goto power_off;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
power_off:
|
||||||
|
icnss_hw_power_off(priv);
|
||||||
|
clear_bit(ICNSS_FW_TEST_MODE, &priv->state);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t icnss_fw_debug_write(struct file *fp,
|
||||||
|
const char __user *user_buf,
|
||||||
|
size_t count, loff_t *off)
|
||||||
|
{
|
||||||
|
struct icnss_priv *priv =
|
||||||
|
((struct seq_file *)fp->private_data)->private;
|
||||||
|
char buf[64];
|
||||||
|
char *sptr, *token;
|
||||||
|
unsigned int len = 0;
|
||||||
|
char *cmd;
|
||||||
|
uint64_t val;
|
||||||
|
const char *delim = " ";
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
len = min(count, sizeof(buf) - 1);
|
||||||
|
if (copy_from_user(buf, user_buf, len))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
buf[len] = '\0';
|
||||||
|
sptr = buf;
|
||||||
|
|
||||||
|
token = strsep(&sptr, delim);
|
||||||
|
if (!token)
|
||||||
|
return -EINVAL;
|
||||||
|
if (!sptr)
|
||||||
|
return -EINVAL;
|
||||||
|
cmd = token;
|
||||||
|
|
||||||
|
token = strsep(&sptr, delim);
|
||||||
|
if (!token)
|
||||||
|
return -EINVAL;
|
||||||
|
if (kstrtou64(token, 0, &val))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (strcmp(cmd, "test_mode") == 0) {
|
||||||
|
switch (val) {
|
||||||
|
case 0:
|
||||||
|
ret = icnss_test_mode_fw_test_off(priv);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ret = icnss_test_mode_fw_test(priv, ICNSS_WALTEST);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ret = icnss_test_mode_fw_test(priv, ICNSS_CCPM);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ret = icnss_trigger_recovery(&priv->pdev->dev);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
icnss_allow_recursive_recovery(&priv->pdev->dev);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
icnss_disallow_recursive_recovery(&priv->pdev->dev);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
} else if (strcmp(cmd, "dynamic_feature_mask") == 0) {
|
||||||
|
ret = wlfw_dynamic_feature_mask_send_sync_msg(priv, val);
|
||||||
|
} else {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_fw_debug_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, icnss_fw_debug_show, inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations icnss_fw_debug_fops = {
|
||||||
|
.read = seq_read,
|
||||||
|
.write = icnss_fw_debug_write,
|
||||||
|
.release = single_release,
|
||||||
|
.open = icnss_fw_debug_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t icnss_control_params_debug_write(struct file *fp,
|
||||||
|
const char __user *user_buf,
|
||||||
|
size_t count, loff_t *off)
|
||||||
|
{
|
||||||
|
struct icnss_priv *priv =
|
||||||
|
((struct seq_file *)fp->private_data)->private;
|
||||||
|
|
||||||
|
char buf[64];
|
||||||
|
char *sptr, *token;
|
||||||
|
char *cmd;
|
||||||
|
u32 val;
|
||||||
|
unsigned int len = 0;
|
||||||
|
const char *delim = " ";
|
||||||
|
|
||||||
|
if (!priv)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
len = min(count, sizeof(buf) - 1);
|
||||||
|
if (copy_from_user(buf, user_buf, len))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
buf[len] = '\0';
|
||||||
|
sptr = buf;
|
||||||
|
|
||||||
|
token = strsep(&sptr, delim);
|
||||||
|
if (!token)
|
||||||
|
return -EINVAL;
|
||||||
|
if (!sptr)
|
||||||
|
return -EINVAL;
|
||||||
|
cmd = token;
|
||||||
|
|
||||||
|
token = strsep(&sptr, delim);
|
||||||
|
if (!token)
|
||||||
|
return -EINVAL;
|
||||||
|
if (kstrtou32(token, 0, &val))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (strcmp(cmd, "qmi_timeout") == 0)
|
||||||
|
priv->ctrl_params.qmi_timeout = msecs_to_jiffies(val);
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_control_params_debug_show(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
struct icnss_priv *priv = s->private;
|
||||||
|
|
||||||
|
seq_puts(s, "\nUsage: echo <params_name> <value> > <debugfs>/icnss/control_params\n");
|
||||||
|
seq_puts(s, "<params_name> can be from below:\n");
|
||||||
|
seq_puts(s, "qmi_timeout: Timeout for QMI message in milliseconds\n");
|
||||||
|
|
||||||
|
seq_puts(s, "\nCurrent value:\n");
|
||||||
|
|
||||||
|
seq_printf(s, "qmi_timeout: %u\n", jiffies_to_msecs(priv->ctrl_params.qmi_timeout));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_control_params_debug_open(struct inode *inode,
|
||||||
|
struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, icnss_control_params_debug_show,
|
||||||
|
inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations icnss_control_params_debug_fops = {
|
||||||
|
.read = seq_read,
|
||||||
|
.write = icnss_control_params_debug_write,
|
||||||
|
.release = single_release,
|
||||||
|
.open = icnss_control_params_debug_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_ICNSS2_DEBUG
|
||||||
|
int icnss_debugfs_create(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct dentry *root_dentry;
|
||||||
|
|
||||||
|
root_dentry = debugfs_create_dir("icnss", NULL);
|
||||||
|
|
||||||
|
if (IS_ERR(root_dentry)) {
|
||||||
|
ret = PTR_ERR(root_dentry);
|
||||||
|
icnss_pr_err("Unable to create debugfs %d\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->root_dentry = root_dentry;
|
||||||
|
|
||||||
|
debugfs_create_file("fw_debug", 0600, root_dentry, priv,
|
||||||
|
&icnss_fw_debug_fops);
|
||||||
|
debugfs_create_file("stats", 0600, root_dentry, priv,
|
||||||
|
&icnss_stats_fops);
|
||||||
|
debugfs_create_file("reg_read", 0600, root_dentry, priv,
|
||||||
|
&icnss_regread_fops);
|
||||||
|
debugfs_create_file("reg_write", 0600, root_dentry, priv,
|
||||||
|
&icnss_regwrite_fops);
|
||||||
|
debugfs_create_file("control_params", 0600, root_dentry, priv,
|
||||||
|
&icnss_control_params_debug_fops);
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int icnss_debugfs_create(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct dentry *root_dentry;
|
||||||
|
|
||||||
|
root_dentry = debugfs_create_dir("icnss", NULL);
|
||||||
|
|
||||||
|
if (IS_ERR(root_dentry)) {
|
||||||
|
ret = PTR_ERR(root_dentry);
|
||||||
|
icnss_pr_err("Unable to create debugfs %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->root_dentry = root_dentry;
|
||||||
|
|
||||||
|
debugfs_create_file("stats", 0600, root_dentry, priv,
|
||||||
|
&icnss_stats_fops);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void icnss_debugfs_destroy(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
debugfs_remove_recursive(priv->root_dentry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void icnss_debug_init(void)
|
||||||
|
{
|
||||||
|
icnss_ipc_log_context = ipc_log_context_create(NUM_LOG_PAGES,
|
||||||
|
"icnss", 0);
|
||||||
|
if (!icnss_ipc_log_context)
|
||||||
|
icnss_pr_err("Unable to create log context\n");
|
||||||
|
|
||||||
|
icnss_ipc_log_long_context = ipc_log_context_create(NUM_LOG_LONG_PAGES,
|
||||||
|
"icnss_long", 0);
|
||||||
|
if (!icnss_ipc_log_long_context)
|
||||||
|
icnss_pr_err("Unable to create log long context\n");
|
||||||
|
|
||||||
|
icnss_ipc_log_smp2p_context = ipc_log_context_create(NUM_LOG_LONG_PAGES,
|
||||||
|
"icnss_smp2p", 0);
|
||||||
|
if (!icnss_ipc_log_smp2p_context)
|
||||||
|
icnss_pr_err("Unable to create log smp2p context\n");
|
||||||
|
|
||||||
|
icnss_ipc_soc_wake_context = ipc_log_context_create(NUM_LOG_LONG_PAGES,
|
||||||
|
"icnss_soc_wake", 0);
|
||||||
|
if (!icnss_ipc_soc_wake_context)
|
||||||
|
icnss_pr_err("Unable to create log soc_wake context\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void icnss_debug_deinit(void)
|
||||||
|
{
|
||||||
|
if (icnss_ipc_log_context) {
|
||||||
|
ipc_log_context_destroy(icnss_ipc_log_context);
|
||||||
|
icnss_ipc_log_context = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icnss_ipc_log_long_context) {
|
||||||
|
ipc_log_context_destroy(icnss_ipc_log_long_context);
|
||||||
|
icnss_ipc_log_long_context = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icnss_ipc_log_smp2p_context) {
|
||||||
|
ipc_log_context_destroy(icnss_ipc_log_smp2p_context);
|
||||||
|
icnss_ipc_log_smp2p_context = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icnss_ipc_soc_wake_context) {
|
||||||
|
ipc_log_context_destroy(icnss_ipc_soc_wake_context);
|
||||||
|
icnss_ipc_soc_wake_context = NULL;
|
||||||
|
}
|
||||||
|
}
|
108
icnss2/debug.h
Normal file
108
icnss2/debug.h
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ICNSS_DEBUG_H
|
||||||
|
#define _ICNSS_DEBUG_H
|
||||||
|
|
||||||
|
#include <linux/ipc_logging.h>
|
||||||
|
#include <linux/printk.h>
|
||||||
|
|
||||||
|
#define NUM_LOG_PAGES 10
|
||||||
|
#define NUM_LOG_LONG_PAGES 4
|
||||||
|
|
||||||
|
extern void *icnss_ipc_log_context;
|
||||||
|
extern void *icnss_ipc_log_long_context;
|
||||||
|
extern void *icnss_ipc_log_smp2p_context;
|
||||||
|
extern void *icnss_ipc_soc_wake_context;
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_IPC_LOGGING)
|
||||||
|
#define icnss_ipc_log_string(_x...) \
|
||||||
|
ipc_log_string(icnss_ipc_log_context, _x)
|
||||||
|
|
||||||
|
#define icnss_ipc_log_long_string(_x...) \
|
||||||
|
ipc_log_string(icnss_ipc_log_long_context, _x)
|
||||||
|
|
||||||
|
#define icnss_ipc_log_smp2p_string(_x...) \
|
||||||
|
ipc_log_string(icnss_ipc_log_smp2p_context, _x)
|
||||||
|
|
||||||
|
#define icnss_ipc_soc_wake_string(_x...) \
|
||||||
|
ipc_log_string(icnss_ipc_soc_wake_context, _x)
|
||||||
|
#else
|
||||||
|
#define icnss_ipc_log_string(_x...)
|
||||||
|
|
||||||
|
#define icnss_ipc_log_long_string(_x...)
|
||||||
|
|
||||||
|
#define icnss_ipc_log_smp2p_string(_x...)
|
||||||
|
|
||||||
|
#define icnss_ipc_soc_wake_string(_x...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define icnss_pr_err(_fmt, ...) do { \
|
||||||
|
printk("%s" pr_fmt(_fmt), KERN_ERR, ##__VA_ARGS__); \
|
||||||
|
icnss_ipc_log_string("%s" pr_fmt(_fmt), "", \
|
||||||
|
##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define icnss_pr_warn(_fmt, ...) do { \
|
||||||
|
printk("%s" pr_fmt(_fmt), KERN_WARNING, ##__VA_ARGS__); \
|
||||||
|
icnss_ipc_log_string("%s" pr_fmt(_fmt), "", \
|
||||||
|
##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define icnss_pr_info(_fmt, ...) do { \
|
||||||
|
printk("%s" pr_fmt(_fmt), KERN_INFO, ##__VA_ARGS__); \
|
||||||
|
icnss_ipc_log_string("%s" pr_fmt(_fmt), "", \
|
||||||
|
##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define icnss_pr_dbg(_fmt, ...) do { \
|
||||||
|
pr_debug(_fmt, ##__VA_ARGS__); \
|
||||||
|
icnss_ipc_log_string(pr_fmt(_fmt), ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define icnss_pr_vdbg(_fmt, ...) do { \
|
||||||
|
pr_debug(_fmt, ##__VA_ARGS__); \
|
||||||
|
icnss_ipc_log_long_string(pr_fmt(_fmt), ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define icnss_pr_smp2p(_fmt, ...) do { \
|
||||||
|
pr_debug(_fmt, ##__VA_ARGS__); \
|
||||||
|
icnss_ipc_log_smp2p_string(pr_fmt(_fmt), ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define icnss_pr_soc_wake(_fmt, ...) do { \
|
||||||
|
pr_debug(_fmt, ##__VA_ARGS__); \
|
||||||
|
icnss_ipc_soc_wake_string(pr_fmt(_fmt), ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#ifdef CONFIG_ICNSS2_DEBUG
|
||||||
|
#define ICNSS_ASSERT(_condition) do { \
|
||||||
|
if (!(_condition)) { \
|
||||||
|
icnss_pr_err("ASSERT at line %d\n", __LINE__); \
|
||||||
|
BUG(); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define ICNSS_ASSERT(_condition) do { } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define icnss_fatal_err(_fmt, ...) \
|
||||||
|
icnss_pr_err("fatal: "_fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
enum icnss_debug_quirks {
|
||||||
|
HW_ALWAYS_ON,
|
||||||
|
HW_DEBUG_ENABLE,
|
||||||
|
SKIP_QMI,
|
||||||
|
RECOVERY_DISABLE,
|
||||||
|
SSR_ONLY,
|
||||||
|
PDR_ONLY,
|
||||||
|
FW_REJUVENATE_ENABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
void icnss_debug_init(void);
|
||||||
|
void icnss_debug_deinit(void);
|
||||||
|
int icnss_debugfs_create(struct icnss_priv *priv);
|
||||||
|
void icnss_debugfs_destroy(struct icnss_priv *priv);
|
||||||
|
#endif /* _ICNSS_DEBUG_H */
|
213
icnss2/genl.c
Normal file
213
icnss2/genl.c
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/* Copyright (c) 2020, The Linux Foundation. All rights reserved. */
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) "cnss_genl: " fmt
|
||||||
|
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <net/netlink.h>
|
||||||
|
#include <net/genetlink.h>
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#define ICNSS_GENL_FAMILY_NAME "cnss-genl"
|
||||||
|
#define ICNSS_GENL_MCAST_GROUP_NAME "cnss-genl-grp"
|
||||||
|
#define ICNSS_GENL_VERSION 1
|
||||||
|
#define ICNSS_GENL_DATA_LEN_MAX (15 * 1024)
|
||||||
|
#define ICNSS_GENL_STR_LEN_MAX 16
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ICNSS_GENL_ATTR_MSG_UNSPEC,
|
||||||
|
ICNSS_GENL_ATTR_MSG_TYPE,
|
||||||
|
ICNSS_GENL_ATTR_MSG_FILE_NAME,
|
||||||
|
ICNSS_GENL_ATTR_MSG_TOTAL_SIZE,
|
||||||
|
ICNSS_GENL_ATTR_MSG_SEG_ID,
|
||||||
|
ICNSS_GENL_ATTR_MSG_END,
|
||||||
|
ICNSS_GENL_ATTR_MSG_DATA_LEN,
|
||||||
|
ICNSS_GENL_ATTR_MSG_DATA,
|
||||||
|
__ICNSS_GENL_ATTR_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ICNSS_GENL_ATTR_MAX (__ICNSS_GENL_ATTR_MAX - 1)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ICNSS_GENL_CMD_UNSPEC,
|
||||||
|
ICNSS_GENL_CMD_MSG,
|
||||||
|
__ICNSS_GENL_CMD_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ICNSS_GENL_CMD_MAX (__ICNSS_GENL_CMD_MAX - 1)
|
||||||
|
|
||||||
|
static struct nla_policy icnss_genl_msg_policy[ICNSS_GENL_ATTR_MAX + 1] = {
|
||||||
|
[ICNSS_GENL_ATTR_MSG_TYPE] = { .type = NLA_U8 },
|
||||||
|
[ICNSS_GENL_ATTR_MSG_FILE_NAME] = { .type = NLA_NUL_STRING,
|
||||||
|
.len = ICNSS_GENL_STR_LEN_MAX },
|
||||||
|
[ICNSS_GENL_ATTR_MSG_TOTAL_SIZE] = { .type = NLA_U32 },
|
||||||
|
[ICNSS_GENL_ATTR_MSG_SEG_ID] = { .type = NLA_U32 },
|
||||||
|
[ICNSS_GENL_ATTR_MSG_END] = { .type = NLA_U8 },
|
||||||
|
[ICNSS_GENL_ATTR_MSG_DATA_LEN] = { .type = NLA_U32 },
|
||||||
|
[ICNSS_GENL_ATTR_MSG_DATA] = { .type = NLA_BINARY,
|
||||||
|
.len = ICNSS_GENL_DATA_LEN_MAX },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int icnss_genl_process_msg(struct sk_buff *skb, struct genl_info *info)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct genl_ops icnss_genl_ops[] = {
|
||||||
|
{
|
||||||
|
.cmd = ICNSS_GENL_CMD_MSG,
|
||||||
|
.doit = icnss_genl_process_msg,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct genl_multicast_group icnss_genl_mcast_grp[] = {
|
||||||
|
{
|
||||||
|
.name = ICNSS_GENL_MCAST_GROUP_NAME,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct genl_family icnss_genl_family = {
|
||||||
|
.id = 0,
|
||||||
|
.hdrsize = 0,
|
||||||
|
.name = ICNSS_GENL_FAMILY_NAME,
|
||||||
|
.version = ICNSS_GENL_VERSION,
|
||||||
|
.maxattr = ICNSS_GENL_ATTR_MAX,
|
||||||
|
.policy = icnss_genl_msg_policy,
|
||||||
|
.module = THIS_MODULE,
|
||||||
|
.ops = icnss_genl_ops,
|
||||||
|
.n_ops = ARRAY_SIZE(icnss_genl_ops),
|
||||||
|
.mcgrps = icnss_genl_mcast_grp,
|
||||||
|
.n_mcgrps = ARRAY_SIZE(icnss_genl_mcast_grp),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int icnss_genl_send_data(u8 type, char *file_name, u32 total_size,
|
||||||
|
u32 seg_id, u8 end, u32 data_len, u8 *msg_buff)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb = NULL;
|
||||||
|
void *msg_header = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
char filename[ICNSS_GENL_STR_LEN_MAX + 1];
|
||||||
|
|
||||||
|
icnss_pr_dbg("type: %u, file_name %s, total_size: %x, seg_id %u, end %u, data_len %u\n",
|
||||||
|
type, file_name, total_size, seg_id, end, data_len);
|
||||||
|
|
||||||
|
if (!file_name)
|
||||||
|
strlcpy(filename, "default", sizeof(filename));
|
||||||
|
else
|
||||||
|
strlcpy(filename, file_name, sizeof(filename));
|
||||||
|
|
||||||
|
skb = genlmsg_new(NLMSG_HDRLEN +
|
||||||
|
nla_total_size(sizeof(type)) +
|
||||||
|
nla_total_size(strlen(filename) + 1) +
|
||||||
|
nla_total_size(sizeof(total_size)) +
|
||||||
|
nla_total_size(sizeof(seg_id)) +
|
||||||
|
nla_total_size(sizeof(end)) +
|
||||||
|
nla_total_size(sizeof(data_len)) +
|
||||||
|
nla_total_size(data_len), GFP_KERNEL);
|
||||||
|
if (!skb)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
msg_header = genlmsg_put(skb, 0, 0,
|
||||||
|
&icnss_genl_family, 0,
|
||||||
|
ICNSS_GENL_CMD_MSG);
|
||||||
|
if (!msg_header) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nla_put_u8(skb, ICNSS_GENL_ATTR_MSG_TYPE, type);
|
||||||
|
if (ret < 0)
|
||||||
|
goto fail;
|
||||||
|
ret = nla_put_string(skb, ICNSS_GENL_ATTR_MSG_FILE_NAME, filename);
|
||||||
|
if (ret < 0)
|
||||||
|
goto fail;
|
||||||
|
ret = nla_put_u32(skb, ICNSS_GENL_ATTR_MSG_TOTAL_SIZE, total_size);
|
||||||
|
if (ret < 0)
|
||||||
|
goto fail;
|
||||||
|
ret = nla_put_u32(skb, ICNSS_GENL_ATTR_MSG_SEG_ID, seg_id);
|
||||||
|
if (ret < 0)
|
||||||
|
goto fail;
|
||||||
|
ret = nla_put_u8(skb, ICNSS_GENL_ATTR_MSG_END, end);
|
||||||
|
if (ret < 0)
|
||||||
|
goto fail;
|
||||||
|
ret = nla_put_u32(skb, ICNSS_GENL_ATTR_MSG_DATA_LEN, data_len);
|
||||||
|
if (ret < 0)
|
||||||
|
goto fail;
|
||||||
|
ret = nla_put(skb, ICNSS_GENL_ATTR_MSG_DATA, data_len, msg_buff);
|
||||||
|
if (ret < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
genlmsg_end(skb, msg_header);
|
||||||
|
ret = genlmsg_multicast(&icnss_genl_family, skb, 0, 0, GFP_KERNEL);
|
||||||
|
if (ret < 0)
|
||||||
|
icnss_pr_err("Fail to send genl msg: %d\n", ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
fail:
|
||||||
|
icnss_pr_err("Fail to generate genl msg: %d\n", ret);
|
||||||
|
if (skb)
|
||||||
|
nlmsg_free(skb);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_genl_send_msg(void *buff, u8 type, char *file_name, u32 total_size)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
u8 *msg_buff = buff;
|
||||||
|
u32 remaining = total_size;
|
||||||
|
u32 seg_id = 0;
|
||||||
|
u32 data_len = 0;
|
||||||
|
u8 end = 0;
|
||||||
|
u8 retry;
|
||||||
|
|
||||||
|
icnss_pr_dbg("type: %u, total_size: %x\n", type, total_size);
|
||||||
|
|
||||||
|
while (remaining) {
|
||||||
|
if (remaining > ICNSS_GENL_DATA_LEN_MAX) {
|
||||||
|
data_len = ICNSS_GENL_DATA_LEN_MAX;
|
||||||
|
} else {
|
||||||
|
data_len = remaining;
|
||||||
|
end = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (retry = 0; retry < 2; retry++) {
|
||||||
|
ret = icnss_genl_send_data(type, file_name, total_size,
|
||||||
|
seg_id, end, data_len,
|
||||||
|
msg_buff);
|
||||||
|
if (ret >= 0)
|
||||||
|
break;
|
||||||
|
msleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
icnss_pr_err("fail to send genl data, ret %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
remaining -= data_len;
|
||||||
|
msg_buff += data_len;
|
||||||
|
seg_id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_genl_init(void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = genl_register_family(&icnss_genl_family);
|
||||||
|
if (ret != 0)
|
||||||
|
icnss_pr_err("genl_register_family fail: %d\n", ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void icnss_genl_exit(void)
|
||||||
|
{
|
||||||
|
genl_unregister_family(&icnss_genl_family);
|
||||||
|
}
|
17
icnss2/genl.h
Normal file
17
icnss2/genl.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */
|
||||||
|
|
||||||
|
#ifndef __ICNSS_GENL_H__
|
||||||
|
#define __ICNSS_GENL_H__
|
||||||
|
|
||||||
|
enum icnss_genl_msg_type {
|
||||||
|
ICNSS_GENL_MSG_TYPE_UNSPEC,
|
||||||
|
ICNSS_GENL_MSG_TYPE_QDSS,
|
||||||
|
};
|
||||||
|
|
||||||
|
int icnss_genl_init(void);
|
||||||
|
void icnss_genl_exit(void);
|
||||||
|
int icnss_genl_send_msg(void *buff, u8 type,
|
||||||
|
char *file_name, u32 total_size);
|
||||||
|
|
||||||
|
#endif
|
4559
icnss2/main.c
Normal file
4559
icnss2/main.c
Normal file
File diff suppressed because it is too large
Load Diff
512
icnss2/main.h
Normal file
512
icnss2/main.h
Normal file
@@ -0,0 +1,512 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2020, 2021, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MAIN_H__
|
||||||
|
#define __MAIN_H__
|
||||||
|
|
||||||
|
#include <linux/adc-tm-clients.h>
|
||||||
|
#include <linux/iio/consumer.h>
|
||||||
|
#include <linux/irqreturn.h>
|
||||||
|
#include <linux/kobject.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/ipc_logging.h>
|
||||||
|
#include <dt-bindings/iio/qcom,spmi-vadc.h>
|
||||||
|
#include <soc/qcom/icnss2.h>
|
||||||
|
#include "wlan_firmware_service_v01.h"
|
||||||
|
#include <linux/mailbox_client.h>
|
||||||
|
|
||||||
|
#define WCN6750_DEVICE_ID 0x6750
|
||||||
|
#define ADRASTEA_DEVICE_ID 0xabcd
|
||||||
|
#define QMI_WLFW_MAX_NUM_MEM_SEG 32
|
||||||
|
#define THERMAL_NAME_LENGTH 20
|
||||||
|
#define ICNSS_SMEM_VALUE_MASK 0xFFFFFFFF
|
||||||
|
#define ICNSS_SMEM_SEQ_NO_POS 16
|
||||||
|
#define QCA6750_PATH_PREFIX "qca6750/"
|
||||||
|
#define ICNSS_MAX_FILE_NAME 35
|
||||||
|
#define ICNSS_PCI_EP_WAKE_OFFSET 4
|
||||||
|
#define ICNSS_DISABLE_M3_SSR 0
|
||||||
|
#define ICNSS_ENABLE_M3_SSR 1
|
||||||
|
|
||||||
|
extern uint64_t dynamic_feature_mask;
|
||||||
|
|
||||||
|
enum icnss_bdf_type {
|
||||||
|
ICNSS_BDF_BIN,
|
||||||
|
ICNSS_BDF_ELF,
|
||||||
|
ICNSS_BDF_REGDB = 4,
|
||||||
|
ICNSS_BDF_DUMMY = 255,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_control_params {
|
||||||
|
unsigned long quirks;
|
||||||
|
unsigned int qmi_timeout;
|
||||||
|
unsigned int bdf_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum icnss_driver_event_type {
|
||||||
|
ICNSS_DRIVER_EVENT_SERVER_ARRIVE,
|
||||||
|
ICNSS_DRIVER_EVENT_SERVER_EXIT,
|
||||||
|
ICNSS_DRIVER_EVENT_FW_READY_IND,
|
||||||
|
ICNSS_DRIVER_EVENT_REGISTER_DRIVER,
|
||||||
|
ICNSS_DRIVER_EVENT_UNREGISTER_DRIVER,
|
||||||
|
ICNSS_DRIVER_EVENT_PD_SERVICE_DOWN,
|
||||||
|
ICNSS_DRIVER_EVENT_FW_EARLY_CRASH_IND,
|
||||||
|
ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN,
|
||||||
|
ICNSS_DRIVER_EVENT_IDLE_RESTART,
|
||||||
|
ICNSS_DRIVER_EVENT_FW_INIT_DONE_IND,
|
||||||
|
ICNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM,
|
||||||
|
ICNSS_DRIVER_EVENT_QDSS_TRACE_SAVE,
|
||||||
|
ICNSS_DRIVER_EVENT_QDSS_TRACE_FREE,
|
||||||
|
ICNSS_DRIVER_EVENT_M3_DUMP_UPLOAD_REQ,
|
||||||
|
ICNSS_DRIVER_EVENT_QDSS_TRACE_REQ_DATA,
|
||||||
|
ICNSS_DRIVER_EVENT_SUBSYS_RESTART_LEVEL,
|
||||||
|
ICNSS_DRIVER_EVENT_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum icnss_soc_wake_event_type {
|
||||||
|
ICNSS_SOC_WAKE_REQUEST_EVENT,
|
||||||
|
ICNSS_SOC_WAKE_RELEASE_EVENT,
|
||||||
|
ICNSS_SOC_WAKE_EVENT_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_event_server_arrive_data {
|
||||||
|
unsigned int node;
|
||||||
|
unsigned int port;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_event_pd_service_down_data {
|
||||||
|
bool crashed;
|
||||||
|
bool fw_rejuvenate;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_driver_event {
|
||||||
|
struct list_head list;
|
||||||
|
enum icnss_driver_event_type type;
|
||||||
|
bool sync;
|
||||||
|
struct completion complete;
|
||||||
|
int ret;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_soc_wake_event {
|
||||||
|
struct list_head list;
|
||||||
|
enum icnss_soc_wake_event_type type;
|
||||||
|
bool sync;
|
||||||
|
struct completion complete;
|
||||||
|
int ret;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum icnss_driver_state {
|
||||||
|
ICNSS_WLFW_CONNECTED,
|
||||||
|
ICNSS_POWER_ON,
|
||||||
|
ICNSS_FW_READY,
|
||||||
|
ICNSS_DRIVER_PROBED,
|
||||||
|
ICNSS_FW_TEST_MODE,
|
||||||
|
ICNSS_PM_SUSPEND,
|
||||||
|
ICNSS_PM_SUSPEND_NOIRQ,
|
||||||
|
ICNSS_SSR_REGISTERED,
|
||||||
|
ICNSS_PDR_REGISTERED,
|
||||||
|
ICNSS_PD_RESTART,
|
||||||
|
ICNSS_WLFW_EXISTS,
|
||||||
|
ICNSS_SHUTDOWN_DONE,
|
||||||
|
ICNSS_HOST_TRIGGERED_PDR,
|
||||||
|
ICNSS_FW_DOWN,
|
||||||
|
ICNSS_DRIVER_UNLOADING,
|
||||||
|
ICNSS_REJUVENATE,
|
||||||
|
ICNSS_MODE_ON,
|
||||||
|
ICNSS_BLOCK_SHUTDOWN,
|
||||||
|
ICNSS_PDR,
|
||||||
|
ICNSS_DEL_SERVER,
|
||||||
|
ICNSS_COLD_BOOT_CAL,
|
||||||
|
ICNSS_QMI_DMS_CONNECTED,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ce_irq_list {
|
||||||
|
int irq;
|
||||||
|
irqreturn_t (*handler)(int irq, void *priv);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_vreg_cfg {
|
||||||
|
const char *name;
|
||||||
|
u32 min_uv;
|
||||||
|
u32 max_uv;
|
||||||
|
u32 load_ua;
|
||||||
|
u32 delay_us;
|
||||||
|
u32 need_unvote;
|
||||||
|
bool required;
|
||||||
|
bool is_supported;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_vreg_info {
|
||||||
|
struct list_head list;
|
||||||
|
struct regulator *reg;
|
||||||
|
struct icnss_vreg_cfg cfg;
|
||||||
|
u32 enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_cpr_info {
|
||||||
|
const char *vreg_ol_cpr;
|
||||||
|
u32 voltage;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum icnss_vreg_type {
|
||||||
|
ICNSS_VREG_PRIM,
|
||||||
|
};
|
||||||
|
struct icnss_clk_cfg {
|
||||||
|
const char *name;
|
||||||
|
u32 freq;
|
||||||
|
u32 required;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_clk_info {
|
||||||
|
struct list_head list;
|
||||||
|
struct clk *clk;
|
||||||
|
struct icnss_clk_cfg cfg;
|
||||||
|
u32 enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_fw_mem {
|
||||||
|
size_t size;
|
||||||
|
void *va;
|
||||||
|
phys_addr_t pa;
|
||||||
|
u8 valid;
|
||||||
|
u32 type;
|
||||||
|
unsigned long attrs;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum icnss_smp2p_msg_id {
|
||||||
|
ICNSS_RESET_MSG,
|
||||||
|
ICNSS_POWER_SAVE_ENTER,
|
||||||
|
ICNSS_POWER_SAVE_EXIT,
|
||||||
|
ICNSS_TRIGGER_SSR,
|
||||||
|
ICNSS_SOC_WAKE_REQ,
|
||||||
|
ICNSS_SOC_WAKE_REL,
|
||||||
|
ICNSS_PCI_EP_POWER_SAVE_ENTER,
|
||||||
|
ICNSS_PCI_EP_POWER_SAVE_EXIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_subsys_restart_level_data {
|
||||||
|
uint8_t restart_level;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_stats {
|
||||||
|
struct {
|
||||||
|
uint32_t posted;
|
||||||
|
uint32_t processed;
|
||||||
|
} events[ICNSS_DRIVER_EVENT_MAX];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u32 posted;
|
||||||
|
u32 processed;
|
||||||
|
} soc_wake_events[ICNSS_SOC_WAKE_EVENT_MAX];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t request;
|
||||||
|
uint32_t free;
|
||||||
|
uint32_t enable;
|
||||||
|
uint32_t disable;
|
||||||
|
} ce_irqs[ICNSS_MAX_IRQ_REGISTRATIONS];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t pdr_fw_crash;
|
||||||
|
uint32_t pdr_host_error;
|
||||||
|
uint32_t root_pd_crash;
|
||||||
|
uint32_t root_pd_shutdown;
|
||||||
|
} recovery;
|
||||||
|
|
||||||
|
uint32_t pm_suspend;
|
||||||
|
uint32_t pm_suspend_err;
|
||||||
|
uint32_t pm_resume;
|
||||||
|
uint32_t pm_resume_err;
|
||||||
|
uint32_t pm_suspend_noirq;
|
||||||
|
uint32_t pm_suspend_noirq_err;
|
||||||
|
uint32_t pm_resume_noirq;
|
||||||
|
uint32_t pm_resume_noirq_err;
|
||||||
|
uint32_t pm_stay_awake;
|
||||||
|
uint32_t pm_relax;
|
||||||
|
|
||||||
|
uint32_t ind_register_req;
|
||||||
|
uint32_t ind_register_resp;
|
||||||
|
uint32_t ind_register_err;
|
||||||
|
uint32_t msa_info_req;
|
||||||
|
uint32_t msa_info_resp;
|
||||||
|
uint32_t msa_info_err;
|
||||||
|
uint32_t msa_ready_req;
|
||||||
|
uint32_t msa_ready_resp;
|
||||||
|
uint32_t msa_ready_err;
|
||||||
|
uint32_t msa_ready_ind;
|
||||||
|
uint32_t cap_req;
|
||||||
|
uint32_t cap_resp;
|
||||||
|
uint32_t cap_err;
|
||||||
|
uint32_t pin_connect_result;
|
||||||
|
uint32_t cfg_req;
|
||||||
|
uint32_t cfg_resp;
|
||||||
|
uint32_t cfg_req_err;
|
||||||
|
uint32_t mode_req;
|
||||||
|
uint32_t mode_resp;
|
||||||
|
uint32_t mode_req_err;
|
||||||
|
uint32_t ini_req;
|
||||||
|
uint32_t ini_resp;
|
||||||
|
uint32_t ini_req_err;
|
||||||
|
u32 rejuvenate_ind;
|
||||||
|
uint32_t rejuvenate_ack_req;
|
||||||
|
uint32_t rejuvenate_ack_resp;
|
||||||
|
uint32_t rejuvenate_ack_err;
|
||||||
|
uint32_t vbatt_req;
|
||||||
|
uint32_t vbatt_resp;
|
||||||
|
uint32_t vbatt_req_err;
|
||||||
|
uint32_t device_info_req;
|
||||||
|
uint32_t device_info_resp;
|
||||||
|
uint32_t device_info_err;
|
||||||
|
u32 exit_power_save_req;
|
||||||
|
u32 exit_power_save_resp;
|
||||||
|
u32 exit_power_save_err;
|
||||||
|
u32 enter_power_save_req;
|
||||||
|
u32 enter_power_save_resp;
|
||||||
|
u32 enter_power_save_err;
|
||||||
|
u32 soc_wake_req;
|
||||||
|
u32 soc_wake_resp;
|
||||||
|
u32 soc_wake_err;
|
||||||
|
u32 restart_level_req;
|
||||||
|
u32 restart_level_resp;
|
||||||
|
u32 restart_level_err;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define WLFW_MAX_TIMESTAMP_LEN 32
|
||||||
|
#define WLFW_MAX_BUILD_ID_LEN 128
|
||||||
|
#define WLFW_MAX_NUM_MEMORY_REGIONS 2
|
||||||
|
#define WLFW_FUNCTION_NAME_LEN 129
|
||||||
|
#define WLFW_MAX_DATA_SIZE 6144
|
||||||
|
#define WLFW_MAX_STR_LEN 16
|
||||||
|
#define WLFW_MAX_NUM_CE 12
|
||||||
|
#define WLFW_MAX_NUM_SVC 24
|
||||||
|
#define WLFW_MAX_NUM_SHADOW_REG 24
|
||||||
|
#define WLFW_MAX_HANG_EVENT_DATA_SIZE 400
|
||||||
|
|
||||||
|
struct wlfw_rf_chip_info {
|
||||||
|
uint32_t chip_id;
|
||||||
|
uint32_t chip_family;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlfw_rf_board_info {
|
||||||
|
uint32_t board_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlfw_fw_version_info {
|
||||||
|
uint32_t fw_version;
|
||||||
|
char fw_build_timestamp[WLFW_MAX_TIMESTAMP_LEN + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_mem_region_info {
|
||||||
|
uint64_t reg_addr;
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t secure_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_msi_user {
|
||||||
|
char *name;
|
||||||
|
int num_vectors;
|
||||||
|
u32 base_vector;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_msi_config {
|
||||||
|
int total_vectors;
|
||||||
|
int total_users;
|
||||||
|
struct icnss_msi_user *users;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_thermal_cdev {
|
||||||
|
struct list_head tcdev_list;
|
||||||
|
int tcdev_id;
|
||||||
|
unsigned long curr_thermal_state;
|
||||||
|
unsigned long max_thermal_state;
|
||||||
|
struct device_node *dev_node;
|
||||||
|
struct thermal_cooling_device *tcdev;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum smp2p_out_entry {
|
||||||
|
ICNSS_SMP2P_OUT_POWER_SAVE,
|
||||||
|
ICNSS_SMP2P_OUT_SOC_WAKE,
|
||||||
|
ICNSS_SMP2P_OUT_EP_POWER_SAVE,
|
||||||
|
ICNSS_SMP2P_OUT_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const icnss_smp2p_str[] = {
|
||||||
|
[ICNSS_SMP2P_OUT_POWER_SAVE] = "wlan-smp2p-out",
|
||||||
|
[ICNSS_SMP2P_OUT_SOC_WAKE] = "wlan-soc-wake-smp2p-out",
|
||||||
|
[ICNSS_SMP2P_OUT_EP_POWER_SAVE] = "wlan-ep-powersave-smp2p-out",
|
||||||
|
};
|
||||||
|
|
||||||
|
struct smp2p_out_info {
|
||||||
|
unsigned short seq;
|
||||||
|
unsigned int smem_bit;
|
||||||
|
struct qcom_smem_state *smem_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_dms_data {
|
||||||
|
u8 mac_valid;
|
||||||
|
u8 nv_mac_not_prov;
|
||||||
|
u8 mac[QMI_WLFW_MAC_ADDR_SIZE_V01];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_ramdump_info {
|
||||||
|
int minor;
|
||||||
|
char name[32];
|
||||||
|
struct device *dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_priv {
|
||||||
|
uint32_t magic;
|
||||||
|
struct platform_device *pdev;
|
||||||
|
struct icnss_driver_ops *ops;
|
||||||
|
struct ce_irq_list ce_irq_list[ICNSS_MAX_IRQ_REGISTRATIONS];
|
||||||
|
struct list_head vreg_list;
|
||||||
|
struct list_head clk_list;
|
||||||
|
struct icnss_cpr_info cpr_info;
|
||||||
|
unsigned long device_id;
|
||||||
|
struct icnss_msi_config *msi_config;
|
||||||
|
u32 msi_base_data;
|
||||||
|
struct icnss_control_params ctrl_params;
|
||||||
|
u8 cal_done;
|
||||||
|
u8 use_prefix_path;
|
||||||
|
u32 ce_irqs[ICNSS_MAX_IRQ_REGISTRATIONS];
|
||||||
|
u32 srng_irqs[IWCN_MAX_IRQ_REGISTRATIONS];
|
||||||
|
phys_addr_t mem_base_pa;
|
||||||
|
void __iomem *mem_base_va;
|
||||||
|
u32 mem_base_size;
|
||||||
|
phys_addr_t mhi_state_info_pa;
|
||||||
|
void __iomem *mhi_state_info_va;
|
||||||
|
u32 mhi_state_info_size;
|
||||||
|
struct iommu_domain *iommu_domain;
|
||||||
|
dma_addr_t smmu_iova_start;
|
||||||
|
size_t smmu_iova_len;
|
||||||
|
dma_addr_t smmu_iova_ipa_start;
|
||||||
|
dma_addr_t smmu_iova_ipa_current;
|
||||||
|
size_t smmu_iova_ipa_len;
|
||||||
|
struct qmi_handle qmi;
|
||||||
|
struct qmi_handle qmi_dms;
|
||||||
|
struct list_head event_list;
|
||||||
|
struct list_head soc_wake_msg_list;
|
||||||
|
spinlock_t event_lock;
|
||||||
|
spinlock_t soc_wake_msg_lock;
|
||||||
|
struct work_struct event_work;
|
||||||
|
struct work_struct fw_recv_msg_work;
|
||||||
|
struct work_struct soc_wake_msg_work;
|
||||||
|
struct workqueue_struct *event_wq;
|
||||||
|
struct workqueue_struct *soc_wake_wq;
|
||||||
|
phys_addr_t msa_pa;
|
||||||
|
phys_addr_t msi_addr_pa;
|
||||||
|
dma_addr_t msi_addr_iova;
|
||||||
|
uint32_t msa_mem_size;
|
||||||
|
void *msa_va;
|
||||||
|
unsigned long state;
|
||||||
|
struct wlfw_rf_chip_info chip_info;
|
||||||
|
uint32_t board_id;
|
||||||
|
uint32_t soc_id;
|
||||||
|
struct wlfw_fw_version_info fw_version_info;
|
||||||
|
char fw_build_id[WLFW_MAX_BUILD_ID_LEN + 1];
|
||||||
|
u32 pwr_pin_result;
|
||||||
|
u32 phy_io_pin_result;
|
||||||
|
u32 rf_pin_result;
|
||||||
|
uint32_t nr_mem_region;
|
||||||
|
struct icnss_mem_region_info
|
||||||
|
mem_region[WLFW_MAX_NUM_MEMORY_REGIONS];
|
||||||
|
struct dentry *root_dentry;
|
||||||
|
spinlock_t on_off_lock;
|
||||||
|
struct icnss_stats stats;
|
||||||
|
void *modem_notify_handler;
|
||||||
|
void *wpss_notify_handler;
|
||||||
|
struct notifier_block modem_ssr_nb;
|
||||||
|
struct notifier_block wpss_ssr_nb;
|
||||||
|
uint32_t diag_reg_read_addr;
|
||||||
|
uint32_t diag_reg_read_mem_type;
|
||||||
|
uint32_t diag_reg_read_len;
|
||||||
|
uint8_t *diag_reg_read_buf;
|
||||||
|
atomic_t pm_count;
|
||||||
|
struct icnss_ramdump_info *msa0_dump_dev;
|
||||||
|
struct icnss_ramdump_info *m3_dump_phyareg;
|
||||||
|
struct icnss_ramdump_info *m3_dump_phydbg;
|
||||||
|
struct icnss_ramdump_info *m3_dump_wmac0reg;
|
||||||
|
struct icnss_ramdump_info *m3_dump_wcssdbg;
|
||||||
|
struct icnss_ramdump_info *m3_dump_phyapdmem;
|
||||||
|
bool force_err_fatal;
|
||||||
|
bool allow_recursive_recovery;
|
||||||
|
bool early_crash_ind;
|
||||||
|
u8 cause_for_rejuvenation;
|
||||||
|
u8 requesting_sub_system;
|
||||||
|
u16 line_number;
|
||||||
|
struct mutex dev_lock;
|
||||||
|
uint32_t fw_error_fatal_irq;
|
||||||
|
uint32_t fw_early_crash_irq;
|
||||||
|
struct smp2p_out_info smp2p_info[ICNSS_SMP2P_OUT_MAX];
|
||||||
|
struct completion unblock_shutdown;
|
||||||
|
struct adc_tm_param vph_monitor_params;
|
||||||
|
struct adc_tm_chip *adc_tm_dev;
|
||||||
|
struct iio_channel *channel;
|
||||||
|
uint64_t vph_pwr;
|
||||||
|
bool vbatt_supported;
|
||||||
|
char function_name[WLFW_FUNCTION_NAME_LEN + 1];
|
||||||
|
bool is_ssr;
|
||||||
|
bool smmu_s1_enable;
|
||||||
|
struct kobject *icnss_kobject;
|
||||||
|
struct rproc *rproc;
|
||||||
|
atomic_t is_shutdown;
|
||||||
|
u32 qdss_mem_seg_len;
|
||||||
|
struct icnss_fw_mem qdss_mem[QMI_WLFW_MAX_NUM_MEM_SEG];
|
||||||
|
void *get_info_cb_ctx;
|
||||||
|
int (*get_info_cb)(void *ctx, void *event, int event_len);
|
||||||
|
atomic_t soc_wake_ref_count;
|
||||||
|
phys_addr_t hang_event_data_pa;
|
||||||
|
void __iomem *hang_event_data_va;
|
||||||
|
uint16_t hang_event_data_len;
|
||||||
|
void *hang_event_data;
|
||||||
|
struct list_head icnss_tcdev_list;
|
||||||
|
struct mutex tcdev_lock;
|
||||||
|
bool is_chain1_supported;
|
||||||
|
bool chain_reg_info_updated;
|
||||||
|
u32 hw_trc_override;
|
||||||
|
struct icnss_dms_data dms;
|
||||||
|
u8 use_nv_mac;
|
||||||
|
struct pdr_handle *pdr_handle;
|
||||||
|
struct pdr_service *pdr_service;
|
||||||
|
bool root_pd_shutdown;
|
||||||
|
struct mbox_client mbox_client_data;
|
||||||
|
struct mbox_chan *mbox_chan;
|
||||||
|
u32 wlan_en_delay_ms;
|
||||||
|
struct class *icnss_ramdump_class;
|
||||||
|
dev_t icnss_ramdump_dev;
|
||||||
|
struct completion smp2p_soc_wake_wait;
|
||||||
|
uint32_t fw_soc_wake_ack_irq;
|
||||||
|
char foundry_name;
|
||||||
|
bool bdf_download_support;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_reg_info {
|
||||||
|
uint32_t mem_type;
|
||||||
|
uint32_t reg_offset;
|
||||||
|
uint32_t data_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
void icnss_free_qdss_mem(struct icnss_priv *priv);
|
||||||
|
char *icnss_driver_event_to_str(enum icnss_driver_event_type type);
|
||||||
|
int icnss_call_driver_uevent(struct icnss_priv *priv,
|
||||||
|
enum icnss_uevent uevent, void *data);
|
||||||
|
int icnss_driver_event_post(struct icnss_priv *priv,
|
||||||
|
enum icnss_driver_event_type type,
|
||||||
|
u32 flags, void *data);
|
||||||
|
void icnss_allow_recursive_recovery(struct device *dev);
|
||||||
|
void icnss_disallow_recursive_recovery(struct device *dev);
|
||||||
|
char *icnss_soc_wake_event_to_str(enum icnss_soc_wake_event_type type);
|
||||||
|
int icnss_soc_wake_event_post(struct icnss_priv *priv,
|
||||||
|
enum icnss_soc_wake_event_type type,
|
||||||
|
u32 flags, void *data);
|
||||||
|
int icnss_get_iova(struct icnss_priv *priv, u64 *addr, u64 *size);
|
||||||
|
int icnss_get_iova_ipa(struct icnss_priv *priv, u64 *addr, u64 *size);
|
||||||
|
int icnss_update_cpr_info(struct icnss_priv *priv);
|
||||||
|
void icnss_add_fw_prefix_name(struct icnss_priv *priv, char *prefix_name,
|
||||||
|
char *name);
|
||||||
|
int icnss_aop_mbox_init(struct icnss_priv *priv);
|
||||||
|
#endif
|
||||||
|
|
942
icnss2/power.c
Normal file
942
icnss2/power.c
Normal file
@@ -0,0 +1,942 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#if IS_ENABLED(CONFIG_MSM_QMP)
|
||||||
|
#include <linux/mailbox/qmp.h>
|
||||||
|
#endif
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/pinctrl/consumer.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
|
#include <soc/qcom/cmd-db.h>
|
||||||
|
#include "main.h"
|
||||||
|
#include "qmi.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "power.h"
|
||||||
|
|
||||||
|
static struct icnss_vreg_cfg icnss_wcn6750_vreg_list[] = {
|
||||||
|
{"vdd-cx-mx", 824000, 952000, 0, 0, 0, false, true},
|
||||||
|
{"vdd-1.8-xo", 1872000, 1872000, 0, 0, 0, false, true},
|
||||||
|
{"vdd-1.3-rfa", 1256000, 1352000, 0, 0, 0, false, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct icnss_vreg_cfg icnss_adrestea_vreg_list[] = {
|
||||||
|
{"vdd-cx-mx", 752000, 752000, 0, 0, 0, false, true},
|
||||||
|
{"vdd-1.8-xo", 1800000, 1800000, 0, 0, 0, false, true},
|
||||||
|
{"vdd-1.3-rfa", 1304000, 1304000, 0, 0, 0, false, true},
|
||||||
|
{"vdd-3.3-ch1", 3312000, 3312000, 0, 0, 0, false, true},
|
||||||
|
{"vdd-3.3-ch0", 3312000, 3312000, 0, 0, 0, false, true},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct icnss_clk_cfg icnss_clk_list[] = {
|
||||||
|
{"rf_clk", 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct icnss_clk_cfg icnss_adrestea_clk_list[] = {
|
||||||
|
{"cxo_ref_clk_pin", 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ICNSS_VREG_LIST_SIZE ARRAY_SIZE(icnss_wcn6750_vreg_list)
|
||||||
|
#define ICNSS_VREG_ADRESTEA_LIST_SIZE ARRAY_SIZE(icnss_adrestea_vreg_list)
|
||||||
|
#define ICNSS_CLK_LIST_SIZE ARRAY_SIZE(icnss_clk_list)
|
||||||
|
#define ICNSS_CLK_ADRESTEA_LIST_SIZE ARRAY_SIZE(icnss_adrestea_clk_list)
|
||||||
|
|
||||||
|
#define ICNSS_CHAIN1_REGULATOR "vdd-3.3-ch1"
|
||||||
|
#define MAX_PROP_SIZE 32
|
||||||
|
#define ICNSS_THRESHOLD_HIGH 3600000
|
||||||
|
#define ICNSS_THRESHOLD_LOW 3450000
|
||||||
|
#define ICNSS_THRESHOLD_GUARD 20000
|
||||||
|
|
||||||
|
#define BT_CXMX_VOLTAGE_MV 950
|
||||||
|
#define ICNSS_MBOX_MSG_MAX_LEN 64
|
||||||
|
#define ICNSS_MBOX_TIMEOUT_MS 1000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum icnss_vreg_param: Voltage regulator TCS param
|
||||||
|
* @ICNSS_VREG_VOLTAGE: Provides voltage level to be configured in TCS
|
||||||
|
* @ICNSS_VREG_MODE: Regulator mode
|
||||||
|
* @ICNSS_VREG_ENABLE: Set Voltage regulator enable config in TCS
|
||||||
|
*/
|
||||||
|
enum icnss_vreg_param {
|
||||||
|
ICNSS_VREG_VOLTAGE,
|
||||||
|
ICNSS_VREG_MODE,
|
||||||
|
ICNSS_VREG_ENABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum icnss_tcs_seq: TCS sequence ID for trigger
|
||||||
|
* ICNSS_TCS_UP_SEQ: TCS Sequence based on up trigger / Wake TCS
|
||||||
|
* ICNSS_TCS_DOWN_SEQ: TCS Sequence based on down trigger / Sleep TCS
|
||||||
|
* ICNSS_TCS_ALL_SEQ: Update for both up and down triggers
|
||||||
|
*/
|
||||||
|
enum icnss_tcs_seq {
|
||||||
|
ICNSS_TCS_UP_SEQ,
|
||||||
|
ICNSS_TCS_DOWN_SEQ,
|
||||||
|
ICNSS_TCS_ALL_SEQ,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int icnss_get_vreg_single(struct icnss_priv *priv,
|
||||||
|
struct icnss_vreg_info *vreg)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct device *dev = NULL;
|
||||||
|
struct regulator *reg = NULL;
|
||||||
|
const __be32 *prop = NULL;
|
||||||
|
char prop_name[MAX_PROP_SIZE] = {0};
|
||||||
|
int len = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dev = &priv->pdev->dev;
|
||||||
|
|
||||||
|
reg = devm_regulator_get_optional(dev, vreg->cfg.name);
|
||||||
|
if (IS_ERR(reg)) {
|
||||||
|
ret = PTR_ERR(reg);
|
||||||
|
if (ret == -ENODEV) {
|
||||||
|
return ret;
|
||||||
|
} else if (ret == -EPROBE_DEFER) {
|
||||||
|
icnss_pr_info("EPROBE_DEFER for regulator: %s\n",
|
||||||
|
vreg->cfg.name);
|
||||||
|
goto out;
|
||||||
|
} else if (priv->device_id == ADRASTEA_DEVICE_ID) {
|
||||||
|
if (vreg->cfg.required) {
|
||||||
|
icnss_pr_err("Regulator %s doesn't exist: %d\n",
|
||||||
|
vreg->cfg.name, ret);
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
|
icnss_pr_dbg("Optional regulator %s doesn't exist: %d\n",
|
||||||
|
vreg->cfg.name, ret);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
icnss_pr_err("Failed to get regulator %s, err = %d\n",
|
||||||
|
vreg->cfg.name, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vreg->reg = reg;
|
||||||
|
|
||||||
|
snprintf(prop_name, MAX_PROP_SIZE, "qcom,%s-config",
|
||||||
|
vreg->cfg.name);
|
||||||
|
|
||||||
|
prop = of_get_property(dev->of_node, prop_name, &len);
|
||||||
|
|
||||||
|
icnss_pr_dbg("Got regulator config, prop: %s, len: %d\n",
|
||||||
|
prop_name, len);
|
||||||
|
|
||||||
|
if (!prop || len < (2 * sizeof(__be32))) {
|
||||||
|
icnss_pr_dbg("Property %s %s, use default\n", prop_name,
|
||||||
|
prop ? "invalid format" : "doesn't exist");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; (i * sizeof(__be32)) < len; i++) {
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
vreg->cfg.min_uv = be32_to_cpup(&prop[0]);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
vreg->cfg.max_uv = be32_to_cpup(&prop[1]);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
vreg->cfg.load_ua = be32_to_cpup(&prop[2]);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
vreg->cfg.delay_us = be32_to_cpup(&prop[3]);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (priv->device_id == WCN6750_DEVICE_ID)
|
||||||
|
vreg->cfg.need_unvote = be32_to_cpup(&prop[4]);
|
||||||
|
else
|
||||||
|
vreg->cfg.need_unvote = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
icnss_pr_dbg("Property %s, ignoring value at %d\n",
|
||||||
|
prop_name, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
icnss_pr_dbg("Got regulator: %s, min_uv: %u, max_uv: %u, load_ua: %u, delay_us: %u, need_unvote: %u\n",
|
||||||
|
vreg->cfg.name, vreg->cfg.min_uv,
|
||||||
|
vreg->cfg.max_uv, vreg->cfg.load_ua,
|
||||||
|
vreg->cfg.delay_us, vreg->cfg.need_unvote);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_vreg_on_single(struct icnss_vreg_info *vreg)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (vreg->enabled) {
|
||||||
|
icnss_pr_dbg("Regulator %s is already enabled\n",
|
||||||
|
vreg->cfg.name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
icnss_pr_dbg("Regulator %s is being enabled\n", vreg->cfg.name);
|
||||||
|
|
||||||
|
if (vreg->cfg.min_uv != 0 && vreg->cfg.max_uv != 0) {
|
||||||
|
ret = regulator_set_voltage(vreg->reg,
|
||||||
|
vreg->cfg.min_uv,
|
||||||
|
vreg->cfg.max_uv);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
icnss_pr_err("Failed to set voltage for regulator %s, min_uv: %u, max_uv: %u, err = %d\n",
|
||||||
|
vreg->cfg.name, vreg->cfg.min_uv,
|
||||||
|
vreg->cfg.max_uv, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vreg->cfg.load_ua) {
|
||||||
|
ret = regulator_set_load(vreg->reg,
|
||||||
|
vreg->cfg.load_ua);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
icnss_pr_err("Failed to set load for regulator %s, load: %u, err = %d\n",
|
||||||
|
vreg->cfg.name, vreg->cfg.load_ua,
|
||||||
|
ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vreg->cfg.delay_us)
|
||||||
|
udelay(vreg->cfg.delay_us);
|
||||||
|
|
||||||
|
ret = regulator_enable(vreg->reg);
|
||||||
|
if (ret) {
|
||||||
|
icnss_pr_err("Failed to enable regulator %s, err = %d\n",
|
||||||
|
vreg->cfg.name, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
vreg->enabled = true;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_vreg_unvote_single(struct icnss_vreg_info *vreg)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!vreg->enabled) {
|
||||||
|
icnss_pr_dbg("Regulator %s is already disabled\n",
|
||||||
|
vreg->cfg.name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
icnss_pr_dbg("Removing vote for Regulator %s\n", vreg->cfg.name);
|
||||||
|
|
||||||
|
if (vreg->cfg.load_ua) {
|
||||||
|
ret = regulator_set_load(vreg->reg, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
icnss_pr_err("Failed to set load for regulator %s, err = %d\n",
|
||||||
|
vreg->cfg.name, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vreg->cfg.min_uv != 0 && vreg->cfg.max_uv != 0) {
|
||||||
|
ret = regulator_set_voltage(vreg->reg, 0,
|
||||||
|
vreg->cfg.max_uv);
|
||||||
|
if (ret)
|
||||||
|
icnss_pr_err("Failed to set voltage for regulator %s, err = %d\n",
|
||||||
|
vreg->cfg.name, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_vreg_off_single(struct icnss_vreg_info *vreg)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!vreg->enabled) {
|
||||||
|
icnss_pr_dbg("Regulator %s is already disabled\n",
|
||||||
|
vreg->cfg.name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
icnss_pr_dbg("Regulator %s is being disabled\n",
|
||||||
|
vreg->cfg.name);
|
||||||
|
|
||||||
|
ret = regulator_disable(vreg->reg);
|
||||||
|
if (ret)
|
||||||
|
icnss_pr_err("Failed to disable regulator %s, err = %d\n",
|
||||||
|
vreg->cfg.name, ret);
|
||||||
|
|
||||||
|
if (vreg->cfg.load_ua) {
|
||||||
|
ret = regulator_set_load(vreg->reg, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
icnss_pr_err("Failed to set load for regulator %s, err = %d\n",
|
||||||
|
vreg->cfg.name, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vreg->cfg.min_uv != 0 && vreg->cfg.max_uv != 0) {
|
||||||
|
ret = regulator_set_voltage(vreg->reg, 0,
|
||||||
|
vreg->cfg.max_uv);
|
||||||
|
if (ret)
|
||||||
|
icnss_pr_err("Failed to set voltage for regulator %s, err = %d\n",
|
||||||
|
vreg->cfg.name, ret);
|
||||||
|
}
|
||||||
|
vreg->enabled = false;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct icnss_vreg_cfg *get_vreg_list(u32 *vreg_list_size,
|
||||||
|
unsigned long device_id)
|
||||||
|
{
|
||||||
|
switch (device_id) {
|
||||||
|
case WCN6750_DEVICE_ID:
|
||||||
|
*vreg_list_size = ICNSS_VREG_LIST_SIZE;
|
||||||
|
return icnss_wcn6750_vreg_list;
|
||||||
|
|
||||||
|
case ADRASTEA_DEVICE_ID:
|
||||||
|
*vreg_list_size = ICNSS_VREG_ADRESTEA_LIST_SIZE;
|
||||||
|
return icnss_adrestea_vreg_list;
|
||||||
|
|
||||||
|
default:
|
||||||
|
icnss_pr_err("Unsupported device_id 0x%x\n", device_id);
|
||||||
|
*vreg_list_size = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_get_vreg(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int i;
|
||||||
|
struct icnss_vreg_info *vreg;
|
||||||
|
struct icnss_vreg_cfg *vreg_cfg = NULL;
|
||||||
|
struct list_head *vreg_list = &priv->vreg_list;
|
||||||
|
struct device *dev = &priv->pdev->dev;
|
||||||
|
u32 vreg_list_size = 0;
|
||||||
|
|
||||||
|
vreg_cfg = get_vreg_list(&vreg_list_size, priv->device_id);
|
||||||
|
if (!vreg_cfg)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (i = 0; i < vreg_list_size; i++) {
|
||||||
|
vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL);
|
||||||
|
if (!vreg)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
memcpy(&vreg->cfg, &vreg_cfg[i], sizeof(vreg->cfg));
|
||||||
|
ret = icnss_get_vreg_single(priv, vreg);
|
||||||
|
if (ret != 0) {
|
||||||
|
if (ret == -ENODEV)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
list_add_tail(&vreg->list, vreg_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void icnss_put_vreg(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
struct list_head *vreg_list = &priv->vreg_list;
|
||||||
|
struct icnss_vreg_info *vreg = NULL;
|
||||||
|
|
||||||
|
while (!list_empty(vreg_list)) {
|
||||||
|
vreg = list_first_entry(vreg_list,
|
||||||
|
struct icnss_vreg_info, list);
|
||||||
|
list_del(&vreg->list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_vreg_on(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
struct list_head *vreg_list = &priv->vreg_list;
|
||||||
|
struct icnss_vreg_info *vreg = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
list_for_each_entry(vreg, vreg_list, list) {
|
||||||
|
if (IS_ERR_OR_NULL(vreg->reg) || !vreg->cfg.is_supported)
|
||||||
|
continue;
|
||||||
|
if (!priv->chain_reg_info_updated &&
|
||||||
|
!strcmp(ICNSS_CHAIN1_REGULATOR, vreg->cfg.name)) {
|
||||||
|
priv->chain_reg_info_updated = true;
|
||||||
|
if (!priv->is_chain1_supported) {
|
||||||
|
vreg->cfg.is_supported = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = icnss_vreg_on_single(vreg);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
list_for_each_entry_continue_reverse(vreg, vreg_list, list) {
|
||||||
|
if (IS_ERR_OR_NULL(vreg->reg) || !vreg->enabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
icnss_vreg_off_single(vreg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_vreg_off(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
struct list_head *vreg_list = &priv->vreg_list;
|
||||||
|
struct icnss_vreg_info *vreg = NULL;
|
||||||
|
|
||||||
|
list_for_each_entry_reverse(vreg, vreg_list, list) {
|
||||||
|
if (IS_ERR_OR_NULL(vreg->reg))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
icnss_vreg_off_single(vreg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_vreg_unvote(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
struct list_head *vreg_list = &priv->vreg_list;
|
||||||
|
struct icnss_vreg_info *vreg = NULL;
|
||||||
|
|
||||||
|
list_for_each_entry_reverse(vreg, vreg_list, list) {
|
||||||
|
if (IS_ERR_OR_NULL(vreg->reg))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (vreg->cfg.need_unvote)
|
||||||
|
icnss_vreg_unvote_single(vreg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_get_clk_single(struct icnss_priv *priv,
|
||||||
|
struct icnss_clk_info *clk_info)
|
||||||
|
{
|
||||||
|
struct device *dev = &priv->pdev->dev;
|
||||||
|
struct clk *clk;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
clk = devm_clk_get(dev, clk_info->cfg.name);
|
||||||
|
if (IS_ERR(clk)) {
|
||||||
|
ret = PTR_ERR(clk);
|
||||||
|
if (clk_info->cfg.required)
|
||||||
|
icnss_pr_err("Failed to get clock %s, err = %d\n",
|
||||||
|
clk_info->cfg.name, ret);
|
||||||
|
else
|
||||||
|
icnss_pr_dbg("Failed to get optional clock %s, err = %d\n",
|
||||||
|
clk_info->cfg.name, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_info->clk = clk;
|
||||||
|
icnss_pr_dbg("Got clock: %s, freq: %u\n",
|
||||||
|
clk_info->cfg.name, clk_info->cfg.freq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_clk_on_single(struct icnss_clk_info *clk_info)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (clk_info->enabled) {
|
||||||
|
icnss_pr_dbg("Clock %s is already enabled\n",
|
||||||
|
clk_info->cfg.name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
icnss_pr_dbg("Clock %s is being enabled\n", clk_info->cfg.name);
|
||||||
|
|
||||||
|
if (clk_info->cfg.freq) {
|
||||||
|
ret = clk_set_rate(clk_info->clk, clk_info->cfg.freq);
|
||||||
|
if (ret) {
|
||||||
|
icnss_pr_err("Failed to set frequency %u for clock %s, err = %d\n",
|
||||||
|
clk_info->cfg.freq, clk_info->cfg.name,
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(clk_info->clk);
|
||||||
|
if (ret) {
|
||||||
|
icnss_pr_err("Failed to enable clock %s, err = %d\n",
|
||||||
|
clk_info->cfg.name, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_info->enabled = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_clk_off_single(struct icnss_clk_info *clk_info)
|
||||||
|
{
|
||||||
|
if (!clk_info->enabled) {
|
||||||
|
icnss_pr_dbg("Clock %s is already disabled\n",
|
||||||
|
clk_info->cfg.name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
icnss_pr_dbg("Clock %s is being disabled\n", clk_info->cfg.name);
|
||||||
|
|
||||||
|
clk_disable_unprepare(clk_info->clk);
|
||||||
|
clk_info->enabled = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_get_clk(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
struct device *dev;
|
||||||
|
struct list_head *clk_list;
|
||||||
|
struct icnss_clk_info *clk_info;
|
||||||
|
struct icnss_clk_cfg *clk_cfg;
|
||||||
|
int ret, i;
|
||||||
|
u32 clk_list_size = 0;
|
||||||
|
|
||||||
|
if (!priv)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
dev = &priv->pdev->dev;
|
||||||
|
clk_list = &priv->clk_list;
|
||||||
|
|
||||||
|
if (priv->device_id == ADRASTEA_DEVICE_ID) {
|
||||||
|
clk_cfg = icnss_adrestea_clk_list;
|
||||||
|
clk_list_size = ICNSS_CLK_ADRESTEA_LIST_SIZE;
|
||||||
|
} else if (priv->device_id == WCN6750_DEVICE_ID) {
|
||||||
|
clk_cfg = icnss_clk_list;
|
||||||
|
clk_list_size = ICNSS_CLK_LIST_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!list_empty(clk_list)) {
|
||||||
|
icnss_pr_dbg("Clocks have already been updated\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < clk_list_size; i++) {
|
||||||
|
clk_info = devm_kzalloc(dev, sizeof(*clk_info), GFP_KERNEL);
|
||||||
|
if (!clk_info) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&clk_info->cfg, &clk_cfg[i],
|
||||||
|
sizeof(clk_info->cfg));
|
||||||
|
ret = icnss_get_clk_single(priv, clk_info);
|
||||||
|
if (ret != 0) {
|
||||||
|
if (clk_info->cfg.required)
|
||||||
|
goto cleanup;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list_add_tail(&clk_info->list, clk_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
while (!list_empty(clk_list)) {
|
||||||
|
clk_info = list_first_entry(clk_list, struct icnss_clk_info,
|
||||||
|
list);
|
||||||
|
list_del(&clk_info->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void icnss_put_clk(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
struct device *dev;
|
||||||
|
struct list_head *clk_list;
|
||||||
|
struct icnss_clk_info *clk_info;
|
||||||
|
|
||||||
|
if (!priv)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dev = &priv->pdev->dev;
|
||||||
|
clk_list = &priv->clk_list;
|
||||||
|
|
||||||
|
while (!list_empty(clk_list)) {
|
||||||
|
clk_info = list_first_entry(clk_list, struct icnss_clk_info,
|
||||||
|
list);
|
||||||
|
list_del(&clk_info->list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_clk_on(struct list_head *clk_list)
|
||||||
|
{
|
||||||
|
struct icnss_clk_info *clk_info;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
list_for_each_entry(clk_info, clk_list, list) {
|
||||||
|
if (IS_ERR_OR_NULL(clk_info->clk))
|
||||||
|
continue;
|
||||||
|
ret = icnss_clk_on_single(clk_info);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
list_for_each_entry_continue_reverse(clk_info, clk_list, list) {
|
||||||
|
if (IS_ERR_OR_NULL(clk_info->clk))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
icnss_clk_off_single(clk_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_clk_off(struct list_head *clk_list)
|
||||||
|
{
|
||||||
|
struct icnss_clk_info *clk_info;
|
||||||
|
|
||||||
|
list_for_each_entry_reverse(clk_info, clk_list, list) {
|
||||||
|
if (IS_ERR_OR_NULL(clk_info->clk))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
icnss_clk_off_single(clk_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_hw_power_on(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
icnss_pr_dbg("HW Power on: state: 0x%lx\n", priv->state);
|
||||||
|
|
||||||
|
spin_lock(&priv->on_off_lock);
|
||||||
|
if (test_bit(ICNSS_POWER_ON, &priv->state)) {
|
||||||
|
spin_unlock(&priv->on_off_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
set_bit(ICNSS_POWER_ON, &priv->state);
|
||||||
|
spin_unlock(&priv->on_off_lock);
|
||||||
|
|
||||||
|
ret = icnss_vreg_on(priv);
|
||||||
|
if (ret) {
|
||||||
|
icnss_pr_err("Failed to turn on vreg, err = %d\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = icnss_clk_on(&priv->clk_list);
|
||||||
|
if (ret)
|
||||||
|
goto vreg_off;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
vreg_off:
|
||||||
|
icnss_vreg_off(priv);
|
||||||
|
out:
|
||||||
|
clear_bit(ICNSS_POWER_ON, &priv->state);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_hw_power_off(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (test_bit(HW_ALWAYS_ON, &priv->ctrl_params.quirks))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (test_bit(ICNSS_FW_DOWN, &priv->state))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
icnss_pr_dbg("HW Power off: 0x%lx\n", priv->state);
|
||||||
|
|
||||||
|
spin_lock(&priv->on_off_lock);
|
||||||
|
if (!test_bit(ICNSS_POWER_ON, &priv->state)) {
|
||||||
|
spin_unlock(&priv->on_off_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
clear_bit(ICNSS_POWER_ON, &priv->state);
|
||||||
|
spin_unlock(&priv->on_off_lock);
|
||||||
|
|
||||||
|
icnss_clk_off(&priv->clk_list);
|
||||||
|
|
||||||
|
ret = icnss_vreg_off(priv);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_power_on(struct device *dev)
|
||||||
|
{
|
||||||
|
struct icnss_priv *priv = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (!priv) {
|
||||||
|
icnss_pr_err("Invalid drvdata: dev %pK, data %pK\n",
|
||||||
|
dev, priv);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
icnss_pr_dbg("Power On: 0x%lx\n", priv->state);
|
||||||
|
|
||||||
|
return icnss_hw_power_on(priv);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(icnss_power_on);
|
||||||
|
|
||||||
|
int icnss_power_off(struct device *dev)
|
||||||
|
{
|
||||||
|
struct icnss_priv *priv = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (!priv) {
|
||||||
|
icnss_pr_err("Invalid drvdata: dev %pK, data %pK\n",
|
||||||
|
dev, priv);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
icnss_pr_dbg("Power Off: 0x%lx\n", priv->state);
|
||||||
|
|
||||||
|
return icnss_hw_power_off(priv);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(icnss_power_off);
|
||||||
|
|
||||||
|
void icnss_put_resources(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
icnss_put_clk(priv);
|
||||||
|
icnss_put_vreg(priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_get_phone_power(struct icnss_priv *priv, uint64_t *result_uv)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (!priv->channel) {
|
||||||
|
icnss_pr_err("Channel doesn't exists\n");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = iio_read_channel_processed(priv->channel, &result);
|
||||||
|
if (ret < 0) {
|
||||||
|
icnss_pr_err("Error reading channel, ret = %d\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result_uv = (uint64_t)result;
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void icnss_vph_notify(enum adc_tm_state state, void *ctx)
|
||||||
|
{
|
||||||
|
struct icnss_priv *priv = ctx;
|
||||||
|
u64 vph_pwr = 0;
|
||||||
|
u64 vph_pwr_prev;
|
||||||
|
int ret = 0;
|
||||||
|
bool update = true;
|
||||||
|
|
||||||
|
if (!priv) {
|
||||||
|
icnss_pr_err("Priv pointer is NULL\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vph_pwr_prev = priv->vph_pwr;
|
||||||
|
|
||||||
|
ret = icnss_get_phone_power(priv, &vph_pwr);
|
||||||
|
if (ret < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (vph_pwr < ICNSS_THRESHOLD_LOW) {
|
||||||
|
if (vph_pwr_prev < ICNSS_THRESHOLD_LOW)
|
||||||
|
update = false;
|
||||||
|
priv->vph_monitor_params.state_request =
|
||||||
|
ADC_TM_HIGH_THR_ENABLE;
|
||||||
|
priv->vph_monitor_params.high_thr = ICNSS_THRESHOLD_LOW +
|
||||||
|
ICNSS_THRESHOLD_GUARD;
|
||||||
|
priv->vph_monitor_params.low_thr = 0;
|
||||||
|
} else if (vph_pwr > ICNSS_THRESHOLD_HIGH) {
|
||||||
|
if (vph_pwr_prev > ICNSS_THRESHOLD_HIGH)
|
||||||
|
update = false;
|
||||||
|
priv->vph_monitor_params.state_request =
|
||||||
|
ADC_TM_LOW_THR_ENABLE;
|
||||||
|
priv->vph_monitor_params.low_thr = ICNSS_THRESHOLD_HIGH -
|
||||||
|
ICNSS_THRESHOLD_GUARD;
|
||||||
|
priv->vph_monitor_params.high_thr = 0;
|
||||||
|
} else {
|
||||||
|
if (vph_pwr_prev > ICNSS_THRESHOLD_LOW &&
|
||||||
|
vph_pwr_prev < ICNSS_THRESHOLD_HIGH)
|
||||||
|
update = false;
|
||||||
|
priv->vph_monitor_params.state_request =
|
||||||
|
ADC_TM_HIGH_LOW_THR_ENABLE;
|
||||||
|
priv->vph_monitor_params.low_thr = ICNSS_THRESHOLD_LOW;
|
||||||
|
priv->vph_monitor_params.high_thr = ICNSS_THRESHOLD_HIGH;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->vph_pwr = vph_pwr;
|
||||||
|
|
||||||
|
if (update) {
|
||||||
|
icnss_send_vbatt_update(priv, vph_pwr);
|
||||||
|
icnss_pr_dbg("set low threshold to %d, high threshold to %d Phone power=%llu\n",
|
||||||
|
priv->vph_monitor_params.low_thr,
|
||||||
|
priv->vph_monitor_params.high_thr, vph_pwr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = adc_tm_channel_measure(priv->adc_tm_dev,
|
||||||
|
&priv->vph_monitor_params);
|
||||||
|
if (ret)
|
||||||
|
icnss_pr_err("TM channel setup failed %d\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icnss_setup_vph_monitor(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!priv->adc_tm_dev) {
|
||||||
|
icnss_pr_err("ADC TM handler is NULL\n");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->vph_monitor_params.low_thr = ICNSS_THRESHOLD_LOW;
|
||||||
|
priv->vph_monitor_params.high_thr = ICNSS_THRESHOLD_HIGH;
|
||||||
|
priv->vph_monitor_params.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
|
||||||
|
priv->vph_monitor_params.channel = ADC5_VBAT_SNS;
|
||||||
|
priv->vph_monitor_params.btm_ctx = priv;
|
||||||
|
priv->vph_monitor_params.threshold_notification = &icnss_vph_notify;
|
||||||
|
icnss_pr_dbg("Set low threshold to %d, high threshold to %d\n",
|
||||||
|
priv->vph_monitor_params.low_thr,
|
||||||
|
priv->vph_monitor_params.high_thr);
|
||||||
|
|
||||||
|
ret = adc_tm_channel_measure(priv->adc_tm_dev,
|
||||||
|
&priv->vph_monitor_params);
|
||||||
|
if (ret)
|
||||||
|
icnss_pr_err("TM channel setup failed %d\n", ret);
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_init_vph_monitor(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = icnss_get_phone_power(priv, &priv->vph_pwr);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
icnss_pr_dbg("Phone power=%llu\n", priv->vph_pwr);
|
||||||
|
|
||||||
|
icnss_send_vbatt_update(priv, priv->vph_pwr);
|
||||||
|
|
||||||
|
ret = icnss_setup_vph_monitor(priv);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_aop_mbox_init(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
struct mbox_client *mbox = &priv->mbox_client_data;
|
||||||
|
struct mbox_chan *chan;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = of_property_read_string(priv->pdev->dev.of_node,
|
||||||
|
"qcom,vreg_ol_cpr",
|
||||||
|
&priv->cpr_info.vreg_ol_cpr);
|
||||||
|
if (ret) {
|
||||||
|
icnss_pr_dbg("Vreg for OL CPR not configured\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbox->dev = &priv->pdev->dev;
|
||||||
|
mbox->tx_block = true;
|
||||||
|
mbox->tx_tout = ICNSS_MBOX_TIMEOUT_MS;
|
||||||
|
mbox->knows_txdone = false;
|
||||||
|
|
||||||
|
priv->mbox_chan = NULL;
|
||||||
|
chan = mbox_request_channel(mbox, 0);
|
||||||
|
if (IS_ERR(chan)) {
|
||||||
|
ret = PTR_ERR(chan);
|
||||||
|
icnss_pr_err("Failed to get mbox channel with err %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
priv->mbox_chan = chan;
|
||||||
|
|
||||||
|
icnss_pr_dbg("Mbox channel initialized\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_MSM_QMP)
|
||||||
|
static int icnss_aop_set_vreg_param(struct icnss_priv *priv,
|
||||||
|
const char *vreg_name,
|
||||||
|
enum icnss_vreg_param param,
|
||||||
|
enum icnss_tcs_seq seq, int val)
|
||||||
|
{
|
||||||
|
struct qmp_pkt pkt;
|
||||||
|
char mbox_msg[ICNSS_MBOX_MSG_MAX_LEN];
|
||||||
|
static const char * const vreg_param_str[] = {"v", "m", "e"};
|
||||||
|
static const char *const tcs_seq_str[] = {"upval", "dwnval", "enable"};
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (param > ICNSS_VREG_ENABLE || seq > ICNSS_TCS_ALL_SEQ || !vreg_name)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
snprintf(mbox_msg, ICNSS_MBOX_MSG_MAX_LEN,
|
||||||
|
"{class: wlan_pdc, res: %s.%s, %s: %d}", vreg_name,
|
||||||
|
vreg_param_str[param], tcs_seq_str[seq], val);
|
||||||
|
|
||||||
|
icnss_pr_dbg("Sending AOP Mbox msg: %s\n", mbox_msg);
|
||||||
|
pkt.size = ICNSS_MBOX_MSG_MAX_LEN;
|
||||||
|
pkt.data = mbox_msg;
|
||||||
|
|
||||||
|
ret = mbox_send_message(priv->mbox_chan, &pkt);
|
||||||
|
if (ret < 0)
|
||||||
|
icnss_pr_err("Failed to send AOP mbox msg: %s,ret: %d\n",
|
||||||
|
mbox_msg, ret);
|
||||||
|
else
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int icnss_aop_set_vreg_param(struct icnss_priv *priv,
|
||||||
|
const char *vreg_name,
|
||||||
|
enum icnss_vreg_param param,
|
||||||
|
enum icnss_tcs_seq seq, int val)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int icnss_update_cpr_info(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
struct icnss_cpr_info *cpr_info = &priv->cpr_info;
|
||||||
|
|
||||||
|
if (!cpr_info->vreg_ol_cpr || !priv->mbox_chan) {
|
||||||
|
icnss_pr_dbg("Mbox channel / OL CPR Vreg not configured\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpr_info->voltage == 0) {
|
||||||
|
icnss_pr_err("Voltage %dmV is not valid\n", cpr_info->voltage);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpr_info->voltage = cpr_info->voltage > BT_CXMX_VOLTAGE_MV ?
|
||||||
|
cpr_info->voltage : BT_CXMX_VOLTAGE_MV;
|
||||||
|
|
||||||
|
return icnss_aop_set_vreg_param(priv,
|
||||||
|
cpr_info->vreg_ol_cpr,
|
||||||
|
ICNSS_VREG_VOLTAGE,
|
||||||
|
ICNSS_TCS_UP_SEQ,
|
||||||
|
cpr_info->voltage);
|
||||||
|
}
|
19
icnss2/power.h
Normal file
19
icnss2/power.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ICNSS_POWER_H__
|
||||||
|
#define __ICNSS_POWER_H__
|
||||||
|
|
||||||
|
int icnss_hw_power_on(struct icnss_priv *priv);
|
||||||
|
int icnss_hw_power_off(struct icnss_priv *priv);
|
||||||
|
int icnss_get_clk(struct icnss_priv *priv);
|
||||||
|
int icnss_get_vreg(struct icnss_priv *priv);
|
||||||
|
int icnss_init_vph_monitor(struct icnss_priv *priv);
|
||||||
|
void icnss_put_resources(struct icnss_priv *priv);
|
||||||
|
void icnss_put_vreg(struct icnss_priv *priv);
|
||||||
|
void icnss_put_clk(struct icnss_priv *priv);
|
||||||
|
int icnss_vreg_unvote(struct icnss_priv *priv);
|
||||||
|
|
||||||
|
#endif
|
3469
icnss2/qmi.c
Normal file
3469
icnss2/qmi.c
Normal file
File diff suppressed because it is too large
Load Diff
264
icnss2/qmi.h
Normal file
264
icnss2/qmi.h
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ICNSS_QMI_H__
|
||||||
|
#define __ICNSS_QMI_H__
|
||||||
|
|
||||||
|
#include "device_management_service_v01.h"
|
||||||
|
|
||||||
|
#define QDSS_TRACE_SEG_LEN_MAX 32
|
||||||
|
#define QDSS_TRACE_FILE_NAME_MAX 16
|
||||||
|
#define M3_SEGMENTS_SIZE_MAX 10
|
||||||
|
#define M3_SEGMENT_NAME_LEN_MAX 16
|
||||||
|
|
||||||
|
struct icnss_mem_seg {
|
||||||
|
u64 addr;
|
||||||
|
u32 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_qmi_event_qdss_trace_save_data {
|
||||||
|
u32 total_size;
|
||||||
|
u32 mem_seg_len;
|
||||||
|
struct icnss_mem_seg mem_seg[QDSS_TRACE_SEG_LEN_MAX];
|
||||||
|
char file_name[QDSS_TRACE_FILE_NAME_MAX + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_m3_segment {
|
||||||
|
u32 type;
|
||||||
|
u64 addr;
|
||||||
|
u64 size;
|
||||||
|
char name[M3_SEGMENT_NAME_LEN_MAX + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_m3_upload_segments_req_data {
|
||||||
|
u32 pdev_id;
|
||||||
|
u32 no_of_valid_segments;
|
||||||
|
struct icnss_m3_segment m3_segment[M3_SEGMENTS_SIZE_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_qmi_event_qdss_trace_req_data {
|
||||||
|
u32 total_size;
|
||||||
|
char file_name[QDSS_TRACE_FILE_NAME_MAX + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef CONFIG_ICNSS2_QMI
|
||||||
|
|
||||||
|
static inline int wlfw_ind_register_send_sync_msg(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int icnss_connect_to_fw_server(struct icnss_priv *priv,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int wlfw_msa_mem_info_send_sync_msg(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int wlfw_msa_ready_send_sync_msg(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int wlfw_cap_send_sync_msg(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int wlfw_dynamic_feature_mask_send_sync_msg(
|
||||||
|
struct icnss_priv *priv, uint64_t dynamic_feature_mask)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int icnss_clear_server(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int wlfw_rejuvenate_ack_send_sync_msg(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline void icnss_ignore_fw_timeout(bool ignore) {}
|
||||||
|
static int wlfw_send_modem_shutdown_msg(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int wlfw_ini_send_sync_msg(struct icnss_priv *priv,
|
||||||
|
uint8_t fw_log_mode)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int wlfw_athdiag_read_send_sync_msg(struct icnss_priv *priv,
|
||||||
|
uint32_t offset, uint32_t mem_type,
|
||||||
|
uint32_t data_len, uint8_t *data)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int wlfw_athdiag_write_send_sync_msg(struct icnss_priv *priv,
|
||||||
|
uint32_t offset, uint32_t mem_type,
|
||||||
|
uint32_t data_len, uint8_t *data)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int wlfw_wlan_mode_send_sync_msg(struct icnss_priv *priv,
|
||||||
|
enum icnss_driver_mode mode)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int wlfw_host_cap_send_sync(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int icnss_send_wlan_enable_to_fw(struct icnss_priv *priv,
|
||||||
|
struct icnss_wlan_enable_cfg *config,
|
||||||
|
enum icnss_driver_mode mode,
|
||||||
|
const char *host_version)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int icnss_send_wlan_disable_to_fw(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline int icnss_register_fw_service(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static inline void icnss_unregister_fw_service(struct icnss_priv *priv) {}
|
||||||
|
static inline int icnss_send_vbatt_update(struct icnss_priv *priv,
|
||||||
|
uint64_t voltage_uv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wlfw_device_info_send_msg(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int wlfw_wlan_mode_send_sync_msg(struct icnss_priv *priv,
|
||||||
|
enum wlfw_driver_mode_enum_v01 mode)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int icnss_wlfw_bdf_dnld_send_sync(struct icnss_priv *priv, u32 bdf_type)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wlfw_qdss_trace_mem_info_send_sync(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wlfw_power_save_send_msg(struct icnss_priv *priv,
|
||||||
|
enum wlfw_power_save_mode_v01 mode)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_wlfw_get_info_send_sync(struct icnss_priv *priv, int type,
|
||||||
|
void *cmd, int cmd_len)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wlfw_send_soc_wake_msg(struct icnss_priv *priv,
|
||||||
|
enum wlfw_soc_wake_enum_v01 type)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_wlfw_m3_dump_upload_done_send_sync(struct icnss_priv *priv,
|
||||||
|
u32 pdev_id, int status)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_qmi_get_dms_mac(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_wlfw_wlan_mac_req_send_sync(struct icnss_priv *priv,
|
||||||
|
u8 *mac, u32 mac_len)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icnss_dms_init(struct icns_priv *priv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void icnss_dms_deinit(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int wlfw_subsys_restart_level_msg(struct icnss_priv *penv, uint8_t restart_level)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wlfw_cal_report_req(struct icnss_priv *priv)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
int wlfw_msa_mem_info_send_sync_msg(struct icnss_priv *priv);
|
||||||
|
int wlfw_msa_ready_send_sync_msg(struct icnss_priv *priv);
|
||||||
|
int wlfw_cap_send_sync_msg(struct icnss_priv *priv);
|
||||||
|
int icnss_qmi_pin_connect_result_ind(struct icnss_priv *priv,
|
||||||
|
void *msg, unsigned int msg_len);
|
||||||
|
int wlfw_dynamic_feature_mask_send_sync_msg(struct icnss_priv *priv,
|
||||||
|
uint64_t dynamic_feature_mask);
|
||||||
|
int icnss_clear_server(struct icnss_priv *priv);
|
||||||
|
int wlfw_rejuvenate_ack_send_sync_msg(struct icnss_priv *priv);
|
||||||
|
void icnss_ignore_fw_timeout(bool ignore);
|
||||||
|
int wlfw_send_modem_shutdown_msg(struct icnss_priv *priv);
|
||||||
|
int wlfw_ini_send_sync_msg(struct icnss_priv *priv, uint8_t fw_log_mode);
|
||||||
|
int wlfw_athdiag_read_send_sync_msg(struct icnss_priv *priv,
|
||||||
|
uint32_t offset, uint32_t mem_type,
|
||||||
|
uint32_t data_len, uint8_t *data);
|
||||||
|
int wlfw_athdiag_write_send_sync_msg(struct icnss_priv *priv,
|
||||||
|
uint32_t offset, uint32_t mem_type,
|
||||||
|
uint32_t data_len, uint8_t *data);
|
||||||
|
int icnss_send_wlan_enable_to_fw(struct icnss_priv *priv,
|
||||||
|
struct icnss_wlan_enable_cfg *config,
|
||||||
|
enum icnss_driver_mode mode,
|
||||||
|
const char *host_version);
|
||||||
|
int icnss_send_wlan_disable_to_fw(struct icnss_priv *priv);
|
||||||
|
int icnss_register_fw_service(struct icnss_priv *priv);
|
||||||
|
void icnss_unregister_fw_service(struct icnss_priv *priv);
|
||||||
|
int icnss_send_vbatt_update(struct icnss_priv *priv, uint64_t voltage_uv);
|
||||||
|
int wlfw_host_cap_send_sync(struct icnss_priv *priv);
|
||||||
|
int wlfw_device_info_send_msg(struct icnss_priv *priv);
|
||||||
|
int wlfw_wlan_mode_send_sync_msg(struct icnss_priv *priv,
|
||||||
|
enum wlfw_driver_mode_enum_v01 mode);
|
||||||
|
int icnss_wlfw_bdf_dnld_send_sync(struct icnss_priv *priv, u32 bdf_type);
|
||||||
|
int icnss_wlfw_qdss_dnld_send_sync(struct icnss_priv *priv);
|
||||||
|
int icnss_wlfw_qdss_data_send_sync(struct icnss_priv *priv, char *file_name,
|
||||||
|
u32 total_size);
|
||||||
|
int wlfw_qdss_trace_start(struct icnss_priv *priv);
|
||||||
|
int wlfw_qdss_trace_stop(struct icnss_priv *priv, unsigned long long option);
|
||||||
|
int wlfw_qdss_trace_mem_info_send_sync(struct icnss_priv *priv);
|
||||||
|
int wlfw_power_save_send_msg(struct icnss_priv *priv,
|
||||||
|
enum wlfw_power_save_mode_v01 mode);
|
||||||
|
int icnss_wlfw_get_info_send_sync(struct icnss_priv *priv, int type,
|
||||||
|
void *cmd, int cmd_len);
|
||||||
|
int wlfw_send_soc_wake_msg(struct icnss_priv *priv,
|
||||||
|
enum wlfw_soc_wake_enum_v01 type);
|
||||||
|
int icnss_wlfw_m3_dump_upload_done_send_sync(struct icnss_priv *priv,
|
||||||
|
u32 pdev_id, int status);
|
||||||
|
int icnss_qmi_get_dms_mac(struct icnss_priv *priv);
|
||||||
|
int icnss_wlfw_wlan_mac_req_send_sync(struct icnss_priv *priv,
|
||||||
|
u8 *mac, u32 mac_len);
|
||||||
|
int icnss_dms_init(struct icnss_priv *priv);
|
||||||
|
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);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __ICNSS_QMI_H__*/
|
207
inc/icnss2.h
Normal file
207
inc/icnss2.h
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
#ifndef _ICNSS_WLAN_H_
|
||||||
|
#define _ICNSS_WLAN_H_
|
||||||
|
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
|
||||||
|
#define ICNSS_MAX_IRQ_REGISTRATIONS 12
|
||||||
|
#define IWCN_MAX_IRQ_REGISTRATIONS 32
|
||||||
|
#define ICNSS_MAX_TIMESTAMP_LEN 32
|
||||||
|
|
||||||
|
#ifndef ICNSS_API_WITH_DEV
|
||||||
|
#define ICNSS_API_WITH_DEV
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEVICE_NAME_MAX 10
|
||||||
|
enum icnss_uevent {
|
||||||
|
ICNSS_UEVENT_FW_CRASHED,
|
||||||
|
ICNSS_UEVENT_FW_DOWN,
|
||||||
|
ICNSS_UEVENT_HANG_DATA,
|
||||||
|
ICNSS_UEVENT_SMMU_FAULT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_uevent_hang_data {
|
||||||
|
void *hang_event_data;
|
||||||
|
uint16_t hang_event_data_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_uevent_fw_down_data {
|
||||||
|
bool crashed;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_uevent_data {
|
||||||
|
enum icnss_uevent uevent;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Device information like supported device ids, etc*/
|
||||||
|
struct device_info {
|
||||||
|
char name[DEVICE_NAME_MAX];
|
||||||
|
uint16_t device_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_driver_ops {
|
||||||
|
char *name;
|
||||||
|
struct device_info *dev_info;
|
||||||
|
unsigned long drv_state;
|
||||||
|
struct device_driver driver;
|
||||||
|
int (*probe)(struct device *dev);
|
||||||
|
void (*remove)(struct device *dev);
|
||||||
|
void (*shutdown)(struct device *dev);
|
||||||
|
int (*reinit)(struct device *dev);
|
||||||
|
void (*crash_shutdown)(void *pdev);
|
||||||
|
int (*pm_suspend)(struct device *dev);
|
||||||
|
int (*pm_resume)(struct device *dev);
|
||||||
|
int (*suspend_noirq)(struct device *dev);
|
||||||
|
int (*resume_noirq)(struct device *dev);
|
||||||
|
int (*runtime_suspend)(struct device *dev);
|
||||||
|
int (*runtime_resume)(struct device *dev);
|
||||||
|
int (*uevent)(struct device *dev, struct icnss_uevent_data *uevent);
|
||||||
|
int (*idle_shutdown)(struct device *dev);
|
||||||
|
int (*idle_restart)(struct device *dev);
|
||||||
|
int (*set_therm_cdev_state)(struct device *dev,
|
||||||
|
unsigned long thermal_state,
|
||||||
|
int tcdev_id);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ce_tgt_pipe_cfg {
|
||||||
|
u32 pipe_num;
|
||||||
|
u32 pipe_dir;
|
||||||
|
u32 nentries;
|
||||||
|
u32 nbytes_max;
|
||||||
|
u32 flags;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ce_svc_pipe_cfg {
|
||||||
|
u32 service_id;
|
||||||
|
u32 pipe_dir;
|
||||||
|
u32 pipe_num;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_shadow_reg_cfg {
|
||||||
|
u16 ce_id;
|
||||||
|
u16 reg_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_shadow_reg_v2_cfg {
|
||||||
|
u32 addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_rri_over_ddr_cfg {
|
||||||
|
u32 base_addr_low;
|
||||||
|
u32 base_addr_high;
|
||||||
|
};
|
||||||
|
/* CE configuration to target */
|
||||||
|
struct icnss_wlan_enable_cfg {
|
||||||
|
u32 num_ce_tgt_cfg;
|
||||||
|
struct ce_tgt_pipe_cfg *ce_tgt_cfg;
|
||||||
|
u32 num_ce_svc_pipe_cfg;
|
||||||
|
struct ce_svc_pipe_cfg *ce_svc_cfg;
|
||||||
|
u32 num_shadow_reg_cfg;
|
||||||
|
struct icnss_shadow_reg_cfg *shadow_reg_cfg;
|
||||||
|
u32 num_shadow_reg_v2_cfg;
|
||||||
|
struct icnss_shadow_reg_v2_cfg *shadow_reg_v2_cfg;
|
||||||
|
bool rri_over_ddr_cfg_valid;
|
||||||
|
struct icnss_rri_over_ddr_cfg rri_over_ddr_cfg;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* driver modes */
|
||||||
|
enum icnss_driver_mode {
|
||||||
|
ICNSS_MISSION,
|
||||||
|
ICNSS_FTM,
|
||||||
|
ICNSS_EPPING,
|
||||||
|
ICNSS_WALTEST,
|
||||||
|
ICNSS_OFF,
|
||||||
|
ICNSS_CCPM,
|
||||||
|
ICNSS_QVIT,
|
||||||
|
ICNSS_CALIBRATION,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct icnss_soc_info {
|
||||||
|
void __iomem *v_addr;
|
||||||
|
phys_addr_t p_addr;
|
||||||
|
uint32_t chip_id;
|
||||||
|
uint32_t chip_family;
|
||||||
|
uint32_t board_id;
|
||||||
|
uint32_t soc_id;
|
||||||
|
uint32_t fw_version;
|
||||||
|
char fw_build_timestamp[ICNSS_MAX_TIMESTAMP_LEN + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define icnss_register_driver(ops) \
|
||||||
|
__icnss_register_driver(ops, THIS_MODULE, KBUILD_MODNAME)
|
||||||
|
extern int __icnss_register_driver(struct icnss_driver_ops *ops,
|
||||||
|
struct module *owner, const char *mod_name);
|
||||||
|
|
||||||
|
extern int icnss_unregister_driver(struct icnss_driver_ops *ops);
|
||||||
|
|
||||||
|
extern int icnss_wlan_enable(struct device *dev,
|
||||||
|
struct icnss_wlan_enable_cfg *config,
|
||||||
|
enum icnss_driver_mode mode,
|
||||||
|
const char *host_version);
|
||||||
|
extern int icnss_wlan_disable(struct device *dev, enum icnss_driver_mode mode);
|
||||||
|
extern void icnss_enable_irq(struct device *dev, unsigned int ce_id);
|
||||||
|
extern void icnss_disable_irq(struct device *dev, unsigned int ce_id);
|
||||||
|
extern int icnss_get_soc_info(struct device *dev, struct icnss_soc_info *info);
|
||||||
|
extern int icnss_ce_free_irq(struct device *dev, unsigned int ce_id, void *ctx);
|
||||||
|
extern int icnss_ce_request_irq(struct device *dev, unsigned int ce_id,
|
||||||
|
irqreturn_t (*handler)(int, void *),
|
||||||
|
unsigned long flags, const char *name, void *ctx);
|
||||||
|
extern int icnss_get_ce_id(struct device *dev, int irq);
|
||||||
|
extern int icnss_set_fw_log_mode(struct device *dev, uint8_t fw_log_mode);
|
||||||
|
extern int icnss_athdiag_read(struct device *dev, uint32_t offset,
|
||||||
|
uint32_t mem_type, uint32_t data_len,
|
||||||
|
uint8_t *output);
|
||||||
|
extern int icnss_athdiag_write(struct device *dev, uint32_t offset,
|
||||||
|
uint32_t mem_type, uint32_t data_len,
|
||||||
|
uint8_t *input);
|
||||||
|
extern int icnss_get_irq(struct device *dev, int ce_id);
|
||||||
|
extern int icnss_power_on(struct device *dev);
|
||||||
|
extern int icnss_power_off(struct device *dev);
|
||||||
|
extern struct dma_iommu_mapping *icnss_smmu_get_mapping(struct device *dev);
|
||||||
|
extern struct iommu_domain *icnss_smmu_get_domain(struct device *dev);
|
||||||
|
extern int icnss_smmu_map(struct device *dev, phys_addr_t paddr,
|
||||||
|
uint32_t *iova_addr, size_t size);
|
||||||
|
extern int icnss_smmu_unmap(struct device *dev,
|
||||||
|
uint32_t iova_addr, size_t size);
|
||||||
|
extern unsigned int icnss_socinfo_get_serial_number(struct device *dev);
|
||||||
|
extern bool icnss_is_qmi_disable(struct device *dev);
|
||||||
|
extern bool icnss_is_fw_ready(void);
|
||||||
|
extern bool icnss_is_fw_down(void);
|
||||||
|
extern bool icnss_is_rejuvenate(void);
|
||||||
|
extern int icnss_trigger_recovery(struct device *dev);
|
||||||
|
extern void icnss_block_shutdown(bool status);
|
||||||
|
extern bool icnss_is_pdr(void);
|
||||||
|
extern int icnss_idle_restart(struct device *dev);
|
||||||
|
extern int icnss_idle_shutdown(struct device *dev);
|
||||||
|
extern int icnss_get_user_msi_assignment(struct device *dev, char *user_name,
|
||||||
|
int *num_vectors, u32 *user_base_data,
|
||||||
|
u32 *base_vector);
|
||||||
|
extern int icnss_get_msi_irq(struct device *dev, unsigned int vector);
|
||||||
|
extern void icnss_get_msi_address(struct device *dev, u32 *msi_addr_low,
|
||||||
|
u32 *msi_addr_high);
|
||||||
|
extern int icnss_qmi_send(struct device *dev, int type, void *cmd,
|
||||||
|
int cmd_len, void *cb_ctx,
|
||||||
|
int (*cb)(void *ctx, void *event, int event_len));
|
||||||
|
extern int icnss_force_wake_request(struct device *dev);
|
||||||
|
extern int icnss_force_wake_release(struct device *dev);
|
||||||
|
extern int icnss_is_device_awake(struct device *dev);
|
||||||
|
extern int icnss_thermal_cdev_register(struct device *dev,
|
||||||
|
unsigned long max_state,
|
||||||
|
int tcdev_id);
|
||||||
|
extern void icnss_thermal_cdev_unregister(struct device *dev, int tcdev_id);
|
||||||
|
extern int icnss_get_curr_therm_cdev_state(struct device *dev,
|
||||||
|
unsigned long *thermal_state,
|
||||||
|
int tcdev_id);
|
||||||
|
extern int icnss_exit_power_save(struct device *dev);
|
||||||
|
extern int icnss_prevent_l1(struct device *dev);
|
||||||
|
extern void icnss_allow_l1(struct device *dev);
|
||||||
|
extern int icnss_get_mhi_state(struct device *dev);
|
||||||
|
extern int icnss_is_pci_ep_awake(struct device *dev);
|
||||||
|
#endif /* _ICNSS_WLAN_H_ */
|
Reference in New Issue
Block a user