aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/qcom/gcc-msm8974.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/qcom/gcc-msm8974.c')
-rw-r--r--drivers/clk/qcom/gcc-msm8974.c207
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
38static const u8 gcc_xo_gpll0_map[] = { 40static 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
50static const u8 gcc_xo_gpll0_gpll4_map[] = {
51 [P_XO] = 0,
52 [P_GPLL0] = 1,
53 [P_GPLL4] = 5,
54};
55
56static 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
50static struct clk_pll gpll0 = { 64static struct clk_pll gpll0 = {
@@ -137,6 +151,33 @@ static struct clk_regmap gpll1_vote = {
137 }, 151 },
138}; 152};
139 153
154static 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
170static 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
140static const struct freq_tbl ftbl_gcc_usb30_master_clk[] = { 181static 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
855static 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
868static 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
814static struct clk_rcg2 sdcc1_apps_clk_src = { 875static 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
828static struct clk_rcg2 sdcc2_apps_clk_src = { 884static struct clk_rcg2 sdcc2_apps_clk_src = {
@@ -1340,7 +1396,7 @@ static struct clk_branch gcc_blsp1_uart6_apps_clk = {
1340}; 1396};
1341 1397
1342static struct clk_branch gcc_blsp2_ahb_clk = { 1398static 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
2053static 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
2069static 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
1997static struct clk_branch gcc_sdcc2_ahb_clk = { 2085static 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
2488static const struct qcom_reset_map gcc_msm8974_resets[] = { 2580static 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
2669static 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
2577static const struct of_device_id gcc_msm8974_match_table[] = { 2677static 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};
2581MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table); 2683MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table);
2582 2684
2583struct qcom_cc { 2685static 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
2589static int gcc_msm8974_probe(struct platform_device *pdev) 2700static 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
2663static int gcc_msm8974_remove(struct platform_device *pdev) 2729static 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