xref: /OK3568_Linux_fs/kernel/drivers/clk/zynq/pll.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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