Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

CLK: TI: DPLL: add support for omap2 core dpll

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>

+82 -16
+9
Documentation/devicetree/bindings/clock/ti/dpll.txt
··· 30 30 "ti,am3-dpll-clock", 31 31 "ti,am3-dpll-core-clock", 32 32 "ti,am3-dpll-x2-clock", 33 + "ti,omap2-dpll-core-clock", 33 34 34 35 - #clock-cells : from common clock binding; shall be set to 0. 35 36 - clocks : link phandles of parent clocks, first entry lists reference clock ··· 42 41 "mult-div1" - contains the multiplier / divider register base address 43 42 "autoidle" - contains the autoidle register base address (optional) 44 43 ti,am3-* dpll types do not have autoidle register 44 + ti,omap2-* dpll type does not support idlest / autoidle registers 45 45 46 46 Optional properties: 47 47 - DPLL mode setting - defining any one or more of the following overrides ··· 74 72 compatible = "ti,am3-dpll-core-clock"; 75 73 clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; 76 74 reg = <0x90>, <0x5c>, <0x68>; 75 + }; 76 + 77 + dpll_ck: dpll_ck { 78 + #clock-cells = <0>; 79 + compatible = "ti,omap2-dpll-core-clock"; 80 + clocks = <&sys_ck>, <&sys_ck>; 81 + reg = <0x0500>, <0x0540>; 77 82 };
-1
arch/arm/mach-omap2/clock.h
··· 279 279 extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait; 280 280 extern const struct clk_hw_omap_ops clkhwops_apll54; 281 281 extern const struct clk_hw_omap_ops clkhwops_apll96; 282 - extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll; 283 282 extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait; 284 283 285 284 /* clksel_rate blocks shared between OMAP44xx and AM33xx */
-4
arch/arm/mach-omap2/clock2xxx.h
··· 21 21 unsigned long parent_rate); 22 22 unsigned long omap2_osc_clk_recalc(struct clk_hw *clk, 23 23 unsigned long parent_rate); 24 - unsigned long omap2_dpllcore_recalc(struct clk_hw *hw, 25 - unsigned long parent_rate); 26 - int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate, 27 - unsigned long parent_rate); 28 24 void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw); 29 25 unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw, 30 26 unsigned long parent_rate);
+67 -11
drivers/clk/ti/dpll.c
··· 35 35 .set_rate = &omap3_noncore_dpll_set_rate, 36 36 .get_parent = &omap2_init_dpll_parent, 37 37 }; 38 + #else 39 + static const struct clk_ops dpll_m4xen_ck_ops = {}; 38 40 #endif 39 41 42 + #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) || \ 43 + defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX) || \ 44 + defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX) 40 45 static const struct clk_ops dpll_core_ck_ops = { 41 46 .recalc_rate = &omap3_dpll_recalc, 42 47 .get_parent = &omap2_init_dpll_parent, 43 48 }; 44 - 45 - #ifdef CONFIG_ARCH_OMAP3 46 - static const struct clk_ops omap3_dpll_core_ck_ops = { 47 - .get_parent = &omap2_init_dpll_parent, 48 - .recalc_rate = &omap3_dpll_recalc, 49 - .round_rate = &omap2_dpll_round_rate, 50 - }; 51 - #endif 52 49 53 50 static const struct clk_ops dpll_ck_ops = { 54 51 .enable = &omap3_noncore_dpll_enable, ··· 62 65 .round_rate = &omap2_dpll_round_rate, 63 66 .set_rate = &omap3_noncore_dpll_set_rate, 64 67 }; 68 + #else 69 + static const struct clk_ops dpll_core_ck_ops = {}; 70 + static const struct clk_ops dpll_ck_ops = {}; 71 + static const struct clk_ops dpll_no_gate_ck_ops = {}; 72 + const struct clk_hw_omap_ops clkhwops_omap3_dpll = {}; 73 + #endif 74 + 75 + #ifdef CONFIG_ARCH_OMAP2 76 + static const struct clk_ops omap2_dpll_core_ck_ops = { 77 + .get_parent = &omap2_init_dpll_parent, 78 + .recalc_rate = &omap2_dpllcore_recalc, 79 + .round_rate = &omap2_dpll_round_rate, 80 + .set_rate = &omap2_reprogram_dpllcore, 81 + }; 82 + #else 83 + static const struct clk_ops omap2_dpll_core_ck_ops = {}; 84 + #endif 85 + 86 + #ifdef CONFIG_ARCH_OMAP3 87 + static const struct clk_ops omap3_dpll_core_ck_ops = { 88 + .get_parent = &omap2_init_dpll_parent, 89 + .recalc_rate = &omap3_dpll_recalc, 90 + .round_rate = &omap2_dpll_round_rate, 91 + }; 92 + #else 93 + static const struct clk_ops omap3_dpll_core_ck_ops = {}; 94 + #endif 65 95 66 96 #ifdef CONFIG_ARCH_OMAP3 67 97 static const struct clk_ops omap3_dpll_ck_ops = { ··· 261 237 init->parent_names = parent_names; 262 238 263 239 dd->control_reg = ti_clk_get_reg_addr(node, 0); 264 - dd->idlest_reg = ti_clk_get_reg_addr(node, 1); 265 - dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2); 266 240 267 - if (!dd->control_reg || !dd->idlest_reg || !dd->mult_div1_reg) 241 + /* 242 + * Special case for OMAP2 DPLL, register order is different due to 243 + * missing idlest_reg, also clkhwops is different. Detected from 244 + * missing idlest_mask. 245 + */ 246 + if (!dd->idlest_mask) { 247 + dd->mult_div1_reg = ti_clk_get_reg_addr(node, 1); 248 + #ifdef CONFIG_ARCH_OMAP2 249 + clk_hw->ops = &clkhwops_omap2xxx_dpll; 250 + omap2xxx_clkt_dpllcore_init(&clk_hw->hw); 251 + #endif 252 + } else { 253 + dd->idlest_reg = ti_clk_get_reg_addr(node, 1); 254 + if (!dd->idlest_reg) 255 + goto cleanup; 256 + 257 + dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2); 258 + } 259 + 260 + if (!dd->control_reg || !dd->mult_div1_reg) 268 261 goto cleanup; 269 262 270 263 if (dd->autoidle_mask) { ··· 588 547 } 589 548 CLK_OF_DECLARE(ti_am3_core_dpll_clock, "ti,am3-dpll-core-clock", 590 549 of_ti_am3_core_dpll_setup); 550 + 551 + static void __init of_ti_omap2_core_dpll_setup(struct device_node *node) 552 + { 553 + const struct dpll_data dd = { 554 + .enable_mask = 0x3, 555 + .mult_mask = 0x3ff << 12, 556 + .div1_mask = 0xf << 8, 557 + .max_divider = 16, 558 + .min_divider = 1, 559 + }; 560 + 561 + of_ti_dpll_setup(node, &omap2_dpll_core_ck_ops, &dd); 562 + } 563 + CLK_OF_DECLARE(ti_omap2_core_dpll_clock, "ti,omap2-dpll-core-clock", 564 + of_ti_omap2_core_dpll_setup);
+6
include/linux/clk/ti.h
··· 259 259 void omap2_dflt_clk_disable(struct clk_hw *hw); 260 260 int omap2_dflt_clk_is_enabled(struct clk_hw *hw); 261 261 void omap3_clk_lock_dpll5(void); 262 + unsigned long omap2_dpllcore_recalc(struct clk_hw *hw, 263 + unsigned long parent_rate); 264 + int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate, 265 + unsigned long parent_rate); 266 + void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw); 262 267 263 268 void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index); 264 269 void ti_dt_clocks_register(struct ti_dt_clk *oclks); ··· 292 287 static inline void of_ti_clk_deny_autoidle_all(void) { } 293 288 #endif 294 289 290 + extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll; 295 291 extern const struct clk_hw_omap_ops clkhwops_omap3_dpll; 296 292 extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx; 297 293 extern const struct clk_hw_omap_ops clkhwops_wait;