aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2017-05-04 12:24:51 +0200
committerSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2017-05-04 12:24:51 +0200
commita7b149f2b1c10d3ca628bf753dbad6047a66ced3 (patch)
treee881ebbb607eb5a31ac6bfa161f34bba52fdca82
parent29c0b2b5091c702d91e5caeabd40c3261a6e7b86 (diff)
parenta9bdcf3f954b92aab6f0068b8f5b0f8c15b713fb (diff)
Merge branch 'tracking-qcomlt-gdsc' into integration-linux-qcomlt
-rw-r--r--arch/arm64/Kconfig.platforms2
-rw-r--r--drivers/clk/clk.c7
-rw-r--r--drivers/clk/qcom/common.c6
-rw-r--r--drivers/clk/qcom/common.h2
-rw-r--r--drivers/clk/qcom/gcc-msm8996.c7
-rw-r--r--drivers/clk/qcom/gdsc.c45
-rw-r--r--drivers/clk/qcom/gdsc.h8
-rw-r--r--drivers/clk/qcom/mmcc-msm8996.c21
-rw-r--r--include/linux/clk-provider.h2
9 files changed, 100 insertions, 0 deletions
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 129cc5ae40914..c5ae2cf921845 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -115,6 +115,8 @@ config ARCH_QCOM
bool "Qualcomm Platforms"
select GPIOLIB
select PINCTRL
+ select PM
+ select PM_GENERIC_DOMAINS
help
This enables support for the ARMv8 based Qualcomm chipsets.
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 67201f67a14af..1a2032b142e8e 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -186,6 +186,13 @@ const char *clk_hw_get_name(const struct clk_hw *hw)
}
EXPORT_SYMBOL_GPL(clk_hw_get_name);
+struct clk *clk_hw_get_clk(const struct clk_hw *hw, const char *dev_id,
+ const char *con_id)
+{
+ return __clk_create_clk(hw, dev_id, con_id);
+}
+EXPORT_SYMBOL_GPL(clk_hw_get_clk);
+
struct clk_hw *__clk_get_hw(struct clk *clk)
{
return !clk ? NULL : clk->core->hw;
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index 03f9d316f9691..17b713a588c3a 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -74,6 +74,12 @@ int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src)
}
EXPORT_SYMBOL_GPL(qcom_find_src_index);
+struct clk *qcom_clk_hw_get_clk(struct clk_hw *hw, const char *dev_id,
+ const char *con_id)
+{
+ return clk_hw_get_clk(hw, dev_id, con_id);
+}
+
struct regmap *
qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
{
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index 23c1927669bac..cb8306d205d33 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -59,5 +59,7 @@ extern int qcom_cc_really_probe(struct platform_device *pdev,
struct regmap *regmap);
extern int qcom_cc_probe(struct platform_device *pdev,
const struct qcom_cc_desc *desc);
+extern struct clk *qcom_clk_hw_get_clk(struct clk_hw *, const char *,
+ const char *);
#endif
diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c
index ad0cde904442d..5db3e8301fd01 100644
--- a/drivers/clk/qcom/gcc-msm8996.c
+++ b/drivers/clk/qcom/gcc-msm8996.c
@@ -3098,6 +3098,13 @@ static struct gdsc aggre0_noc_gdsc = {
.pd = {
.name = "aggre0_noc",
},
+ .clk_hws = {
+ &gcc_aggre0_snoc_axi_clk.clkr.hw,
+ &gcc_aggre0_cnoc_ahb_clk.clkr.hw,
+ &gcc_smmu_aggre0_axi_clk.clkr.hw,
+ &gcc_smmu_aggre0_ahb_clk.clkr.hw,
+ },
+ .clk_count = 4,
.pwrsts = PWRSTS_OFF_ON,
.flags = VOTABLE,
};
diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c
index a4f3580587b7e..5d4366b1e820d 100644
--- a/drivers/clk/qcom/gdsc.c
+++ b/drivers/clk/qcom/gdsc.c
@@ -12,15 +12,18 @@
*/
#include <linux/bitops.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/ktime.h>
+#include <linux/pm_clock.h>
#include <linux/pm_domain.h>
#include <linux/regmap.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
+#include "common.h"
#include "gdsc.h"
#define PWR_ON_MASK BIT(31)
@@ -254,6 +257,45 @@ static int gdsc_disable(struct generic_pm_domain *domain)
return 0;
}
+static int gdsc_attach(struct generic_pm_domain *domain, struct device *dev)
+{
+ int ret, i;
+ struct gdsc *sc = domain_to_gdsc(domain);
+
+ if (!sc->clk_count)
+ return 0;
+
+ ret = pm_clk_create(dev);
+ if (ret) {
+ dev_dbg(dev, "pm_clk_create failed %d\n", ret);
+ return ret;
+ }
+
+ sc->clks = devm_kcalloc(dev, sc->clk_count, sizeof(sc->clks),
+ GFP_KERNEL);
+ if (!sc->clks)
+ return -ENOMEM;
+
+ for (i = 0; i < sc->clk_count; i++) {
+ sc->clks[i] = qcom_clk_hw_get_clk(sc->clk_hws[i], domain->name,
+ NULL);
+ ret = pm_clk_add_clk(dev, sc->clks[i]);
+ if (ret)
+ dev_dbg(dev, "pm_clk_add_clk failed %d\n", ret);
+ }
+ return 0;
+};
+
+static void gdsc_detach(struct generic_pm_domain *domain, struct device *dev)
+{
+ struct gdsc *sc = domain_to_gdsc(domain);
+
+ if (!sc->clk_count)
+ return;
+
+ pm_clk_destroy(dev);
+};
+
static int gdsc_init(struct gdsc *sc)
{
u32 mask, val;
@@ -298,6 +340,9 @@ static int gdsc_init(struct gdsc *sc)
sc->pd.power_off = gdsc_disable;
sc->pd.power_on = gdsc_enable;
+ sc->pd.attach_dev = gdsc_attach;
+ sc->pd.detach_dev = gdsc_detach;
+ sc->pd.flags = GENPD_FLAG_PM_CLK;
pm_genpd_init(&sc->pd, NULL, !on);
return 0;
diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h
index 39648348e5ec9..a7fd51b6653ff 100644
--- a/drivers/clk/qcom/gdsc.h
+++ b/drivers/clk/qcom/gdsc.h
@@ -17,6 +17,8 @@
#include <linux/err.h>
#include <linux/pm_domain.h>
+struct clk;
+struct clk_hw;
struct regmap;
struct reset_controller_dev;
@@ -32,6 +34,9 @@ struct reset_controller_dev;
* @resets: ids of resets associated with this gdsc
* @reset_count: number of @resets
* @rcdev: reset controller
+ * @clk_count: number of gdsc clocks
+ * @clks: clk pointers for gdsc clocks
+ * @clk_hws: clk_hw pointers for gdsc clocks
*/
struct gdsc {
struct generic_pm_domain pd;
@@ -56,6 +61,9 @@ struct gdsc {
struct reset_controller_dev *rcdev;
unsigned int *resets;
unsigned int reset_count;
+ unsigned int clk_count;
+ struct clk **clks;
+ struct clk_hw *clk_hws[];
};
struct gdsc_desc {
diff --git a/drivers/clk/qcom/mmcc-msm8996.c b/drivers/clk/qcom/mmcc-msm8996.c
index 9b97246287a73..f978ddc61059d 100644
--- a/drivers/clk/qcom/mmcc-msm8996.c
+++ b/drivers/clk/qcom/mmcc-msm8996.c
@@ -2893,6 +2893,9 @@ static struct gdsc mmagic_bimc_gdsc = {
.pd = {
.name = "mmagic_bimc",
},
+ .clk_hws = {
+ &mmagic_bimc_noc_cfg_ahb_clk.clkr.hw,
+ },
.pwrsts = PWRSTS_OFF_ON,
};
@@ -2902,6 +2905,11 @@ static struct gdsc mmagic_video_gdsc = {
.pd = {
.name = "mmagic_video",
},
+ .clk_hws = {
+ &mmagic_video_axi_clk.clkr.hw,
+ &mmagic_video_noc_cfg_ahb_clk.clkr.hw,
+ },
+ .parent = &mmagic_bimc_gdsc.pd,
.pwrsts = PWRSTS_OFF_ON,
.flags = VOTABLE,
};
@@ -2912,6 +2920,14 @@ static struct gdsc mmagic_mdss_gdsc = {
.pd = {
.name = "mmagic_mdss",
},
+ .clk_hws = {
+ &mmss_mmagic_ahb_clk.clkr.hw,
+ &mmss_mmagic_cfg_ahb_clk.clkr.hw,
+ &mmss_mmagic_maxi_clk.clkr.hw,
+ &mmagic_mdss_axi_clk.clkr.hw,
+ &mmagic_mdss_noc_cfg_ahb_clk.clkr.hw,
+ },
+ .parent = &mmagic_bimc_gdsc.pd,
.pwrsts = PWRSTS_OFF_ON,
.flags = VOTABLE,
};
@@ -2922,6 +2938,11 @@ static struct gdsc mmagic_camss_gdsc = {
.pd = {
.name = "mmagic_camss",
},
+ .clk_hws = {
+ &mmagic_camss_axi_clk.clkr.hw,
+ &mmagic_camss_noc_cfg_ahb_clk.clkr.hw,
+ },
+ .parent = &mmagic_bimc_gdsc.pd,
.pwrsts = PWRSTS_OFF_ON,
.flags = VOTABLE,
};
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index a428aec36acee..863f331b46014 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -729,6 +729,8 @@ void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw);
/* helper functions */
const char *__clk_get_name(const struct clk *clk);
const char *clk_hw_get_name(const struct clk_hw *hw);
+struct clk *clk_hw_get_clk(const struct clk_hw *hw, const char *dev_id,
+ const char *con_id);
struct clk_hw *__clk_get_hw(struct clk *clk);
unsigned int clk_hw_get_num_parents(const struct clk_hw *hw);
struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw);