From 5004b2140509bc6f874a72990267f00cf4fef5df Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Tue, 28 Jul 2020 19:14:13 -0700 Subject: [PATCH] clk: qcom: lahaina: Add runtime_pm support Add runtime_pm support for clock providers which have register access requirements that aren't always satisfied. Stop registers clocks previously flagged as CLK_IS_CRITICAL, since doing so means the device is always active and suspend is never called. Instead, just enable these clocks by default in HW during probe. Change-Id: I34cf74080745b627b3978fafd9eb8bbde4bb655e Signed-off-by: Mike Tipton --- drivers/clk/qcom/camcc-lahaina.c | 51 +++++++++------------ drivers/clk/qcom/dispcc-lahaina.c | 49 +++++++++----------- drivers/clk/qcom/videocc-lahaina.c | 72 ++++++++++-------------------- 3 files changed, 66 insertions(+), 106 deletions(-) diff --git a/drivers/clk/qcom/camcc-lahaina.c b/drivers/clk/qcom/camcc-lahaina.c index d5ed88ad6ae2..74bfce7e3ebd 100644 --- a/drivers/clk/qcom/camcc-lahaina.c +++ b/drivers/clk/qcom/camcc-lahaina.c @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -1931,24 +1932,6 @@ static struct clk_branch cam_cc_csiphy5_clk = { }, }; -static struct clk_branch cam_cc_gdsc_clk = { - .halt_reg = 0xc148, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0xc148, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "cam_cc_gdsc_clk", - .parent_data = &(const struct clk_parent_data){ - .hw = &cam_cc_xo_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch cam_cc_icp_ahb_clk = { .halt_reg = 0xc094, .halt_check = BRANCH_HALT, @@ -2866,7 +2849,6 @@ static struct clk_regmap *cam_cc_lahaina_clocks[] = { [CAM_CC_CSIPHY4_CLK] = &cam_cc_csiphy4_clk.clkr, [CAM_CC_CSIPHY5_CLK] = &cam_cc_csiphy5_clk.clkr, [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr, - [CAM_CC_GDSC_CLK] = &cam_cc_gdsc_clk.clkr, [CAM_CC_ICP_AHB_CLK] = &cam_cc_icp_ahb_clk.clkr, [CAM_CC_ICP_CLK] = &cam_cc_icp_clk.clkr, [CAM_CC_ICP_CLK_SRC] = &cam_cc_icp_clk_src.clkr, @@ -2972,7 +2954,7 @@ static const struct regmap_config cam_cc_lahaina_regmap_config = { .fast_io = true, }; -static const struct qcom_cc_desc cam_cc_lahaina_desc = { +static struct qcom_cc_desc cam_cc_lahaina_desc = { .config = &cam_cc_lahaina_regmap_config, .clks = cam_cc_lahaina_clocks, .num_clks = ARRAY_SIZE(cam_cc_lahaina_clocks), @@ -3014,23 +2996,22 @@ static int cam_cc_lahaina_fixup(struct platform_device *pdev, static int cam_cc_lahaina_probe(struct platform_device *pdev) { struct regmap *regmap; - struct clk *clk; int ret; - clk = devm_clk_get(&pdev->dev, "cfg_ahb_clk"); - if (IS_ERR(clk)) { - if (PTR_ERR(clk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Unable to get ahb clock handle\n"); - return PTR_ERR(clk); - } - devm_clk_put(&pdev->dev, clk); - regmap = qcom_cc_map(pdev, &cam_cc_lahaina_desc); if (IS_ERR(regmap)) { dev_err(&pdev->dev, "Failed to map cam CC registers\n"); return PTR_ERR(regmap); } + ret = qcom_cc_runtime_init(pdev, &cam_cc_lahaina_desc); + if (ret) + return ret; + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret) + return ret; + clk_lucid_5lpe_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config); clk_lucid_5lpe_pll_configure(&cam_cc_pll1, regmap, &cam_cc_pll1_config); clk_zonda_5lpe_pll_configure(&cam_cc_pll2, regmap, &cam_cc_pll2_config); @@ -3043,12 +3024,19 @@ static int cam_cc_lahaina_probe(struct platform_device *pdev) if (ret) return ret; + /* + * Keep clocks always enabled: + * cam_cc_gdsc_clk + */ + regmap_update_bits(regmap, 0xc148, BIT(0), BIT(0)); + ret = qcom_cc_really_probe(pdev, &cam_cc_lahaina_desc, regmap); if (ret) { dev_err(&pdev->dev, "Failed to register CAM CC clocks\n"); return ret; } + pm_runtime_put_sync(&pdev->dev); dev_info(&pdev->dev, "Registered CAM CC clocks\n"); return ret; @@ -3059,12 +3047,17 @@ static void cam_cc_lahaina_sync_state(struct device *dev) qcom_cc_sync_state(dev, &cam_cc_lahaina_desc); } +static const struct dev_pm_ops cam_cc_lahaina_pm_ops = { + SET_RUNTIME_PM_OPS(qcom_cc_runtime_suspend, qcom_cc_runtime_resume, NULL) +}; + static struct platform_driver cam_cc_lahaina_driver = { .probe = cam_cc_lahaina_probe, .driver = { .name = "lahaina-cam_cc", .of_match_table = cam_cc_lahaina_match_table, .sync_state = cam_cc_lahaina_sync_state, + .pm = &cam_cc_lahaina_pm_ops, }, }; diff --git a/drivers/clk/qcom/dispcc-lahaina.c b/drivers/clk/qcom/dispcc-lahaina.c index 23ca6170c4d6..94a412c531fc 100644 --- a/drivers/clk/qcom/dispcc-lahaina.c +++ b/drivers/clk/qcom/dispcc-lahaina.c @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -1422,24 +1423,6 @@ static struct clk_branch disp_cc_sleep_clk = { }, }; -static struct clk_branch disp_cc_xo_clk = { - .halt_reg = 0x605c, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0x605c, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "disp_cc_xo_clk", - .parent_data = &(const struct clk_parent_data){ - .hw = &disp_cc_xo_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_regmap *disp_cc_lahaina_clocks[] = { [DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr, [DISP_CC_MDSS_AHB_CLK_SRC] = &disp_cc_mdss_ahb_clk_src.clkr, @@ -1502,7 +1485,6 @@ static struct clk_regmap *disp_cc_lahaina_clocks[] = { [DISP_CC_PLL1] = &disp_cc_pll1.clkr, [DISP_CC_SLEEP_CLK] = &disp_cc_sleep_clk.clkr, [DISP_CC_SLEEP_CLK_SRC] = &disp_cc_sleep_clk_src.clkr, - [DISP_CC_XO_CLK] = &disp_cc_xo_clk.clkr, [DISP_CC_XO_CLK_SRC] = &disp_cc_xo_clk_src.clkr, }; @@ -1519,7 +1501,7 @@ static const struct regmap_config disp_cc_lahaina_regmap_config = { .fast_io = true, }; -static const struct qcom_cc_desc disp_cc_lahaina_desc = { +static struct qcom_cc_desc disp_cc_lahaina_desc = { .config = &disp_cc_lahaina_regmap_config, .clks = disp_cc_lahaina_clocks, .num_clks = ARRAY_SIZE(disp_cc_lahaina_clocks), @@ -1538,20 +1520,19 @@ MODULE_DEVICE_TABLE(of, disp_cc_lahaina_match_table); static int disp_cc_lahaina_probe(struct platform_device *pdev) { struct regmap *regmap; - struct clk *clk; int ret; regmap = qcom_cc_map(pdev, &disp_cc_lahaina_desc); if (IS_ERR(regmap)) return PTR_ERR(regmap); - clk = devm_clk_get(&pdev->dev, "cfg_ahb_clk"); - if (IS_ERR(clk)) { - if (PTR_ERR(clk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Unable to get ahb clock handle\n"); - return PTR_ERR(clk); - } - devm_clk_put(&pdev->dev, clk); + ret = qcom_cc_runtime_init(pdev, &disp_cc_lahaina_desc); + if (ret) + return ret; + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret) + return ret; clk_lucid_5lpe_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config); @@ -1561,12 +1542,19 @@ static int disp_cc_lahaina_probe(struct platform_device *pdev) /* Enable clock gating for MDP clocks */ regmap_update_bits(regmap, DISP_CC_MISC_CMD, 0x10, 0x10); + /* + * Keep clocks always enabled: + * disp_cc_xo_clk + */ + regmap_update_bits(regmap, 0x605c, BIT(0), BIT(0)); + ret = qcom_cc_really_probe(pdev, &disp_cc_lahaina_desc, regmap); if (ret) { dev_err(&pdev->dev, "Failed to register DISP CC clocks\n"); return ret; } + pm_runtime_put_sync(&pdev->dev); dev_info(&pdev->dev, "Registered DISP CC clocks\n"); return ret; @@ -1577,12 +1565,17 @@ static void disp_cc_lahaina_sync_state(struct device *dev) qcom_cc_sync_state(dev, &disp_cc_lahaina_desc); } +static const struct dev_pm_ops disp_cc_lahaina_pm_ops = { + SET_RUNTIME_PM_OPS(qcom_cc_runtime_suspend, qcom_cc_runtime_resume, NULL) +}; + static struct platform_driver disp_cc_lahaina_driver = { .probe = disp_cc_lahaina_probe, .driver = { .name = "disp_cc-lahaina", .of_match_table = disp_cc_lahaina_match_table, .sync_state = disp_cc_lahaina_sync_state, + .pm = &disp_cc_lahaina_pm_ops, }, }; diff --git a/drivers/clk/qcom/videocc-lahaina.c b/drivers/clk/qcom/videocc-lahaina.c index 0b628014e238..b4985b3d4367 100644 --- a/drivers/clk/qcom/videocc-lahaina.c +++ b/drivers/clk/qcom/videocc-lahaina.c @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -361,26 +362,6 @@ static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = { }, }; -static struct clk_branch video_cc_ahb_clk = { - .halt_reg = 0xe58, - .halt_check = BRANCH_HALT_VOTED, - .hwcg_reg = 0xe58, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0xe58, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "video_cc_ahb_clk", - .parent_data = &(const struct clk_parent_data){ - .hw = &video_cc_ahb_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch video_cc_mvs0_clk = { .halt_reg = 0xd34, .halt_check = BRANCH_HALT_VOTED, @@ -495,26 +476,7 @@ static struct clk_branch video_cc_sleep_clk = { }, }; -static struct clk_branch video_cc_xo_clk = { - .halt_reg = 0xeec, - .halt_check = BRANCH_HALT, - .clkr = { - .enable_reg = 0xeec, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "video_cc_xo_clk", - .parent_data = &(const struct clk_parent_data){ - .hw = &video_cc_xo_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_regmap *video_cc_lahaina_clocks[] = { - [VIDEO_CC_AHB_CLK] = &video_cc_ahb_clk.clkr, [VIDEO_CC_AHB_CLK_SRC] = &video_cc_ahb_clk_src.clkr, [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr, [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr, @@ -531,7 +493,6 @@ static struct clk_regmap *video_cc_lahaina_clocks[] = { &video_cc_mvs1c_div2_div_clk_src.clkr, [VIDEO_CC_SLEEP_CLK] = &video_cc_sleep_clk.clkr, [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr, - [VIDEO_CC_XO_CLK] = &video_cc_xo_clk.clkr, [VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr, [VIDEO_PLL0] = &video_pll0.clkr, [VIDEO_PLL1] = &video_pll1.clkr, @@ -555,7 +516,7 @@ static const struct regmap_config video_cc_lahaina_regmap_config = { .fast_io = true, }; -static const struct qcom_cc_desc video_cc_lahaina_desc = { +static struct qcom_cc_desc video_cc_lahaina_desc = { .config = &video_cc_lahaina_regmap_config, .clks = video_cc_lahaina_clocks, .num_clks = ARRAY_SIZE(video_cc_lahaina_clocks), @@ -574,30 +535,38 @@ MODULE_DEVICE_TABLE(of, video_cc_lahaina_match_table); static int video_cc_lahaina_probe(struct platform_device *pdev) { struct regmap *regmap; - struct clk *clk; int ret; regmap = qcom_cc_map(pdev, &video_cc_lahaina_desc); if (IS_ERR(regmap)) return PTR_ERR(regmap); - clk = devm_clk_get(&pdev->dev, "cfg_ahb_clk"); - if (IS_ERR(clk)) { - if (PTR_ERR(clk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Unable to get ahb clock handle\n"); - return PTR_ERR(clk); - } - devm_clk_put(&pdev->dev, clk); + ret = qcom_cc_runtime_init(pdev, &video_cc_lahaina_desc); + if (ret) + return ret; + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret) + return ret; clk_lucid_5lpe_pll_configure(&video_pll0, regmap, &video_pll0_config); clk_lucid_5lpe_pll_configure(&video_pll1, regmap, &video_pll1_config); + /* + * Keep clocks always enabled: + * video_cc_ahb_clk + * video_cc_xo_clk + */ + regmap_update_bits(regmap, 0xe58, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0xeec, BIT(0), BIT(0)); + ret = qcom_cc_really_probe(pdev, &video_cc_lahaina_desc, regmap); if (ret) { dev_err(&pdev->dev, "Failed to register VIDEO CC clocks\n"); return ret; } + pm_runtime_put_sync(&pdev->dev); dev_info(&pdev->dev, "Registered VIDEO CC clocks\n"); return ret; @@ -608,12 +577,17 @@ static void video_cc_lahaina_sync_state(struct device *dev) qcom_cc_sync_state(dev, &video_cc_lahaina_desc); } +static const struct dev_pm_ops video_cc_lahaina_pm_ops = { + SET_RUNTIME_PM_OPS(qcom_cc_runtime_suspend, qcom_cc_runtime_resume, NULL) +}; + static struct platform_driver video_cc_lahaina_driver = { .probe = video_cc_lahaina_probe, .driver = { .name = "video_cc-lahaina", .of_match_table = video_cc_lahaina_match_table, .sync_state = video_cc_lahaina_sync_state, + .pm = &video_cc_lahaina_pm_ops, }, };