Lines Matching +full:raspberrypi +full:- +full:rp1 +full:- +full:state

1 // SPDX-License-Identifier: GPL-2.0
5 * Clock driver for RP1 PCIe multifunction chip.
9 #include <linux/clk-provider.h>
16 #include <dt-bindings/clock/raspberrypi,rp1-clocks.h>
374 regmap_write(clockman->regmap, reg, val); in clockman_write()
381 regmap_read(clockman->regmap, reg, &val); in clockman_read()
389 struct rp1_clockman *clockman = pll_core->clockman; in rp1_pll_core_is_on()
390 const struct rp1_pll_core_data *data = pll_core->data; in rp1_pll_core_is_on()
391 u32 pwr = clockman_read(clockman, data->pwr_reg); in rp1_pll_core_is_on()
399 struct rp1_clockman *clockman = pll_core->clockman; in rp1_pll_core_on()
400 const struct rp1_pll_core_data *data = pll_core->data; in rp1_pll_core_on()
404 spin_lock(&clockman->regs_lock); in rp1_pll_core_on()
406 if (!(clockman_read(clockman, data->cs_reg) & PLL_CS_LOCK)) { in rp1_pll_core_on()
407 /* Reset to a known state. */ in rp1_pll_core_on()
408 clockman_write(clockman, data->pwr_reg, PLL_PWR_MASK); in rp1_pll_core_on()
409 clockman_write(clockman, data->fbdiv_int_reg, 20); in rp1_pll_core_on()
410 clockman_write(clockman, data->fbdiv_frac_reg, 0); in rp1_pll_core_on()
411 clockman_write(clockman, data->cs_reg, PLL_CS_REFDIV_MASK); in rp1_pll_core_on()
415 fbdiv_frac = clockman_read(clockman, data->fbdiv_frac_reg); in rp1_pll_core_on()
416 clockman_write(clockman, data->pwr_reg, fbdiv_frac ? 0 : PLL_PWR_DSMPD); in rp1_pll_core_on()
417 spin_unlock(&clockman->regs_lock); in rp1_pll_core_on()
420 ret = regmap_read_poll_timeout(clockman->regmap, data->cs_reg, val, in rp1_pll_core_on()
424 dev_err(clockman->dev, "%s: can't lock PLL\n", in rp1_pll_core_on()
433 struct rp1_clockman *clockman = pll_core->clockman; in rp1_pll_core_off()
434 const struct rp1_pll_core_data *data = pll_core->data; in rp1_pll_core_off()
436 spin_lock(&clockman->regs_lock); in rp1_pll_core_off()
437 clockman_write(clockman, data->pwr_reg, 0); in rp1_pll_core_off()
438 spin_unlock(&clockman->regs_lock); in rp1_pll_core_off()
456 div_fp64 += 1 << (32 - 24 - 1); in get_pll_core_divider()
459 fbdiv_frac = (div_fp64 >> (32 - 24)) & 0xffffff; in get_pll_core_divider()
476 struct rp1_clockman *clockman = pll_core->clockman; in rp1_pll_core_set_rate()
477 const struct rp1_pll_core_data *data = pll_core->data; in rp1_pll_core_set_rate()
482 spin_lock(&clockman->regs_lock); in rp1_pll_core_set_rate()
483 clockman_write(clockman, data->fbdiv_int_reg, 0); in rp1_pll_core_set_rate()
484 clockman_write(clockman, data->fbdiv_frac_reg, 0); in rp1_pll_core_set_rate()
485 spin_unlock(&clockman->regs_lock); in rp1_pll_core_set_rate()
490 spin_lock(&clockman->regs_lock); in rp1_pll_core_set_rate()
491 clockman_write(clockman, data->pwr_reg, fbdiv_frac ? 0 : PLL_PWR_DSMPD); in rp1_pll_core_set_rate()
492 clockman_write(clockman, data->fbdiv_int_reg, fbdiv_int); in rp1_pll_core_set_rate()
493 clockman_write(clockman, data->fbdiv_frac_reg, fbdiv_frac); in rp1_pll_core_set_rate()
494 spin_unlock(&clockman->regs_lock); in rp1_pll_core_set_rate()
498 return -ERANGE; in rp1_pll_core_set_rate()
500 pll_core->cached_rate = calc_rate; in rp1_pll_core_set_rate()
502 spin_lock(&clockman->regs_lock); in rp1_pll_core_set_rate()
504 clockman_write(clockman, data->cs_reg, in rp1_pll_core_set_rate()
505 clockman_read(clockman, data->cs_reg) | in rp1_pll_core_set_rate()
507 spin_unlock(&clockman->regs_lock); in rp1_pll_core_set_rate()
516 struct rp1_clockman *clockman = pll_core->clockman; in rp1_pll_core_recalc_rate()
517 const struct rp1_pll_core_data *data = pll_core->data; in rp1_pll_core_recalc_rate()
522 fbdiv_int = clockman_read(clockman, data->fbdiv_int_reg); in rp1_pll_core_recalc_rate()
523 fbdiv_frac = clockman_read(clockman, data->fbdiv_frac_reg); in rp1_pll_core_recalc_rate()
577 struct rp1_clockman *clockman = pll->clockman; in rp1_pll_set_rate()
578 const struct rp1_pll_data *data = pll->data; in rp1_pll_set_rate()
584 spin_lock(&clockman->regs_lock); in rp1_pll_set_rate()
585 prim = clockman_read(clockman, data->ctrl_reg); in rp1_pll_set_rate()
590 clockman_write(clockman, data->ctrl_reg, prim); in rp1_pll_set_rate()
591 spin_unlock(&clockman->regs_lock); in rp1_pll_set_rate()
600 struct rp1_clockman *clockman = pll->clockman; in rp1_pll_recalc_rate()
601 const struct rp1_pll_data *data = pll->data; in rp1_pll_recalc_rate()
604 prim = clockman_read(clockman, data->ctrl_reg); in rp1_pll_recalc_rate()
609 dev_err(clockman->dev, "%s: (%s) zero divider value\n", in rp1_pll_recalc_rate()
630 struct rp1_clockman *clockman = pll_ph->clockman; in rp1_pll_ph_is_on()
631 const struct rp1_pll_ph_data *data = pll_ph->data; in rp1_pll_ph_is_on()
633 return !!(clockman_read(clockman, data->ph_reg) & PLL_PH_EN); in rp1_pll_ph_is_on()
639 struct rp1_clockman *clockman = pll_ph->clockman; in rp1_pll_ph_on()
640 const struct rp1_pll_ph_data *data = pll_ph->data; in rp1_pll_ph_on()
643 spin_lock(&clockman->regs_lock); in rp1_pll_ph_on()
644 ph_reg = clockman_read(clockman, data->ph_reg); in rp1_pll_ph_on()
645 ph_reg |= data->phase << PLL_PH_PHASE_SHIFT; in rp1_pll_ph_on()
647 clockman_write(clockman, data->ph_reg, ph_reg); in rp1_pll_ph_on()
648 spin_unlock(&clockman->regs_lock); in rp1_pll_ph_on()
656 struct rp1_clockman *clockman = pll_ph->clockman; in rp1_pll_ph_off()
657 const struct rp1_pll_ph_data *data = pll_ph->data; in rp1_pll_ph_off()
659 spin_lock(&clockman->regs_lock); in rp1_pll_ph_off()
660 clockman_write(clockman, data->ph_reg, in rp1_pll_ph_off()
661 clockman_read(clockman, data->ph_reg) & ~PLL_PH_EN); in rp1_pll_ph_off()
662 spin_unlock(&clockman->regs_lock); in rp1_pll_ph_off()
669 const struct rp1_pll_ph_data *data = pll_ph->data; in rp1_pll_ph_recalc_rate()
671 return parent_rate / data->fixed_divider; in rp1_pll_ph_recalc_rate()
678 const struct rp1_pll_ph_data *data = pll_ph->data; in rp1_pll_ph_round_rate()
680 return *parent_rate / data->fixed_divider; in rp1_pll_ph_round_rate()
686 struct rp1_clockman *clockman = divider->clockman; in rp1_pll_divider_is_on()
687 const struct rp1_pll_data *data = divider->data; in rp1_pll_divider_is_on()
689 return !(clockman_read(clockman, data->ctrl_reg) & PLL_SEC_RST); in rp1_pll_divider_is_on()
695 struct rp1_clockman *clockman = divider->clockman; in rp1_pll_divider_on()
696 const struct rp1_pll_data *data = divider->data; in rp1_pll_divider_on()
698 spin_lock(&clockman->regs_lock); in rp1_pll_divider_on()
700 WARN_ON(!(clockman_read(clockman, data->ctrl_reg) & PLL_SEC_IMPL)); in rp1_pll_divider_on()
701 clockman_write(clockman, data->ctrl_reg, in rp1_pll_divider_on()
702 clockman_read(clockman, data->ctrl_reg) & ~PLL_SEC_RST); in rp1_pll_divider_on()
703 spin_unlock(&clockman->regs_lock); in rp1_pll_divider_on()
711 struct rp1_clockman *clockman = divider->clockman; in rp1_pll_divider_off()
712 const struct rp1_pll_data *data = divider->data; in rp1_pll_divider_off()
714 spin_lock(&clockman->regs_lock); in rp1_pll_divider_off()
715 clockman_write(clockman, data->ctrl_reg, in rp1_pll_divider_off()
716 clockman_read(clockman, data->ctrl_reg) | PLL_SEC_RST); in rp1_pll_divider_off()
717 spin_unlock(&clockman->regs_lock); in rp1_pll_divider_off()
725 struct rp1_clockman *clockman = divider->clockman; in rp1_pll_divider_set_rate()
726 const struct rp1_pll_data *data = divider->data; in rp1_pll_divider_set_rate()
732 spin_lock(&clockman->regs_lock); in rp1_pll_divider_set_rate()
733 sec = clockman_read(clockman, data->ctrl_reg); in rp1_pll_divider_set_rate()
739 clockman_write(clockman, data->ctrl_reg, sec); in rp1_pll_divider_set_rate()
745 clockman_write(clockman, data->ctrl_reg, sec); in rp1_pll_divider_set_rate()
746 spin_unlock(&clockman->regs_lock); in rp1_pll_divider_set_rate()
767 struct rp1_clockman *clockman = clock->clockman; in rp1_clock_is_on()
768 const struct rp1_clock_data *data = clock->data; in rp1_clock_is_on()
770 return !!(clockman_read(clockman, data->ctrl_reg) & CLK_CTRL_ENABLE); in rp1_clock_is_on()
777 struct rp1_clockman *clockman = clock->clockman; in rp1_clock_recalc_rate()
778 const struct rp1_clock_data *data = clock->data; in rp1_clock_recalc_rate()
783 div = clockman_read(clockman, data->div_int_reg); in rp1_clock_recalc_rate()
784 frac = (data->div_frac_reg != 0) ? in rp1_clock_recalc_rate()
785 clockman_read(clockman, data->div_frac_reg) : 0; in rp1_clock_recalc_rate()
791 div = (div << CLK_DIV_FRAC_BITS) | (frac >> (32 - CLK_DIV_FRAC_BITS)); in rp1_clock_recalc_rate()
802 struct rp1_clockman *clockman = clock->clockman; in rp1_clock_on()
803 const struct rp1_clock_data *data = clock->data; in rp1_clock_on()
805 spin_lock(&clockman->regs_lock); in rp1_clock_on()
806 clockman_write(clockman, data->ctrl_reg, in rp1_clock_on()
807 clockman_read(clockman, data->ctrl_reg) | CLK_CTRL_ENABLE); in rp1_clock_on()
808 /* If this is a GPCLK, turn on the output-enable */ in rp1_clock_on()
809 if (data->oe_mask) in rp1_clock_on()
811 clockman_read(clockman, GPCLK_OE_CTRL) | data->oe_mask); in rp1_clock_on()
812 spin_unlock(&clockman->regs_lock); in rp1_clock_on()
820 struct rp1_clockman *clockman = clock->clockman; in rp1_clock_off()
821 const struct rp1_clock_data *data = clock->data; in rp1_clock_off()
823 spin_lock(&clockman->regs_lock); in rp1_clock_off()
824 clockman_write(clockman, data->ctrl_reg, in rp1_clock_off()
825 clockman_read(clockman, data->ctrl_reg) & ~CLK_CTRL_ENABLE); in rp1_clock_off()
826 /* If this is a GPCLK, turn off the output-enable */ in rp1_clock_off()
827 if (data->oe_mask) in rp1_clock_off()
829 clockman_read(clockman, GPCLK_OE_CTRL) & ~data->oe_mask); in rp1_clock_off()
830 spin_unlock(&clockman->regs_lock); in rp1_clock_off()
846 * Always express div in fixed-point format for fractional division; in rp1_clock_choose_div()
849 if (data->div_frac_reg) { in rp1_clock_choose_div()
859 (u64)data->div_int_max << CLK_DIV_FRAC_BITS); in rp1_clock_choose_div()
867 struct rp1_clockman *clockman = clock->clockman; in rp1_clock_get_parent()
868 const struct rp1_clock_data *data = clock->data; in rp1_clock_get_parent()
872 /* Sel is one-hot, so find the first bit set */ in rp1_clock_get_parent()
873 sel = clockman_read(clockman, data->sel_reg); in rp1_clock_get_parent()
874 parent = ffs(sel) - 1; in rp1_clock_get_parent()
879 ctrl = clockman_read(clockman, data->ctrl_reg); in rp1_clock_get_parent()
880 parent = (ctrl & data->clk_src_mask) >> CLK_CTRL_SRC_SHIFT; in rp1_clock_get_parent()
883 if (parent >= data->num_std_parents) in rp1_clock_get_parent()
891 ctrl = clockman_read(clockman, data->ctrl_reg); in rp1_clock_get_parent()
893 parent += data->num_std_parents; in rp1_clock_get_parent()
902 struct rp1_clockman *clockman = clock->clockman; in rp1_clock_set_parent()
903 const struct rp1_clock_data *data = clock->data; in rp1_clock_set_parent()
906 spin_lock(&clockman->regs_lock); in rp1_clock_set_parent()
907 ctrl = clockman_read(clockman, data->ctrl_reg); in rp1_clock_set_parent()
909 if (index >= data->num_std_parents) { in rp1_clock_set_parent()
911 if (index >= data->num_std_parents + data->num_aux_parents) { in rp1_clock_set_parent()
912 spin_unlock(&clockman->regs_lock); in rp1_clock_set_parent()
913 return -EINVAL; in rp1_clock_set_parent()
918 ctrl |= FIELD_PREP(CLK_CTRL_AUXSRC_MASK, index - data->num_std_parents); in rp1_clock_set_parent()
920 ctrl &= ~data->clk_src_mask; in rp1_clock_set_parent()
921 ctrl |= (AUX_SEL << CLK_CTRL_SRC_SHIFT) & data->clk_src_mask; in rp1_clock_set_parent()
923 ctrl &= ~data->clk_src_mask; in rp1_clock_set_parent()
924 ctrl |= (index << CLK_CTRL_SRC_SHIFT) & data->clk_src_mask; in rp1_clock_set_parent()
927 clockman_write(clockman, data->ctrl_reg, ctrl); in rp1_clock_set_parent()
928 spin_unlock(&clockman->regs_lock); in rp1_clock_set_parent()
932 return -EINVAL; in rp1_clock_set_parent()
943 struct rp1_clockman *clockman = clock->clockman; in rp1_clock_set_rate_and_parent()
944 const struct rp1_clock_data *data = clock->data; in rp1_clock_set_rate_and_parent()
947 spin_lock(&clockman->regs_lock); in rp1_clock_set_rate_and_parent()
949 clockman_write(clockman, data->div_int_reg, div >> CLK_DIV_FRAC_BITS); in rp1_clock_set_rate_and_parent()
950 if (data->div_frac_reg) in rp1_clock_set_rate_and_parent()
951 clockman_write(clockman, data->div_frac_reg, div << (32 - CLK_DIV_FRAC_BITS)); in rp1_clock_set_rate_and_parent()
953 spin_unlock(&clockman->regs_lock); in rp1_clock_set_rate_and_parent()
974 const struct rp1_clock_data *data = clock->data; in rp1_clock_choose_div_and_prate()
994 * Prevent overclocks - if all parent choices result in in rp1_clock_choose_div_and_prate()
998 if (tmp > data->max_freq) in rp1_clock_choose_div_and_prate()
1021 rp1_clock_choose_div_and_prate(hw, i, req->rate, &prate, in rp1_clock_determine_rate()
1024 req->best_parent_hw = parent; in rp1_clock_determine_rate()
1025 req->best_parent_rate = prate; in rp1_clock_determine_rate()
1026 req->rate = calc_rate; in rp1_clock_determine_rate()
1041 rp1_clock_choose_div_and_prate(hw, i, req->rate, &prate, in rp1_clock_determine_rate()
1044 if (abs_diff(calc_rate, req->rate) < best_rate_diff) { in rp1_clock_determine_rate()
1048 best_rate_diff = abs_diff(calc_rate, req->rate); in rp1_clock_determine_rate()
1056 return -EINVAL; in rp1_clock_determine_rate()
1058 req->best_parent_hw = best_parent; in rp1_clock_determine_rate()
1059 req->best_parent_rate = best_prate; in rp1_clock_determine_rate()
1060 req->rate = best_rate; in rp1_clock_determine_rate()
1114 desc->clockman = clockman; in rp1_register_pll()
1116 ret = devm_clk_hw_register(clockman->dev, &desc->hw); in rp1_register_pll()
1120 return &desc->hw; in rp1_register_pll()
1126 const struct rp1_pll_data *divider_data = desc->data; in rp1_register_pll_divider()
1129 desc->div.reg = clockman->regs + divider_data->ctrl_reg; in rp1_register_pll_divider()
1130 desc->div.shift = __ffs(PLL_SEC_DIV_MASK); in rp1_register_pll_divider()
1131 desc->div.width = __ffs(~(PLL_SEC_DIV_MASK >> desc->div.shift)); in rp1_register_pll_divider()
1132 desc->div.flags = CLK_DIVIDER_ROUND_CLOSEST; in rp1_register_pll_divider()
1133 desc->div.lock = &clockman->regs_lock; in rp1_register_pll_divider()
1134 desc->div.hw.init = desc->hw.init; in rp1_register_pll_divider()
1135 desc->div.table = pll_sec_div_table; in rp1_register_pll_divider()
1137 desc->clockman = clockman; in rp1_register_pll_divider()
1139 ret = devm_clk_hw_register(clockman->dev, &desc->div.hw); in rp1_register_pll_divider()
1143 return &desc->div.hw; in rp1_register_pll_divider()
1149 const struct rp1_clock_data *clock_data = desc->data; in rp1_register_clock()
1153 clock_data->num_std_parents + clock_data->num_aux_parents)) in rp1_register_clock()
1154 return ERR_PTR(-EINVAL); in rp1_register_clock()
1157 if (WARN_ON_ONCE(clock_data->num_std_parents > AUX_SEL && in rp1_register_clock()
1158 desc->hw.init->parent_data[AUX_SEL].index != -1)) in rp1_register_clock()
1159 return ERR_PTR(-EINVAL); in rp1_register_clock()
1161 desc->clockman = clockman; in rp1_register_clock()
1163 ret = devm_clk_hw_register(clockman->dev, &desc->hw); in rp1_register_clock()
1167 return &desc->hw; in rp1_register_clock()
1304 { .index = -1 },
1426 .name = "rp1-clk",
1435 struct device *dev = &pdev->dev; in rp1_clk_probe()
1443 return -ENOMEM; in rp1_clk_probe()
1445 spin_lock_init(&clockman->regs_lock); in rp1_clk_probe()
1446 clockman->dev = dev; in rp1_clk_probe()
1448 clockman->regs = devm_platform_ioremap_resource(pdev, 0); in rp1_clk_probe()
1449 if (IS_ERR(clockman->regs)) in rp1_clk_probe()
1450 return PTR_ERR(clockman->regs); in rp1_clk_probe()
1452 clockman->regmap = devm_regmap_init_mmio(dev, clockman->regs, in rp1_clk_probe()
1454 if (IS_ERR(clockman->regmap)) { in rp1_clk_probe()
1455 dev_err_probe(dev, PTR_ERR(clockman->regmap), in rp1_clk_probe()
1457 return PTR_ERR(clockman->regmap); in rp1_clk_probe()
1460 clockman->onecell.num = asize; in rp1_clk_probe()
1461 hws = clockman->onecell.hws; in rp1_clk_probe()
1465 if (desc && desc->clk_register && desc->data) in rp1_clk_probe()
1466 hws[i] = desc->clk_register(clockman, desc); in rp1_clk_probe()
1472 &clockman->onecell); in rp1_clk_probe()
1476 { .compatible = "raspberrypi,rp1-clocks" },
1483 .name = "rp1-clk",
1491 MODULE_AUTHOR("Naushir Patuck <naush@raspberrypi.com>");
1493 MODULE_DESCRIPTION("RP1 clock driver");