From f818cb90340f9cb7959950f66e8aa8ecaa31d6fa Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Mon, 20 Jul 2020 20:05:20 -0700 Subject: [PATCH] cnss2: Get Bus bandwidth voting table from DT Update cnss platform driver to use bus bandwidth voting data as configured in device tree file. Change-Id: I327c41613a6ca1d53550cf6d266db90b46f7bc77 Signed-off-by: Manikandan Mohan --- drivers/net/wireless/cnss2/main.c | 40 +++++++++++++++++++++++++++++-- drivers/net/wireless/cnss2/main.h | 2 ++ drivers/net/wireless/cnss2/pci.c | 37 +++++++++++++--------------- include/net/cnss2.h | 3 ++- 4 files changed, 58 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index f528e73b6538..a731d7f66892 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -1955,20 +1955,54 @@ int cnss_minidump_remove_region(struct cnss_plat_data *plat_priv, static int cnss_register_bus_scale(struct cnss_plat_data *plat_priv) { - int ret = 0; + int ret = 0, len = 0, i, j; struct cnss_bus_bw_info *bus_bw_info; + const u32 *cfg_arr; bus_bw_info = &plat_priv->bus_bw_info; bus_bw_info->cnss_path = of_icc_get(&plat_priv->plat_dev->dev, NULL); + + if (!bus_bw_info->cnss_path) { + cnss_pr_err("Skip Bus BW setup. Interconnect not configured\n"); + return 0; + } + if (IS_ERR(bus_bw_info->cnss_path)) { ret = PTR_ERR(bus_bw_info->cnss_path); if (ret != -EPROBE_DEFER) { - cnss_pr_err("Failed to get bus path: %d!\n", ret); + cnss_pr_err("Failed to get Interconnect path: %d!\n", + ret); goto out; } } + ret = of_property_read_u32(plat_priv->plat_dev->dev.of_node, + "qcom,bus-bw-cfg-num", + &bus_bw_info->num_cfg); + if (ret) { + cnss_pr_err("Failed to get Bus BW Config table size\n"); + goto out; + } + + cfg_arr = of_get_property(plat_priv->plat_dev->dev.of_node, + "qcom,bus-bw-cfg", &len); + if (!cfg_arr) { + cnss_pr_err("Bus BW Config Table not setup!\n"); + ret = -EINVAL; + goto out; + } + + bus_bw_info->cfg_table = kcalloc(bus_bw_info->num_cfg, + sizeof(*bus_bw_info->cfg_table), + GFP_KERNEL); + for (i = 0, j = 0; i < bus_bw_info->num_cfg; i++, j += 2) { + bus_bw_info->cfg_table[i].ab = be32_to_cpu(cfg_arr[j]); + bus_bw_info->cfg_table[i].ib = be32_to_cpu(cfg_arr[j + 1]); + cnss_pr_dbg("Bandwidth Type: %d bw_cfg.ab: %d bw_cfg.ib: %d\n", + i, bus_bw_info->cfg_table[i].ab, + bus_bw_info->cfg_table[i].ib); + } return 0; out: @@ -1983,6 +2017,8 @@ static void cnss_unregister_bus_scale(struct cnss_plat_data *plat_priv) if (bus_bw_info->cnss_path) icc_put(bus_bw_info->cnss_path); + + kfree(bus_bw_info->cfg_table); } static ssize_t shutdown_store(struct device *dev, diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index be90950b7cec..bf62b15c85ee 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -138,6 +138,8 @@ struct cnss_bus_bw_cfg { struct cnss_bus_bw_info { struct icc_path *cnss_path; int current_bw_vote; + u32 num_cfg; + struct cnss_bus_bw_cfg *cfg_table; }; struct cnss_fw_mem { diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index f7040432f9ce..f7a57568668a 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -357,21 +357,6 @@ static struct cnss_misc_reg wlaon_reg_access_seq[] = { {0, QCA6390_SYSPM_WCSSAON_SR_STATUS, 0}, }; -static struct cnss_bus_bw_cfg cnss_bus_bw_table[] = { - /* no vote */ - {0, 0}, - /* idle: 0-18 Mbps, ddr freq: 100 MHz */ - {2250, 400000}, - /* low: 18-60 Mbps, ddr freq: 200 MHz*/ - {7500, 800000}, - /* medium: 60-240 Mbps, ddr freq: 451.2 MHz */ - {30000, 1804800}, - /* high: 240 - 800 Mbps, ddr freq: 451.2 MHz */ - {100000, 1804800}, - /* very high: 800 - 1400 Mbps, ddr freq: 1555.2 MHz */ - {175000, 6220800}, -}; - #define WCSS_REG_SIZE ARRAY_SIZE(wcss_reg_access_seq) #define PCIE_REG_SIZE ARRAY_SIZE(pcie_reg_access_seq) #define WLAON_REG_SIZE ARRAY_SIZE(wlaon_reg_access_seq) @@ -531,7 +516,7 @@ int cnss_request_bus_bandwidth(struct device *dev, int bandwidth) return -ENODEV; bus_bw_info = &plat_priv->bus_bw_info; - if (!bus_bw_info->cnss_path) + if (!bus_bw_info->cnss_path || bandwidth > bus_bw_info->num_cfg) return -EINVAL; switch (bandwidth) { @@ -541,9 +526,10 @@ int cnss_request_bus_bandwidth(struct device *dev, int bandwidth) case CNSS_BUS_WIDTH_MEDIUM: case CNSS_BUS_WIDTH_HIGH: case CNSS_BUS_WIDTH_VERY_HIGH: + case CNSS_BUS_WIDTH_LOW_LATENCY: ret = icc_set_bw(bus_bw_info->cnss_path, - cnss_bus_bw_table[bandwidth].ab, - cnss_bus_bw_table[bandwidth].ib); + bus_bw_info->cfg_table[bandwidth].ab, + bus_bw_info->cfg_table[bandwidth].ib); if (!ret) bus_bw_info->current_bw_vote = bandwidth; else @@ -2957,6 +2943,7 @@ int cnss_auto_suspend(struct device *dev) struct pci_dev *pci_dev = to_pci_dev(dev); struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev); struct cnss_plat_data *plat_priv; + struct cnss_bus_bw_info *bus_bw_info; if (!pci_priv) return -ENODEV; @@ -2977,10 +2964,18 @@ int cnss_auto_suspend(struct device *dev) cnss_pci_set_monitor_wake_intr(pci_priv, true); - icc_set_bw(plat_priv->bus_bw_info.cnss_path, - cnss_bus_bw_table[CNSS_BUS_WIDTH_NONE].ab, - cnss_bus_bw_table[CNSS_BUS_WIDTH_NONE].ib); + bus_bw_info = &plat_priv->bus_bw_info; + if (!bus_bw_info->cnss_path) + goto out; + /* For suspend temporarily set bandwidth vote to NONE and dont save in + * current_bw_vote as in resume path we should vote for last used + * bandwidth vote. Also ignore error if bw voting is not setup. + */ + icc_set_bw(bus_bw_info->cnss_path, + bus_bw_info->cfg_table[CNSS_BUS_WIDTH_NONE].ab, + bus_bw_info->cfg_table[CNSS_BUS_WIDTH_NONE].ib); +out: return 0; } EXPORT_SYMBOL(cnss_auto_suspend); diff --git a/include/net/cnss2.h b/include/net/cnss2.h index ac786ced79ce..ecec0832af77 100644 --- a/include/net/cnss2.h +++ b/include/net/cnss2.h @@ -21,7 +21,8 @@ enum cnss_bus_width_type { CNSS_BUS_WIDTH_LOW, CNSS_BUS_WIDTH_MEDIUM, CNSS_BUS_WIDTH_HIGH, - CNSS_BUS_WIDTH_VERY_HIGH + CNSS_BUS_WIDTH_VERY_HIGH, + CNSS_BUS_WIDTH_LOW_LATENCY }; enum cnss_platform_cap_flag {