0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/clk/zynq.h>
0010 #include <linux/clk-provider.h>
0011 #include <linux/slab.h>
0012 #include <linux/io.h>
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 struct zynq_pll {
0024 struct clk_hw hw;
0025 void __iomem *pll_ctrl;
0026 void __iomem *pll_status;
0027 spinlock_t *lock;
0028 u8 lockbit;
0029 };
0030 #define to_zynq_pll(_hw) container_of(_hw, struct zynq_pll, hw)
0031
0032
0033 #define PLLCTRL_FBDIV_MASK 0x7f000
0034 #define PLLCTRL_FBDIV_SHIFT 12
0035 #define PLLCTRL_BPQUAL_MASK (1 << 3)
0036 #define PLLCTRL_PWRDWN_MASK 2
0037 #define PLLCTRL_PWRDWN_SHIFT 1
0038 #define PLLCTRL_RESET_MASK 1
0039 #define PLLCTRL_RESET_SHIFT 0
0040
0041 #define PLL_FBDIV_MIN 13
0042 #define PLL_FBDIV_MAX 66
0043
0044
0045
0046
0047
0048
0049
0050
0051 static long zynq_pll_round_rate(struct clk_hw *hw, unsigned long rate,
0052 unsigned long *prate)
0053 {
0054 u32 fbdiv;
0055
0056 fbdiv = DIV_ROUND_CLOSEST(rate, *prate);
0057 if (fbdiv < PLL_FBDIV_MIN)
0058 fbdiv = PLL_FBDIV_MIN;
0059 else if (fbdiv > PLL_FBDIV_MAX)
0060 fbdiv = PLL_FBDIV_MAX;
0061
0062 return *prate * fbdiv;
0063 }
0064
0065
0066
0067
0068
0069
0070
0071 static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
0072 unsigned long parent_rate)
0073 {
0074 struct zynq_pll *clk = to_zynq_pll(hw);
0075 u32 fbdiv;
0076
0077
0078
0079
0080
0081 fbdiv = (readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >>
0082 PLLCTRL_FBDIV_SHIFT;
0083
0084 return parent_rate * fbdiv;
0085 }
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 static int zynq_pll_is_enabled(struct clk_hw *hw)
0096 {
0097 unsigned long flags = 0;
0098 u32 reg;
0099 struct zynq_pll *clk = to_zynq_pll(hw);
0100
0101 spin_lock_irqsave(clk->lock, flags);
0102
0103 reg = readl(clk->pll_ctrl);
0104
0105 spin_unlock_irqrestore(clk->lock, flags);
0106
0107 return !(reg & (PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK));
0108 }
0109
0110
0111
0112
0113
0114
0115 static int zynq_pll_enable(struct clk_hw *hw)
0116 {
0117 unsigned long flags = 0;
0118 u32 reg;
0119 struct zynq_pll *clk = to_zynq_pll(hw);
0120
0121 if (zynq_pll_is_enabled(hw))
0122 return 0;
0123
0124 pr_info("PLL: enable\n");
0125
0126
0127 spin_lock_irqsave(clk->lock, flags);
0128
0129 reg = readl(clk->pll_ctrl);
0130 reg &= ~(PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK);
0131 writel(reg, clk->pll_ctrl);
0132 while (!(readl(clk->pll_status) & (1 << clk->lockbit)))
0133 ;
0134
0135 spin_unlock_irqrestore(clk->lock, flags);
0136
0137 return 0;
0138 }
0139
0140
0141
0142
0143
0144
0145 static void zynq_pll_disable(struct clk_hw *hw)
0146 {
0147 unsigned long flags = 0;
0148 u32 reg;
0149 struct zynq_pll *clk = to_zynq_pll(hw);
0150
0151 if (!zynq_pll_is_enabled(hw))
0152 return;
0153
0154 pr_info("PLL: shutdown\n");
0155
0156
0157 spin_lock_irqsave(clk->lock, flags);
0158
0159 reg = readl(clk->pll_ctrl);
0160 reg |= PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK;
0161 writel(reg, clk->pll_ctrl);
0162
0163 spin_unlock_irqrestore(clk->lock, flags);
0164 }
0165
0166 static const struct clk_ops zynq_pll_ops = {
0167 .enable = zynq_pll_enable,
0168 .disable = zynq_pll_disable,
0169 .is_enabled = zynq_pll_is_enabled,
0170 .round_rate = zynq_pll_round_rate,
0171 .recalc_rate = zynq_pll_recalc_rate
0172 };
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184 struct clk *clk_register_zynq_pll(const char *name, const char *parent,
0185 void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index,
0186 spinlock_t *lock)
0187 {
0188 struct zynq_pll *pll;
0189 struct clk *clk;
0190 u32 reg;
0191 const char *parent_arr[1] = {parent};
0192 unsigned long flags = 0;
0193 struct clk_init_data initd = {
0194 .name = name,
0195 .parent_names = parent_arr,
0196 .ops = &zynq_pll_ops,
0197 .num_parents = 1,
0198 .flags = 0
0199 };
0200
0201 pll = kmalloc(sizeof(*pll), GFP_KERNEL);
0202 if (!pll)
0203 return ERR_PTR(-ENOMEM);
0204
0205
0206 pll->hw.init = &initd;
0207 pll->pll_ctrl = pll_ctrl;
0208 pll->pll_status = pll_status;
0209 pll->lockbit = lock_index;
0210 pll->lock = lock;
0211
0212 spin_lock_irqsave(pll->lock, flags);
0213
0214 reg = readl(pll->pll_ctrl);
0215 reg &= ~PLLCTRL_BPQUAL_MASK;
0216 writel(reg, pll->pll_ctrl);
0217
0218 spin_unlock_irqrestore(pll->lock, flags);
0219
0220 clk = clk_register(NULL, &pll->hw);
0221 if (WARN_ON(IS_ERR(clk)))
0222 goto free_pll;
0223
0224 return clk;
0225
0226 free_pll:
0227 kfree(pll);
0228
0229 return clk;
0230 }