xref: /linux/drivers/clk/mediatek/clk-mux.c (revision 522ba450b56fff29f868b1552bdc2965f55de7ed)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2018 MediaTek Inc.
4  * Author: Owen Chen <owen.chen@mediatek.com>
5  */
6 
7 #include <linux/clk.h>
8 #include <linux/clk-provider.h>
9 #include <linux/compiler_types.h>
10 #include <linux/container_of.h>
11 #include <linux/dev_printk.h>
12 #include <linux/err.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/module.h>
15 #include <linux/regmap.h>
16 #include <linux/spinlock.h>
17 #include <linux/slab.h>
18 
19 #include "clk-mtk.h"
20 #include "clk-mux.h"
21 
22 #define MTK_WAIT_FENC_DONE_US	30
23 
24 struct mtk_clk_mux {
25 	struct clk_hw hw;
26 	struct regmap *regmap;
27 	struct regmap *regmap_hwv;
28 	const struct mtk_mux *data;
29 	spinlock_t *lock;
30 	bool reparent;
31 };
32 
to_mtk_clk_mux(struct clk_hw * hw)33 static inline struct mtk_clk_mux *to_mtk_clk_mux(struct clk_hw *hw)
34 {
35 	return container_of(hw, struct mtk_clk_mux, hw);
36 }
37 
mtk_clk_mux_fenc_enable_setclr(struct clk_hw * hw)38 static int mtk_clk_mux_fenc_enable_setclr(struct clk_hw *hw)
39 {
40 	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
41 	unsigned long flags;
42 	u32 val;
43 	int ret;
44 
45 	if (mux->lock)
46 		spin_lock_irqsave(mux->lock, flags);
47 	else
48 		__acquire(mux->lock);
49 
50 	regmap_write(mux->regmap, mux->data->clr_ofs,
51 		     BIT(mux->data->gate_shift));
52 
53 	ret = regmap_read_poll_timeout_atomic(mux->regmap, mux->data->fenc_sta_mon_ofs,
54 					      val, val & BIT(mux->data->fenc_shift), 1,
55 					      MTK_WAIT_FENC_DONE_US);
56 
57 	if (mux->lock)
58 		spin_unlock_irqrestore(mux->lock, flags);
59 	else
60 		__release(mux->lock);
61 
62 	return ret;
63 }
64 
mtk_clk_mux_enable_setclr(struct clk_hw * hw)65 static int mtk_clk_mux_enable_setclr(struct clk_hw *hw)
66 {
67 	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
68 	unsigned long flags = 0;
69 
70 	if (mux->lock)
71 		spin_lock_irqsave(mux->lock, flags);
72 	else
73 		__acquire(mux->lock);
74 
75 	regmap_write(mux->regmap, mux->data->clr_ofs,
76 		     BIT(mux->data->gate_shift));
77 
78 	/*
79 	 * If the parent has been changed when the clock was disabled, it will
80 	 * not be effective yet. Set the update bit to ensure the mux gets
81 	 * updated.
82 	 */
83 	if (mux->reparent && mux->data->upd_shift >= 0) {
84 		regmap_write(mux->regmap, mux->data->upd_ofs,
85 			     BIT(mux->data->upd_shift));
86 		mux->reparent = false;
87 	}
88 
89 	if (mux->lock)
90 		spin_unlock_irqrestore(mux->lock, flags);
91 	else
92 		__release(mux->lock);
93 
94 	return 0;
95 }
96 
mtk_clk_mux_disable_setclr(struct clk_hw * hw)97 static void mtk_clk_mux_disable_setclr(struct clk_hw *hw)
98 {
99 	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
100 
101 	regmap_write(mux->regmap, mux->data->set_ofs,
102 			BIT(mux->data->gate_shift));
103 }
104 
mtk_clk_mux_fenc_is_enabled(struct clk_hw * hw)105 static int mtk_clk_mux_fenc_is_enabled(struct clk_hw *hw)
106 {
107 	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
108 	u32 val;
109 
110 	regmap_read(mux->regmap, mux->data->fenc_sta_mon_ofs, &val);
111 
112 	return !!(val & BIT(mux->data->fenc_shift));
113 }
114 
mtk_clk_mux_is_enabled(struct clk_hw * hw)115 static int mtk_clk_mux_is_enabled(struct clk_hw *hw)
116 {
117 	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
118 	u32 val;
119 
120 	regmap_read(mux->regmap, mux->data->mux_ofs, &val);
121 
122 	return (val & BIT(mux->data->gate_shift)) == 0;
123 }
124 
mtk_clk_mux_hwv_fenc_enable(struct clk_hw * hw)125 static int mtk_clk_mux_hwv_fenc_enable(struct clk_hw *hw)
126 {
127 	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
128 	u32 val;
129 	int ret;
130 
131 	regmap_write(mux->regmap_hwv, mux->data->hwv_set_ofs,
132 		     BIT(mux->data->gate_shift));
133 
134 	ret = regmap_read_poll_timeout_atomic(mux->regmap_hwv, mux->data->hwv_sta_ofs,
135 					      val, val & BIT(mux->data->gate_shift), 0,
136 					      MTK_WAIT_HWV_DONE_US);
137 	if (ret)
138 		return ret;
139 
140 	ret = regmap_read_poll_timeout_atomic(mux->regmap, mux->data->fenc_sta_mon_ofs,
141 					      val, val & BIT(mux->data->fenc_shift), 1,
142 					      MTK_WAIT_FENC_DONE_US);
143 
144 	return ret;
145 }
146 
mtk_clk_mux_hwv_disable(struct clk_hw * hw)147 static void mtk_clk_mux_hwv_disable(struct clk_hw *hw)
148 {
149 	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
150 	u32 val;
151 
152 	regmap_write(mux->regmap_hwv, mux->data->hwv_clr_ofs,
153 		     BIT(mux->data->gate_shift));
154 
155 	regmap_read_poll_timeout_atomic(mux->regmap_hwv, mux->data->hwv_sta_ofs,
156 					val, (val & BIT(mux->data->gate_shift)),
157 					0, MTK_WAIT_HWV_DONE_US);
158 }
159 
mtk_clk_mux_get_parent(struct clk_hw * hw)160 static u8 mtk_clk_mux_get_parent(struct clk_hw *hw)
161 {
162 	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
163 	u32 mask = GENMASK(mux->data->mux_width - 1, 0);
164 	u32 val;
165 
166 	regmap_read(mux->regmap, mux->data->mux_ofs, &val);
167 	val = (val >> mux->data->mux_shift) & mask;
168 
169 	if (mux->data->parent_index) {
170 		int i;
171 
172 		for (i = 0; i < mux->data->num_parents; i++)
173 			if (mux->data->parent_index[i] == val)
174 				return i;
175 
176 		/* Not found: return an impossible index to generate error */
177 		return mux->data->num_parents + 1;
178 	}
179 
180 	return val;
181 }
182 
mtk_clk_mux_set_parent_setclr_lock(struct clk_hw * hw,u8 index)183 static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index)
184 {
185 	struct mtk_clk_mux *mux = to_mtk_clk_mux(hw);
186 	u32 mask = GENMASK(mux->data->mux_width - 1, 0);
187 	u32 val, orig;
188 	unsigned long flags = 0;
189 
190 	if (mux->lock)
191 		spin_lock_irqsave(mux->lock, flags);
192 	else
193 		__acquire(mux->lock);
194 
195 	if (mux->data->parent_index)
196 		index = mux->data->parent_index[index];
197 
198 	regmap_read(mux->regmap, mux->data->mux_ofs, &orig);
199 	val = (orig & ~(mask << mux->data->mux_shift))
200 			| (index << mux->data->mux_shift);
201 
202 	if (val != orig) {
203 		regmap_write(mux->regmap, mux->data->clr_ofs,
204 				mask << mux->data->mux_shift);
205 		regmap_write(mux->regmap, mux->data->set_ofs,
206 				index << mux->data->mux_shift);
207 
208 		if (mux->data->upd_shift >= 0) {
209 			regmap_write(mux->regmap, mux->data->upd_ofs,
210 					BIT(mux->data->upd_shift));
211 			mux->reparent = true;
212 		}
213 	}
214 
215 	if (mux->lock)
216 		spin_unlock_irqrestore(mux->lock, flags);
217 	else
218 		__release(mux->lock);
219 
220 	return 0;
221 }
222 
mtk_clk_mux_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)223 static int mtk_clk_mux_determine_rate(struct clk_hw *hw,
224 				      struct clk_rate_request *req)
225 {
226 	return clk_mux_determine_rate_flags(hw, req, 0);
227 }
228 
mtk_clk_mux_uses_hwv(const struct clk_ops * ops)229 static bool mtk_clk_mux_uses_hwv(const struct clk_ops *ops)
230 {
231 	if (ops == &mtk_mux_gate_hwv_fenc_clr_set_upd_ops)
232 		return true;
233 
234 	return false;
235 }
236 
237 const struct clk_ops mtk_mux_clr_set_upd_ops = {
238 	.get_parent = mtk_clk_mux_get_parent,
239 	.set_parent = mtk_clk_mux_set_parent_setclr_lock,
240 	.determine_rate = mtk_clk_mux_determine_rate,
241 };
242 EXPORT_SYMBOL_GPL(mtk_mux_clr_set_upd_ops);
243 
244 const struct clk_ops mtk_mux_gate_clr_set_upd_ops  = {
245 	.enable = mtk_clk_mux_enable_setclr,
246 	.disable = mtk_clk_mux_disable_setclr,
247 	.is_enabled = mtk_clk_mux_is_enabled,
248 	.get_parent = mtk_clk_mux_get_parent,
249 	.set_parent = mtk_clk_mux_set_parent_setclr_lock,
250 	.determine_rate = mtk_clk_mux_determine_rate,
251 };
252 EXPORT_SYMBOL_GPL(mtk_mux_gate_clr_set_upd_ops);
253 
254 const struct clk_ops mtk_mux_gate_fenc_clr_set_upd_ops = {
255 	.enable = mtk_clk_mux_fenc_enable_setclr,
256 	.disable = mtk_clk_mux_disable_setclr,
257 	.is_enabled = mtk_clk_mux_fenc_is_enabled,
258 	.get_parent = mtk_clk_mux_get_parent,
259 	.set_parent = mtk_clk_mux_set_parent_setclr_lock,
260 	.determine_rate = mtk_clk_mux_determine_rate,
261 };
262 EXPORT_SYMBOL_GPL(mtk_mux_gate_fenc_clr_set_upd_ops);
263 
264 const struct clk_ops mtk_mux_gate_hwv_fenc_clr_set_upd_ops = {
265 	.enable = mtk_clk_mux_hwv_fenc_enable,
266 	.disable = mtk_clk_mux_hwv_disable,
267 	.is_enabled = mtk_clk_mux_fenc_is_enabled,
268 	.get_parent = mtk_clk_mux_get_parent,
269 	.set_parent = mtk_clk_mux_set_parent_setclr_lock,
270 	.determine_rate = mtk_clk_mux_determine_rate,
271 };
272 EXPORT_SYMBOL_GPL(mtk_mux_gate_hwv_fenc_clr_set_upd_ops);
273 
mtk_clk_register_mux(struct device * dev,const struct mtk_mux * mux,struct regmap * regmap,struct regmap * regmap_hwv,spinlock_t * lock)274 static struct clk_hw *mtk_clk_register_mux(struct device *dev,
275 					   const struct mtk_mux *mux,
276 					   struct regmap *regmap,
277 					   struct regmap *regmap_hwv,
278 					   spinlock_t *lock)
279 {
280 	struct mtk_clk_mux *clk_mux;
281 	struct clk_init_data init = {};
282 	int ret;
283 
284 	clk_mux = kzalloc(sizeof(*clk_mux), GFP_KERNEL);
285 	if (!clk_mux)
286 		return ERR_PTR(-ENOMEM);
287 
288 	init.name = mux->name;
289 	init.flags = mux->flags;
290 	init.parent_names = mux->parent_names;
291 	init.num_parents = mux->num_parents;
292 	init.ops = mux->ops;
293 	if (mtk_clk_mux_uses_hwv(init.ops) && !regmap_hwv)
294 		return dev_err_ptr_probe(
295 			dev, -ENXIO,
296 			"regmap not found for hardware voter clocks\n");
297 
298 	clk_mux->regmap = regmap;
299 	clk_mux->regmap_hwv = regmap_hwv;
300 	clk_mux->data = mux;
301 	clk_mux->lock = lock;
302 	clk_mux->hw.init = &init;
303 
304 	ret = clk_hw_register(dev, &clk_mux->hw);
305 	if (ret) {
306 		kfree(clk_mux);
307 		return ERR_PTR(ret);
308 	}
309 
310 	return &clk_mux->hw;
311 }
312 
mtk_clk_unregister_mux(struct clk_hw * hw)313 static void mtk_clk_unregister_mux(struct clk_hw *hw)
314 {
315 	struct mtk_clk_mux *mux;
316 	if (!hw)
317 		return;
318 
319 	mux = to_mtk_clk_mux(hw);
320 
321 	clk_hw_unregister(hw);
322 	kfree(mux);
323 }
324 
mtk_clk_register_muxes(struct device * dev,const struct mtk_mux * muxes,int num,struct device_node * node,spinlock_t * lock,struct clk_hw_onecell_data * clk_data)325 int mtk_clk_register_muxes(struct device *dev,
326 			   const struct mtk_mux *muxes,
327 			   int num, struct device_node *node,
328 			   spinlock_t *lock,
329 			   struct clk_hw_onecell_data *clk_data)
330 {
331 	struct regmap *regmap;
332 	struct regmap *regmap_hwv;
333 	struct clk_hw *hw;
334 	int i;
335 
336 	regmap = device_node_to_regmap(node);
337 	if (IS_ERR(regmap)) {
338 		pr_err("Cannot find regmap for %pOF: %pe\n", node, regmap);
339 		return PTR_ERR(regmap);
340 	}
341 
342 	regmap_hwv = mtk_clk_get_hwv_regmap(node);
343 	if (IS_ERR(regmap_hwv))
344 		return dev_err_probe(
345 			dev, PTR_ERR(regmap_hwv),
346 			"Cannot find hardware voter regmap for %pOF\n", node);
347 
348 	for (i = 0; i < num; i++) {
349 		const struct mtk_mux *mux = &muxes[i];
350 
351 		if (!IS_ERR_OR_NULL(clk_data->hws[mux->id])) {
352 			pr_warn("%pOF: Trying to register duplicate clock ID: %d\n",
353 				node, mux->id);
354 			continue;
355 		}
356 
357 		hw = mtk_clk_register_mux(dev, mux, regmap, regmap_hwv, lock);
358 
359 		if (IS_ERR(hw)) {
360 			pr_err("Failed to register clk %s: %pe\n", mux->name,
361 			       hw);
362 			goto err;
363 		}
364 
365 		clk_data->hws[mux->id] = hw;
366 	}
367 
368 	return 0;
369 
370 err:
371 	while (--i >= 0) {
372 		const struct mtk_mux *mux = &muxes[i];
373 
374 		if (IS_ERR_OR_NULL(clk_data->hws[mux->id]))
375 			continue;
376 
377 		mtk_clk_unregister_mux(clk_data->hws[mux->id]);
378 		clk_data->hws[mux->id] = ERR_PTR(-ENOENT);
379 	}
380 
381 	return PTR_ERR(hw);
382 }
383 EXPORT_SYMBOL_GPL(mtk_clk_register_muxes);
384 
mtk_clk_unregister_muxes(const struct mtk_mux * muxes,int num,struct clk_hw_onecell_data * clk_data)385 void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num,
386 			      struct clk_hw_onecell_data *clk_data)
387 {
388 	int i;
389 
390 	if (!clk_data)
391 		return;
392 
393 	for (i = num; i > 0; i--) {
394 		const struct mtk_mux *mux = &muxes[i - 1];
395 
396 		if (IS_ERR_OR_NULL(clk_data->hws[mux->id]))
397 			continue;
398 
399 		mtk_clk_unregister_mux(clk_data->hws[mux->id]);
400 		clk_data->hws[mux->id] = ERR_PTR(-ENOENT);
401 	}
402 }
403 EXPORT_SYMBOL_GPL(mtk_clk_unregister_muxes);
404 
405 /*
406  * This clock notifier is called when the frequency of the parent
407  * PLL clock is to be changed. The idea is to switch the parent to a
408  * stable clock, such as the main oscillator, while the PLL frequency
409  * stabilizes.
410  */
mtk_clk_mux_notifier_cb(struct notifier_block * nb,unsigned long event,void * _data)411 static int mtk_clk_mux_notifier_cb(struct notifier_block *nb,
412 				   unsigned long event, void *_data)
413 {
414 	struct clk_notifier_data *data = _data;
415 	struct clk_hw *hw = __clk_get_hw(data->clk);
416 	struct mtk_mux_nb *mux_nb = to_mtk_mux_nb(nb);
417 	int ret = 0;
418 
419 	switch (event) {
420 	case PRE_RATE_CHANGE:
421 		mux_nb->original_index = mux_nb->ops->get_parent(hw);
422 		ret = mux_nb->ops->set_parent(hw, mux_nb->bypass_index);
423 		break;
424 	case POST_RATE_CHANGE:
425 	case ABORT_RATE_CHANGE:
426 		ret = mux_nb->ops->set_parent(hw, mux_nb->original_index);
427 		break;
428 	}
429 
430 	return notifier_from_errno(ret);
431 }
432 
devm_mtk_clk_mux_notifier_register(struct device * dev,struct clk * clk,struct mtk_mux_nb * mux_nb)433 int devm_mtk_clk_mux_notifier_register(struct device *dev, struct clk *clk,
434 				       struct mtk_mux_nb *mux_nb)
435 {
436 	mux_nb->nb.notifier_call = mtk_clk_mux_notifier_cb;
437 
438 	return devm_clk_notifier_register(dev, clk, &mux_nb->nb);
439 }
440 EXPORT_SYMBOL_GPL(devm_mtk_clk_mux_notifier_register);
441 
442 MODULE_LICENSE("GPL");
443