Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5004b214 authored by Mike Tipton's avatar Mike Tipton
Browse files

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: default avatarMike Tipton <mdtipton@codeaurora.org>
parent 7c2b115d
Loading
Loading
Loading
Loading
+22 −29
Original line number Diff line number Diff line
@@ -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,
	},
};

+21 −28
Original line number Diff line number Diff line
@@ -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,
	},
};

+23 −49
Original line number Diff line number Diff line
@@ -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,
	},
};