diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index f22e95e3ebed..fbd5b3ba9fcf 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -2344,6 +2344,7 @@ static int cnss_probe(struct platform_device *plat_dev) INIT_LIST_HEAD(&plat_priv->clk_list); cnss_get_wlaon_pwr_ctrl_info(plat_priv); + cnss_get_tcs_info(plat_priv); cnss_get_cpr_info(plat_priv); cnss_init_control_params(plat_priv); diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index 7b2db9149138..6e57871810f1 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -307,10 +307,13 @@ struct cnss_control_params { unsigned int time_sync_period; }; +struct cnss_tcs_info { + resource_size_t cmd_base_addr; + void __iomem *cmd_base_addr_io; +}; + 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; @@ -403,6 +406,7 @@ struct cnss_plat_data { bool cbc_enabled; u8 use_nv_mac; u8 set_wlaon_pwr_ctrl; + struct cnss_tcs_info tcs_info; }; #ifdef CONFIG_ARCH_QCOM @@ -460,5 +464,7 @@ int cnss_minidump_add_region(struct cnss_plat_data *plat_priv, int cnss_minidump_remove_region(struct cnss_plat_data *plat_priv, enum cnss_fw_dump_type type, int seg_no, void *va, phys_addr_t pa, size_t size); +int cnss_enable_int_pow_amp_vreg(struct cnss_plat_data *plat_priv); +int cnss_get_tcs_info(struct cnss_plat_data *plat_priv); #endif /* _CNSS_MAIN_H */ diff --git a/drivers/net/wireless/cnss2/power.c b/drivers/net/wireless/cnss2/power.c index a224d075e10d..9d26835b407f 100644 --- a/drivers/net/wireless/cnss2/power.c +++ b/drivers/net/wireless/cnss2/power.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #include #include @@ -10,6 +10,7 @@ #include "main.h" #include "debug.h" +#include "bus.h" static struct cnss_vreg_cfg cnss_vreg_list[] = { {"vdd-wlan-core", 1300000, 1300000, 0, 0, 0}, @@ -832,15 +833,12 @@ void cnss_set_pin_connect_status(struct cnss_plat_data *plat_priv) plat_priv->pin_result.host_pin_result = pin_status; } -int cnss_get_cpr_info(struct cnss_plat_data *plat_priv) +int cnss_get_tcs_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"); @@ -849,6 +847,37 @@ int cnss_get_cpr_info(struct cnss_plat_data *plat_priv) goto out; } + plat_priv->tcs_info.cmd_base_addr = res->start; + addr_len = resource_size(res); + cnss_pr_dbg("TCS CMD base address is %pa with length %pa\n", + &plat_priv->tcs_info.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; + } + plat_priv->tcs_info.cmd_base_addr_io = tcs_cmd_base_addr; + return 0; +out: + return ret; +} + +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; + const char *cmd_db_name; + u32 cpr_pmic_addr = 0; + int ret = 0; + + if (plat_priv->tcs_info.cmd_base_addr == 0) { + cnss_pr_dbg("TCS CMD not configured\n"); + return 0; + } + ret = of_property_read_string(plat_dev->dev.of_node, "qcom,cmd_db_name", &cmd_db_name); if (ret) { @@ -873,24 +902,7 @@ int cnss_get_cpr_info(struct cnss_plat_data *plat_priv) 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; } @@ -902,8 +914,8 @@ int cnss_update_cpr_info(struct cnss_plat_data *plat_priv) 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"); + if (plat_priv->tcs_info.cmd_base_addr == 0) { + cnss_pr_dbg("TCS CMD not configured\n"); return 0; } @@ -919,7 +931,8 @@ int cnss_update_cpr_info(struct cnss_plat_data *plat_priv) 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; + tcs_cmd_addr = plat_priv->tcs_info.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 + @@ -931,9 +944,8 @@ int cnss_update_cpr_info(struct cnss_plat_data *plat_priv) 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; + plat_priv->tcs_info.cmd_base_addr + + offset + TCS_CMD_DATA_ADDR_OFFSET; cpr_info->tcs_cmd_data_addr_io = tcs_cmd_data_addr; } @@ -955,3 +967,37 @@ update_cpr: return 0; } + +int cnss_enable_int_pow_amp_vreg(struct cnss_plat_data *plat_priv) +{ + struct platform_device *plat_dev = plat_priv->plat_dev; + u32 offset, addr_val, data_val; + void __iomem *tcs_cmd; + int ret; + + if (!plat_priv->tcs_info.cmd_base_addr_io) { + cnss_pr_err("TCS CMD not configured\n"); + return -EINVAL; + } + + if (plat_priv->device_id != QCA6490_DEVICE_ID) + return -EINVAL; + + ret = of_property_read_u32(plat_dev->dev.of_node, + "qcom,tcs_offset_int_pow_amp_vreg", + &offset); + if (ret) { + cnss_pr_dbg("Internal Power Amp Vreg not configured\n"); + return -EINVAL; + } + tcs_cmd = plat_priv->tcs_info.cmd_base_addr_io + offset; + addr_val = readl_relaxed(tcs_cmd); + tcs_cmd += TCS_CMD_DATA_ADDR_OFFSET; + + /* 1 = enable Vreg */ + writel_relaxed(1, tcs_cmd); + + data_val = readl_relaxed(tcs_cmd); + cnss_pr_dbg("Setup S3E TCS Addr: %x Data: %d\n", addr_val, data_val); + return 0; +} diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c index c4f3f42a38ab..30b13b1651f9 100644 --- a/drivers/net/wireless/cnss2/qmi.c +++ b/drivers/net/wireless/cnss2/qmi.c @@ -632,6 +632,12 @@ bypass_bdf: if (bdf_type != CNSS_BDF_DUMMY) release_firmware(fw_entry); + /* QCA6490 enable S3E regulator for IPA configuration only */ + if (resp->host_bdf_data_valid) { + if (!(resp->host_bdf_data & QMI_WLFW_HW_XPA_V01)) + cnss_enable_int_pow_amp_vreg(plat_priv); + } + kfree(req); kfree(resp); return 0;