diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2016-08-16 16:35:06 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-08-16 16:35:05 -0700 |
commit | 13dc7954bfe3ffb1eb51e1496250dab730601c6d (patch) | |
tree | 6af2edd5d138e31980b281f000848b00336a5350 | |
parent | 4669827998890c911482969168bf8f22c25a3fcc (diff) | |
parent | 1efe85c3ea782037867b276d0763686eba6cf4d2 (diff) |
Merge "icnss: Vote aggre2_noc_clk through bus bandwidth framework"
-rw-r--r-- | drivers/soc/qcom/icnss.c | 92 |
1 files changed, 52 insertions, 40 deletions
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 16ca3eaee61b..bfe2072ee554 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -33,6 +33,7 @@ #include <linux/dma-mapping.h> #include <linux/qmi_encdec.h> #include <linux/ipc_logging.h> +#include <linux/msm-bus.h> #include <soc/qcom/memory_dump.h> #include <soc/qcom/icnss.h> #include <soc/qcom/msm_qmi_interface.h> @@ -43,7 +44,6 @@ #define ICNSS_PANIC 1 #define WLFW_TIMEOUT_MS 3000 #define WLFW_SERVICE_INS_ID_V01 0 -#define SMMU_CLOCK_NAME "smmu_aggre2_noc_clk" #define MAX_PROP_SIZE 32 #define MAX_VOLTAGE_LEVEL 2 #define VREG_ON 1 @@ -203,7 +203,8 @@ static struct icnss_data { size_t smmu_iova_len; dma_addr_t smmu_iova_ipa_start; size_t smmu_iova_ipa_len; - struct clk *smmu_clk; + struct msm_bus_scale_pdata *bus_scale_table; + uint32_t bus_client; struct qmi_handle *wlfw_clnt; struct list_head event_list; spinlock_t event_lock; @@ -1789,44 +1790,60 @@ int icnss_smmu_map(struct device *dev, } EXPORT_SYMBOL(icnss_smmu_map); -static struct clk *icnss_clock_init(struct device *dev, const char *cname) +static int icnss_bw_vote(struct icnss_data *priv, int index) { - struct clk *c; - long rate; - - if (of_property_match_string(dev->of_node, "clock-names", cname) < 0) { - icnss_pr_err("Clock %s not found!", cname); - return NULL; - } - - c = devm_clk_get(dev, cname); - if (IS_ERR(c)) { - icnss_pr_err("Couldn't get clock %s!", cname); - return NULL; - } + int ret = 0; - if (clk_get_rate(c) == 0) { - rate = clk_round_rate(c, 1000); - clk_set_rate(c, rate); - } + icnss_pr_dbg("Vote %d for msm_bus, state 0x%lx\n", + index, priv->state); + ret = msm_bus_scale_client_update_request(priv->bus_client, index); + if (ret) + icnss_pr_err("Fail to vote %d: ret %d, state 0x%lx!\n", + index, ret, priv->state); - return c; + return ret; } -static int icnss_clock_enable(struct clk *c) +static int icnss_bw_init(struct icnss_data *priv) { int ret = 0; - ret = clk_prepare_enable(c); + priv->bus_scale_table = msm_bus_cl_get_pdata(priv->pdev); + if (!priv->bus_scale_table) { + icnss_pr_err("Missing entry for msm_bus scale table\n"); + return -EINVAL; + } - if (ret < 0) - icnss_pr_err("Couldn't enable clock: %d!\n", ret); + priv->bus_client = msm_bus_scale_register_client(priv->bus_scale_table); + if (!priv->bus_client) { + icnss_pr_err("Fail to register with bus_scale client\n"); + ret = -EINVAL; + goto out; + } + + ret = icnss_bw_vote(priv, 1); + if (ret) + goto out; + + return 0; + +out: + msm_bus_cl_clear_pdata(priv->bus_scale_table); return ret; } -static void icnss_clock_disable(struct clk *c) +static void icnss_bw_deinit(struct icnss_data *priv) { - clk_disable_unprepare(c); + if (!priv) + return; + + if (priv->bus_client) { + icnss_bw_vote(priv, 0); + msm_bus_scale_unregister_client(priv->bus_client); + } + + if (priv->bus_scale_table) + msm_bus_cl_clear_pdata(priv->bus_scale_table); } static int icnss_smmu_init(struct device *dev) @@ -2460,12 +2477,9 @@ static int icnss_probe(struct platform_device *pdev) goto err_smmu_init; } - penv->smmu_clk = icnss_clock_init(&pdev->dev, SMMU_CLOCK_NAME); - if (penv->smmu_clk) { - ret = icnss_clock_enable(penv->smmu_clk); - if (ret < 0) - goto err_smmu_clock_enable; - } + ret = icnss_bw_init(penv); + if (ret) + goto err_bw_init; } penv->skip_qmi = of_property_read_bool(dev->of_node, @@ -2478,7 +2492,7 @@ static int icnss_probe(struct platform_device *pdev) if (!penv->event_wq) { icnss_pr_err("Workqueue creation failed\n"); ret = -EFAULT; - goto err_smmu_clock_enable; + goto err_alloc_workqueue; } INIT_WORK(&penv->event_work, icnss_driver_event_work); @@ -2503,7 +2517,9 @@ static int icnss_probe(struct platform_device *pdev) err_qmi: if (penv->event_wq) destroy_workqueue(penv->event_wq); -err_smmu_clock_enable: +err_alloc_workqueue: + icnss_bw_deinit(penv); +err_bw_init: if (penv->smmu_mapping) icnss_smmu_remove(&pdev->dev); err_smmu_init: @@ -2538,11 +2554,7 @@ static int icnss_remove(struct platform_device *pdev) if (penv->event_wq) destroy_workqueue(penv->event_wq); - if (penv->smmu_mapping) { - if (penv->smmu_clk) - icnss_clock_disable(penv->smmu_clk); - icnss_smmu_remove(&pdev->dev); - } + icnss_bw_deinit(penv); if (penv->msa_va) dma_free_coherent(&pdev->dev, penv->msa_mem_size, |