Lines Matching +full:shared +full:- +full:lrclk

1 // SPDX-License-Identifier: GPL-2.0
8 * - Root source, usually 12MHz supplied by an external crystal
9 * - 3 PLLs which generate multiples of root rate [AUX, CPU, AUX2]
12 * - 6 clock dividers with:
18 * - up to 6 "internal" (fixed) consumers which:
24 * - sysbus clock: CPU core clock (CPUPLL) divided by 2, 3 or 4.
25 * depends on board design and should be set by bootloader, read-only.
26 * - peripheral clock: half the rate of sysbus clock, source for a lot
27 * of peripheral blocks, read-only.
28 * - memory clock: clk rate to main memory chips, depends on board
29 * design and is read-only,
30 * - lrclk: the static bus clock signal for synchronous operation.
40 #include <linux/clk-provider.h>
45 #include <asm/mach-au1x00/au1000.h>
84 /* aliases for a few on-chip sources which are either shared
124 * On early Au1000, sys_cpupll was write-only. Since these in alchemy_clk_cpu_recalc()
159 return ERR_PTR(-ENOMEM); in alchemy_clk_setup_cpu()
166 h->init = &id; in alchemy_clk_setup_cpu()
191 return (alchemy_rdsys(a->reg) & 0xff) * parent_rate; in alchemy_clk_aux_recalc()
206 /* minimum is 84MHz, max is 756-1032 depending on variant */ in alchemy_clk_aux_setr()
207 if (((d < 7) && (d != 0)) || (d > a->maxmult)) in alchemy_clk_aux_setr()
208 return -EINVAL; in alchemy_clk_aux_setr()
210 alchemy_wrsys(d, a->reg); in alchemy_clk_aux_setr()
228 if (mult > a->maxmult) in alchemy_clk_aux_roundr()
229 mult = a->maxmult; in alchemy_clk_aux_roundr()
250 return ERR_PTR(-ENOMEM); in alchemy_clk_setup_aux()
258 a->reg = reg; in alchemy_clk_setup_aux()
259 a->maxmult = maxmult; in alchemy_clk_setup_aux()
260 a->hw.init = &id; in alchemy_clk_setup_aux()
262 c = clk_register(NULL, &a->hw); in alchemy_clk_setup_aux()
333 /* lrclk: external synchronous static bus clock ***********************/
337 /* Au1000, Au1500: MEM_STCFG0[11]: If bit is set, lrclk=pclk/5, in alchemy_clk_setup_lrclk()
338 * otherwise lrclk=pclk/4. in alchemy_clk_setup_lrclk()
364 /* data for fgen and csrc mux-dividers */
385 if (scale == 2) { /* only div-by-multiple-of-2 possible */ in alchemy_calc_div()
390 div2 = (div1 / scale) - 1; /* value to write to register */ in alchemy_calc_div()
412 br = -EINVAL; in alchemy_clk_fgcs_detr()
425 * but this is a good-enough approximation for now. in alchemy_clk_fgcs_detr()
433 if (pr < req->rate) in alchemy_clk_fgcs_detr()
437 tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv, NULL); in alchemy_clk_fgcs_detr()
439 diff = req->rate - nr; in alchemy_clk_fgcs_detr()
440 if (nr > req->rate) in alchemy_clk_fgcs_detr()
459 tpr = req->rate * j; in alchemy_clk_fgcs_detr()
464 tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv, in alchemy_clk_fgcs_detr()
467 diff = req->rate - nr; in alchemy_clk_fgcs_detr()
468 if (nr > req->rate) in alchemy_clk_fgcs_detr()
484 req->best_parent_rate = bpr; in alchemy_clk_fgcs_detr()
485 req->best_parent_hw = bpc; in alchemy_clk_fgcs_detr()
486 req->rate = br; in alchemy_clk_fgcs_detr()
496 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_fgv1_en()
497 v = alchemy_rdsys(c->reg); in alchemy_clk_fgv1_en()
498 v |= (1 << 1) << c->shift; in alchemy_clk_fgv1_en()
499 alchemy_wrsys(v, c->reg); in alchemy_clk_fgv1_en()
500 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_fgv1_en()
508 unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 1); in alchemy_clk_fgv1_isen()
518 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_fgv1_dis()
519 v = alchemy_rdsys(c->reg); in alchemy_clk_fgv1_dis()
520 v &= ~((1 << 1) << c->shift); in alchemy_clk_fgv1_dis()
521 alchemy_wrsys(v, c->reg); in alchemy_clk_fgv1_dis()
522 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_fgv1_dis()
530 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_fgv1_setp()
531 v = alchemy_rdsys(c->reg); in alchemy_clk_fgv1_setp()
533 v |= (1 << c->shift); in alchemy_clk_fgv1_setp()
535 v &= ~(1 << c->shift); in alchemy_clk_fgv1_setp()
536 alchemy_wrsys(v, c->reg); in alchemy_clk_fgv1_setp()
537 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_fgv1_setp()
546 return (alchemy_rdsys(c->reg) >> c->shift) & 1; in alchemy_clk_fgv1_getp()
554 int sh = c->shift + 2; in alchemy_clk_fgv1_setr()
557 return -EINVAL; in alchemy_clk_fgv1_setr()
559 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_fgv1_setr()
560 v = alchemy_rdsys(c->reg); in alchemy_clk_fgv1_setr()
563 alchemy_wrsys(v, c->reg); in alchemy_clk_fgv1_setr()
564 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_fgv1_setr()
573 unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 2); in alchemy_clk_fgv1_recalc()
599 unsigned long v = alchemy_rdsys(c->reg); in __alchemy_clk_fgv2_en()
601 v &= ~(3 << c->shift); in __alchemy_clk_fgv2_en()
602 v |= (c->parent & 3) << c->shift; in __alchemy_clk_fgv2_en()
603 alchemy_wrsys(v, c->reg); in __alchemy_clk_fgv2_en()
604 c->isen = 1; in __alchemy_clk_fgv2_en()
613 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_fgv2_en()
615 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_fgv2_en()
624 return ((alchemy_rdsys(c->reg) >> c->shift) & 3) != 0; in alchemy_clk_fgv2_isen()
632 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_fgv2_dis()
633 v = alchemy_rdsys(c->reg); in alchemy_clk_fgv2_dis()
634 v &= ~(3 << c->shift); /* set input mux to "disabled" state */ in alchemy_clk_fgv2_dis()
635 alchemy_wrsys(v, c->reg); in alchemy_clk_fgv2_dis()
636 c->isen = 0; in alchemy_clk_fgv2_dis()
637 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_fgv2_dis()
645 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_fgv2_setp()
646 c->parent = index + 1; /* value to write to register */ in alchemy_clk_fgv2_setp()
647 if (c->isen) in alchemy_clk_fgv2_setp()
649 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_fgv2_setp()
659 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_fgv2_getp()
660 v = c->parent - 1; in alchemy_clk_fgv2_getp()
661 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_fgv2_getp()
665 /* fg0-2 and fg4-6 share a "scale"-bit. With this bit cleared, the
674 int sh = c->shift + 2; in alchemy_clk_fgv2_setr()
678 return -EINVAL; in alchemy_clk_fgv2_setr()
680 v = alchemy_rdsys(c->reg) & (1 << 30); /* test "scale" bit */ in alchemy_clk_fgv2_setr()
684 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_fgv2_setr()
685 v = alchemy_rdsys(c->reg); in alchemy_clk_fgv2_setr()
688 alchemy_wrsys(v, c->reg); in alchemy_clk_fgv2_setr()
689 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_fgv2_setr()
698 int sh = c->shift + 2; in alchemy_clk_fgv2_recalc()
701 v = alchemy_rdsys(c->reg); in alchemy_clk_fgv2_recalc()
715 if (alchemy_rdsys(c->reg) & (1 << 30)) { in alchemy_clk_fgv2_detr()
770 return -ENODEV; in alchemy_clk_init_fgens()
776 return -ENOMEM; in alchemy_clk_init_fgens()
783 a->shift = 10 * (i < 3 ? i : i - 3); in alchemy_clk_init_fgens()
785 a->reg = AU1000_SYS_FREQCTRL1; in alchemy_clk_init_fgens()
786 a->reglock = &alchemy_clk_fg1_lock; in alchemy_clk_init_fgens()
788 a->reg = AU1000_SYS_FREQCTRL0; in alchemy_clk_init_fgens()
789 a->reglock = &alchemy_clk_fg0_lock; in alchemy_clk_init_fgens()
796 v = alchemy_rdsys(a->reg); in alchemy_clk_init_fgens()
797 a->parent = (v >> a->shift) & 3; in alchemy_clk_init_fgens()
798 if (!a->parent) { in alchemy_clk_init_fgens()
799 a->parent = 1; in alchemy_clk_init_fgens()
800 a->isen = 0; in alchemy_clk_init_fgens()
802 a->isen = 1; in alchemy_clk_init_fgens()
805 a->hw.init = &id; in alchemy_clk_init_fgens()
806 c = clk_register(NULL, &a->hw); in alchemy_clk_init_fgens()
822 unsigned long v = alchemy_rdsys(c->reg); in alchemy_clk_csrc_isen()
824 return (((v >> c->shift) >> 2) & 7) != 0; in alchemy_clk_csrc_isen()
829 unsigned long v = alchemy_rdsys(c->reg); in __alchemy_clk_csrc_en()
831 v &= ~((7 << 2) << c->shift); in __alchemy_clk_csrc_en()
832 v |= ((c->parent & 7) << 2) << c->shift; in __alchemy_clk_csrc_en()
833 alchemy_wrsys(v, c->reg); in __alchemy_clk_csrc_en()
834 c->isen = 1; in __alchemy_clk_csrc_en()
843 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_csrc_en()
845 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_csrc_en()
855 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_csrc_dis()
856 v = alchemy_rdsys(c->reg); in alchemy_clk_csrc_dis()
857 v &= ~((3 << 2) << c->shift); /* mux to "disabled" state */ in alchemy_clk_csrc_dis()
858 alchemy_wrsys(v, c->reg); in alchemy_clk_csrc_dis()
859 c->isen = 0; in alchemy_clk_csrc_dis()
860 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_csrc_dis()
868 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_csrc_setp()
869 c->parent = index + 1; /* value to write to register */ in alchemy_clk_csrc_setp()
870 if (c->isen) in alchemy_clk_csrc_setp()
872 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_csrc_setp()
881 return c->parent - 1; in alchemy_clk_csrc_getp()
888 unsigned long v = (alchemy_rdsys(c->reg) >> c->shift) & 3; in alchemy_clk_csrc_recalc()
890 return parent_rate / c->dt[v]; in alchemy_clk_csrc_recalc()
901 return -EINVAL; in alchemy_clk_csrc_setr()
905 return -EINVAL; in alchemy_clk_csrc_setr()
906 if ((d == 3) && (c->dt[2] != 3)) in alchemy_clk_csrc_setr()
910 if (c->dt[i] == d) in alchemy_clk_csrc_setr()
914 return -EINVAL; /* oops */ in alchemy_clk_csrc_setr()
916 spin_lock_irqsave(c->reglock, flags); in alchemy_clk_csrc_setr()
917 v = alchemy_rdsys(c->reg); in alchemy_clk_csrc_setr()
918 v &= ~(3 << c->shift); in alchemy_clk_csrc_setr()
919 v |= (i & 3) << c->shift; in alchemy_clk_csrc_setr()
920 alchemy_wrsys(v, c->reg); in alchemy_clk_csrc_setr()
921 spin_unlock_irqrestore(c->reglock, flags); in alchemy_clk_csrc_setr()
930 int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */ in alchemy_clk_csrc_detr()
992 return -ENODEV; in alchemy_clk_setup_imux()
997 return -ENOMEM; in alchemy_clk_setup_imux()
1006 a->shift = i * 5; in alchemy_clk_setup_imux()
1007 a->reg = AU1000_SYS_CLKSRC; in alchemy_clk_setup_imux()
1008 a->reglock = &alchemy_clk_csrc_lock; in alchemy_clk_setup_imux()
1009 a->dt = dt; in alchemy_clk_setup_imux()
1014 v = alchemy_rdsys(a->reg); in alchemy_clk_setup_imux()
1015 a->parent = ((v >> a->shift) >> 2) & 7; in alchemy_clk_setup_imux()
1016 if (!a->parent) { in alchemy_clk_setup_imux()
1017 a->parent = 1; in alchemy_clk_setup_imux()
1018 a->isen = 0; in alchemy_clk_setup_imux()
1020 a->isen = 1; in alchemy_clk_setup_imux()
1022 a->hw.init = &id; in alchemy_clk_setup_imux()
1023 c = clk_register(NULL, &a->hw); in alchemy_clk_setup_imux()
1089 /* Frequency dividers 0-5 */ in alchemy_clk_init()
1092 ret = -ENODEV; in alchemy_clk_init()
1099 ret = -ENODEV; in alchemy_clk_init()
1104 while (t->base) { in alchemy_clk_init()
1105 if (t->cputype == ctype) in alchemy_clk_init()
1106 clk_add_alias(t->alias, NULL, t->base, NULL); in alchemy_clk_init()