]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
clk: zynqmp: Add support for dpll clock source
authorPadmarao Begari <padmarao.begari@amd.com>
Wed, 18 Jun 2025 09:43:29 +0000 (15:13 +0530)
committerMichal Simek <michal.simek@amd.com>
Tue, 8 Jul 2025 12:58:43 +0000 (14:58 +0200)
The clock driver fails to correctly calculate the PLL clock
rate for peripherals when using the DPLL as the clock source.
The DPLL operates within the full power domain, while peripheral
clocks reside in the low power domain. To ensure accurate PLL
clock rate computation when the peripheral clock source is set
to DPLL, the DPLL-to-LPD cross divisor is used.

Signed-off-by: Padmarao Begari <padmarao.begari@amd.com>
Link: https://lore.kernel.org/r/20250618094329.296731-1-padmarao.begari@amd.com
Signed-off-by: Michal Simek <michal.simek@amd.com>
drivers/clk/clk_zynqmp.c

index a8239e228cf6a916b8a8edd5400e69a0851f1869..4f67c958d0fc9b24a1046aecda0ba878e97ddf7f 100644 (file)
@@ -108,6 +108,8 @@ static const resource_size_t zynqmp_crl_apb_clkc_base = 0xff5e0020;
 #define PLLCTRL_POST_SRC_MASK  (0x7 << PLLCTRL_POST_SRC_SHFT)
 #define PLLCTRL_PRE_SRC_SHFT   20
 #define PLLCTRL_PRE_SRC_MASK   (0x7 << PLLCTRL_PRE_SRC_SHFT)
+#define PLL_TO_LPD_DIV_SHIFT   8
+#define PLL_TO_LPD_DIV_MASK    (0x3f << PLL_TO_LPD_DIV_SHIFT)
 
 #define NUM_MIO_PINS   77
 
@@ -334,6 +336,8 @@ static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
                return CRF_APB_TOPSW_LSBUS_CTRL;
        case iopll_to_fpd:
                return CRL_APB_IOPLL_TO_FPD_CTRL;
+       case dpll_to_lpd:
+               return CRF_APB_DPLL_TO_LPD_CTRL;
        default:
                debug("Invalid clk id%d\n", id);
        }
@@ -397,6 +401,22 @@ static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
        if (clk_ctrl & (1 << 16))
                freq /= 2;
 
+       if (id == dpll) {
+               u32 dpll_lpd_reg, cross_div;
+
+               dpll_lpd_reg = zynqmp_clk_get_register(dpll_to_lpd);
+
+               ret = zynqmp_mmio_read(dpll_lpd_reg, &cross_div);
+               if (ret) {
+                       printf("%s mio read fail\n", __func__);
+                       return -EIO;
+               }
+
+               cross_div = (cross_div & PLL_TO_LPD_DIV_MASK) >>
+                            PLL_TO_LPD_DIV_SHIFT;
+               freq /= cross_div;
+       }
+
        return freq;
 }