On 26/04/16 19:19, Tony Lindgren wrote:
Tero, * Ladislav Michl <ladis@xxxxxxxxxxxxxx> [160322 08:34]:On Tue, Mar 22, 2016 at 08:57:13AM +0200, Tero Kristo wrote:You can drop the checks against 120MHz inside round_rate then.What if omap3630_dpll_round_rate is called directly as ops->round_rate()?What's the status of this fix? Would be good to have this out of the way.
Sorry I think this got buried in my inbox...Yea I think the last inline patch looks reasonably good to me. Added a couple of comments below, but once those are fixed (+ any checkpatch issues), it should be good to go. I haven't tested the patch itself though as I don't have local access to omap36xx hw.
Regards, Tony--- drivers/clk/ti/dpll3xxx.c.orig 2016-03-21 22:55:29.515746383 +0100 +++ drivers/clk/ti/dpll3xxx.c 2016-03-22 01:43:54.004896607 +0100 @@ -534,6 +534,33 @@ return 0; } +int omap3630_noncore_dpll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_hw_omap *clk = to_clk_hw_omap(hw); + struct dpll_data *dd; + + if (!req->rate) + return -EINVAL; + + dd = clk->dpll_data; + if (!dd) + return -EINVAL; + + if (clk_get_rate(dd->clk_bypass) == req->rate && + (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) { + req->best_parent_hw = __clk_get_hw(dd->clk_bypass); + } else { + req->rate = omap3630_dpll_round_rate(hw, req->rate, + &req->best_parent_rate); + req->best_parent_hw = __clk_get_hw(dd->clk_ref); + } + + req->best_parent_rate = req->rate; + + return 0; +} + /** * omap3_noncore_dpll_set_parent - set parent for a DPLL clock * @hw: pointer to the clock to set parent for --- drivers/clk/ti/clkt_dpll.c.orig 2016-03-22 01:59:21.724896607 +0100 +++ drivers/clk/ti/clkt_dpll.c 2016-03-22 16:23:22.804383248 +0100 @@ -368,3 +368,52 @@ return dd->last_rounded_rate; } + +/** + * omap3630_dpll_round_rate - round a target rate for an OMAP DPLL + * @clk: struct clk * for a DPLL + * @target_rate: desired DPLL clock rate + * + * DM3730 errata (sprz319e), advisory 2.1 + */ +long omap3630_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, + unsigned long *parent_rate) +{ + unsigned int i, m, n; + unsigned long r; + struct dpll_data *dd; + + static const struct { + unsigned long rate; + unsigned int m; + unsigned int n; /* value of the register is n - 1 */ + } dpll5_advisory[] = { + { 12000000, 80, 0 + 1, }, + { 19200000, 50, 0 + 1, }, + { 38400000, 25, 0 + 1, }, + { 13000000, 443, 5 + 1, }, + { 26000000, 443, 11 + 1, }, + { 26000000, 480, 12 + 1, }, + };
I would avoid local/mixed definition like this.
+ + if (target_rate == 120000000) + for (i = 0; i < ARRAY_SIZE(dpll5_advisory); i++) + if (*parent_rate == dpll5_advisory[i].rate) { + m = dpll5_advisory[i].m; + n = dpll5_advisory[i].n; + r = _dpll_compute_new_rate(*parent_rate, m, n); + r /= 8; + + printk("clock %s: m=%d, n=%d, rate=%lu\n", + clk_hw_get_name(hw), m, n, r);
Debugging info should be dropped. Thanks, Tero.
+ + dd = to_clk_hw_omap(hw)->dpll_data; + dd->last_rounded_m = m; + dd->last_rounded_n = n; + dd->last_rounded_rate = r; + + return r; + } + + return omap2_dpll_round_rate(hw, target_rate, parent_rate); +} --- drivers/clk/ti/dpll.c.orig 2016-03-21 22:53:16.379746383 +0100 +++ drivers/clk/ti/dpll.c 2016-03-22 16:27:08.284383248 +0100 @@ -114,6 +114,18 @@ .round_rate = &omap2_dpll_round_rate, }; +static const struct clk_ops omap3630_dpll_ck_ops = { + .enable = &omap3_noncore_dpll_enable, + .disable = &omap3_noncore_dpll_disable, + .get_parent = &omap2_init_dpll_parent, + .recalc_rate = &omap3_dpll_recalc, + .set_rate = &omap3_noncore_dpll_set_rate, + .set_parent = &omap3_noncore_dpll_set_parent, + .set_rate_and_parent = &omap3_noncore_dpll_set_rate_and_parent, + .determine_rate = &omap3630_noncore_dpll_determine_rate, + .round_rate = &omap3630_dpll_round_rate, +}; + static const struct clk_ops omap3_dpll_per_ck_ops = { .enable = &omap3_noncore_dpll_enable, .disable = &omap3_noncore_dpll_disable, @@ -466,6 +478,26 @@ CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock", of_ti_omap3_dpll_setup); +static void __init of_ti_omap3630_dpll5_setup(struct device_node *node) +{ + const struct dpll_data dd = { + .idlest_mask = 0x1, + .enable_mask = 0x7, + .autoidle_mask = 0x7, + .mult_mask = 0x7ff << 8, + .div1_mask = 0x7f, + .max_multiplier = 2047, + .max_divider = 128, + .min_divider = 1, + .freqsel_mask = 0xf0, + .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), + }; + + of_ti_dpll_setup(node, &omap3630_dpll_ck_ops, &dd); +} +CLK_OF_DECLARE(ti_omap3630_dpll5_clock, "ti,omap3630-dpll5-clock", + of_ti_omap3630_dpll5_setup); + static void __init of_ti_omap3_core_dpll_setup(struct device_node *node) { const struct dpll_data dd = { --- drivers/clk/ti/clock.h.orig 2016-03-21 22:55:09.011746383 +0100 +++ drivers/clk/ti/clock.h 2016-03-22 01:42:45.840896607 +0100 @@ -252,8 +252,12 @@ u8 index); int omap3_noncore_dpll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req); +int omap3630_noncore_dpll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req); long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, unsigned long *parent_rate); +long omap3630_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, + unsigned long *parent_rate); unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, unsigned long parent_rate);
-- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html