blob: 8584a52bca01b387d48c564e9494e532de12ccae [file] [log] [blame]
Gabriel Fernandez1308d752020-03-11 11:30:34 +01001/*
2 * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
3 *
4 * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <errno.h>
9
10#include "clk-stm32-core.h"
11#include <common/debug.h>
12#include <common/fdt_wrappers.h>
13#include <drivers/clk.h>
14#include <drivers/delay_timer.h>
15#include <drivers/st/stm32mp_clkfunc.h>
16#include <lib/mmio.h>
17#include <lib/spinlock.h>
18
19static struct spinlock reg_lock;
20static struct spinlock refcount_lock;
21
22static struct stm32_clk_priv *stm32_clock_data;
23
24const struct stm32_clk_ops clk_mux_ops;
25
26struct stm32_clk_priv *clk_stm32_get_priv(void)
27{
28 return stm32_clock_data;
29}
30
31static void stm32mp1_clk_lock(struct spinlock *lock)
32{
33 if (stm32mp_lock_available()) {
34 /* Assume interrupts are masked */
35 spin_lock(lock);
36 }
37}
38
39static void stm32mp1_clk_unlock(struct spinlock *lock)
40{
41 if (stm32mp_lock_available()) {
42 spin_unlock(lock);
43 }
44}
45
46void stm32mp1_clk_rcc_regs_lock(void)
47{
48 stm32mp1_clk_lock(&reg_lock);
49}
50
51void stm32mp1_clk_rcc_regs_unlock(void)
52{
53 stm32mp1_clk_unlock(&reg_lock);
54}
55
56#define TIMEOUT_US_1S U(1000000)
57#define OSCRDY_TIMEOUT TIMEOUT_US_1S
58
59struct clk_oscillator_data *clk_oscillator_get_data(struct stm32_clk_priv *priv, int id)
60{
61 const struct clk_stm32 *clk = _clk_get(priv, id);
62 struct stm32_osc_cfg *osc_cfg = clk->clock_cfg;
63 int osc_id = osc_cfg->osc_id;
64
65 return &priv->osci_data[osc_id];
66}
67
68void clk_oscillator_set_bypass(struct stm32_clk_priv *priv, int id, bool digbyp, bool bypass)
69{
70 struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
71
72 struct stm32_clk_bypass *bypass_data = osc_data->bypass;
73 uintptr_t address;
74
75 if (bypass_data == NULL) {
76 return;
77 }
78
79 address = priv->base + bypass_data->offset;
80
81 if (digbyp) {
82 mmio_setbits_32(address, BIT(bypass_data->bit_digbyp));
83 }
84
85 if (bypass || digbyp) {
86 mmio_setbits_32(address, BIT(bypass_data->bit_byp));
87 }
88}
89
90void clk_oscillator_set_css(struct stm32_clk_priv *priv, int id, bool css)
91{
92 struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
93
94 struct stm32_clk_css *css_data = osc_data->css;
95 uintptr_t address;
96
97 if (css_data == NULL) {
98 return;
99 }
100
101 address = priv->base + css_data->offset;
102
103 if (css) {
104 mmio_setbits_32(address, BIT(css_data->bit_css));
105 }
106}
107
108void clk_oscillator_set_drive(struct stm32_clk_priv *priv, int id, uint8_t lsedrv)
109{
110 struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
111
112 struct stm32_clk_drive *drive_data = osc_data->drive;
113 uintptr_t address;
114 uint32_t mask;
115 uint32_t value;
116
117 if (drive_data == NULL) {
118 return;
119 }
120
121 address = priv->base + drive_data->offset;
122
123 mask = (BIT(drive_data->drv_width) - 1U) << drive_data->drv_shift;
124
125 /*
126 * Warning: not recommended to switch directly from "high drive"
127 * to "medium low drive", and vice-versa.
128 */
129 value = (mmio_read_32(address) & mask) >> drive_data->drv_shift;
130
131 while (value != lsedrv) {
132 if (value > lsedrv) {
133 value--;
134 } else {
135 value++;
136 }
137
138 mmio_clrsetbits_32(address, mask, value << drive_data->drv_shift);
139 }
140}
141
142int clk_oscillator_wait_ready(struct stm32_clk_priv *priv, int id, bool ready_on)
143{
144 struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
145
Yann Gautier8d137232022-06-21 15:12:27 +0200146 return _clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, ready_on);
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100147}
148
149int clk_oscillator_wait_ready_on(struct stm32_clk_priv *priv, int id)
150{
151 return clk_oscillator_wait_ready(priv, id, true);
152}
153
154int clk_oscillator_wait_ready_off(struct stm32_clk_priv *priv, int id)
155{
156 return clk_oscillator_wait_ready(priv, id, false);
157}
158
159static int clk_gate_enable(struct stm32_clk_priv *priv, int id)
160{
161 const struct clk_stm32 *clk = _clk_get(priv, id);
162 struct clk_gate_cfg *cfg = clk->clock_cfg;
163
164 mmio_setbits_32(priv->base + cfg->offset, BIT(cfg->bit_idx));
165
166 return 0;
167}
168
169static void clk_gate_disable(struct stm32_clk_priv *priv, int id)
170{
171 const struct clk_stm32 *clk = _clk_get(priv, id);
172 struct clk_gate_cfg *cfg = clk->clock_cfg;
173
174 mmio_clrbits_32(priv->base + cfg->offset, BIT(cfg->bit_idx));
175}
176
177static bool clk_gate_is_enabled(struct stm32_clk_priv *priv, int id)
178{
179 const struct clk_stm32 *clk = _clk_get(priv, id);
180 struct clk_gate_cfg *cfg = clk->clock_cfg;
181
182 return ((mmio_read_32(priv->base + cfg->offset) & BIT(cfg->bit_idx)) != 0U);
183}
184
185const struct stm32_clk_ops clk_gate_ops = {
186 .enable = clk_gate_enable,
187 .disable = clk_gate_disable,
188 .is_enabled = clk_gate_is_enabled,
189};
190
191void _clk_stm32_gate_disable(struct stm32_clk_priv *priv, uint16_t gate_id)
192{
193 const struct gate_cfg *gate = &priv->gates[gate_id];
194 uintptr_t addr = priv->base + gate->offset;
195
196 if (gate->set_clr != 0U) {
197 mmio_write_32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx));
198 } else {
199 mmio_clrbits_32(addr, BIT(gate->bit_idx));
200 }
201}
202
203int _clk_stm32_gate_enable(struct stm32_clk_priv *priv, uint16_t gate_id)
204{
205 const struct gate_cfg *gate = &priv->gates[gate_id];
206 uintptr_t addr = priv->base + gate->offset;
207
208 if (gate->set_clr != 0U) {
209 mmio_write_32(addr, BIT(gate->bit_idx));
210
211 } else {
212 mmio_setbits_32(addr, BIT(gate->bit_idx));
213 }
214
215 return 0;
216}
217
218const char *_clk_stm32_get_name(struct stm32_clk_priv *priv, int id)
219{
220 return priv->clks[id].name;
221}
222
223const char *clk_stm32_get_name(struct stm32_clk_priv *priv,
224 unsigned long binding_id)
225{
226 int id;
227
228 id = clk_get_index(priv, binding_id);
229 if (id == -EINVAL) {
230 return NULL;
231 }
232
233 return _clk_stm32_get_name(priv, id);
234}
235
236const struct clk_stm32 *_clk_get(struct stm32_clk_priv *priv, int id)
237{
238 if ((unsigned int)id < priv->num) {
239 return &priv->clks[id];
240 }
241
242 return NULL;
243}
244
245#define clk_div_mask(_width) GENMASK(((_width) - 1U), 0U)
246
247static unsigned int _get_table_div(const struct clk_div_table *table,
248 unsigned int val)
249{
250 const struct clk_div_table *clkt;
251
252 for (clkt = table; clkt->div; clkt++) {
253 if (clkt->val == val) {
254 return clkt->div;
255 }
256 }
257
258 return 0;
259}
260
261static unsigned int _get_div(const struct clk_div_table *table,
262 unsigned int val, unsigned long flags,
263 uint8_t width)
264{
265 if ((flags & CLK_DIVIDER_ONE_BASED) != 0UL) {
266 return val;
267 }
268
269 if ((flags & CLK_DIVIDER_POWER_OF_TWO) != 0UL) {
270 return BIT(val);
271 }
272
273 if ((flags & CLK_DIVIDER_MAX_AT_ZERO) != 0UL) {
274 return (val != 0U) ? val : BIT(width);
275 }
276
277 if (table != NULL) {
278 return _get_table_div(table, val);
279 }
280
281 return val + 1U;
282}
283
284#define TIMEOUT_US_200MS U(200000)
285#define CLKSRC_TIMEOUT TIMEOUT_US_200MS
286
287int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel)
288{
289 const struct parent_cfg *parents = &priv->parents[pid & MUX_PARENT_MASK];
290 const struct mux_cfg *mux = parents->mux;
291 uintptr_t address = priv->base + mux->offset;
292 uint32_t mask;
293 uint64_t timeout;
294
295 mask = MASK_WIDTH_SHIFT(mux->width, mux->shift);
296
297 mmio_clrsetbits_32(address, mask, (sel << mux->shift) & mask);
298
299 if (mux->bitrdy == MUX_NO_BIT_RDY) {
300 return 0;
301 }
302
303 timeout = timeout_init_us(CLKSRC_TIMEOUT);
304
305 mask = BIT(mux->bitrdy);
306
307 while ((mmio_read_32(address) & mask) == 0U) {
308 if (timeout_elapsed(timeout)) {
309 return -ETIMEDOUT;
310 }
311 }
312
313 return 0;
314}
315
316int _clk_stm32_set_parent(struct stm32_clk_priv *priv, int clk, int clkp)
317{
318 const struct parent_cfg *parents;
319 uint16_t pid;
320 uint8_t sel;
321 int old_parent;
322
323 pid = priv->clks[clk].parent;
324
325 if ((pid == CLK_IS_ROOT) || (pid < MUX_MAX_PARENTS)) {
326 return -EINVAL;
327 }
328
329 old_parent = _clk_stm32_get_parent(priv, clk);
Yann Gautier972221c2022-03-29 09:51:21 +0200330 if (old_parent < 0) {
331 return old_parent;
332 }
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100333 if (old_parent == clkp) {
334 return 0;
335 }
336
337 parents = &priv->parents[pid & MUX_PARENT_MASK];
338
339 for (sel = 0; sel < parents->num_parents; sel++) {
340 if (parents->id_parents[sel] == (uint16_t)clkp) {
341 bool clk_was_enabled = _clk_stm32_is_enabled(priv, clk);
342 int err = 0;
343
344 /* Enable the parents (for glitch free mux) */
345 _clk_stm32_enable(priv, clkp);
346 _clk_stm32_enable(priv, old_parent);
347
348 err = clk_mux_set_parent(priv, pid, sel);
349
350 _clk_stm32_disable(priv, old_parent);
351
352 if (clk_was_enabled) {
353 _clk_stm32_disable(priv, old_parent);
354 } else {
355 _clk_stm32_disable(priv, clkp);
356 }
357
358 return err;
359 }
360 }
361
362 return -EINVAL;
363}
364
365int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id)
366{
367 const struct parent_cfg *parent;
368 const struct mux_cfg *mux;
369 uint32_t mask;
370
371 if (mux_id >= priv->nb_parents) {
372 panic();
373 }
374
375 parent = &priv->parents[mux_id];
376 mux = parent->mux;
377
378 mask = MASK_WIDTH_SHIFT(mux->width, mux->shift);
379
380 return (mmio_read_32(priv->base + mux->offset) & mask) >> mux->shift;
381}
382
383int _clk_stm32_set_parent_by_index(struct stm32_clk_priv *priv, int clk, int sel)
384{
385 uint16_t pid;
386
387 pid = priv->clks[clk].parent;
388
389 if ((pid == CLK_IS_ROOT) || (pid < MUX_MAX_PARENTS)) {
390 return -EINVAL;
391 }
392
393 return clk_mux_set_parent(priv, pid, sel);
394}
395
396int _clk_stm32_get_parent(struct stm32_clk_priv *priv, int clk_id)
397{
398 const struct clk_stm32 *clk = _clk_get(priv, clk_id);
399 const struct parent_cfg *parent;
400 uint16_t mux_id;
401 int sel;
402
403 mux_id = priv->clks[clk_id].parent;
404 if (mux_id == CLK_IS_ROOT) {
405 return CLK_IS_ROOT;
406 }
407
408 if (mux_id < MUX_MAX_PARENTS) {
409 return mux_id & MUX_PARENT_MASK;
410 }
411
412 mux_id &= MUX_PARENT_MASK;
413 parent = &priv->parents[mux_id];
414
415 if (clk->ops->get_parent != NULL) {
416 sel = clk->ops->get_parent(priv, clk_id);
417 } else {
418 sel = clk_mux_get_parent(priv, mux_id);
419 }
420
Yann Gautier972221c2022-03-29 09:51:21 +0200421 if ((sel >= 0) && (sel < parent->num_parents)) {
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100422 return parent->id_parents[sel];
423 }
424
425 return -EINVAL;
426}
427
428int _clk_stm32_get_parent_index(struct stm32_clk_priv *priv, int clk_id)
429{
430 uint16_t mux_id;
431
432 mux_id = priv->clks[clk_id].parent;
433 if (mux_id == CLK_IS_ROOT) {
434 return CLK_IS_ROOT;
435 }
436
437 if (mux_id < MUX_MAX_PARENTS) {
438 return mux_id & MUX_PARENT_MASK;
439 }
440
441 mux_id &= MUX_PARENT_MASK;
442
443 return clk_mux_get_parent(priv, mux_id);
444}
445
446int _clk_stm32_get_parent_by_index(struct stm32_clk_priv *priv, int clk_id, int idx)
447{
448 const struct parent_cfg *parent;
449 uint16_t mux_id;
450
451 mux_id = priv->clks[clk_id].parent;
452 if (mux_id == CLK_IS_ROOT) {
453 return CLK_IS_ROOT;
454 }
455
456 if (mux_id < MUX_MAX_PARENTS) {
457 return mux_id & MUX_PARENT_MASK;
458 }
459
460 mux_id &= MUX_PARENT_MASK;
461 parent = &priv->parents[mux_id];
462
463 if (idx < parent->num_parents) {
464 return parent->id_parents[idx];
465 }
466
467 return -EINVAL;
468}
469
470int clk_get_index(struct stm32_clk_priv *priv, unsigned long binding_id)
471{
472 unsigned int i;
473
474 for (i = 0U; i < priv->num; i++) {
475 if (binding_id == priv->clks[i].binding) {
476 return (int)i;
477 }
478 }
479
480 return -EINVAL;
481}
482
483unsigned long _clk_stm32_get_rate(struct stm32_clk_priv *priv, int id)
484{
485 const struct clk_stm32 *clk = _clk_get(priv, id);
486 int parent;
487 unsigned long rate = 0UL;
488
489 if ((unsigned int)id >= priv->num) {
490 return rate;
491 }
492
493 parent = _clk_stm32_get_parent(priv, id);
Yann Gautier972221c2022-03-29 09:51:21 +0200494 if (parent < 0) {
495 return 0UL;
496 }
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100497
498 if (clk->ops->recalc_rate != NULL) {
499 unsigned long prate = 0UL;
500
501 if (parent != CLK_IS_ROOT) {
502 prate = _clk_stm32_get_rate(priv, parent);
503 }
504
505 rate = clk->ops->recalc_rate(priv, id, prate);
506
507 return rate;
508 }
509
510 switch (parent) {
511 case CLK_IS_ROOT:
512 panic();
513
514 default:
515 rate = _clk_stm32_get_rate(priv, parent);
516 break;
517 }
518 return rate;
519
520}
521
522unsigned long _clk_stm32_get_parent_rate(struct stm32_clk_priv *priv, int id)
523{
524 int parent_id = _clk_stm32_get_parent(priv, id);
525
Yann Gautier972221c2022-03-29 09:51:21 +0200526 if (parent_id < 0) {
527 return 0UL;
528 }
529
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100530 return _clk_stm32_get_rate(priv, parent_id);
531}
532
533static uint8_t _stm32_clk_get_flags(struct stm32_clk_priv *priv, int id)
534{
535 return priv->clks[id].flags;
536}
537
538bool _stm32_clk_is_flags(struct stm32_clk_priv *priv, int id, uint8_t flag)
539{
540 if (_stm32_clk_get_flags(priv, id) & flag) {
541 return true;
542 }
543
544 return false;
545}
546
547int clk_stm32_enable_call_ops(struct stm32_clk_priv *priv, uint16_t id)
548{
549 const struct clk_stm32 *clk = _clk_get(priv, id);
550
551 if (clk->ops->enable != NULL) {
552 clk->ops->enable(priv, id);
553 }
554
555 return 0;
556}
557
558static int _clk_stm32_enable_core(struct stm32_clk_priv *priv, int id)
559{
560 int parent;
561 int ret = 0;
562
563 if (priv->gate_refcounts[id] == 0U) {
564 parent = _clk_stm32_get_parent(priv, id);
Yann Gautier972221c2022-03-29 09:51:21 +0200565 if (parent < 0) {
566 return parent;
567 }
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100568 if (parent != CLK_IS_ROOT) {
569 ret = _clk_stm32_enable_core(priv, parent);
570 if (ret) {
571 return ret;
572 }
573 }
574 clk_stm32_enable_call_ops(priv, id);
575 }
576
577 priv->gate_refcounts[id]++;
578
579 if (priv->gate_refcounts[id] == UINT_MAX) {
580 ERROR("%s: %d max enable count !", __func__, id);
581 panic();
582 }
583
584 return 0;
585}
586
587int _clk_stm32_enable(struct stm32_clk_priv *priv, int id)
588{
589 int ret;
590
591 stm32mp1_clk_lock(&refcount_lock);
592 ret = _clk_stm32_enable_core(priv, id);
593 stm32mp1_clk_unlock(&refcount_lock);
594
595 return ret;
596}
597
598void clk_stm32_disable_call_ops(struct stm32_clk_priv *priv, uint16_t id)
599{
600 const struct clk_stm32 *clk = _clk_get(priv, id);
601
602 if (clk->ops->disable != NULL) {
603 clk->ops->disable(priv, id);
604 }
605}
606
607static void _clk_stm32_disable_core(struct stm32_clk_priv *priv, int id)
608{
609 int parent;
610
611 if ((priv->gate_refcounts[id] == 1U) && _stm32_clk_is_flags(priv, id, CLK_IS_CRITICAL)) {
612 return;
613 }
614
615 if (priv->gate_refcounts[id] == 0U) {
616 /* case of clock ignore unused */
617 if (_clk_stm32_is_enabled(priv, id)) {
618 clk_stm32_disable_call_ops(priv, id);
619 return;
620 }
621 VERBOSE("%s: %d already disabled !\n\n", __func__, id);
622 return;
623 }
624
625 if (--priv->gate_refcounts[id] > 0U) {
626 return;
627 }
628
629 clk_stm32_disable_call_ops(priv, id);
630
631 parent = _clk_stm32_get_parent(priv, id);
Yann Gautier972221c2022-03-29 09:51:21 +0200632 if ((parent >= 0) && (parent != CLK_IS_ROOT)) {
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100633 _clk_stm32_disable_core(priv, parent);
634 }
635}
636
637void _clk_stm32_disable(struct stm32_clk_priv *priv, int id)
638{
639 stm32mp1_clk_lock(&refcount_lock);
640
641 _clk_stm32_disable_core(priv, id);
642
643 stm32mp1_clk_unlock(&refcount_lock);
644}
645
646bool _clk_stm32_is_enabled(struct stm32_clk_priv *priv, int id)
647{
648 const struct clk_stm32 *clk = _clk_get(priv, id);
649
650 if (clk->ops->is_enabled != NULL) {
651 return clk->ops->is_enabled(priv, id);
652 }
653
654 return priv->gate_refcounts[id];
655}
656
657static int clk_stm32_enable(unsigned long binding_id)
658{
659 struct stm32_clk_priv *priv = clk_stm32_get_priv();
660 int id;
661
662 id = clk_get_index(priv, binding_id);
663 if (id == -EINVAL) {
664 return id;
665 }
666
667 return _clk_stm32_enable(priv, id);
668}
669
670static void clk_stm32_disable(unsigned long binding_id)
671{
672 struct stm32_clk_priv *priv = clk_stm32_get_priv();
673 int id;
674
675 id = clk_get_index(priv, binding_id);
676 if (id != -EINVAL) {
677 _clk_stm32_disable(priv, id);
678 }
679}
680
681static bool clk_stm32_is_enabled(unsigned long binding_id)
682{
683 struct stm32_clk_priv *priv = clk_stm32_get_priv();
684 int id;
685
686 id = clk_get_index(priv, binding_id);
687 if (id == -EINVAL) {
688 return false;
689 }
690
691 return _clk_stm32_is_enabled(priv, id);
692}
693
694static unsigned long clk_stm32_get_rate(unsigned long binding_id)
695{
696 struct stm32_clk_priv *priv = clk_stm32_get_priv();
697 int id;
698
699 id = clk_get_index(priv, binding_id);
700 if (id == -EINVAL) {
701 return 0UL;
702 }
703
704 return _clk_stm32_get_rate(priv, id);
705}
706
707static int clk_stm32_get_parent(unsigned long binding_id)
708{
709 struct stm32_clk_priv *priv = clk_stm32_get_priv();
710 int id;
711
712 id = clk_get_index(priv, binding_id);
713 if (id == -EINVAL) {
714 return id;
715 }
716
717 return _clk_stm32_get_parent(priv, id);
718}
719
720static const struct clk_ops stm32mp_clk_ops = {
721 .enable = clk_stm32_enable,
722 .disable = clk_stm32_disable,
723 .is_enabled = clk_stm32_is_enabled,
724 .get_rate = clk_stm32_get_rate,
725 .get_parent = clk_stm32_get_parent,
726};
727
728void clk_stm32_enable_critical_clocks(void)
729{
730 struct stm32_clk_priv *priv = clk_stm32_get_priv();
731 unsigned int i;
732
733 for (i = 0U; i < priv->num; i++) {
734 if (_stm32_clk_is_flags(priv, i, CLK_IS_CRITICAL)) {
735 _clk_stm32_enable(priv, i);
736 }
737 }
738}
739
740static void stm32_clk_register(void)
741{
742 clk_register(&stm32mp_clk_ops);
743}
744
745uint32_t clk_stm32_div_get_value(struct stm32_clk_priv *priv, int div_id)
746{
747 const struct div_cfg *divider = &priv->div[div_id];
748 uint32_t val = 0;
749
750 val = mmio_read_32(priv->base + divider->offset) >> divider->shift;
751 val &= clk_div_mask(divider->width);
752
753 return val;
754}
755
756unsigned long _clk_stm32_divider_recalc(struct stm32_clk_priv *priv,
757 int div_id,
758 unsigned long prate)
759{
760 const struct div_cfg *divider = &priv->div[div_id];
761 uint32_t val = clk_stm32_div_get_value(priv, div_id);
762 unsigned int div = 0U;
763
764 div = _get_div(divider->table, val, divider->flags, divider->width);
765 if (div == 0U) {
766 return prate;
767 }
768
769 return div_round_up((uint64_t)prate, div);
770}
771
772unsigned long clk_stm32_divider_recalc(struct stm32_clk_priv *priv, int id,
773 unsigned long prate)
774{
775 const struct clk_stm32 *clk = _clk_get(priv, id);
776 struct clk_stm32_div_cfg *div_cfg = clk->clock_cfg;
777
778 return _clk_stm32_divider_recalc(priv, div_cfg->id, prate);
779}
780
781const struct stm32_clk_ops clk_stm32_divider_ops = {
782 .recalc_rate = clk_stm32_divider_recalc,
783};
784
785int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value)
786{
787 const struct div_cfg *divider;
788 uintptr_t address;
789 uint64_t timeout;
790 uint32_t mask;
791
792 if (div_id >= priv->nb_div) {
793 panic();
794 }
795
796 divider = &priv->div[div_id];
797 address = priv->base + divider->offset;
798
799 mask = MASK_WIDTH_SHIFT(divider->width, divider->shift);
800 mmio_clrsetbits_32(address, mask, (value << divider->shift) & mask);
801
802 if (divider->bitrdy == DIV_NO_BIT_RDY) {
803 return 0;
804 }
805
806 timeout = timeout_init_us(CLKSRC_TIMEOUT);
807 mask = BIT(divider->bitrdy);
808
809 while ((mmio_read_32(address) & mask) == 0U) {
810 if (timeout_elapsed(timeout)) {
811 return -ETIMEDOUT;
812 }
813 }
814
815 return 0;
816}
817
818int _clk_stm32_gate_wait_ready(struct stm32_clk_priv *priv, uint16_t gate_id,
819 bool ready_on)
820{
821 const struct gate_cfg *gate = &priv->gates[gate_id];
822 uintptr_t address = priv->base + gate->offset;
823 uint32_t mask_rdy = BIT(gate->bit_idx);
824 uint64_t timeout;
825 uint32_t mask_test;
826
827 if (ready_on) {
828 mask_test = BIT(gate->bit_idx);
829 } else {
830 mask_test = 0U;
831 }
832
833 timeout = timeout_init_us(OSCRDY_TIMEOUT);
834
835 while ((mmio_read_32(address) & mask_rdy) != mask_test) {
836 if (timeout_elapsed(timeout)) {
837 break;
838 }
839 }
840
Yann Gautierbd513f52022-06-21 14:34:13 +0200841 if ((mmio_read_32(address) & mask_rdy) != mask_test) {
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100842 return -ETIMEDOUT;
Yann Gautierbd513f52022-06-21 14:34:13 +0200843 }
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100844
845 return 0;
846}
847
848int clk_stm32_gate_enable(struct stm32_clk_priv *priv, int id)
849{
850 const struct clk_stm32 *clk = _clk_get(priv, id);
851 struct clk_stm32_gate_cfg *cfg = clk->clock_cfg;
852 const struct gate_cfg *gate = &priv->gates[cfg->id];
853 uintptr_t addr = priv->base + gate->offset;
854
855 if (gate->set_clr != 0U) {
856 mmio_write_32(addr, BIT(gate->bit_idx));
857
858 } else {
859 mmio_setbits_32(addr, BIT(gate->bit_idx));
860 }
861
862 return 0;
863}
864
865void clk_stm32_gate_disable(struct stm32_clk_priv *priv, int id)
866{
867 const struct clk_stm32 *clk = _clk_get(priv, id);
868 struct clk_stm32_gate_cfg *cfg = clk->clock_cfg;
869 const struct gate_cfg *gate = &priv->gates[cfg->id];
870 uintptr_t addr = priv->base + gate->offset;
871
872 if (gate->set_clr != 0U) {
873 mmio_write_32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx));
874 } else {
875 mmio_clrbits_32(addr, BIT(gate->bit_idx));
876 }
877}
878
879bool _clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int gate_id)
880{
881 const struct gate_cfg *gate;
882 uint32_t addr;
883
884 gate = &priv->gates[gate_id];
885 addr = priv->base + gate->offset;
886
887 return ((mmio_read_32(addr) & BIT(gate->bit_idx)) != 0U);
888}
889
890bool clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int id)
891{
892 const struct clk_stm32 *clk = _clk_get(priv, id);
893 struct clk_stm32_gate_cfg *cfg = clk->clock_cfg;
894
895 return _clk_stm32_gate_is_enabled(priv, cfg->id);
896}
897
898const struct stm32_clk_ops clk_stm32_gate_ops = {
899 .enable = clk_stm32_gate_enable,
900 .disable = clk_stm32_gate_disable,
901 .is_enabled = clk_stm32_gate_is_enabled,
902};
903
904const struct stm32_clk_ops clk_fixed_factor_ops = {
905 .recalc_rate = fixed_factor_recalc_rate,
906};
907
908unsigned long fixed_factor_recalc_rate(struct stm32_clk_priv *priv,
909 int id, unsigned long prate)
910{
911 const struct clk_stm32 *clk = _clk_get(priv, id);
912 const struct fixed_factor_cfg *cfg = clk->clock_cfg;
913 unsigned long long rate;
914
915 rate = (unsigned long long)prate * cfg->mult;
916
917 if (cfg->div == 0U) {
918 ERROR("division by zero\n");
919 panic();
920 }
921
922 return (unsigned long)(rate / cfg->div);
923};
924
925#define APB_DIV_MASK GENMASK(2, 0)
926#define TIM_PRE_MASK BIT(0)
927
928static unsigned long timer_recalc_rate(struct stm32_clk_priv *priv,
929 int id, unsigned long prate)
930{
931 const struct clk_stm32 *clk = _clk_get(priv, id);
932 const struct clk_timer_cfg *cfg = clk->clock_cfg;
933 uint32_t prescaler, timpre;
934 uintptr_t rcc_base = priv->base;
935
936 prescaler = mmio_read_32(rcc_base + cfg->apbdiv) &
937 APB_DIV_MASK;
938
939 timpre = mmio_read_32(rcc_base + cfg->timpre) &
940 TIM_PRE_MASK;
941
942 if (prescaler == 0U) {
943 return prate;
944 }
945
946 return prate * (timpre + 1U) * 2U;
947};
948
949const struct stm32_clk_ops clk_timer_ops = {
950 .recalc_rate = timer_recalc_rate,
951};
952
953static unsigned long clk_fixed_rate_recalc(struct stm32_clk_priv *priv, int id,
954 unsigned long prate)
955{
956 const struct clk_stm32 *clk = _clk_get(priv, id);
957 struct clk_stm32_fixed_rate_cfg *cfg = clk->clock_cfg;
958
959 return cfg->rate;
960}
961
962const struct stm32_clk_ops clk_stm32_fixed_rate_ops = {
963 .recalc_rate = clk_fixed_rate_recalc,
964};
965
966static unsigned long clk_stm32_osc_recalc_rate(struct stm32_clk_priv *priv,
967 int id, unsigned long prate)
968{
969 struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
970
971 return osc_data->frequency;
972};
973
974bool clk_stm32_osc_gate_is_enabled(struct stm32_clk_priv *priv, int id)
975{
976 struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
977
978 return _clk_stm32_gate_is_enabled(priv, osc_data->gate_id);
979
980}
981
982int clk_stm32_osc_gate_enable(struct stm32_clk_priv *priv, int id)
983{
984 struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
985
986 _clk_stm32_gate_enable(priv, osc_data->gate_id);
987
988 if (_clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, true) != 0U) {
989 ERROR("%s: %s (%d)\n", __func__, osc_data->name, __LINE__);
990 panic();
991 }
992
993 return 0;
994}
995
996void clk_stm32_osc_gate_disable(struct stm32_clk_priv *priv, int id)
997{
998 struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
999
1000 _clk_stm32_gate_disable(priv, osc_data->gate_id);
1001
1002 if (_clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, false) != 0U) {
1003 ERROR("%s: %s (%d)\n", __func__, osc_data->name, __LINE__);
1004 panic();
1005 }
1006}
1007
1008static unsigned long clk_stm32_get_dt_oscillator_frequency(const char *name)
1009{
1010 void *fdt = NULL;
1011 int node = 0;
1012 int subnode = 0;
1013
1014 if (fdt_get_address(&fdt) == 0) {
1015 panic();
1016 }
1017
1018 node = fdt_path_offset(fdt, "/clocks");
1019 if (node < 0) {
1020 return 0UL;
1021 }
1022
1023 fdt_for_each_subnode(subnode, fdt, node) {
1024 const char *cchar = NULL;
1025 const fdt32_t *cuint = NULL;
1026 int ret = 0;
1027
1028 cchar = fdt_get_name(fdt, subnode, &ret);
1029 if (cchar == NULL) {
1030 continue;
1031 }
1032
1033 if (strncmp(cchar, name, (size_t)ret) ||
1034 fdt_get_status(subnode) == DT_DISABLED) {
1035 continue;
1036 }
1037
1038 cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret);
1039 if (cuint == NULL) {
1040 return 0UL;
1041 }
1042
1043 return fdt32_to_cpu(*cuint);
1044 }
1045
1046 return 0UL;
1047}
1048
1049void clk_stm32_osc_init(struct stm32_clk_priv *priv, int id)
1050{
1051 struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id);
1052 const char *name = osc_data->name;
1053
1054 osc_data->frequency = clk_stm32_get_dt_oscillator_frequency(name);
1055}
1056
1057const struct stm32_clk_ops clk_stm32_osc_ops = {
1058 .recalc_rate = clk_stm32_osc_recalc_rate,
1059 .is_enabled = clk_stm32_osc_gate_is_enabled,
1060 .enable = clk_stm32_osc_gate_enable,
1061 .disable = clk_stm32_osc_gate_disable,
1062 .init = clk_stm32_osc_init,
1063};
1064
1065const struct stm32_clk_ops clk_stm32_osc_nogate_ops = {
1066 .recalc_rate = clk_stm32_osc_recalc_rate,
1067 .init = clk_stm32_osc_init,
1068};
1069
1070int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb)
1071{
1072 const fdt32_t *cell;
1073 int len = 0;
1074 uint32_t i;
1075
1076 cell = fdt_getprop(fdt, node, name, &len);
Yann Gautierd56fff32022-04-05 15:16:28 +02001077 if (cell == NULL) {
1078 *nb = 0U;
1079 return 0;
1080 }
1081
1082 for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
1083 uint32_t val = fdt32_to_cpu(cell[i]);
Gabriel Fernandez1308d752020-03-11 11:30:34 +01001084
Yann Gautierd56fff32022-04-05 15:16:28 +02001085 tab[i] = val;
Gabriel Fernandez1308d752020-03-11 11:30:34 +01001086 }
1087
1088 *nb = (uint32_t)len / sizeof(uint32_t);
1089
1090 return 0;
1091}
1092
1093int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base)
1094{
1095 unsigned int i;
1096
1097 stm32_clock_data = priv;
1098
1099 priv->base = base;
1100
1101 for (i = 0U; i < priv->num; i++) {
1102 const struct clk_stm32 *clk = _clk_get(priv, i);
1103
1104 assert(clk->ops != NULL);
1105
1106 if (clk->ops->init != NULL) {
1107 clk->ops->init(priv, i);
1108 }
1109 }
1110
1111 stm32_clk_register();
1112
1113 return 0;
1114}