From f994b66c19c4a6446809d829e2856dfa4bd7976a Mon Sep 17 00:00:00 2001 From: Xingyu Wu Date: Fri, 30 Sep 2022 15:26:59 +0800 Subject: [PATCH] clk:starfive:isp:Add runtime and system pm control Add runtime and system pm in isp clock tree driver. Signed-off-by: Xingyu Wu --- drivers/clk/starfive/clk-starfive-jh7110-gen.c | 16 ++- drivers/clk/starfive/clk-starfive-jh7110-isp.c | 151 ++++++++++++++++++------- drivers/clk/starfive/clk-starfive-jh7110-sys.c | 2 +- 3 files changed, 126 insertions(+), 43 deletions(-) mode change 100755 => 100644 drivers/clk/starfive/clk-starfive-jh7110-gen.c mode change 100755 => 100644 drivers/clk/starfive/clk-starfive-jh7110-isp.c mode change 100755 => 100644 drivers/clk/starfive/clk-starfive-jh7110-sys.c diff --git a/drivers/clk/starfive/clk-starfive-jh7110-gen.c b/drivers/clk/starfive/clk-starfive-jh7110-gen.c old mode 100755 new mode 100644 index 42e6176..9aac50d --- a/drivers/clk/starfive/clk-starfive-jh7110-gen.c +++ b/drivers/clk/starfive/clk-starfive-jh7110-gen.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "clk-starfive-jh7110.h" @@ -53,6 +54,19 @@ void __iomem *jh7110_clk_reg_addr_get(struct jh7110_clk *clk) static u32 jh7110_clk_reg_get(struct jh7110_clk *clk) { void __iomem *reg = jh7110_clk_reg_addr_get(clk); + if (clk->reg_flags == JH7110_CLK_ISP_FLAG) { + int ret; + struct jh7110_clk_priv *priv = jh7110_priv_from(clk); + + if (pm_runtime_suspended(priv->dev)) { + ret = pm_runtime_get_sync(priv->dev); + if (ret < 0) { + dev_err(priv->dev, "cannot resume device :%d.\n", ret); + return 0; + } + pm_runtime_put(priv->dev); + } + } return readl_relaxed(reg); } @@ -69,7 +83,7 @@ static void jh7110_clk_reg_rmw(struct jh7110_clk *clk, u32 mask, u32 value) || clk->idx == JH7110_UART5_CLK_CORE) && (value != JH7110_CLK_ENABLE)) value <<= 8; - value |= readl_relaxed(reg) & ~mask; + value |= jh7110_clk_reg_get(clk) & ~mask; writel_relaxed(value, reg); spin_unlock_irqrestore(&priv->rmw_lock, flags); } diff --git a/drivers/clk/starfive/clk-starfive-jh7110-isp.c b/drivers/clk/starfive/clk-starfive-jh7110-isp.c old mode 100755 new mode 100644 index a8fc3c5..b30cc76 --- a/drivers/clk/starfive/clk-starfive-jh7110-isp.c +++ b/drivers/clk/starfive/clk-starfive-jh7110-isp.c @@ -30,6 +30,12 @@ #define JH7110_ISP_TOP_CLK_BIST_APB_CLKGEN (JH7110_CLK_ISP_END + 2) #define JH7110_ISP_TOP_CLK_DVP_CLKGEN (JH7110_CLK_ISP_END + 3) +struct isp_init_crg { + int num_clks; + struct clk_bulk_data *clks; + struct reset_control *rsts; +}; + static const struct jh7110_clk_data jh7110_clk_isp_data[] __initconst = { //syscon JH7110__DIV(JH7110_DOM4_APB_FUNC, "dom4_apb_func", @@ -72,7 +78,92 @@ static const struct jh7110_clk_data jh7110_clk_isp_data[] __initconst = { static struct clk_bulk_data isp_top_clks[] = { { .id = "u0_dom_isp_top_clk_dom_isp_top_clk_ispcore_2x" }, { .id = "u0_dom_isp_top_clk_dom_isp_top_clk_isp_axi" }, - { .id = "u0_sft7110_noc_bus_clk_isp_axi" }, +}; + +static int jh7110_isp_crg_get(struct device *dev, struct isp_init_crg *crg) +{ + int ret; + + crg->rsts = devm_reset_control_array_get_shared(dev); + if (IS_ERR(crg->rsts)) { + dev_err(dev, "rst get failed\n"); + return PTR_ERR(crg->rsts); + } + + crg->clks = isp_top_clks; + crg->num_clks = ARRAY_SIZE(isp_top_clks); + ret = clk_bulk_get(dev, crg->num_clks, crg->clks); + if (ret) { + dev_err(dev, "clks get failed: %d\n", ret); + goto clks_get_failed; + } + + return 0; + +clks_get_failed: + reset_control_assert(crg->rsts); + reset_control_put(crg->rsts); + + return ret; +} + +static int jh7110_isp_crg_enable(struct device *dev, struct isp_init_crg *crg, bool enable) +{ + int ret; + + dev_dbg(dev, "starfive jh7110 isp clk&rst %sable\n", enable ? "en":"dis"); + if (enable) { + ret = reset_control_deassert(crg->rsts); + if (ret) { + dev_err(dev, "rst deassert failed: %d\n", ret); + goto crg_failed; + } + + ret = clk_bulk_prepare_enable(crg->num_clks, crg->clks); + if (ret) { + dev_err(dev, "clks enable failed: %d\n", ret); + goto crg_failed; + } + } else { + clk_bulk_disable_unprepare(crg->num_clks, crg->clks); + } + + return 0; +crg_failed: + return ret; +} + +#ifdef CONFIG_PM_SLEEP +static int clk_isp_system_suspend(struct device *dev) +{ + return pm_runtime_force_suspend(dev); +} + +static int clk_isp_system_resume(struct device *dev) +{ + return pm_runtime_force_resume(dev); +} +#endif + +#ifdef CONFIG_PM +static int clk_isp_runtime_suspend(struct device *dev) +{ + struct isp_init_crg *crg = dev_get_drvdata(dev); + + return jh7110_isp_crg_enable(dev, crg, false); +} + +static int clk_isp_runtime_resume(struct device *dev) +{ + struct isp_init_crg *crg = dev_get_drvdata(dev); + + return jh7110_isp_crg_enable(dev, crg, true); +} +#endif + +static const struct dev_pm_ops clk_isp_pm_ops = { + SET_RUNTIME_PM_OPS(clk_isp_runtime_suspend, clk_isp_runtime_resume, NULL) + SET_LATE_SYSTEM_SLEEP_PM_OPS(clk_isp_system_suspend, clk_isp_system_resume) }; static struct clk_hw *jh7110_isp_clk_get(struct of_phandle_args *clkspec, @@ -93,9 +184,8 @@ static struct clk_hw *jh7110_isp_clk_get(struct of_phandle_args *clkspec, static int __init clk_starfive_jh7110_isp_probe(struct platform_device *pdev) { struct jh7110_clk_priv *priv; + struct isp_init_crg *crg; unsigned int idx; - struct reset_control *rsts; - int num_clks; int ret = 0; priv = devm_kzalloc(&pdev->dev, struct_size(priv, reg, @@ -109,36 +199,22 @@ static int __init clk_starfive_jh7110_isp_probe(struct platform_device *pdev) if (IS_ERR(priv->isp_base)) return PTR_ERR(priv->isp_base); + crg = devm_kzalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL); + if (!crg) + return -ENOMEM; + dev_set_drvdata(&pdev->dev, crg); + + ret = jh7110_isp_crg_get(&pdev->dev, crg); + if (ret) + goto init_failed; + + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, 50); pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "failed to get pm runtime: %d\n", ret); - return ret; - } - - rsts = devm_reset_control_array_get_shared(priv->dev); - if (!IS_ERR(rsts)) { - ret = reset_control_deassert(rsts); - if (ret) { - dev_err(priv->dev, "rst deassert failed: %d\n", ret); - goto rsts_deassert_failed; - } - } else { - dev_err(priv->dev, "rst get failed\n"); - return PTR_ERR(rsts); - } - - num_clks = ARRAY_SIZE(isp_top_clks); - ret = clk_bulk_get(priv->dev, num_clks, isp_top_clks); - if (!ret) { - ret = clk_bulk_prepare_enable(num_clks, isp_top_clks); - if (ret) { - dev_err(priv->dev, "clks enable failed: %d\n", ret); - goto clks_enable_failed; - } - } else { - dev_err(priv->dev, "clks get failed: %d\n", ret); - goto clks_get_failed; + goto init_failed; } priv->pll[PLL_OFI(JH7110_U3_PCLK_MUX_FUNC_PCLK)] = @@ -247,28 +323,20 @@ static int __init clk_starfive_jh7110_isp_probe(struct platform_device *pdev) ret = devm_clk_hw_register(priv->dev, &clk->hw); if (ret) - return ret; + goto init_failed; } ret = devm_of_clk_add_hw_provider(priv->dev, jh7110_isp_clk_get, priv); if (ret) - return ret; + goto init_failed; - clk_bulk_put(num_clks, isp_top_clks); - reset_control_put(rsts); + pm_runtime_put_sync(&pdev->dev); dev_info(&pdev->dev, "starfive JH7110 clk_isp init successfully."); return 0; -clks_enable_failed: - clk_bulk_put(num_clks, isp_top_clks); -clks_get_failed: - reset_control_assert(rsts); -rsts_deassert_failed: - reset_control_put(rsts); - +init_failed: return ret; - } static const struct of_device_id clk_starfive_jh7110_isp_match[] = { @@ -281,6 +349,7 @@ static struct platform_driver clk_starfive_jh7110_isp_driver = { .driver = { .name = "clk-starfive-jh7110-isp", .of_match_table = clk_starfive_jh7110_isp_match, + .pm = &clk_isp_pm_ops, }, }; module_platform_driver(clk_starfive_jh7110_isp_driver); diff --git a/drivers/clk/starfive/clk-starfive-jh7110-sys.c b/drivers/clk/starfive/clk-starfive-jh7110-sys.c old mode 100755 new mode 100644 index 73051bb..cc19ec6 --- a/drivers/clk/starfive/clk-starfive-jh7110-sys.c +++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c @@ -138,7 +138,7 @@ static const struct jh7110_clk_data jh7110_clk_sys_data[] __initconst = { GATE_FLAG_NORMAL, JH7110_ISP_AXI), JH7110_GATE(JH7110_NOC_BUS_CLK_ISP_AXI, "u0_sft7110_noc_bus_clk_isp_axi", - CLK_IGNORE_UNUSED, JH7110_ISP_AXI), + CLK_IS_CRITICAL, JH7110_ISP_AXI), //HIFI4 JH7110__DIV(JH7110_HIFI4_CORE, "hifi4_core", 15, JH7110_BUS_ROOT), JH7110__DIV(JH7110_HIFI4_AXI, "hifi4_axi", 2, JH7110_HIFI4_CORE), -- 2.7.4