Loading drivers/clk/qcom/clock-pll.c +68 −8 Original line number Diff line number Diff line Loading @@ -38,7 +38,8 @@ (x)->config_alt_reg) #define PLL_CFG_CTL_REG(x) (*(x)->base + (unsigned long) \ (x)->config_ctl_reg) #define PLL_TEST_CTL_LO_REG(x) (*(x)->base + (unsigned long) \ (x)->test_ctl_lo_reg) static DEFINE_SPINLOCK(pll_reg_lock); #define ENABLE_WAIT_MAX_LOOPS 200 Loading Loading @@ -170,9 +171,6 @@ static int sr2_pll_clk_enable(struct clk *c) spin_lock_irqsave(&pll_reg_lock, flags); if (pll->masks.apc_pdn_mask) mode &= ~pll->masks.apc_pdn_mask; /* Disable PLL bypass mode. */ mode |= PLL_BYPASSNL; writel_relaxed(mode, PLL_MODE_REG(pll)); Loading Loading @@ -238,6 +236,12 @@ static void __variable_rate_pll_init(struct clk *c) regval &= ~pll->masks.mn_en_mask; writel_relaxed(regval, PLL_CONFIG_REG(pll)); regval = readl_relaxed(PLL_MODE_REG(pll)); if (pll->masks.apc_pdn_mask) regval &= ~pll->masks.apc_pdn_mask; writel_relaxed(regval, PLL_MODE_REG(pll)); writel_relaxed(pll->vals.alpha_val, PLL_ALPHA_REG(pll)); writel_relaxed(pll->vals.config_ctl_val, PLL_CFG_CTL_REG(pll)); Loading @@ -246,10 +250,67 @@ static void __variable_rate_pll_init(struct clk *c) static int variable_rate_pll_clk_enable(struct clk *c) { unsigned long flags; struct pll_clk *pll = to_pll_clk(c); int ret = 0, count; u32 mode; u32 lockmask = pll->masks.lock_mask ?: PLL_LOCKED_BIT; spin_lock_irqsave(&pll_reg_lock, flags); if (unlikely(!to_pll_clk(c)->inited)) __variable_rate_pll_init(c); return sr2_pll_clk_enable(c); mode = readl_relaxed(PLL_MODE_REG(pll)); /* Set test control bits as required by HW doc */ if (pll->test_ctl_lo_reg && pll->vals.test_ctl_lo_val) writel_relaxed(pll->vals.test_ctl_lo_val, PLL_TEST_CTL_LO_REG(pll)); /* Disable PLL bypass mode. */ mode |= PLL_BYPASSNL; writel_relaxed(mode, PLL_MODE_REG(pll)); /* * H/W requires a 5us delay between disabling the bypass and * de-asserting the reset. Use 10us to be sure. */ mb(); udelay(10); /* De-assert active-low PLL reset. */ mode |= PLL_RESET_N; writel_relaxed(mode, PLL_MODE_REG(pll)); /* 5us delay mandated by HPG. Use 10 to be sure. */ mb(); udelay(10); /* Clear test control bits */ if (pll->test_ctl_lo_reg && pll->vals.test_ctl_lo_val) writel_relaxed(0x0, PLL_TEST_CTL_LO_REG(pll)); /* Wait for pll to lock. */ for (count = ENABLE_WAIT_MAX_LOOPS; count > 0; count--) { if (readl_relaxed(PLL_STATUS_REG(pll)) & lockmask) break; udelay(1); } if (!(readl_relaxed(PLL_STATUS_REG(pll)) & lockmask)) pr_err("PLL %s didn't lock after enabling it!\n", c->dbg_name); /* Enable PLL output. */ mode |= PLL_OUTCTRL; writel_relaxed(mode, PLL_MODE_REG(pll)); /* Ensure that the write above goes through before returning. */ mb(); spin_unlock_irqrestore(&pll_reg_lock, flags); return ret; } static void __pll_clk_enable_reg(void __iomem *mode_reg) Loading Loading @@ -294,11 +355,10 @@ static int local_pll_clk_enable(struct clk *c) return 0; } static void __pll_clk_disable_reg(void __iomem *mode_reg, u32 apc_pdn_mask) static void __pll_clk_disable_reg(void __iomem *mode_reg) { u32 mode = readl_relaxed(mode_reg); mode &= ~PLL_MODE_MASK; mode |= apc_pdn_mask; writel_relaxed(mode, mode_reg); } Loading @@ -312,7 +372,7 @@ static void local_pll_clk_disable(struct clk *c) * the bypass mode, and assert the reset. */ spin_lock_irqsave(&pll_reg_lock, flags); __pll_clk_disable_reg(PLL_MODE_REG(pll), pll->masks.apc_pdn_mask); __pll_clk_disable_reg(PLL_MODE_REG(pll)); spin_unlock_irqrestore(&pll_reg_lock, flags); } Loading include/soc/qcom/clock-pll.h +2 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ struct pll_config_vals { u32 post_div_masked; u32 pre_div_masked; u32 config_ctl_val; u32 test_ctl_lo_val; u32 alpha_val; bool enable_mn; }; Loading Loading @@ -129,6 +130,7 @@ struct pll_clk { void __iomem *const config_reg; void __iomem *const config_ctl_reg; void __iomem *const status_reg; void __iomem *const test_ctl_lo_reg; struct pll_config_masks masks; struct pll_config_vals vals; Loading Loading
drivers/clk/qcom/clock-pll.c +68 −8 Original line number Diff line number Diff line Loading @@ -38,7 +38,8 @@ (x)->config_alt_reg) #define PLL_CFG_CTL_REG(x) (*(x)->base + (unsigned long) \ (x)->config_ctl_reg) #define PLL_TEST_CTL_LO_REG(x) (*(x)->base + (unsigned long) \ (x)->test_ctl_lo_reg) static DEFINE_SPINLOCK(pll_reg_lock); #define ENABLE_WAIT_MAX_LOOPS 200 Loading Loading @@ -170,9 +171,6 @@ static int sr2_pll_clk_enable(struct clk *c) spin_lock_irqsave(&pll_reg_lock, flags); if (pll->masks.apc_pdn_mask) mode &= ~pll->masks.apc_pdn_mask; /* Disable PLL bypass mode. */ mode |= PLL_BYPASSNL; writel_relaxed(mode, PLL_MODE_REG(pll)); Loading Loading @@ -238,6 +236,12 @@ static void __variable_rate_pll_init(struct clk *c) regval &= ~pll->masks.mn_en_mask; writel_relaxed(regval, PLL_CONFIG_REG(pll)); regval = readl_relaxed(PLL_MODE_REG(pll)); if (pll->masks.apc_pdn_mask) regval &= ~pll->masks.apc_pdn_mask; writel_relaxed(regval, PLL_MODE_REG(pll)); writel_relaxed(pll->vals.alpha_val, PLL_ALPHA_REG(pll)); writel_relaxed(pll->vals.config_ctl_val, PLL_CFG_CTL_REG(pll)); Loading @@ -246,10 +250,67 @@ static void __variable_rate_pll_init(struct clk *c) static int variable_rate_pll_clk_enable(struct clk *c) { unsigned long flags; struct pll_clk *pll = to_pll_clk(c); int ret = 0, count; u32 mode; u32 lockmask = pll->masks.lock_mask ?: PLL_LOCKED_BIT; spin_lock_irqsave(&pll_reg_lock, flags); if (unlikely(!to_pll_clk(c)->inited)) __variable_rate_pll_init(c); return sr2_pll_clk_enable(c); mode = readl_relaxed(PLL_MODE_REG(pll)); /* Set test control bits as required by HW doc */ if (pll->test_ctl_lo_reg && pll->vals.test_ctl_lo_val) writel_relaxed(pll->vals.test_ctl_lo_val, PLL_TEST_CTL_LO_REG(pll)); /* Disable PLL bypass mode. */ mode |= PLL_BYPASSNL; writel_relaxed(mode, PLL_MODE_REG(pll)); /* * H/W requires a 5us delay between disabling the bypass and * de-asserting the reset. Use 10us to be sure. */ mb(); udelay(10); /* De-assert active-low PLL reset. */ mode |= PLL_RESET_N; writel_relaxed(mode, PLL_MODE_REG(pll)); /* 5us delay mandated by HPG. Use 10 to be sure. */ mb(); udelay(10); /* Clear test control bits */ if (pll->test_ctl_lo_reg && pll->vals.test_ctl_lo_val) writel_relaxed(0x0, PLL_TEST_CTL_LO_REG(pll)); /* Wait for pll to lock. */ for (count = ENABLE_WAIT_MAX_LOOPS; count > 0; count--) { if (readl_relaxed(PLL_STATUS_REG(pll)) & lockmask) break; udelay(1); } if (!(readl_relaxed(PLL_STATUS_REG(pll)) & lockmask)) pr_err("PLL %s didn't lock after enabling it!\n", c->dbg_name); /* Enable PLL output. */ mode |= PLL_OUTCTRL; writel_relaxed(mode, PLL_MODE_REG(pll)); /* Ensure that the write above goes through before returning. */ mb(); spin_unlock_irqrestore(&pll_reg_lock, flags); return ret; } static void __pll_clk_enable_reg(void __iomem *mode_reg) Loading Loading @@ -294,11 +355,10 @@ static int local_pll_clk_enable(struct clk *c) return 0; } static void __pll_clk_disable_reg(void __iomem *mode_reg, u32 apc_pdn_mask) static void __pll_clk_disable_reg(void __iomem *mode_reg) { u32 mode = readl_relaxed(mode_reg); mode &= ~PLL_MODE_MASK; mode |= apc_pdn_mask; writel_relaxed(mode, mode_reg); } Loading @@ -312,7 +372,7 @@ static void local_pll_clk_disable(struct clk *c) * the bypass mode, and assert the reset. */ spin_lock_irqsave(&pll_reg_lock, flags); __pll_clk_disable_reg(PLL_MODE_REG(pll), pll->masks.apc_pdn_mask); __pll_clk_disable_reg(PLL_MODE_REG(pll)); spin_unlock_irqrestore(&pll_reg_lock, flags); } Loading
include/soc/qcom/clock-pll.h +2 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ struct pll_config_vals { u32 post_div_masked; u32 pre_div_masked; u32 config_ctl_val; u32 test_ctl_lo_val; u32 alpha_val; bool enable_mn; }; Loading Loading @@ -129,6 +130,7 @@ struct pll_clk { void __iomem *const config_reg; void __iomem *const config_ctl_reg; void __iomem *const status_reg; void __iomem *const test_ctl_lo_reg; struct pll_config_masks masks; struct pll_config_vals vals; Loading