[PATCH] clk: Add is_enabled callback
Sascha Hauer
s.hauer at pengutronix.de
Fri Mar 15 04:54:01 EDT 2013
This allows us to better detect whether a clk is enabled or not.
- If we can ask a clk, ask it. If it's enabled, go on and ask parents
- If we can't ask it, but it can be enabled, depend on the enable_count.
if it's positive, go on and ask parents
- If we can't ask it and it cannot be enabled, assume it is enabled
and ask parents.
This makes the CLK_ALWAYS_ENABLED unnecessary, since the fixed clk now
always returns 1 in its is_enabled callback.
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
drivers/clk/clk-fixed.c | 2 +-
drivers/clk/clk-gate.c | 14 ++++++++++++
drivers/clk/clk.c | 61 +++++++++++++++++++++++++++++++++++++------------
include/linux/clk.h | 4 ++--
4 files changed, 63 insertions(+), 18 deletions(-)
diff --git a/drivers/clk/clk-fixed.c b/drivers/clk/clk-fixed.c
index 5e81e72..e5d36b4 100644
--- a/drivers/clk/clk-fixed.c
+++ b/drivers/clk/clk-fixed.c
@@ -34,6 +34,7 @@ static unsigned long clk_fixed_recalc_rate(struct clk *clk,
struct clk_ops clk_fixed_ops = {
.recalc_rate = clk_fixed_recalc_rate,
+ .is_enabled = clk_is_enabled_always,
};
struct clk *clk_fixed(const char *name, int rate)
@@ -44,7 +45,6 @@ struct clk *clk_fixed(const char *name, int rate)
fix->rate = rate;
fix->clk.ops = &clk_fixed_ops;
fix->clk.name = name;
- fix->clk.flags = CLK_ALWAYS_ENABLED;
ret = clk_register(&fix->clk);
if (ret) {
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index cf1bb1a..a455094 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -49,9 +49,23 @@ static void clk_gate_disable(struct clk *clk)
writel(val, g->reg);
}
+static int clk_gate_is_enabled(struct clk *clk)
+{
+ struct clk_gate *g = container_of(clk, struct clk_gate, clk);
+ u32 val;
+
+ val = readl(g->reg);
+
+ if (val & (1 << g->shift))
+ return 1;
+ else
+ return 0;
+}
+
struct clk_ops clk_gate_ops = {
.enable = clk_gate_enable,
.disable = clk_gate_disable,
+ .is_enabled = clk_gate_is_enabled,
};
struct clk *clk_gate(const char *name, const char *parent, void __iomem *reg,
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index cb94755..690a0c6 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -46,9 +46,6 @@ int clk_enable(struct clk *clk)
if (IS_ERR(clk))
return PTR_ERR(clk);
- if (clk->flags & CLK_ALWAYS_ENABLED)
- return 0;
-
if (!clk->enable_count) {
ret = clk_parent_enable(clk);
if (ret)
@@ -73,9 +70,6 @@ void clk_disable(struct clk *clk)
if (IS_ERR(clk))
return;
- if (clk->flags & CLK_ALWAYS_ENABLED)
- return;
-
if (!clk->enable_count)
return;
@@ -211,23 +205,60 @@ int clk_register(struct clk *clk)
list_add_tail(&clk->list, &clks);
- if (clk->flags & CLK_ALWAYS_ENABLED) {
- clk->enable_count = 1;
+ return 0;
+}
+
+int clk_is_enabled(struct clk *clk)
+{
+ int enabled;
+
+ if (IS_ERR(clk))
+ return 0;
+
+ if (clk->ops->is_enabled) {
+ /*
+ * If we can ask a clk, do it
+ */
+ enabled = clk->ops->is_enabled(clk);
+ } else {
+ if (clk->ops->enable) {
+ /*
+ * If we can't ask a clk, but it can be enabled,
+ * depend on the enable_count.
+ */
+ enabled = clk->enable_count;
+ } else {
+ /*
+ * We can't ask a clk, it has no enable op,
+ * so assume it's enabled and go on and ask
+ * the parent.
+ */
+ enabled = 1;
+ }
}
- return 0;
+ if (!enabled)
+ return 0;
+
+ clk = clk_get_parent(clk);
+
+ if (IS_ERR(clk))
+ return 1;
+
+ return clk_is_enabled(clk);
+}
+
+int clk_is_enabled_always(struct clk *clk)
+{
+ return 1;
}
static void dump_one(struct clk *clk, int verbose, int indent)
{
struct clk *c;
- char *always = "";
-
- if (clk->flags & CLK_ALWAYS_ENABLED)
- always = "always ";
- printf("%*s%s (rate %ld, %s%sabled)\n", indent * 4, "", clk->name, clk_get_rate(clk),
- always, clk->enable_count ? "en" : "dis");
+ printf("%*s%s (rate %ld, %sabled)\n", indent * 4, "", clk->name, clk_get_rate(clk),
+ clk_is_enabled(clk) ? "en" : "dis");
if (verbose) {
if (clk->num_parents > 1) {
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 4389cf8..37a4813 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -182,8 +182,6 @@ struct clk {
unsigned long flags;
};
-#define CLK_ALWAYS_ENABLED (1 << 0)
-
struct clk_div_table {
unsigned int val;
unsigned int div;
@@ -202,6 +200,8 @@ struct clk *clk_mux(const char *name, void __iomem *reg,
struct clk *clk_gate(const char *name, const char *parent, void __iomem *reg,
u8 shift);
+int clk_is_enabled_always(struct clk *clk);
+
int clk_register(struct clk *clk);
struct clk *clk_lookup(const char *name);
--
1.8.2.rc2
More information about the barebox
mailing list