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