clk: tm2: fix pcie pll lock failed [1/1]
authorJian Hu <jian.hu@amlogic.com>
Fri, 6 Sep 2019 11:47:02 +0000 (19:47 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Wed, 11 Sep 2019 02:33:08 +0000 (19:33 -0700)
PD#SWPL-11934

Problem:
pcie pll lock failed some times

Solution:
1.add retry mechanism when pcie lock failed
2.add protection mechanism for all plls

Verify:
test passed on tm2 ab311

Change-Id: Id34e87d84e2bc2368c074556f500f8af1f2a4088
Signed-off-by: Jian Hu <jian.hu@amlogic.com>
drivers/amlogic/clk/tl1/tl1_clk-pll.c

index 473e644..b08c29f 100644 (file)
@@ -231,6 +231,7 @@ static int meson_tl1_pll_set_rate(struct clk_hw *hw, unsigned long rate,
        u32 reg;
        unsigned long flags = 0;
        void *cntlbase;
+       int j = 10;
 
        if (parent_rate == 0 || rate == 0)
                return -EINVAL;
@@ -263,110 +264,117 @@ static int meson_tl1_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 
        cntlbase = pll->base + p->reg_off;
 
-
-       if (!strcmp(clk_hw_get_name(hw), "sys_pll")) {
-               writel((readl(cntlbase) | MESON_PLL_RESET)
-                       & (~MESON_PLL_ENABLE), cntlbase);
-               writel(TL1_SYS_PLL_CNTL1,
-                               cntlbase + (unsigned long)(1*4));
-               writel(TL1_SYS_PLL_CNTL2,
-                               cntlbase + (unsigned long)(2*4));
-               writel(TL1_SYS_PLL_CNTL3,
-                               cntlbase + (unsigned long)(3*4));
-               writel(TL1_SYS_PLL_CNTL4,
-                               cntlbase + (unsigned long)(4*4));
-               writel(TL1_SYS_PLL_CNTL5,
-                               cntlbase + (unsigned long)(5*4));
-               writel(TL1_PLL_CNTL6,
-                               cntlbase + (unsigned long)(6*4));
-               udelay(10);
-       }  else if (!strcmp(clk_hw_get_name(hw), "gp0_pll") ||
-                               !strcmp(clk_hw_get_name(hw), "gp1_pll")) {
-               writel((readl(cntlbase) | MESON_PLL_RESET)
-                       & (~MESON_PLL_ENABLE), cntlbase);
-               writel(TL1_GP0_PLL_CNTL1,
-                               cntlbase + (unsigned long)(1*4));
-               writel(TL1_GP0_PLL_CNTL2,
-                               cntlbase + (unsigned long)(2*4));
-               writel(TL1_GP0_PLL_CNTL3,
-                               cntlbase + (unsigned long)(3*4));
-               writel(TL1_GP0_PLL_CNTL4,
-                               cntlbase + (unsigned long)(4*4));
-               writel(TL1_GP0_PLL_CNTL5,
-                               cntlbase + (unsigned long)(5*4));
-               writel(TL1_PLL_CNTL6,
-                               cntlbase + (unsigned long)(6*4));
-               udelay(10);
-       } else if (!strcmp(clk_hw_get_name(hw), "hifi_pll")) {
-               writel((readl(cntlbase) | MESON_PLL_RESET)
-                       & (~MESON_PLL_ENABLE), cntlbase);
-               writel(TL1_HIFI_PLL_CNTL1,
-                               cntlbase + (unsigned long)(1*4));
-               writel(TL1_HIFI_PLL_CNTL2,
-                               cntlbase + (unsigned long)(2*4));
-               writel(TL1_HIFI_PLL_CNTL3,
-                               cntlbase + (unsigned long)(3*4));
-               writel(TL1_HIFI_PLL_CNTL4,
-                               cntlbase + (unsigned long)(4*4));
-               writel(TL1_HIFI_PLL_CNTL5,
-                               cntlbase + (unsigned long)(5*4));
-               writel(TL1_PLL_CNTL6,
-                               cntlbase + (unsigned long)(6*4));
-               udelay(10);
-       } else if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) {
-               writel(TM2_PCIE_PLL_CNTL0_0,
-                       cntlbase + (unsigned long)(0*4));
-               writel(TM2_PCIE_PLL_CNTL0_1,
-                       cntlbase + (unsigned long)(0*4));
-               writel(TM2_PCIE_PLL_CNTL1,
-                       cntlbase + (unsigned long)(1*4));
-               writel(TM2_PCIE_PLL_CNTL2,
-                       cntlbase + (unsigned long)(7*4));
-               writel(TM2_PCIE_PLL_CNTL3,
-                       cntlbase + (unsigned long)(8*4));
-               writel(TM2_PCIE_PLL_CNTL4,
-                       cntlbase + (unsigned long)(53*4));
-               writel(TM2_PCIE_PLL_CNTL5,
-                       cntlbase + (unsigned long)(54*4));
-               writel(TM2_PCIE_PLL_CNTL5_,
-                       cntlbase + (unsigned long)(54*4));
-               udelay(20);
-               writel(TM2_PCIE_PLL_CNTL4_,
-                       cntlbase + (unsigned long)(53*4));
-               udelay(10);
-               /*set pcie_apll_afc_start bit*/
-               writel(TM2_PCIE_PLL_CNTL0_2,
-                       cntlbase + (unsigned long)(0*4));
-               writel(TM2_PCIE_PLL_CNTL0_3,
-                       cntlbase + (unsigned long)(0*4));
-               udelay(20);
-               writel(TM2_PCIE_PLL_CNTL0_4,
-                       cntlbase + (unsigned long)(0*4));
-               writel(TM2_PCIE_PLL_CNTL2_,
-                       cntlbase + (unsigned long)(7*4));
-       } else if (!strcmp(clk_hw_get_name(hw), "fixed_pll")) {
-               writel((readl(cntlbase) | MESON_PLL_RESET)
-                       & (~MESON_PLL_ENABLE), cntlbase);
-
-               udelay(100);
-               writel(TL1_FIXED_PLL_CNTL1,
-                               cntlbase + (unsigned long)(1*4));
-               writel(TL1_FIXED_PLL_CNTL2,
-                               cntlbase + (unsigned long)(2*4));
-               writel(TL1_FIXED_PLL_CNTL3,
-                               cntlbase + (unsigned long)(3*4));
-               writel(TL1_FIXED_PLL_CNTL4,
-                               cntlbase + (unsigned long)(4*4));
-               writel(TL1_FIXED_PLL_CNTL5,
-                               cntlbase + (unsigned long)(5*4));
-               writel(TL1_FIXED_PLL_CNTL6,
-                               cntlbase + (unsigned long)(6*4));
-               udelay(10);
-       } else {
-               pr_err("%s: %s pll not found!!!\n",
-                       __func__, clk_hw_get_name(hw));
-               return -EINVAL;
-       }
+       do {
+               if (!strcmp(clk_hw_get_name(hw), "sys_pll")) {
+                       writel((readl(cntlbase) | MESON_PLL_RESET)
+                               & (~MESON_PLL_ENABLE), cntlbase);
+                       writel(TL1_SYS_PLL_CNTL1,
+                              cntlbase + (unsigned long)(1 * 4));
+                       writel(TL1_SYS_PLL_CNTL2,
+                              cntlbase + (unsigned long)(2 * 4));
+                       writel(TL1_SYS_PLL_CNTL3,
+                              cntlbase + (unsigned long)(3 * 4));
+                       writel(TL1_SYS_PLL_CNTL4,
+                              cntlbase + (unsigned long)(4 * 4));
+                       writel(TL1_SYS_PLL_CNTL5,
+                              cntlbase + (unsigned long)(5 * 4));
+                       writel(TL1_PLL_CNTL6,
+                              cntlbase + (unsigned long)(6 * 4));
+                       udelay(10);
+               }  else if (!strcmp(clk_hw_get_name(hw), "gp0_pll") ||
+                           !strcmp(clk_hw_get_name(hw), "gp1_pll")) {
+                       writel((readl(cntlbase) | MESON_PLL_RESET)
+                              & (~MESON_PLL_ENABLE), cntlbase);
+                       writel(TL1_GP0_PLL_CNTL1,
+                              cntlbase + (unsigned long)(1 * 4));
+                       writel(TL1_GP0_PLL_CNTL2,
+                              cntlbase + (unsigned long)(2 * 4));
+                       writel(TL1_GP0_PLL_CNTL3,
+                              cntlbase + (unsigned long)(3 * 4));
+                       writel(TL1_GP0_PLL_CNTL4,
+                              cntlbase + (unsigned long)(4 * 4));
+                       writel(TL1_GP0_PLL_CNTL5,
+                              cntlbase + (unsigned long)(5 * 4));
+                       writel(TL1_PLL_CNTL6,
+                              cntlbase + (unsigned long)(6 * 4));
+                       udelay(10);
+               } else if (!strcmp(clk_hw_get_name(hw), "hifi_pll")) {
+                       writel((readl(cntlbase) | MESON_PLL_RESET)
+                              & (~MESON_PLL_ENABLE), cntlbase);
+                       writel(TL1_HIFI_PLL_CNTL1,
+                              cntlbase + (unsigned long)(1 * 4));
+                       writel(TL1_HIFI_PLL_CNTL2,
+                              cntlbase + (unsigned long)(2 * 4));
+                       writel(TL1_HIFI_PLL_CNTL3,
+                              cntlbase + (unsigned long)(3 * 4));
+                       writel(TL1_HIFI_PLL_CNTL4,
+                              cntlbase + (unsigned long)(4 * 4));
+                       writel(TL1_HIFI_PLL_CNTL5,
+                              cntlbase + (unsigned long)(5 * 4));
+                       writel(TL1_PLL_CNTL6,
+                              cntlbase + (unsigned long)(6 * 4));
+                       udelay(10);
+               } else if (!strcmp(clk_hw_get_name(hw), "pcie_pll")) {
+                       writel(TM2_PCIE_PLL_CNTL0_0,
+                              cntlbase + (unsigned long)(0 * 4));
+                       writel(TM2_PCIE_PLL_CNTL0_1,
+                              cntlbase + (unsigned long)(0 * 4));
+                       writel(TM2_PCIE_PLL_CNTL1,
+                              cntlbase + (unsigned long)(1 * 4));
+                       writel(TM2_PCIE_PLL_CNTL2,
+                              cntlbase + (unsigned long)(7 * 4));
+                       writel(TM2_PCIE_PLL_CNTL3,
+                              cntlbase + (unsigned long)(8 * 4));
+                       writel(TM2_PCIE_PLL_CNTL4,
+                              cntlbase + (unsigned long)(53 * 4));
+                       writel(TM2_PCIE_PLL_CNTL5,
+                              cntlbase + (unsigned long)(54 * 4));
+                       writel(TM2_PCIE_PLL_CNTL5_,
+                              cntlbase + (unsigned long)(54 * 4));
+                       udelay(20);
+                       writel(TM2_PCIE_PLL_CNTL4_,
+                              cntlbase + (unsigned long)(53 * 4));
+                       udelay(10);
+                       /*set pcie_apll_afc_start bit*/
+                       writel(TM2_PCIE_PLL_CNTL0_2,
+                              cntlbase + (unsigned long)(0 * 4));
+                       writel(TM2_PCIE_PLL_CNTL0_3,
+                              cntlbase + (unsigned long)(0 * 4));
+                       udelay(20);
+                       writel(TM2_PCIE_PLL_CNTL0_4,
+                              cntlbase + (unsigned long)(0 * 4));
+                       writel(TM2_PCIE_PLL_CNTL2_,
+                              cntlbase + (unsigned long)(7 * 4));
+               } else if (!strcmp(clk_hw_get_name(hw), "fixed_pll")) {
+                       writel((readl(cntlbase) | MESON_PLL_RESET)
+                              & (~MESON_PLL_ENABLE), cntlbase);
+                       udelay(100);
+                       writel(TL1_FIXED_PLL_CNTL1,
+                              cntlbase + (unsigned long)(1 * 4));
+                       writel(TL1_FIXED_PLL_CNTL2,
+                              cntlbase + (unsigned long)(2 * 4));
+                       writel(TL1_FIXED_PLL_CNTL3,
+                              cntlbase + (unsigned long)(3 * 4));
+                       writel(TL1_FIXED_PLL_CNTL4,
+                              cntlbase + (unsigned long)(4 * 4));
+                       writel(TL1_FIXED_PLL_CNTL5,
+                              cntlbase + (unsigned long)(5 * 4));
+                       writel(TL1_FIXED_PLL_CNTL6,
+                              cntlbase + (unsigned long)(6 * 4));
+                       udelay(10);
+               } else {
+                       pr_err("%s: %s pll not found!!!\n",
+                              __func__, clk_hw_get_name(hw));
+                       return -EINVAL;
+               }
+               /* waiting for 50us to check is locked or not */
+               udelay(50);
+               /* lock bit is in the cntlbase */
+               if (readl(cntlbase + (unsigned long)(0 * 4))
+                   & MESON_PLL_LOCK)
+                       break;
+               j--;
+       } while (j);
 
        reg = readl(pll->base + p->reg_off);