1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Zynq PLL driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2013 Xilinx
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Sören Brinkmann <soren.brinkmann@xilinx.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun #include <linux/clk/zynq.h>
10*4882a593Smuzhiyun #include <linux/clk-provider.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/io.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun /**
15*4882a593Smuzhiyun * struct zynq_pll
16*4882a593Smuzhiyun * @hw: Handle between common and hardware-specific interfaces
17*4882a593Smuzhiyun * @pll_ctrl: PLL control register
18*4882a593Smuzhiyun * @pll_status: PLL status register
19*4882a593Smuzhiyun * @lock: Register lock
20*4882a593Smuzhiyun * @lockbit: Indicates the associated PLL_LOCKED bit in the PLL status
21*4882a593Smuzhiyun * register.
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun struct zynq_pll {
24*4882a593Smuzhiyun struct clk_hw hw;
25*4882a593Smuzhiyun void __iomem *pll_ctrl;
26*4882a593Smuzhiyun void __iomem *pll_status;
27*4882a593Smuzhiyun spinlock_t *lock;
28*4882a593Smuzhiyun u8 lockbit;
29*4882a593Smuzhiyun };
30*4882a593Smuzhiyun #define to_zynq_pll(_hw) container_of(_hw, struct zynq_pll, hw)
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /* Register bitfield defines */
33*4882a593Smuzhiyun #define PLLCTRL_FBDIV_MASK 0x7f000
34*4882a593Smuzhiyun #define PLLCTRL_FBDIV_SHIFT 12
35*4882a593Smuzhiyun #define PLLCTRL_BPQUAL_MASK (1 << 3)
36*4882a593Smuzhiyun #define PLLCTRL_PWRDWN_MASK 2
37*4882a593Smuzhiyun #define PLLCTRL_PWRDWN_SHIFT 1
38*4882a593Smuzhiyun #define PLLCTRL_RESET_MASK 1
39*4882a593Smuzhiyun #define PLLCTRL_RESET_SHIFT 0
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #define PLL_FBDIV_MIN 13
42*4882a593Smuzhiyun #define PLL_FBDIV_MAX 66
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /**
45*4882a593Smuzhiyun * zynq_pll_round_rate() - Round a clock frequency
46*4882a593Smuzhiyun * @hw: Handle between common and hardware-specific interfaces
47*4882a593Smuzhiyun * @rate: Desired clock frequency
48*4882a593Smuzhiyun * @prate: Clock frequency of parent clock
49*4882a593Smuzhiyun * Returns frequency closest to @rate the hardware can generate.
50*4882a593Smuzhiyun */
zynq_pll_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)51*4882a593Smuzhiyun static long zynq_pll_round_rate(struct clk_hw *hw, unsigned long rate,
52*4882a593Smuzhiyun unsigned long *prate)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun u32 fbdiv;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun fbdiv = DIV_ROUND_CLOSEST(rate, *prate);
57*4882a593Smuzhiyun if (fbdiv < PLL_FBDIV_MIN)
58*4882a593Smuzhiyun fbdiv = PLL_FBDIV_MIN;
59*4882a593Smuzhiyun else if (fbdiv > PLL_FBDIV_MAX)
60*4882a593Smuzhiyun fbdiv = PLL_FBDIV_MAX;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun return *prate * fbdiv;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun /**
66*4882a593Smuzhiyun * zynq_pll_recalc_rate() - Recalculate clock frequency
67*4882a593Smuzhiyun * @hw: Handle between common and hardware-specific interfaces
68*4882a593Smuzhiyun * @parent_rate: Clock frequency of parent clock
69*4882a593Smuzhiyun * Returns current clock frequency.
70*4882a593Smuzhiyun */
zynq_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)71*4882a593Smuzhiyun static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
72*4882a593Smuzhiyun unsigned long parent_rate)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun struct zynq_pll *clk = to_zynq_pll(hw);
75*4882a593Smuzhiyun u32 fbdiv;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun /*
78*4882a593Smuzhiyun * makes probably sense to redundantly save fbdiv in the struct
79*4882a593Smuzhiyun * zynq_pll to save the IO access.
80*4882a593Smuzhiyun */
81*4882a593Smuzhiyun fbdiv = (readl(clk->pll_ctrl) & PLLCTRL_FBDIV_MASK) >>
82*4882a593Smuzhiyun PLLCTRL_FBDIV_SHIFT;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun return parent_rate * fbdiv;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /**
88*4882a593Smuzhiyun * zynq_pll_is_enabled - Check if a clock is enabled
89*4882a593Smuzhiyun * @hw: Handle between common and hardware-specific interfaces
90*4882a593Smuzhiyun * Returns 1 if the clock is enabled, 0 otherwise.
91*4882a593Smuzhiyun *
92*4882a593Smuzhiyun * Not sure this is a good idea, but since disabled means bypassed for
93*4882a593Smuzhiyun * this clock implementation we say we are always enabled.
94*4882a593Smuzhiyun */
zynq_pll_is_enabled(struct clk_hw * hw)95*4882a593Smuzhiyun static int zynq_pll_is_enabled(struct clk_hw *hw)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun unsigned long flags = 0;
98*4882a593Smuzhiyun u32 reg;
99*4882a593Smuzhiyun struct zynq_pll *clk = to_zynq_pll(hw);
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun spin_lock_irqsave(clk->lock, flags);
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun reg = readl(clk->pll_ctrl);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun spin_unlock_irqrestore(clk->lock, flags);
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun return !(reg & (PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK));
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun /**
111*4882a593Smuzhiyun * zynq_pll_enable - Enable clock
112*4882a593Smuzhiyun * @hw: Handle between common and hardware-specific interfaces
113*4882a593Smuzhiyun * Returns 0 on success
114*4882a593Smuzhiyun */
zynq_pll_enable(struct clk_hw * hw)115*4882a593Smuzhiyun static int zynq_pll_enable(struct clk_hw *hw)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun unsigned long flags = 0;
118*4882a593Smuzhiyun u32 reg;
119*4882a593Smuzhiyun struct zynq_pll *clk = to_zynq_pll(hw);
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun if (zynq_pll_is_enabled(hw))
122*4882a593Smuzhiyun return 0;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun pr_info("PLL: enable\n");
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun /* Power up PLL and wait for lock */
127*4882a593Smuzhiyun spin_lock_irqsave(clk->lock, flags);
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun reg = readl(clk->pll_ctrl);
130*4882a593Smuzhiyun reg &= ~(PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK);
131*4882a593Smuzhiyun writel(reg, clk->pll_ctrl);
132*4882a593Smuzhiyun while (!(readl(clk->pll_status) & (1 << clk->lockbit)))
133*4882a593Smuzhiyun ;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun spin_unlock_irqrestore(clk->lock, flags);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun return 0;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /**
141*4882a593Smuzhiyun * zynq_pll_disable - Disable clock
142*4882a593Smuzhiyun * @hw: Handle between common and hardware-specific interfaces
143*4882a593Smuzhiyun * Returns 0 on success
144*4882a593Smuzhiyun */
zynq_pll_disable(struct clk_hw * hw)145*4882a593Smuzhiyun static void zynq_pll_disable(struct clk_hw *hw)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun unsigned long flags = 0;
148*4882a593Smuzhiyun u32 reg;
149*4882a593Smuzhiyun struct zynq_pll *clk = to_zynq_pll(hw);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun if (!zynq_pll_is_enabled(hw))
152*4882a593Smuzhiyun return;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun pr_info("PLL: shutdown\n");
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /* shut down PLL */
157*4882a593Smuzhiyun spin_lock_irqsave(clk->lock, flags);
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun reg = readl(clk->pll_ctrl);
160*4882a593Smuzhiyun reg |= PLLCTRL_RESET_MASK | PLLCTRL_PWRDWN_MASK;
161*4882a593Smuzhiyun writel(reg, clk->pll_ctrl);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun spin_unlock_irqrestore(clk->lock, flags);
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun static const struct clk_ops zynq_pll_ops = {
167*4882a593Smuzhiyun .enable = zynq_pll_enable,
168*4882a593Smuzhiyun .disable = zynq_pll_disable,
169*4882a593Smuzhiyun .is_enabled = zynq_pll_is_enabled,
170*4882a593Smuzhiyun .round_rate = zynq_pll_round_rate,
171*4882a593Smuzhiyun .recalc_rate = zynq_pll_recalc_rate
172*4882a593Smuzhiyun };
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun /**
175*4882a593Smuzhiyun * clk_register_zynq_pll() - Register PLL with the clock framework
176*4882a593Smuzhiyun * @name PLL name
177*4882a593Smuzhiyun * @parent Parent clock name
178*4882a593Smuzhiyun * @pll_ctrl Pointer to PLL control register
179*4882a593Smuzhiyun * @pll_status Pointer to PLL status register
180*4882a593Smuzhiyun * @lock_index Bit index to this PLL's lock status bit in @pll_status
181*4882a593Smuzhiyun * @lock Register lock
182*4882a593Smuzhiyun * Returns handle to the registered clock.
183*4882a593Smuzhiyun */
clk_register_zynq_pll(const char * name,const char * parent,void __iomem * pll_ctrl,void __iomem * pll_status,u8 lock_index,spinlock_t * lock)184*4882a593Smuzhiyun struct clk *clk_register_zynq_pll(const char *name, const char *parent,
185*4882a593Smuzhiyun void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index,
186*4882a593Smuzhiyun spinlock_t *lock)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun struct zynq_pll *pll;
189*4882a593Smuzhiyun struct clk *clk;
190*4882a593Smuzhiyun u32 reg;
191*4882a593Smuzhiyun const char *parent_arr[1] = {parent};
192*4882a593Smuzhiyun unsigned long flags = 0;
193*4882a593Smuzhiyun struct clk_init_data initd = {
194*4882a593Smuzhiyun .name = name,
195*4882a593Smuzhiyun .parent_names = parent_arr,
196*4882a593Smuzhiyun .ops = &zynq_pll_ops,
197*4882a593Smuzhiyun .num_parents = 1,
198*4882a593Smuzhiyun .flags = 0
199*4882a593Smuzhiyun };
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun pll = kmalloc(sizeof(*pll), GFP_KERNEL);
202*4882a593Smuzhiyun if (!pll)
203*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun /* Populate the struct */
206*4882a593Smuzhiyun pll->hw.init = &initd;
207*4882a593Smuzhiyun pll->pll_ctrl = pll_ctrl;
208*4882a593Smuzhiyun pll->pll_status = pll_status;
209*4882a593Smuzhiyun pll->lockbit = lock_index;
210*4882a593Smuzhiyun pll->lock = lock;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun spin_lock_irqsave(pll->lock, flags);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun reg = readl(pll->pll_ctrl);
215*4882a593Smuzhiyun reg &= ~PLLCTRL_BPQUAL_MASK;
216*4882a593Smuzhiyun writel(reg, pll->pll_ctrl);
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun spin_unlock_irqrestore(pll->lock, flags);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun clk = clk_register(NULL, &pll->hw);
221*4882a593Smuzhiyun if (WARN_ON(IS_ERR(clk)))
222*4882a593Smuzhiyun goto free_pll;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun return clk;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun free_pll:
227*4882a593Smuzhiyun kfree(pll);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun return clk;
230*4882a593Smuzhiyun }
231