The callbacks for clocks are almost the same as those used on common_clk, now reduce the number of remaining differences: - make .recalc_rate and .round_rate take a parent_rate argument - move .recalc_rate/.set_rate/.round_rate/.init from 'struct clk_hw' into 'struct clk_ops'. Signed-off-by: Arnd Bergmann <arnd@xxxxxxxx> --- arch/arm/mach-omap1/clock.c | 368 ++++++++++++++++++++---------------- 1 file changed, 200 insertions(+), 168 deletions(-) diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 577686f61b3b..8b4d5ee13ba0 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -56,6 +56,10 @@ struct omap1_clk_lookup { * struct clk_ops - some clock function pointers * @enable: fn ptr that enables the current clock in hardware * @disable: fn ptr that enables the current clock in hardware + * @recalc_rate: fn ptr that returns the clock's current rate + * @set_rate: fn ptr that can change the clock's current rate + * @round_rate: fn ptr that can round the clock's current rate + * @init: fn ptr to do clock-specific initialization * * A "companion" clk is an accompanying clock to the one being queried * that must be enabled for the IP module connected to the clock to @@ -66,8 +70,12 @@ struct omap1_clk_lookup { * @find_companion must, unfortunately, remain. */ struct clk_ops { - int (*enable)(struct clk_hw *); - void (*disable)(struct clk_hw *); + int (*enable)(struct clk_hw *); + void (*disable)(struct clk_hw *); + unsigned long (*recalc_rate)(struct clk_hw *, unsigned long); + int (*set_rate)(struct clk_hw *, unsigned long, unsigned long); + long (*round_rate)(struct clk_hw *, unsigned long, unsigned long *); + void (*init)(struct clk_hw *); }; /* @@ -90,10 +98,6 @@ struct clk_ops { * @sibling: list_head connecting this clk to its parent clk's @children * @rate: current clock rate * @enable_reg: register to write to enable the clock (see @enable_bit) - * @recalc: fn ptr that returns the clock's current rate - * @set_rate: fn ptr that can change the clock's current rate - * @round_rate: fn ptr that can round the clock's current rate - * @init: fn ptr to do clock-specific initialization * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg) * @usecount: number of users that have requested this clock to be enabled * @fixed_div: when > 0, this clock's rate is its parent's rate / @fixed_div @@ -138,10 +142,6 @@ struct omap1_clk { struct list_head sibling; /* node for children */ unsigned long rate; void __iomem *enable_reg; - unsigned long (*recalc)(struct clk_hw *); - int (*set_rate)(struct clk_hw *, unsigned long); - long (*round_rate)(struct clk_hw *, unsigned long); - void (*init)(struct clk_hw *); u8 enable_bit; s8 usecount; u8 fixed_div; @@ -268,22 +268,21 @@ static DEFINE_SPINLOCK(clockfw_lock); * Omap1 specific clock functions */ -static unsigned long omap1_uart_recalc(struct clk_hw *clk_hw) +static unsigned long omap1_uart_recalc(struct clk_hw *clk_hw, unsigned long parent_rate) { struct omap1_clk *clk = to_omap1_clk(clk_hw); unsigned int val = __raw_readl(clk->enable_reg); return val & clk->enable_bit ? 48000000 : 12000000; } -static unsigned long omap1_sossi_recalc(struct clk_hw *clk_hw) +static unsigned long omap1_sossi_recalc(struct clk_hw *clk_hw, unsigned long parent_rate) { - struct omap1_clk *clk = to_omap1_clk(clk_hw); u32 div = omap_readl(MOD_CONF_CTRL_1); div = (div >> 17) & 0x7; div++; - return clk->parent->rate / div; + return parent_rate / div; } static void omap1_clk_allow_idle(struct clk_hw *clk_hw) @@ -363,7 +362,7 @@ static __u16 verify_ckctl_value(__u16 newval) return newval; } -static int calc_dsor_exp(struct omap1_clk *clk, unsigned long rate) +static int calc_dsor_exp(struct omap1_clk *clk, unsigned long rate, unsigned long parent_rate) { /* Note: If target frequency is too low, this function will return 4, * which is invalid value. Caller must check for this value and act @@ -377,14 +376,9 @@ static int calc_dsor_exp(struct omap1_clk *clk, unsigned long rate) * DSPMMU_CK >= TC_CK */ unsigned long realrate; - struct omap1_clk * parent; unsigned dsor_exp; - parent = clk->parent; - if (unlikely(parent == NULL)) - return -EIO; - - realrate = parent->rate; + realrate = parent_rate; for (dsor_exp=0; dsor_exp<4; dsor_exp++) { if (realrate <= rate) break; @@ -395,13 +389,13 @@ static int calc_dsor_exp(struct omap1_clk *clk, unsigned long rate) return dsor_exp; } -static unsigned long omap1_ckctl_recalc(struct clk_hw *clk_hw) +static unsigned long omap1_ckctl_recalc(struct clk_hw *clk_hw, unsigned long parent_rate) { struct omap1_clk *clk = to_omap1_clk(clk_hw); /* Calculate divisor encoded as 2-bit exponent */ int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset)); - return clk->parent->rate / dsor; + return parent_rate / dsor; } /*------------------------------------------------------------------------- @@ -453,7 +447,7 @@ static struct mpu_rate omap1_rate_table[] = { }; /* MPU virtual clock functions */ -static int omap1_select_table_rate(struct clk_hw *clk_hw, unsigned long rate) +static int omap1_select_table_rate(struct clk_hw *clk_hw, unsigned long rate, unsigned long parent_rate) { /* Find the highest supported frequency <= rate and switch to it */ struct mpu_rate * ptr; @@ -488,13 +482,13 @@ static int omap1_select_table_rate(struct clk_hw *clk_hw, unsigned long rate) return 0; } -static int omap1_clk_set_rate_dsp_domain(struct clk_hw *clk_hw, unsigned long rate) +static int omap1_clk_set_rate_dsp_domain(struct clk_hw *clk_hw, unsigned long rate, unsigned long parent_rate) { struct omap1_clk *clk = to_omap1_clk(clk_hw); int dsor_exp; u16 regval; - dsor_exp = calc_dsor_exp(clk, rate); + dsor_exp = calc_dsor_exp(clk, rate, parent_rate); if (dsor_exp > 3) dsor_exp = -EINVAL; if (dsor_exp < 0) @@ -504,29 +498,29 @@ static int omap1_clk_set_rate_dsp_domain(struct clk_hw *clk_hw, unsigned long ra regval &= ~(3 << clk->rate_offset); regval |= dsor_exp << clk->rate_offset; __raw_writew(regval, DSP_CKCTL); - clk->rate = clk->parent->rate / (1 << dsor_exp); + clk->rate = parent_rate / (1 << dsor_exp); return 0; } -static long omap1_clk_round_rate_ckctl_arm(struct clk_hw *clk_hw, unsigned long rate) +static long omap1_clk_round_rate_ckctl_arm(struct clk_hw *clk_hw, unsigned long rate, unsigned long *parent_rate) { struct omap1_clk *clk = to_omap1_clk(clk_hw); - int dsor_exp = calc_dsor_exp(clk, rate); + int dsor_exp = calc_dsor_exp(clk, rate, *parent_rate); if (dsor_exp < 0) return dsor_exp; if (dsor_exp > 3) dsor_exp = 3; - return clk->parent->rate / (1 << dsor_exp); + return *parent_rate / (1 << dsor_exp); } -static int omap1_clk_set_rate_ckctl_arm(struct clk_hw *clk_hw, unsigned long rate) +static int omap1_clk_set_rate_ckctl_arm(struct clk_hw *clk_hw, unsigned long rate, unsigned long parent_rate) { struct omap1_clk *clk = to_omap1_clk(clk_hw); int dsor_exp; u16 regval; - dsor_exp = calc_dsor_exp(clk, rate); + dsor_exp = calc_dsor_exp(clk, rate, parent_rate); if (dsor_exp > 3) dsor_exp = -EINVAL; if (dsor_exp < 0) @@ -537,11 +531,11 @@ static int omap1_clk_set_rate_ckctl_arm(struct clk_hw *clk_hw, unsigned long rat regval |= dsor_exp << clk->rate_offset; regval = verify_ckctl_value(regval); omap_writew(regval, ARM_CKCTL); - clk->rate = clk->parent->rate / (1 << dsor_exp); + clk->rate = parent_rate / (1 << dsor_exp); return 0; } -static long omap1_round_to_table_rate(struct clk_hw *clk_hw, unsigned long rate) +static long omap1_round_to_table_rate(struct clk_hw *clk_hw, unsigned long rate, unsigned long *parent_rate) { /* Find the highest supported frequency <= rate */ struct mpu_rate * ptr; @@ -592,7 +586,7 @@ static unsigned calc_ext_dsor(unsigned long rate) } /* XXX Only needed on 1510 */ -static int omap1_set_uart_rate(struct clk_hw *clk_hw, unsigned long rate) +static int omap1_set_uart_rate(struct clk_hw *clk_hw, unsigned long rate, unsigned long parent_rate) { struct omap1_clk *clk = to_omap1_clk(clk_hw); unsigned int val; @@ -611,7 +605,7 @@ static int omap1_set_uart_rate(struct clk_hw *clk_hw, unsigned long rate) } /* External clock (MCLK & BCLK) functions */ -static int omap1_set_ext_clk_rate(struct clk_hw *clk_hw, unsigned long rate) +static int omap1_set_ext_clk_rate(struct clk_hw *clk_hw, unsigned long rate, unsigned long parent_rate) { struct omap1_clk *clk = to_omap1_clk(clk_hw); unsigned dsor; @@ -630,16 +624,14 @@ static int omap1_set_ext_clk_rate(struct clk_hw *clk_hw, unsigned long rate) return 0; } -static int omap1_set_sossi_rate(struct clk_hw *clk_hw, unsigned long rate) +static int omap1_set_sossi_rate(struct clk_hw *clk_hw, unsigned long rate, unsigned long parent_rate) { struct omap1_clk *clk = to_omap1_clk(clk_hw); u32 l; int div; - unsigned long p_rate; - p_rate = clk->parent->rate; /* Round towards slower frequency */ - div = (p_rate + rate - 1) / rate; + div = (parent_rate + rate - 1) / rate; div--; if (div < 0 || div > 7) return -EINVAL; @@ -649,12 +641,12 @@ static int omap1_set_sossi_rate(struct clk_hw *clk_hw, unsigned long rate) l |= div << 17; omap_writel(l, MOD_CONF_CTRL_1); - clk->rate = p_rate / (div + 1); + clk->rate = parent_rate / (div + 1); return 0; } -static long omap1_round_ext_clk_rate(struct clk_hw *clk_hw, unsigned long rate) +static long omap1_round_ext_clk_rate(struct clk_hw *clk_hw, unsigned long rate, unsigned long *parent_rate) { return 96000000 / calc_ext_dsor(rate); } @@ -678,16 +670,27 @@ static void omap1_init_ext_clk(struct clk_hw *clk_hw) clk-> rate = 96000000 / dsor; } +struct clk_hw *clk_hw_get_parent(const struct clk_hw *clk_hw) +{ + struct omap1_clk *clk = to_omap1_clk(clk_hw); + + if (!clk->parent) + return NULL; + + return &clk->parent->clk_hw; +} + static void omap1_clk_disable(struct clk_hw *clk_hw) { struct omap1_clk *clk = to_omap1_clk(clk_hw); + struct clk_hw *parent = clk_hw_get_parent(clk_hw); if (clk->usecount > 0 && !(--clk->usecount)) { - clk->ops->disable(&clk->clk_hw); - if (likely(clk->parent)) { - omap1_clk_disable(&clk->parent->clk_hw); + clk->ops->disable(clk_hw); + if (likely(parent)) { + omap1_clk_disable(parent); if (clk->flags & CLOCK_NO_IDLE_PARENT) - omap1_clk_allow_idle(&clk->parent->clk_hw); + omap1_clk_allow_idle(parent); } } } @@ -695,22 +698,23 @@ static void omap1_clk_disable(struct clk_hw *clk_hw) static omap1_clk_enable(struct clk_hw *clk_hw) { struct omap1_clk *clk = to_omap1_clk(clk_hw); + struct clk_hw *parent = clk_hw_get_parent(clk_hw); int ret = 0; if (clk->usecount++ == 0) { - if (clk->parent) { - ret = omap1_clk_enable(&clk->parent->clk_hw); + if (parent) { + ret = omap1_clk_enable(parent); if (ret) goto err; if (clk->flags & CLOCK_NO_IDLE_PARENT) - omap1_clk_deny_idle(&clk->parent->clk_hw); + omap1_clk_deny_idle(parent); } ret = clk->ops->enable(&clk->clk_hw); if (ret) { - if (clk->parent) - omap1_clk_disable(&clk->parent->clk_hw); + if (parent) + omap1_clk_disable(parent); goto err; } } @@ -771,7 +775,7 @@ static const struct clk_ops clkops_generic = { .disable = omap1_clk_disable_generic, }; -static unsigned long omap1_ckctl_recalc_dsp_domain(struct clk_hw *clk_hw) +static unsigned long omap1_ckctl_recalc_dsp_domain(struct clk_hw *clk_hw, unsigned long parent_rate) { struct omap1_clk *clk = to_omap1_clk(clk_hw); int dsor; @@ -787,7 +791,7 @@ static unsigned long omap1_ckctl_recalc_dsp_domain(struct clk_hw *clk_hw) dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset)); omap1_clk_disable(api_ck_p); - return clk->parent->rate / dsor; + return parent_rate / dsor; } static int omap1_clk_enable_dsp_domain(struct clk_hw *clk_hw) @@ -812,11 +816,6 @@ static void omap1_clk_disable_dsp_domain(struct clk_hw *clk_hw) } } -static const struct clk_ops clkops_dspck = { - .enable = omap1_clk_enable_dsp_domain, - .disable = omap1_clk_disable_dsp_domain, -}; - /* XXX SYSC register handling does not belong in the clock framework */ static int omap1_clk_enable_uart_functional_16xx(struct clk_hw *clk_hw) { @@ -857,9 +856,20 @@ static const struct clk_ops clkops_uart_16xx = { static long omap1_clk_round_rate(struct clk_hw *clk_hw, unsigned long rate) { struct omap1_clk *clk = to_omap1_clk(clk_hw); + struct clk_hw *parent = clk_hw_get_parent(clk_hw); + struct omap1_clk *parent_clk; + unsigned long parent_rate = 0; + + if (parent) { + parent_clk = to_omap1_clk(parent); + parent_rate = parent_clk->rate; + } + + if (clk->ops->round_rate != NULL) + return clk->ops->round_rate(clk_hw, rate, &parent_rate); - if (clk->round_rate != NULL) - return clk->round_rate(clk_hw, rate); + if (parent) + parent_clk->rate = parent_rate; return clk->rate; } @@ -867,10 +877,15 @@ static long omap1_clk_round_rate(struct clk_hw *clk_hw, unsigned long rate) static int omap1_clk_set_rate(struct clk_hw *clk_hw, unsigned long rate) { struct omap1_clk *clk = to_omap1_clk(clk_hw); + struct clk_hw *parent = clk_hw_get_parent(clk_hw); + unsigned long parent_rate = 0; int ret = -EINVAL; - if (clk->set_rate) - ret = clk->set_rate(clk_hw, rate); + if (parent) + parent_rate = to_omap1_clk(parent)->rate; + + if (clk->ops->set_rate) + ret = clk->ops->set_rate(clk_hw, rate, parent_rate); return ret; } @@ -880,8 +895,8 @@ static void propagate_rate(struct omap1_clk *tclk) struct omap1_clk *clkp; list_for_each_entry(clkp, &tclk->children, sibling) { - if (clkp->recalc) - clkp->rate = clkp->recalc(&clkp->clk_hw); + if (clkp->ops->recalc_rate) + clkp->rate = clkp->ops->recalc_rate(&clkp->clk_hw, tclk->rate); propagate_rate(clkp); } } @@ -993,9 +1008,12 @@ EXPORT_SYMBOL(clk_set_parent); struct clk *clk_get_parent(struct clk *clk) { - struct omap1_clk *parent = to_omap1_clk(clk->clk_hw)->parent; + struct clk_hw *parent = clk_hw_get_parent(clk->clk_hw); + + if (!parent) + return NULL; - return &parent->clk_hw.clk; + return &parent->clk; } EXPORT_SYMBOL(clk_get_parent); @@ -1004,24 +1022,22 @@ EXPORT_SYMBOL(clk_get_parent); */ /* Used for clocks that always have same value as the parent clock */ -static unsigned long followparent_recalc(struct clk_hw *clk_hw) +static unsigned long followparent_recalc(struct clk_hw *clk_hw, unsigned long parent_rate) { - struct omap1_clk *clk = to_omap1_clk(clk_hw); - - return clk->parent->rate; + return parent_rate; } /* * Used for clocks that have the same value as the parent clock, * divided by some factor */ -static unsigned long omap_fixed_divisor_recalc(struct clk_hw *clk_hw) +static unsigned long omap_fixed_divisor_recalc(struct clk_hw *clk_hw, unsigned long parent_rate) { struct omap1_clk *clk = to_omap1_clk(clk_hw); WARN_ON(!clk->fixed_div); - return clk->parent->rate / clk->fixed_div; + return parent_rate / clk->fixed_div; } /** @@ -1056,8 +1072,8 @@ static int clk_register(struct device *dev, struct clk_hw *clk_hw) list_add(&clk->sibling, &clk->parent->children); list_add(&clk->node, &clocks); - if (clk->init) - clk->init(&clk->clk_hw); + if (clk->ops->init) + clk->ops->init(&clk->clk_hw); mutex_unlock(&clocks_mutex); return 0; @@ -1080,6 +1096,12 @@ static const struct clk_ops clkops_null = { .disable = clkll_disable_null, }; +static const struct clk_ops clkops_followparent = { + .enable = clkll_enable_null, + .disable = clkll_disable_null, + .recalc_rate = followparent_recalc, +}; + /* * Dummy clock * @@ -1239,6 +1261,12 @@ static struct omap1_clk ck_dpll1 = { .parent = &ck_ref, }; +static const struct clk_ops clkops_generic_followparent = { + .enable = omap1_clk_enable_generic, + .disable = omap1_clk_disable_generic, + .recalc_rate = followparent_recalc, +}; + /* * FIXME: This clock seems to be necessary but no-one has asked for its * activation. [ FIX: SoSSI, SSR ] @@ -1246,33 +1274,50 @@ static struct omap1_clk ck_dpll1 = { static struct arm_idlect1_clk ck_dpll1out = { .clk = { .name = "ck_dpll1out", - .ops = &clkops_generic, + .ops = &clkops_generic_followparent, .parent = &ck_dpll1, .flags = CLOCK_IDLE_CONTROL | ENABLE_REG_32BIT, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_CKOUT_ARM, - .recalc = &followparent_recalc, }, .idlect_shift = IDL_CLKOUT_ARM_SHIFT, }; +static const struct clk_ops clkops_sossi = { + .enable = omap1_clk_enable_generic, + .disable = omap1_clk_disable_generic, + .recalc_rate = &omap1_sossi_recalc, + .set_rate = &omap1_set_sossi_rate, +}; + static struct omap1_clk sossi_ck = { .name = "ck_sossi", - .ops = &clkops_generic, + .ops = &clkops_sossi, .parent = &ck_dpll1out.clk, .flags = CLOCK_NO_IDLE_PARENT | ENABLE_REG_32BIT, .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1), .enable_bit = CONF_MOD_SOSSI_CLK_EN_R, - .recalc = &omap1_sossi_recalc, - .set_rate = &omap1_set_sossi_rate, +}; + +struct clk_ops clkops_null_ckctl = { + .enable = clkll_enable_null, + .disable = clkll_disable_null, + .recalc_rate = omap1_ckctl_recalc, + .round_rate = omap1_clk_round_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_ckctl_arm, }; static struct omap1_clk arm_ck = { .name = "arm_ck", - .ops = &clkops_null, + .ops = &clkops_null_ckctl, .parent = &ck_dpll1, .rate_offset = CKCTL_ARMDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, +}; + +struct clk_ops clkops_generic_ckctl = { + .enable = omap1_clk_enable_generic, + .disable = omap1_clk_disable_generic, + .recalc_rate = omap1_ckctl_recalc, .round_rate = omap1_clk_round_rate_ckctl_arm, .set_rate = omap1_clk_set_rate_ckctl_arm, }; @@ -1280,15 +1325,12 @@ static struct omap1_clk arm_ck = { static struct arm_idlect1_clk armper_ck = { .clk = { .name = "armper_ck", - .ops = &clkops_generic, + .ops = &clkops_generic_ckctl, .parent = &ck_dpll1, .flags = CLOCK_IDLE_CONTROL, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_PERCK, .rate_offset = CKCTL_PERDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, }, .idlect_shift = IDLPER_ARM_SHIFT, }; @@ -1299,22 +1341,20 @@ static struct arm_idlect1_clk armper_ck = { */ static struct omap1_clk arm_gpio_ck = { .name = "ick", - .ops = &clkops_generic, + .ops = &clkops_generic_followparent, .parent = &ck_dpll1, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_GPIOCK, - .recalc = &followparent_recalc, }; static struct arm_idlect1_clk armxor_ck = { .clk = { .name = "armxor_ck", - .ops = &clkops_generic, + .ops = &clkops_generic_followparent, .parent = &ck_ref, .flags = CLOCK_IDLE_CONTROL, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_XORPCK, - .recalc = &followparent_recalc, }, .idlect_shift = IDLXORP_ARM_SHIFT, }; @@ -1322,16 +1362,21 @@ static struct arm_idlect1_clk armxor_ck = { static struct arm_idlect1_clk armtim_ck = { .clk = { .name = "armtim_ck", - .ops = &clkops_generic, + .ops = &clkops_generic_followparent, .parent = &ck_ref, .flags = CLOCK_IDLE_CONTROL, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_TIMCK, - .recalc = &followparent_recalc, }, .idlect_shift = IDLTIM_ARM_SHIFT, }; +static const struct clk_ops clkops_fixed_divisor = { + .enable = omap1_clk_enable_generic, + .disable = omap1_clk_disable_generic, + .recalc_rate = omap_fixed_divisor_recalc, +}; + static struct arm_idlect1_clk armwdt_ck = { .clk = { .name = "armwdt_ck", @@ -1341,16 +1386,14 @@ static struct arm_idlect1_clk armwdt_ck = { .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_WDTCK, .fixed_div = 14, - .recalc = &omap_fixed_divisor_recalc, }, .idlect_shift = IDLWDT_ARM_SHIFT, }; static struct omap1_clk arminth_ck16xx = { .name = "arminth_ck", - .ops = &clkops_null, + .ops = &clkops_followparent, .parent = &arm_ck, - .recalc = &followparent_recalc, /* Note: On 16xx the frequency can be divided by 2 by programming * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1 * @@ -1360,24 +1403,26 @@ static struct omap1_clk arminth_ck16xx = { static struct omap1_clk dsp_ck = { .name = "dsp_ck", - .ops = &clkops_generic, + .ops = &clkops_generic_ckctl, .parent = &ck_dpll1, .enable_reg = OMAP1_IO_ADDRESS(ARM_CKCTL), .enable_bit = EN_DSPCK, .rate_offset = CKCTL_DSPDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, }; static struct omap1_clk dspmmu_ck = { .name = "dspmmu_ck", - .ops = &clkops_null, + .ops = &clkops_null_ckctl, .parent = &ck_dpll1, .rate_offset = CKCTL_DSPMMUDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, +}; + +static const struct clk_ops clkops_dspck = { + .enable = omap1_clk_enable_dsp_domain, + .disable = omap1_clk_disable_dsp_domain, + .recalc_rate = omap1_ckctl_recalc_dsp_domain, .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, + .set_rate = omap1_clk_set_rate_dsp_domain, }; static struct omap1_clk dspper_ck = { @@ -1387,48 +1432,45 @@ static struct omap1_clk dspper_ck = { .enable_reg = DSP_IDLECT2, .enable_bit = EN_PERCK, .rate_offset = CKCTL_PERDIV_OFFSET, - .recalc = &omap1_ckctl_recalc_dsp_domain, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = &omap1_clk_set_rate_dsp_domain, +}; + +static const struct clk_ops clkops_dspck_followparent = { + .enable = omap1_clk_enable_dsp_domain, + .disable = omap1_clk_disable_dsp_domain, + .recalc_rate = followparent_recalc, }; static struct omap1_clk dspxor_ck = { .name = "dspxor_ck", - .ops = &clkops_dspck, + .ops = &clkops_dspck_followparent, .parent = &ck_ref, .enable_reg = DSP_IDLECT2, .enable_bit = EN_XORPCK, - .recalc = &followparent_recalc, }; static struct omap1_clk dsptim_ck = { .name = "dsptim_ck", - .ops = &clkops_dspck, + .ops = &clkops_dspck_followparent, .parent = &ck_ref, .enable_reg = DSP_IDLECT2, .enable_bit = EN_DSPTIMCK, - .recalc = &followparent_recalc, }; static struct arm_idlect1_clk tc_ck = { .clk = { .name = "tc_ck", - .ops = &clkops_null, + .ops = &clkops_null_ckctl, .parent = &ck_dpll1, .flags = CLOCK_IDLE_CONTROL, .rate_offset = CKCTL_TCDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, }, .idlect_shift = IDLIF_ARM_SHIFT, }; static struct omap1_clk arminth_ck1510 = { .name = "arminth_ck", - .ops = &clkops_null, + .ops = &clkops_followparent, .parent = &tc_ck.clk, - .recalc = &followparent_recalc, /* Note: On 1510 the frequency follows TC_CK * * 16xx version is in MPU clocks. @@ -1438,28 +1480,25 @@ static struct omap1_clk arminth_ck1510 = { static struct omap1_clk tipb_ck = { /* No-idle controlled by "tc_ck" */ .name = "tipb_ck", - .ops = &clkops_null, + .ops = &clkops_followparent, .parent = &tc_ck.clk, - .recalc = &followparent_recalc, }; static struct omap1_clk l3_ocpi_ck = { /* No-idle controlled by "tc_ck" */ .name = "l3_ocpi_ck", - .ops = &clkops_generic, + .ops = &clkops_generic_followparent, .parent = &tc_ck.clk, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3), .enable_bit = EN_OCPI_CK, - .recalc = &followparent_recalc, }; static struct omap1_clk tc1_ck = { .name = "tc1_ck", - .ops = &clkops_generic, + .ops = &clkops_generic_followparent, .parent = &tc_ck.clk, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3), .enable_bit = EN_TC1_CK, - .recalc = &followparent_recalc, }; /* @@ -1468,37 +1507,33 @@ static struct omap1_clk tc1_ck = { */ static struct omap1_clk tc2_ck = { .name = "tc2_ck", - .ops = &clkops_generic, + .ops = &clkops_generic_followparent, .parent = &tc_ck.clk, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3), .enable_bit = EN_TC2_CK, - .recalc = &followparent_recalc, }; static struct omap1_clk dma_ck = { /* No-idle controlled by "tc_ck" */ .name = "dma_ck", - .ops = &clkops_null, + .ops = &clkops_followparent, .parent = &tc_ck.clk, - .recalc = &followparent_recalc, }; static struct omap1_clk dma_lcdfree_ck = { .name = "dma_lcdfree_ck", - .ops = &clkops_null, + .ops = &clkops_followparent, .parent = &tc_ck.clk, - .recalc = &followparent_recalc, }; static struct arm_idlect1_clk api_ck = { .clk = { .name = "api_ck", - .ops = &clkops_generic, + .ops = &clkops_generic_followparent, .parent = &tc_ck.clk, .flags = CLOCK_IDLE_CONTROL, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_APICK, - .recalc = &followparent_recalc, }, .idlect_shift = IDLAPI_ARM_SHIFT, }; @@ -1506,58 +1541,56 @@ static struct arm_idlect1_clk api_ck = { static struct arm_idlect1_clk lb_ck = { .clk = { .name = "lb_ck", - .ops = &clkops_generic, + .ops = &clkops_generic_followparent, .parent = &tc_ck.clk, .flags = CLOCK_IDLE_CONTROL, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_LBCK, - .recalc = &followparent_recalc, }, .idlect_shift = IDLLB_ARM_SHIFT, }; static struct omap1_clk rhea1_ck = { .name = "rhea1_ck", - .ops = &clkops_null, + .ops = &clkops_followparent, .parent = &tc_ck.clk, - .recalc = &followparent_recalc, }; static struct omap1_clk rhea2_ck = { .name = "rhea2_ck", - .ops = &clkops_null, + .ops = &clkops_followparent, .parent = &tc_ck.clk, - .recalc = &followparent_recalc, }; static struct omap1_clk lcd_ck_16xx = { .name = "lcd_ck", - .ops = &clkops_generic, + .ops = &clkops_generic_ckctl, .parent = &ck_dpll1, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, }; static struct arm_idlect1_clk lcd_ck_1510 = { .clk = { .name = "lcd_ck", - .ops = &clkops_generic, + .ops = &clkops_generic_ckctl, .parent = &ck_dpll1, .flags = CLOCK_IDLE_CONTROL, .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2), .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, - .recalc = &omap1_ckctl_recalc, - .round_rate = omap1_clk_round_rate_ckctl_arm, - .set_rate = omap1_clk_set_rate_ckctl_arm, }, .idlect_shift = OMAP1510_IDLLCD_ARM_SHIFT, }; +static const struct clk_ops clkops_uart = { + .enable = clkll_enable_null, + .disable = clkll_disable_null, + .set_rate = omap1_set_uart_rate, + .recalc_rate = omap1_uart_recalc, +}; + /* * XXX The enable_bit here is misused - it simply switches between 12MHz * and 48MHz. Reimplement with clksel. @@ -1566,15 +1599,13 @@ static struct arm_idlect1_clk lcd_ck_1510 = { */ static struct omap1_clk uart1_1510 = { .name = "uart1_ck", - .ops = &clkops_null, + .ops = &clkops_uart, /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 12000000, .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), .enable_bit = CONF_MOD_UART1_CLK_MODE_R, - .set_rate = &omap1_set_uart_rate, - .recalc = &omap1_uart_recalc, }; /* @@ -1605,15 +1636,13 @@ static struct uart_clk uart1_16xx = { */ static struct omap1_clk uart2_ck = { .name = "uart2_ck", - .ops = &clkops_null, + .ops = &clkops_uart, /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 12000000, .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), .enable_bit = CONF_MOD_UART2_CLK_MODE_R, - .set_rate = &omap1_set_uart_rate, - .recalc = &omap1_uart_recalc, }; /* @@ -1624,15 +1653,13 @@ static struct omap1_clk uart2_ck = { */ static struct omap1_clk uart3_1510 = { .name = "uart3_ck", - .ops = &clkops_null, + .ops = &clkops_uart, /* Direct from ULPD, no real parent */ .parent = &armper_ck.clk, .rate = 12000000, .flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0), .enable_bit = CONF_MOD_UART3_CLK_MODE_R, - .set_rate = &omap1_set_uart_rate, - .recalc = &omap1_uart_recalc, }; /* @@ -1722,15 +1749,20 @@ static struct omap1_clk mclk_1510 = { .enable_bit = SOFT_COM_MCKO_REQ_SHIFT, }; +static const struct clk_ops clkops_ext_clk = { + .enable = omap1_clk_enable_generic, + .disable = omap1_clk_disable_generic, + .set_rate = omap1_set_ext_clk_rate, + .round_rate = omap1_round_ext_clk_rate, + .init = omap1_init_ext_clk, +}; + static struct omap1_clk mclk_16xx = { .name = "mclk", - .ops = &clkops_generic, + .ops = &clkops_ext_clk, /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .enable_reg = OMAP1_IO_ADDRESS(COM_CLK_DIV_CTRL_SEL), .enable_bit = COM_ULPD_PLL_CLK_REQ, - .set_rate = &omap1_set_ext_clk_rate, - .round_rate = &omap1_round_ext_clk_rate, - .init = &omap1_init_ext_clk, }; static struct omap1_clk bclk_1510 = { @@ -1742,13 +1774,10 @@ static struct omap1_clk bclk_1510 = { static struct omap1_clk bclk_16xx = { .name = "bclk", - .ops = &clkops_generic, + .ops = &clkops_ext_clk, /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .enable_reg = OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL), .enable_bit = SWD_ULPD_PLL_CLK_REQ, - .set_rate = &omap1_set_ext_clk_rate, - .round_rate = &omap1_round_ext_clk_rate, - .init = &omap1_init_ext_clk, }; static struct omap1_clk mmc1_ck = { @@ -1788,31 +1817,34 @@ static struct omap1_clk mmc3_ck = { .enable_bit = SOFT_MMC_DPLL_REQ_SHIFT, }; +static const struct clk_ops clkops_mpu = { + .enable = clkll_enable_null, + .disable = clkll_disable_null, + .recalc_rate = followparent_recalc, + .set_rate = omap1_select_table_rate, + .round_rate = omap1_round_to_table_rate, +}; + static struct omap1_clk virtual_ck_mpu = { .name = "mpu", - .ops = &clkops_null, + .ops = &clkops_mpu, .parent = &arm_ck, /* Is smarter alias for */ - .recalc = &followparent_recalc, - .set_rate = &omap1_select_table_rate, - .round_rate = &omap1_round_to_table_rate, }; /* virtual functional clock domain for I2C. Just for making sure that ARMXOR_CK remains active during MPU idle whenever this is enabled */ static struct omap1_clk i2c_fck = { .name = "i2c_fck", - .ops = &clkops_null, + .ops = &clkops_followparent, .flags = CLOCK_NO_IDLE_PARENT, .parent = &armxor_ck.clk, - .recalc = &followparent_recalc, }; static struct omap1_clk i2c_ick = { .name = "i2c_ick", - .ops = &clkops_null, + .ops = &clkops_followparent, .flags = CLOCK_NO_IDLE_PARENT, .parent = &armper_ck.clk, - .recalc = &followparent_recalc, }; /* @@ -2057,7 +2089,7 @@ void __init omap1_clk_late_init(void) unsigned long rate = ck_dpll1.rate; /* Find the highest supported frequency and enable it */ - if (omap1_select_table_rate(&virtual_ck_mpu.clk_hw, ~0)) { + if (omap1_select_table_rate(&virtual_ck_mpu.clk_hw, ~0, 0)) { pr_err("System frequencies not set, using default. Check your config.\n"); /* * Reprogramming the DPLL is tricky, it must be done from SRAM. -- 2.20.0