From 6677196fb1932e60b88ad0794a7ae532df178654 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 25 Mar 2024 09:58:35 +0100 Subject: [PATCH 1/6] clk: qcom: gdsc: treat optional supplies as optional Since commit deebc79b28d6 ("clk: qcom: gpucc-sc8280xp: Add external supply for GX gdsc") the GDSC supply must be treated as optional to avoid warnings like: gpu_cc-sc8280xp 3d90000.clock-controller: supply vdd-gfx not found, using dummy regulator on SC8280XP. Fortunately, the driver is already prepared to handle this by checking that the regulator pointer is non-NULL before use. This also avoids triggering a potential deadlock on SC8280XP even if the underlying issue still remains for the derivative platforms like SA8295P that actually use the supply. Fixes: deebc79b28d6 ("clk: qcom: gpucc-sc8280xp: Add external supply for GX gdsc") Link: https://lore.kernel.org/lkml/Zf25Sv2x9WaCFuIH@hovoldconsulting.com/ Signed-off-by: Johan Hovold Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/20240325085835.26158-1-johan+linaro@kernel.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gdsc.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index e7a4068b9f39..df9618ab7eea 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -487,9 +487,14 @@ int gdsc_register(struct gdsc_desc *desc, if (!scs[i] || !scs[i]->supply) continue; - scs[i]->rsupply = devm_regulator_get(dev, scs[i]->supply); - if (IS_ERR(scs[i]->rsupply)) - return PTR_ERR(scs[i]->rsupply); + scs[i]->rsupply = devm_regulator_get_optional(dev, scs[i]->supply); + if (IS_ERR(scs[i]->rsupply)) { + ret = PTR_ERR(scs[i]->rsupply); + if (ret != -ENODEV) + return ret; + + scs[i]->rsupply = NULL; + } } data->num_domains = num; From 0d4ce2458cd7d1d66a5ee2f3c036592fb663d5bc Mon Sep 17 00:00:00 2001 From: Adam Skladowski Date: Mon, 1 Apr 2024 19:16:39 +0200 Subject: [PATCH 2/6] clk: qcom: smd-rpm: Restore msm8976 num_clk During rework somehow msm8976 num_clk got removed, restore it. Fixes: d6edc31f3a68 ("clk: qcom: smd-rpm: Separate out interconnect bus clocks") Signed-off-by: Adam Skladowski Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20240401171641.8979-1-a39.skl@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-smd-rpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 8602c02047d0..45c5255bcd11 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -768,6 +768,7 @@ static struct clk_smd_rpm *msm8976_clks[] = { static const struct rpm_smd_clk_desc rpm_clk_msm8976 = { .clks = msm8976_clks, + .num_clks = ARRAY_SIZE(msm8976_clks), .icc_clks = bimc_pcnoc_snoc_smmnoc_icc_clks, .num_icc_clks = ARRAY_SIZE(bimc_pcnoc_snoc_smmnoc_icc_clks), }; From 7e91ed763dc07437777bd012af7a2bd4493731ff Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Fri, 13 Oct 2023 20:17:12 +0200 Subject: [PATCH 3/6] clk: sunxi-ng: h6: Reparent CPUX during PLL CPUX rate change While PLL CPUX clock rate change when CPU is running from it works in vast majority of cases, now and then it causes instability. This leads to system crashes and other undefined behaviour. After a lot of testing (30+ hours) while also doing a lot of frequency switches, we can't observe any instability issues anymore when doing reparenting to stable clock like 24 MHz oscillator. Fixes: 524353ea480b ("clk: sunxi-ng: add support for the Allwinner H6 CCU") Reported-by: Chad Wagner Link: https://forum.libreelec.tv/thread/27295-orange-pi-3-lts-freezes/ Tested-by: Chad Wagner Reviewed-by: Chen-Yu Tsai Link: https://lore.kernel.org/r/20231013181712.2128037-1-jernej.skrabec@gmail.com Signed-off-by: Jernej Skrabec --- drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c index 42568c616181..892df807275c 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -1181,11 +1181,18 @@ static const u32 usb2_clk_regs[] = { SUN50I_H6_USB3_CLK_REG, }; +static struct ccu_mux_nb sun50i_h6_cpu_nb = { + .common = &cpux_clk.common, + .cm = &cpux_clk.mux, + .delay_us = 1, + .bypass_index = 0, /* index of 24 MHz oscillator */ +}; + static int sun50i_h6_ccu_probe(struct platform_device *pdev) { void __iomem *reg; + int i, ret; u32 val; - int i; reg = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg)) @@ -1252,7 +1259,15 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev) val |= BIT(24); writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG); - return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc); + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc); + if (ret) + return ret; + + /* Reparent CPU during PLL CPUX rate changes */ + ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, + &sun50i_h6_cpu_nb); + + return 0; } static const struct of_device_id sun50i_h6_ccu_ids[] = { From b914ec33b391ec766545a41f0cfc0de3e0b388d7 Mon Sep 17 00:00:00 2001 From: Frank Oltmanns Date: Sun, 10 Mar 2024 14:21:11 +0100 Subject: [PATCH 4/6] clk: sunxi-ng: common: Support minimum and maximum rate The Allwinner SoC's typically have an upper and lower limit for their clocks' rates. Up until now, support for that has been implemented separately for each clock type. Implement that functionality in the sunxi-ng's common part making use of the CCF rate liming capabilities, so that it is available for all clock types. Suggested-by: Maxime Ripard Signed-off-by: Frank Oltmanns Cc: stable@vger.kernel.org Reviewed-by: Jernej Skrabec Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20240310-pinephone-pll-fixes-v4-1-46fc80c83637@oltmanns.dev Signed-off-by: Jernej Skrabec --- drivers/clk/sunxi-ng/ccu_common.c | 19 +++++++++++++++++++ drivers/clk/sunxi-ng/ccu_common.h | 3 +++ 2 files changed, 22 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c index 8babce55302f..ac0091b4ce24 100644 --- a/drivers/clk/sunxi-ng/ccu_common.c +++ b/drivers/clk/sunxi-ng/ccu_common.c @@ -44,6 +44,16 @@ bool ccu_is_better_rate(struct ccu_common *common, unsigned long current_rate, unsigned long best_rate) { + unsigned long min_rate, max_rate; + + clk_hw_get_rate_range(&common->hw, &min_rate, &max_rate); + + if (current_rate > max_rate) + return false; + + if (current_rate < min_rate) + return false; + if (common->features & CCU_FEATURE_CLOSEST_RATE) return abs(current_rate - target_rate) < abs(best_rate - target_rate); @@ -122,6 +132,7 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev, for (i = 0; i < desc->hw_clks->num ; i++) { struct clk_hw *hw = desc->hw_clks->hws[i]; + struct ccu_common *common = hw_to_ccu_common(hw); const char *name; if (!hw) @@ -136,6 +147,14 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev, pr_err("Couldn't register clock %d - %s\n", i, name); goto err_clk_unreg; } + + if (common->max_rate) + clk_hw_set_rate_range(hw, common->min_rate, + common->max_rate); + else + WARN(common->min_rate, + "No max_rate, ignoring min_rate of clock %d - %s\n", + i, name); } ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h index 942a72c09437..329734f8cf42 100644 --- a/drivers/clk/sunxi-ng/ccu_common.h +++ b/drivers/clk/sunxi-ng/ccu_common.h @@ -31,6 +31,9 @@ struct ccu_common { u16 lock_reg; u32 prediv; + unsigned long min_rate; + unsigned long max_rate; + unsigned long features; spinlock_t *lock; struct clk_hw hw; From 69f16d9b789821183d342719d2ebd4a5ac7178bc Mon Sep 17 00:00:00 2001 From: Frank Oltmanns Date: Sun, 10 Mar 2024 14:21:12 +0100 Subject: [PATCH 5/6] clk: sunxi-ng: a64: Set minimum and maximum rate for PLL-MIPI When the Allwinner A64's TCON0 searches the ideal rate for the connected panel, it may happen that it requests a rate from its parent PLL-MIPI which PLL-MIPI does not support. This happens for example on the Olimex TERES-I laptop where TCON0 requests PLL-MIPI to change to a rate of several GHz which causes the panel to stay blank. It also happens on the pinephone where a rate of less than 500 MHz is requested which causes instabilities on some phones. Set the minimum and maximum rate of Allwinner A64's PLL-MIPI according to the Allwinner User Manual. Fixes: ca1170b69968 ("clk: sunxi-ng: a64: force select PLL_MIPI in TCON0 mux") Reported-by: Diego Roversi Closes: https://groups.google.com/g/linux-sunxi/c/Rh-Uqqa66bw Tested-by: Diego Roversi Cc: stable@vger.kernel.org Reviewed-by: Maxime Ripard Signed-off-by: Frank Oltmanns Reviewed-by: Jernej Skrabec Link: https://lore.kernel.org/r/20240310-pinephone-pll-fixes-v4-2-46fc80c83637@oltmanns.dev Signed-off-by: Jernej Skrabec --- drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c index 8951ffc14ff5..6a4b2b9ef30a 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c @@ -182,6 +182,8 @@ static struct ccu_nkm pll_mipi_clk = { &ccu_nkm_ops, CLK_SET_RATE_UNGATE | CLK_SET_RATE_PARENT), .features = CCU_FEATURE_CLOSEST_RATE, + .min_rate = 500000000, + .max_rate = 1400000000, }, }; From aacb99de1099346244d488bdf7df489a44278574 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 30 Apr 2024 20:46:56 +0200 Subject: [PATCH 6/6] clk: samsung: Revert "clk: Use device_get_match_data()" device_get_match_data() function should not be used on the device other than the one matched to the given driver, because it always returns the match_data of the matched driver. In case of exynos-clkout driver, the original code matches the OF IDs on the PARENT device, so replacing it with of_device_get_match_data() broke the driver. This has been already pointed once in commit 2bc5febd05ab ("clk: samsung: Revert "clk: samsung: exynos-clkout: Use of_device_get_match_data()""). To avoid further confusion, add a comment about this special case, which requires direct of_match_device() call to pass custom IDs array. This partially reverts commit 409c39ec92a35e3708f5b5798c78eae78512cd71. Cc: Fixes: 409c39ec92a3 ("clk: Use device_get_match_data()") Signed-off-by: Marek Szyprowski Link: https://lore.kernel.org/r/20240425075628.838497-1-m.szyprowski@samsung.com Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430184656.357805-1-krzysztof.kozlowski@linaro.org Signed-off-by: Stephen Boyd --- drivers/clk/samsung/clk-exynos-clkout.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c index 3484e6cc80ad..503c6f5b20d5 100644 --- a/drivers/clk/samsung/clk-exynos-clkout.c +++ b/drivers/clk/samsung/clk-exynos-clkout.c @@ -13,9 +13,9 @@ #include #include #include +#include #include #include -#include #define EXYNOS_CLKOUT_NR_CLKS 1 #define EXYNOS_CLKOUT_PARENTS 32 @@ -84,17 +84,24 @@ MODULE_DEVICE_TABLE(of, exynos_clkout_ids); static int exynos_clkout_match_parent_dev(struct device *dev, u32 *mux_mask) { const struct exynos_clkout_variant *variant; + const struct of_device_id *match; if (!dev->parent) { dev_err(dev, "not instantiated from MFD\n"); return -EINVAL; } - variant = device_get_match_data(dev->parent); - if (!variant) { + /* + * 'exynos_clkout_ids' arrays is not the ids array matched by + * the dev->parent driver, so of_device_get_match_data() or + * device_get_match_data() cannot be used here. + */ + match = of_match_device(exynos_clkout_ids, dev->parent); + if (!match) { dev_err(dev, "cannot match parent device\n"); return -EINVAL; } + variant = match->data; *mux_mask = variant->mux_mask;