xref: /linux/drivers/clk/qcom/clk-hfpll.c (revision 6e7fd890f1d6ac83805409e9c346240de2705584)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2018, The Linux Foundation. All rights reserved.
3 
4 #include <linux/kernel.h>
5 #include <linux/export.h>
6 #include <linux/regmap.h>
7 #include <linux/delay.h>
8 #include <linux/err.h>
9 #include <linux/clk-provider.h>
10 #include <linux/spinlock.h>
11 
12 #include "clk-regmap.h"
13 #include "clk-hfpll.h"
14 
15 #define PLL_OUTCTRL	BIT(0)
16 #define PLL_BYPASSNL	BIT(1)
17 #define PLL_RESET_N	BIT(2)
18 
19 /* Initialize a HFPLL at a given rate and enable it. */
20 static void __clk_hfpll_init_once(struct clk_hw *hw)
21 {
22 	struct clk_hfpll *h = to_clk_hfpll(hw);
23 	struct hfpll_data const *hd = h->d;
24 	struct regmap *regmap = h->clkr.regmap;
25 
26 	if (likely(h->init_done))
27 		return;
28 
29 	/* Configure PLL parameters for integer mode. */
30 	if (hd->config_val)
31 		regmap_write(regmap, hd->config_reg, hd->config_val);
32 	regmap_write(regmap, hd->m_reg, 0);
33 	regmap_write(regmap, hd->n_reg, 1);
34 
35 	if (hd->user_reg) {
36 		u32 regval = hd->user_val;
37 		unsigned long rate;
38 
39 		rate = clk_hw_get_rate(hw);
40 
41 		/* Pick the right VCO. */
42 		if (hd->user_vco_mask && rate > hd->low_vco_max_rate)
43 			regval |= hd->user_vco_mask;
44 		regmap_write(regmap, hd->user_reg, regval);
45 	}
46 
47 	/* Write L_VAL from conf if it exist */
48 	if (hd->l_val)
49 		regmap_write(regmap, hd->l_reg, hd->l_val);
50 
51 	if (hd->droop_reg)
52 		regmap_write(regmap, hd->droop_reg, hd->droop_val);
53 
54 	h->init_done = true;
55 }
56 
57 static void __clk_hfpll_enable(struct clk_hw *hw)
58 {
59 	struct clk_hfpll *h = to_clk_hfpll(hw);
60 	struct hfpll_data const *hd = h->d;
61 	struct regmap *regmap = h->clkr.regmap;
62 	u32 val;
63 
64 	__clk_hfpll_init_once(hw);
65 
66 	/* Disable PLL bypass mode. */
67 	regmap_update_bits(regmap, hd->mode_reg, PLL_BYPASSNL, PLL_BYPASSNL);
68 
69 	/*
70 	 * H/W requires a 5us delay between disabling the bypass and
71 	 * de-asserting the reset. Delay 10us just to be safe.
72 	 */
73 	udelay(10);
74 
75 	/* De-assert active-low PLL reset. */
76 	regmap_update_bits(regmap, hd->mode_reg, PLL_RESET_N, PLL_RESET_N);
77 
78 	/* Wait for PLL to lock. */
79 	if (hd->status_reg)
80 		/*
81 		 * Busy wait. Should never timeout, we add a timeout to
82 		 * prevent any sort of stall.
83 		 */
84 		regmap_read_poll_timeout(regmap, hd->status_reg, val,
85 					 !(val & BIT(hd->lock_bit)), 0,
86 					 100 * USEC_PER_MSEC);
87 	else
88 		udelay(60);
89 
90 	/* Enable PLL output. */
91 	regmap_update_bits(regmap, hd->mode_reg, PLL_OUTCTRL, PLL_OUTCTRL);
92 }
93 
94 /* Enable an already-configured HFPLL. */
95 static int clk_hfpll_enable(struct clk_hw *hw)
96 {
97 	unsigned long flags;
98 	struct clk_hfpll *h = to_clk_hfpll(hw);
99 	struct hfpll_data const *hd = h->d;
100 	struct regmap *regmap = h->clkr.regmap;
101 	u32 mode;
102 
103 	spin_lock_irqsave(&h->lock, flags);
104 	regmap_read(regmap, hd->mode_reg, &mode);
105 	if (!(mode & (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL)))
106 		__clk_hfpll_enable(hw);
107 	spin_unlock_irqrestore(&h->lock, flags);
108 
109 	return 0;
110 }
111 
112 static void __clk_hfpll_disable(struct clk_hfpll *h)
113 {
114 	struct hfpll_data const *hd = h->d;
115 	struct regmap *regmap = h->clkr.regmap;
116 
117 	/*
118 	 * Disable the PLL output, disable test mode, enable the bypass mode,
119 	 * and assert the reset.
120 	 */
121 	regmap_update_bits(regmap, hd->mode_reg,
122 			   PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL, 0);
123 }
124 
125 static void clk_hfpll_disable(struct clk_hw *hw)
126 {
127 	struct clk_hfpll *h = to_clk_hfpll(hw);
128 	unsigned long flags;
129 
130 	spin_lock_irqsave(&h->lock, flags);
131 	__clk_hfpll_disable(h);
132 	spin_unlock_irqrestore(&h->lock, flags);
133 }
134 
135 static int clk_hfpll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
136 {
137 	struct clk_hfpll *h = to_clk_hfpll(hw);
138 	struct hfpll_data const *hd = h->d;
139 	unsigned long rrate;
140 
141 	req->rate = clamp(req->rate, hd->min_rate, hd->max_rate);
142 
143 	rrate = DIV_ROUND_UP(req->rate, req->best_parent_rate) * req->best_parent_rate;
144 	if (rrate > hd->max_rate)
145 		rrate -= req->best_parent_rate;
146 
147 	req->rate = rrate;
148 	return 0;
149 }
150 
151 /*
152  * For optimization reasons, assumes no downstream clocks are actively using
153  * it.
154  */
155 static int clk_hfpll_set_rate(struct clk_hw *hw, unsigned long rate,
156 			      unsigned long parent_rate)
157 {
158 	struct clk_hfpll *h = to_clk_hfpll(hw);
159 	struct hfpll_data const *hd = h->d;
160 	struct regmap *regmap = h->clkr.regmap;
161 	unsigned long flags;
162 	u32 l_val, val;
163 	bool enabled;
164 
165 	l_val = rate / parent_rate;
166 
167 	spin_lock_irqsave(&h->lock, flags);
168 
169 	enabled = __clk_is_enabled(hw->clk);
170 	if (enabled)
171 		__clk_hfpll_disable(h);
172 
173 	/* Pick the right VCO. */
174 	if (hd->user_reg && hd->user_vco_mask) {
175 		regmap_read(regmap, hd->user_reg, &val);
176 		if (rate <= hd->low_vco_max_rate)
177 			val &= ~hd->user_vco_mask;
178 		else
179 			val |= hd->user_vco_mask;
180 		regmap_write(regmap, hd->user_reg, val);
181 	}
182 
183 	regmap_write(regmap, hd->l_reg, l_val);
184 
185 	if (enabled)
186 		__clk_hfpll_enable(hw);
187 
188 	spin_unlock_irqrestore(&h->lock, flags);
189 
190 	return 0;
191 }
192 
193 static unsigned long clk_hfpll_recalc_rate(struct clk_hw *hw,
194 					   unsigned long parent_rate)
195 {
196 	struct clk_hfpll *h = to_clk_hfpll(hw);
197 	struct hfpll_data const *hd = h->d;
198 	struct regmap *regmap = h->clkr.regmap;
199 	u32 l_val;
200 
201 	regmap_read(regmap, hd->l_reg, &l_val);
202 
203 	return l_val * parent_rate;
204 }
205 
206 static int clk_hfpll_init(struct clk_hw *hw)
207 {
208 	struct clk_hfpll *h = to_clk_hfpll(hw);
209 	struct hfpll_data const *hd = h->d;
210 	struct regmap *regmap = h->clkr.regmap;
211 	u32 mode, status;
212 
213 	regmap_read(regmap, hd->mode_reg, &mode);
214 	if (mode != (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL)) {
215 		__clk_hfpll_init_once(hw);
216 		return 0;
217 	}
218 
219 	if (hd->status_reg) {
220 		regmap_read(regmap, hd->status_reg, &status);
221 		if (!(status & BIT(hd->lock_bit))) {
222 			WARN(1, "HFPLL %s is ON, but not locked!\n",
223 			     __clk_get_name(hw->clk));
224 			clk_hfpll_disable(hw);
225 			__clk_hfpll_init_once(hw);
226 		}
227 	}
228 
229 	return 0;
230 }
231 
232 static int hfpll_is_enabled(struct clk_hw *hw)
233 {
234 	struct clk_hfpll *h = to_clk_hfpll(hw);
235 	struct hfpll_data const *hd = h->d;
236 	struct regmap *regmap = h->clkr.regmap;
237 	u32 mode;
238 
239 	regmap_read(regmap, hd->mode_reg, &mode);
240 	mode &= 0x7;
241 	return mode == (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL);
242 }
243 
244 const struct clk_ops clk_ops_hfpll = {
245 	.enable = clk_hfpll_enable,
246 	.disable = clk_hfpll_disable,
247 	.is_enabled = hfpll_is_enabled,
248 	.determine_rate = clk_hfpll_determine_rate,
249 	.set_rate = clk_hfpll_set_rate,
250 	.recalc_rate = clk_hfpll_recalc_rate,
251 	.init = clk_hfpll_init,
252 };
253 EXPORT_SYMBOL_GPL(clk_ops_hfpll);
254