From patchwork Thu Feb 28 04:49:28 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Turquette X-Patchwork-Id: 15130 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id A563123E24 for ; Thu, 28 Feb 2013 04:50:31 +0000 (UTC) Received: from mail-ve0-f179.google.com (mail-ve0-f179.google.com [209.85.128.179]) by fiordland.canonical.com (Postfix) with ESMTP id 45509A18B1D for ; Thu, 28 Feb 2013 04:50:31 +0000 (UTC) Received: by mail-ve0-f179.google.com with SMTP id da11so1403293veb.10 for ; Wed, 27 Feb 2013 20:50:30 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:x-received:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references:x-gm-message-state; bh=XQnZTN7E6dvFpOx6ODRT0zVM7Db9bPHnWW7ZBxy/s4c=; b=irZOonEDAG63xYEbFCRQcmm2HUHEwHjO+9U2ux6iKAyD1uHpBO0vButV++9WmyuVEx WFuD3TSFZnHIPL3EG3pmM0U1cdXg7ZRqeW4IEQXqy7EyKA2Y8efaER2CbaJldIDDEpga hy4TI6GSFC4jcTohV9tbDhhFPZzPXVT9X2zCMZ4GBE12hnU7wzdn89sTeI9TT959hVf1 FSZP6d7L/Ks7w3RsGOzrpmNWQAi1i+jXG3hGbWOVMJhWmX8lAQFlaMu9vqlgzL0rWxfv QRsJZbnuNCY0jdNT5EzVm4alx6+eEN3lKX80SzpWrZtYOpv/4Oef4jIPHPlnjb+6OFNY tzfA== X-Received: by 10.220.214.6 with SMTP id gy6mr1952888vcb.8.1362027030744; Wed, 27 Feb 2013 20:50:30 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.58.145.101 with SMTP id st5csp206253veb; Wed, 27 Feb 2013 20:50:30 -0800 (PST) X-Received: by 10.68.255.161 with SMTP id ar1mr7204497pbd.17.1362027029942; Wed, 27 Feb 2013 20:50:29 -0800 (PST) Received: from mail-pb0-f53.google.com (mail-pb0-f53.google.com [209.85.160.53]) by mx.google.com with ESMTPS id xm3si1673202pbc.46.2013.02.27.20.50.29 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 27 Feb 2013 20:50:29 -0800 (PST) Received-SPF: neutral (google.com: 209.85.160.53 is neither permitted nor denied by best guess record for domain of mturquette@linaro.org) client-ip=209.85.160.53; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.160.53 is neither permitted nor denied by best guess record for domain of mturquette@linaro.org) smtp.mail=mturquette@linaro.org Received: by mail-pb0-f53.google.com with SMTP id un1so830446pbc.12 for ; Wed, 27 Feb 2013 20:50:29 -0800 (PST) X-Received: by 10.68.219.133 with SMTP id po5mr7277210pbc.36.1362027029569; Wed, 27 Feb 2013 20:50:29 -0800 (PST) Received: from quantum.gateway.2wire.net (adsl-69-228-86-207.dsl.pltn13.pacbell.net. [69.228.86.207]) by mx.google.com with ESMTPS id y9sm7799811paw.1.2013.02.27.20.50.26 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 27 Feb 2013 20:50:28 -0800 (PST) From: Mike Turquette To: linux-kernel@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, patches@linaro.org, linaro-dev@lists.linaro.org, Mike Turquette Subject: [PATCH 4/5] HACK: set_parent callback for OMAP4 non-core DPLLs Date: Wed, 27 Feb 2013 20:49:28 -0800 Message-Id: <1362026969-11457-5-git-send-email-mturquette@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1362026969-11457-1-git-send-email-mturquette@linaro.org> References: <1362026969-11457-1-git-send-email-mturquette@linaro.org> X-Gm-Message-State: ALoCoQnWmTfbrRnOz2r6ZRaprR8bTIQAzUUyrWQ3L5UHzubmP4djmP+WB5bBXeEvv30W7L/ojDQk This is a silly patch that demonstrates calling clk_set_parent from within a .set_rate callback, which itself was called by clk_set_rate. It may make your board burst into flames or otherwise void various warrantees. I do not suggest that the OMAP folks take this approach in unless they really want to. Instead it was a way for me to increase code coverage while testing the reentrancy changes to the core clock framework. Changes in this patch include removing __clk_prepare and __clk_unprepare from omap3_noncore_dpll_set_rate and using the (now reentrant) clk_prepare & clk_unprepare versions. Most importantly this patch introduces omap3_noncore_dpll_set_parent and adds it to the clk_ops for all OMAP3+ DPLLs. The net gain is that on OMAP4 platforms it is now possible to call clk_set_parent(some_dpll_ck, ...) in order to change the PLL input from the reference clock to the bypass clock, and vice versa. omap3_noncore_dpll_set_rate is modified to call clk_set_parent when appropriate as a way to test reentrancy. Not-signed-off-by: Mike Turquette --- arch/arm/mach-omap2/cclock44xx_data.c | 1 + arch/arm/mach-omap2/clock.h | 1 + arch/arm/mach-omap2/dpll3xxx.c | 107 +++++++++++++++++++++++++-------- 3 files changed, 84 insertions(+), 25 deletions(-) diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c index 5789a5e..df5da7f 100644 --- a/arch/arm/mach-omap2/cclock44xx_data.c +++ b/arch/arm/mach-omap2/cclock44xx_data.c @@ -386,6 +386,7 @@ static const struct clk_ops dpll_ck_ops = { .round_rate = &omap2_dpll_round_rate, .set_rate = &omap3_noncore_dpll_set_rate, .get_parent = &omap2_init_dpll_parent, + .set_parent = &omap3_noncore_dpll_set_parent, }; static struct clk_hw_omap dpll_iva_ck_hw = { diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index b402048..1cf43a5 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -367,6 +367,7 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate); int omap3_noncore_dpll_enable(struct clk_hw *hw); void omap3_noncore_dpll_disable(struct clk_hw *hw); +int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index); int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate); u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk); diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index 0a02aab5..bae123e 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c @@ -450,6 +450,76 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw) clkdm_clk_disable(clk->clkdm, hw->clk); } +/* Non-CORE DPLL set parent code */ + +/** + * omap3_noncore_dpll_set_parent - set non-core DPLL input + * @hw: hardware object for this clock/dpll + * @index: parent to switch to in the array of possible parents + * + * Sets the input to the DPLL to either the reference clock or bypass + * clock. Returns error code upon failure or 0 upon success. + */ +int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_hw_omap *clk = to_clk_hw_omap(hw); + u16 freqsel = 0; + struct dpll_data *dd; + int ret; + + if (!hw) + return -EINVAL; + + dd = clk->dpll_data; + if (!dd) + return -EINVAL; + + clk_prepare(dd->clk_bypass); + clk_enable(dd->clk_bypass); + clk_prepare(dd->clk_ref); + clk_enable(dd->clk_ref); + + /* FIXME hard coded magic numbers are gross */ + switch (index) { + /* dpll input is the reference clock */ + case 0: + if (dd->last_rounded_rate == 0) + return -EINVAL; + + /* No freqsel on OMAP4 and OMAP3630 */ + if (!cpu_is_omap44xx() && !cpu_is_omap3630()) { + freqsel = _omap3_dpll_compute_freqsel(clk, + dd->last_rounded_n); + WARN_ON(!freqsel); + } + + pr_debug("%s: %s: set rate: locking rate to %lu.\n", + __func__, __clk_get_name(hw->clk), dd->last_rounded_rate); + + ret = omap3_noncore_dpll_program(clk, freqsel); + break; + + /* dpll input is the bypass clock */ + case 1: + pr_debug("%s: %s: set rate: entering bypass.\n", + __func__, __clk_get_name(hw->clk)); + + ret = _omap3_noncore_dpll_bypass(clk); + break; + + default: + pr_warn("%s: %s: set parent: invalid parent\n", + __func__, __clk_get_name(hw->clk)); + return -EINVAL; + } + + clk_disable(dd->clk_ref); + clk_unprepare(dd->clk_ref); + clk_disable(dd->clk_bypass); + clk_unprepare(dd->clk_bypass); + + return 0; +} /* Non-CORE DPLL rate set code */ @@ -468,7 +538,6 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_hw_omap *clk = to_clk_hw_omap(hw); - struct clk *new_parent = NULL; u16 freqsel = 0; struct dpll_data *dd; int ret; @@ -480,22 +549,18 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, if (!dd) return -EINVAL; - __clk_prepare(dd->clk_bypass); + clk_prepare(dd->clk_bypass); clk_enable(dd->clk_bypass); - __clk_prepare(dd->clk_ref); + clk_prepare(dd->clk_ref); clk_enable(dd->clk_ref); - if (__clk_get_rate(dd->clk_bypass) == rate && + /* FIXME below block should call clk_set_parent */ + if (clk_get_rate(dd->clk_bypass) == rate && (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) { - pr_debug("%s: %s: set rate: entering bypass.\n", - __func__, __clk_get_name(hw->clk)); - - ret = _omap3_noncore_dpll_bypass(clk); - if (!ret) - new_parent = dd->clk_bypass; + clk_set_parent(hw->clk, dd->clk_bypass); } else { if (dd->last_rounded_rate != rate) - rate = __clk_round_rate(hw->clk, rate); + rate = clk_round_rate(hw->clk, rate); if (dd->last_rounded_rate == 0) return -EINVAL; @@ -510,24 +575,16 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, pr_debug("%s: %s: set rate: locking rate to %lu.\n", __func__, __clk_get_name(hw->clk), rate); - ret = omap3_noncore_dpll_program(clk, freqsel); - if (!ret) - new_parent = dd->clk_ref; + if (clk_get_parent(hw->clk) == dd->clk_bypass) + clk_set_parent(hw->clk, dd->clk_ref); + else + ret = omap3_noncore_dpll_program(clk, freqsel); } - /* - * FIXME - this is all wrong. common code handles reparenting and - * migrating prepare/enable counts. dplls should be a multiplexer - * clock and this should be a set_parent operation so that all of that - * stuff is inherited for free - */ - - if (!ret) - __clk_reparent(hw->clk, new_parent); clk_disable(dd->clk_ref); - __clk_unprepare(dd->clk_ref); + clk_unprepare(dd->clk_ref); clk_disable(dd->clk_bypass); - __clk_unprepare(dd->clk_bypass); + clk_unprepare(dd->clk_bypass); return 0; }