From: Mike Turquette <mturquette@linaro.org>
To: linux-kernel@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org, patches@linaro.org,
linaro-dev@lists.linaro.org,
Mike Turquette <mturquette@linaro.org>
Subject: [PATCH 4/5] HACK: set_parent callback for OMAP4 non-core DPLLs
Date: Wed, 27 Feb 2013 20:49:28 -0800 [thread overview]
Message-ID: <1362026969-11457-5-git-send-email-mturquette@linaro.org> (raw)
In-Reply-To: <1362026969-11457-1-git-send-email-mturquette@linaro.org>
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 <mturquette@linaro.org>
---
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;
}
--
1.7.10.4
next prev parent reply other threads:[~2013-02-28 4:50 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-28 4:49 [PATCH v3 0/5] common clk framework reentrancy & dvfs, take 3 Mike Turquette
2013-02-28 4:49 ` [PATCH 1/5] clk: allow reentrant calls into the clk framework Mike Turquette
2013-02-28 9:54 ` Ulf Hansson
[not found] ` <20130318201551.8663.22731@quantum>
2013-03-18 21:00 ` Russell King - ARM Linux
2013-03-27 3:33 ` Bill Huang
2013-02-28 4:49 ` [PATCH 2/5] clk: notifier handler for dynamic voltage scaling Mike Turquette
2013-03-01 9:41 ` Bill Huang
2013-03-01 20:49 ` Stephen Warren
2013-03-02 2:58 ` Bill Huang
[not found] ` <20130301182234.6210.63879@quantum>
[not found] ` <20130301204832.6210.40653@quantum>
2013-03-02 2:55 ` Bill Huang
2013-03-02 8:22 ` Richard Zhao
2013-03-03 10:54 ` Mike Turquette
2013-03-03 13:27 ` Richard Zhao
[not found] ` <20130304072519.6210.97088@quantum>
2013-03-13 13:59 ` Ulf Hansson
2013-03-10 10:21 ` Francesco Lavra
2013-04-02 17:49 ` Taras Kondratiuk
2013-02-28 4:49 ` [PATCH 3/5] cpufreq: omap: scale regulator from clk notifier Mike Turquette
2013-02-28 4:49 ` Mike Turquette [this message]
2013-02-28 4:49 ` [PATCH 5/5] HACK: omap: opp: add fake 400MHz OPP to bypass MPU Mike Turquette
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1362026969-11457-5-git-send-email-mturquette@linaro.org \
--to=mturquette@linaro.org \
--cc=linaro-dev@lists.linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=patches@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).