[PATCH 1/3] clk: composite: Add fixed-rate support
Emilio López
emilio at elopez.com.ar
Tue Apr 9 09:48:02 EDT 2013
This patchset adds fixed-rate support to the composite clock, allowing
us to register gatable oscillators.
Signed-off-by: Emilio López <emilio at elopez.com.ar>
---
drivers/clk/clk-composite.c | 57 ++++++++++++++++++++++++++++++++++++++++----
include/linux/clk-provider.h | 6 +++++
2 files changed, 59 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 097dee4..5416e1d 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -43,8 +43,8 @@ static int clk_composite_set_parent(struct clk_hw *hw, u8 index)
return mux_ops->set_parent(mux_hw, index);
}
-static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
+static unsigned long clk_composite_recalc_rate_div(struct clk_hw *hw,
+ unsigned long parent_rate)
{
struct clk_composite *composite = to_clk_composite(hw);
const struct clk_ops *div_ops = composite->div_ops;
@@ -55,6 +55,18 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
return div_ops->recalc_rate(div_hw, parent_rate);
}
+static unsigned long clk_composite_recalc_rate_fixed(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_composite *composite = to_clk_composite(hw);
+ const struct clk_ops *fixed_ops = composite->fixed_ops;
+ struct clk_hw *fixed_hw = composite->fixed_hw;
+
+ fixed_hw->clk = hw->clk;
+
+ return fixed_ops->recalc_rate(fixed_hw, parent_rate);
+}
+
static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
@@ -112,11 +124,12 @@ static void clk_composite_disable(struct clk_hw *hw)
gate_ops->disable(gate_hw);
}
-struct clk *clk_register_composite(struct device *dev, const char *name,
+static struct clk *_clk_register_composite(struct device *dev, const char *name,
const char **parent_names, int num_parents,
struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
struct clk_hw *div_hw, const struct clk_ops *div_ops,
struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+ struct clk_hw *fixed_hw, const struct clk_ops *fixed_ops,
unsigned long flags)
{
struct clk *clk;
@@ -158,7 +171,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
composite->div_hw = div_hw;
composite->div_ops = div_ops;
- clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
+ clk_composite_ops->recalc_rate = clk_composite_recalc_rate_div;
clk_composite_ops->round_rate = clk_composite_round_rate;
clk_composite_ops->set_rate = clk_composite_set_rate;
}
@@ -177,6 +190,17 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
clk_composite_ops->disable = clk_composite_disable;
}
+ if (fixed_hw && fixed_ops) {
+ if (!fixed_ops->recalc_rate) {
+ clk = ERR_PTR(-EINVAL);
+ goto err;
+ }
+
+ composite->fixed_hw = fixed_hw;
+ composite->fixed_ops = fixed_ops;
+ clk_composite_ops->recalc_rate = clk_composite_recalc_rate_fixed;
+ }
+
init.ops = clk_composite_ops;
composite->hw.init = &init;
@@ -193,9 +217,34 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
if (composite->gate_hw)
composite->gate_hw->clk = clk;
+ if (composite->fixed_hw)
+ composite->fixed_hw->clk = clk;
+
return clk;
err:
kfree(composite);
return clk;
}
+
+struct clk *clk_register_composite(struct device *dev, const char *name,
+ const char **parent_names, int num_parents,
+ struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+ struct clk_hw *div_hw, const struct clk_ops *div_ops,
+ struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+ unsigned long flags)
+{
+ return _clk_register_composite(dev, name, parent_names, num_parents,
+ mux_hw, mux_ops, div_hw, div_ops,
+ gate_hw, gate_ops, NULL, NULL, flags);
+}
+
+struct clk *clk_register_gatable_osc(struct device *dev, const char *name,
+ struct clk_hw *fixed_hw, const struct clk_ops *fixed_ops,
+ struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+ unsigned long flags)
+{
+ return _clk_register_composite(dev, name, NULL, 0, NULL, NULL,
+ NULL, NULL, gate_hw, gate_ops,
+ fixed_hw, fixed_ops, flags);
+}
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 33e7e64..82dd006 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -343,10 +343,12 @@ struct clk_composite {
struct clk_hw *mux_hw;
struct clk_hw *div_hw;
struct clk_hw *gate_hw;
+ struct clk_hw *fixed_hw;
const struct clk_ops *mux_ops;
const struct clk_ops *div_ops;
const struct clk_ops *gate_ops;
+ const struct clk_ops *fixed_ops;
};
struct clk *clk_register_composite(struct device *dev, const char *name,
@@ -356,6 +358,10 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
unsigned long flags);
+struct clk *clk_register_gatable_osc(struct device *dev, const char *name,
+ struct clk_hw *fixed_hw, const struct clk_ops *fixed_ops,
+ struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+ unsigned long flags);
/**
* clk_register - allocate a new clock, register it and return an opaque cookie
* @dev: device that is registering this clock
--
1.8.2.1
More information about the linux-arm-kernel
mailing list