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> |
