diff options
author | Neil Armstrong <narmstrong@baylibre.com> | 2019-03-07 09:14:55 -0500 |
---|---|---|
committer | Neil Armstrong <narmstrong@baylibre.com> | 2019-04-01 04:45:11 -0400 |
commit | 34775209ba37bff3b4e60ddee0a2d69966146a5d (patch) | |
tree | 56e95653b6f0ae3dfc4da6b7cc362d450e52470a | |
parent | 39b8500283b45252e2f9ad9d60992f2c0d3a1659 (diff) |
clk: meson-g12a: add PCIE PLL clocks
Add the PCIe reference clock feeding the USB3 + PCIE combo PHY.
This PLL needs a very precise register sequence to permit to be locked,
thus using the specific clk-pll pcie ops.
The PLL is then followed by :
- a fixed /2 divider
- a 5-bit 1-based divider
- a final /2 divider
This reference clock is fixed to 100MHz, thus only a single PLL setup
is added.
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Acked-by: Jerome Brunet <jbrunet@baylibre.com>
Link: https://lkml.kernel.org/r/20190307141455.23879-4-narmstrong@baylibre.com
-rw-r--r-- | drivers/clk/meson/g12a.c | 118 | ||||
-rw-r--r-- | drivers/clk/meson/g12a.h | 5 |
2 files changed, 122 insertions, 1 deletions
diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index 10ba8bc4646d..a47435f91f2f 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c | |||
@@ -614,6 +614,118 @@ static struct clk_regmap g12a_hifi_pll = { | |||
614 | }, | 614 | }, |
615 | }; | 615 | }; |
616 | 616 | ||
617 | /* | ||
618 | * The Meson G12A PCIE PLL is fined tuned to deliver a very precise | ||
619 | * 100MHz reference clock for the PCIe Analog PHY, and thus requires | ||
620 | * a strict register sequence to enable the PLL. | ||
621 | */ | ||
622 | static const struct reg_sequence g12a_pcie_pll_init_regs[] = { | ||
623 | { .reg = HHI_PCIE_PLL_CNTL0, .def = 0x20090496 }, | ||
624 | { .reg = HHI_PCIE_PLL_CNTL0, .def = 0x30090496 }, | ||
625 | { .reg = HHI_PCIE_PLL_CNTL1, .def = 0x00000000 }, | ||
626 | { .reg = HHI_PCIE_PLL_CNTL2, .def = 0x00001100 }, | ||
627 | { .reg = HHI_PCIE_PLL_CNTL3, .def = 0x10058e00 }, | ||
628 | { .reg = HHI_PCIE_PLL_CNTL4, .def = 0x000100c0 }, | ||
629 | { .reg = HHI_PCIE_PLL_CNTL5, .def = 0x68000048 }, | ||
630 | { .reg = HHI_PCIE_PLL_CNTL5, .def = 0x68000068, .delay_us = 20 }, | ||
631 | { .reg = HHI_PCIE_PLL_CNTL4, .def = 0x008100c0, .delay_us = 10 }, | ||
632 | { .reg = HHI_PCIE_PLL_CNTL0, .def = 0x34090496 }, | ||
633 | { .reg = HHI_PCIE_PLL_CNTL0, .def = 0x14090496, .delay_us = 10 }, | ||
634 | { .reg = HHI_PCIE_PLL_CNTL2, .def = 0x00001000 }, | ||
635 | }; | ||
636 | |||
637 | /* Keep a single entry table for recalc/round_rate() ops */ | ||
638 | static const struct pll_params_table g12a_pcie_pll_table[] = { | ||
639 | PLL_PARAMS(150, 1), | ||
640 | {0, 0}, | ||
641 | }; | ||
642 | |||
643 | static struct clk_regmap g12a_pcie_pll_dco = { | ||
644 | .data = &(struct meson_clk_pll_data){ | ||
645 | .en = { | ||
646 | .reg_off = HHI_PCIE_PLL_CNTL0, | ||
647 | .shift = 28, | ||
648 | .width = 1, | ||
649 | }, | ||
650 | .m = { | ||
651 | .reg_off = HHI_PCIE_PLL_CNTL0, | ||
652 | .shift = 0, | ||
653 | .width = 8, | ||
654 | }, | ||
655 | .n = { | ||
656 | .reg_off = HHI_PCIE_PLL_CNTL0, | ||
657 | .shift = 10, | ||
658 | .width = 5, | ||
659 | }, | ||
660 | .frac = { | ||
661 | .reg_off = HHI_PCIE_PLL_CNTL1, | ||
662 | .shift = 0, | ||
663 | .width = 12, | ||
664 | }, | ||
665 | .l = { | ||
666 | .reg_off = HHI_PCIE_PLL_CNTL0, | ||
667 | .shift = 31, | ||
668 | .width = 1, | ||
669 | }, | ||
670 | .rst = { | ||
671 | .reg_off = HHI_PCIE_PLL_CNTL0, | ||
672 | .shift = 29, | ||
673 | .width = 1, | ||
674 | }, | ||
675 | .table = g12a_pcie_pll_table, | ||
676 | .init_regs = g12a_pcie_pll_init_regs, | ||
677 | .init_count = ARRAY_SIZE(g12a_pcie_pll_init_regs), | ||
678 | }, | ||
679 | .hw.init = &(struct clk_init_data){ | ||
680 | .name = "pcie_pll_dco", | ||
681 | .ops = &meson_clk_pcie_pll_ops, | ||
682 | .parent_names = (const char *[]){ IN_PREFIX "xtal" }, | ||
683 | .num_parents = 1, | ||
684 | }, | ||
685 | }; | ||
686 | |||
687 | static struct clk_fixed_factor g12a_pcie_pll_dco_div2 = { | ||
688 | .mult = 1, | ||
689 | .div = 2, | ||
690 | .hw.init = &(struct clk_init_data){ | ||
691 | .name = "pcie_pll_dco_div2", | ||
692 | .ops = &clk_fixed_factor_ops, | ||
693 | .parent_names = (const char *[]){ "pcie_pll_dco" }, | ||
694 | .num_parents = 1, | ||
695 | .flags = CLK_SET_RATE_PARENT, | ||
696 | }, | ||
697 | }; | ||
698 | |||
699 | static struct clk_regmap g12a_pcie_pll_od = { | ||
700 | .data = &(struct clk_regmap_div_data){ | ||
701 | .offset = HHI_PCIE_PLL_CNTL0, | ||
702 | .shift = 16, | ||
703 | .width = 5, | ||
704 | .flags = CLK_DIVIDER_ROUND_CLOSEST | | ||
705 | CLK_DIVIDER_ONE_BASED | | ||
706 | CLK_DIVIDER_ALLOW_ZERO, | ||
707 | }, | ||
708 | .hw.init = &(struct clk_init_data){ | ||
709 | .name = "pcie_pll_od", | ||
710 | .ops = &clk_regmap_divider_ops, | ||
711 | .parent_names = (const char *[]){ "pcie_pll_dco_div2" }, | ||
712 | .num_parents = 1, | ||
713 | .flags = CLK_SET_RATE_PARENT, | ||
714 | }, | ||
715 | }; | ||
716 | |||
717 | static struct clk_fixed_factor g12a_pcie_pll = { | ||
718 | .mult = 1, | ||
719 | .div = 2, | ||
720 | .hw.init = &(struct clk_init_data){ | ||
721 | .name = "pcie_pll_pll", | ||
722 | .ops = &clk_fixed_factor_ops, | ||
723 | .parent_names = (const char *[]){ "pcie_pll_od" }, | ||
724 | .num_parents = 1, | ||
725 | .flags = CLK_SET_RATE_PARENT, | ||
726 | }, | ||
727 | }; | ||
728 | |||
617 | static struct clk_regmap g12a_hdmi_pll_dco = { | 729 | static struct clk_regmap g12a_hdmi_pll_dco = { |
618 | .data = &(struct meson_clk_pll_data){ | 730 | .data = &(struct meson_clk_pll_data){ |
619 | .en = { | 731 | .en = { |
@@ -2499,6 +2611,10 @@ static struct clk_hw_onecell_data g12a_hw_onecell_data = { | |||
2499 | [CLKID_CPU_CLK_AXI] = &g12a_cpu_clk_axi.hw, | 2611 | [CLKID_CPU_CLK_AXI] = &g12a_cpu_clk_axi.hw, |
2500 | [CLKID_CPU_CLK_TRACE_DIV] = &g12a_cpu_clk_trace_div.hw, | 2612 | [CLKID_CPU_CLK_TRACE_DIV] = &g12a_cpu_clk_trace_div.hw, |
2501 | [CLKID_CPU_CLK_TRACE] = &g12a_cpu_clk_trace.hw, | 2613 | [CLKID_CPU_CLK_TRACE] = &g12a_cpu_clk_trace.hw, |
2614 | [CLKID_PCIE_PLL_DCO] = &g12a_pcie_pll_dco.hw, | ||
2615 | [CLKID_PCIE_PLL_DCO_DIV2] = &g12a_pcie_pll_dco_div2.hw, | ||
2616 | [CLKID_PCIE_PLL_OD] = &g12a_pcie_pll_od.hw, | ||
2617 | [CLKID_PCIE_PLL] = &g12a_pcie_pll.hw, | ||
2502 | [NR_CLKS] = NULL, | 2618 | [NR_CLKS] = NULL, |
2503 | }, | 2619 | }, |
2504 | .num = NR_CLKS, | 2620 | .num = NR_CLKS, |
@@ -2685,6 +2801,8 @@ static struct clk_regmap *const g12a_clk_regmaps[] = { | |||
2685 | &g12a_cpu_clk_axi, | 2801 | &g12a_cpu_clk_axi, |
2686 | &g12a_cpu_clk_trace_div, | 2802 | &g12a_cpu_clk_trace_div, |
2687 | &g12a_cpu_clk_trace, | 2803 | &g12a_cpu_clk_trace, |
2804 | &g12a_pcie_pll_od, | ||
2805 | &g12a_pcie_pll_dco, | ||
2688 | }; | 2806 | }; |
2689 | 2807 | ||
2690 | static const struct meson_eeclkc_data g12a_clkc_data = { | 2808 | static const struct meson_eeclkc_data g12a_clkc_data = { |
diff --git a/drivers/clk/meson/g12a.h b/drivers/clk/meson/g12a.h index 70aa469ca1cf..1393a09730a6 100644 --- a/drivers/clk/meson/g12a.h +++ b/drivers/clk/meson/g12a.h | |||
@@ -186,8 +186,11 @@ | |||
186 | #define CLKID_CPU_CLK_AXI 195 | 186 | #define CLKID_CPU_CLK_AXI 195 |
187 | #define CLKID_CPU_CLK_TRACE_DIV 196 | 187 | #define CLKID_CPU_CLK_TRACE_DIV 196 |
188 | #define CLKID_CPU_CLK_TRACE 197 | 188 | #define CLKID_CPU_CLK_TRACE 197 |
189 | #define CLKID_PCIE_PLL_DCO 198 | ||
190 | #define CLKID_PCIE_PLL_DCO_DIV2 199 | ||
191 | #define CLKID_PCIE_PLL_OD 200 | ||
189 | 192 | ||
190 | #define NR_CLKS 198 | 193 | #define NR_CLKS 202 |
191 | 194 | ||
192 | /* include the CLKIDs that have been made part of the DT binding */ | 195 | /* include the CLKIDs that have been made part of the DT binding */ |
193 | #include <dt-bindings/clock/g12a-clkc.h> | 196 | #include <dt-bindings/clock/g12a-clkc.h> |