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 <mdtipton@codeaurora.org>
This commit is contained in:
Mike Tipton 2020-07-28 19:14:13 -07:00
commit 5004b21405
3 changed files with 66 additions and 106 deletions

View file

@ -10,6 +10,7 @@
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/pm_runtime.h>
#include <dt-bindings/clock/qcom,camcc-lahaina.h>
@ -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,
},
};

View file

@ -10,6 +10,7 @@
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/pm_runtime.h>
#include <dt-bindings/clock/qcom,dispcc-lahaina.h>
@ -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,
},
};

View file

@ -10,6 +10,7 @@
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/pm_runtime.h>
#include <dt-bindings/clock/qcom,videocc-lahaina.h>
@ -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,
},
};