Merge "cnss2: Update driver to support multiple devices"

This commit is contained in:
qctecmdr 2021-03-11 10:14:26 -08:00 • committed by Gerrit - the friendly Code Review server
commit 18b2685bee
9 changed files with 318 additions and 36 deletions

View file

@ -19,18 +19,39 @@ enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev)
return CNSS_BUS_NONE;
}
enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id)
enum cnss_dev_bus_type cnss_get_bus_type(struct cnss_plat_data *plat_priv)
{
switch (device_id) {
int ret;
struct device *dev;
enum cnss_dev_bus_type bus_type = CNSS_BUS_NONE;
if (plat_priv->is_converged_dt) {
dev = &plat_priv->plat_dev->dev;
ret = of_property_read_u32(dev->of_node, "qcom,bus-type",
&bus_type);
if (!ret && bus_type <= CNSS_BUS_USB)
cnss_pr_dbg("Got bus type[%u] from dt\n", bus_type);
else
cnss_pr_err("No bus type for converged dt\n");
return bus_type;
}
/* Get bus type according to device id if it's not converged DT */
switch (plat_priv->device_id) {
case QCA6174_DEVICE_ID:
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
return CNSS_BUS_PCI;
bus_type = CNSS_BUS_PCI;
break;
default:
cnss_pr_err("Unknown device_id: 0x%lx\n", device_id);
return CNSS_BUS_NONE;
cnss_pr_err("Unknown device: 0x%lx\n", plat_priv->device_id);
break;
}
return bus_type;
}
void *cnss_bus_dev_to_bus_priv(struct device *dev)
@ -544,3 +565,26 @@ int cnss_bus_get_iova_ipa(struct cnss_plat_data *plat_priv, u64 *addr,
return -EINVAL;
}
}
int cnss_bus_get_msi_assignment(struct cnss_plat_data *plat_priv,
char *msi_name,
int *num_vectors,
u32 *user_base_data,
u32 *base_vector)
{
if (!plat_priv)
return -ENODEV;
switch (plat_priv->bus_type) {
case CNSS_BUS_PCI:
return cnss_pci_get_user_msi_assignment(plat_priv->bus_priv,
msi_name,
num_vectors,
user_base_data,
base_vector);
default:
cnss_pr_err("Unsupported bus type: %d\n",
plat_priv->bus_type);
return -EINVAL;
}
}

View file

@ -15,13 +15,15 @@
#define QCA6290_DEVICE_ID 0x1100
#define QCA6390_VENDOR_ID 0x17CB
#define QCA6390_DEVICE_ID 0x1101
#define QCN7605_VENDOR_ID 0x17CB
#define QCN7605_DEVICE_ID 0x1102
#define QCA6490_VENDOR_ID 0x17CB
#define QCA6490_DEVICE_ID 0x1103
#define WCN7850_VENDOR_ID 0x17CB
#define WCN7850_DEVICE_ID 0x1107
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);
enum cnss_dev_bus_type cnss_get_bus_type(struct cnss_plat_data *plat_priv);
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);
@ -62,4 +64,9 @@ int cnss_bus_debug_reg_write(struct cnss_plat_data *plat_priv, u32 offset,
int cnss_bus_get_iova(struct cnss_plat_data *plat_priv, u64 *addr, u64 *size);
int cnss_bus_get_iova_ipa(struct cnss_plat_data *plat_priv, u64 *addr,
u64 *size);
int cnss_bus_get_msi_assignment(struct cnss_plat_data *plat_priv,
char *msi_name,
int *num_vectors,
u32 *user_base_data,
u32 *base_vector);
#endif /* _CNSS_BUS_H */

View file

@ -301,6 +301,9 @@ int cnss_wlan_enable(struct device *dev,
if (mode == CNSS_WALTEST || mode == CNSS_CCPM)
goto skip_cfg;
if (plat_priv->device_id == QCN7605_DEVICE_ID)
config->send_msi_ce = true;
ret = cnss_wlfw_wlan_cfg_send_sync(plat_priv, config, host_version);
if (ret)
goto out;
@ -435,11 +438,17 @@ static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
cnss_wlfw_bdf_dnld_send_sync(plat_priv, CNSS_BDF_REGDB);
if (plat_priv->device_id == QCN7605_DEVICE_ID)
plat_priv->ctrl_params.bdf_type = CNSS_BDF_BIN;
ret = cnss_wlfw_bdf_dnld_send_sync(plat_priv,
plat_priv->ctrl_params.bdf_type);
if (ret)
goto out;
if (plat_priv->device_id == QCN7605_DEVICE_ID)
return 0;
ret = cnss_bus_load_m3(plat_priv);
if (ret)
goto out;
@ -1596,8 +1605,13 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv,
cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_OFF);
cnss_bus_free_qdss_mem(plat_priv);
cnss_release_antenna_sharing(plat_priv);
if (plat_priv->device_id == QCN7605_DEVICE_ID)
goto skip_shutdown;
cnss_bus_dev_shutdown(plat_priv);
msleep(COLD_BOOT_CAL_SHUTDOWN_DELAY_MS);
skip_shutdown:
complete(&plat_priv->cal_complete);
clear_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state);
set_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state);
@ -2183,7 +2197,7 @@ static int cnss_register_ramdump_v1(struct cnss_plat_data *plat_priv)
dev = &plat_priv->plat_dev->dev;
ramdump_info = &plat_priv->ramdump_info;
if (of_property_read_u32(dev->of_node, "qcom,wlan-ramdump-dynamic",
if (of_property_read_u32(plat_priv->dev_node, "qcom,wlan-ramdump-dynamic",
&ramdump_size) == 0) {
ramdump_info->ramdump_va =
dma_alloc_coherent(dev, ramdump_size,
@ -2261,13 +2275,13 @@ static int cnss_register_ramdump_v2(struct cnss_plat_data *plat_priv)
struct cnss_ramdump_info_v2 *info_v2;
struct cnss_dump_data *dump_data;
struct msm_dump_entry dump_entry;
struct device *dev = &plat_priv->plat_dev->dev;
u32 ramdump_size = 0;
info_v2 = &plat_priv->ramdump_info_v2;
dump_data = &info_v2->dump_data;
if (of_property_read_u32(dev->of_node, "qcom,wlan-ramdump-dynamic",
if (of_property_read_u32(plat_priv->dev_node,
"qcom,wlan-ramdump-dynamic",
&ramdump_size) == 0)
info_v2->ramdump_size = ramdump_size;
@ -2334,6 +2348,7 @@ int cnss_register_ramdump(struct cnss_plat_data *plat_priv)
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case WCN7850_DEVICE_ID:
ret = cnss_register_ramdump_v2(plat_priv);
@ -2354,6 +2369,7 @@ void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv)
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case WCN7850_DEVICE_ID:
cnss_unregister_ramdump_v2(plat_priv);
@ -2477,7 +2493,7 @@ int cnss_minidump_remove_region(struct cnss_plat_data *plat_priv,
* For different interconnect path configured in device tree setup voting data
* for list of bandwidth requirements.
*
* Result: 0 for success. -EINVAL if not configured
* Result: 0 for success. -ENOMEM if cannot allocate memory
*/
static int cnss_register_bus_scale(struct cnss_plat_data *plat_priv)
{
@ -2491,8 +2507,8 @@ static int cnss_register_bus_scale(struct cnss_plat_data *plat_priv)
"qcom,icc-path-count",
&plat_priv->icc.path_count);
if (ret) {
cnss_pr_err("Platform Bus Interconnect path not configured\n");
return -EINVAL;
cnss_pr_dbg("Platform Bus Interconnect path not configured\n");
return 0;
}
ret = of_property_read_u32(plat_priv->plat_dev->dev.of_node,
"qcom,bus-bw-cfg-count",
@ -2967,6 +2983,7 @@ static const struct platform_device_id cnss_platform_id_table[] = {
{ .name = "qca6390", .driver_data = QCA6390_DEVICE_ID, },
{ .name = "qca6490", .driver_data = QCA6490_DEVICE_ID, },
{ .name = "wcn7850", .driver_data = WCN7850_DEVICE_ID, },
{ .name = "qcaconv", .driver_data = 0},
{ },
};
@ -2986,6 +3003,9 @@ static const struct of_device_id cnss_of_match_table[] = {
{
.compatible = "qcom,cnss-wcn7850",
.data = (void *)&cnss_platform_id_table[4]},
{
.compatible = "qcom,cnss-qca-converged",
.data = (void *)&cnss_platform_id_table[5]},
{ },
};
MODULE_DEVICE_TABLE(of, cnss_of_match_table);
@ -2997,6 +3017,12 @@ cnss_use_nv_mac(struct cnss_plat_data *plat_priv)
"use-nv-mac");
}
static inline bool
cnss_is_converged_dt(struct cnss_plat_data *plat_priv)
{
return of_property_read_bool(plat_priv->plat_dev->dev.of_node,
"qcom,converged-dt");
}
static int cnss_probe(struct platform_device *plat_dev)
{
int ret = 0;
@ -3028,7 +3054,9 @@ static int cnss_probe(struct platform_device *plat_dev)
plat_priv->plat_dev = plat_dev;
plat_priv->device_id = device_id->driver_data;
plat_priv->bus_type = cnss_get_bus_type(plat_priv->device_id);
plat_priv->is_converged_dt = cnss_is_converged_dt(plat_priv);
plat_priv->dev_node = plat_priv->plat_dev->dev.of_node;
plat_priv->bus_type = cnss_get_bus_type(plat_priv);
plat_priv->use_nv_mac = cnss_use_nv_mac(plat_priv);
plat_priv->use_fw_path_with_prefix =
cnss_use_fw_path_with_prefix(plat_priv);

View file

@ -54,6 +54,7 @@
enum cnss_dev_bus_type {
CNSS_BUS_NONE = -1,
CNSS_BUS_PCI,
CNSS_BUS_USB,
};
struct cnss_vreg_cfg {
@ -493,6 +494,8 @@ struct cnss_plat_data {
struct cnss_dms_data dms;
int power_up_error;
u32 hw_trc_override;
u32 is_converged_dt;
struct device_node *dev_node;
};
#ifdef CONFIG_ARCH_QCOM
@ -558,5 +561,5 @@ int cnss_enable_int_pow_amp_vreg(struct cnss_plat_data *plat_priv);
int cnss_get_tcs_info(struct cnss_plat_data *plat_priv);
unsigned int cnss_get_timeout(struct cnss_plat_data *plat_priv,
enum cnss_timeout_type);
int cnss_dev_specific_power_on(struct cnss_plat_data *plat_priv);
#endif /* _CNSS_MAIN_H */

View file

@ -7,6 +7,7 @@
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/msi.h>
#include <linux/of_address.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_reserved_mem.h>
@ -43,6 +44,7 @@
#define QCA6390_PATH_PREFIX "qca6390/"
#define QCA6490_PATH_PREFIX "qca6490/"
#define WCN7850_PATH_PREFIX "wcn7850/"
#define QCN7605_PATH_PREFIX "qcn7605/"
#define DEFAULT_M3_FILE_NAME "m3.bin"
#define DEFAULT_FW_FILE_NAME "amss.bin"
#define FW_V2_FILE_NAME "amss20.bin"
@ -2594,6 +2596,7 @@ int cnss_pci_dev_powerup(struct cnss_pci_data *pci_priv)
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case WCN7850_DEVICE_ID:
ret = cnss_qca6290_powerup(pci_priv);
@ -2622,6 +2625,7 @@ int cnss_pci_dev_shutdown(struct cnss_pci_data *pci_priv)
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case WCN7850_DEVICE_ID:
ret = cnss_qca6290_shutdown(pci_priv);
@ -2650,6 +2654,7 @@ int cnss_pci_dev_crash_shutdown(struct cnss_pci_data *pci_priv)
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case WCN7850_DEVICE_ID:
cnss_qca6290_crash_shutdown(pci_priv);
@ -2678,6 +2683,7 @@ int cnss_pci_dev_ramdump(struct cnss_pci_data *pci_priv)
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case WCN7850_DEVICE_ID:
ret = cnss_qca6290_ramdump(pci_priv);
@ -3980,18 +3986,24 @@ static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv)
struct pci_dev *pci_dev = pci_priv->pci_dev;
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
struct device_node *of_node;
struct resource res_tmp;
struct resource *res;
const char *iommu_dma_type;
u32 addr_win[2];
int ret = 0;
int index;
of_node = of_parse_phandle(pci_dev->dev.of_node, "qcom,iommu-group", 0);
if (!of_node)
if (!of_node) {
cnss_pr_err("No iommu group configuration\n");
return ret;
}
cnss_pr_dbg("Initializing SMMU\n");
pci_priv->iommu_domain = iommu_get_domain_for_dev(&pci_dev->dev);
if (!pci_priv->iommu_domain)
cnss_pr_err("No iommu domain found\n");
ret = of_property_read_string(of_node, "qcom,iommu-dma",
&iommu_dma_type);
if (!ret && !strcmp("fastmap", iommu_dma_type)) {
@ -4005,8 +4017,7 @@ static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv)
addr_win, ARRAY_SIZE(addr_win));
if (ret) {
cnss_pr_err("Invalid SMMU size window, err = %d\n", ret);
of_node_put(of_node);
return ret;
goto out;
}
pci_priv->smmu_iova_start = addr_win[0];
@ -4015,8 +4026,28 @@ static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv)
&pci_priv->smmu_iova_start,
pci_priv->smmu_iova_len);
res = platform_get_resource_byname(plat_priv->plat_dev, IORESOURCE_MEM,
"smmu_iova_ipa");
if (plat_priv->is_converged_dt) {
index = of_property_match_string(plat_priv->dev_node, "reg-names",
"smmu_iova_ipa");
if (index < 0) {
cnss_pr_err("failed to find reg smmu_iova_ipa\n");
ret = index;
goto out;
}
ret = of_address_to_resource(plat_priv->dev_node, index, &res_tmp);
if (ret) {
cnss_pr_err("failed to get resource\n");
goto out;
}
res = &res_tmp;
} else {
res = platform_get_resource_byname(plat_priv->plat_dev,
IORESOURCE_MEM,
"smmu_iova_ipa");
}
if (res) {
pci_priv->smmu_iova_ipa_start = res->start;
pci_priv->smmu_iova_ipa_current = res->start;
@ -4029,10 +4060,10 @@ static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv)
pci_priv->iommu_geometry = of_property_read_bool(of_node,
"qcom,iommu-geometry");
cnss_pr_dbg("iommu_geometry: %d\n", pci_priv->iommu_geometry);
out:
of_node_put(of_node);
return 0;
return ret;
}
static void cnss_pci_deinit_smmu(struct cnss_pci_data *pci_priv)
@ -4299,6 +4330,19 @@ static void cnss_pci_disable_msi(struct cnss_pci_data *pci_priv)
pci_free_irq_vectors(pci_priv->pci_dev);
}
int cnss_pci_get_user_msi_assignment(struct cnss_pci_data *pci_priv,
char *user_name,
int *num_vectors,
u32 *user_base_data,
u32 *base_vector)
{
return cnss_get_user_msi_assignment(&pci_priv->pci_dev->dev,
user_name,
num_vectors,
user_base_data,
base_vector);
}
int cnss_get_user_msi_assignment(struct device *dev, char *user_name,
int *num_vectors, u32 *user_base_data,
u32 *base_vector)
@ -4380,9 +4424,9 @@ u32 cnss_pci_get_wake_msi(struct cnss_pci_data *pci_priv)
if (!pci_priv)
return -ENODEV;
ret = cnss_get_user_msi_assignment(&pci_priv->pci_dev->dev,
WAKE_MSI_NAME, &num_vectors,
&user_base_data, &base_vector);
ret = cnss_pci_get_user_msi_assignment(pci_priv,
WAKE_MSI_NAME, &num_vectors,
&user_base_data, &base_vector);
if (ret) {
cnss_pr_err("WAKE MSI is not valid\n");
return 0;
@ -4930,6 +4974,10 @@ void cnss_pci_add_fw_prefix_name(struct cnss_pci_data *pci_priv,
}
switch (pci_priv->device_id) {
case QCN7605_DEVICE_ID:
scnprintf(prefix_name, MAX_FIRMWARE_NAME_LEN,
QCN7605_PATH_PREFIX "%s", name);
break;
case QCA6390_DEVICE_ID:
scnprintf(prefix_name, MAX_FIRMWARE_NAME_LEN,
QCA6390_PATH_PREFIX "%s", name);
@ -5129,9 +5177,9 @@ static int cnss_pci_get_mhi_msi(struct cnss_pci_data *pci_priv)
u32 user_base_data, base_vector;
int *irq;
ret = cnss_get_user_msi_assignment(&pci_priv->pci_dev->dev,
MHI_MSI_NAME, &num_vectors,
&user_base_data, &base_vector);
ret = cnss_pci_get_user_msi_assignment(pci_priv,
MHI_MSI_NAME, &num_vectors,
&user_base_data, &base_vector);
if (ret)
return ret;
@ -5245,7 +5293,7 @@ static int cnss_pci_register_mhi(struct cnss_pci_data *pci_priv)
mhi_ctrl->priv_data = pci_priv;
mhi_ctrl->dev = &pci_dev->dev;
mhi_ctrl->of_node = (&plat_priv->plat_dev->dev)->of_node;
mhi_ctrl->of_node = plat_priv->dev_node;
mhi_ctrl->dev_id = pci_priv->device_id;
mhi_ctrl->domain = pci_domain_nr(pci_dev->bus);
mhi_ctrl->bus = pci_dev->bus->number;
@ -5284,7 +5332,12 @@ static int cnss_pci_register_mhi(struct cnss_pci_data *pci_priv)
mhi_ctrl->rddm_size = pci_priv->plat_priv->ramdump_info_v2.ramdump_size;
if (!mhi_ctrl->rddm_size)
mhi_ctrl->rddm_size = RAMDUMP_SIZE_DEFAULT;
mhi_ctrl->sbl_size = SZ_512K;
if (pci_priv->device_id == QCN7605_DEVICE_ID)
mhi_ctrl->sbl_size = SZ_256K;
else
mhi_ctrl->sbl_size = SZ_512K;
mhi_ctrl->seg_len = SZ_512K;
mhi_ctrl->fbc_download = true;
mhi_ctrl->rddm_supported = true;
@ -5512,6 +5565,52 @@ static struct dev_pm_domain cnss_pm_domain = {
}
};
static int cnss_pci_get_dev_cfg_node(struct cnss_plat_data *plat_priv)
{
struct device_node *child;
u32 id, i;
int id_n, ret;
if (!plat_priv->is_converged_dt)
return 0;
if (!plat_priv->device_id) {
cnss_pr_err("Invalid device id\n");
return -EINVAL;
}
for_each_available_child_of_node(plat_priv->plat_dev->dev.of_node,
child) {
if (strcmp(child->name, "chip_cfg"))
continue;
id_n = of_property_count_u32_elems(child, "supported-ids");
if (id_n <= 0) {
cnss_pr_err("Device id is NOT set\n");
return -EINVAL;
}
for (i = 0; i < id_n; i++) {
ret = of_property_read_u32_index(child,
"supported-ids",
i, &id);
if (ret) {
cnss_pr_err("Failed to read supported ids\n");
return -EINVAL;
}
if (id == plat_priv->device_id) {
plat_priv->dev_node = child;
cnss_pr_dbg("got node[%s@%d] for device[0x%x]\n",
child->name, i, id);
return 0;
}
}
}
return -EINVAL;
}
static int cnss_pci_probe(struct pci_dev *pci_dev,
const struct pci_device_id *id)
{
@ -5544,6 +5643,16 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
if (plat_priv->use_pm_domain)
dev->pm_domain = &cnss_pm_domain;
ret = cnss_pci_get_dev_cfg_node(plat_priv);
if (ret) {
cnss_pr_err("Failed to get device cfg node, err = %d\n", ret);
goto reset_ctx;
}
ret = cnss_dev_specific_power_on(plat_priv);
if (ret)
goto reset_ctx;
cnss_pci_of_reserved_mem_device_init(pci_priv);
ret = cnss_register_subsys(plat_priv);
@ -5583,6 +5692,7 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
break;
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
case QCN7605_DEVICE_ID:
case QCA6490_DEVICE_ID:
case WCN7850_DEVICE_ID:
cnss_pci_set_wlaon_pwr_ctrl(pci_priv, false, false, false);
@ -5671,6 +5781,7 @@ static const struct pci_device_id cnss_pci_id_table[] = {
{ QCA6174_VENDOR_ID, QCA6174_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ QCA6290_VENDOR_ID, QCA6290_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ QCA6390_VENDOR_ID, QCA6390_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ QCN7605_VENDOR_ID, QCN7605_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID},
{ QCA6490_VENDOR_ID, QCA6490_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ WCN7850_VENDOR_ID, WCN7850_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
{ 0 }

View file

@ -248,5 +248,9 @@ int cnss_pci_debug_reg_write(struct cnss_pci_data *pci_priv, u32 offset,
int cnss_pci_get_iova(struct cnss_pci_data *pci_priv, u64 *addr, u64 *size);
int cnss_pci_get_iova_ipa(struct cnss_pci_data *pci_priv, u64 *addr,
u64 *size);
int cnss_pci_get_user_msi_assignment(struct cnss_pci_data *pci_priv,
char *user_name,
int *num_vectors,
u32 *user_base_data,
u32 *base_vector);
#endif /* _CNSS_PCI_H */

View file

@ -56,6 +56,7 @@ static struct cnss_clk_cfg cnss_clk_list[] = {
#define XO_CLK_GPIO "qcom,xo-clk-gpio"
#define WLAN_EN_ACTIVE "wlan_en_active"
#define WLAN_EN_SLEEP "wlan_en_sleep"
#define WLAN_VREGS_PROP "wlan_vregs"
#define BOOTSTRAP_DELAY 1000
#define WLAN_ENABLE_DELAY 1000
@ -97,7 +98,7 @@ static int cnss_get_vreg_single(struct cnss_plat_data *plat_priv,
snprintf(prop_name, MAX_PROP_SIZE, "qcom,%s-config",
vreg->cfg.name);
prop = of_get_property(dev->of_node, prop_name, &len);
prop = of_get_property(plat_priv->dev_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");
@ -269,18 +270,51 @@ static int cnss_get_vreg(struct cnss_plat_data *plat_priv,
int i;
struct cnss_vreg_info *vreg;
struct device *dev = &plat_priv->plat_dev->dev;
int id_n;
if (!list_empty(vreg_list)) {
if (!list_empty(&plat_priv->vreg_list) &&
!plat_priv->is_converged_dt) {
cnss_pr_dbg("Vregs have already been updated\n");
return 0;
}
for (i = 0; i < vreg_list_size; i++) {
if (plat_priv->is_converged_dt) {
id_n = of_property_count_strings(plat_priv->dev_node,
WLAN_VREGS_PROP);
if (id_n <= 0) {
if (id_n == -ENODATA) {
cnss_pr_dbg("No additional vregs for: %s:%lx\n",
plat_priv->dev_node->name,
plat_priv->device_id);
return 0;
}
cnss_pr_err("property %s is invalid or missed: %s:%lx\n",
WLAN_VREGS_PROP, plat_priv->dev_node->name,
plat_priv->device_id);
return -EINVAL;
}
} else {
id_n = vreg_list_size;
}
for (i = 0; i < id_n; i++) {
vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL);
if (!vreg)
return -ENOMEM;
memcpy(&vreg->cfg, &vreg_cfg[i], sizeof(vreg->cfg));
if (plat_priv->is_converged_dt) {
ret = of_property_read_string_index(plat_priv->dev_node,
WLAN_VREGS_PROP, i,
&vreg->cfg.name);
if (ret) {
cnss_pr_err("Failed to read vreg ids\n");
return ret;
}
} else {
memcpy(&vreg->cfg, &vreg_cfg[i], sizeof(vreg->cfg));
}
ret = cnss_get_vreg_single(plat_priv, vreg);
if (ret != 0) {
if (ret == -ENODEV) {
@ -1146,3 +1180,18 @@ int cnss_enable_int_pow_amp_vreg(struct cnss_plat_data *plat_priv)
cnss_pr_dbg("Setup S3E TCS Addr: %x Data: %d\n", addr_val, data_val);
return 0;
}
int cnss_dev_specific_power_on(struct cnss_plat_data *plat_priv)
{
int ret;
if (!plat_priv->is_converged_dt)
return 0;
ret = cnss_get_vreg_type(plat_priv, CNSS_VREG_PRIM);
if (ret)
return ret;
plat_priv->powered_on = false;
return cnss_power_on_device(plat_priv);
}

View file

@ -30,6 +30,7 @@
#define DEBUG_STR "debug"
#define HW_V1_NUMBER "v1"
#define HW_V2_NUMBER "v2"
#define CE_MSI_NAME "CE"
#define QMI_WLFW_TIMEOUT_MS (plat_priv->ctrl_params.qmi_timeout)
#define QMI_WLFW_TIMEOUT_JF msecs_to_jiffies(QMI_WLFW_TIMEOUT_MS)
@ -1277,7 +1278,7 @@ int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
struct wlfw_wlan_cfg_req_msg_v01 *req;
struct wlfw_wlan_cfg_resp_msg_v01 *resp;
struct qmi_txn txn;
u32 i;
u32 i, ce_id, num_vectors, user_base_data, base_vector;
int ret = 0;
if (!plat_priv)
@ -1323,7 +1324,17 @@ int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
req->svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir;
req->svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
}
if (config->num_shadow_reg_cfg) {
req->shadow_reg_valid = 1;
if (config->num_shadow_reg_cfg >
QMI_WLFW_MAX_NUM_SHADOW_REG_V01)
req->shadow_reg_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V01;
else
req->shadow_reg_len = config->num_shadow_reg_cfg;
memcpy(req->shadow_reg, config->shadow_reg_cfg,
sizeof(struct wlfw_shadow_reg_cfg_s_v01)
* req->shadow_reg_len);
}
req->shadow_reg_v2_valid = 1;
if (config->num_shadow_reg_v2_cfg >
QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01)
@ -1334,6 +1345,30 @@ int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
memcpy(req->shadow_reg_v2, config->shadow_reg_v2_cfg,
sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01)
* req->shadow_reg_v2_len);
if (config->rri_over_ddr_cfg_valid) {
req->rri_over_ddr_cfg_valid = 1;
req->rri_over_ddr_cfg.base_addr_low =
config->rri_over_ddr_cfg.base_addr_low;
req->rri_over_ddr_cfg.base_addr_high =
config->rri_over_ddr_cfg.base_addr_high;
}
if (config->send_msi_ce) {
ret = cnss_bus_get_msi_assignment(plat_priv,
CE_MSI_NAME,
&num_vectors,
&user_base_data,
&base_vector);
if (!ret) {
req->msi_cfg_valid = 1;
req->msi_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
for (ce_id = 0; ce_id < QMI_WLFW_MAX_NUM_CE_V01;
ce_id++) {
req->msi_cfg[ce_id].ce_id = ce_id;
req->msi_cfg[ce_id].msi_vector =
(ce_id % num_vectors) + base_vector;
}
}
}
ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
wlfw_wlan_cfg_resp_msg_v01_ei, resp);

View file

@ -149,6 +149,7 @@ struct cnss_wlan_enable_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;
bool send_msi_ce;
};
enum cnss_driver_mode {