Re: [PATCH v2 1/4] media: qcom: camss: Add PM clock support and integrate with runtime PM
From: Frank Li
Date: Tue Jul 21 2026 - 12:30:54 EST
On Tue, Jul 21, 2026 at 03:21:08PM +0200, Loic Poulain wrote:
> Add optional PM clock support to the CAMSS driver using the PM clock
> framework. This allows CAMSS clocks to be registered once and
> automatically managed during runtime suspend and resume.
>
> This is especially useful for global CAMSS clocks that are shared across
> multiple CAMSS subblocks.
>
> This avoids the need for each subblock to reference and manage the
> shared clocks individually. A typical example is the set of clocks in
> the top_group, which may be used by CSID, PHY, CCI, and other CAMSS
> blocks.
>
> Introduce a small PM clock descriptor table in the CAMSS resources
> structure to describe clocks and their optional rates. Initialize
> these clocks at probe time and delegate clock ownership to the PM
> core.
>
> Hook PM clock handling into the runtime PM callbacks to ensure clocks
> are properly suspended and resumed alongside power domains and ICC
> paths.
>
> Signed-off-by: Loic Poulain <loic.poulain@xxxxxxxxxxxxxxxx>
> ---
Reviewed-by: Frank Li <Frank.Li@xxxxxxx>
> drivers/media/platform/qcom/camss/camss.c | 42 ++++++++++++++++++++++++++++++-
> drivers/media/platform/qcom/camss/camss.h | 1 +
> 2 files changed, 42 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
> index 2123f6388e3d7eafe669efd6b033e22d8eb5cf79..01a9d4f780fbe130554601481bed50eac5978bed 100644
> --- a/drivers/media/platform/qcom/camss/camss.c
> +++ b/drivers/media/platform/qcom/camss/camss.c
> @@ -18,6 +18,7 @@
> #include <linux/of_graph.h>
> #include <linux/pm_runtime.h>
> #include <linux/pm_domain.h>
> +#include <linux/pm_clock.h>
> #include <linux/slab.h>
> #include <linux/videodev2.h>
>
> @@ -5346,6 +5347,37 @@ static void camss_genpd_cleanup(struct camss *camss)
> dev_pm_domain_detach(camss->genpd, true);
> }
>
> +/*
> + * camss_init_pm_clks - register shared CAMSS clocks with the PM clock framework
> + *
> + * Clocks listed in res->pm_clks are shared across all CAMSS sub-devices (e.g.
> + * top_ahb, axi). They are managed automatically by the PM framework.
> + */
> +static int camss_init_pm_clks(struct camss *camss)
> +{
> + struct device *dev = camss->dev;
> + unsigned int i;
> + int ret;
> +
> + if (!camss->res->pm_clks[0])
> + return 0;
> +
> + ret = devm_pm_clk_create(dev);
> + if (ret)
> + return ret;
> +
> + for (i = 0; i < CAMSS_RES_MAX && camss->res->pm_clks[i]; i++) {
> + ret = pm_clk_add(dev, camss->res->pm_clks[i]);
> + if (ret) {
> + dev_err(dev, "failed to add pm_clk %s: %d\n",
> + camss->res->pm_clks[i], ret);
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
> +
> /*
> * camss_probe - Probe CAMSS platform device
> * @pdev: Pointer to CAMSS platform device
> @@ -5434,6 +5466,10 @@ static int camss_probe(struct platform_device *pdev)
>
> pm_runtime_enable(dev);
>
> + ret = camss_init_pm_clks(camss);
> + if (ret)
> + goto err_v4l2_device_unregister;
> +
> ret = camss_parse_ports(camss);
> if (ret < 0)
> goto err_v4l2_device_unregister;
> @@ -5775,7 +5811,7 @@ static int __maybe_unused camss_runtime_suspend(struct device *dev)
> return ret;
> }
>
> - return 0;
> + return pm_clk_suspend(dev);
> }
>
> static int __maybe_unused camss_runtime_resume(struct device *dev)
> @@ -5785,6 +5821,10 @@ static int __maybe_unused camss_runtime_resume(struct device *dev)
> int i;
> int ret;
>
> + ret = pm_clk_resume(dev);
> + if (ret)
> + return ret;
> +
> for (i = 0; i < camss->res->icc_path_num; i++) {
> ret = icc_set_bw(camss->icc_path[i],
> icc_res[i].icc_bw_tbl.avg,
> diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h
> index 93d691c8ac63b2a47dbb234856b627d8911a1851..fe5fe25d5f18d8a3ce35b48077a975f1453c341f 100644
> --- a/drivers/media/platform/qcom/camss/camss.h
> +++ b/drivers/media/platform/qcom/camss/camss.h
> @@ -107,6 +107,7 @@ enum icc_count {
> struct camss_resources {
> enum camss_version version;
> const char *pd_name;
> + const char *pm_clks[CAMSS_RES_MAX];
> const struct camss_subdev_resources *csiphy_res;
> const struct camss_subdev_resources *tpg_res;
> const struct camss_subdev_resources *csid_res;
>
> --
> 2.34.1
>