net: cnss2: Add snapshot of CNSS2 driver

This is a snapshot of the CNSS2 driver and associated files as of
msm-4.19 commit a1c93228c0bb
("cnss2: Fix synchronization issues related to idle shutdown").

Remove obsolete cnss_utils.c and add Kconfig dependency.
Replace bus scaling APIs with interconnect APIs due to msm_bus migration.

CRs-Fixed: 2500800
Change-Id: I4f0af08c3d0f2982a0f9605dcc56bfeb0145a3fa
Signed-off-by: Yuanyuan Liu <yuanliu@codeaurora.org>
This commit is contained in:
Yuanyuan Liu 2019-07-31 11:53:34 -07:00
parent 844cb3e3ab
commit bedd876b6f
24 changed files with 16415 additions and 0 deletions

View File

@ -122,4 +122,6 @@ config VIRT_WIFI
This option adds support for ethernet connections to appear as if they
are wifi connections through a special rtnetlink device.
source "drivers/net/wireless/cnss2/Kconfig"
endif # WLAN

View File

@ -29,3 +29,5 @@ obj-$(CONFIG_USB_NET_RNDIS_WLAN) += rndis_wlan.o
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
obj-$(CONFIG_VIRT_WIFI) += virt_wifi.o
obj-$(CONFIG_CNSS2) += cnss2/

View File

@ -0,0 +1,88 @@
# SPDX-License-Identifier: GPL-2.0-only
config CNSS2
tristate "CNSS2 Platform Driver for Wi-Fi Module"
depends on !CNSS && PCI_MSM
help
This module adds the support for Connectivity Subsystem (CNSS) used
for PCIe based Wi-Fi devices with QCA6174/QCA6290 chipsets.
This driver also adds support to integrate WLAN module to subsystem
restart framework.
config CNSS2_DEBUG
bool "CNSS2 Platform Driver Debug Support"
depends on CNSS2
help
This option is to enable CNSS2 platform driver debug support which
primarily includes providing additional verbose logs for certain
features, enabling kernel panic for certain cases to aid the
debugging, and enabling any other debug mechanisms.
config CNSS2_QMI
bool "CNSS2 Platform Driver QMI support"
depends on CNSS2
help
CNSS2 platform driver uses QMI framework to communicate with WLAN
firmware. It sends and receives boot handshake messages to WLAN
firmware, which includes hardware and software capabilities and
configurations. It also sends WLAN on/off control message to
firmware over QMI channel.
config CNSS_ASYNC
bool "Enable/disable CNSS platform driver asynchronous probe"
depends on CNSS2
help
If enabled, CNSS platform driver would do asynchronous probe.
Using asynchronous probe will allow CNSS platform driver to
probe in parallel with other device drivers and will help to
reduce kernel boot time.
config BUS_AUTO_SUSPEND
bool "Enable/Disable Runtime PM support for PCIe based WLAN Drivers"
depends on CNSS2
depends on PCI
help
Runtime Power Management is supported for PCIe based WLAN Drivers.
The features enable cld wlan driver to suspend pcie bus when APPS
is awake based on the driver inactivity with the Firmware.
The Feature uses runtime power management framework from kernel to
track bus access clients and to synchronize the driver activity
during system pm.
This config flag controls the feature per target based. The feature
requires CNSS driver support.
config CNSS_QCA6290
bool "Enable CNSS QCA6290 chipset specific changes"
depends on CNSS2
help
This enables the changes from WLAN host driver that are specific to
CNSS QCA6290 chipset.
These changes are needed to support the new hardware architecture
for CNSS QCA6290 chipset.
config CNSS_QCA6390
bool "Enable CNSS QCA6390 chipset specific changes"
depends on CNSS2
help
This enables the changes from WLAN host driver that are specific to
CNSS QCA6390 chipset.
These changes are needed to support the new hardware architecture
for CNSS QCA6390 chipset.
config CNSS_EMULATION
bool "Enable specific changes for emulation hardware"
depends on CNSS2
help
This enables the changes from WLAN drivers that are specific to
emulation hardware.
These changes are needed for WLAN drivers to support and meet the
requirement of emulation hardware.
config CNSS_QCA6490
bool "Enable CNSS QCA6490 chipset specific changes"
depends on CNSS2
help
This enables the changes from WLAN host driver that are specific to
CNSS QCA6490 chipset.
These changes are needed to support the new hardware architecture
for CNSS QCA6490 chipset.

View File

@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_CNSS2) += cnss2.o
cnss2-y := main.o
cnss2-y += bus.o
cnss2-y += debug.o
cnss2-y += pci.o
cnss2-y += power.o
cnss2-$(CONFIG_CNSS2_DEBUG) += genl.o
cnss2-$(CONFIG_CNSS2_QMI) += qmi.o wlan_firmware_service_v01.o coexistence_service_v01.o ip_multimedia_subsystem_private_service_v01.o

View File

@ -0,0 +1,374 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */
#include "bus.h"
#include "debug.h"
#include "pci.h"
enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev)
{
if (!dev)
return CNSS_BUS_NONE;
if (!dev->bus)
return CNSS_BUS_NONE;
if (memcmp(dev->bus->name, "pci", 3) == 0)
return CNSS_BUS_PCI;
else
return CNSS_BUS_NONE;
}
enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id)
{
switch (device_id) {
case QCA6174_DEVICE_ID:
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
case QCA6490_DEVICE_ID:
return CNSS_BUS_PCI;
default:
cnss_pr_err("Unknown device_id: 0x%lx\n", device_id);
return CNSS_BUS_NONE;
}
}
void *cnss_bus_dev_to_bus_priv(struct device *dev)
{
if (!dev)
return NULL;
switch (cnss_get_dev_bus_type(dev)) {
case CNSS_BUS_PCI:
return cnss_get_pci_priv(to_pci_dev(dev));
default:
return NULL;
}
}
struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev)
{
void *bus_priv;
if (!dev)
return cnss_get_plat_priv(NULL);
bus_priv = cnss_bus_dev_to_bus_priv(dev);
if (!bus_priv)
return NULL;
switch (cnss_get_dev_bus_type(dev)) {
case CNSS_BUS_PCI:
return cnss_pci_priv_to_plat_priv(bus_priv);
default:
return NULL;
}
}
int cnss_bus_init(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_init(plat_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
void cnss_bus_deinit(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
cnss_pci_deinit(plat_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return;
}
}
int cnss_bus_load_m3(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_load_m3(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
int cnss_bus_alloc_fw_mem(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_alloc_fw_mem(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
int cnss_bus_alloc_qdss_mem(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_alloc_qdss_mem(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
void cnss_bus_free_qdss_mem(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
cnss_pci_free_qdss_mem(plat_priv->bus_priv);
return;
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return;
}
}
u32 cnss_bus_get_wake_irq(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_get_wake_msi(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
int cnss_bus_force_fw_assert_hdlr(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_force_fw_assert_hdlr(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
void cnss_bus_fw_boot_timeout_hdlr(struct timer_list *t)
{
struct cnss_plat_data *plat_priv =
from_timer(plat_priv, t, fw_boot_timer);
if (!plat_priv)
return;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_fw_boot_timeout_hdlr(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return;
}
}
void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv, bool in_panic)
{
if (!plat_priv)
return;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_collect_dump_info(plat_priv->bus_priv,
in_panic);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return;
}
}
int cnss_bus_call_driver_probe(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_call_driver_probe(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
int cnss_bus_call_driver_remove(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_call_driver_remove(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
int cnss_bus_dev_powerup(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_dev_powerup(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
int cnss_bus_dev_shutdown(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_dev_shutdown(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
int cnss_bus_dev_crash_shutdown(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_dev_crash_shutdown(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
int cnss_bus_dev_ramdump(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_dev_ramdump(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
int cnss_bus_register_driver_hdlr(struct cnss_plat_data *plat_priv, void *data)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_register_driver_hdlr(plat_priv->bus_priv, data);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
int cnss_bus_unregister_driver_hdlr(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_unregister_driver_hdlr(plat_priv->bus_priv);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
int cnss_bus_call_driver_modem_status(struct cnss_plat_data *plat_priv,
int modem_current_status)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_call_driver_modem_status(plat_priv->bus_priv,
modem_current_status);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}
int cnss_bus_update_status(struct cnss_plat_data *plat_priv,
enum cnss_driver_status status)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_update_status(plat_priv->bus_priv, status);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}

View File

@ -0,0 +1,49 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */
#ifndef _CNSS_BUS_H
#define _CNSS_BUS_H
#include "main.h"
#define QCA6174_VENDOR_ID 0x168C
#define QCA6174_DEVICE_ID 0x003E
#define QCA6174_REV_ID_OFFSET 0x08
#define QCA6174_REV3_VERSION 0x5020000
#define QCA6174_REV3_2_VERSION 0x5030000
#define QCA6290_VENDOR_ID 0x17CB
#define QCA6290_DEVICE_ID 0x1100
#define QCA6390_VENDOR_ID 0x17CB
#define QCA6390_DEVICE_ID 0x1101
#define QCA6490_VENDOR_ID 0x17CB
#define QCA6490_DEVICE_ID 0x1103
enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev);
enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id);
void *cnss_bus_dev_to_bus_priv(struct device *dev);
struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev);
int cnss_bus_init(struct cnss_plat_data *plat_priv);
void cnss_bus_deinit(struct cnss_plat_data *plat_priv);
int cnss_bus_load_m3(struct cnss_plat_data *plat_priv);
int cnss_bus_alloc_fw_mem(struct cnss_plat_data *plat_priv);
int cnss_bus_alloc_qdss_mem(struct cnss_plat_data *plat_priv);
void cnss_bus_free_qdss_mem(struct cnss_plat_data *plat_priv);
u32 cnss_bus_get_wake_irq(struct cnss_plat_data *plat_priv);
int cnss_bus_force_fw_assert_hdlr(struct cnss_plat_data *plat_priv);
void cnss_bus_fw_boot_timeout_hdlr(struct timer_list *t);
void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv,
bool in_panic);
int cnss_bus_call_driver_probe(struct cnss_plat_data *plat_priv);
int cnss_bus_call_driver_remove(struct cnss_plat_data *plat_priv);
int cnss_bus_dev_powerup(struct cnss_plat_data *plat_priv);
int cnss_bus_dev_shutdown(struct cnss_plat_data *plat_priv);
int cnss_bus_dev_crash_shutdown(struct cnss_plat_data *plat_priv);
int cnss_bus_dev_ramdump(struct cnss_plat_data *plat_priv);
int cnss_bus_register_driver_hdlr(struct cnss_plat_data *plat_priv, void *data);
int cnss_bus_unregister_driver_hdlr(struct cnss_plat_data *plat_priv);
int cnss_bus_call_driver_modem_status(struct cnss_plat_data *plat_priv,
int modem_current_status);
int cnss_bus_update_status(struct cnss_plat_data *plat_priv,
enum cnss_driver_status status);
#endif /* _CNSS_BUS_H */

View File

@ -0,0 +1,95 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2019, The Linux Foundation. All rights reserved. */
#include <linux/soc/qcom/qmi.h>
#include "coexistence_service_v01.h"
struct qmi_elem_info coex_antenna_switch_to_wlan_req_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct
coex_antenna_switch_to_wlan_req_msg_v01,
antenna),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
struct qmi_elem_info coex_antenna_switch_to_wlan_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
coex_antenna_switch_to_wlan_resp_msg_v01,
resp),
.ei_array = qmi_response_type_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct
coex_antenna_switch_to_wlan_resp_msg_v01,
grant_valid),
},
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct
coex_antenna_switch_to_wlan_resp_msg_v01,
grant),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
struct qmi_elem_info coex_antenna_switch_to_mdm_req_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct
coex_antenna_switch_to_mdm_req_msg_v01,
antenna),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
struct qmi_elem_info coex_antenna_switch_to_mdm_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
coex_antenna_switch_to_mdm_resp_msg_v01,
resp),
.ei_array = qmi_response_type_v01_ei,
},
};

View File

@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2019, The Linux Foundation. All rights reserved. */
#ifndef COEXISTENCE_SERVICE_V01_H
#define COEXISTENCE_SERVICE_V01_H
#define COEX_SERVICE_ID_V01 0x22
#define COEX_SERVICE_VERS_V01 0x01
#define COEX_SERVICE_MAX_MSG_LEN 8204
#define QMI_COEX_SWITCH_ANTENNA_TO_WLAN_RESP_V01 0x0042
#define QMI_COEX_SWITCH_ANTENNA_TO_WLAN_REQ_V01 0x0042
#define QMI_COEX_SWITCH_ANTENNA_TO_MDM_RESP_V01 0x0042
#define QMI_COEX_SWITCH_ANTENNA_TO_MDM_REQ_V01 0x0042
#define COEX_ANTENNA_BAND_2GHZ_CHAIN0_V01 ((u64)0x0000000000000001ULL)
#define COEX_ANTENNA_BAND_2GHZ_CHAIN1_V01 ((u64)0x0000000000000002ULL)
#define COEX_ANTENNA_BAND_5GHZ_CHAIN0_V01 ((u64)0x0000000000000004ULL)
#define COEX_ANTENNA_BAND_5GHZ_CHAIN1_V01 ((u64)0x0000000000000008ULL)
struct coex_antenna_switch_to_wlan_req_msg_v01 {
u64 antenna;
};
#define COEX_ANTENNA_SWITCH_TO_WLAN_REQ_MSG_V01_MAX_MSG_LEN 11
extern struct qmi_elem_info coex_antenna_switch_to_wlan_req_msg_v01_ei[];
struct coex_antenna_switch_to_wlan_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 grant_valid;
u64 grant;
};
#define COEX_ANTENNA_SWITCH_TO_WLAN_RESP_MSG_V01_MAX_MSG_LEN 18
extern struct qmi_elem_info coex_antenna_switch_to_wlan_resp_msg_v01_ei[];
struct coex_antenna_switch_to_mdm_req_msg_v01 {
u64 antenna;
};
#define COEX_ANTENNA_SWITCH_TO_MDM_REQ_MSG_V01_MAX_MSG_LEN 11
extern struct qmi_elem_info coex_antenna_switch_to_mdm_req_msg_v01_ei[];
struct coex_antenna_switch_to_mdm_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define COEX_ANTENNA_SWITCH_TO_MDM_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info coex_antenna_switch_to_mdm_resp_msg_v01_ei[];
#endif

View File

@ -0,0 +1,795 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */
#include <linux/err.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
#include "main.h"
#include "debug.h"
#include "pci.h"
void *cnss_ipc_log_context;
void *cnss_ipc_log_long_context;
static int cnss_pin_connect_show(struct seq_file *s, void *data)
{
struct cnss_plat_data *cnss_priv = s->private;
seq_puts(s, "Pin connect results\n");
seq_printf(s, "FW power pin result: %04x\n",
cnss_priv->pin_result.fw_pwr_pin_result);
seq_printf(s, "FW PHY IO pin result: %04x\n",
cnss_priv->pin_result.fw_phy_io_pin_result);
seq_printf(s, "FW RF pin result: %04x\n",
cnss_priv->pin_result.fw_rf_pin_result);
seq_printf(s, "Host pin result: %04x\n",
cnss_priv->pin_result.host_pin_result);
seq_puts(s, "\n");
return 0;
}
static int cnss_pin_connect_open(struct inode *inode, struct file *file)
{
return single_open(file, cnss_pin_connect_show, inode->i_private);
}
static const struct file_operations cnss_pin_connect_fops = {
.read = seq_read,
.release = single_release,
.open = cnss_pin_connect_open,
.owner = THIS_MODULE,
.llseek = seq_lseek,
};
static int cnss_stats_show_state(struct seq_file *s,
struct cnss_plat_data *plat_priv)
{
enum cnss_driver_state i;
int skip = 0;
unsigned long state;
seq_printf(s, "\nState: 0x%lx(", plat_priv->driver_state);
for (i = 0, state = plat_priv->driver_state; state != 0;
state >>= 1, i++) {
if (!(state & 0x1))
continue;
if (skip++)
seq_puts(s, " | ");
switch (i) {
case CNSS_QMI_WLFW_CONNECTED:
seq_puts(s, "QMI_WLFW_CONNECTED");
continue;
case CNSS_FW_MEM_READY:
seq_puts(s, "FW_MEM_READY");
continue;
case CNSS_FW_READY:
seq_puts(s, "FW_READY");
continue;
case CNSS_COLD_BOOT_CAL:
seq_puts(s, "COLD_BOOT_CAL");
continue;
case CNSS_DRIVER_LOADING:
seq_puts(s, "DRIVER_LOADING");
continue;
case CNSS_DRIVER_UNLOADING:
seq_puts(s, "DRIVER_UNLOADING");
continue;
case CNSS_DRIVER_IDLE_RESTART:
seq_puts(s, "IDLE_RESTART");
continue;
case CNSS_DRIVER_IDLE_SHUTDOWN:
seq_puts(s, "IDLE_SHUTDOWN");
continue;
case CNSS_DRIVER_PROBED:
seq_puts(s, "DRIVER_PROBED");
continue;
case CNSS_DRIVER_RECOVERY:
seq_puts(s, "DRIVER_RECOVERY");
continue;
case CNSS_FW_BOOT_RECOVERY:
seq_puts(s, "FW_BOOT_RECOVERY");
continue;
case CNSS_DEV_ERR_NOTIFY:
seq_puts(s, "DEV_ERR");
continue;
case CNSS_DRIVER_DEBUG:
seq_puts(s, "DRIVER_DEBUG");
continue;
case CNSS_COEX_CONNECTED:
seq_puts(s, "COEX_CONNECTED");
continue;
case CNSS_IMS_CONNECTED:
seq_puts(s, "IMS_CONNECTED");
continue;
case CNSS_IN_SUSPEND_RESUME:
seq_puts(s, "IN_SUSPEND_RESUME");
continue;
}
seq_printf(s, "UNKNOWN-%d", i);
}
seq_puts(s, ")\n");
return 0;
}
static int cnss_stats_show(struct seq_file *s, void *data)
{
struct cnss_plat_data *plat_priv = s->private;
cnss_stats_show_state(s, plat_priv);
return 0;
}
static int cnss_stats_open(struct inode *inode, struct file *file)
{
return single_open(file, cnss_stats_show, inode->i_private);
}
static const struct file_operations cnss_stats_fops = {
.read = seq_read,
.release = single_release,
.open = cnss_stats_open,
.owner = THIS_MODULE,
.llseek = seq_lseek,
};
static ssize_t cnss_dev_boot_debug_write(struct file *fp,
const char __user *user_buf,
size_t count, loff_t *off)
{
struct cnss_plat_data *plat_priv =
((struct seq_file *)fp->private_data)->private;
struct cnss_pci_data *pci_priv;
char buf[64];
char *cmd;
unsigned int len = 0;
int ret = 0;
if (!plat_priv)
return -ENODEV;
pci_priv = plat_priv->bus_priv;
if (!pci_priv)
return -ENODEV;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
cmd = buf;
if (sysfs_streq(cmd, "on")) {
ret = cnss_power_on_device(plat_priv);
} else if (sysfs_streq(cmd, "off")) {
cnss_power_off_device(plat_priv);
} else if (sysfs_streq(cmd, "enumerate")) {
ret = cnss_pci_init(plat_priv);
} else if (sysfs_streq(cmd, "download")) {
set_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
ret = cnss_pci_start_mhi(pci_priv);
} else if (sysfs_streq(cmd, "linkup")) {
ret = cnss_resume_pci_link(pci_priv);
} else if (sysfs_streq(cmd, "linkdown")) {
ret = cnss_suspend_pci_link(pci_priv);
} else if (sysfs_streq(cmd, "powerup")) {
set_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
ret = cnss_driver_event_post(plat_priv,
CNSS_DRIVER_EVENT_POWER_UP,
CNSS_EVENT_SYNC, NULL);
} else if (sysfs_streq(cmd, "shutdown")) {
ret = cnss_driver_event_post(plat_priv,
CNSS_DRIVER_EVENT_POWER_DOWN,
0, NULL);
clear_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
} else if (sysfs_streq(cmd, "assert")) {
ret = cnss_force_fw_assert(&pci_priv->pci_dev->dev);
} else {
cnss_pr_err("Device boot debugfs command is invalid\n");
ret = -EINVAL;
}
if (ret)
return ret;
return count;
}
static int cnss_dev_boot_debug_show(struct seq_file *s, void *data)
{
seq_puts(s, "\nUsage: echo <action> > <debugfs_path>/cnss/dev_boot\n");
seq_puts(s, "<action> can be one of below:\n");
seq_puts(s, "on: turn on device power, assert WLAN_EN\n");
seq_puts(s, "off: de-assert WLAN_EN, turn off device power\n");
seq_puts(s, "enumerate: de-assert PERST, enumerate PCIe\n");
seq_puts(s, "download: download FW and do QMI handshake with FW\n");
seq_puts(s, "linkup: bring up PCIe link\n");
seq_puts(s, "linkdown: bring down PCIe link\n");
seq_puts(s, "powerup: full power on sequence to boot device, download FW and do QMI handshake with FW\n");
seq_puts(s, "shutdown: full power off sequence to shutdown device\n");
seq_puts(s, "assert: trigger firmware assert\n");
return 0;
}
static int cnss_dev_boot_debug_open(struct inode *inode, struct file *file)
{
return single_open(file, cnss_dev_boot_debug_show, inode->i_private);
}
static const struct file_operations cnss_dev_boot_debug_fops = {
.read = seq_read,
.write = cnss_dev_boot_debug_write,
.release = single_release,
.open = cnss_dev_boot_debug_open,
.owner = THIS_MODULE,
.llseek = seq_lseek,
};
static int cnss_reg_read_debug_show(struct seq_file *s, void *data)
{
struct cnss_plat_data *plat_priv = s->private;
mutex_lock(&plat_priv->dev_lock);
if (!plat_priv->diag_reg_read_buf) {
seq_puts(s, "\nUsage: echo <mem_type> <offset> <data_len> > <debugfs_path>/cnss/reg_read\n");
mutex_unlock(&plat_priv->dev_lock);
return 0;
}
seq_printf(s, "\nRegister read, address: 0x%x memory type: 0x%x length: 0x%x\n\n",
plat_priv->diag_reg_read_addr,
plat_priv->diag_reg_read_mem_type,
plat_priv->diag_reg_read_len);
seq_hex_dump(s, "", DUMP_PREFIX_OFFSET, 32, 4,
plat_priv->diag_reg_read_buf,
plat_priv->diag_reg_read_len, false);
plat_priv->diag_reg_read_len = 0;
kfree(plat_priv->diag_reg_read_buf);
plat_priv->diag_reg_read_buf = NULL;
mutex_unlock(&plat_priv->dev_lock);
return 0;
}
static ssize_t cnss_reg_read_debug_write(struct file *fp,
const char __user *user_buf,
size_t count, loff_t *off)
{
struct cnss_plat_data *plat_priv =
((struct seq_file *)fp->private_data)->private;
char buf[64];
char *sptr, *token;
unsigned int len = 0;
u32 reg_offset, mem_type;
u32 data_len = 0;
u8 *reg_buf = NULL;
const char *delim = " ";
int ret = 0;
if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
cnss_pr_err("Firmware is not ready yet\n");
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, &reg_offset))
return -EINVAL;
token = strsep(&sptr, delim);
if (!token)
return -EINVAL;
if (kstrtou32(token, 0, &data_len))
return -EINVAL;
mutex_lock(&plat_priv->dev_lock);
kfree(plat_priv->diag_reg_read_buf);
plat_priv->diag_reg_read_buf = NULL;
reg_buf = kzalloc(data_len, GFP_KERNEL);
if (!reg_buf) {
mutex_unlock(&plat_priv->dev_lock);
return -ENOMEM;
}
ret = cnss_wlfw_athdiag_read_send_sync(plat_priv, reg_offset,
mem_type, data_len,
reg_buf);
if (ret) {
kfree(reg_buf);
mutex_unlock(&plat_priv->dev_lock);
return ret;
}
plat_priv->diag_reg_read_addr = reg_offset;
plat_priv->diag_reg_read_mem_type = mem_type;
plat_priv->diag_reg_read_len = data_len;
plat_priv->diag_reg_read_buf = reg_buf;
mutex_unlock(&plat_priv->dev_lock);
return count;
}
static int cnss_reg_read_debug_open(struct inode *inode, struct file *file)
{
return single_open(file, cnss_reg_read_debug_show, inode->i_private);
}
static const struct file_operations cnss_reg_read_debug_fops = {
.read = seq_read,
.write = cnss_reg_read_debug_write,
.open = cnss_reg_read_debug_open,
.owner = THIS_MODULE,
.llseek = seq_lseek,
};
static int cnss_reg_write_debug_show(struct seq_file *s, void *data)
{
seq_puts(s, "\nUsage: echo <mem_type> <offset> <reg_val> > <debugfs_path>/cnss/reg_write\n");
return 0;
}
static ssize_t cnss_reg_write_debug_write(struct file *fp,
const char __user *user_buf,
size_t count, loff_t *off)
{
struct cnss_plat_data *plat_priv =
((struct seq_file *)fp->private_data)->private;
char buf[64];
char *sptr, *token;
unsigned int len = 0;
u32 reg_offset, mem_type, reg_val;
const char *delim = " ";
int ret = 0;
if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
cnss_pr_err("Firmware is not ready yet\n");
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, &reg_offset))
return -EINVAL;
token = strsep(&sptr, delim);
if (!token)
return -EINVAL;
if (kstrtou32(token, 0, &reg_val))
return -EINVAL;
ret = cnss_wlfw_athdiag_write_send_sync(plat_priv, reg_offset, mem_type,
sizeof(u32),
(u8 *)&reg_val);
if (ret)
return ret;
return count;
}
static int cnss_reg_write_debug_open(struct inode *inode, struct file *file)
{
return single_open(file, cnss_reg_write_debug_show, inode->i_private);
}
static const struct file_operations cnss_reg_write_debug_fops = {
.read = seq_read,
.write = cnss_reg_write_debug_write,
.open = cnss_reg_write_debug_open,
.owner = THIS_MODULE,
.llseek = seq_lseek,
};
static ssize_t cnss_runtime_pm_debug_write(struct file *fp,
const char __user *user_buf,
size_t count, loff_t *off)
{
struct cnss_plat_data *plat_priv =
((struct seq_file *)fp->private_data)->private;
struct cnss_pci_data *pci_priv;
char buf[64];
char *cmd;
unsigned int len = 0;
int ret = 0;
if (!plat_priv)
return -ENODEV;
pci_priv = plat_priv->bus_priv;
if (!pci_priv)
return -ENODEV;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
cmd = buf;
if (sysfs_streq(cmd, "usage_count")) {
cnss_pci_pm_runtime_show_usage_count(pci_priv);
} else if (sysfs_streq(cmd, "request_resume")) {
ret = cnss_pci_pm_request_resume(pci_priv);
} else if (sysfs_streq(cmd, "resume")) {
ret = cnss_pci_pm_runtime_resume(pci_priv);
} else if (sysfs_streq(cmd, "get")) {
ret = cnss_pci_pm_runtime_get(pci_priv);
} else if (sysfs_streq(cmd, "get_noresume")) {
cnss_pci_pm_runtime_get_noresume(pci_priv);
} else if (sysfs_streq(cmd, "put_autosuspend")) {
ret = cnss_pci_pm_runtime_put_autosuspend(pci_priv);
} else if (sysfs_streq(cmd, "put_noidle")) {
cnss_pci_pm_runtime_put_noidle(pci_priv);
} else if (sysfs_streq(cmd, "mark_last_busy")) {
cnss_pci_pm_runtime_mark_last_busy(pci_priv);
} else {
cnss_pr_err("Runtime PM debugfs command is invalid\n");
ret = -EINVAL;
}
if (ret)
return ret;
return count;
}
static int cnss_runtime_pm_debug_show(struct seq_file *s, void *data)
{
seq_puts(s, "\nUsage: echo <action> > <debugfs_path>/cnss/runtime_pm\n");
seq_puts(s, "<action> can be one of below:\n");
seq_puts(s, "usage_count: get runtime PM usage count\n");
seq_puts(s, "get: do runtime PM get\n");
seq_puts(s, "get_noresume: do runtime PM get noresume\n");
seq_puts(s, "put_noidle: do runtime PM put noidle\n");
seq_puts(s, "put_autosuspend: do runtime PM put autosuspend\n");
seq_puts(s, "mark_last_busy: do runtime PM mark last busy\n");
return 0;
}
static int cnss_runtime_pm_debug_open(struct inode *inode, struct file *file)
{
return single_open(file, cnss_runtime_pm_debug_show, inode->i_private);
}
static const struct file_operations cnss_runtime_pm_debug_fops = {
.read = seq_read,
.write = cnss_runtime_pm_debug_write,
.open = cnss_runtime_pm_debug_open,
.owner = THIS_MODULE,
.llseek = seq_lseek,
};
static ssize_t cnss_control_params_debug_write(struct file *fp,
const char __user *user_buf,
size_t count, loff_t *off)
{
struct cnss_plat_data *plat_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 (!plat_priv)
return -ENODEV;
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;
cmd = token;
token = strsep(&sptr, delim);
if (!token)
return -EINVAL;
if (kstrtou32(token, 0, &val))
return -EINVAL;
if (strcmp(cmd, "quirks") == 0)
plat_priv->ctrl_params.quirks = val;
else if (strcmp(cmd, "mhi_timeout") == 0)
plat_priv->ctrl_params.mhi_timeout = val;
else if (strcmp(cmd, "qmi_timeout") == 0)
plat_priv->ctrl_params.qmi_timeout = val;
else if (strcmp(cmd, "bdf_type") == 0)
plat_priv->ctrl_params.bdf_type = val;
else if (strcmp(cmd, "time_sync_period") == 0)
plat_priv->ctrl_params.time_sync_period = val;
else
return -EINVAL;
return count;
}
static int cnss_show_quirks_state(struct seq_file *s,
struct cnss_plat_data *plat_priv)
{
enum cnss_debug_quirks i;
int skip = 0;
unsigned long state;
seq_printf(s, "quirks: 0x%lx (", plat_priv->ctrl_params.quirks);
for (i = 0, state = plat_priv->ctrl_params.quirks;
state != 0; state >>= 1, i++) {
if (!(state & 0x1))
continue;
if (skip++)
seq_puts(s, " | ");
switch (i) {
case LINK_DOWN_SELF_RECOVERY:
seq_puts(s, "LINK_DOWN_SELF_RECOVERY");
continue;
case SKIP_DEVICE_BOOT:
seq_puts(s, "SKIP_DEVICE_BOOT");
continue;
case USE_CORE_ONLY_FW:
seq_puts(s, "USE_CORE_ONLY_FW");
continue;
case SKIP_RECOVERY:
seq_puts(s, "SKIP_RECOVERY");
continue;
case QMI_BYPASS:
seq_puts(s, "QMI_BYPASS");
continue;
case ENABLE_WALTEST:
seq_puts(s, "WALTEST");
continue;
case ENABLE_PCI_LINK_DOWN_PANIC:
seq_puts(s, "PCI_LINK_DOWN_PANIC");
continue;
case FBC_BYPASS:
seq_puts(s, "FBC_BYPASS");
continue;
case ENABLE_DAEMON_SUPPORT:
seq_puts(s, "DAEMON_SUPPORT");
continue;
case DISABLE_DRV:
seq_puts(s, "DISABLE_DRV");
continue;
}
seq_printf(s, "UNKNOWN-%d", i);
}
seq_puts(s, ")\n");
return 0;
}
static int cnss_control_params_debug_show(struct seq_file *s, void *data)
{
struct cnss_plat_data *cnss_priv = s->private;
seq_puts(s, "\nUsage: echo <params_name> <value> > <debugfs_path>/cnss/control_params\n");
seq_puts(s, "<params_name> can be one of below:\n");
seq_puts(s, "quirks: Debug quirks for driver\n");
seq_puts(s, "mhi_timeout: Timeout for MHI operation in milliseconds\n");
seq_puts(s, "qmi_timeout: Timeout for QMI message in milliseconds\n");
seq_puts(s, "bdf_type: Type of board data file to be downloaded\n");
seq_puts(s, "time_sync_period: Time period to do time sync with device in milliseconds\n");
seq_puts(s, "\nCurrent value:\n");
cnss_show_quirks_state(s, cnss_priv);
seq_printf(s, "mhi_timeout: %u\n", cnss_priv->ctrl_params.mhi_timeout);
seq_printf(s, "qmi_timeout: %u\n", cnss_priv->ctrl_params.qmi_timeout);
seq_printf(s, "bdf_type: %u\n", cnss_priv->ctrl_params.bdf_type);
seq_printf(s, "time_sync_period: %u\n",
cnss_priv->ctrl_params.time_sync_period);
return 0;
}
static int cnss_control_params_debug_open(struct inode *inode,
struct file *file)
{
return single_open(file, cnss_control_params_debug_show,
inode->i_private);
}
static const struct file_operations cnss_control_params_debug_fops = {
.read = seq_read,
.write = cnss_control_params_debug_write,
.open = cnss_control_params_debug_open,
.owner = THIS_MODULE,
.llseek = seq_lseek,
};
static ssize_t cnss_dynamic_feature_write(struct file *fp,
const char __user *user_buf,
size_t count, loff_t *off)
{
struct cnss_plat_data *plat_priv =
((struct seq_file *)fp->private_data)->private;
int ret = 0;
u64 val;
ret = kstrtou64_from_user(user_buf, count, 0, &val);
if (ret)
return ret;
plat_priv->dynamic_feature = val;
ret = cnss_wlfw_dynamic_feature_mask_send_sync(plat_priv);
if (ret < 0)
return ret;
return count;
}
static int cnss_dynamic_feature_show(struct seq_file *s, void *data)
{
struct cnss_plat_data *cnss_priv = s->private;
seq_printf(s, "dynamic_feature: 0x%llx\n", cnss_priv->dynamic_feature);
return 0;
}
static int cnss_dynamic_feature_open(struct inode *inode,
struct file *file)
{
return single_open(file, cnss_dynamic_feature_show,
inode->i_private);
}
static const struct file_operations cnss_dynamic_feature_fops = {
.read = seq_read,
.write = cnss_dynamic_feature_write,
.open = cnss_dynamic_feature_open,
.owner = THIS_MODULE,
.llseek = seq_lseek,
};
#ifdef CONFIG_CNSS2_DEBUG
static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv)
{
struct dentry *root_dentry = plat_priv->root_dentry;
debugfs_create_file("dev_boot", 0600, root_dentry, plat_priv,
&cnss_dev_boot_debug_fops);
debugfs_create_file("reg_read", 0600, root_dentry, plat_priv,
&cnss_reg_read_debug_fops);
debugfs_create_file("reg_write", 0600, root_dentry, plat_priv,
&cnss_reg_write_debug_fops);
debugfs_create_file("runtime_pm", 0600, root_dentry, plat_priv,
&cnss_runtime_pm_debug_fops);
debugfs_create_file("control_params", 0600, root_dentry, plat_priv,
&cnss_control_params_debug_fops);
debugfs_create_file("dynamic_feature", 0600, root_dentry, plat_priv,
&cnss_dynamic_feature_fops);
return 0;
}
#else
static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv)
{
return 0;
}
#endif
int cnss_debugfs_create(struct cnss_plat_data *plat_priv)
{
int ret = 0;
struct dentry *root_dentry;
root_dentry = debugfs_create_dir("cnss", 0);
if (IS_ERR(root_dentry)) {
ret = PTR_ERR(root_dentry);
cnss_pr_err("Unable to create debugfs %d\n", ret);
goto out;
}
plat_priv->root_dentry = root_dentry;
debugfs_create_file("pin_connect_result", 0644, root_dentry, plat_priv,
&cnss_pin_connect_fops);
debugfs_create_file("stats", 0644, root_dentry, plat_priv,
&cnss_stats_fops);
cnss_create_debug_only_node(plat_priv);
out:
return ret;
}
void cnss_debugfs_destroy(struct cnss_plat_data *plat_priv)
{
debugfs_remove_recursive(plat_priv->root_dentry);
}
int cnss_debug_init(void)
{
cnss_ipc_log_context = ipc_log_context_create(CNSS_IPC_LOG_PAGES,
"cnss", 0);
if (!cnss_ipc_log_context) {
cnss_pr_err("Unable to create IPC log context\n");
return -EINVAL;
}
cnss_ipc_log_long_context = ipc_log_context_create(CNSS_IPC_LOG_PAGES,
"cnss-long", 0);
if (!cnss_ipc_log_long_context) {
cnss_pr_err("Unable to create IPC long log context\n");
ipc_log_context_destroy(cnss_ipc_log_context);
return -EINVAL;
}
return 0;
}
void cnss_debug_deinit(void)
{
if (cnss_ipc_log_long_context) {
ipc_log_context_destroy(cnss_ipc_log_long_context);
cnss_ipc_log_long_context = NULL;
}
if (cnss_ipc_log_context) {
ipc_log_context_destroy(cnss_ipc_log_context);
cnss_ipc_log_context = NULL;
}
}

View File

@ -0,0 +1,77 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */
#ifndef _CNSS_DEBUG_H
#define _CNSS_DEBUG_H
#include <linux/ipc_logging.h>
#include <linux/printk.h>
#define CNSS_IPC_LOG_PAGES 32
extern void *cnss_ipc_log_context;
extern void *cnss_ipc_log_long_context;
#define cnss_ipc_log_string(_x...) do { \
if (cnss_ipc_log_context) \
ipc_log_string(cnss_ipc_log_context, _x); \
} while (0)
#define cnss_ipc_log_long_string(_x...) do { \
if (cnss_ipc_log_long_context) \
ipc_log_string(cnss_ipc_log_long_context, _x); \
} while (0)
#define cnss_pr_err(_fmt, ...) do { \
printk("%scnss: " _fmt, KERN_ERR, ##__VA_ARGS__); \
cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\
} while (0)
#define cnss_pr_warn(_fmt, ...) do { \
printk("%scnss: " _fmt, KERN_WARNING, ##__VA_ARGS__); \
cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\
} while (0)
#define cnss_pr_info(_fmt, ...) do { \
printk("%scnss: " _fmt, KERN_INFO, ##__VA_ARGS__); \
cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\
} while (0)
#define cnss_pr_dbg(_fmt, ...) do { \
printk("%scnss: " _fmt, KERN_DEBUG, ##__VA_ARGS__); \
cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\
} while (0)
#define cnss_pr_vdbg(_fmt, ...) do { \
printk("%scnss: " _fmt, KERN_DEBUG, ##__VA_ARGS__); \
cnss_ipc_log_long_string("%scnss: " _fmt, "", \
##__VA_ARGS__); \
} while (0)
#ifdef CONFIG_CNSS2_DEBUG
#define CNSS_ASSERT(_condition) do { \
if (!(_condition)) { \
cnss_pr_err("ASSERT at line %d\n", \
__LINE__); \
BUG(); \
} \
} while (0)
#else
#define CNSS_ASSERT(_condition) do { \
if (!(_condition)) { \
cnss_pr_err("ASSERT at line %d\n", \
__LINE__); \
WARN_ON(1); \
} \
} while (0)
#endif
#define cnss_fatal_err(_fmt, ...) \
cnss_pr_err("fatal: " _fmt, ##__VA_ARGS__)
int cnss_debug_init(void);
void cnss_debug_deinit(void);
int cnss_debugfs_create(struct cnss_plat_data *plat_priv);
void cnss_debugfs_destroy(struct cnss_plat_data *plat_priv);
#endif /* _CNSS_DEBUG_H */

View File

@ -0,0 +1,203 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2019, The Linux Foundation. All rights reserved. */
#define pr_fmt(fmt) "cnss_genl: " fmt
#include <linux/err.h>
#include <linux/module.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include "main.h"
#include "debug.h"
#define CNSS_GENL_FAMILY_NAME "cnss-genl"
#define CNSS_GENL_MCAST_GROUP_NAME "cnss-genl-grp"
#define CNSS_GENL_VERSION 1
#define CNSS_GENL_DATA_LEN_MAX (15 * 1024)
#define CNSS_GENL_STR_LEN_MAX 16
enum {
CNSS_GENL_ATTR_MSG_UNSPEC,
CNSS_GENL_ATTR_MSG_TYPE,
CNSS_GENL_ATTR_MSG_FILE_NAME,
CNSS_GENL_ATTR_MSG_TOTAL_SIZE,
CNSS_GENL_ATTR_MSG_SEG_ID,
CNSS_GENL_ATTR_MSG_END,
CNSS_GENL_ATTR_MSG_DATA_LEN,
CNSS_GENL_ATTR_MSG_DATA,
__CNSS_GENL_ATTR_MAX,
};
#define CNSS_GENL_ATTR_MAX (__CNSS_GENL_ATTR_MAX - 1)
enum {
CNSS_GENL_CMD_UNSPEC,
CNSS_GENL_CMD_MSG,
__CNSS_GENL_CMD_MAX,
};
#define CNSS_GENL_CMD_MAX (__CNSS_GENL_CMD_MAX - 1)
static struct nla_policy cnss_genl_msg_policy[CNSS_GENL_ATTR_MAX + 1] = {
[CNSS_GENL_ATTR_MSG_TYPE] = { .type = NLA_U8 },
[CNSS_GENL_ATTR_MSG_FILE_NAME] = { .type = NLA_NUL_STRING,
.len = CNSS_GENL_STR_LEN_MAX },
[CNSS_GENL_ATTR_MSG_TOTAL_SIZE] = { .type = NLA_U32 },
[CNSS_GENL_ATTR_MSG_SEG_ID] = { .type = NLA_U32 },
[CNSS_GENL_ATTR_MSG_END] = { .type = NLA_U8 },
[CNSS_GENL_ATTR_MSG_DATA_LEN] = { .type = NLA_U32 },
[CNSS_GENL_ATTR_MSG_DATA] = { .type = NLA_BINARY,
.len = CNSS_GENL_DATA_LEN_MAX },
};
static int cnss_genl_process_msg(struct sk_buff *skb, struct genl_info *info)
{
return 0;
}
static struct genl_ops cnss_genl_ops[] = {
{
.cmd = CNSS_GENL_CMD_MSG,
.policy = cnss_genl_msg_policy,
.doit = cnss_genl_process_msg,
},
};
static struct genl_multicast_group cnss_genl_mcast_grp[] = {
{
.name = CNSS_GENL_MCAST_GROUP_NAME,
},
};
static struct genl_family cnss_genl_family = {
.id = 0,
.hdrsize = 0,
.name = CNSS_GENL_FAMILY_NAME,
.version = CNSS_GENL_VERSION,
.maxattr = CNSS_GENL_ATTR_MAX,
.module = THIS_MODULE,
.ops = cnss_genl_ops,
.n_ops = ARRAY_SIZE(cnss_genl_ops),
.mcgrps = cnss_genl_mcast_grp,
.n_mcgrps = ARRAY_SIZE(cnss_genl_mcast_grp),
};
static int cnss_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[CNSS_GENL_STR_LEN_MAX + 1];
cnss_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,
&cnss_genl_family, 0,
CNSS_GENL_CMD_MSG);
if (!msg_header) {
ret = -ENOMEM;
goto fail;
}
ret = nla_put_u8(skb, CNSS_GENL_ATTR_MSG_TYPE, type);
if (ret < 0)
goto fail;
ret = nla_put_string(skb, CNSS_GENL_ATTR_MSG_FILE_NAME, filename);
if (ret < 0)
goto fail;
ret = nla_put_u32(skb, CNSS_GENL_ATTR_MSG_TOTAL_SIZE, total_size);
if (ret < 0)
goto fail;
ret = nla_put_u32(skb, CNSS_GENL_ATTR_MSG_SEG_ID, seg_id);
if (ret < 0)
goto fail;
ret = nla_put_u8(skb, CNSS_GENL_ATTR_MSG_END, end);
if (ret < 0)
goto fail;
ret = nla_put_u32(skb, CNSS_GENL_ATTR_MSG_DATA_LEN, data_len);
if (ret < 0)
goto fail;
ret = nla_put(skb, CNSS_GENL_ATTR_MSG_DATA, data_len, msg_buff);
if (ret < 0)
goto fail;
genlmsg_end(skb, msg_header);
ret = genlmsg_multicast(&cnss_genl_family, skb, 0, 0, GFP_KERNEL);
if (ret < 0)
cnss_pr_err("Fail to send genl msg: %d\n", ret);
return ret;
fail:
cnss_pr_err("Fail to generate genl msg: %d\n", ret);
if (skb)
nlmsg_free(skb);
return ret;
}
int cnss_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;
cnss_pr_dbg("type: %u, total_size: %x\n", type, total_size);
while (remaining) {
if (remaining > CNSS_GENL_DATA_LEN_MAX) {
data_len = CNSS_GENL_DATA_LEN_MAX;
} else {
data_len = remaining;
end = 1;
}
ret = cnss_genl_send_data(type, file_name, total_size,
seg_id, end, data_len, msg_buff);
if (ret < 0) {
cnss_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 cnss_genl_init(void)
{
int ret = 0;
ret = genl_register_family(&cnss_genl_family);
if (ret != 0)
cnss_pr_err("genl_register_family fail: %d\n", ret);
return ret;
}
void cnss_genl_exit(void)
{
genl_unregister_family(&cnss_genl_family);
}

View File

@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2019, The Linux Foundation. All rights reserved. */
#ifndef __CNSS_GENL_H__
#define __CNSS_GENL_H__
enum cnss_genl_msg_type {
CNSS_GENL_MSG_TYPE_UNSPEC,
CNSS_GENL_MSG_TYPE_QDSS,
};
#ifdef CONFIG_CNSS2_DEBUG
int cnss_genl_init(void);
void cnss_genl_exit(void);
int cnss_genl_send_msg(void *buff, u8 type,
char *file_name, u32 total_size);
#else
static inline int cnss_genl_init(void)
{
return 0;
}
static inline void cnss_genl_exit(void)
{
}
static inline int cnss_genl_send_msg(void *buff, u8 type,
char *file_name, u32 total_size)
{
return 0;
}
#endif
#endif

View File

@ -0,0 +1,93 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2019, The Linux Foundation. All rights reserved. */
#include <linux/soc/qcom/qmi.h>
#include "ip_multimedia_subsystem_private_service_v01.h"
struct qmi_elem_info
ims_private_service_subscribe_for_indications_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
ims_private_service_subscribe_for_indications_req_msg_v01,
mt_invite_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct
ims_private_service_subscribe_for_indications_req_msg_v01,
mt_invite),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct
ims_private_service_subscribe_for_indications_req_msg_v01,
wfc_call_status_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct
ims_private_service_subscribe_for_indications_req_msg_v01,
wfc_call_status),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
struct qmi_elem_info
ims_private_service_subscribe_for_indications_rsp_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
ims_private_service_subscribe_for_indications_rsp_msg_v01,
resp),
.ei_array = qmi_response_type_v01_ei,
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
struct qmi_elem_info ims_private_service_wfc_call_status_ind_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct
ims_private_service_wfc_call_status_ind_msg_v01,
wfc_call_active),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};

View File

@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2019, The Linux Foundation. All rights reserved. */
#ifndef IP_MULTIMEDIA_SUBSYSTEM_PRIVATE_SERVICE_V01_H
#define IP_MULTIMEDIA_SUBSYSTEM_PRIVATE_SERVICE_V01_H
#define IMSPRIVATE_SERVICE_ID_V01 0x4D
#define IMSPRIVATE_SERVICE_VERS_V01 0x01
#define IMSPRIVATE_SERVICE_MAX_MSG_LEN 8
#define QMI_IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_RSP_V01 0x003E
#define QMI_IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_REQ_V01 0x003E
#define QMI_IMS_PRIVATE_SERVICE_WFC_CALL_STATUS_IND_V01 0x0040
struct ims_private_service_subscribe_for_indications_req_msg_v01 {
u8 mt_invite_valid;
u8 mt_invite;
u8 wfc_call_status_valid;
u8 wfc_call_status;
};
#define IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_REQ_MSG_V01_MAX_MSG_LEN 8
extern struct
qmi_elem_info ims_private_service_subscribe_for_indications_req_msg_v01_ei[];
struct ims_private_service_subscribe_for_indications_rsp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_RSP_MSG_V01_MAX_MSG_LEN 7
extern struct
qmi_elem_info ims_private_service_subscribe_for_indications_rsp_msg_v01_ei[];
struct ims_private_service_wfc_call_status_ind_msg_v01 {
u8 wfc_call_active;
};
#define IMS_PRIVATE_SERVICE_WFC_CALL_STATUS_IND_MSG_V01_MAX_MSG_LEN 4
extern struct
qmi_elem_info ims_private_service_wfc_call_status_ind_msg_v01_ei[];
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,408 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */
#ifndef _CNSS_MAIN_H
#define _CNSS_MAIN_H
#include <asm/arch_timer.h>
#include <linux/esoc_client.h>
#include <linux/etherdevice.h>
#include <linux/interconnect.h>
#include <linux/pm_qos.h>
#include <net/cnss2.h>
#include <soc/qcom/memory_dump.h>
#include <soc/qcom/subsystem_restart.h>
#include "qmi.h"
#define MAX_NO_OF_MAC_ADDR 4
#define QMI_WLFW_MAX_TIMESTAMP_LEN 32
#define QMI_WLFW_MAX_NUM_MEM_SEG 32
#define CNSS_RDDM_TIMEOUT_MS 20000
#define RECOVERY_TIMEOUT 60000
#define TIME_CLOCK_FREQ_HZ 19200000
#define CNSS_EVENT_SYNC BIT(0)
#define CNSS_EVENT_UNINTERRUPTIBLE BIT(1)
#define CNSS_EVENT_SYNC_UNINTERRUPTIBLE (CNSS_EVENT_SYNC | \
CNSS_EVENT_UNINTERRUPTIBLE)
enum cnss_dev_bus_type {
CNSS_BUS_NONE = -1,
CNSS_BUS_PCI,
};
struct cnss_vreg_cfg {
const char *name;
u32 min_uv;
u32 max_uv;
u32 load_ua;
u32 delay_us;
u32 need_unvote;
};
struct cnss_vreg_info {
struct list_head list;
struct regulator *reg;
struct cnss_vreg_cfg cfg;
u32 enabled;
};
enum cnss_vreg_type {
CNSS_VREG_PRIM,
};
struct cnss_clk_cfg {
const char *name;
u32 freq;
u32 required;
};
struct cnss_clk_info {
struct list_head list;
struct clk *clk;
struct cnss_clk_cfg cfg;
u32 enabled;
};
struct cnss_pinctrl_info {
struct pinctrl *pinctrl;
struct pinctrl_state *bootstrap_active;
struct pinctrl_state *wlan_en_active;
struct pinctrl_state *wlan_en_sleep;
};
struct cnss_subsys_info {
struct subsys_device *subsys_device;
struct subsys_desc subsys_desc;
void *subsys_handle;
};
struct cnss_ramdump_info {
struct ramdump_device *ramdump_dev;
unsigned long ramdump_size;
void *ramdump_va;
phys_addr_t ramdump_pa;
struct msm_dump_data dump_data;
};
struct cnss_dump_seg {
unsigned long address;
void *v_address;
unsigned long size;
u32 type;
};
struct cnss_dump_data {
u32 version;
u32 magic;
char name[32];
phys_addr_t paddr;
int nentries;
u32 seg_version;
};
struct cnss_ramdump_info_v2 {
struct ramdump_device *ramdump_dev;
unsigned long ramdump_size;
void *dump_data_vaddr;
u8 dump_data_valid;
struct cnss_dump_data dump_data;
};
struct cnss_esoc_info {
struct esoc_desc *esoc_desc;
u8 notify_modem_status;
void *modem_notify_handler;
int modem_current_status;
};
struct cnss_bus_bw_cfg {
u32 ab;
u32 ib;
};
struct cnss_bus_bw_info {
struct icc_path *cnss_path;
int current_bw_vote;
};
struct cnss_fw_mem {
size_t size;
void *va;
phys_addr_t pa;
u8 valid;
u32 type;
};
struct wlfw_rf_chip_info {
u32 chip_id;
u32 chip_family;
};
struct wlfw_rf_board_info {
u32 board_id;
};
struct wlfw_soc_info {
u32 soc_id;
};
struct wlfw_fw_version_info {
u32 fw_version;
char fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN + 1];
};
enum cnss_mem_type {
CNSS_MEM_TYPE_MSA,
CNSS_MEM_TYPE_DDR,
CNSS_MEM_BDF,
CNSS_MEM_M3,
CNSS_MEM_CAL_V01,
CNSS_MEM_DPD_V01,
};
enum cnss_fw_dump_type {
CNSS_FW_IMAGE,
CNSS_FW_RDDM,
CNSS_FW_REMOTE_HEAP,
};
enum cnss_driver_event_type {
CNSS_DRIVER_EVENT_SERVER_ARRIVE,
CNSS_DRIVER_EVENT_SERVER_EXIT,
CNSS_DRIVER_EVENT_REQUEST_MEM,
CNSS_DRIVER_EVENT_FW_MEM_READY,
CNSS_DRIVER_EVENT_FW_READY,
CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START,
CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE,
CNSS_DRIVER_EVENT_REGISTER_DRIVER,
CNSS_DRIVER_EVENT_UNREGISTER_DRIVER,
CNSS_DRIVER_EVENT_RECOVERY,
CNSS_DRIVER_EVENT_FORCE_FW_ASSERT,
CNSS_DRIVER_EVENT_POWER_UP,
CNSS_DRIVER_EVENT_POWER_DOWN,
CNSS_DRIVER_EVENT_IDLE_RESTART,
CNSS_DRIVER_EVENT_IDLE_SHUTDOWN,
CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM,
CNSS_DRIVER_EVENT_QDSS_TRACE_SAVE,
CNSS_DRIVER_EVENT_QDSS_TRACE_FREE,
CNSS_DRIVER_EVENT_MAX,
};
enum cnss_driver_state {
CNSS_QMI_WLFW_CONNECTED,
CNSS_FW_MEM_READY,
CNSS_FW_READY,
CNSS_COLD_BOOT_CAL,
CNSS_DRIVER_LOADING,
CNSS_DRIVER_UNLOADING,
CNSS_DRIVER_IDLE_RESTART,
CNSS_DRIVER_IDLE_SHUTDOWN,
CNSS_DRIVER_PROBED,
CNSS_DRIVER_RECOVERY,
CNSS_FW_BOOT_RECOVERY,
CNSS_DEV_ERR_NOTIFY,
CNSS_DRIVER_DEBUG,
CNSS_COEX_CONNECTED,
CNSS_IMS_CONNECTED,
CNSS_IN_SUSPEND_RESUME,
};
struct cnss_recovery_data {
enum cnss_recovery_reason reason;
};
enum cnss_pins {
CNSS_WLAN_EN,
CNSS_PCIE_TXP,
CNSS_PCIE_TXN,
CNSS_PCIE_RXP,
CNSS_PCIE_RXN,
CNSS_PCIE_REFCLKP,
CNSS_PCIE_REFCLKN,
CNSS_PCIE_RST,
CNSS_PCIE_WAKE,
};
struct cnss_pin_connect_result {
u32 fw_pwr_pin_result;
u32 fw_phy_io_pin_result;
u32 fw_rf_pin_result;
u32 host_pin_result;
};
enum cnss_debug_quirks {
LINK_DOWN_SELF_RECOVERY,
SKIP_DEVICE_BOOT,
USE_CORE_ONLY_FW,
SKIP_RECOVERY,
QMI_BYPASS,
ENABLE_WALTEST,
ENABLE_PCI_LINK_DOWN_PANIC,
FBC_BYPASS,
ENABLE_DAEMON_SUPPORT,
DISABLE_DRV,
};
enum cnss_bdf_type {
CNSS_BDF_BIN,
CNSS_BDF_ELF,
CNSS_BDF_REGDB = 4,
CNSS_BDF_DUMMY = 255,
};
enum cnss_cal_status {
CNSS_CAL_DONE,
CNSS_CAL_TIMEOUT,
};
struct cnss_cal_info {
enum cnss_cal_status cal_status;
};
struct cnss_control_params {
unsigned long quirks;
unsigned int mhi_timeout;
unsigned int qmi_timeout;
unsigned int bdf_type;
unsigned int time_sync_period;
};
struct cnss_cpr_info {
resource_size_t tcs_cmd_base_addr;
resource_size_t tcs_cmd_data_addr;
void __iomem *tcs_cmd_base_addr_io;
void __iomem *tcs_cmd_data_addr_io;
u32 cpr_pmic_addr;
u32 voltage;
};
enum cnss_ce_index {
CNSS_CE_00,
CNSS_CE_01,
CNSS_CE_02,
CNSS_CE_03,
CNSS_CE_04,
CNSS_CE_05,
CNSS_CE_06,
CNSS_CE_07,
CNSS_CE_08,
CNSS_CE_09,
CNSS_CE_10,
CNSS_CE_11,
CNSS_CE_COMMON,
};
struct cnss_plat_data {
struct platform_device *plat_dev;
void *bus_priv;
enum cnss_dev_bus_type bus_type;
struct list_head vreg_list;
struct list_head clk_list;
struct cnss_pinctrl_info pinctrl_info;
struct cnss_subsys_info subsys_info;
struct cnss_ramdump_info ramdump_info;
struct cnss_ramdump_info_v2 ramdump_info_v2;
struct cnss_esoc_info esoc_info;
struct cnss_bus_bw_info bus_bw_info;
struct notifier_block modem_nb;
struct cnss_platform_cap cap;
struct pm_qos_request qos_request;
struct cnss_device_version device_version;
unsigned long device_id;
enum cnss_driver_status driver_status;
u32 recovery_count;
unsigned long driver_state;
struct list_head event_list;
spinlock_t event_lock; /* spinlock for driver work event handling */
struct work_struct event_work;
struct workqueue_struct *event_wq;
struct qmi_handle qmi_wlfw;
struct wlfw_rf_chip_info chip_info;
struct wlfw_rf_board_info board_info;
struct wlfw_soc_info soc_info;
struct wlfw_fw_version_info fw_version_info;
u32 otp_version;
u32 fw_mem_seg_len;
struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG];
struct cnss_fw_mem m3_mem;
u32 qdss_mem_seg_len;
struct cnss_fw_mem qdss_mem[QMI_WLFW_MAX_NUM_MEM_SEG];
u32 *qdss_reg;
struct cnss_pin_connect_result pin_result;
struct dentry *root_dentry;
atomic_t pm_count;
struct timer_list fw_boot_timer;
struct completion power_up_complete;
struct completion cal_complete;
struct mutex dev_lock; /* mutex for register access through debugfs */
u32 device_freq_hz;
u32 diag_reg_read_addr;
u32 diag_reg_read_mem_type;
u32 diag_reg_read_len;
u8 *diag_reg_read_buf;
u8 cal_done;
u8 powered_on;
char firmware_name[13];
struct completion rddm_complete;
struct completion recovery_complete;
struct cnss_control_params ctrl_params;
struct cnss_cpr_info cpr_info;
u64 antenna;
u64 grant;
struct qmi_handle coex_qmi;
struct qmi_handle ims_qmi;
struct qmi_txn txn;
u64 dynamic_feature;
};
#ifdef CONFIG_ARCH_QCOM
static inline u64 cnss_get_host_timestamp(struct cnss_plat_data *plat_priv)
{
u64 ticks = arch_counter_get_cntvct();
do_div(ticks, TIME_CLOCK_FREQ_HZ / 100000);
return ticks * 10;
}
#else
static inline u64 cnss_get_host_timestamp(struct cnss_plat_data *plat_priv)
{
struct timespec ts;
ktime_get_ts(&ts);
return ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
}
#endif
struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev);
int cnss_driver_event_post(struct cnss_plat_data *plat_priv,
enum cnss_driver_event_type type,
u32 flags, void *data);
int cnss_get_vreg_type(struct cnss_plat_data *plat_priv,
enum cnss_vreg_type type);
void cnss_put_vreg_type(struct cnss_plat_data *plat_priv,
enum cnss_vreg_type type);
int cnss_vreg_on_type(struct cnss_plat_data *plat_priv,
enum cnss_vreg_type type);
int cnss_vreg_off_type(struct cnss_plat_data *plat_priv,
enum cnss_vreg_type type);
int cnss_get_clk(struct cnss_plat_data *plat_priv);
void cnss_put_clk(struct cnss_plat_data *plat_priv);
int cnss_vreg_unvote_type(struct cnss_plat_data *plat_priv,
enum cnss_vreg_type type);
int cnss_get_pinctrl(struct cnss_plat_data *plat_priv);
int cnss_power_on_device(struct cnss_plat_data *plat_priv);
void cnss_power_off_device(struct cnss_plat_data *plat_priv);
bool cnss_is_device_powered_on(struct cnss_plat_data *plat_priv);
int cnss_register_subsys(struct cnss_plat_data *plat_priv);
void cnss_unregister_subsys(struct cnss_plat_data *plat_priv);
int cnss_register_ramdump(struct cnss_plat_data *plat_priv);
void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv);
void cnss_set_pin_connect_status(struct cnss_plat_data *plat_priv);
int cnss_get_cpr_info(struct cnss_plat_data *plat_priv);
int cnss_update_cpr_info(struct cnss_plat_data *plat_priv);
#endif /* _CNSS_MAIN_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,187 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */
#ifndef _CNSS_PCI_H
#define _CNSS_PCI_H
#include <asm/dma-iommu.h>
#include <linux/iommu.h>
#include <linux/mhi.h>
#include <linux/msm_pcie.h>
#include <linux/pci.h>
#include "main.h"
enum cnss_mhi_state {
CNSS_MHI_INIT,
CNSS_MHI_DEINIT,
CNSS_MHI_POWER_ON,
CNSS_MHI_POWER_OFF,
CNSS_MHI_FORCE_POWER_OFF,
CNSS_MHI_SUSPEND,
CNSS_MHI_RESUME,
CNSS_MHI_TRIGGER_RDDM,
CNSS_MHI_RDDM,
CNSS_MHI_RDDM_DONE,
};
enum pci_link_status {
PCI_GEN1,
PCI_GEN2,
PCI_DEF,
};
struct cnss_msi_user {
char *name;
int num_vectors;
u32 base_vector;
};
struct cnss_msi_config {
int total_vectors;
int total_users;
struct cnss_msi_user *users;
};
struct cnss_pci_reg {
char *name;
u32 offset;
};
struct cnss_pci_debug_reg {
u32 offset;
u32 val;
};
struct cnss_pci_data {
struct pci_dev *pci_dev;
struct cnss_plat_data *plat_priv;
const struct pci_device_id *pci_device_id;
u32 device_id;
u16 revision_id;
struct cnss_wlan_driver *driver_ops;
u8 pci_link_state;
u8 pci_link_down_ind;
struct pci_saved_state *saved_state;
struct pci_saved_state *default_state;
struct msm_pcie_register_event msm_pci_event;
atomic_t auto_suspended;
atomic_t drv_connected;
u8 drv_connected_last;
u16 def_link_speed;
u16 def_link_width;
u8 monitor_wake_intr;
struct iommu_domain *iommu_domain;
u8 smmu_s1_enable;
dma_addr_t smmu_iova_start;
size_t smmu_iova_len;
dma_addr_t smmu_iova_ipa_start;
size_t smmu_iova_ipa_len;
void __iomem *bar;
struct cnss_msi_config *msi_config;
u32 msi_ep_base_data;
struct mhi_controller *mhi_ctrl;
unsigned long mhi_state;
u32 remap_window;
struct timer_list dev_rddm_timer;
struct delayed_work time_sync_work;
u8 disable_pc;
struct cnss_pci_debug_reg *debug_reg;
};
static inline void cnss_set_pci_priv(struct pci_dev *pci_dev, void *data)
{
pci_set_drvdata(pci_dev, data);
}
static inline struct cnss_pci_data *cnss_get_pci_priv(struct pci_dev *pci_dev)
{
return pci_get_drvdata(pci_dev);
}
static inline struct cnss_plat_data *cnss_pci_priv_to_plat_priv(void *bus_priv)
{
struct cnss_pci_data *pci_priv = bus_priv;
return pci_priv->plat_priv;
}
static inline void cnss_pci_set_monitor_wake_intr(void *bus_priv, bool val)
{
struct cnss_pci_data *pci_priv = bus_priv;
pci_priv->monitor_wake_intr = val;
}
static inline bool cnss_pci_get_monitor_wake_intr(void *bus_priv)
{
struct cnss_pci_data *pci_priv = bus_priv;
return pci_priv->monitor_wake_intr;
}
static inline void cnss_pci_set_auto_suspended(void *bus_priv, int val)
{
struct cnss_pci_data *pci_priv = bus_priv;
atomic_set(&pci_priv->auto_suspended, val);
}
static inline int cnss_pci_get_auto_suspended(void *bus_priv)
{
struct cnss_pci_data *pci_priv = bus_priv;
return atomic_read(&pci_priv->auto_suspended);
}
static inline void cnss_pci_set_drv_connected(void *bus_priv, int val)
{
struct cnss_pci_data *pci_priv = bus_priv;
atomic_set(&pci_priv->drv_connected, val);
}
static inline int cnss_pci_get_drv_connected(void *bus_priv)
{
struct cnss_pci_data *pci_priv = bus_priv;
return atomic_read(&pci_priv->drv_connected);
}
int cnss_suspend_pci_link(struct cnss_pci_data *pci_priv);
int cnss_resume_pci_link(struct cnss_pci_data *pci_priv);
int cnss_pci_init(struct cnss_plat_data *plat_priv);
void cnss_pci_deinit(struct cnss_plat_data *plat_priv);
int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv);
int cnss_pci_alloc_qdss_mem(struct cnss_pci_data *pci_priv);
void cnss_pci_free_qdss_mem(struct cnss_pci_data *pci_priv);
int cnss_pci_load_m3(struct cnss_pci_data *pci_priv);
int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv);
void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic);
void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv);
u32 cnss_pci_get_wake_msi(struct cnss_pci_data *pci_priv);
int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv);
void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv);
int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv);
int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv);
int cnss_pci_dev_powerup(struct cnss_pci_data *pci_priv);
int cnss_pci_dev_shutdown(struct cnss_pci_data *pci_priv);
int cnss_pci_dev_crash_shutdown(struct cnss_pci_data *pci_priv);
int cnss_pci_dev_ramdump(struct cnss_pci_data *pci_priv);
int cnss_pci_register_driver_hdlr(struct cnss_pci_data *pci_priv, void *data);
int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv);
int cnss_pci_call_driver_modem_status(struct cnss_pci_data *pci_priv,
int modem_current_status);
void cnss_pci_pm_runtime_show_usage_count(struct cnss_pci_data *pci_priv);
int cnss_pci_pm_request_resume(struct cnss_pci_data *pci_priv);
int cnss_pci_pm_runtime_resume(struct cnss_pci_data *pci_priv);
int cnss_pci_pm_runtime_get(struct cnss_pci_data *pci_priv);
int cnss_pci_pm_runtime_get_sync(struct cnss_pci_data *pci_priv);
void cnss_pci_pm_runtime_get_noresume(struct cnss_pci_data *pci_priv);
int cnss_pci_pm_runtime_put_autosuspend(struct cnss_pci_data *pci_priv);
void cnss_pci_pm_runtime_put_noidle(struct cnss_pci_data *pci_priv);
void cnss_pci_pm_runtime_mark_last_busy(struct cnss_pci_data *pci_priv);
int cnss_pci_update_status(struct cnss_pci_data *pci_priv,
enum cnss_driver_status status);
#endif /* _CNSS_PCI_H */

View File

@ -0,0 +1,957 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/regulator/consumer.h>
#include <soc/qcom/cmd-db.h>
#include "main.h"
#include "debug.h"
static struct cnss_vreg_cfg cnss_vreg_list[] = {
{"vdd-wlan-core", 1300000, 1300000, 0, 0, 0},
{"vdd-wlan-io", 1800000, 1800000, 0, 0, 0},
{"vdd-wlan-xtal-aon", 0, 0, 0, 0, 0},
{"vdd-wlan-xtal", 1800000, 1800000, 0, 2, 0},
{"vdd-wlan", 0, 0, 0, 0, 0},
{"vdd-wlan-ctrl1", 0, 0, 0, 0, 0},
{"vdd-wlan-ctrl2", 0, 0, 0, 0, 0},
{"vdd-wlan-sp2t", 2700000, 2700000, 0, 0, 0},
{"wlan-ant-switch", 1800000, 1800000, 0, 0, 0},
{"wlan-soc-swreg", 1200000, 1200000, 0, 0, 0},
{"vdd-wlan-aon", 950000, 950000, 0, 0, 0},
{"vdd-wlan-dig", 950000, 952000, 0, 0, 0},
{"vdd-wlan-rfa1", 1900000, 1900000, 0, 0, 0},
{"vdd-wlan-rfa2", 1350000, 1350000, 0, 0, 0},
{"vdd-wlan-en", 0, 0, 0, 10, 0},
};
static struct cnss_clk_cfg cnss_clk_list[] = {
{"rf_clk", 0, 0},
};
#define CNSS_VREG_INFO_SIZE ARRAY_SIZE(cnss_vreg_list)
#define CNSS_CLK_INFO_SIZE ARRAY_SIZE(cnss_clk_list)
#define MAX_PROP_SIZE 32
#define BOOTSTRAP_GPIO "qcom,enable-bootstrap-gpio"
#define BOOTSTRAP_ACTIVE "bootstrap_active"
#define WLAN_EN_GPIO "wlan-en-gpio"
#define WLAN_EN_ACTIVE "wlan_en_active"
#define WLAN_EN_SLEEP "wlan_en_sleep"
#define BOOTSTRAP_DELAY 1000
#define WLAN_ENABLE_DELAY 1000
#define TCS_CMD_DATA_ADDR_OFFSET 0x4
#define TCS_OFFSET 0xC8
#define TCS_CMD_OFFSET 0x10
#define MAX_TCS_NUM 8
#define MAX_TCS_CMD_NUM 5
#define BT_CXMX_VOLTAGE_MV 950
static int cnss_get_vreg_single(struct cnss_plat_data *plat_priv,
struct cnss_vreg_info *vreg)
{
int ret = 0;
struct device *dev;
struct regulator *reg;
const __be32 *prop;
char prop_name[MAX_PROP_SIZE] = {0};
int len;
dev = &plat_priv->plat_dev->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)
cnss_pr_info("EPROBE_DEFER for regulator: %s\n",
vreg->cfg.name);
else
cnss_pr_err("Failed to get regulator %s, err = %d\n",
vreg->cfg.name, ret);
return ret;
}
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);
if (!prop || len != (5 * sizeof(__be32))) {
cnss_pr_dbg("Property %s %s, use default\n", prop_name,
prop ? "invalid format" : "doesn't exist");
} else {
vreg->cfg.min_uv = be32_to_cpup(&prop[0]);
vreg->cfg.max_uv = be32_to_cpup(&prop[1]);
vreg->cfg.load_ua = be32_to_cpup(&prop[2]);
vreg->cfg.delay_us = be32_to_cpup(&prop[3]);
vreg->cfg.need_unvote = be32_to_cpup(&prop[4]);
}
cnss_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;
}
static void cnss_put_vreg_single(struct cnss_plat_data *plat_priv,
struct cnss_vreg_info *vreg)
{
struct device *dev = &plat_priv->plat_dev->dev;
cnss_pr_dbg("Put regulator: %s\n", vreg->cfg.name);
devm_regulator_put(vreg->reg);
devm_kfree(dev, vreg);
}
static int cnss_vreg_on_single(struct cnss_vreg_info *vreg)
{
int ret = 0;
if (vreg->enabled) {
cnss_pr_dbg("Regulator %s is already enabled\n",
vreg->cfg.name);
return 0;
}
cnss_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) {
cnss_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) {
cnss_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) {
cnss_pr_err("Failed to enable regulator %s, err = %d\n",
vreg->cfg.name, ret);
goto out;
}
vreg->enabled = true;
out:
return ret;
}
static int cnss_vreg_unvote_single(struct cnss_vreg_info *vreg)
{
int ret = 0;
if (!vreg->enabled) {
cnss_pr_dbg("Regulator %s is already disabled\n",
vreg->cfg.name);
return 0;
}
cnss_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)
cnss_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)
cnss_pr_err("Failed to set voltage for regulator %s, err = %d\n",
vreg->cfg.name, ret);
}
return ret;
}
static int cnss_vreg_off_single(struct cnss_vreg_info *vreg)
{
int ret = 0;
if (!vreg->enabled) {
cnss_pr_dbg("Regulator %s is already disabled\n",
vreg->cfg.name);
return 0;
}
cnss_pr_dbg("Regulator %s is being disabled\n",
vreg->cfg.name);
ret = regulator_disable(vreg->reg);
if (ret)
cnss_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)
cnss_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)
cnss_pr_err("Failed to set voltage for regulator %s, err = %d\n",
vreg->cfg.name, ret);
}
vreg->enabled = false;
return ret;
}
static struct cnss_vreg_cfg *get_vreg_list(u32 *vreg_list_size,
enum cnss_vreg_type type)
{
switch (type) {
case CNSS_VREG_PRIM:
*vreg_list_size = CNSS_VREG_INFO_SIZE;
return cnss_vreg_list;
default:
cnss_pr_err("Unsupported vreg type 0x%x\n", type);
*vreg_list_size = 0;
return NULL;
}
}
static int cnss_get_vreg(struct cnss_plat_data *plat_priv,
struct list_head *vreg_list,
struct cnss_vreg_cfg *vreg_cfg,
u32 vreg_list_size)
{
int ret = 0;
int i;
struct cnss_vreg_info *vreg;
struct device *dev = &plat_priv->plat_dev->dev;
if (!list_empty(vreg_list)) {
cnss_pr_dbg("Vregs have already been updated\n");
return 0;
}
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 = cnss_get_vreg_single(plat_priv, vreg);
if (ret != 0) {
if (ret == -ENODEV) {
devm_kfree(dev, vreg);
continue;
} else {
devm_kfree(dev, vreg);
return ret;
}
}
list_add_tail(&vreg->list, vreg_list);
}
return 0;
}
static void cnss_put_vreg(struct cnss_plat_data *plat_priv,
struct list_head *vreg_list)
{
struct cnss_vreg_info *vreg;
while (!list_empty(vreg_list)) {
vreg = list_first_entry(vreg_list,
struct cnss_vreg_info, list);
list_del(&vreg->list);
if (IS_ERR_OR_NULL(vreg->reg))
continue;
cnss_put_vreg_single(plat_priv, vreg);
}
}
static int cnss_vreg_on(struct cnss_plat_data *plat_priv,
struct list_head *vreg_list)
{
struct cnss_vreg_info *vreg;
int ret = 0;
list_for_each_entry(vreg, vreg_list, list) {
if (IS_ERR_OR_NULL(vreg->reg))
continue;
ret = cnss_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;
cnss_vreg_off_single(vreg);
}
return ret;
}
static int cnss_vreg_off(struct cnss_plat_data *plat_priv,
struct list_head *vreg_list)
{
struct cnss_vreg_info *vreg;
list_for_each_entry_reverse(vreg, vreg_list, list) {
if (IS_ERR_OR_NULL(vreg->reg))
continue;
cnss_vreg_off_single(vreg);
}
return 0;
}
static int cnss_vreg_unvote(struct cnss_plat_data *plat_priv,
struct list_head *vreg_list)
{
struct cnss_vreg_info *vreg;
list_for_each_entry_reverse(vreg, vreg_list, list) {
if (IS_ERR_OR_NULL(vreg->reg))
continue;
if (vreg->cfg.need_unvote)
cnss_vreg_unvote_single(vreg);
}
return 0;
}
int cnss_get_vreg_type(struct cnss_plat_data *plat_priv,
enum cnss_vreg_type type)
{
struct cnss_vreg_cfg *vreg_cfg;
u32 vreg_list_size = 0;
int ret = 0;
vreg_cfg = get_vreg_list(&vreg_list_size, type);
if (!vreg_cfg)
return -EINVAL;
switch (type) {
case CNSS_VREG_PRIM:
ret = cnss_get_vreg(plat_priv, &plat_priv->vreg_list,
vreg_cfg, vreg_list_size);
break;
default:
cnss_pr_err("Unsupported vreg type 0x%x\n", type);
return -EINVAL;
}
return ret;
}
void cnss_put_vreg_type(struct cnss_plat_data *plat_priv,
enum cnss_vreg_type type)
{
switch (type) {
case CNSS_VREG_PRIM:
cnss_put_vreg(plat_priv, &plat_priv->vreg_list);
break;
default:
return;
}
}
int cnss_vreg_on_type(struct cnss_plat_data *plat_priv,
enum cnss_vreg_type type)
{
int ret = 0;
switch (type) {
case CNSS_VREG_PRIM:
ret = cnss_vreg_on(plat_priv, &plat_priv->vreg_list);
break;
default:
cnss_pr_err("Unsupported vreg type 0x%x\n", type);
return -EINVAL;
}
return ret;
}
int cnss_vreg_off_type(struct cnss_plat_data *plat_priv,
enum cnss_vreg_type type)
{
int ret = 0;
switch (type) {
case CNSS_VREG_PRIM:
ret = cnss_vreg_off(plat_priv, &plat_priv->vreg_list);
break;
default:
cnss_pr_err("Unsupported vreg type 0x%x\n", type);
return -EINVAL;
}
return ret;
}
int cnss_vreg_unvote_type(struct cnss_plat_data *plat_priv,
enum cnss_vreg_type type)
{
int ret = 0;
switch (type) {
case CNSS_VREG_PRIM:
ret = cnss_vreg_unvote(plat_priv, &plat_priv->vreg_list);
break;
default:
cnss_pr_err("Unsupported vreg type 0x%x\n", type);
return -EINVAL;
}
return ret;
}
static int cnss_get_clk_single(struct cnss_plat_data *plat_priv,
struct cnss_clk_info *clk_info)
{
struct device *dev = &plat_priv->plat_dev->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)
cnss_pr_err("Failed to get clock %s, err = %d\n",
clk_info->cfg.name, ret);
else
cnss_pr_dbg("Failed to get optional clock %s, err = %d\n",
clk_info->cfg.name, ret);
return ret;
}
clk_info->clk = clk;
cnss_pr_dbg("Got clock: %s, freq: %u\n",
clk_info->cfg.name, clk_info->cfg.freq);
return 0;
}
static void cnss_put_clk_single(struct cnss_plat_data *plat_priv,
struct cnss_clk_info *clk_info)
{
struct device *dev = &plat_priv->plat_dev->dev;
cnss_pr_dbg("Put clock: %s\n", clk_info->cfg.name);
devm_clk_put(dev, clk_info->clk);
}
static int cnss_clk_on_single(struct cnss_clk_info *clk_info)
{
int ret;
if (clk_info->enabled) {
cnss_pr_dbg("Clock %s is already enabled\n",
clk_info->cfg.name);
return 0;
}
cnss_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) {
cnss_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) {
cnss_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 cnss_clk_off_single(struct cnss_clk_info *clk_info)
{
if (!clk_info->enabled) {
cnss_pr_dbg("Clock %s is already disabled\n",
clk_info->cfg.name);
return 0;
}
cnss_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 cnss_get_clk(struct cnss_plat_data *plat_priv)
{
struct device *dev;
struct list_head *clk_list;
struct cnss_clk_info *clk_info;
int ret, i;
if (!plat_priv)
return -ENODEV;
dev = &plat_priv->plat_dev->dev;
clk_list = &plat_priv->clk_list;
if (!list_empty(clk_list)) {
cnss_pr_dbg("Clocks have already been updated\n");
return 0;
}
for (i = 0; i < CNSS_CLK_INFO_SIZE; i++) {
clk_info = devm_kzalloc(dev, sizeof(*clk_info), GFP_KERNEL);
if (!clk_info) {
ret = -ENOMEM;
goto cleanup;
}
memcpy(&clk_info->cfg, &cnss_clk_list[i],
sizeof(clk_info->cfg));
ret = cnss_get_clk_single(plat_priv, clk_info);
if (ret != 0) {
if (clk_info->cfg.required) {
devm_kfree(dev, clk_info);
goto cleanup;
} else {
devm_kfree(dev, clk_info);
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 cnss_clk_info,
list);
list_del(&clk_info->list);
if (IS_ERR_OR_NULL(clk_info->clk))
continue;
cnss_put_clk_single(plat_priv, clk_info);
devm_kfree(dev, clk_info);
}
return ret;
}
void cnss_put_clk(struct cnss_plat_data *plat_priv)
{
struct device *dev;
struct list_head *clk_list;
struct cnss_clk_info *clk_info;
if (!plat_priv)
return;
dev = &plat_priv->plat_dev->dev;
clk_list = &plat_priv->clk_list;
while (!list_empty(clk_list)) {
clk_info = list_first_entry(clk_list, struct cnss_clk_info,
list);
list_del(&clk_info->list);
if (IS_ERR_OR_NULL(clk_info->clk))
continue;
cnss_put_clk_single(plat_priv, clk_info);
devm_kfree(dev, clk_info);
}
}
static int cnss_clk_on(struct cnss_plat_data *plat_priv,
struct list_head *clk_list)
{
struct cnss_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 = cnss_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;
cnss_clk_off_single(clk_info);
}
return ret;
}
static int cnss_clk_off(struct cnss_plat_data *plat_priv,
struct list_head *clk_list)
{
struct cnss_clk_info *clk_info;
list_for_each_entry_reverse(clk_info, clk_list, list) {
if (IS_ERR_OR_NULL(clk_info->clk))
continue;
cnss_clk_off_single(clk_info);
}
return 0;
}
int cnss_get_pinctrl(struct cnss_plat_data *plat_priv)
{
int ret = 0;
struct device *dev;
struct cnss_pinctrl_info *pinctrl_info;
dev = &plat_priv->plat_dev->dev;
pinctrl_info = &plat_priv->pinctrl_info;
pinctrl_info->pinctrl = devm_pinctrl_get(dev);
if (IS_ERR_OR_NULL(pinctrl_info->pinctrl)) {
ret = PTR_ERR(pinctrl_info->pinctrl);
cnss_pr_err("Failed to get pinctrl, err = %d\n", ret);
goto out;
}
if (of_find_property(dev->of_node, BOOTSTRAP_GPIO, NULL)) {
pinctrl_info->bootstrap_active =
pinctrl_lookup_state(pinctrl_info->pinctrl,
BOOTSTRAP_ACTIVE);
if (IS_ERR_OR_NULL(pinctrl_info->bootstrap_active)) {
ret = PTR_ERR(pinctrl_info->bootstrap_active);
cnss_pr_err("Failed to get bootstrap active state, err = %d\n",
ret);
goto out;
}
}
if (of_find_property(dev->of_node, WLAN_EN_GPIO, NULL)) {
pinctrl_info->wlan_en_active =
pinctrl_lookup_state(pinctrl_info->pinctrl,
WLAN_EN_ACTIVE);
if (IS_ERR_OR_NULL(pinctrl_info->wlan_en_active)) {
ret = PTR_ERR(pinctrl_info->wlan_en_active);
cnss_pr_err("Failed to get wlan_en active state, err = %d\n",
ret);
goto out;
}
pinctrl_info->wlan_en_sleep =
pinctrl_lookup_state(pinctrl_info->pinctrl,
WLAN_EN_SLEEP);
if (IS_ERR_OR_NULL(pinctrl_info->wlan_en_sleep)) {
ret = PTR_ERR(pinctrl_info->wlan_en_sleep);
cnss_pr_err("Failed to get wlan_en sleep state, err = %d\n",
ret);
goto out;
}
}
return 0;
out:
return ret;
}
static int cnss_select_pinctrl_state(struct cnss_plat_data *plat_priv,
bool state)
{
int ret = 0;
struct cnss_pinctrl_info *pinctrl_info;
if (!plat_priv) {
cnss_pr_err("plat_priv is NULL!\n");
ret = -ENODEV;
goto out;
}
pinctrl_info = &plat_priv->pinctrl_info;
if (state) {
if (!IS_ERR_OR_NULL(pinctrl_info->bootstrap_active)) {
ret = pinctrl_select_state
(pinctrl_info->pinctrl,
pinctrl_info->bootstrap_active);
if (ret) {
cnss_pr_err("Failed to select bootstrap active state, err = %d\n",
ret);
goto out;
}
udelay(BOOTSTRAP_DELAY);
}
if (!IS_ERR_OR_NULL(pinctrl_info->wlan_en_active)) {
ret = pinctrl_select_state
(pinctrl_info->pinctrl,
pinctrl_info->wlan_en_active);
if (ret) {
cnss_pr_err("Failed to select wlan_en active state, err = %d\n",
ret);
goto out;
}
udelay(WLAN_ENABLE_DELAY);
}
} else {
if (!IS_ERR_OR_NULL(pinctrl_info->wlan_en_sleep)) {
ret = pinctrl_select_state(pinctrl_info->pinctrl,
pinctrl_info->wlan_en_sleep);
if (ret) {
cnss_pr_err("Failed to select wlan_en sleep state, err = %d\n",
ret);
goto out;
}
}
}
return 0;
out:
return ret;
}
int cnss_power_on_device(struct cnss_plat_data *plat_priv)
{
int ret = 0;
if (plat_priv->powered_on) {
cnss_pr_dbg("Already powered up");
return 0;
}
ret = cnss_vreg_on_type(plat_priv, CNSS_VREG_PRIM);
if (ret) {
cnss_pr_err("Failed to turn on vreg, err = %d\n", ret);
goto out;
}
ret = cnss_clk_on(plat_priv, &plat_priv->clk_list);
if (ret) {
cnss_pr_err("Failed to turn on clocks, err = %d\n", ret);
goto vreg_off;
}
ret = cnss_select_pinctrl_state(plat_priv, true);
if (ret) {
cnss_pr_err("Failed to select pinctrl state, err = %d\n", ret);
goto clk_off;
}
plat_priv->powered_on = true;
return 0;
clk_off:
cnss_clk_off(plat_priv, &plat_priv->clk_list);
vreg_off:
cnss_vreg_off_type(plat_priv, CNSS_VREG_PRIM);
out:
return ret;
}
void cnss_power_off_device(struct cnss_plat_data *plat_priv)
{
if (!plat_priv->powered_on) {
cnss_pr_dbg("Already powered down");
return;
}
cnss_select_pinctrl_state(plat_priv, false);
cnss_clk_off(plat_priv, &plat_priv->clk_list);
cnss_vreg_off_type(plat_priv, CNSS_VREG_PRIM);
plat_priv->powered_on = false;
}
bool cnss_is_device_powered_on(struct cnss_plat_data *plat_priv)
{
return plat_priv->powered_on;
}
void cnss_set_pin_connect_status(struct cnss_plat_data *plat_priv)
{
unsigned long pin_status = 0;
set_bit(CNSS_WLAN_EN, &pin_status);
set_bit(CNSS_PCIE_TXN, &pin_status);
set_bit(CNSS_PCIE_TXP, &pin_status);
set_bit(CNSS_PCIE_RXN, &pin_status);
set_bit(CNSS_PCIE_RXP, &pin_status);
set_bit(CNSS_PCIE_REFCLKN, &pin_status);
set_bit(CNSS_PCIE_REFCLKP, &pin_status);
set_bit(CNSS_PCIE_RST, &pin_status);
plat_priv->pin_result.host_pin_result = pin_status;
}
int cnss_get_cpr_info(struct cnss_plat_data *plat_priv)
{
struct platform_device *plat_dev = plat_priv->plat_dev;
struct cnss_cpr_info *cpr_info = &plat_priv->cpr_info;
struct resource *res;
resource_size_t addr_len;
void __iomem *tcs_cmd_base_addr;
const char *cmd_db_name;
u32 cpr_pmic_addr = 0;
int ret = 0;
res = platform_get_resource_byname(plat_dev, IORESOURCE_MEM, "tcs_cmd");
if (!res) {
cnss_pr_dbg("TCS CMD address is not present for CPR\n");
goto out;
}
ret = of_property_read_string(plat_dev->dev.of_node,
"qcom,cmd_db_name", &cmd_db_name);
if (ret) {
cnss_pr_dbg("CommandDB name is not present for CPR\n");
goto out;
}
ret = cmd_db_ready();
if (ret) {
cnss_pr_err("CommandDB is not ready\n");
goto out;
}
cpr_pmic_addr = cmd_db_read_addr(cmd_db_name);
if (cpr_pmic_addr > 0) {
cpr_info->cpr_pmic_addr = cpr_pmic_addr;
cnss_pr_dbg("Get CPR PMIC address 0x%x from %s\n",
cpr_info->cpr_pmic_addr, cmd_db_name);
} else {
cnss_pr_err("CPR PMIC address is not available for %s\n",
cmd_db_name);
ret = -EINVAL;
goto out;
}
cpr_info->tcs_cmd_base_addr = res->start;
addr_len = resource_size(res);
cnss_pr_dbg("TCS CMD base address is %pa with length %pa\n",
&cpr_info->tcs_cmd_base_addr, &addr_len);
tcs_cmd_base_addr = devm_ioremap_resource(&plat_dev->dev, res);
if (IS_ERR(tcs_cmd_base_addr)) {
ret = PTR_ERR(tcs_cmd_base_addr);
cnss_pr_err("Failed to map TCS CMD address, err = %d\n",
ret);
goto out;
}
cpr_info->tcs_cmd_base_addr_io = tcs_cmd_base_addr;
return 0;
out:
return ret;
}
int cnss_update_cpr_info(struct cnss_plat_data *plat_priv)
{
struct cnss_cpr_info *cpr_info = &plat_priv->cpr_info;
u32 pmic_addr, voltage = 0, voltage_tmp, offset;
void __iomem *tcs_cmd_addr, *tcs_cmd_data_addr;
int i, j;
if (cpr_info->tcs_cmd_base_addr == 0) {
cnss_pr_dbg("CPR is not enabled\n");
return 0;
}
if (cpr_info->voltage == 0 || cpr_info->cpr_pmic_addr == 0) {
cnss_pr_err("Voltage %dmV or PMIC address 0x%x is not valid\n",
cpr_info->voltage, cpr_info->cpr_pmic_addr);
return -EINVAL;
}
if (cpr_info->tcs_cmd_data_addr_io)
goto update_cpr;
for (i = 0; i < MAX_TCS_NUM; i++) {
for (j = 0; j < MAX_TCS_CMD_NUM; j++) {
offset = i * TCS_OFFSET + j * TCS_CMD_OFFSET;
tcs_cmd_addr = cpr_info->tcs_cmd_base_addr_io + offset;
pmic_addr = readl_relaxed(tcs_cmd_addr);
if (pmic_addr == cpr_info->cpr_pmic_addr) {
tcs_cmd_data_addr = tcs_cmd_addr +
TCS_CMD_DATA_ADDR_OFFSET;
voltage_tmp = readl_relaxed(tcs_cmd_data_addr);
cnss_pr_dbg("Got voltage %dmV from i: %d, j: %d\n",
voltage_tmp, i, j);
if (voltage_tmp > voltage) {
voltage = voltage_tmp;
cpr_info->tcs_cmd_data_addr =
cpr_info->tcs_cmd_base_addr +
offset +
TCS_CMD_DATA_ADDR_OFFSET;
cpr_info->tcs_cmd_data_addr_io =
tcs_cmd_data_addr;
}
}
}
}
if (!cpr_info->tcs_cmd_data_addr_io) {
cnss_pr_err("Failed to find proper TCS CMD data address\n");
return -EINVAL;
}
update_cpr:
cpr_info->voltage = cpr_info->voltage > BT_CXMX_VOLTAGE_MV ?
cpr_info->voltage : BT_CXMX_VOLTAGE_MV;
cnss_pr_dbg("Update TCS CMD data address %pa with voltage %dmV\n",
&cpr_info->tcs_cmd_data_addr, cpr_info->voltage);
writel_relaxed(cpr_info->voltage, cpr_info->tcs_cmd_data_addr_io);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,211 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. */
#ifndef _CNSS_QMI_H
#define _CNSS_QMI_H
#include <linux/soc/qcom/qmi.h>
struct cnss_plat_data;
struct cnss_qmi_event_server_arrive_data {
unsigned int node;
unsigned int port;
};
#define QDSS_TRACE_SEG_LEN_MAX 32
#define QDSS_TRACE_FILE_NAME_MAX 16
struct cnss_mem_seg {
u64 addr;
u32 size;
};
struct cnss_qmi_event_qdss_trace_save_data {
u32 total_size;
u32 mem_seg_len;
struct cnss_mem_seg mem_seg[QDSS_TRACE_SEG_LEN_MAX];
char file_name[QDSS_TRACE_FILE_NAME_MAX + 1];
};
#ifdef CONFIG_CNSS2_QMI
#include "wlan_firmware_service_v01.h"
#include "coexistence_service_v01.h"
#include "ip_multimedia_subsystem_private_service_v01.h"
int cnss_qmi_init(struct cnss_plat_data *plat_priv);
void cnss_qmi_deinit(struct cnss_plat_data *plat_priv);
unsigned int cnss_get_qmi_timeout(struct cnss_plat_data *plat_priv);
int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv, void *data);
int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv);
int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv);
int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv);
int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
u32 bdf_type);
int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv);
int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
enum cnss_driver_mode mode);
int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
struct cnss_wlan_enable_cfg *config,
const char *host_version);
int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv,
u32 offset, u32 mem_type,
u32 data_len, u8 *data);
int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv,
u32 offset, u32 mem_type,
u32 data_len, u8 *data);
int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
u8 fw_log_mode);
int cnss_wlfw_antenna_switch_send_sync(struct cnss_plat_data *plat_priv);
int cnss_wlfw_antenna_grant_send_sync(struct cnss_plat_data *plat_priv);
int cnss_wlfw_dynamic_feature_mask_send_sync(struct cnss_plat_data *plat_priv);
int cnss_register_coex_service(struct cnss_plat_data *plat_priv);
void cnss_unregister_coex_service(struct cnss_plat_data *plat_priv);
int coex_antenna_switch_to_wlan_send_sync_msg(struct cnss_plat_data *plat_priv);
int coex_antenna_switch_to_mdm_send_sync_msg(struct cnss_plat_data *plat_priv);
int cnss_wlfw_qdss_trace_mem_info_send_sync(struct cnss_plat_data *plat_priv);
int cnss_register_ims_service(struct cnss_plat_data *plat_priv);
void cnss_unregister_ims_service(struct cnss_plat_data *plat_priv);
#else
#define QMI_WLFW_TIMEOUT_MS 10000
static inline int cnss_qmi_init(struct cnss_plat_data *plat_priv)
{
return 0;
}
static inline void cnss_qmi_deinit(struct cnss_plat_data *plat_priv)
{
}
static inline
unsigned int cnss_get_qmi_timeout(struct cnss_plat_data *plat_priv)
{
return QMI_WLFW_TIMEOUT_MS;
}
static inline int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv,
void *data)
{
return 0;
}
static inline int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv)
{
return 0;
}
static inline
int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv)
{
return 0;
}
static inline int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
{
return 0;
}
static inline int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
u32 bdf_type)
{
return 0;
}
static inline int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv)
{
return 0;
}
static inline
int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
enum cnss_driver_mode mode)
{
return 0;
}
static inline
int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
struct cnss_wlan_enable_cfg *config,
const char *host_version)
{
return 0;
}
static inline
int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv,
u32 offset, u32 mem_type,
u32 data_len, u8 *data)
{
return 0;
}
static inline
int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv,
u32 offset, u32 mem_type,
u32 data_len, u8 *data)
{
return 0;
}
static inline
int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
u8 fw_log_mode)
{
return 0;
}
static inline
int cnss_wlfw_antenna_switch_send_sync(struct cnss_plat_data *plat_priv)
{
return 0;
}
static inline
int cnss_wlfw_antenna_grant_send_sync(struct cnss_plat_data *plat_priv)
{
return 0;
}
static inline
int cnss_wlfw_dynamic_feature_mask_send_sync(struct cnss_plat_data *plat_priv)
{
return 0;
}
static inline
int cnss_register_coex_service(struct cnss_plat_data *plat_priv)
{
return 0;
}
static inline
void cnss_unregister_coex_service(struct cnss_plat_data *plat_priv) {}
static inline
int coex_antenna_switch_to_wlan_send_sync_msg(struct cnss_plat_data *plat_priv)
{
return 0;
}
static inline
int coex_antenna_switch_to_mdm_send_sync_msg(struct cnss_plat_data *plat_priv)
static inline
int cnss_wlfw_qdss_trace_mem_info_send_sync(struct cnss_plat_data *plat_priv)
{
return 0;
}
static inline
int cnss_register_ims_service(struct cnss_plat_data *plat_priv)
{
return 0;
}
static inline
void cnss_unregister_ims_service(struct cnss_plat_data *plat_priv) {}
#endif /* CONFIG_CNSS2_QMI */
#endif /* _CNSS_QMI_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,952 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. */
#ifndef WLAN_FIRMWARE_SERVICE_V01_H
#define WLAN_FIRMWARE_SERVICE_V01_H
#include <linux/soc/qcom/qmi.h>
#define WLFW_SERVICE_ID_V01 0x45
#define WLFW_SERVICE_VERS_V01 0x01
#define QMI_WLFW_WFC_CALL_STATUS_REQ_V01 0x0049
#define QMI_WLFW_BDF_DOWNLOAD_REQ_V01 0x0025
#define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037
#define QMI_WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01 0x0044
#define QMI_WLFW_INITIATE_CAL_UPDATE_IND_V01 0x002A
#define QMI_WLFW_CAL_DONE_IND_V01 0x003E
#define QMI_WLFW_WFC_CALL_STATUS_RESP_V01 0x0049
#define QMI_WLFW_HOST_CAP_REQ_V01 0x0034
#define QMI_WLFW_DYNAMIC_FEATURE_MASK_RESP_V01 0x003B
#define QMI_WLFW_M3_INFO_REQ_V01 0x003C
#define QMI_WLFW_CAP_REQ_V01 0x0024
#define QMI_WLFW_FW_INIT_DONE_IND_V01 0x0038
#define QMI_WLFW_ANTENNA_GRANT_RESP_V01 0x0048
#define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026
#define QMI_WLFW_M3_INFO_RESP_V01 0x003C
#define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029
#define QMI_WLFW_CAL_DOWNLOAD_RESP_V01 0x0027
#define QMI_WLFW_XO_CAL_IND_V01 0x003D
#define QMI_WLFW_INI_RESP_V01 0x002F
#define QMI_WLFW_CAL_REPORT_RESP_V01 0x0026
#define QMI_WLFW_QDSS_TRACE_MEM_INFO_REQ_V01 0x0040
#define QMI_WLFW_ANTENNA_SWITCH_REQ_V01 0x0047
#define QMI_WLFW_QDSS_TRACE_REQ_MEM_IND_V01 0x003F
#define QMI_WLFW_SHUTDOWN_RESP_V01 0x0043
#define QMI_WLFW_MAC_ADDR_RESP_V01 0x0033
#define QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028
#define QMI_WLFW_HOST_CAP_RESP_V01 0x0034
#define QMI_WLFW_MSA_READY_IND_V01 0x002B
#define QMI_WLFW_ATHDIAG_WRITE_RESP_V01 0x0031
#define QMI_WLFW_WLAN_MODE_REQ_V01 0x0022
#define QMI_WLFW_IND_REGISTER_REQ_V01 0x0020
#define QMI_WLFW_WLAN_CFG_RESP_V01 0x0023
#define QMI_WLFW_QDSS_TRACE_MODE_REQ_V01 0x0045
#define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035
#define QMI_WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_V01 0x0044
#define QMI_WLFW_REJUVENATE_IND_V01 0x0039
#define QMI_WLFW_DYNAMIC_FEATURE_MASK_REQ_V01 0x003B
#define QMI_WLFW_ATHDIAG_WRITE_REQ_V01 0x0031
#define QMI_WLFW_WLAN_MODE_RESP_V01 0x0022
#define QMI_WLFW_RESPOND_MEM_REQ_V01 0x0036
#define QMI_WLFW_QDSS_TRACE_MODE_RESP_V01 0x0045
#define QMI_WLFW_PIN_CONNECT_RESULT_IND_V01 0x002C
#define QMI_WLFW_FW_READY_IND_V01 0x0021
#define QMI_WLFW_QDSS_TRACE_SAVE_IND_V01 0x0041
#define QMI_WLFW_QDSS_TRACE_MEM_INFO_RESP_V01 0x0040
#define QMI_WLFW_ANTENNA_GRANT_REQ_V01 0x0048
#define QMI_WLFW_MSA_READY_RESP_V01 0x002E
#define QMI_WLFW_QDSS_TRACE_DATA_REQ_V01 0x0042
#define QMI_WLFW_CAL_UPDATE_REQ_V01 0x0029
#define QMI_WLFW_INI_REQ_V01 0x002F
#define QMI_WLFW_BDF_DOWNLOAD_RESP_V01 0x0025
#define QMI_WLFW_REJUVENATE_ACK_RESP_V01 0x003A
#define QMI_WLFW_MSA_INFO_RESP_V01 0x002D
#define QMI_WLFW_MSA_READY_REQ_V01 0x002E
#define QMI_WLFW_QDSS_TRACE_DATA_RESP_V01 0x0042
#define QMI_WLFW_CAP_RESP_V01 0x0024
#define QMI_WLFW_REJUVENATE_ACK_REQ_V01 0x003A
#define QMI_WLFW_ATHDIAG_READ_RESP_V01 0x0030
#define QMI_WLFW_SHUTDOWN_REQ_V01 0x0043
#define QMI_WLFW_VBATT_REQ_V01 0x0032
#define QMI_WLFW_ANTENNA_SWITCH_RESP_V01 0x0047
#define QMI_WLFW_MAC_ADDR_REQ_V01 0x0033
#define QMI_WLFW_RESPOND_MEM_RESP_V01 0x0036
#define QMI_WLFW_VBATT_RESP_V01 0x0032
#define QMI_WLFW_MSA_INFO_REQ_V01 0x002D
#define QMI_WLFW_QDSS_TRACE_FREE_IND_V01 0x0046
#define QMI_WLFW_CAL_DOWNLOAD_REQ_V01 0x0027
#define QMI_WLFW_ATHDIAG_READ_REQ_V01 0x0030
#define QMI_WLFW_WLAN_CFG_REQ_V01 0x0023
#define QMI_WLFW_IND_REGISTER_RESP_V01 0x0020
#define QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01 2
#define QMI_WLFW_MAX_NUM_MEM_SEG_V01 32
#define QMI_WLFW_MAX_NUM_CAL_V01 5
#define QMI_WLFW_MAX_DATA_SIZE_V01 6144
#define QMI_WLFW_FUNCTION_NAME_LEN_V01 128
#define QMI_WLFW_MAX_NUM_CE_V01 12
#define QMI_WLFW_MAX_TIMESTAMP_LEN_V01 32
#define QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01 6144
#define QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01 256
#define QMI_WLFW_MAX_NUM_GPIO_V01 32
#define QMI_WLFW_MAX_BUILD_ID_LEN_V01 128
#define QMI_WLFW_MAX_NUM_MEM_CFG_V01 2
#define QMI_WLFW_MAX_STR_LEN_V01 16
#define QMI_WLFW_MAX_NUM_SHADOW_REG_V01 24
#define QMI_WLFW_MAC_ADDR_SIZE_V01 6
#define QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01 36
#define QMI_WLFW_MAX_NUM_SVC_V01 24
enum wlfw_driver_mode_enum_v01 {
WLFW_DRIVER_MODE_ENUM_MIN_VAL_V01 = INT_MIN,
QMI_WLFW_MISSION_V01 = 0,
QMI_WLFW_FTM_V01 = 1,
QMI_WLFW_EPPING_V01 = 2,
QMI_WLFW_WALTEST_V01 = 3,
QMI_WLFW_OFF_V01 = 4,
QMI_WLFW_CCPM_V01 = 5,
QMI_WLFW_QVIT_V01 = 6,
QMI_WLFW_CALIBRATION_V01 = 7,
WLFW_DRIVER_MODE_ENUM_MAX_VAL_V01 = INT_MAX,
};
enum wlfw_cal_temp_id_enum_v01 {
WLFW_CAL_TEMP_ID_ENUM_MIN_VAL_V01 = INT_MIN,
QMI_WLFW_CAL_TEMP_IDX_0_V01 = 0,
QMI_WLFW_CAL_TEMP_IDX_1_V01 = 1,
QMI_WLFW_CAL_TEMP_IDX_2_V01 = 2,
QMI_WLFW_CAL_TEMP_IDX_3_V01 = 3,
QMI_WLFW_CAL_TEMP_IDX_4_V01 = 4,
WLFW_CAL_TEMP_ID_ENUM_MAX_VAL_V01 = INT_MAX,
};
enum wlfw_pipedir_enum_v01 {
WLFW_PIPEDIR_ENUM_MIN_VAL_V01 = INT_MIN,
QMI_WLFW_PIPEDIR_NONE_V01 = 0,
QMI_WLFW_PIPEDIR_IN_V01 = 1,
QMI_WLFW_PIPEDIR_OUT_V01 = 2,
QMI_WLFW_PIPEDIR_INOUT_V01 = 3,
WLFW_PIPEDIR_ENUM_MAX_VAL_V01 = INT_MAX,
};
enum wlfw_mem_type_enum_v01 {
WLFW_MEM_TYPE_ENUM_MIN_VAL_V01 = INT_MIN,
QMI_WLFW_MEM_TYPE_MSA_V01 = 0,
QMI_WLFW_MEM_TYPE_DDR_V01 = 1,
QMI_WLFW_MEM_BDF_V01 = 2,
QMI_WLFW_MEM_M3_V01 = 3,
QMI_WLFW_MEM_CAL_V01 = 4,
QMI_WLFW_MEM_DPD_V01 = 5,
QMI_WLFW_MEM_QDSS_V01 = 6,
WLFW_MEM_TYPE_ENUM_MAX_VAL_V01 = INT_MAX,
};
enum wlfw_qdss_trace_mode_enum_v01 {
WLFW_QDSS_TRACE_MODE_ENUM_MIN_VAL_V01 = INT_MIN,
QMI_WLFW_QDSS_TRACE_OFF_V01 = 0,
QMI_WLFW_QDSS_TRACE_ON_V01 = 1,
WLFW_QDSS_TRACE_MODE_ENUM_MAX_VAL_V01 = INT_MAX,
};
#define QMI_WLFW_CE_ATTR_FLAGS_V01 ((u32)0x00)
#define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01)
#define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02)
#define QMI_WLFW_CE_ATTR_SWIZZLE_DESCRIPTORS_V01 ((u32)0x04)
#define QMI_WLFW_CE_ATTR_DISABLE_INTR_V01 ((u32)0x08)
#define QMI_WLFW_CE_ATTR_ENABLE_POLL_V01 ((u32)0x10)
#define QMI_WLFW_ALREADY_REGISTERED_V01 ((u64)0x01ULL)
#define QMI_WLFW_FW_READY_V01 ((u64)0x02ULL)
#define QMI_WLFW_MSA_READY_V01 ((u64)0x04ULL)
#define QMI_WLFW_FW_MEM_READY_V01 ((u64)0x08ULL)
#define QMI_WLFW_FW_INIT_DONE_V01 ((u64)0x10ULL)
#define QMI_WLFW_FW_REJUVENATE_V01 ((u64)0x01ULL)
struct wlfw_ce_tgt_pipe_cfg_s_v01 {
u32 pipe_num;
enum wlfw_pipedir_enum_v01 pipe_dir;
u32 nentries;
u32 nbytes_max;
u32 flags;
};
struct wlfw_ce_svc_pipe_cfg_s_v01 {
u32 service_id;
enum wlfw_pipedir_enum_v01 pipe_dir;
u32 pipe_num;
};
struct wlfw_shadow_reg_cfg_s_v01 {
u16 id;
u16 offset;
};
struct wlfw_shadow_reg_v2_cfg_s_v01 {
u32 addr;
};
struct wlfw_rri_over_ddr_cfg_s_v01 {
u32 base_addr_low;
u32 base_addr_high;
};
struct wlfw_msi_cfg_s_v01 {
u16 ce_id;
u16 msi_vector;
};
struct wlfw_memory_region_info_s_v01 {
u64 region_addr;
u32 size;
u8 secure_flag;
};
struct wlfw_mem_cfg_s_v01 {
u64 offset;
u32 size;
u8 secure_flag;
};
struct wlfw_mem_seg_s_v01 {
u32 size;
enum wlfw_mem_type_enum_v01 type;
u32 mem_cfg_len;
struct wlfw_mem_cfg_s_v01 mem_cfg[QMI_WLFW_MAX_NUM_MEM_CFG_V01];
};
struct wlfw_mem_seg_resp_s_v01 {
u64 addr;
u32 size;
enum wlfw_mem_type_enum_v01 type;
u8 restore;
};
struct wlfw_rf_chip_info_s_v01 {
u32 chip_id;
u32 chip_family;
};
struct wlfw_rf_board_info_s_v01 {
u32 board_id;
};
struct wlfw_soc_info_s_v01 {
u32 soc_id;
};
struct wlfw_fw_version_info_s_v01 {
u32 fw_version;
char fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN_V01 + 1];
};
struct wlfw_ind_register_req_msg_v01 {
u8 fw_ready_enable_valid;
u8 fw_ready_enable;
u8 initiate_cal_download_enable_valid;
u8 initiate_cal_download_enable;
u8 initiate_cal_update_enable_valid;
u8 initiate_cal_update_enable;
u8 msa_ready_enable_valid;
u8 msa_ready_enable;
u8 pin_connect_result_enable_valid;
u8 pin_connect_result_enable;
u8 client_id_valid;
u32 client_id;
u8 request_mem_enable_valid;
u8 request_mem_enable;
u8 fw_mem_ready_enable_valid;
u8 fw_mem_ready_enable;
u8 fw_init_done_enable_valid;
u8 fw_init_done_enable;
u8 rejuvenate_enable_valid;
u32 rejuvenate_enable;
u8 xo_cal_enable_valid;
u8 xo_cal_enable;
u8 cal_done_enable_valid;
u8 cal_done_enable;
u8 qdss_trace_req_mem_enable_valid;
u8 qdss_trace_req_mem_enable;
u8 qdss_trace_save_enable_valid;
u8 qdss_trace_save_enable;
u8 qdss_trace_free_enable_valid;
u8 qdss_trace_free_enable;
};
#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 66
extern struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[];
struct wlfw_ind_register_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 fw_status_valid;
u64 fw_status;
};
#define WLFW_IND_REGISTER_RESP_MSG_V01_MAX_MSG_LEN 18
extern struct qmi_elem_info wlfw_ind_register_resp_msg_v01_ei[];
struct wlfw_fw_ready_ind_msg_v01 {
char placeholder;
};
#define WLFW_FW_READY_IND_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_fw_ready_ind_msg_v01_ei[];
struct wlfw_msa_ready_ind_msg_v01 {
char placeholder;
};
#define WLFW_MSA_READY_IND_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[];
struct wlfw_pin_connect_result_ind_msg_v01 {
u8 pwr_pin_result_valid;
u32 pwr_pin_result;
u8 phy_io_pin_result_valid;
u32 phy_io_pin_result;
u8 rf_pin_result_valid;
u32 rf_pin_result;
};
#define WLFW_PIN_CONNECT_RESULT_IND_MSG_V01_MAX_MSG_LEN 21
extern struct qmi_elem_info wlfw_pin_connect_result_ind_msg_v01_ei[];
struct wlfw_wlan_mode_req_msg_v01 {
enum wlfw_driver_mode_enum_v01 mode;
u8 hw_debug_valid;
u8 hw_debug;
};
#define WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN 11
extern struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[];
struct wlfw_wlan_mode_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_WLAN_MODE_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_wlan_mode_resp_msg_v01_ei[];
struct wlfw_wlan_cfg_req_msg_v01 {
u8 host_version_valid;
char host_version[QMI_WLFW_MAX_STR_LEN_V01 + 1];
u8 tgt_cfg_valid;
u32 tgt_cfg_len;
struct wlfw_ce_tgt_pipe_cfg_s_v01 tgt_cfg[QMI_WLFW_MAX_NUM_CE_V01];
u8 svc_cfg_valid;
u32 svc_cfg_len;
struct wlfw_ce_svc_pipe_cfg_s_v01 svc_cfg[QMI_WLFW_MAX_NUM_SVC_V01];
u8 shadow_reg_valid;
u32 shadow_reg_len;
struct wlfw_shadow_reg_cfg_s_v01
shadow_reg[QMI_WLFW_MAX_NUM_SHADOW_REG_V01];
u8 shadow_reg_v2_valid;
u32 shadow_reg_v2_len;
struct wlfw_shadow_reg_v2_cfg_s_v01
shadow_reg_v2[QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01];
u8 rri_over_ddr_cfg_valid;
struct wlfw_rri_over_ddr_cfg_s_v01 rri_over_ddr_cfg;
u8 msi_cfg_valid;
u32 msi_cfg_len;
struct wlfw_msi_cfg_s_v01 msi_cfg[QMI_WLFW_MAX_NUM_CE_V01];
};
#define WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN 866
extern struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[];
struct wlfw_wlan_cfg_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_WLAN_CFG_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_wlan_cfg_resp_msg_v01_ei[];
struct wlfw_cap_req_msg_v01 {
char placeholder;
};
#define WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_cap_req_msg_v01_ei[];
struct wlfw_cap_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 chip_info_valid;
struct wlfw_rf_chip_info_s_v01 chip_info;
u8 board_info_valid;
struct wlfw_rf_board_info_s_v01 board_info;
u8 soc_info_valid;
struct wlfw_soc_info_s_v01 soc_info;
u8 fw_version_info_valid;
struct wlfw_fw_version_info_s_v01 fw_version_info;
u8 fw_build_id_valid;
char fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1];
u8 num_macs_valid;
u8 num_macs;
u8 voltage_mv_valid;
u32 voltage_mv;
u8 time_freq_hz_valid;
u32 time_freq_hz;
u8 otp_version_valid;
u32 otp_version;
};
#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 228
extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[];
struct wlfw_bdf_download_req_msg_v01 {
u8 valid;
u8 file_id_valid;
enum wlfw_cal_temp_id_enum_v01 file_id;
u8 total_size_valid;
u32 total_size;
u8 seg_id_valid;
u32 seg_id;
u8 data_valid;
u32 data_len;
u8 data[QMI_WLFW_MAX_DATA_SIZE_V01];
u8 end_valid;
u8 end;
u8 bdf_type_valid;
u8 bdf_type;
};
#define WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6182
extern struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[];
struct wlfw_bdf_download_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_BDF_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_bdf_download_resp_msg_v01_ei[];
struct wlfw_cal_report_req_msg_v01 {
u32 meta_data_len;
enum wlfw_cal_temp_id_enum_v01 meta_data[QMI_WLFW_MAX_NUM_CAL_V01];
u8 xo_cal_data_valid;
u8 xo_cal_data;
};
#define WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN 28
extern struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[];
struct wlfw_cal_report_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_CAL_REPORT_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_cal_report_resp_msg_v01_ei[];
struct wlfw_initiate_cal_download_ind_msg_v01 {
enum wlfw_cal_temp_id_enum_v01 cal_id;
u8 total_size_valid;
u32 total_size;
u8 cal_data_location_valid;
u32 cal_data_location;
};
#define WLFW_INITIATE_CAL_DOWNLOAD_IND_MSG_V01_MAX_MSG_LEN 21
extern struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[];
struct wlfw_cal_download_req_msg_v01 {
u8 valid;
u8 file_id_valid;
enum wlfw_cal_temp_id_enum_v01 file_id;
u8 total_size_valid;
u32 total_size;
u8 seg_id_valid;
u32 seg_id;
u8 data_valid;
u32 data_len;
u8 data[QMI_WLFW_MAX_DATA_SIZE_V01];
u8 end_valid;
u8 end;
u8 cal_data_location_valid;
u32 cal_data_location;
};
#define WLFW_CAL_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6185
extern struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[];
struct wlfw_cal_download_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_CAL_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_cal_download_resp_msg_v01_ei[];
struct wlfw_initiate_cal_update_ind_msg_v01 {
enum wlfw_cal_temp_id_enum_v01 cal_id;
u32 total_size;
u8 cal_data_location_valid;
u32 cal_data_location;
};
#define WLFW_INITIATE_CAL_UPDATE_IND_MSG_V01_MAX_MSG_LEN 21
extern struct qmi_elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[];
struct wlfw_cal_update_req_msg_v01 {
enum wlfw_cal_temp_id_enum_v01 cal_id;
u32 seg_id;
};
#define WLFW_CAL_UPDATE_REQ_MSG_V01_MAX_MSG_LEN 14
extern struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[];
struct wlfw_cal_update_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 file_id_valid;
enum wlfw_cal_temp_id_enum_v01 file_id;
u8 total_size_valid;
u32 total_size;
u8 seg_id_valid;
u32 seg_id;
u8 data_valid;
u32 data_len;
u8 data[QMI_WLFW_MAX_DATA_SIZE_V01];
u8 end_valid;
u8 end;
u8 cal_data_location_valid;
u32 cal_data_location;
};
#define WLFW_CAL_UPDATE_RESP_MSG_V01_MAX_MSG_LEN 6188
extern struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[];
struct wlfw_msa_info_req_msg_v01 {
u64 msa_addr;
u32 size;
};
#define WLFW_MSA_INFO_REQ_MSG_V01_MAX_MSG_LEN 18
extern struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[];
struct wlfw_msa_info_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u32 mem_region_info_len;
struct wlfw_memory_region_info_s_v01
mem_region_info[QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01];
};
#define WLFW_MSA_INFO_RESP_MSG_V01_MAX_MSG_LEN 37
extern struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[];
struct wlfw_msa_ready_req_msg_v01 {
char placeholder;
};
#define WLFW_MSA_READY_REQ_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_msa_ready_req_msg_v01_ei[];
struct wlfw_msa_ready_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_MSA_READY_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_msa_ready_resp_msg_v01_ei[];
struct wlfw_ini_req_msg_v01 {
u8 enablefwlog_valid;
u8 enablefwlog;
};
#define WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN 4
extern struct qmi_elem_info wlfw_ini_req_msg_v01_ei[];
struct wlfw_ini_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_INI_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_ini_resp_msg_v01_ei[];
struct wlfw_athdiag_read_req_msg_v01 {
u32 offset;
u32 mem_type;
u32 data_len;
};
#define WLFW_ATHDIAG_READ_REQ_MSG_V01_MAX_MSG_LEN 21
extern struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[];
struct wlfw_athdiag_read_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 data_valid;
u32 data_len;
u8 data[QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01];
};
#define WLFW_ATHDIAG_READ_RESP_MSG_V01_MAX_MSG_LEN 6156
extern struct qmi_elem_info wlfw_athdiag_read_resp_msg_v01_ei[];
struct wlfw_athdiag_write_req_msg_v01 {
u32 offset;
u32 mem_type;
u32 data_len;
u8 data[QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01];
};
#define WLFW_ATHDIAG_WRITE_REQ_MSG_V01_MAX_MSG_LEN 6163
extern struct qmi_elem_info wlfw_athdiag_write_req_msg_v01_ei[];
struct wlfw_athdiag_write_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_ATHDIAG_WRITE_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_athdiag_write_resp_msg_v01_ei[];
struct wlfw_vbatt_req_msg_v01 {
u64 voltage_uv;
};
#define WLFW_VBATT_REQ_MSG_V01_MAX_MSG_LEN 11
extern struct qmi_elem_info wlfw_vbatt_req_msg_v01_ei[];
struct wlfw_vbatt_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_VBATT_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_vbatt_resp_msg_v01_ei[];
struct wlfw_mac_addr_req_msg_v01 {
u8 mac_addr_valid;
u8 mac_addr[QMI_WLFW_MAC_ADDR_SIZE_V01];
};
#define WLFW_MAC_ADDR_REQ_MSG_V01_MAX_MSG_LEN 9
extern struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[];
struct wlfw_mac_addr_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_MAC_ADDR_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[];
struct wlfw_host_cap_req_msg_v01 {
u8 num_clients_valid;
u32 num_clients;
u8 wake_msi_valid;
u32 wake_msi;
u8 gpios_valid;
u32 gpios_len;
u32 gpios[QMI_WLFW_MAX_NUM_GPIO_V01];
u8 nm_modem_valid;
u8 nm_modem;
u8 bdf_support_valid;
u8 bdf_support;
u8 bdf_cache_support_valid;
u8 bdf_cache_support;
u8 m3_support_valid;
u8 m3_support;
u8 m3_cache_support_valid;
u8 m3_cache_support;
u8 cal_filesys_support_valid;
u8 cal_filesys_support;
u8 cal_cache_support_valid;
u8 cal_cache_support;
u8 cal_done_valid;
u8 cal_done;
u8 mem_bucket_valid;
u32 mem_bucket;
u8 mem_cfg_mode_valid;
u8 mem_cfg_mode;
u8 cal_duration_valid;
u16 cal_duration;
};
#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 194
extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
struct wlfw_host_cap_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_HOST_CAP_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[];
struct wlfw_request_mem_ind_msg_v01 {
u32 mem_seg_len;
struct wlfw_mem_seg_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
};
#define WLFW_REQUEST_MEM_IND_MSG_V01_MAX_MSG_LEN 1124
extern struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[];
struct wlfw_respond_mem_req_msg_v01 {
u32 mem_seg_len;
struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
};
#define WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN 548
extern struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[];
struct wlfw_respond_mem_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_RESPOND_MEM_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[];
struct wlfw_fw_mem_ready_ind_msg_v01 {
char placeholder;
};
#define WLFW_FW_MEM_READY_IND_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[];
struct wlfw_fw_init_done_ind_msg_v01 {
char placeholder;
};
#define WLFW_FW_INIT_DONE_IND_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[];
struct wlfw_rejuvenate_ind_msg_v01 {
u8 cause_for_rejuvenation_valid;
u8 cause_for_rejuvenation;
u8 requesting_sub_system_valid;
u8 requesting_sub_system;
u8 line_number_valid;
u16 line_number;
u8 function_name_valid;
char function_name[QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1];
};
#define WLFW_REJUVENATE_IND_MSG_V01_MAX_MSG_LEN 144
extern struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[];
struct wlfw_rejuvenate_ack_req_msg_v01 {
char placeholder;
};
#define WLFW_REJUVENATE_ACK_REQ_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_rejuvenate_ack_req_msg_v01_ei[];
struct wlfw_rejuvenate_ack_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_REJUVENATE_ACK_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_rejuvenate_ack_resp_msg_v01_ei[];
struct wlfw_dynamic_feature_mask_req_msg_v01 {
u8 mask_valid;
u64 mask;
};
#define WLFW_DYNAMIC_FEATURE_MASK_REQ_MSG_V01_MAX_MSG_LEN 11
extern struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[];
struct wlfw_dynamic_feature_mask_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 prev_mask_valid;
u64 prev_mask;
u8 curr_mask_valid;
u64 curr_mask;
};
#define WLFW_DYNAMIC_FEATURE_MASK_RESP_MSG_V01_MAX_MSG_LEN 29
extern struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[];
struct wlfw_m3_info_req_msg_v01 {
u64 addr;
u32 size;
};
#define WLFW_M3_INFO_REQ_MSG_V01_MAX_MSG_LEN 18
extern struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[];
struct wlfw_m3_info_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_M3_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_m3_info_resp_msg_v01_ei[];
struct wlfw_xo_cal_ind_msg_v01 {
u8 xo_cal_data;
};
#define WLFW_XO_CAL_IND_MSG_V01_MAX_MSG_LEN 4
extern struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[];
struct wlfw_cal_done_ind_msg_v01 {
char placeholder;
};
#define WLFW_CAL_DONE_IND_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_cal_done_ind_msg_v01_ei[];
struct wlfw_qdss_trace_req_mem_ind_msg_v01 {
u32 mem_seg_len;
struct wlfw_mem_seg_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
};
#define WLFW_QDSS_TRACE_REQ_MEM_IND_MSG_V01_MAX_MSG_LEN 1124
extern struct qmi_elem_info wlfw_qdss_trace_req_mem_ind_msg_v01_ei[];
struct wlfw_qdss_trace_mem_info_req_msg_v01 {
u32 mem_seg_len;
struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
};
#define WLFW_QDSS_TRACE_MEM_INFO_REQ_MSG_V01_MAX_MSG_LEN 548
extern struct qmi_elem_info wlfw_qdss_trace_mem_info_req_msg_v01_ei[];
struct wlfw_qdss_trace_mem_info_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_QDSS_TRACE_MEM_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_qdss_trace_mem_info_resp_msg_v01_ei[];
struct wlfw_qdss_trace_save_ind_msg_v01 {
u32 source;
u32 total_size;
u8 mem_seg_valid;
u32 mem_seg_len;
struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
u8 file_name_valid;
char file_name[QMI_WLFW_MAX_STR_LEN_V01 + 1];
};
#define WLFW_QDSS_TRACE_SAVE_IND_MSG_V01_MAX_MSG_LEN 581
extern struct qmi_elem_info wlfw_qdss_trace_save_ind_msg_v01_ei[];
struct wlfw_qdss_trace_data_req_msg_v01 {
u32 seg_id;
};
#define WLFW_QDSS_TRACE_DATA_REQ_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_qdss_trace_data_req_msg_v01_ei[];
struct wlfw_qdss_trace_data_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 total_size_valid;
u32 total_size;
u8 seg_id_valid;
u32 seg_id;
u8 data_valid;
u32 data_len;
u8 data[QMI_WLFW_MAX_DATA_SIZE_V01];
u8 end_valid;
u8 end;
};
#define WLFW_QDSS_TRACE_DATA_RESP_MSG_V01_MAX_MSG_LEN 6174
extern struct qmi_elem_info wlfw_qdss_trace_data_resp_msg_v01_ei[];
struct wlfw_qdss_trace_config_download_req_msg_v01 {
u8 total_size_valid;
u32 total_size;
u8 seg_id_valid;
u32 seg_id;
u8 data_valid;
u32 data_len;
u8 data[QMI_WLFW_MAX_DATA_SIZE_V01];
u8 end_valid;
u8 end;
};
#define WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6167
extern struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[];
struct wlfw_qdss_trace_config_download_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_qdss_trace_config_download_resp_msg_v01_ei[];
struct wlfw_qdss_trace_mode_req_msg_v01 {
u8 mode_valid;
enum wlfw_qdss_trace_mode_enum_v01 mode;
u8 option_valid;
u64 option;
};
#define WLFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_MSG_LEN 18
extern struct qmi_elem_info wlfw_qdss_trace_mode_req_msg_v01_ei[];
struct wlfw_qdss_trace_mode_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_QDSS_TRACE_MODE_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_qdss_trace_mode_resp_msg_v01_ei[];
struct wlfw_qdss_trace_free_ind_msg_v01 {
u8 mem_seg_valid;
u32 mem_seg_len;
struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
};
#define WLFW_QDSS_TRACE_FREE_IND_MSG_V01_MAX_MSG_LEN 548
extern struct qmi_elem_info wlfw_qdss_trace_free_ind_msg_v01_ei[];
struct wlfw_shutdown_req_msg_v01 {
u8 shutdown_valid;
u8 shutdown;
};
#define WLFW_SHUTDOWN_REQ_MSG_V01_MAX_MSG_LEN 4
extern struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[];
struct wlfw_shutdown_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_SHUTDOWN_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[];
struct wlfw_antenna_switch_req_msg_v01 {
char placeholder;
};
#define WLFW_ANTENNA_SWITCH_REQ_MSG_V01_MAX_MSG_LEN 0
extern struct qmi_elem_info wlfw_antenna_switch_req_msg_v01_ei[];
struct wlfw_antenna_switch_resp_msg_v01 {
struct qmi_response_type_v01 resp;
u8 antenna_valid;
u64 antenna;
};
#define WLFW_ANTENNA_SWITCH_RESP_MSG_V01_MAX_MSG_LEN 18
extern struct qmi_elem_info wlfw_antenna_switch_resp_msg_v01_ei[];
struct wlfw_antenna_grant_req_msg_v01 {
u8 grant_valid;
u64 grant;
};
#define WLFW_ANTENNA_GRANT_REQ_MSG_V01_MAX_MSG_LEN 11
extern struct qmi_elem_info wlfw_antenna_grant_req_msg_v01_ei[];
struct wlfw_antenna_grant_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_ANTENNA_GRANT_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_antenna_grant_resp_msg_v01_ei[];
struct wlfw_wfc_call_status_req_msg_v01 {
u32 wfc_call_status_len;
u8 wfc_call_status[QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01];
};
#define WLFW_WFC_CALL_STATUS_REQ_MSG_V01_MAX_MSG_LEN 261
extern struct qmi_elem_info wlfw_wfc_call_status_req_msg_v01_ei[];
struct wlfw_wfc_call_status_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define WLFW_WFC_CALL_STATUS_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct qmi_elem_info wlfw_wfc_call_status_resp_msg_v01_ei[];
#endif

216
include/net/cnss2.h Normal file
View File

@ -0,0 +1,216 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */
#ifndef _NET_CNSS2_H
#define _NET_CNSS2_H
#include <linux/pci.h>
#define CNSS_MAX_FILE_NAME 20
#define CNSS_MAX_TIMESTAMP_LEN 32
/*
* Temporary change for compilation, will be removed
* after WLAN host driver switched to use new APIs
*/
#define CNSS_API_WITH_DEV
enum cnss_bus_width_type {
CNSS_BUS_WIDTH_NONE,
CNSS_BUS_WIDTH_IDLE,
CNSS_BUS_WIDTH_LOW,
CNSS_BUS_WIDTH_MEDIUM,
CNSS_BUS_WIDTH_HIGH,
CNSS_BUS_WIDTH_VERY_HIGH
};
enum cnss_platform_cap_flag {
CNSS_HAS_EXTERNAL_SWREG = 0x01,
CNSS_HAS_UART_ACCESS = 0x02,
};
struct cnss_platform_cap {
u32 cap_flag;
};
struct cnss_fw_files {
char image_file[CNSS_MAX_FILE_NAME];
char board_data[CNSS_MAX_FILE_NAME];
char otp_data[CNSS_MAX_FILE_NAME];
char utf_file[CNSS_MAX_FILE_NAME];
char utf_board_data[CNSS_MAX_FILE_NAME];
char epping_file[CNSS_MAX_FILE_NAME];
char evicted_data[CNSS_MAX_FILE_NAME];
};
struct cnss_device_version {
u32 family_number;
u32 device_number;
u32 major_version;
u32 minor_version;
};
struct cnss_soc_info {
void __iomem *va;
phys_addr_t pa;
uint32_t chip_id;
uint32_t chip_family;
uint32_t board_id;
uint32_t soc_id;
uint32_t fw_version;
char fw_build_timestamp[CNSS_MAX_TIMESTAMP_LEN + 1];
struct cnss_device_version device_version;
};
struct cnss_wlan_runtime_ops {
int (*runtime_suspend)(struct pci_dev *pdev);
int (*runtime_resume)(struct pci_dev *pdev);
};
struct cnss_wlan_driver {
char *name;
int (*probe)(struct pci_dev *pdev, const struct pci_device_id *id);
void (*remove)(struct pci_dev *pdev);
int (*idle_restart)(struct pci_dev *pdev,
const struct pci_device_id *id);
int (*idle_shutdown)(struct pci_dev *pdev);
int (*reinit)(struct pci_dev *pdev, const struct pci_device_id *id);
void (*shutdown)(struct pci_dev *pdev);
void (*crash_shutdown)(struct pci_dev *pdev);
int (*suspend)(struct pci_dev *pdev, pm_message_t state);
int (*resume)(struct pci_dev *pdev);
int (*suspend_noirq)(struct pci_dev *pdev);
int (*resume_noirq)(struct pci_dev *pdev);
void (*modem_status)(struct pci_dev *pdev, int state);
void (*update_status)(struct pci_dev *pdev, uint32_t status);
struct cnss_wlan_runtime_ops *runtime_ops;
const struct pci_device_id *id_table;
};
enum cnss_driver_status {
CNSS_UNINITIALIZED,
CNSS_INITIALIZED,
CNSS_LOAD_UNLOAD,
CNSS_RECOVERY,
CNSS_FW_DOWN,
};
struct cnss_ce_tgt_pipe_cfg {
u32 pipe_num;
u32 pipe_dir;
u32 nentries;
u32 nbytes_max;
u32 flags;
u32 reserved;
};
struct cnss_ce_svc_pipe_cfg {
u32 service_id;
u32 pipe_dir;
u32 pipe_num;
};
struct cnss_shadow_reg_cfg {
u16 ce_id;
u16 reg_offset;
};
struct cnss_shadow_reg_v2_cfg {
u32 addr;
};
struct cnss_rri_over_ddr_cfg {
u32 base_addr_low;
u32 base_addr_high;
};
struct cnss_wlan_enable_cfg {
u32 num_ce_tgt_cfg;
struct cnss_ce_tgt_pipe_cfg *ce_tgt_cfg;
u32 num_ce_svc_pipe_cfg;
struct cnss_ce_svc_pipe_cfg *ce_svc_cfg;
u32 num_shadow_reg_cfg;
struct cnss_shadow_reg_cfg *shadow_reg_cfg;
u32 num_shadow_reg_v2_cfg;
struct cnss_shadow_reg_v2_cfg *shadow_reg_v2_cfg;
bool rri_over_ddr_cfg_valid;
struct cnss_rri_over_ddr_cfg rri_over_ddr_cfg;
};
enum cnss_driver_mode {
CNSS_MISSION,
CNSS_FTM,
CNSS_EPPING,
CNSS_WALTEST,
CNSS_OFF,
CNSS_CCPM,
CNSS_QVIT,
CNSS_CALIBRATION,
};
enum cnss_recovery_reason {
CNSS_REASON_DEFAULT,
CNSS_REASON_LINK_DOWN,
CNSS_REASON_RDDM,
CNSS_REASON_TIMEOUT,
};
extern int cnss_wlan_register_driver(struct cnss_wlan_driver *driver);
extern void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver);
extern void cnss_device_crashed(struct device *dev);
extern int cnss_pci_link_down(struct device *dev);
extern int cnss_pci_is_device_down(struct device *dev);
extern void cnss_schedule_recovery(struct device *dev,
enum cnss_recovery_reason reason);
extern int cnss_self_recovery(struct device *dev,
enum cnss_recovery_reason reason);
extern int cnss_force_fw_assert(struct device *dev);
extern int cnss_force_collect_rddm(struct device *dev);
extern void *cnss_get_virt_ramdump_mem(struct device *dev, unsigned long *size);
extern int cnss_get_fw_files_for_target(struct device *dev,
struct cnss_fw_files *pfw_files,
u32 target_type, u32 target_version);
extern int cnss_get_platform_cap(struct device *dev,
struct cnss_platform_cap *cap);
extern struct iommu_domain *cnss_smmu_get_domain(struct device *dev);
extern int cnss_smmu_map(struct device *dev,
phys_addr_t paddr, uint32_t *iova_addr, size_t size);
extern int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info);
extern int cnss_request_bus_bandwidth(struct device *dev, int bandwidth);
extern int cnss_power_up(struct device *dev);
extern int cnss_power_down(struct device *dev);
extern int cnss_idle_restart(struct device *dev);
extern int cnss_idle_shutdown(struct device *dev);
extern void cnss_request_pm_qos(struct device *dev, u32 qos_val);
extern void cnss_remove_pm_qos(struct device *dev);
extern void cnss_lock_pm_sem(struct device *dev);
extern void cnss_release_pm_sem(struct device *dev);
extern int cnss_wlan_pm_control(struct device *dev, bool vote);
extern int cnss_auto_suspend(struct device *dev);
extern int cnss_auto_resume(struct device *dev);
extern int cnss_pci_is_drv_connected(struct device *dev);
extern int cnss_pci_force_wake_request(struct device *dev);
extern int cnss_pci_is_device_awake(struct device *dev);
extern int cnss_pci_force_wake_release(struct device *dev);
extern int cnss_get_user_msi_assignment(struct device *dev, char *user_name,
int *num_vectors,
uint32_t *user_base_data,
uint32_t *base_vector);
extern int cnss_get_msi_irq(struct device *dev, unsigned int vector);
extern void cnss_get_msi_address(struct device *dev, uint32_t *msi_addr_low,
uint32_t *msi_addr_high);
extern int cnss_wlan_enable(struct device *dev,
struct cnss_wlan_enable_cfg *config,
enum cnss_driver_mode mode,
const char *host_version);
extern int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode);
extern unsigned int cnss_get_boot_timeout(struct device *dev);
extern int cnss_athdiag_read(struct device *dev, uint32_t offset,
uint32_t mem_type, uint32_t data_len,
uint8_t *output);
extern int cnss_athdiag_write(struct device *dev, uint32_t offset,
uint32_t mem_type, uint32_t data_len,
uint8_t *input);
extern int cnss_set_fw_log_mode(struct device *dev, uint8_t fw_log_mode);
#endif /* _NET_CNSS2_H */