linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1] clk: qcom: Add support for regmap clock dividers
@ 2014-09-30 17:20 Georgi Djakov
  2014-10-02 18:11 ` Stephen Boyd
  0 siblings, 1 reply; 6+ messages in thread
From: Georgi Djakov @ 2014-09-30 17:20 UTC (permalink / raw)
  To: sboyd; +Cc: mturquette, linux-kernel, linux-arm-msm, Georgi Djakov

This patch expands the regmap support to allow registration of clock
dividers. It just prepares for the introduction of a clkdiv driver,
that will be in a separate patch.
Such dividers are found in the Qualcomm PMIC chips such as PM8941,
PMA8084 and others.

Signed-off-by: Georgi Djakov <gdjakov@mm-sol.com>
---
 drivers/clk/qcom/clk-regmap.c |   68 +++++++++++++++++++++++++++++++++++++++++
 drivers/clk/qcom/clk-regmap.h |   24 +++++++++++++++
 2 files changed, 92 insertions(+)

diff --git a/drivers/clk/qcom/clk-regmap.c b/drivers/clk/qcom/clk-regmap.c
index a58ba39..d63b8ca 100644
--- a/drivers/clk/qcom/clk-regmap.c
+++ b/drivers/clk/qcom/clk-regmap.c
@@ -112,3 +112,71 @@ struct clk *devm_clk_register_regmap(struct device *dev,
 	return devm_clk_register(dev, &rclk->hw);
 }
 EXPORT_SYMBOL_GPL(devm_clk_register_regmap);
+
+/**
+ * clkdiv_recalc_rate_regmap - Calculate clock divider output rate
+ */
+unsigned long clkdiv_recalc_rate_regmap(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct clk_regmap *rclk = to_clk_regmap(hw);
+	struct clkdiv_regmap *clkdiv = to_clkdiv_regmap(rclk);
+	unsigned int div, val;
+
+	regmap_read(rclk->regmap, clkdiv->reg, &val);
+	if (!val)
+		return parent_rate;
+
+	div = (val >> clkdiv->shift) & ((1 << clkdiv->width)-1);
+
+	return parent_rate / div;
+}
+EXPORT_SYMBOL_GPL(clkdiv_recalc_rate_regmap);
+
+static const struct clk_ops clkdiv_ops = {
+	.enable = clk_enable_regmap,
+	.disable = clk_disable_regmap,
+	.is_enabled = clk_is_enabled_regmap,
+	.recalc_rate = clkdiv_recalc_rate_regmap,
+};
+EXPORT_SYMBOL_GPL(clkdiv_ops);
+
+/**
+ * devm_clkdiv_register_regmap - register a clk_regmap clock divider
+ *
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @clkdiv: clock divider to operate on
+ *
+ * Clocks that use regmap for their register I/O should register their
+ * clk_regmap struct via this function so that the regmap is initialized
+ * and so that the clock is registered with the common clock framework.
+ */
+struct clk *devm_clkdiv_register_regmap(struct device *dev, const char *name,
+					const char *parent_name,
+					unsigned long flags,
+					struct clkdiv_regmap *clkdiv)
+{
+	struct clk_init_data init;
+
+	if (!clkdiv)
+		return ERR_PTR(-ENODEV);
+
+	clkdiv->rclk.regmap = dev_get_regmap(dev->parent, NULL);
+
+	if (!clkdiv->rclk.regmap)
+		return ERR_PTR(-ENXIO);
+
+	init.name = name;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+	init.flags = flags;
+	init.ops = &clkdiv_ops;
+
+	clkdiv->rclk.hw.init = &init;
+
+	return devm_clk_register(dev, &clkdiv->rclk.hw);
+}
+EXPORT_SYMBOL_GPL(devm_clkdiv_register_regmap);
diff --git a/drivers/clk/qcom/clk-regmap.h b/drivers/clk/qcom/clk-regmap.h
index 491a63d..02582cf 100644
--- a/drivers/clk/qcom/clk-regmap.h
+++ b/drivers/clk/qcom/clk-regmap.h
@@ -42,4 +42,28 @@ void clk_disable_regmap(struct clk_hw *hw);
 struct clk *
 devm_clk_register_regmap(struct device *dev, struct clk_regmap *rclk);
 
+/**
+ * struct clkdiv_regmap - regmap supporting clock divider
+ * @rclk:   regmap supporting clock struct
+ * @reg:    offset into regmap for the control register
+ * @shift:  bit position for divider value
+ * @width:  number of bits used for divider value
+ * @table:  pointer to table containing an array of divider/value pairs
+ */
+struct clkdiv_regmap {
+	struct clk_regmap rclk;
+	unsigned int reg;
+	unsigned int shift;
+	unsigned int width;
+	struct clk_div_table *table;
+};
+
+#define to_clkdiv_regmap(_rclk) container_of(_rclk, struct clkdiv_regmap, rclk)
+
+unsigned long
+clkdiv_recalc_rate_regmap(struct clk_hw *hw, unsigned long parent_rate);
+struct clk *
+devm_clkdiv_register_regmap(struct device *dev, const char *name,
+			    const char *parent_name, unsigned long flags,
+			    struct clkdiv_regmap *clkdiv);
 #endif
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-10-03 17:49 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-30 17:20 [PATCH v1] clk: qcom: Add support for regmap clock dividers Georgi Djakov
2014-10-02 18:11 ` Stephen Boyd
2014-10-02 19:51   ` Kumar Gala
2014-10-02 21:26     ` Stephen Boyd
2014-10-03 15:13   ` Georgi Djakov
2014-10-03 17:49     ` Stephen Boyd

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).