diff options
author | Srinivas Kandagatla <srinivas.kandagatla@linaro.org> | 2017-05-04 12:24:51 +0200 |
---|---|---|
committer | Srinivas Kandagatla <srinivas.kandagatla@linaro.org> | 2017-05-04 12:24:51 +0200 |
commit | a7b149f2b1c10d3ca628bf753dbad6047a66ced3 (patch) | |
tree | e881ebbb607eb5a31ac6bfa161f34bba52fdca82 | |
parent | 29c0b2b5091c702d91e5caeabd40c3261a6e7b86 (diff) | |
parent | a9bdcf3f954b92aab6f0068b8f5b0f8c15b713fb (diff) |
Merge branch 'tracking-qcomlt-gdsc' into integration-linux-qcomlt
-rw-r--r-- | arch/arm64/Kconfig.platforms | 2 | ||||
-rw-r--r-- | drivers/clk/clk.c | 7 | ||||
-rw-r--r-- | drivers/clk/qcom/common.c | 6 | ||||
-rw-r--r-- | drivers/clk/qcom/common.h | 2 | ||||
-rw-r--r-- | drivers/clk/qcom/gcc-msm8996.c | 7 | ||||
-rw-r--r-- | drivers/clk/qcom/gdsc.c | 45 | ||||
-rw-r--r-- | drivers/clk/qcom/gdsc.h | 8 | ||||
-rw-r--r-- | drivers/clk/qcom/mmcc-msm8996.c | 21 | ||||
-rw-r--r-- | include/linux/clk-provider.h | 2 |
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); |