socfpga: arria10: Replace delays with busy waiting in cm_full_cfg
authorPaweł Anikiel <pan@semihalf.com>
Fri, 17 Jun 2022 10:47:23 +0000 (12:47 +0200)
committerTien Fong Chee <tien.fong.chee@intel.com>
Fri, 1 Jul 2022 06:57:14 +0000 (14:57 +0800)
Using udelay while the clocks aren't fully configured causes the timer
system to save the wrong clock rate. Use sdelay and wait_on_value
instead (the values used in these functions were found experimentally).

Signed-off-by: Paweł Anikiel <pan@semihalf.com>
Reviewed-by: Tien Fong Chee <tien.fong.chee@intel.com>
arch/arm/mach-socfpga/clock_manager_arria10.c

index 58d5d3f..b48a2b4 100644 (file)
 
 #ifdef CONFIG_SPL_BUILD
 
+void sdelay(unsigned long loops);
+u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr,
+                 u32 bound);
+
 static u32 eosc1_hz;
 static u32 cb_intosc_hz;
 static u32 f2s_free_hz;
@@ -551,13 +555,13 @@ static void cm_pll_ramp_main(struct mainpll_cfg *main_cfg,
                        CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
                        cm_calc_safe_pll_numer(0, main_cfg, per_cfg, clk_hz),
                        socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
-               mdelay(1);
+               sdelay(1000000); /* 1ms */
                cm_wait_for_lock(LOCKED_MASK);
        }
        writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
                main_cfg->vco1_numer,
                socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
-       mdelay(1);
+       sdelay(1000000); /* 1ms */
        cm_wait_for_lock(LOCKED_MASK);
 }
 
@@ -585,16 +589,25 @@ static void cm_pll_ramp_periph(struct mainpll_cfg *main_cfg,
                                                     clk_hz),
                              socfpga_get_clkmgr_addr() +
                              CLKMGR_A10_PERPLL_VCO1);
-               mdelay(1);
+               sdelay(1000000); /* 1ms */
                cm_wait_for_lock(LOCKED_MASK);
        }
        writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) |
                      per_cfg->vco1_numer,
                      socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
-       mdelay(1);
+       sdelay(1000000); /* 1ms */
        cm_wait_for_lock(LOCKED_MASK);
 }
 
+/* function to poll in the fsm busy bit */
+static int cm_busy_wait_for_fsm(void)
+{
+       void *reg = (void *)(socfpga_get_clkmgr_addr() + CLKMGR_STAT);
+
+       /* 20s timeout */
+       return wait_on_value(CLKMGR_STAT_BUSY, 0, reg, 100000000);
+}
+
 /*
  * Setup clocks while making no assumptions of the
  * previous state of the clocks.
@@ -727,7 +740,7 @@ static int cm_full_cfg(struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
                        socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
 
        /* Wait for at least 5 us */
-       udelay(5);
+       sdelay(5000);
 
        /* Now deassert BGPWRDN and PWRDN */
        clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0,
@@ -738,7 +751,7 @@ static int cm_full_cfg(struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
                     CLKMGR_PERPLL_VCO0_PWRDN_SET_MSK);
 
        /* Wait for at least 7 us */
-       udelay(7);
+       sdelay(7000);
 
        /* enable the VCO and disable the external regulator to PLL */
        writel((readl(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0) &
@@ -878,19 +891,19 @@ static int cm_full_cfg(struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
        writel(CLKMGR_MAINPLL_BYPASS_RESET,
               socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_BYPASSR);
        /* wait till Clock Manager is not busy */
-       cm_wait_for_fsm();
+       cm_busy_wait_for_fsm();
 
        /* release perpll from bypass */
        writel(CLKMGR_PERPLL_BYPASS_RESET,
               socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_BYPASSR);
        /* wait till Clock Manager is not busy */
-       cm_wait_for_fsm();
+       cm_busy_wait_for_fsm();
 
        /* clear boot mode */
        clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_CTRL,
                     CLKMGR_CLKMGR_CTL_BOOTMOD_SET_MSK);
        /* wait till Clock Manager is not busy */
-       cm_wait_for_fsm();
+       cm_busy_wait_for_fsm();
 
        /* At here, we need to ramp to final value if needed */
        if (pll_ramp_main_hz != 0)