diff options
Diffstat (limited to 'drivers/clk/qcom/gcc-msm8974.c')
-rw-r--r-- | drivers/clk/qcom/gcc-msm8974.c | 207 |
1 files changed, 136 insertions, 71 deletions
diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c index 51d457e2b959..7af7c18d2144 100644 --- a/drivers/clk/qcom/gcc-msm8974.c +++ b/drivers/clk/qcom/gcc-msm8974.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <dt-bindings/clock/qcom,gcc-msm8974.h> | 25 | #include <dt-bindings/clock/qcom,gcc-msm8974.h> |
26 | #include <dt-bindings/reset/qcom,gcc-msm8974.h> | 26 | #include <dt-bindings/reset/qcom,gcc-msm8974.h> |
27 | 27 | ||
28 | #include "common.h" | ||
28 | #include "clk-regmap.h" | 29 | #include "clk-regmap.h" |
29 | #include "clk-pll.h" | 30 | #include "clk-pll.h" |
30 | #include "clk-rcg.h" | 31 | #include "clk-rcg.h" |
@@ -34,6 +35,7 @@ | |||
34 | #define P_XO 0 | 35 | #define P_XO 0 |
35 | #define P_GPLL0 1 | 36 | #define P_GPLL0 1 |
36 | #define P_GPLL1 1 | 37 | #define P_GPLL1 1 |
38 | #define P_GPLL4 2 | ||
37 | 39 | ||
38 | static const u8 gcc_xo_gpll0_map[] = { | 40 | static const u8 gcc_xo_gpll0_map[] = { |
39 | [P_XO] = 0, | 41 | [P_XO] = 0, |
@@ -45,6 +47,18 @@ static const char *gcc_xo_gpll0[] = { | |||
45 | "gpll0_vote", | 47 | "gpll0_vote", |
46 | }; | 48 | }; |
47 | 49 | ||
50 | static const u8 gcc_xo_gpll0_gpll4_map[] = { | ||
51 | [P_XO] = 0, | ||
52 | [P_GPLL0] = 1, | ||
53 | [P_GPLL4] = 5, | ||
54 | }; | ||
55 | |||
56 | static const char *gcc_xo_gpll0_gpll4[] = { | ||
57 | "xo", | ||
58 | "gpll0_vote", | ||
59 | "gpll4_vote", | ||
60 | }; | ||
61 | |||
48 | #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } | 62 | #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } |
49 | 63 | ||
50 | static struct clk_pll gpll0 = { | 64 | static struct clk_pll gpll0 = { |
@@ -137,6 +151,33 @@ static struct clk_regmap gpll1_vote = { | |||
137 | }, | 151 | }, |
138 | }; | 152 | }; |
139 | 153 | ||
154 | static struct clk_pll gpll4 = { | ||
155 | .l_reg = 0x1dc4, | ||
156 | .m_reg = 0x1dc8, | ||
157 | .n_reg = 0x1dcc, | ||
158 | .config_reg = 0x1dd4, | ||
159 | .mode_reg = 0x1dc0, | ||
160 | .status_reg = 0x1ddc, | ||
161 | .status_bit = 17, | ||
162 | .clkr.hw.init = &(struct clk_init_data){ | ||
163 | .name = "gpll4", | ||
164 | .parent_names = (const char *[]){ "xo" }, | ||
165 | .num_parents = 1, | ||
166 | .ops = &clk_pll_ops, | ||
167 | }, | ||
168 | }; | ||
169 | |||
170 | static struct clk_regmap gpll4_vote = { | ||
171 | .enable_reg = 0x1480, | ||
172 | .enable_mask = BIT(4), | ||
173 | .hw.init = &(struct clk_init_data){ | ||
174 | .name = "gpll4_vote", | ||
175 | .parent_names = (const char *[]){ "gpll4" }, | ||
176 | .num_parents = 1, | ||
177 | .ops = &clk_pll_vote_ops, | ||
178 | }, | ||
179 | }; | ||
180 | |||
140 | static const struct freq_tbl ftbl_gcc_usb30_master_clk[] = { | 181 | static const struct freq_tbl ftbl_gcc_usb30_master_clk[] = { |
141 | F(125000000, P_GPLL0, 1, 5, 24), | 182 | F(125000000, P_GPLL0, 1, 5, 24), |
142 | { } | 183 | { } |
@@ -811,18 +852,33 @@ static const struct freq_tbl ftbl_gcc_sdcc1_4_apps_clk[] = { | |||
811 | { } | 852 | { } |
812 | }; | 853 | }; |
813 | 854 | ||
855 | static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_pro[] = { | ||
856 | F(144000, P_XO, 16, 3, 25), | ||
857 | F(400000, P_XO, 12, 1, 4), | ||
858 | F(20000000, P_GPLL0, 15, 1, 2), | ||
859 | F(25000000, P_GPLL0, 12, 1, 2), | ||
860 | F(50000000, P_GPLL0, 12, 0, 0), | ||
861 | F(100000000, P_GPLL0, 6, 0, 0), | ||
862 | F(192000000, P_GPLL4, 4, 0, 0), | ||
863 | F(200000000, P_GPLL0, 3, 0, 0), | ||
864 | F(384000000, P_GPLL4, 2, 0, 0), | ||
865 | { } | ||
866 | }; | ||
867 | |||
868 | static struct clk_init_data sdcc1_apps_clk_src_init = { | ||
869 | .name = "sdcc1_apps_clk_src", | ||
870 | .parent_names = gcc_xo_gpll0, | ||
871 | .num_parents = 2, | ||
872 | .ops = &clk_rcg2_ops, | ||
873 | }; | ||
874 | |||
814 | static struct clk_rcg2 sdcc1_apps_clk_src = { | 875 | static struct clk_rcg2 sdcc1_apps_clk_src = { |
815 | .cmd_rcgr = 0x04d0, | 876 | .cmd_rcgr = 0x04d0, |
816 | .mnd_width = 8, | 877 | .mnd_width = 8, |
817 | .hid_width = 5, | 878 | .hid_width = 5, |
818 | .parent_map = gcc_xo_gpll0_map, | 879 | .parent_map = gcc_xo_gpll0_map, |
819 | .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk, | 880 | .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk, |
820 | .clkr.hw.init = &(struct clk_init_data){ | 881 | .clkr.hw.init = &sdcc1_apps_clk_src_init, |
821 | .name = "sdcc1_apps_clk_src", | ||
822 | .parent_names = gcc_xo_gpll0, | ||
823 | .num_parents = 2, | ||
824 | .ops = &clk_rcg2_ops, | ||
825 | }, | ||
826 | }; | 882 | }; |
827 | 883 | ||
828 | static struct clk_rcg2 sdcc2_apps_clk_src = { | 884 | static struct clk_rcg2 sdcc2_apps_clk_src = { |
@@ -1340,7 +1396,7 @@ static struct clk_branch gcc_blsp1_uart6_apps_clk = { | |||
1340 | }; | 1396 | }; |
1341 | 1397 | ||
1342 | static struct clk_branch gcc_blsp2_ahb_clk = { | 1398 | static struct clk_branch gcc_blsp2_ahb_clk = { |
1343 | .halt_reg = 0x05c4, | 1399 | .halt_reg = 0x0944, |
1344 | .halt_check = BRANCH_HALT_VOTED, | 1400 | .halt_check = BRANCH_HALT_VOTED, |
1345 | .clkr = { | 1401 | .clkr = { |
1346 | .enable_reg = 0x1484, | 1402 | .enable_reg = 0x1484, |
@@ -1994,6 +2050,38 @@ static struct clk_branch gcc_sdcc1_apps_clk = { | |||
1994 | }, | 2050 | }, |
1995 | }; | 2051 | }; |
1996 | 2052 | ||
2053 | static struct clk_branch gcc_sdcc1_cdccal_ff_clk = { | ||
2054 | .halt_reg = 0x04e8, | ||
2055 | .clkr = { | ||
2056 | .enable_reg = 0x04e8, | ||
2057 | .enable_mask = BIT(0), | ||
2058 | .hw.init = &(struct clk_init_data){ | ||
2059 | .name = "gcc_sdcc1_cdccal_ff_clk", | ||
2060 | .parent_names = (const char *[]){ | ||
2061 | "xo" | ||
2062 | }, | ||
2063 | .num_parents = 1, | ||
2064 | .ops = &clk_branch2_ops, | ||
2065 | }, | ||
2066 | }, | ||
2067 | }; | ||
2068 | |||
2069 | static struct clk_branch gcc_sdcc1_cdccal_sleep_clk = { | ||
2070 | .halt_reg = 0x04e4, | ||
2071 | .clkr = { | ||
2072 | .enable_reg = 0x04e4, | ||
2073 | .enable_mask = BIT(0), | ||
2074 | .hw.init = &(struct clk_init_data){ | ||
2075 | .name = "gcc_sdcc1_cdccal_sleep_clk", | ||
2076 | .parent_names = (const char *[]){ | ||
2077 | "sleep_clk_src" | ||
2078 | }, | ||
2079 | .num_parents = 1, | ||
2080 | .ops = &clk_branch2_ops, | ||
2081 | }, | ||
2082 | }, | ||
2083 | }; | ||
2084 | |||
1997 | static struct clk_branch gcc_sdcc2_ahb_clk = { | 2085 | static struct clk_branch gcc_sdcc2_ahb_clk = { |
1998 | .halt_reg = 0x0508, | 2086 | .halt_reg = 0x0508, |
1999 | .clkr = { | 2087 | .clkr = { |
@@ -2483,6 +2571,10 @@ static struct clk_regmap *gcc_msm8974_clocks[] = { | |||
2483 | [GCC_USB_HSIC_IO_CAL_SLEEP_CLK] = &gcc_usb_hsic_io_cal_sleep_clk.clkr, | 2571 | [GCC_USB_HSIC_IO_CAL_SLEEP_CLK] = &gcc_usb_hsic_io_cal_sleep_clk.clkr, |
2484 | [GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr, | 2572 | [GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr, |
2485 | [GCC_MMSS_GPLL0_CLK_SRC] = &gcc_mmss_gpll0_clk_src, | 2573 | [GCC_MMSS_GPLL0_CLK_SRC] = &gcc_mmss_gpll0_clk_src, |
2574 | [GPLL4] = NULL, | ||
2575 | [GPLL4_VOTE] = NULL, | ||
2576 | [GCC_SDCC1_CDCCAL_SLEEP_CLK] = NULL, | ||
2577 | [GCC_SDCC1_CDCCAL_FF_CLK] = NULL, | ||
2486 | }; | 2578 | }; |
2487 | 2579 | ||
2488 | static const struct qcom_reset_map gcc_msm8974_resets[] = { | 2580 | static const struct qcom_reset_map gcc_msm8974_resets[] = { |
@@ -2574,51 +2666,51 @@ static const struct regmap_config gcc_msm8974_regmap_config = { | |||
2574 | .fast_io = true, | 2666 | .fast_io = true, |
2575 | }; | 2667 | }; |
2576 | 2668 | ||
2669 | static const struct qcom_cc_desc gcc_msm8974_desc = { | ||
2670 | .config = &gcc_msm8974_regmap_config, | ||
2671 | .clks = gcc_msm8974_clocks, | ||
2672 | .num_clks = ARRAY_SIZE(gcc_msm8974_clocks), | ||
2673 | .resets = gcc_msm8974_resets, | ||
2674 | .num_resets = ARRAY_SIZE(gcc_msm8974_resets), | ||
2675 | }; | ||
2676 | |||
2577 | static const struct of_device_id gcc_msm8974_match_table[] = { | 2677 | static const struct of_device_id gcc_msm8974_match_table[] = { |
2578 | { .compatible = "qcom,gcc-msm8974" }, | 2678 | { .compatible = "qcom,gcc-msm8974" }, |
2679 | { .compatible = "qcom,gcc-msm8974pro" , .data = (void *)1UL }, | ||
2680 | { .compatible = "qcom,gcc-msm8974pro-ac", .data = (void *)1UL }, | ||
2579 | { } | 2681 | { } |
2580 | }; | 2682 | }; |
2581 | MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table); | 2683 | MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table); |
2582 | 2684 | ||
2583 | struct qcom_cc { | 2685 | static void msm8974_pro_clock_override(void) |
2584 | struct qcom_reset_controller reset; | 2686 | { |
2585 | struct clk_onecell_data data; | 2687 | sdcc1_apps_clk_src_init.parent_names = gcc_xo_gpll0_gpll4; |
2586 | struct clk *clks[]; | 2688 | sdcc1_apps_clk_src_init.num_parents = 3; |
2587 | }; | 2689 | sdcc1_apps_clk_src.freq_tbl = ftbl_gcc_sdcc1_apps_clk_pro; |
2690 | sdcc1_apps_clk_src.parent_map = gcc_xo_gpll0_gpll4_map; | ||
2691 | |||
2692 | gcc_msm8974_clocks[GPLL4] = &gpll4.clkr; | ||
2693 | gcc_msm8974_clocks[GPLL4_VOTE] = &gpll4_vote; | ||
2694 | gcc_msm8974_clocks[GCC_SDCC1_CDCCAL_SLEEP_CLK] = | ||
2695 | &gcc_sdcc1_cdccal_sleep_clk.clkr; | ||
2696 | gcc_msm8974_clocks[GCC_SDCC1_CDCCAL_FF_CLK] = | ||
2697 | &gcc_sdcc1_cdccal_ff_clk.clkr; | ||
2698 | } | ||
2588 | 2699 | ||
2589 | static int gcc_msm8974_probe(struct platform_device *pdev) | 2700 | static int gcc_msm8974_probe(struct platform_device *pdev) |
2590 | { | 2701 | { |
2591 | void __iomem *base; | ||
2592 | struct resource *res; | ||
2593 | int i, ret; | ||
2594 | struct device *dev = &pdev->dev; | ||
2595 | struct clk *clk; | 2702 | struct clk *clk; |
2596 | struct clk_onecell_data *data; | 2703 | struct device *dev = &pdev->dev; |
2597 | struct clk **clks; | 2704 | bool pro; |
2598 | struct regmap *regmap; | 2705 | const struct of_device_id *id; |
2599 | size_t num_clks; | 2706 | |
2600 | struct qcom_reset_controller *reset; | 2707 | id = of_match_device(gcc_msm8974_match_table, dev); |
2601 | struct qcom_cc *cc; | 2708 | if (!id) |
2602 | 2709 | return -ENODEV; | |
2603 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2710 | pro = !!(id->data); |
2604 | base = devm_ioremap_resource(dev, res); | 2711 | |
2605 | if (IS_ERR(base)) | 2712 | if (pro) |
2606 | return PTR_ERR(base); | 2713 | msm8974_pro_clock_override(); |
2607 | |||
2608 | regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8974_regmap_config); | ||
2609 | if (IS_ERR(regmap)) | ||
2610 | return PTR_ERR(regmap); | ||
2611 | |||
2612 | num_clks = ARRAY_SIZE(gcc_msm8974_clocks); | ||
2613 | cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks, | ||
2614 | GFP_KERNEL); | ||
2615 | if (!cc) | ||
2616 | return -ENOMEM; | ||
2617 | |||
2618 | clks = cc->clks; | ||
2619 | data = &cc->data; | ||
2620 | data->clks = clks; | ||
2621 | data->clk_num = num_clks; | ||
2622 | 2714 | ||
2623 | /* Temporary until RPM clocks supported */ | 2715 | /* Temporary until RPM clocks supported */ |
2624 | clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000); | 2716 | clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000); |
@@ -2631,39 +2723,12 @@ static int gcc_msm8974_probe(struct platform_device *pdev) | |||
2631 | if (IS_ERR(clk)) | 2723 | if (IS_ERR(clk)) |
2632 | return PTR_ERR(clk); | 2724 | return PTR_ERR(clk); |
2633 | 2725 | ||
2634 | for (i = 0; i < num_clks; i++) { | 2726 | return qcom_cc_probe(pdev, &gcc_msm8974_desc); |
2635 | if (!gcc_msm8974_clocks[i]) | ||
2636 | continue; | ||
2637 | clk = devm_clk_register_regmap(dev, gcc_msm8974_clocks[i]); | ||
2638 | if (IS_ERR(clk)) | ||
2639 | return PTR_ERR(clk); | ||
2640 | clks[i] = clk; | ||
2641 | } | ||
2642 | |||
2643 | ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data); | ||
2644 | if (ret) | ||
2645 | return ret; | ||
2646 | |||
2647 | reset = &cc->reset; | ||
2648 | reset->rcdev.of_node = dev->of_node; | ||
2649 | reset->rcdev.ops = &qcom_reset_ops, | ||
2650 | reset->rcdev.owner = THIS_MODULE, | ||
2651 | reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8974_resets), | ||
2652 | reset->regmap = regmap; | ||
2653 | reset->reset_map = gcc_msm8974_resets, | ||
2654 | platform_set_drvdata(pdev, &reset->rcdev); | ||
2655 | |||
2656 | ret = reset_controller_register(&reset->rcdev); | ||
2657 | if (ret) | ||
2658 | of_clk_del_provider(dev->of_node); | ||
2659 | |||
2660 | return ret; | ||
2661 | } | 2727 | } |
2662 | 2728 | ||
2663 | static int gcc_msm8974_remove(struct platform_device *pdev) | 2729 | static int gcc_msm8974_remove(struct platform_device *pdev) |
2664 | { | 2730 | { |
2665 | of_clk_del_provider(pdev->dev.of_node); | 2731 | qcom_cc_remove(pdev); |
2666 | reset_controller_unregister(platform_get_drvdata(pdev)); | ||
2667 | return 0; | 2732 | return 0; |
2668 | } | 2733 | } |
2669 | 2734 | ||