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