Thread (1 message) 1 message, 1 author, 2012-05-04
DORMANTno replies

[PATCH] clk: give clock chance to change parent at setrate stage

From: Lei Wen <hidden>
Date: 2012-05-04 15:55:38

Hi Raul,

On Fri, May 4, 2012 at 6:34 PM, Raul Xiong [off-list ref] wrote:

2012/5/4 Lei Wen [off-list ref]
quoted
There is one clock rate changing requirement like those:
1. clock may need specify specific rate binded with specific parent
2. driver care only set_rate, don't care for which parent it is linked
3. It need registering notification to changing voltage
4. It want keep parent and rate changing in an atomic operation, which
? means for chaning parent, it only caching the mux chaning, and
? maintent the relationship in this tree, while do the real parent
? and rate chaning in the set_rate callback. And it requires
? recalculated rate reflect the true rate changing state to make the
? decision to whether sending notification (for voltage change).

Base on those assumption, the logic in set_rate is changed a little, the
round_rate should return not only best parent_rate, but also best
parent. If best parent is changed, we would switch parent first, then do
the sub rate chaning.

Signed-off-by: Lei Wen <redacted>
---
?drivers/clk/clk.c ? ? ? ? ? ?| ? 22 +++++++++++++++++++++-
?include/linux/clk-provider.h | ? ?2 ++
?2 files changed, 23 insertions(+), 1 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 9cf6f59..d207617 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -23,6 +23,7 @@ static DEFINE_MUTEX(prepare_lock);
?static HLIST_HEAD(clk_root_list);
?static HLIST_HEAD(clk_orphan_list);
?static LIST_HEAD(clk_notifier_list);
+static int __clk_set_parent(struct clk *clk, struct clk *parent);

?/*** ? ? ? ?debugfs support ? ? ? ?***/
@@ -767,6 +768,7 @@ static struct clk *clk_calc_new_rates(struct clk
*clk, unsigned long rate)
? ? ? ?struct clk *top = clk;
? ? ? ?unsigned long best_parent_rate = clk->parent->rate;
? ? ? ?unsigned long new_rate;
+ ? ? ? int ret;

? ? ? ?if (!clk->ops->round_rate && !(clk->flags & CLK_SET_RATE_PARENT)) {
? ? ? ? ? ? ? ?clk->new_rate = clk->rate;
@@ -785,6 +787,21 @@ static struct clk *clk_calc_new_rates(struct clk
*clk, unsigned long rate)
? ? ? ?else
? ? ? ? ? ? ? ?new_rate = clk->ops->round_rate(clk->hw, rate, NULL);

+ ? ? ? if (clk->hw->new_parent != clk->parent) {

Acked-by: Raul Xiong <redacted>

Suggest to change it as
+ ? ? ??if (clk->hw->new_parent != NULL &&?clk->hw->new_parent !=
clk->parent) {
to allow round_rate callback leave it as NULL.
Thanks for pointing out! I would post V2 patch to fix it.
quoted
+ ? ? ? ? ? ? ? if ((clk->flags & CLK_SET_PARENT_GATE) &&
clk->prepare_count)

+ ? ? ? ? ? ? ? ? ? ? ? ret = -EBUSY;
+ ? ? ? ? ? ? ? else
+ ? ? ? ? ? ? ? ? ? ? ? ret = __clk_set_parent(clk, clk->hw->new_parent);
+
+ ? ? ? ? ? ? ? if (ret) {
+ ? ? ? ? ? ? ? ? ? ? ? pr_debug("%s: %s set parent to %s failed\n",
__func__,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clk->name,
clk->hw->new_parent->name);
+ ? ? ? ? ? ? ? ? ? ? ? return NULL;
+ ? ? ? ? ? ? ? }
+
+ ? ? ? ? ? ? ? __clk_reparent(clk, clk->hw->new_parent);
+ ? ? ? }
+
? ? ? ?if (best_parent_rate != clk->parent->rate) {
? ? ? ? ? ? ? ?top = clk_calc_new_rates(clk->parent, best_parent_rate);
@@ -1050,7 +1067,10 @@ out:
? ? ? ?clk->parent = new_parent;

- ? ? ? __clk_recalc_rates(clk, POST_RATE_CHANGE);
+ ? ? ? if (!clk->hw->new_parent)
+ ? ? ? ? ? ? ? __clk_recalc_rates(clk, POST_RATE_CHANGE);
+ ? ? ? else
+ ? ? ? ? ? ? ? clk->hw->new_parent = NULL;
?}

?static int __clk_set_parent(struct clk *clk, struct clk *parent)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 5508897..54dad8a 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -23,9 +23,11 @@
?*
?* clk: pointer to the struct clk instance that points back to this struct
?* clk_hw instance
+ * new_parent: pointer for caching new parent position
?*/
?struct clk_hw {
? ? ? ?struct clk *clk;
+ ? ? ? struct clk *new_parent;
?};

?/*
--
1.7.5.4

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Thanks,
Lei
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help