]> git.karo-electronics.de Git - linux-beck.git/commitdiff
ath10k: add clock ctrl related functions in ahb
authorRaja Mani <rmani@qti.qualcomm.com>
Wed, 27 Jan 2016 09:54:28 +0000 (15:24 +0530)
committerKalle Valo <kvalo@qca.qualcomm.com>
Thu, 28 Jan 2016 08:47:23 +0000 (10:47 +0200)
pre qca4019 chipsets has/uses internal clock generator for
the operation. But, qca4019 uses external clocks supplied from
outside of target (ie, outside of wifi core). Three different clocks
(cmd clock, ref clock, rtc clock) comes into picture in qca4019.
All those clocks needs to configured with help of global clock
controller (gcc) to make qca4019 functioning.

Add functions for clock init/deinit, clock enable/disable in ahb.
This is just a preparation, functions added in this patch will be
used in later patches.

Signed-off-by: Raja Mani <rmani@qti.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/ahb.c
drivers/net/wireless/ath/ath10k/ahb.h

index eab4b47237e0ecb2239f6fcd30d5c43f4c1632ce..11185c0dc6ad3c52d3827043f4fd12a6a21b698d 100644 (file)
@@ -15,6 +15,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 #include <linux/module.h>
+#include <linux/clk.h>
 #include "core.h"
 #include "debug.h"
 #include "pci.h"
@@ -84,6 +85,128 @@ static int ath10k_ahb_get_num_banks(struct ath10k *ar)
        return 1;
 }
 
+static int ath10k_ahb_clock_init(struct ath10k *ar)
+{
+       struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
+       struct device *dev;
+       int ret;
+
+       dev = &ar_ahb->pdev->dev;
+
+       ar_ahb->cmd_clk = clk_get(dev, "wifi_wcss_cmd");
+       if (IS_ERR_OR_NULL(ar_ahb->cmd_clk)) {
+               ath10k_err(ar, "failed to get cmd clk: %ld\n",
+                          PTR_ERR(ar_ahb->cmd_clk));
+               ret = ar_ahb->cmd_clk ? PTR_ERR(ar_ahb->cmd_clk) : -ENODEV;
+               goto out;
+       }
+
+       ar_ahb->ref_clk = clk_get(dev, "wifi_wcss_ref");
+       if (IS_ERR_OR_NULL(ar_ahb->ref_clk)) {
+               ath10k_err(ar, "failed to get ref clk: %ld\n",
+                          PTR_ERR(ar_ahb->ref_clk));
+               ret = ar_ahb->ref_clk ? PTR_ERR(ar_ahb->ref_clk) : -ENODEV;
+               goto err_cmd_clk_put;
+       }
+
+       ar_ahb->rtc_clk = clk_get(dev, "wifi_wcss_rtc");
+       if (IS_ERR_OR_NULL(ar_ahb->rtc_clk)) {
+               ath10k_err(ar, "failed to get rtc clk: %ld\n",
+                          PTR_ERR(ar_ahb->rtc_clk));
+               ret = ar_ahb->rtc_clk ? PTR_ERR(ar_ahb->rtc_clk) : -ENODEV;
+               goto err_ref_clk_put;
+       }
+
+       return 0;
+
+err_ref_clk_put:
+       clk_put(ar_ahb->ref_clk);
+
+err_cmd_clk_put:
+       clk_put(ar_ahb->cmd_clk);
+
+out:
+       return ret;
+}
+
+static void ath10k_ahb_clock_deinit(struct ath10k *ar)
+{
+       struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
+
+       if (!IS_ERR_OR_NULL(ar_ahb->cmd_clk))
+               clk_put(ar_ahb->cmd_clk);
+
+       if (!IS_ERR_OR_NULL(ar_ahb->ref_clk))
+               clk_put(ar_ahb->ref_clk);
+
+       if (!IS_ERR_OR_NULL(ar_ahb->rtc_clk))
+               clk_put(ar_ahb->rtc_clk);
+
+       ar_ahb->cmd_clk = NULL;
+       ar_ahb->ref_clk = NULL;
+       ar_ahb->rtc_clk = NULL;
+}
+
+static int ath10k_ahb_clock_enable(struct ath10k *ar)
+{
+       struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
+       struct device *dev;
+       int ret;
+
+       dev = &ar_ahb->pdev->dev;
+
+       if (IS_ERR_OR_NULL(ar_ahb->cmd_clk) ||
+           IS_ERR_OR_NULL(ar_ahb->ref_clk) ||
+           IS_ERR_OR_NULL(ar_ahb->rtc_clk)) {
+               ath10k_err(ar, "clock(s) is/are not initialized\n");
+               ret = -EIO;
+               goto out;
+       }
+
+       ret = clk_prepare_enable(ar_ahb->cmd_clk);
+       if (ret) {
+               ath10k_err(ar, "failed to enable cmd clk: %d\n", ret);
+               goto out;
+       }
+
+       ret = clk_prepare_enable(ar_ahb->ref_clk);
+       if (ret) {
+               ath10k_err(ar, "failed to enable ref clk: %d\n", ret);
+               goto err_cmd_clk_disable;
+       }
+
+       ret = clk_prepare_enable(ar_ahb->rtc_clk);
+       if (ret) {
+               ath10k_err(ar, "failed to enable rtc clk: %d\n", ret);
+               goto err_ref_clk_disable;
+       }
+
+       return 0;
+
+err_ref_clk_disable:
+       clk_disable_unprepare(ar_ahb->ref_clk);
+
+err_cmd_clk_disable:
+       clk_disable_unprepare(ar_ahb->cmd_clk);
+
+out:
+       return ret;
+}
+
+static void ath10k_ahb_clock_disable(struct ath10k *ar)
+{
+       struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar);
+
+       if (!IS_ERR_OR_NULL(ar_ahb->cmd_clk))
+               clk_disable_unprepare(ar_ahb->cmd_clk);
+
+       if (!IS_ERR_OR_NULL(ar_ahb->ref_clk))
+               clk_disable_unprepare(ar_ahb->ref_clk);
+
+       if (!IS_ERR_OR_NULL(ar_ahb->rtc_clk))
+               clk_disable_unprepare(ar_ahb->rtc_clk);
+}
+
 static int ath10k_ahb_probe(struct platform_device *pdev)
 {
        return 0;
index 77d15af59c4ab5a6192da91657c348853ae56cd5..753b4330075aa4266a2294f30e5b3daf01797d1d 100644 (file)
@@ -25,6 +25,10 @@ struct ath10k_ahb {
        void __iomem *mem;
        void __iomem *gcc_mem;
        void __iomem *tcsr_mem;
+
+       struct clk *cmd_clk;
+       struct clk *ref_clk;
+       struct clk *rtc_clk;
 };
 
 #ifdef CONFIG_ATH10K_AHB