diff options
Diffstat (limited to 'drivers/net')
| -rw-r--r-- | drivers/net/wireless/cnss/cnss_pci.c | 51 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/debug.c | 93 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/main.c | 21 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/pci.c | 32 | ||||
| -rw-r--r-- | drivers/net/wireless/wcnss/wcnss_vreg.c | 32 | ||||
| -rw-r--r-- | drivers/net/wireless/wcnss/wcnss_wlan.c | 154 |
6 files changed, 264 insertions, 119 deletions
diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c index 22c59d8c3c45..c9412ca6e794 100644 --- a/drivers/net/wireless/cnss/cnss_pci.c +++ b/drivers/net/wireless/cnss/cnss_pci.c @@ -134,7 +134,6 @@ static DEFINE_SPINLOCK(pci_link_down_lock); #define FW_IMAGE_MISSION (0x02) #define FW_IMAGE_BDATA (0x03) #define FW_IMAGE_PRINT (0x04) -#define FW_SETUP_DELAY 2000 #define SEG_METADATA (0x01) #define SEG_NON_PAGED (0x02) @@ -274,10 +273,8 @@ static struct cnss_data { u32 fw_dma_size; u32 fw_seg_count; struct segment_memory fw_seg_mem[MAX_NUM_OF_SEGMENTS]; - atomic_t fw_store_in_progress; /* Firmware setup complete lock */ struct mutex fw_setup_stat_lock; - struct completion fw_setup_complete; void *bdata_cpu; dma_addr_t bdata_dma; u32 bdata_dma_size; @@ -1374,15 +1371,6 @@ int cnss_get_fw_image(struct image_desc_info *image_desc_info) !penv->fw_seg_count || !penv->bdata_seg_count) return -EINVAL; - /* Check for firmware setup trigger by usersapce is in progress - * and wait for complition of firmware setup. - */ - - if (atomic_read(&penv->fw_store_in_progress)) { - wait_for_completion_timeout(&penv->fw_setup_complete, - msecs_to_jiffies(FW_SETUP_DELAY)); - } - mutex_lock(&penv->fw_setup_stat_lock); image_desc_info->fw_addr = penv->fw_dma; image_desc_info->fw_size = penv->fw_dma_size; @@ -1627,7 +1615,9 @@ static int cnss_wlan_pci_probe(struct pci_dev *pdev, goto err_pcie_suspend; } + mutex_lock(&penv->fw_setup_stat_lock); cnss_wlan_fw_mem_alloc(pdev); + mutex_unlock(&penv->fw_setup_stat_lock); ret = device_create_file(&penv->pldev->dev, &dev_attr_wlan_setup); @@ -1874,17 +1864,11 @@ static ssize_t fw_image_setup_store(struct device *dev, if (!penv) return -ENODEV; - if (atomic_read(&penv->fw_store_in_progress)) { - pr_info("%s: Firmware setup in progress\n", __func__); - return 0; - } - - atomic_set(&penv->fw_store_in_progress, 1); - init_completion(&penv->fw_setup_complete); + mutex_lock(&penv->fw_setup_stat_lock); + pr_info("%s: Firmware setup in progress\n", __func__); if (kstrtoint(buf, 0, &val)) { - atomic_set(&penv->fw_store_in_progress, 0); - complete(&penv->fw_setup_complete); + mutex_unlock(&penv->fw_setup_stat_lock); return -EINVAL; } @@ -1895,8 +1879,7 @@ static ssize_t fw_image_setup_store(struct device *dev, if (ret != 0) { pr_err("%s: Invalid parsing of FW image files %d", __func__, ret); - atomic_set(&penv->fw_store_in_progress, 0); - complete(&penv->fw_setup_complete); + mutex_unlock(&penv->fw_setup_stat_lock); return -EINVAL; } penv->fw_image_setup = val; @@ -1906,9 +1889,8 @@ static ssize_t fw_image_setup_store(struct device *dev, penv->bmi_test = val; } - atomic_set(&penv->fw_store_in_progress, 0); - complete(&penv->fw_setup_complete); - + pr_info("%s: Firmware setup completed\n", __func__); + mutex_unlock(&penv->fw_setup_stat_lock); return count; } @@ -2007,16 +1989,21 @@ int cnss_get_codeswap_struct(struct codeswap_codeseg_info *swap_seg) { struct codeswap_codeseg_info *cnss_seg_info = penv->cnss_seg_info; + mutex_lock(&penv->fw_setup_stat_lock); if (!cnss_seg_info) { swap_seg = NULL; + mutex_unlock(&penv->fw_setup_stat_lock); return -ENOENT; } + if (!atomic_read(&penv->fw_available)) { pr_debug("%s: fw is not available\n", __func__); + mutex_unlock(&penv->fw_setup_stat_lock); return -ENOENT; } *swap_seg = *cnss_seg_info; + mutex_unlock(&penv->fw_setup_stat_lock); return 0; } @@ -2035,15 +2022,6 @@ static void cnss_wlan_memory_expansion(void) u_int32_t total_length = 0; struct pci_dev *pdev; - /* Check for firmware setup trigger by usersapce is in progress - * and wait for complition of firmware setup. - */ - - if (atomic_read(&penv->fw_store_in_progress)) { - wait_for_completion_timeout(&penv->fw_setup_complete, - msecs_to_jiffies(FW_SETUP_DELAY)); - } - mutex_lock(&penv->fw_setup_stat_lock); filename = cnss_wlan_get_evicted_data_file(); pdev = penv->pdev; @@ -2859,6 +2837,7 @@ static int cnss_probe(struct platform_device *pdev) penv->vreg_info.wlan_reg = NULL; penv->vreg_info.state = VREG_OFF; penv->pci_register_again = false; + mutex_init(&penv->fw_setup_stat_lock); ret = cnss_wlan_get_resources(pdev); if (ret) @@ -3016,8 +2995,6 @@ skip_ramdump: memset(phys_to_virt(0), 0, SZ_4K); #endif - atomic_set(&penv->fw_store_in_progress, 0); - mutex_init(&penv->fw_setup_stat_lock); ret = device_create_file(dev, &dev_attr_fw_image_setup); if (ret) { pr_err("cnss: fw_image_setup sys file creation failed\n"); diff --git a/drivers/net/wireless/cnss2/debug.c b/drivers/net/wireless/cnss2/debug.c index 360ab31c61dd..c3bcb38f428f 100644 --- a/drivers/net/wireless/cnss2/debug.c +++ b/drivers/net/wireless/cnss2/debug.c @@ -15,6 +15,7 @@ #include <linux/debugfs.h> #include "main.h" #include "debug.h" +#include "pci.h" #define CNSS_IPC_LOG_PAGES 32 @@ -121,13 +122,90 @@ static int cnss_stats_open(struct inode *inode, struct file *file) } static const struct file_operations cnss_stats_fops = { - .read = seq_read, - .release = single_release, - .open = cnss_stats_open, - .owner = THIS_MODULE, - .llseek = seq_lseek, + .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; + char buf[64]; + char *cmd; + unsigned int len = 0; + int ret = 0; + + 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, "enumerate")) { + ret = cnss_pci_init(plat_priv); + } else if (sysfs_streq(cmd, "download")) { + ret = cnss_pci_start_mhi(plat_priv->bus_priv); + } 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, "enumerate: de-assert PERST, enumerate PCIe\n"); + seq_puts(s, "download: download FW and do QMI handshake with FW\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, +}; + +#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); + + 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; @@ -139,11 +217,16 @@ int cnss_debugfs_create(struct cnss_plat_data *plat_priv) 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; } diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index e114d0c51a07..8838a1319629 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -57,6 +57,7 @@ MODULE_PARM_DESC(enable_waltest, "Enable to handle firmware waltest"); enum cnss_debug_quirks { LINK_DOWN_SELF_RECOVERY, + SKIP_DEVICE_BOOT, }; unsigned long quirks; @@ -2232,13 +2233,15 @@ static int cnss_probe(struct platform_device *plat_dev) if (ret) goto reset_ctx; - ret = cnss_power_on_device(plat_priv); - if (ret) - goto free_res; + if (!test_bit(SKIP_DEVICE_BOOT, &quirks)) { + ret = cnss_power_on_device(plat_priv); + if (ret) + goto free_res; - ret = cnss_pci_init(plat_priv); - if (ret) - goto power_off; + ret = cnss_pci_init(plat_priv); + if (ret) + goto power_off; + } ret = cnss_register_esoc(plat_priv); if (ret) @@ -2291,9 +2294,11 @@ unreg_bus_scale: unreg_esoc: cnss_unregister_esoc(plat_priv); deinit_pci: - cnss_pci_deinit(plat_priv); + if (!test_bit(SKIP_DEVICE_BOOT, &quirks)) + cnss_pci_deinit(plat_priv); power_off: - cnss_power_off_device(plat_priv); + if (!test_bit(SKIP_DEVICE_BOOT, &quirks)) + cnss_power_off_device(plat_priv); free_res: cnss_put_resources(plat_priv); reset_ctx: diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index edc39af2d361..ce5a7b2bc88e 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -787,36 +787,6 @@ int cnss_pci_get_bar_info(struct cnss_pci_data *pci_priv, void __iomem **va, return 0; } -#ifdef CONFIG_CNSS_QCA6290 -#define PCI_MAX_BAR_SIZE 0xD00000 - -static void __iomem *cnss_pci_iomap(struct pci_dev *dev, int bar, - unsigned long maxlen) -{ - resource_size_t start = pci_resource_start(dev, bar); - resource_size_t len = PCI_MAX_BAR_SIZE; - unsigned long flags = pci_resource_flags(dev, bar); - - if (!len || !start) - return NULL; - - if ((flags & IORESOURCE_IO) || (flags & IORESOURCE_MEM)) { - if (flags & IORESOURCE_CACHEABLE && !(flags & IORESOURCE_IO)) - return ioremap(start, len); - else - return ioremap_nocache(start, len); - } - - return NULL; -} -#else -static void __iomem *cnss_pci_iomap(struct pci_dev *dev, int bar, - unsigned long maxlen) -{ - return pci_iomap(dev, bar, maxlen); -} -#endif - static struct cnss_msi_config msi_config = { .total_vectors = 32, .total_users = 4, @@ -1003,7 +973,7 @@ static int cnss_pci_enable_bus(struct cnss_pci_data *pci_priv) pci_set_master(pci_dev); - pci_priv->bar = cnss_pci_iomap(pci_dev, PCI_BAR_NUM, 0); + pci_priv->bar = pci_iomap(pci_dev, PCI_BAR_NUM, 0); if (!pci_priv->bar) { cnss_pr_err("Failed to do PCI IO map!\n"); ret = -EIO; diff --git a/drivers/net/wireless/wcnss/wcnss_vreg.c b/drivers/net/wireless/wcnss/wcnss_vreg.c index 82b90ad00f8b..d0a74744f70a 100644 --- a/drivers/net/wireless/wcnss/wcnss_vreg.c +++ b/drivers/net/wireless/wcnss/wcnss_vreg.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2015, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -417,13 +417,18 @@ static void wcnss_vregs_off(struct vregs_info regulators[], uint size, if (regulators[i].state == VREG_NULL_CONFIG) continue; + if (cfg->wcn_external_gpio_support) { + if (!memcmp(regulators[i].name, VDD_PA, sizeof(VDD_PA))) + continue; + } + /* Remove PWM mode */ if (regulators[i].state & VREG_OPTIMUM_MODE_MASK) { - rc = regulator_set_optimum_mode( - regulators[i].regulator, 0); - if (rc < 0) - pr_err("regulator_set_optimum_mode(%s) failed (%d)\n", - regulators[i].name, rc); + rc = regulator_set_load(regulators[i].regulator, 0); + if (rc < 0) { + pr_err("regulator set load(%s) failed (%d)\n", + regulators[i].name, rc); + } } /* Set voltage to lowest level */ @@ -478,7 +483,12 @@ static int wcnss_vregs_on(struct device *dev, } for (i = 0; i < size; i++) { - /* Get regulator source */ + if (cfg->wcn_external_gpio_support) { + if (!memcmp(regulators[i].name, VDD_PA, sizeof(VDD_PA))) + continue; + } + + /* Get regulator source */ regulators[i].regulator = regulator_get(dev, regulators[i].name); if (IS_ERR(regulators[i].regulator)) { @@ -518,11 +528,11 @@ static int wcnss_vregs_on(struct device *dev, /* Vote for PWM/PFM mode if needed */ if (voltage_level[i].uA_load && (reg_cnt > 0)) { - rc = regulator_set_optimum_mode(regulators[i].regulator, - voltage_level[i].uA_load); + rc = regulator_set_load(regulators[i].regulator, + voltage_level[i].uA_load); if (rc < 0) { - pr_err("regulator_set_optimum_mode(%s) failed (%d)\n", - regulators[i].name, rc); + pr_err("regulator set load(%s) failed (%d)\n", + regulators[i].name, rc); goto fail; } regulators[i].state |= VREG_OPTIMUM_MODE_MASK; diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c index 9347882fba92..e99d46ca51b0 100644 --- a/drivers/net/wireless/wcnss/wcnss_wlan.c +++ b/drivers/net/wireless/wcnss/wcnss_wlan.c @@ -36,6 +36,7 @@ #include <linux/qpnp/qpnp-adc.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_qos.h> +#include <linux/bitops.h> #include <soc/qcom/subsystem_restart.h> #include <soc/qcom/subsystem_notif.h> @@ -56,6 +57,7 @@ #define WCNSS_PM_QOS_TIMEOUT 15000 #define IS_CAL_DATA_PRESENT 0 #define WAIT_FOR_CBC_IND 2 +#define WCNSS_DUAL_BAND_CAPABILITY_OFFSET BIT(8) /* module params */ #define WCNSS_CONFIG_UNSPECIFIED (-1) @@ -119,6 +121,8 @@ static DEFINE_SPINLOCK(reg_spinlock); #define PRONTO_PMU_COM_CSR_OFFSET 0x1040 #define PRONTO_PMU_SOFT_RESET_OFFSET 0x104C +#define PRONTO_QFUSE_DUAL_BAND_OFFSET 0x0018 + #define A2XB_CFG_OFFSET 0x00 #define A2XB_INT_SRC_OFFSET 0x0c #define A2XB_TSTBUS_CTRL_OFFSET 0x14 @@ -381,6 +385,7 @@ static struct { void __iomem *pronto_saw2_base; void __iomem *pronto_pll_base; void __iomem *pronto_mcu_base; + void __iomem *pronto_qfuse; void __iomem *wlan_tx_status; void __iomem *wlan_tx_phy_aborts; void __iomem *wlan_brdg_err_source; @@ -423,6 +428,9 @@ static struct { int pc_disabled; struct delayed_work wcnss_pm_qos_del_req; struct mutex pm_qos_mutex; + struct clk *snoc_wcnss; + unsigned int snoc_wcnss_clock_freq; + bool is_dual_band_disabled; } *penv = NULL; static ssize_t wcnss_wlan_macaddr_store(struct device *dev, @@ -595,7 +603,31 @@ void wcnss_pronto_is_a2xb_bus_stall(void *tst_addr, u32 fifo_mask, char *type) } } -/* Log pronto debug registers before sending reset interrupt */ +int wcnss_get_dual_band_capability_info(struct platform_device *pdev) +{ + u32 reg = 0; + struct resource *res; + + res = platform_get_resource_byname( + pdev, IORESOURCE_MEM, "pronto_qfuse"); + if (!res) + return -EINVAL; + + penv->pronto_qfuse = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(penv->pronto_qfuse)) + return -ENOMEM; + + reg = readl_relaxed(penv->pronto_qfuse + + PRONTO_QFUSE_DUAL_BAND_OFFSET); + if (reg & WCNSS_DUAL_BAND_CAPABILITY_OFFSET) + penv->is_dual_band_disabled = true; + else + penv->is_dual_band_disabled = false; + + return 0; +} + +/* Log pronto debug registers during SSR Timeout CB */ void wcnss_pronto_log_debug_regs(void) { void __iomem *reg_addr, *tst_addr, *tst_ctrl_addr; @@ -1683,6 +1715,14 @@ int wcnss_wlan_iris_xo_mode(void) } EXPORT_SYMBOL(wcnss_wlan_iris_xo_mode); +int wcnss_wlan_dual_band_disabled(void) +{ + if (penv && penv->pdev) + return penv->is_dual_band_disabled; + + return -EINVAL; +} +EXPORT_SYMBOL(wcnss_wlan_dual_band_disabled); void wcnss_suspend_notify(void) { @@ -2717,23 +2757,23 @@ wcnss_trigger_config(struct platform_device *pdev) int is_pronto_vadc; int is_pronto_v3; int pil_retry = 0; - int has_pronto_hw = of_property_read_bool(pdev->dev.of_node, - "qcom,has-pronto-hw"); - - is_pronto_vadc = of_property_read_bool(pdev->dev.of_node, - "qcom,is-pronto-vadc"); + struct wcnss_wlan_config *wlan_cfg = &penv->wlan_config; + struct device_node *node = (&pdev->dev)->of_node; + int has_pronto_hw = of_property_read_bool(node, "qcom,has-pronto-hw"); - is_pronto_v3 = of_property_read_bool(pdev->dev.of_node, - "qcom,is-pronto-v3"); + is_pronto_vadc = of_property_read_bool(node, "qcom,is-pronto-vadc"); + is_pronto_v3 = of_property_read_bool(node, "qcom,is-pronto-v3"); - penv->is_vsys_adc_channel = of_property_read_bool(pdev->dev.of_node, - "qcom,has-vsys-adc-channel"); + penv->is_vsys_adc_channel = + of_property_read_bool(node, "qcom,has-vsys-adc-channel"); + penv->is_a2xb_split_reg = + of_property_read_bool(node, "qcom,has-a2xb-split-reg"); - penv->is_a2xb_split_reg = of_property_read_bool(pdev->dev.of_node, - "qcom,has-a2xb-split-reg"); + wlan_cfg->wcn_external_gpio_support = + of_property_read_bool(node, "qcom,wcn-external-gpio-support"); - if (of_property_read_u32(pdev->dev.of_node, - "qcom,wlan-rx-buff-count", &penv->wlan_rx_buff_count)) { + if (of_property_read_u32(node, "qcom,wlan-rx-buff-count", + &penv->wlan_rx_buff_count)) { penv->wlan_rx_buff_count = WCNSS_DEF_WLAN_RX_BUFF_COUNT; } @@ -2794,15 +2834,18 @@ wcnss_trigger_config(struct platform_device *pdev) goto fail; } - index++; - ret = wcnss_dt_parse_vreg_level(&pdev->dev, index, - "qcom,iris-vddpa-current", - "qcom,iris-vddpa-voltage-level", - penv->wlan_config.iris_vlevel); - - if (ret) { - dev_err(&pdev->dev, "error reading voltage-level property\n"); - goto fail; + if (!wlan_cfg->wcn_external_gpio_support) { + index++; + ret = wcnss_dt_parse_vreg_level( + &pdev->dev, index, + "qcom,iris-vddpa-current", + "qcom,iris-vddpa-voltage-level", + penv->wlan_config.iris_vlevel); + if (ret) { + dev_err(&pdev->dev, + "error reading voltage-level property\n"); + goto fail; + } } index++; @@ -2825,8 +2868,8 @@ wcnss_trigger_config(struct platform_device *pdev) pdata = pdev->dev.platform_data; if (WCNSS_CONFIG_UNSPECIFIED == has_48mhz_xo) { if (has_pronto_hw) { - has_48mhz_xo = of_property_read_bool(pdev->dev.of_node, - "qcom,has-48mhz-xo"); + has_48mhz_xo = + of_property_read_bool(node, "qcom,has-48mhz-xo"); } else { has_48mhz_xo = pdata->has_48mhz_xo; } @@ -2837,8 +2880,8 @@ wcnss_trigger_config(struct platform_device *pdev) penv->wlan_config.is_pronto_v3 = is_pronto_v3; if (WCNSS_CONFIG_UNSPECIFIED == has_autodetect_xo && has_pronto_hw) { - has_autodetect_xo = of_property_read_bool(pdev->dev.of_node, - "qcom,has-autodetect-xo"); + has_autodetect_xo = + of_property_read_bool(node, "qcom,has-autodetect-xo"); } penv->thermal_mitigation = 0; @@ -3118,6 +3161,16 @@ wcnss_trigger_config(struct platform_device *pdev) __func__); goto fail_ioremap2; } + + if (of_property_read_bool(node, + "qcom,is-dual-band-disabled")) { + ret = wcnss_get_dual_band_capability_info(pdev); + if (ret) { + pr_err( + "%s: failed to get dual band info\n", __func__); + goto fail_ioremap2; + } + } } penv->adc_tm_dev = qpnp_get_adc_tm(&penv->pdev->dev, "wcnss"); @@ -3129,6 +3182,21 @@ wcnss_trigger_config(struct platform_device *pdev) penv->fw_vbatt_state = WCNSS_CONFIG_UNSPECIFIED; } + penv->snoc_wcnss = devm_clk_get(&penv->pdev->dev, "snoc_wcnss"); + if (IS_ERR(penv->snoc_wcnss)) { + pr_err("%s: couldn't get snoc_wcnss\n", __func__); + penv->snoc_wcnss = NULL; + } else { + if (of_property_read_u32(pdev->dev.of_node, + "qcom,snoc-wcnss-clock-freq", + &penv->snoc_wcnss_clock_freq)) { + pr_debug("%s: wcnss snoc clock frequency is not defined\n", + __func__); + devm_clk_put(&penv->pdev->dev, penv->snoc_wcnss); + penv->snoc_wcnss = NULL; + } + } + if (penv->wlan_config.is_pronto_vadc) { penv->vadc_dev = qpnp_get_vadc(&penv->pdev->dev, "wcnss"); @@ -3191,6 +3259,38 @@ fail: return ret; } +/* Driver requires to directly vote the snoc clocks + * To enable and disable snoc clock, it call + * wcnss_snoc_vote function + */ +void wcnss_snoc_vote(bool clk_chk_en) +{ + int rc; + + if (!penv->snoc_wcnss) { + pr_err("%s: couldn't get clk snoc_wcnss\n", __func__); + return; + } + + if (clk_chk_en) { + rc = clk_set_rate(penv->snoc_wcnss, + penv->snoc_wcnss_clock_freq); + if (rc) { + pr_err("%s: snoc_wcnss_clk-clk_set_rate failed =%d\n", + __func__, rc); + return; + } + + if (clk_prepare_enable(penv->snoc_wcnss)) { + pr_err("%s: snoc_wcnss clk enable failed\n", __func__); + return; + } + } else { + clk_disable_unprepare(penv->snoc_wcnss); + } +} +EXPORT_SYMBOL(wcnss_snoc_vote); + /* wlan prop driver cannot invoke cancel_work_sync * function directly, so to invoke this function it * call wcnss_flush_work function |
