xref: /linux/drivers/clk/sophgo/clk-cv18xx-ip.c (revision 522ba450b56fff29f868b1552bdc2965f55de7ed)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
4  */
5 
6 #include <linux/clk-provider.h>
7 #include <linux/io.h>
8 #include <linux/gcd.h>
9 #include <linux/spinlock.h>
10 
11 #include "clk-cv18xx-ip.h"
12 
13 /* GATE */
hw_to_cv1800_clk_gate(struct clk_hw * hw)14 static inline struct cv1800_clk_gate *hw_to_cv1800_clk_gate(struct clk_hw *hw)
15 {
16 	struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw);
17 
18 	return container_of(common, struct cv1800_clk_gate, common);
19 }
20 
gate_enable(struct clk_hw * hw)21 static int gate_enable(struct clk_hw *hw)
22 {
23 	struct cv1800_clk_gate *gate = hw_to_cv1800_clk_gate(hw);
24 
25 	return cv1800_clk_setbit(&gate->common, &gate->gate);
26 }
27 
gate_disable(struct clk_hw * hw)28 static void gate_disable(struct clk_hw *hw)
29 {
30 	struct cv1800_clk_gate *gate = hw_to_cv1800_clk_gate(hw);
31 
32 	cv1800_clk_clearbit(&gate->common, &gate->gate);
33 }
34 
gate_is_enabled(struct clk_hw * hw)35 static int gate_is_enabled(struct clk_hw *hw)
36 {
37 	struct cv1800_clk_gate *gate = hw_to_cv1800_clk_gate(hw);
38 
39 	return cv1800_clk_checkbit(&gate->common, &gate->gate);
40 }
41 
gate_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)42 static unsigned long gate_recalc_rate(struct clk_hw *hw,
43 				      unsigned long parent_rate)
44 {
45 	return parent_rate;
46 }
47 
gate_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)48 static int gate_determine_rate(struct clk_hw *hw,
49 			       struct clk_rate_request *req)
50 {
51 	req->rate = req->best_parent_rate;
52 
53 	return 0;
54 }
55 
gate_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)56 static int gate_set_rate(struct clk_hw *hw, unsigned long rate,
57 			 unsigned long parent_rate)
58 {
59 	return 0;
60 }
61 
62 const struct clk_ops cv1800_clk_gate_ops = {
63 	.disable = gate_disable,
64 	.enable = gate_enable,
65 	.is_enabled = gate_is_enabled,
66 
67 	.recalc_rate = gate_recalc_rate,
68 	.determine_rate = gate_determine_rate,
69 	.set_rate = gate_set_rate,
70 };
71 
72 /* DIV */
73 #define _DIV_EN_CLK_DIV_FACTOR_FIELD		BIT(3)
74 
75 #define DIV_GET_EN_CLK_DIV_FACTOR(_reg) \
76 	FIELD_GET(_DIV_EN_CLK_DIV_FACTOR_FIELD, _reg)
77 
78 #define DIV_SET_EN_DIV_FACTOR(_reg) \
79 	_CV1800_SET_FIELD(_reg, 1, _DIV_EN_CLK_DIV_FACTOR_FIELD)
80 
hw_to_cv1800_clk_div(struct clk_hw * hw)81 static inline struct cv1800_clk_div *hw_to_cv1800_clk_div(struct clk_hw *hw)
82 {
83 	struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw);
84 
85 	return container_of(common, struct cv1800_clk_div, common);
86 }
87 
div_enable(struct clk_hw * hw)88 static int div_enable(struct clk_hw *hw)
89 {
90 	struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
91 
92 	return cv1800_clk_setbit(&div->common, &div->gate);
93 }
94 
div_disable(struct clk_hw * hw)95 static void div_disable(struct clk_hw *hw)
96 {
97 	struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
98 
99 	cv1800_clk_clearbit(&div->common, &div->gate);
100 }
101 
div_is_enabled(struct clk_hw * hw)102 static int div_is_enabled(struct clk_hw *hw)
103 {
104 	struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
105 
106 	return cv1800_clk_checkbit(&div->common, &div->gate);
107 }
108 
div_helper_set_rate(struct cv1800_clk_common * common,struct cv1800_clk_regfield * div,unsigned long val)109 static int div_helper_set_rate(struct cv1800_clk_common *common,
110 			       struct cv1800_clk_regfield *div,
111 			       unsigned long val)
112 {
113 	unsigned long flags;
114 	u32 reg;
115 
116 	if (div->width == 0)
117 		return 0;
118 
119 	spin_lock_irqsave(common->lock, flags);
120 
121 	reg = readl(common->base + div->reg);
122 	reg = cv1800_clk_regfield_set(reg, val, div);
123 	if (div->initval > 0)
124 		reg = DIV_SET_EN_DIV_FACTOR(reg);
125 
126 	writel(reg, common->base + div->reg);
127 
128 	spin_unlock_irqrestore(common->lock, flags);
129 
130 	return 0;
131 }
132 
div_helper_get_clockdiv(struct cv1800_clk_common * common,struct cv1800_clk_regfield * div)133 static u32 div_helper_get_clockdiv(struct cv1800_clk_common *common,
134 				   struct cv1800_clk_regfield *div)
135 {
136 	u32 clockdiv = 1;
137 	u32 reg;
138 
139 	if (!div || div->initval < 0 || (div->width == 0 && div->initval <= 0))
140 		return 1;
141 
142 	if (div->width == 0 && div->initval > 0)
143 		return div->initval;
144 
145 	reg = readl(common->base + div->reg);
146 
147 	if (div->initval == 0 || DIV_GET_EN_CLK_DIV_FACTOR(reg))
148 		clockdiv = cv1800_clk_regfield_get(reg, div);
149 	else if (div->initval > 0)
150 		clockdiv = div->initval;
151 
152 	return clockdiv;
153 }
154 
div_helper_round_rate(struct cv1800_clk_regfield * div,struct clk_hw * hw,struct clk_hw * parent,unsigned long rate,unsigned long * prate)155 static u32 div_helper_round_rate(struct cv1800_clk_regfield *div,
156 				 struct clk_hw *hw, struct clk_hw *parent,
157 				 unsigned long rate, unsigned long *prate)
158 {
159 	if (div->width == 0) {
160 		if (div->initval <= 0)
161 			return DIV_ROUND_UP_ULL(*prate, 1);
162 		else
163 			return DIV_ROUND_UP_ULL(*prate, div->initval);
164 	}
165 
166 	return divider_round_rate_parent(hw, parent, rate, prate, NULL,
167 					 div->width, div->flags);
168 }
169 
div_round_rate(struct clk_hw * parent,unsigned long * parent_rate,unsigned long rate,int id,void * data)170 static long div_round_rate(struct clk_hw *parent, unsigned long *parent_rate,
171 			   unsigned long rate, int id, void *data)
172 {
173 	struct cv1800_clk_div *div = data;
174 
175 	return div_helper_round_rate(&div->div, &div->common.hw, parent,
176 				     rate, parent_rate);
177 }
178 
div_is_better_rate(struct cv1800_clk_common * common,unsigned long target,unsigned long now,unsigned long best)179 static bool div_is_better_rate(struct cv1800_clk_common *common,
180 			       unsigned long target, unsigned long now,
181 			       unsigned long best)
182 {
183 	if (common->features & CLK_DIVIDER_ROUND_CLOSEST)
184 		return abs_diff(target, now) < abs_diff(target, best);
185 
186 	return now <= target && now > best;
187 }
188 
mux_helper_determine_rate(struct cv1800_clk_common * common,struct clk_rate_request * req,long (* round)(struct clk_hw *,unsigned long *,unsigned long,int,void *),void * data)189 static int mux_helper_determine_rate(struct cv1800_clk_common *common,
190 				     struct clk_rate_request *req,
191 				     long (*round)(struct clk_hw *,
192 						   unsigned long *,
193 						   unsigned long,
194 						   int,
195 						   void *),
196 				     void *data)
197 {
198 	unsigned long best_parent_rate = 0, best_rate = 0;
199 	struct clk_hw *best_parent, *hw = &common->hw;
200 	unsigned int i;
201 
202 	if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) {
203 		unsigned long adj_parent_rate;
204 
205 		best_parent = clk_hw_get_parent(hw);
206 		best_parent_rate = clk_hw_get_rate(best_parent);
207 
208 		best_rate = round(best_parent, &adj_parent_rate,
209 				  req->rate, -1, data);
210 
211 		goto find;
212 	}
213 
214 	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
215 		unsigned long tmp_rate, parent_rate;
216 		struct clk_hw *parent;
217 
218 		parent = clk_hw_get_parent_by_index(hw, i);
219 		if (!parent)
220 			continue;
221 
222 		parent_rate = clk_hw_get_rate(parent);
223 
224 		tmp_rate = round(parent, &parent_rate, req->rate, i, data);
225 
226 		if (tmp_rate == req->rate) {
227 			best_parent = parent;
228 			best_parent_rate = parent_rate;
229 			best_rate = tmp_rate;
230 			goto find;
231 		}
232 
233 		if (div_is_better_rate(common, req->rate,
234 				       tmp_rate, best_rate)) {
235 			best_parent = parent;
236 			best_parent_rate = parent_rate;
237 			best_rate = tmp_rate;
238 		}
239 	}
240 
241 	if (best_rate == 0)
242 		return -EINVAL;
243 
244 find:
245 	req->best_parent_hw = best_parent;
246 	req->best_parent_rate = best_parent_rate;
247 	req->rate = best_rate;
248 	return 0;
249 }
250 
div_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)251 static int div_determine_rate(struct clk_hw *hw,
252 			      struct clk_rate_request *req)
253 {
254 	struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
255 
256 	return mux_helper_determine_rate(&div->common, req,
257 					 div_round_rate, div);
258 }
259 
div_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)260 static unsigned long div_recalc_rate(struct clk_hw *hw,
261 				     unsigned long parent_rate)
262 {
263 	struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
264 	unsigned long val;
265 
266 	val = div_helper_get_clockdiv(&div->common, &div->div);
267 	if (val == 0)
268 		return 0;
269 
270 	return divider_recalc_rate(hw, parent_rate, val, NULL,
271 				   div->div.flags, div->div.width);
272 }
273 
div_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)274 static int div_set_rate(struct clk_hw *hw, unsigned long rate,
275 			 unsigned long parent_rate)
276 {
277 	struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
278 	unsigned long val;
279 
280 	val = divider_get_val(rate, parent_rate, NULL,
281 			      div->div.width, div->div.flags);
282 
283 	return div_helper_set_rate(&div->common, &div->div, val);
284 }
285 
286 const struct clk_ops cv1800_clk_div_ops = {
287 	.disable = div_disable,
288 	.enable = div_enable,
289 	.is_enabled = div_is_enabled,
290 
291 	.determine_rate = div_determine_rate,
292 	.recalc_rate	= div_recalc_rate,
293 	.set_rate = div_set_rate,
294 };
295 
296 static inline struct cv1800_clk_bypass_div *
hw_to_cv1800_clk_bypass_div(struct clk_hw * hw)297 hw_to_cv1800_clk_bypass_div(struct clk_hw *hw)
298 {
299 	struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
300 
301 	return container_of(div, struct cv1800_clk_bypass_div, div);
302 }
303 
bypass_div_round_rate(struct clk_hw * parent,unsigned long * parent_rate,unsigned long rate,int id,void * data)304 static long bypass_div_round_rate(struct clk_hw *parent,
305 				  unsigned long *parent_rate,
306 				  unsigned long rate, int id, void *data)
307 {
308 	struct cv1800_clk_bypass_div *div = data;
309 
310 	if (id == -1) {
311 		if (cv1800_clk_checkbit(&div->div.common, &div->bypass))
312 			return *parent_rate;
313 		else
314 			return div_round_rate(parent, parent_rate, rate,
315 					      -1, &div->div);
316 	}
317 
318 	if (id == 0)
319 		return *parent_rate;
320 
321 	return div_round_rate(parent, parent_rate, rate, id - 1, &div->div);
322 }
323 
bypass_div_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)324 static int bypass_div_determine_rate(struct clk_hw *hw,
325 				     struct clk_rate_request *req)
326 {
327 	struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw);
328 
329 	return mux_helper_determine_rate(&div->div.common, req,
330 					 bypass_div_round_rate, div);
331 }
332 
bypass_div_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)333 static unsigned long bypass_div_recalc_rate(struct clk_hw *hw,
334 					    unsigned long parent_rate)
335 {
336 	struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw);
337 
338 	if (cv1800_clk_checkbit(&div->div.common, &div->bypass))
339 		return parent_rate;
340 
341 	return div_recalc_rate(hw, parent_rate);
342 }
343 
bypass_div_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)344 static int bypass_div_set_rate(struct clk_hw *hw, unsigned long rate,
345 			       unsigned long parent_rate)
346 {
347 	struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw);
348 
349 	if (cv1800_clk_checkbit(&div->div.common, &div->bypass))
350 		return 0;
351 
352 	return div_set_rate(hw, rate, parent_rate);
353 }
354 
bypass_div_get_parent(struct clk_hw * hw)355 static u8 bypass_div_get_parent(struct clk_hw *hw)
356 {
357 	struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw);
358 
359 	if (cv1800_clk_checkbit(&div->div.common, &div->bypass))
360 		return 0;
361 
362 	return 1;
363 }
364 
bypass_div_set_parent(struct clk_hw * hw,u8 index)365 static int bypass_div_set_parent(struct clk_hw *hw, u8 index)
366 {
367 	struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw);
368 
369 	if (index)
370 		return cv1800_clk_clearbit(&div->div.common, &div->bypass);
371 
372 	return cv1800_clk_setbit(&div->div.common, &div->bypass);
373 }
374 
375 const struct clk_ops cv1800_clk_bypass_div_ops = {
376 	.disable = div_disable,
377 	.enable = div_enable,
378 	.is_enabled = div_is_enabled,
379 
380 	.determine_rate = bypass_div_determine_rate,
381 	.recalc_rate = bypass_div_recalc_rate,
382 	.set_rate = bypass_div_set_rate,
383 
384 	.set_parent = bypass_div_set_parent,
385 	.get_parent = bypass_div_get_parent,
386 };
387 
388 /* MUX */
hw_to_cv1800_clk_mux(struct clk_hw * hw)389 static inline struct cv1800_clk_mux *hw_to_cv1800_clk_mux(struct clk_hw *hw)
390 {
391 	struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw);
392 
393 	return container_of(common, struct cv1800_clk_mux, common);
394 }
395 
mux_enable(struct clk_hw * hw)396 static int mux_enable(struct clk_hw *hw)
397 {
398 	struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
399 
400 	return cv1800_clk_setbit(&mux->common, &mux->gate);
401 }
402 
mux_disable(struct clk_hw * hw)403 static void mux_disable(struct clk_hw *hw)
404 {
405 	struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
406 
407 	cv1800_clk_clearbit(&mux->common, &mux->gate);
408 }
409 
mux_is_enabled(struct clk_hw * hw)410 static int mux_is_enabled(struct clk_hw *hw)
411 {
412 	struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
413 
414 	return cv1800_clk_checkbit(&mux->common, &mux->gate);
415 }
416 
mux_round_rate(struct clk_hw * parent,unsigned long * parent_rate,unsigned long rate,int id,void * data)417 static long mux_round_rate(struct clk_hw *parent, unsigned long *parent_rate,
418 			   unsigned long rate, int id, void *data)
419 {
420 	struct cv1800_clk_mux *mux = data;
421 
422 	return div_helper_round_rate(&mux->div, &mux->common.hw, parent,
423 				     rate, parent_rate);
424 }
425 
mux_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)426 static int mux_determine_rate(struct clk_hw *hw,
427 			      struct clk_rate_request *req)
428 {
429 	struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
430 
431 	return mux_helper_determine_rate(&mux->common, req,
432 					 mux_round_rate, mux);
433 }
434 
mux_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)435 static unsigned long mux_recalc_rate(struct clk_hw *hw,
436 				     unsigned long parent_rate)
437 {
438 	struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
439 	unsigned long val;
440 
441 	val = div_helper_get_clockdiv(&mux->common, &mux->div);
442 	if (val == 0)
443 		return 0;
444 
445 	return divider_recalc_rate(hw, parent_rate, val, NULL,
446 				   mux->div.flags, mux->div.width);
447 }
448 
mux_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)449 static int mux_set_rate(struct clk_hw *hw, unsigned long rate,
450 			unsigned long parent_rate)
451 {
452 	struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
453 	unsigned long val;
454 
455 	val = divider_get_val(rate, parent_rate, NULL,
456 			      mux->div.width, mux->div.flags);
457 
458 	return div_helper_set_rate(&mux->common, &mux->div, val);
459 }
460 
mux_get_parent(struct clk_hw * hw)461 static u8 mux_get_parent(struct clk_hw *hw)
462 {
463 	struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
464 	u32 reg = readl(mux->common.base + mux->mux.reg);
465 
466 	return cv1800_clk_regfield_get(reg, &mux->mux);
467 }
468 
_mux_set_parent(struct cv1800_clk_mux * mux,u8 index)469 static int _mux_set_parent(struct cv1800_clk_mux *mux, u8 index)
470 {
471 	u32 reg;
472 
473 	reg = readl(mux->common.base + mux->mux.reg);
474 	reg = cv1800_clk_regfield_set(reg, index, &mux->mux);
475 	writel(reg, mux->common.base + mux->mux.reg);
476 
477 	return 0;
478 }
479 
mux_set_parent(struct clk_hw * hw,u8 index)480 static int mux_set_parent(struct clk_hw *hw, u8 index)
481 {
482 	struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
483 	unsigned long flags;
484 
485 	spin_lock_irqsave(mux->common.lock, flags);
486 
487 	_mux_set_parent(mux, index);
488 
489 	spin_unlock_irqrestore(mux->common.lock, flags);
490 
491 	return 0;
492 }
493 
494 const struct clk_ops cv1800_clk_mux_ops = {
495 	.disable = mux_disable,
496 	.enable = mux_enable,
497 	.is_enabled = mux_is_enabled,
498 
499 	.determine_rate = mux_determine_rate,
500 	.recalc_rate = mux_recalc_rate,
501 	.set_rate = mux_set_rate,
502 
503 	.set_parent = mux_set_parent,
504 	.get_parent = mux_get_parent,
505 };
506 
507 static inline struct cv1800_clk_bypass_mux *
hw_to_cv1800_clk_bypass_mux(struct clk_hw * hw)508 hw_to_cv1800_clk_bypass_mux(struct clk_hw *hw)
509 {
510 	struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
511 
512 	return container_of(mux, struct cv1800_clk_bypass_mux, mux);
513 }
514 
bypass_mux_round_rate(struct clk_hw * parent,unsigned long * parent_rate,unsigned long rate,int id,void * data)515 static long bypass_mux_round_rate(struct clk_hw *parent,
516 				  unsigned long *parent_rate,
517 				  unsigned long rate, int id, void *data)
518 {
519 	struct cv1800_clk_bypass_mux *mux = data;
520 
521 	if (id == -1) {
522 		if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass))
523 			return *parent_rate;
524 		else
525 			return mux_round_rate(parent, parent_rate, rate,
526 					      -1, &mux->mux);
527 	}
528 
529 	if (id == 0)
530 		return *parent_rate;
531 
532 	return mux_round_rate(parent, parent_rate, rate, id - 1, &mux->mux);
533 }
534 
bypass_mux_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)535 static int bypass_mux_determine_rate(struct clk_hw *hw,
536 				     struct clk_rate_request *req)
537 {
538 	struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw);
539 
540 	return mux_helper_determine_rate(&mux->mux.common, req,
541 					 bypass_mux_round_rate, mux);
542 }
543 
bypass_mux_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)544 static unsigned long bypass_mux_recalc_rate(struct clk_hw *hw,
545 					    unsigned long parent_rate)
546 {
547 	struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw);
548 
549 	if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass))
550 		return parent_rate;
551 
552 	return mux_recalc_rate(hw, parent_rate);
553 }
554 
bypass_mux_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)555 static int bypass_mux_set_rate(struct clk_hw *hw, unsigned long rate,
556 			       unsigned long parent_rate)
557 {
558 	struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw);
559 
560 	if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass))
561 		return 0;
562 
563 	return mux_set_rate(hw, rate, parent_rate);
564 }
565 
bypass_mux_get_parent(struct clk_hw * hw)566 static u8 bypass_mux_get_parent(struct clk_hw *hw)
567 {
568 	struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw);
569 
570 	if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass))
571 		return 0;
572 
573 	return mux_get_parent(hw) + 1;
574 }
575 
bypass_mux_set_parent(struct clk_hw * hw,u8 index)576 static int bypass_mux_set_parent(struct clk_hw *hw, u8 index)
577 {
578 	struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw);
579 
580 	if (index == 0)
581 		return cv1800_clk_setbit(&mux->mux.common, &mux->bypass);
582 
583 	return cv1800_clk_clearbit(&mux->mux.common, &mux->bypass);
584 }
585 
586 const struct clk_ops cv1800_clk_bypass_mux_ops = {
587 	.disable = mux_disable,
588 	.enable = mux_enable,
589 	.is_enabled = mux_is_enabled,
590 
591 	.determine_rate = bypass_mux_determine_rate,
592 	.recalc_rate = bypass_mux_recalc_rate,
593 	.set_rate = bypass_mux_set_rate,
594 
595 	.set_parent = bypass_mux_set_parent,
596 	.get_parent = bypass_mux_get_parent,
597 };
598 
599 /* MMUX */
hw_to_cv1800_clk_mmux(struct clk_hw * hw)600 static inline struct cv1800_clk_mmux *hw_to_cv1800_clk_mmux(struct clk_hw *hw)
601 {
602 	struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw);
603 
604 	return container_of(common, struct cv1800_clk_mmux, common);
605 }
606 
mmux_get_parent_id(struct cv1800_clk_mmux * mmux)607 static u8 mmux_get_parent_id(struct cv1800_clk_mmux *mmux)
608 {
609 	struct clk_hw *hw = &mmux->common.hw;
610 	struct clk_hw *parent = clk_hw_get_parent(hw);
611 	unsigned int i;
612 
613 	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
614 		if (parent == clk_hw_get_parent_by_index(hw, i))
615 			return i;
616 	}
617 
618 	BUG();
619 }
620 
mmux_enable(struct clk_hw * hw)621 static int mmux_enable(struct clk_hw *hw)
622 {
623 	struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
624 
625 	return cv1800_clk_setbit(&mmux->common, &mmux->gate);
626 }
627 
mmux_disable(struct clk_hw * hw)628 static void mmux_disable(struct clk_hw *hw)
629 {
630 	struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
631 
632 	cv1800_clk_clearbit(&mmux->common, &mmux->gate);
633 }
634 
mmux_is_enabled(struct clk_hw * hw)635 static int mmux_is_enabled(struct clk_hw *hw)
636 {
637 	struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
638 
639 	return cv1800_clk_checkbit(&mmux->common, &mmux->gate);
640 }
641 
mmux_round_rate(struct clk_hw * parent,unsigned long * parent_rate,unsigned long rate,int id,void * data)642 static long mmux_round_rate(struct clk_hw *parent, unsigned long *parent_rate,
643 			    unsigned long rate, int id, void *data)
644 {
645 	struct cv1800_clk_mmux *mmux = data;
646 	s8 div_id;
647 
648 	if (id == -1) {
649 		if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass))
650 			return *parent_rate;
651 
652 		id = mmux_get_parent_id(mmux);
653 	}
654 
655 	div_id = mmux->parent2sel[id];
656 
657 	if (div_id < 0)
658 		return *parent_rate;
659 
660 	return div_helper_round_rate(&mmux->div[div_id],
661 				     &mmux->common.hw, parent,
662 				     rate, parent_rate);
663 }
664 
mmux_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)665 static int mmux_determine_rate(struct clk_hw *hw,
666 			       struct clk_rate_request *req)
667 {
668 	struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
669 
670 	return mux_helper_determine_rate(&mmux->common, req,
671 					 mmux_round_rate, mmux);
672 }
673 
mmux_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)674 static unsigned long mmux_recalc_rate(struct clk_hw *hw,
675 				      unsigned long parent_rate)
676 {
677 	struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
678 	unsigned long val;
679 	struct cv1800_clk_regfield *div;
680 
681 	if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass))
682 		return parent_rate;
683 
684 	if (cv1800_clk_checkbit(&mmux->common, &mmux->clk_sel))
685 		div = &mmux->div[0];
686 	else
687 		div = &mmux->div[1];
688 
689 	val = div_helper_get_clockdiv(&mmux->common, div);
690 	if (val == 0)
691 		return 0;
692 
693 	return divider_recalc_rate(hw, parent_rate, val, NULL,
694 				   div->flags, div->width);
695 }
696 
mmux_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)697 static int mmux_set_rate(struct clk_hw *hw, unsigned long rate,
698 			 unsigned long parent_rate)
699 {
700 	struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
701 	struct cv1800_clk_regfield *div;
702 	unsigned long val;
703 
704 	if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass))
705 		return parent_rate;
706 
707 	if (cv1800_clk_checkbit(&mmux->common, &mmux->clk_sel))
708 		div = &mmux->div[0];
709 	else
710 		div = &mmux->div[1];
711 
712 	val = divider_get_val(rate, parent_rate, NULL,
713 			      div->width, div->flags);
714 
715 	return div_helper_set_rate(&mmux->common, div, val);
716 }
717 
mmux_get_parent(struct clk_hw * hw)718 static u8 mmux_get_parent(struct clk_hw *hw)
719 {
720 	struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
721 	struct cv1800_clk_regfield *mux;
722 	u32 reg;
723 	s8 clk_sel;
724 
725 	if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass))
726 		return 0;
727 
728 	if (cv1800_clk_checkbit(&mmux->common, &mmux->clk_sel))
729 		clk_sel = 0;
730 	else
731 		clk_sel = 1;
732 	mux = &mmux->mux[clk_sel];
733 
734 	reg = readl(mmux->common.base + mux->reg);
735 
736 	return mmux->sel2parent[clk_sel][cv1800_clk_regfield_get(reg, mux)];
737 }
738 
mmux_set_parent(struct clk_hw * hw,u8 index)739 static int mmux_set_parent(struct clk_hw *hw, u8 index)
740 {
741 	struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
742 	struct cv1800_clk_regfield *mux;
743 	unsigned long flags;
744 	u32 reg;
745 	s8 clk_sel = mmux->parent2sel[index];
746 
747 	if (index == 0 || clk_sel == -1) {
748 		cv1800_clk_setbit(&mmux->common, &mmux->bypass);
749 		goto release;
750 	}
751 
752 	cv1800_clk_clearbit(&mmux->common, &mmux->bypass);
753 
754 	if (clk_sel)
755 		cv1800_clk_clearbit(&mmux->common, &mmux->clk_sel);
756 	else
757 		cv1800_clk_setbit(&mmux->common, &mmux->clk_sel);
758 
759 	spin_lock_irqsave(mmux->common.lock, flags);
760 
761 	mux = &mmux->mux[clk_sel];
762 	reg = readl(mmux->common.base + mux->reg);
763 	reg = cv1800_clk_regfield_set(reg, index, mux);
764 
765 	writel(reg, mmux->common.base + mux->reg);
766 
767 	spin_unlock_irqrestore(mmux->common.lock, flags);
768 
769 release:
770 	return 0;
771 }
772 
773 const struct clk_ops cv1800_clk_mmux_ops = {
774 	.disable = mmux_disable,
775 	.enable = mmux_enable,
776 	.is_enabled = mmux_is_enabled,
777 
778 	.determine_rate = mmux_determine_rate,
779 	.recalc_rate = mmux_recalc_rate,
780 	.set_rate = mmux_set_rate,
781 
782 	.set_parent = mmux_set_parent,
783 	.get_parent = mmux_get_parent,
784 };
785 
786 /* AUDIO CLK */
787 static inline struct cv1800_clk_audio *
hw_to_cv1800_clk_audio(struct clk_hw * hw)788 hw_to_cv1800_clk_audio(struct clk_hw *hw)
789 {
790 	struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw);
791 
792 	return container_of(common, struct cv1800_clk_audio, common);
793 }
794 
aclk_enable(struct clk_hw * hw)795 static int aclk_enable(struct clk_hw *hw)
796 {
797 	struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw);
798 
799 	cv1800_clk_setbit(&aclk->common, &aclk->src_en);
800 	return cv1800_clk_setbit(&aclk->common, &aclk->output_en);
801 }
802 
aclk_disable(struct clk_hw * hw)803 static void aclk_disable(struct clk_hw *hw)
804 {
805 	struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw);
806 
807 	cv1800_clk_clearbit(&aclk->common, &aclk->output_en);
808 	cv1800_clk_clearbit(&aclk->common, &aclk->src_en);
809 }
810 
aclk_is_enabled(struct clk_hw * hw)811 static int aclk_is_enabled(struct clk_hw *hw)
812 {
813 	struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw);
814 
815 	return cv1800_clk_checkbit(&aclk->common, &aclk->output_en);
816 }
817 
aclk_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)818 static int aclk_determine_rate(struct clk_hw *hw,
819 			       struct clk_rate_request *req)
820 {
821 	struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw);
822 
823 	req->rate = aclk->target_rate;
824 
825 	return 0;
826 }
827 
aclk_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)828 static unsigned long aclk_recalc_rate(struct clk_hw *hw,
829 				      unsigned long parent_rate)
830 {
831 	struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw);
832 	u64 rate = parent_rate;
833 	u64 factor = 2;
834 	u32 regval;
835 
836 	if (!cv1800_clk_checkbit(&aclk->common, &aclk->div_en))
837 		return 0;
838 
839 	regval = readl(aclk->common.base + aclk->m.reg);
840 	factor *= cv1800_clk_regfield_get(regval, &aclk->m);
841 
842 	regval = readl(aclk->common.base + aclk->n.reg);
843 	rate *= cv1800_clk_regfield_get(regval, &aclk->n);
844 
845 	return DIV64_U64_ROUND_UP(rate, factor);
846 }
847 
aclk_determine_mn(unsigned long parent_rate,unsigned long rate,u32 * m,u32 * n)848 static void aclk_determine_mn(unsigned long parent_rate, unsigned long rate,
849 			      u32 *m, u32 *n)
850 {
851 	u32 tm = parent_rate / 2;
852 	u32 tn = rate;
853 	u32 tcommon = gcd(tm, tn);
854 	*m = tm / tcommon;
855 	*n = tn / tcommon;
856 }
857 
aclk_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)858 static int aclk_set_rate(struct clk_hw *hw, unsigned long rate,
859 			 unsigned long parent_rate)
860 {
861 	struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw);
862 	unsigned long flags;
863 	u32 m, n;
864 
865 	aclk_determine_mn(parent_rate, rate,
866 			  &m, &n);
867 
868 	spin_lock_irqsave(aclk->common.lock, flags);
869 
870 	writel(m, aclk->common.base + aclk->m.reg);
871 	writel(n, aclk->common.base + aclk->n.reg);
872 
873 	cv1800_clk_setbit(&aclk->common, &aclk->div_en);
874 	cv1800_clk_setbit(&aclk->common, &aclk->div_up);
875 
876 	spin_unlock_irqrestore(aclk->common.lock, flags);
877 
878 	return 0;
879 }
880 
881 const struct clk_ops cv1800_clk_audio_ops = {
882 	.disable = aclk_disable,
883 	.enable = aclk_enable,
884 	.is_enabled = aclk_is_enabled,
885 
886 	.determine_rate = aclk_determine_rate,
887 	.recalc_rate = aclk_recalc_rate,
888 	.set_rate = aclk_set_rate,
889 };
890