aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/qcom/gcc-msm8974.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-07 23:27:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-07 23:27:30 -0400
commit1a5700bc2d10cd379a795fd2bb377a190af5acd4 (patch)
treee9f754cbc34020dd23c1d2e3e45fb6890ba7593c /drivers/clk/qcom/gcc-msm8974.c
parenta68a7509d3af8ee458d32b2416b0c2aaf2a4a7e3 (diff)
parent3cbcb16095f916f50a5a55066fcc4be06946ce1e (diff)
Merge tag 'clk-for-linus-3.16' of git://git.linaro.org/people/mike.turquette/linux into next
Pull clock framework updates from Mike Turquette: "The clock framework changes for 3.16 are pretty typical: mostly clock driver additions and fixes. There are additions to the clock core code for some of the basic types (e.g. the common divider type has some fixes and featured added to it). One minor annoyance is a last-minute dependency that wasn't handled quite right. Commit ba0fae3b06a6 ("clk: berlin: add core clock driver for BG2/BG2CD") in this pull request depends on include/dt-bindings/clock/berlin2.h, which is already in your tree via the arm-soc pull request. Building for the berlin platform will break when the clk tree is built on it's own, but merged into your master branch everything should be fine" * tag 'clk-for-linus-3.16' of git://git.linaro.org/people/mike.turquette/linux: (75 commits) mmc: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs clk: export __clk_round_rate for providers clk: versatile: free icst on error return clk: qcom: Return error pointers for unimplemented clocks clk: qcom: Support msm8974pro global clock control hardware clk: qcom: Properly support display clocks on msm8974 clk: qcom: Support display RCG clocks clk: qcom: Return highest rate when round_rate() exceeds plan clk: qcom: Fix mmcc-8974's PLL configurations clk: qcom: Fix clk_rcg2_is_enabled() check clk: berlin: add core clock driver for BG2Q clk: berlin: add core clock driver for BG2/BG2CD clk: berlin: add driver for BG2x complex divider cells clk: berlin: add driver for BG2x simple PLLs clk: berlin: add driver for BG2x audio/video PLL clk: st: Terminate of match table clk/exynos4: Fix compilation warning ARM: shmobile: r8a7779: Add clock index macros for DT sources clk: divider: Fix overflow in clk_divider_bestdiv clk: u300: Terminate of match table ...
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