From patchwork Tue Mar 22 01:22:15 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ladislav Michl X-Patchwork-Id: 8636861 Return-Path: X-Original-To: patchwork-linux-omap@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 752519F3D1 for ; Tue, 22 Mar 2016 01:22:23 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 106C22034B for ; Tue, 22 Mar 2016 01:22:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9F48B20306 for ; Tue, 22 Mar 2016 01:22:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756194AbcCVBWT (ORCPT ); Mon, 21 Mar 2016 21:22:19 -0400 Received: from eddie.linux-mips.org ([148.251.95.138]:52748 "EHLO cvs.linux-mips.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755946AbcCVBWS (ORCPT ); Mon, 21 Mar 2016 21:22:18 -0400 Received: (from localhost user: 'ladis' uid#1021 fake: STDIN (ladis@eddie.linux-mips.org)) by eddie.linux-mips.org id S27014029AbcCVBWQ3PN4H (ORCPT ); Tue, 22 Mar 2016 02:22:16 +0100 Date: Tue, 22 Mar 2016 02:22:15 +0100 From: Ladislav Michl To: Tony Lindgren Cc: Richard Watts , Tero Kristo , Robert Nelson , "linux-omap@vger.kernel.org" , Paul Walmsley Subject: Re: DM3730 sprz319 erratum 2.1 Message-ID: <20160322012215.GA6963@localhost.localdomain> References: <56E7BA0F.6000100@ti.com> <56E7C6E2.3010509@kynesim.co.uk> <20160316004058.GA4207@localhost.localdomain> <56E8FCB2.5010501@ti.com> <20160316143344.GJ9329@atomide.com> <56E96FAE.3060607@ti.com> <20160316144216.GK9329@atomide.com> <56E9943A.2060302@kynesim.co.uk> <20160317144238.GN9329@atomide.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20160317144238.GN9329@atomide.com> User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On Thu, Mar 17, 2016 at 07:42:38AM -0700, Tony Lindgren wrote: > * Richard Watts [160316 10:14]: > > However, there are several possible options for a workaround if you are > > using a 13MHz or 26MHz xtal - see > > PDF p111. It might perhaps > > be civilised to give the user the option, since which is appropriate to your > > board is a matter of board characterisation. > > Seems like we should just configure dpll5 based on the SYS_CLK rate > automatically. Something like patch v0 bellow. However note, that rate is determined using determine_rate, therefore omap3630_noncore_dpll_determine_rate which is just a copy of omap2_noncore_dpll_determine_rate is calling omap3630_dpll_round_rate - shame, shall we use function pointer determine_rate? Neither is nice and elegant. Also we somehow need to know soc_is_omap3630() and bringing is to drivers/clk does not seem as an option. Also note, that there's no choice between options for 26MHz. Hints? > > I see no shame in simply exposing something like: > > > > ti,omap3-dpll5-clock = < 443 5 8 > > > If we want a binding like that it should be Linux generic and disucced > on the linux-clk list. It's usually best to stick to standard > bindings and hide the quirks in the driver(s). It seem at most we just > need to specify the 36xx related compatible flag for dpll5. > > > I have a Beagle xM or two here I can send out to anyone in need - throw me an > > address. > > Cool, I think also Tomi Valkeinen was looking for a 36xx test board > for occasional DSS testing. I have a beagle xm on loan here so I'm > all set for now. I'm considering this errata runtime tested enough, for now it would be nice to have patch ready and verify that dd->mult_div1_reg contains the right value ;-) > > OMAP3530 should also suffer from this problem, but it is not listed in the > > errata sheet. > > > > Other than that, the only devices I know of that have this combination of > > DPLL and HSUSB are OMAP3630 and DM3730 - if it's important, I can try and > > find the appropriate people in TI? > > AFAIK 3630 and dm3730 are exactly the same. The dm3730 is just the > catalog part GP version. Ok, let's prefix errata functions omap3630_ then. Regards, ladis --- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html --- drivers/clk/ti/dpll.c.orig 2016-03-21 22:53:16.379746383 +0100 +++ drivers/clk/ti/dpll.c 2016-03-22 01:48:36.988896607 +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, @@ -448,6 +460,7 @@ #ifdef CONFIG_ARCH_OMAP3 static void __init of_ti_omap3_dpll_setup(struct device_node *node) { + const struct clk_ops *ops = &omap3_dpll_ck_ops; const struct dpll_data dd = { .idlest_mask = 0x1, .enable_mask = 0x7, @@ -461,7 +474,10 @@ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), }; - of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd); + if (/* soc_is_omap3630() && */ strcmp(node->name, "dpll5_ck") == 0) + ops = &omap3630_dpll_ck_ops; + + of_ti_dpll_setup(node, ops, &dd); } CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock", of_ti_omap3_dpll_setup); --- 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); --- drivers/clk/ti/clkt_dpll.c.orig 2016-03-22 01:59:21.724896607 +0100 +++ drivers/clk/ti/clkt_dpll.c 2016-03-22 01:53:41.072896607 +0100 @@ -368,3 +368,46 @@ 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, table 36 implementation + */ +long omap3630_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, + unsigned long *parent_rate) +{ + unsigned long rate; + struct dpll_data *dd; + struct clk_hw_omap *clk = to_clk_hw_omap(hw); + + if (!clk || !clk->dpll_data) + return ~0; + + dd = clk->dpll_data; + rate = target_rate == 120000000 ? *parent_rate : 0; + + switch (rate) { + case 13000000: + dd->last_rounded_m = 443; + dd->last_rounded_n = 5; + break; + case 26000000: + dd->last_rounded_m = 443; + dd->last_rounded_n = 11; + break; + default: + return omap2_dpll_round_rate(hw, target_rate, parent_rate); + } + /* actual divide value, value of the register is n - 1 */ + dd->last_rounded_n++; + dd->last_rounded_rate = rate * dd->last_rounded_m / dd->last_rounded_n; + + pr_debug("clock: %s: fixed m = %d, n = %d, new_rate = %lu\n", + clk_hw_get_name(hw), dd->last_rounded_m, dd->last_rounded_n, + dd->last_rounded_rate); + + return dd->last_rounded_rate; +} --- 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