@@ -1631,8 +1631,16 @@ static const struct regmap_config cam_cc_sc7180_regmap_config = {
.fast_io = true,
};
+static const char * const cam_cc_sc7180_pm_clks[] = { "xo", "iface" };
+
+static const struct qcom_cc_pm cam_cc_sc7180_pm = {
+ .pm_clks = cam_cc_sc7180_pm_clks,
+ .num_pm_clks = ARRAY_SIZE(cam_cc_sc7180_pm_clks),
+};
+
static const struct qcom_cc_desc cam_cc_sc7180_desc = {
.config = &cam_cc_sc7180_regmap_config,
+ .pm = &cam_cc_sc7180_pm,
.clk_hws = cam_cc_sc7180_hws,
.num_clk_hws = ARRAY_SIZE(cam_cc_sc7180_hws),
.clks = cam_cc_sc7180_clocks,
@@ -1652,25 +1660,9 @@ static int cam_cc_sc7180_probe(struct platform_device *pdev)
struct regmap *regmap;
int ret;
- ret = devm_pm_runtime_enable(&pdev->dev);
- if (ret < 0)
- return ret;
-
- ret = devm_pm_clk_create(&pdev->dev);
- if (ret < 0)
- return ret;
-
- ret = pm_clk_add(&pdev->dev, "xo");
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to acquire XO clock\n");
- return ret;
- }
-
- ret = pm_clk_add(&pdev->dev, "iface");
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to acquire iface clock\n");
+ ret = qcom_cc_setup_pm(pdev, &cam_cc_sc7180_desc);
+ if (ret)
return ret;
- }
ret = pm_runtime_get(&pdev->dev);
if (ret)
@@ -7,6 +7,8 @@
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
#include <linux/clk-provider.h>
#include <linux/reset-controller.h>
#include <linux/of.h>
@@ -307,6 +309,8 @@ int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
{
struct regmap *regmap;
+ qcom_cc_setup_pm(pdev, desc);
+
regmap = qcom_cc_map(pdev, desc);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
@@ -320,6 +324,8 @@ int qcom_cc_probe_by_index(struct platform_device *pdev, int index,
{
struct regmap *regmap;
+ qcom_cc_setup_pm(pdev, desc);
+
regmap = qcom_cc_map_by_index(pdev, desc, index);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
@@ -328,4 +334,34 @@ int qcom_cc_probe_by_index(struct platform_device *pdev, int index,
}
EXPORT_SYMBOL_GPL(qcom_cc_probe_by_index);
+int qcom_cc_really_setup_pm(struct platform_device *pdev, const struct qcom_cc_pm *pm)
+{
+ int ret;
+ int i;
+
+ if (!pm)
+ return -EINVAL;
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ if (pm->num_pm_clks) {
+ ret = devm_pm_clk_create(&pdev->dev);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < pm->num_pm_clks; i++) {
+ ret = pm_clk_add(&pdev->dev, pm->pm_clks[i]);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to acquire %s pm clk\n", pm->pm_clks[i]);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_cc_really_setup_pm);
+
MODULE_LICENSE("GPL v2");
@@ -19,8 +19,15 @@ struct clk_hw;
#define PLL_VOTE_FSM_ENA BIT(20)
#define PLL_VOTE_FSM_RESET BIT(21)
+/* This can be used from within the qcom_cc_desc or separately */
+struct qcom_cc_pm {
+ const char *const *pm_clks;
+ size_t num_pm_clks;
+};
+
struct qcom_cc_desc {
const struct regmap_config *config;
+ const struct qcom_cc_pm *pm;
struct clk_regmap **clks;
size_t num_clks;
const struct qcom_reset_map *resets;
@@ -54,6 +61,16 @@ extern int qcom_cc_register_board_clk(struct device *dev, const char *path,
const char *name, unsigned long rate);
extern int qcom_cc_register_sleep_clk(struct device *dev);
+extern int qcom_cc_really_setup_pm(struct platform_device *pdev, const struct qcom_cc_pm *pm);
+
+static inline int qcom_cc_setup_pm(struct platform_device *pdev, const struct qcom_cc_desc *desc)
+{
+ if (!desc->pm)
+ return 0;
+
+ return qcom_cc_really_setup_pm(pdev, desc->pm);
+}
+
extern struct regmap *qcom_cc_map(struct platform_device *pdev,
const struct qcom_cc_desc *desc);
extern int qcom_cc_really_probe(struct platform_device *pdev,
@@ -338,8 +338,16 @@ static struct regmap_config lpass_core_cc_sc7180_regmap_config = {
.fast_io = true,
};
+static const char * const lpass_core_sc7180_pm_clks[] = { "iface" };
+
+static const struct qcom_cc_pm lpass_core_sc7180_pm = {
+ .pm_clks = lpass_core_sc7180_pm_clks,
+ .num_pm_clks = ARRAY_SIZE(lpass_core_sc7180_pm_clks),
+};
+
static const struct qcom_cc_desc lpass_core_hm_sc7180_desc = {
.config = &lpass_core_cc_sc7180_regmap_config,
+ .pm = &lpass_core_sc7180_pm,
.gdscs = lpass_core_hm_sc7180_gdscs,
.num_gdscs = ARRAY_SIZE(lpass_core_hm_sc7180_gdscs),
};
@@ -356,35 +364,16 @@ static const struct qcom_cc_desc lpass_audio_hm_sc7180_desc = {
.num_gdscs = ARRAY_SIZE(lpass_audio_hm_sc7180_gdscs),
};
-static int lpass_create_pm_clks(struct platform_device *pdev)
-{
- int ret;
-
- pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
-
- ret = devm_pm_runtime_enable(&pdev->dev);
- if (ret)
- return ret;
-
- ret = devm_pm_clk_create(&pdev->dev);
- if (ret)
- return ret;
-
- ret = pm_clk_add(&pdev->dev, "iface");
- if (ret < 0)
- dev_err(&pdev->dev, "failed to acquire iface clock\n");
-
- return ret;
-}
-
static int lpass_core_cc_sc7180_probe(struct platform_device *pdev)
{
const struct qcom_cc_desc *desc;
struct regmap *regmap;
int ret;
- ret = lpass_create_pm_clks(pdev);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
+
+ ret = qcom_cc_really_setup_pm(pdev, &lpass_core_sc7180_pm);
if (ret)
return ret;
@@ -423,11 +412,9 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev)
static int lpass_hm_core_probe(struct platform_device *pdev)
{
const struct qcom_cc_desc *desc;
- int ret;
- ret = lpass_create_pm_clks(pdev);
- if (ret)
- return ret;
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
lpass_core_cc_sc7180_regmap_config.name = "lpass_hm_core";
desc = &lpass_core_hm_sc7180_desc;
@@ -7,7 +7,6 @@
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/pm_clock.h>
-#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,mss-sc7180.h>
@@ -63,35 +62,23 @@ static struct clk_regmap *mss_sc7180_clocks[] = {
[MSS_AXI_NAV_CLK] = &mss_axi_nav_clk.clkr,
};
+static const char * const mss_sc7180_pm_clks[] = { "cfg_ahb" };
+
+static const struct qcom_cc_pm mss_sc7180_pm = {
+ .pm_clks = mss_sc7180_pm_clks,
+ .num_pm_clks = ARRAY_SIZE(mss_sc7180_pm_clks),
+};
+
static const struct qcom_cc_desc mss_sc7180_desc = {
.config = &mss_regmap_config,
+ .pm = &mss_sc7180_pm,
.clks = mss_sc7180_clocks,
.num_clks = ARRAY_SIZE(mss_sc7180_clocks),
};
static int mss_sc7180_probe(struct platform_device *pdev)
{
- int ret;
-
- ret = devm_pm_runtime_enable(&pdev->dev);
- if (ret)
- return ret;
-
- ret = devm_pm_clk_create(&pdev->dev);
- if (ret)
- return ret;
-
- ret = pm_clk_add(&pdev->dev, "cfg_ahb");
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to acquire iface clock\n");
- return ret;
- }
-
- ret = qcom_cc_probe(pdev, &mss_sc7180_desc);
- if (ret < 0)
- return ret;
-
- return 0;
+ return qcom_cc_probe(pdev, &mss_sc7180_desc);
}
static const struct dev_pm_ops mss_sc7180_pm_ops = {
@@ -8,7 +8,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_clock.h>
-#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,q6sstopcc-qcs404.h>
@@ -117,6 +116,13 @@ static struct regmap_config q6sstop_regmap_config = {
.fast_io = true,
};
+static const char * const q6sstop_qcs404_pm_clks[] = { NULL };
+
+static const struct qcom_cc_pm q6sstop_qcs404_pm = {
+ .pm_clks = q6sstop_qcs404_pm_clks,
+ .num_pm_clks = ARRAY_SIZE(q6sstop_qcs404_pm_clks),
+};
+
static struct clk_regmap *q6sstop_qcs404_clocks[] = {
[LCC_AHBFABRIC_CBC_CLK] = &lcc_ahbfabric_cbc_clk.clkr,
[LCC_Q6SS_AHBS_CBC_CLK] = &lcc_q6ss_ahbs_cbc_clk.clkr,
@@ -159,19 +165,7 @@ static int q6sstopcc_qcs404_probe(struct platform_device *pdev)
const struct qcom_cc_desc *desc;
int ret;
- ret = devm_pm_runtime_enable(&pdev->dev);
- if (ret)
- return ret;
-
- ret = devm_pm_clk_create(&pdev->dev);
- if (ret)
- return ret;
-
- ret = pm_clk_add(&pdev->dev, NULL);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to acquire iface clock\n");
- return ret;
- }
+ ret = qcom_cc_really_setup_pm(pdev, &q6sstop_qcs404_pm);
q6sstop_regmap_config.name = "q6sstop_tcsr";
desc = &tcsr_qcs404_desc;
@@ -9,7 +9,6 @@
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/pm_clock.h>
-#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,turingcc-qcs404.h>
@@ -100,35 +99,23 @@ static const struct regmap_config turingcc_regmap_config = {
.fast_io = true,
};
+static const char * const turingcc_pm_clks[] = { NULL };
+
+static const struct qcom_cc_pm turingcc_pm = {
+ .pm_clks = turingcc_pm_clks,
+ .num_pm_clks = ARRAY_SIZE(turingcc_pm_clks),
+};
+
static const struct qcom_cc_desc turingcc_desc = {
.config = &turingcc_regmap_config,
+ .pm = &turingcc_pm,
.clks = turingcc_clocks,
.num_clks = ARRAY_SIZE(turingcc_clocks),
};
static int turingcc_probe(struct platform_device *pdev)
{
- int ret;
-
- ret = devm_pm_runtime_enable(&pdev->dev);
- if (ret)
- return ret;
-
- ret = devm_pm_clk_create(&pdev->dev);
- if (ret)
- return ret;
-
- ret = pm_clk_add(&pdev->dev, NULL);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to acquire iface clock\n");
- return ret;
- }
-
- ret = qcom_cc_probe(pdev, &turingcc_desc);
- if (ret < 0)
- return ret;
-
- return 0;
+ return qcom_cc_probe(pdev, &turingcc_desc);
}
static const struct dev_pm_ops turingcc_pm_ops = {
Several Qualcomm clock controller drivers use pm_clk functionality. Instead of having common code in all the drivers, move the pm_clk handling to the qcom_cc_map/qcom_cc_probe. Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> --- drivers/clk/qcom/camcc-sc7180.c | 28 +++++++----------- drivers/clk/qcom/common.c | 36 +++++++++++++++++++++++ drivers/clk/qcom/common.h | 17 +++++++++++ drivers/clk/qcom/lpasscorecc-sc7180.c | 41 +++++++++------------------ drivers/clk/qcom/mss-sc7180.c | 31 ++++++-------------- drivers/clk/qcom/q6sstop-qcs404.c | 22 ++++++-------- drivers/clk/qcom/turingcc-qcs404.c | 31 ++++++-------------- 7 files changed, 103 insertions(+), 103 deletions(-)