]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
CLK: TI: DPLL: add support for omap2 core dpll
authorTero Kristo <t-kristo@ti.com>
Fri, 21 Feb 2014 15:36:21 +0000 (17:36 +0200)
committerTero Kristo <t-kristo@ti.com>
Wed, 28 May 2014 09:28:20 +0000 (12:28 +0300)
OMAP2 has slightly different DPLL compared to later OMAP generations.
This patch adds support for the ti,omap2-dpll-core-clock and also adds
the bindings documentation.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Documentation/devicetree/bindings/clock/ti/dpll.txt
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock2xxx.h
drivers/clk/ti/dpll.c
include/linux/clk/ti.h

index 30bfdb7c9f18a7137a5e9e7de12accfb4e82f6f2..50a1a427608f00edfbd62f88139e29320b91997f 100644 (file)
@@ -30,6 +30,7 @@ Required properties:
                "ti,am3-dpll-clock",
                "ti,am3-dpll-core-clock",
                "ti,am3-dpll-x2-clock",
+               "ti,omap2-dpll-core-clock",
 
 - #clock-cells : from common clock binding; shall be set to 0.
 - clocks : link phandles of parent clocks, first entry lists reference clock
@@ -41,6 +42,7 @@ Required properties:
        "mult-div1" - contains the multiplier / divider register base address
        "autoidle" - contains the autoidle register base address (optional)
   ti,am3-* dpll types do not have autoidle register
+  ti,omap2-* dpll type does not support idlest / autoidle registers
 
 Optional properties:
 - DPLL mode setting - defining any one or more of the following overrides
@@ -73,3 +75,10 @@ Examples:
                clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
                reg = <0x90>, <0x5c>, <0x68>;
        };
+
+       dpll_ck: dpll_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap2-dpll-core-clock";
+               clocks = <&sys_ck>, <&sys_ck>;
+               reg = <0x0500>, <0x0540>;
+       };
index bda767a9dea862d7223d86d1a59c0b1505e091f9..f6e9904d7a75252ebc988ae75a5cb544d5b53a07 100644 (file)
@@ -279,7 +279,6 @@ extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
 extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
 extern const struct clk_hw_omap_ops clkhwops_apll54;
 extern const struct clk_hw_omap_ops clkhwops_apll96;
-extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
 extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
 
 /* clksel_rate blocks shared between OMAP44xx and AM33xx */
index 539dc08afbbaf3cb93536f600a5bb930b35d7d55..45f41a4116031be4cbb722bc2db63cc33841c31f 100644 (file)
@@ -21,10 +21,6 @@ unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk,
                                      unsigned long parent_rate);
 unsigned long omap2_osc_clk_recalc(struct clk_hw *clk,
                                   unsigned long parent_rate);
-unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
-                                   unsigned long parent_rate);
-int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
-                            unsigned long parent_rate);
 void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
 unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw,
                                      unsigned long parent_rate);
index dda262db42ea57260687941dc57abc9d013b346a..34e2339902124bd14916b9234b18ed0a95e7d5cf 100644 (file)
@@ -35,21 +35,18 @@ static const struct clk_ops dpll_m4xen_ck_ops = {
        .set_rate       = &omap3_noncore_dpll_set_rate,
        .get_parent     = &omap2_init_dpll_parent,
 };
+#else
+static const struct clk_ops dpll_m4xen_ck_ops = {};
 #endif
 
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) || \
+       defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX) || \
+       defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX)
 static const struct clk_ops dpll_core_ck_ops = {
        .recalc_rate    = &omap3_dpll_recalc,
        .get_parent     = &omap2_init_dpll_parent,
 };
 
-#ifdef CONFIG_ARCH_OMAP3
-static const struct clk_ops omap3_dpll_core_ck_ops = {
-       .get_parent     = &omap2_init_dpll_parent,
-       .recalc_rate    = &omap3_dpll_recalc,
-       .round_rate     = &omap2_dpll_round_rate,
-};
-#endif
-
 static const struct clk_ops dpll_ck_ops = {
        .enable         = &omap3_noncore_dpll_enable,
        .disable        = &omap3_noncore_dpll_disable,
@@ -65,6 +62,33 @@ static const struct clk_ops dpll_no_gate_ck_ops = {
        .round_rate     = &omap2_dpll_round_rate,
        .set_rate       = &omap3_noncore_dpll_set_rate,
 };
+#else
+static const struct clk_ops dpll_core_ck_ops = {};
+static const struct clk_ops dpll_ck_ops = {};
+static const struct clk_ops dpll_no_gate_ck_ops = {};
+const struct clk_hw_omap_ops clkhwops_omap3_dpll = {};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+static const struct clk_ops omap2_dpll_core_ck_ops = {
+       .get_parent     = &omap2_init_dpll_parent,
+       .recalc_rate    = &omap2_dpllcore_recalc,
+       .round_rate     = &omap2_dpll_round_rate,
+       .set_rate       = &omap2_reprogram_dpllcore,
+};
+#else
+static const struct clk_ops omap2_dpll_core_ck_ops = {};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static const struct clk_ops omap3_dpll_core_ck_ops = {
+       .get_parent     = &omap2_init_dpll_parent,
+       .recalc_rate    = &omap3_dpll_recalc,
+       .round_rate     = &omap2_dpll_round_rate,
+};
+#else
+static const struct clk_ops omap3_dpll_core_ck_ops = {};
+#endif
 
 #ifdef CONFIG_ARCH_OMAP3
 static const struct clk_ops omap3_dpll_ck_ops = {
@@ -237,10 +261,27 @@ static void __init of_ti_dpll_setup(struct device_node *node,
        init->parent_names = parent_names;
 
        dd->control_reg = ti_clk_get_reg_addr(node, 0);
-       dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
-       dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
 
-       if (!dd->control_reg || !dd->idlest_reg || !dd->mult_div1_reg)
+       /*
+        * Special case for OMAP2 DPLL, register order is different due to
+        * missing idlest_reg, also clkhwops is different. Detected from
+        * missing idlest_mask.
+        */
+       if (!dd->idlest_mask) {
+               dd->mult_div1_reg = ti_clk_get_reg_addr(node, 1);
+#ifdef CONFIG_ARCH_OMAP2
+               clk_hw->ops = &clkhwops_omap2xxx_dpll;
+               omap2xxx_clkt_dpllcore_init(&clk_hw->hw);
+#endif
+       } else {
+               dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
+               if (!dd->idlest_reg)
+                       goto cleanup;
+
+               dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
+       }
+
+       if (!dd->control_reg || !dd->mult_div1_reg)
                goto cleanup;
 
        if (dd->autoidle_mask) {
@@ -547,3 +588,18 @@ static void __init of_ti_am3_core_dpll_setup(struct device_node *node)
 }
 CLK_OF_DECLARE(ti_am3_core_dpll_clock, "ti,am3-dpll-core-clock",
               of_ti_am3_core_dpll_setup);
+
+static void __init of_ti_omap2_core_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .enable_mask = 0x3,
+               .mult_mask = 0x3ff << 12,
+               .div1_mask = 0xf << 8,
+               .max_divider = 16,
+               .min_divider = 1,
+       };
+
+       of_ti_dpll_setup(node, &omap2_dpll_core_ck_ops, &dd);
+}
+CLK_OF_DECLARE(ti_omap2_core_dpll_clock, "ti,omap2-dpll-core-clock",
+              of_ti_omap2_core_dpll_setup);
index 4a21a872dbbd6423025f1a9253832f228cfe1c48..753878c6fa525a958abdb3cdede371a15b07e845 100644 (file)
@@ -259,6 +259,11 @@ int omap2_dflt_clk_enable(struct clk_hw *hw);
 void omap2_dflt_clk_disable(struct clk_hw *hw);
 int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
 void omap3_clk_lock_dpll5(void);
+unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
+                                   unsigned long parent_rate);
+int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
+                            unsigned long parent_rate);
+void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
 
 void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
@@ -287,6 +292,7 @@ static inline void of_ti_clk_allow_autoidle_all(void) { }
 static inline void of_ti_clk_deny_autoidle_all(void) { }
 #endif
 
+extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
 extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
 extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
 extern const struct clk_hw_omap_ops clkhwops_wait;