Skip to content

Commit

Permalink
CLK: TI: DPLL: add support for omap2 core dpll
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tero Kristo committed May 28, 2014
1 parent a6fe377 commit aa76fcf
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 16 deletions.
9 changes: 9 additions & 0 deletions Documentation/devicetree/bindings/clock/ti/dpll.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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>;
};
1 change: 0 additions & 1 deletion arch/arm/mach-omap2/clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
4 changes: 0 additions & 4 deletions arch/arm/mach-omap2/clock2xxx.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
78 changes: 67 additions & 11 deletions drivers/clk/ti/dpll.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 = {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
6 changes: 6 additions & 0 deletions include/linux/clk/ti.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit aa76fcf

Please sign in to comment.