From: Stephen Boyd <sboyd@codeaurora.org>
To: Mike Turquette <mturquette@baylibre.com>,
Stephen Boyd <sboyd@codeaurora.org>
Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
Subject: [PATCH 03/14] clk: Add {devm_}clk_hw_{register,unregister}() APIs
Date: Mon, 8 Feb 2016 17:45:30 -0800 [thread overview]
Message-ID: <1454982341-22715-4-git-send-email-sboyd@codeaurora.org> (raw)
In-Reply-To: <1454982341-22715-1-git-send-email-sboyd@codeaurora.org>
We've largely split the clk consumer and provider APIs along
struct clk and struct clk_hw, but clk_register() still returns a
struct clk pointer for each struct clk_hw that's registered.
Eventually we'd like to only allocate struct clks when there's a
user, because struct clk is per-user now, so clk_register() needs
to change.
Let's add new APIs to register struct clk_hws, but this time
we'll hide the struct clk from the caller by returning an int
error code. Also add an unregistration API that takes the clk_hw
structure that was passed to the registration API. This way
provider drivers never have to deal with a struct clk pointer
unless they're using the clk consumer APIs.
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
Documentation/driver-model/devres.txt | 1 +
drivers/clk/clk.c | 86 +++++++++++++++++++++++++++++++++++
include/linux/clk-provider.h | 6 +++
3 files changed, 93 insertions(+)
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 831a5363f6be..600e30bf52c5 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -236,6 +236,7 @@ certainly invest a bit more effort into libata core layer).
CLOCK
devm_clk_get()
devm_clk_put()
+ devm_clk_hw_register()
DMA
dmam_alloc_coherent()
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index b4db67a446c8..adaaead3639f 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2613,6 +2613,22 @@ fail_out:
}
EXPORT_SYMBOL_GPL(clk_register);
+/**
+ * clk_hw_register - register a clk_hw and return an error code
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * clk_hw_register is the primary interface for populating the clock tree with
+ * new clock nodes. It returns an integer equal to zero indicating success or
+ * less than zero indicating failure. Drivers must test for an error code after
+ * calling clk_hw_register().
+ */
+int clk_hw_register(struct device *dev, struct clk_hw *hw)
+{
+ return PTR_ERR_OR_ZERO(clk_register(dev, hw));
+}
+EXPORT_SYMBOL_GPL(clk_hw_register);
+
/* Free memory allocated for a clock. */
static void __clk_release(struct kref *ref)
{
@@ -2714,11 +2730,26 @@ void clk_unregister(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_unregister);
+/**
+ * clk_hw_unregister - unregister a currently registered clk_hw
+ * @hw: hardware-specific clock data to unregister
+ */
+void clk_hw_unregister(struct clk_hw *hw)
+{
+ clk_unregister(hw->clk);
+}
+EXPORT_SYMBOL_GPL(clk_hw_unregister);
+
static void devm_clk_release(struct device *dev, void *res)
{
clk_unregister(*(struct clk **)res);
}
+static void devm_clk_hw_release(struct device *dev, void *res)
+{
+ clk_hw_unregister(*(struct clk_hw **)res);
+}
+
/**
* devm_clk_register - resource managed clk_register()
* @dev: device that is registering this clock
@@ -2749,6 +2780,36 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
}
EXPORT_SYMBOL_GPL(devm_clk_register);
+/**
+ * devm_clk_hw_register - resource managed clk_hw_register()
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * Managed clk_hw_register(). Clocks returned from this function are
+ * automatically clk_hw_unregister()ed on driver detach. See clk_hw_register()
+ * for more information.
+ */
+int devm_clk_hw_register(struct device *dev, struct clk_hw *hw)
+{
+ struct clk_hw **hwp;
+ int ret;
+
+ hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL);
+ if (!hwp)
+ return -ENOMEM;
+
+ ret = clk_hw_register(dev, hw);
+ if (!ret) {
+ *hwp = hw;
+ devres_add(dev, hwp);
+ } else {
+ devres_free(hwp);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(devm_clk_hw_register);
+
static int devm_clk_match(struct device *dev, void *res, void *data)
{
struct clk *c = res;
@@ -2757,6 +2818,15 @@ static int devm_clk_match(struct device *dev, void *res, void *data)
return c == data;
}
+static int devm_clk_hw_match(struct device *dev, void *res, void *data)
+{
+ struct clk_hw *hw = res;
+
+ if (WARN_ON(!hw))
+ return 0;
+ return hw == data;
+}
+
/**
* devm_clk_unregister - resource managed clk_unregister()
* @clk: clock to unregister
@@ -2771,6 +2841,22 @@ void devm_clk_unregister(struct device *dev, struct clk *clk)
}
EXPORT_SYMBOL_GPL(devm_clk_unregister);
+/**
+ * devm_clk_hw_unregister - resource managed clk_hw_unregister()
+ * @dev: device that is unregistering the hardware-specific clock data
+ * @hw: link to hardware-specific clock data
+ *
+ * Unregister a clk_hw registered with devm_clk_hw_register(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw)
+{
+ WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match,
+ hw));
+}
+EXPORT_SYMBOL_GPL(devm_clk_hw_unregister);
+
/*
* clkdev helpers
*/
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1143e38555a4..abc16d77fb62 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -639,9 +639,15 @@ void of_gpio_mux_clk_setup(struct device_node *node);
struct clk *clk_register(struct device *dev, struct clk_hw *hw);
struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
+int __must_check clk_hw_register(struct device *dev, struct clk_hw *hw);
+int __must_check devm_clk_hw_register(struct device *dev, struct clk_hw *hw);
+
void clk_unregister(struct clk *clk);
void devm_clk_unregister(struct device *dev, struct clk *clk);
+void clk_hw_unregister(struct clk_hw *hw);
+void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw);
+
/* helper functions */
const char *__clk_get_name(const struct clk *clk);
const char *clk_hw_get_name(const struct clk_hw *hw);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
WARNING: multiple messages have this Message-ID (diff)
From: sboyd@codeaurora.org (Stephen Boyd)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 03/14] clk: Add {devm_}clk_hw_{register,unregister}() APIs
Date: Mon, 8 Feb 2016 17:45:30 -0800 [thread overview]
Message-ID: <1454982341-22715-4-git-send-email-sboyd@codeaurora.org> (raw)
In-Reply-To: <1454982341-22715-1-git-send-email-sboyd@codeaurora.org>
We've largely split the clk consumer and provider APIs along
struct clk and struct clk_hw, but clk_register() still returns a
struct clk pointer for each struct clk_hw that's registered.
Eventually we'd like to only allocate struct clks when there's a
user, because struct clk is per-user now, so clk_register() needs
to change.
Let's add new APIs to register struct clk_hws, but this time
we'll hide the struct clk from the caller by returning an int
error code. Also add an unregistration API that takes the clk_hw
structure that was passed to the registration API. This way
provider drivers never have to deal with a struct clk pointer
unless they're using the clk consumer APIs.
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
Documentation/driver-model/devres.txt | 1 +
drivers/clk/clk.c | 86 +++++++++++++++++++++++++++++++++++
include/linux/clk-provider.h | 6 +++
3 files changed, 93 insertions(+)
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 831a5363f6be..600e30bf52c5 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -236,6 +236,7 @@ certainly invest a bit more effort into libata core layer).
CLOCK
devm_clk_get()
devm_clk_put()
+ devm_clk_hw_register()
DMA
dmam_alloc_coherent()
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index b4db67a446c8..adaaead3639f 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2613,6 +2613,22 @@ fail_out:
}
EXPORT_SYMBOL_GPL(clk_register);
+/**
+ * clk_hw_register - register a clk_hw and return an error code
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * clk_hw_register is the primary interface for populating the clock tree with
+ * new clock nodes. It returns an integer equal to zero indicating success or
+ * less than zero indicating failure. Drivers must test for an error code after
+ * calling clk_hw_register().
+ */
+int clk_hw_register(struct device *dev, struct clk_hw *hw)
+{
+ return PTR_ERR_OR_ZERO(clk_register(dev, hw));
+}
+EXPORT_SYMBOL_GPL(clk_hw_register);
+
/* Free memory allocated for a clock. */
static void __clk_release(struct kref *ref)
{
@@ -2714,11 +2730,26 @@ void clk_unregister(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_unregister);
+/**
+ * clk_hw_unregister - unregister a currently registered clk_hw
+ * @hw: hardware-specific clock data to unregister
+ */
+void clk_hw_unregister(struct clk_hw *hw)
+{
+ clk_unregister(hw->clk);
+}
+EXPORT_SYMBOL_GPL(clk_hw_unregister);
+
static void devm_clk_release(struct device *dev, void *res)
{
clk_unregister(*(struct clk **)res);
}
+static void devm_clk_hw_release(struct device *dev, void *res)
+{
+ clk_hw_unregister(*(struct clk_hw **)res);
+}
+
/**
* devm_clk_register - resource managed clk_register()
* @dev: device that is registering this clock
@@ -2749,6 +2780,36 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
}
EXPORT_SYMBOL_GPL(devm_clk_register);
+/**
+ * devm_clk_hw_register - resource managed clk_hw_register()
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * Managed clk_hw_register(). Clocks returned from this function are
+ * automatically clk_hw_unregister()ed on driver detach. See clk_hw_register()
+ * for more information.
+ */
+int devm_clk_hw_register(struct device *dev, struct clk_hw *hw)
+{
+ struct clk_hw **hwp;
+ int ret;
+
+ hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL);
+ if (!hwp)
+ return -ENOMEM;
+
+ ret = clk_hw_register(dev, hw);
+ if (!ret) {
+ *hwp = hw;
+ devres_add(dev, hwp);
+ } else {
+ devres_free(hwp);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(devm_clk_hw_register);
+
static int devm_clk_match(struct device *dev, void *res, void *data)
{
struct clk *c = res;
@@ -2757,6 +2818,15 @@ static int devm_clk_match(struct device *dev, void *res, void *data)
return c == data;
}
+static int devm_clk_hw_match(struct device *dev, void *res, void *data)
+{
+ struct clk_hw *hw = res;
+
+ if (WARN_ON(!hw))
+ return 0;
+ return hw == data;
+}
+
/**
* devm_clk_unregister - resource managed clk_unregister()
* @clk: clock to unregister
@@ -2771,6 +2841,22 @@ void devm_clk_unregister(struct device *dev, struct clk *clk)
}
EXPORT_SYMBOL_GPL(devm_clk_unregister);
+/**
+ * devm_clk_hw_unregister - resource managed clk_hw_unregister()
+ * @dev: device that is unregistering the hardware-specific clock data
+ * @hw: link to hardware-specific clock data
+ *
+ * Unregister a clk_hw registered with devm_clk_hw_register(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw)
+{
+ WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match,
+ hw));
+}
+EXPORT_SYMBOL_GPL(devm_clk_hw_unregister);
+
/*
* clkdev helpers
*/
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 1143e38555a4..abc16d77fb62 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -639,9 +639,15 @@ void of_gpio_mux_clk_setup(struct device_node *node);
struct clk *clk_register(struct device *dev, struct clk_hw *hw);
struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
+int __must_check clk_hw_register(struct device *dev, struct clk_hw *hw);
+int __must_check devm_clk_hw_register(struct device *dev, struct clk_hw *hw);
+
void clk_unregister(struct clk *clk);
void devm_clk_unregister(struct device *dev, struct clk *clk);
+void clk_hw_unregister(struct clk_hw *hw);
+void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw);
+
/* helper functions */
const char *__clk_get_name(const struct clk *clk);
const char *clk_hw_get_name(const struct clk_hw *hw);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
next prev parent reply other threads:[~2016-02-09 1:45 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-09 1:45 [PATCH 00/14] clk_hw based clkdev/DT providers Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-09 1:45 ` [PATCH 01/14] mfd: intel_quark_i2c_gpio: Use clkdev_create() Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-10 16:23 ` Lee Jones
2016-02-10 16:23 ` Lee Jones
2016-02-10 18:35 ` Stephen Boyd
2016-02-10 18:35 ` Stephen Boyd
2016-02-11 9:09 ` Lee Jones
2016-02-11 9:09 ` Lee Jones
2016-02-11 11:08 ` Lee Jones
2016-02-11 11:08 ` Lee Jones
2016-02-15 15:14 ` Andy Shevchenko
2016-02-15 15:14 ` Andy Shevchenko
2016-02-15 22:13 ` Michael Turquette
2016-02-15 22:13 ` Michael Turquette
2016-02-15 22:13 ` Michael Turquette
2016-02-09 1:45 ` [PATCH 02/14] clkdev: Remove clk_register_clkdevs() Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-15 15:16 ` Andy Shevchenko
2016-02-15 15:16 ` Andy Shevchenko
2016-02-15 22:12 ` Michael Turquette
2016-02-15 22:12 ` Michael Turquette
2016-02-15 22:12 ` Michael Turquette
2016-02-09 1:45 ` Stephen Boyd [this message]
2016-02-09 1:45 ` [PATCH 03/14] clk: Add {devm_}clk_hw_{register,unregister}() APIs Stephen Boyd
2016-02-15 22:13 ` Michael Turquette
2016-02-15 22:13 ` Michael Turquette
2016-02-15 22:13 ` [PATCH 03/14] clk: Add {devm_}clk_hw_{register, unregister}() APIs Michael Turquette
2016-02-09 1:45 ` [PATCH 04/14] clk: Add clk_hw OF clk providers Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-09 3:31 ` kbuild test robot
2016-02-09 3:31 ` kbuild test robot
2016-02-09 1:45 ` [PATCH 05/14] clkdev: Add clk_hw based registration APIs Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-09 1:45 ` [PATCH 06/14] clk: divider: Add hw " Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-09 1:45 ` [PATCH 07/14] clk: gate: " Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-09 1:45 ` [PATCH 08/14] clk: mux: " Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-09 1:45 ` [PATCH 09/14] clk: fixed-factor: " Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-09 1:45 ` [PATCH 10/14] clk: fractional-divider: " Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-09 1:45 ` [PATCH 11/14] clk: composite: " Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-09 1:45 ` [PATCH 12/14] clk: gpio: " Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-09 1:45 ` [PATCH 13/14] clk: fixed-rate: " Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-09 1:45 ` [PATCH 14/14] clk: qcom: Migrate to clk_hw based registration and OF APIs Stephen Boyd
2016-02-09 1:45 ` Stephen Boyd
2016-02-09 5:30 ` kbuild test robot
2016-02-09 5:30 ` kbuild test robot
2016-02-09 8:01 ` kbuild test robot
2016-02-09 8:01 ` kbuild test robot
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=1454982341-22715-4-git-send-email-sboyd@codeaurora.org \
--to=sboyd@codeaurora.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mturquette@baylibre.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.