clk: samsung: clk-pll: Add support for pll_531x
authorSunyeal Hong <sunyeal.hong@samsung.com>
Wed, 21 Aug 2024 23:26:51 +0000 (08:26 +0900)
committerKrzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Fri, 23 Aug 2024 07:21:28 +0000 (09:21 +0200)
pll531x PLL is used in Exynos Auto v920 SoC for shared pll.
pll531x: Integer/fractional PLL with mid frequency FVCO (800 to 3120 MHz)

PLL531x
FOUT = (MDIV x FIN)/(PDIV x 2^SDIV) for integer PLL
FOUT = (MDIV + F/2^32-F[31]) x FIN/(PDIV x 2^SDIV) for fractional PLL

Signed-off-by: Sunyeal Hong <sunyeal.hong@samsung.com>
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Link: https://lore.kernel.org/r/20240821232652.1077701-4-sunyeal.hong@samsung.com
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
drivers/clk/samsung/clk-pll.c
drivers/clk/samsung/clk-pll.h

index 4307cd534ee6fd0fa3384560cf5a6180fd1087d0..cca3e630922c1487c76aa92999d6c1896c156b06 100644 (file)
@@ -1272,6 +1272,47 @@ static const struct clk_ops samsung_pll2650xx_clk_min_ops = {
        .recalc_rate = samsung_pll2650xx_recalc_rate,
 };
 
+/*
+ * PLL531X Clock Type
+ */
+/* Maximum lock time can be 500 * PDIV cycles */
+#define PLL531X_LOCK_FACTOR            (500)
+#define PLL531X_MDIV_MASK              (0x3FF)
+#define PLL531X_PDIV_MASK              (0x3F)
+#define PLL531X_SDIV_MASK              (0x7)
+#define PLL531X_FDIV_MASK              (0xFFFFFFFF)
+#define PLL531X_MDIV_SHIFT             (16)
+#define PLL531X_PDIV_SHIFT             (8)
+#define PLL531X_SDIV_SHIFT             (0)
+
+static unsigned long samsung_pll531x_recalc_rate(struct clk_hw *hw,
+                                                unsigned long parent_rate)
+{
+       struct samsung_clk_pll *pll = to_clk_pll(hw);
+       u32 pdiv, sdiv, fdiv, pll_con0, pll_con8;
+       u64 mdiv, fout = parent_rate;
+
+       pll_con0 = readl_relaxed(pll->con_reg);
+       pll_con8 = readl_relaxed(pll->con_reg + 20);
+       mdiv = (pll_con0 >> PLL531X_MDIV_SHIFT) & PLL531X_MDIV_MASK;
+       pdiv = (pll_con0 >> PLL531X_PDIV_SHIFT) & PLL531X_PDIV_MASK;
+       sdiv = (pll_con0 >> PLL531X_SDIV_SHIFT) & PLL531X_SDIV_MASK;
+       fdiv = (pll_con8 & PLL531X_FDIV_MASK);
+
+       if (fdiv >> 31)
+               mdiv--;
+
+       fout *= (mdiv << 24) + (fdiv >> 8);
+       do_div(fout, (pdiv << sdiv));
+       fout >>= 24;
+
+       return (unsigned long)fout;
+}
+
+static const struct clk_ops samsung_pll531x_clk_ops = {
+       .recalc_rate = samsung_pll531x_recalc_rate,
+};
+
 static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
                                const struct samsung_pll_clock *pll_clk)
 {
@@ -1406,6 +1447,9 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
                else
                        init.ops = &samsung_pll2650xx_clk_ops;
                break;
+       case pll_531x:
+               init.ops = &samsung_pll531x_clk_ops;
+               break;
        default:
                pr_warn("%s: Unknown pll type for pll clk %s\n",
                        __func__, pll_clk->name);
index 1efbe4c446d0e3f55a09f80afd7ca7f93ff31b11..3481941ba07a9d8bf5251508573324223ad84802 100644 (file)
@@ -42,6 +42,7 @@ enum samsung_pll_type {
        pll_0516x,
        pll_0517x,
        pll_0518x,
+       pll_531x,
 };
 
 #define PLL_RATE(_fin, _m, _p, _s, _k, _ks) \